HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

插件源码授权版购买流程

插件源码授权版购买流程 插件市场

插件源码授权版购买流程

购买,购买时需要确认基本信息


如果未经过e签宝认证则点击确认生成e签宝实名认证链接,跳转去e签宝实名认证

认证完成后,生成电子协议

点击跳转到e签宝签署电子协议
签署完成后

等待插件作者签署电子协议

协议签署完成,购买者会收到e签宝 短信/邮件 签署完成通知
用户可以在我购买的插件订单-未完成订单-待付款看到该订单或者直接打开该插件地址进行支付购买

购买完成,下载/导入HX

什么是e签宝

点击查看e签宝介绍

e签宝实名认证流程

点击查看e签宝实名认证流程

e签宝电子协议签署流程

点击查看e签宝电子协议签署流程

继续阅读 »

插件源码授权版购买流程

购买,购买时需要确认基本信息


如果未经过e签宝认证则点击确认生成e签宝实名认证链接,跳转去e签宝实名认证

认证完成后,生成电子协议

点击跳转到e签宝签署电子协议
签署完成后

等待插件作者签署电子协议

协议签署完成,购买者会收到e签宝 短信/邮件 签署完成通知
用户可以在我购买的插件订单-未完成订单-待付款看到该订单或者直接打开该插件地址进行支付购买

购买完成,下载/导入HX

什么是e签宝

点击查看e签宝介绍

e签宝实名认证流程

点击查看e签宝实名认证流程

e签宝电子协议签署流程

点击查看e签宝电子协议签署流程

收起阅读 »

数据修改页面不刷新问题记录

双向绑定 uniapp

一般来说页面和数据是双向绑定的,数据改变页面就会改变,可是有时候页面数据改变后,APP上页面不刷新,但微信小程序开发工具上又是可以的,一般这种情况是在数组使用时遇到的,记录几个遇到的情况和解决办法:
一、数组值修改,页面样式不刷新。解决:尝试用this.$set()方法,里面三个参数,第一个传这个数组,第二个传要修改的那项的下标,第三个传修改后的那项内容。下面会根据数组中的state状态加载不同的样式:

this.model.answer[j].state = !this.model.answer[j].state;  
this.$set(this.model.answer, j, this.model.answer[j])  
//页面根据变量加载不同样式  
<view  :class="item.state?'answer_yes':'answer_no'">{{item.name}}</view>

二、有一次我用this.$set()方法,数据改变后页面上的样式任然不刷新,奇怪的是,另一个页面一模一样的代码,刷新又正常,代码同上。询问了一圈,有老铁告诉我可能是数据太深了,然后我试着将answer数据从model中提取出来,新建一个数组来绑定页面:

this.model.answer[j].state = !this.model.answer[j].state;  
this.$set(this.model.answer, j, this.model.answer[j])  
//在上面的基础上添加下面这种操作,把页面上绑定的数组换成current_answer,测试时把上面一句注释竟然又失效了   
this.current_answer = this.model.answer

最后就正常了,坑啊。。。。
三、还有一种情况是定义的全局变量,如果页面绑定的是定义在其他文件下的全局变量,变量修改的时候,页面也不会刷新,这种情况就在当前页面再定义一个变量,这个变量在页面加载的时候接收全局变量的值,然后页面绑定这个变量就好了。

继续阅读 »

一般来说页面和数据是双向绑定的,数据改变页面就会改变,可是有时候页面数据改变后,APP上页面不刷新,但微信小程序开发工具上又是可以的,一般这种情况是在数组使用时遇到的,记录几个遇到的情况和解决办法:
一、数组值修改,页面样式不刷新。解决:尝试用this.$set()方法,里面三个参数,第一个传这个数组,第二个传要修改的那项的下标,第三个传修改后的那项内容。下面会根据数组中的state状态加载不同的样式:

this.model.answer[j].state = !this.model.answer[j].state;  
this.$set(this.model.answer, j, this.model.answer[j])  
//页面根据变量加载不同样式  
<view  :class="item.state?'answer_yes':'answer_no'">{{item.name}}</view>

二、有一次我用this.$set()方法,数据改变后页面上的样式任然不刷新,奇怪的是,另一个页面一模一样的代码,刷新又正常,代码同上。询问了一圈,有老铁告诉我可能是数据太深了,然后我试着将answer数据从model中提取出来,新建一个数组来绑定页面:

this.model.answer[j].state = !this.model.answer[j].state;  
this.$set(this.model.answer, j, this.model.answer[j])  
//在上面的基础上添加下面这种操作,把页面上绑定的数组换成current_answer,测试时把上面一句注释竟然又失效了   
this.current_answer = this.model.answer

最后就正常了,坑啊。。。。
三、还有一种情况是定义的全局变量,如果页面绑定的是定义在其他文件下的全局变量,变量修改的时候,页面也不会刷新,这种情况就在当前页面再定义一个变量,这个变量在页面加载的时候接收全局变量的值,然后页面绑定这个变量就好了。

收起阅读 »

本应用无法独立运行,需要与hbuilderX 搭配使用问题之一(使用SD卡)

uniapp 真机调试
  • uni-app项目使用荣耀手机(本人是荣耀20)真机调试时,出现app运行时显示“本应用无法独立运行,需要与hbuilderX 搭配使用”,是因为将存储的默认存储位置设置为SanDisk存储卡引起的。解决方法是将手机默认存储位置设置为内部存储即可。感觉应该是HBuilderX存在的BUG,希望官方对此类问题进行测试并解决。
  • 解决此问题时查询了很多类似的帖子,大概总结了一下,主要存在目录或文件名存在中文或者修改了存储位置引起,大家稍加注意应该可以解决,如还有其他情况请大家回复收集。
  • 仅供大家参考。
继续阅读 »
  • uni-app项目使用荣耀手机(本人是荣耀20)真机调试时,出现app运行时显示“本应用无法独立运行,需要与hbuilderX 搭配使用”,是因为将存储的默认存储位置设置为SanDisk存储卡引起的。解决方法是将手机默认存储位置设置为内部存储即可。感觉应该是HBuilderX存在的BUG,希望官方对此类问题进行测试并解决。
  • 解决此问题时查询了很多类似的帖子,大概总结了一下,主要存在目录或文件名存在中文或者修改了存储位置引起,大家稍加注意应该可以解决,如还有其他情况请大家回复收集。
  • 仅供大家参考。
收起阅读 »

nfc读取加密扇区

NFC

// 包路径
const package_NdefRecord = 'android.nfc.NdefRecord';
const package_NdefMessage = 'android.nfc.NdefMessage';
const package_TECH_DISCOVERED = 'android.nfc.action.TECH_DISCOVERED';
const package_Intent = 'android.content.Intent';
const package_Activity = 'android.app.Activity';
const package_PendingIntent = 'android.app.PendingIntent';
const package_IntentFilter = 'android.content.IntentFilter';
const package_NfcAdapter = 'android.nfc.NfcAdapter';
const package_Ndef = 'android.nfc.tech.Ndef';
const package_NdefFormatable = 'android.nfc.tech.NdefFormatable';
const package_Parcelable = 'android.os.Parcelable';
const package_String = 'java.lang.String';

let NfcAdapter;
let NdefRecord;
let NdefMessage;
let readyWriteData = false;
let readyRead = false;
let noNFC = false;
let techListsArray = [
["android.nfc.tech.IsoDep"],
["android.nfc.tech.NfcA"],
["android.nfc.tech.NfcB"],
["android.nfc.tech.NfcF"],
["android.nfc.tech.Ndef"],
["android.nfc.tech.NfcV"],
["android.nfc.tech.NdefFormatable"],
["android.nfc.tech.MifareClassic"],
["android.nfc.tech.MifareUltralight"]
];
// 要写入的数据
let text = '{id:123,name:nfc,stie:cssmini.com}';
let readResult = '';

export default {
listenNFCStatus: function() {
let that = this;
try {
let main = plus.android.runtimeMainActivity();
let Intent = plus.android.importClass('android.content.Intent');
let Activity = plus.android.importClass('android.app.Activity');
let PendingIntent = plus.android.importClass('android.app.PendingIntent');
let IntentFilter = plus.android.importClass('android.content.IntentFilter');
NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');
let nfcAdapter = NfcAdapter.getDefaultAdapter(main);

        if (nfcAdapter == null) {  
            uni.showToast({  
                title: '设备不支持NFC!',  
                icon: 'none'  
            })  
            noNFC = true;  
            return;  
        }  

        if (!nfcAdapter.isEnabled()) {  
            uni.showToast({  
                title: '请在系统设置中先启用NFC功能!',  
                icon: 'none'  
            });  
            noNFC = true;  
            return;  
        } else {  
            noNFC = false;  
        }  

        let intent = new Intent(main, main.getClass());  
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  
        let pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);  
        let ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");  
        ndef.addDataType("*/*");  
        let intentFiltersArray = [ndef];  

        plus.globalEvent.addEventListener('newintent', function() {  
            console.log('newintent running');  
            // 监听 NFC  
            setTimeout(that.nfcRuning(), 1000);  
        });  
        plus.globalEvent.addEventListener('pause', function(e) {  
            console.log('pause running');  
            if (nfcAdapter) {  
                //关闭前台调度系统  
                //恢复默认状态  
                nfcAdapter.disableForegroundDispatch(main);  
            }  
        });  
        plus.globalEvent.addEventListener('resume', function(e) {  
            console.log('resume running');  
            if (nfcAdapter) {  
                //开启前台调度系统  
                nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);  
            }  
        });  
        nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);  
    } catch (e) {  
        console.error(e);  
    }  
},  
nfcRuning: function() {  
    NdefRecord = plus.android.importClass("android.nfc.NdefRecord");  
    NdefMessage = plus.android.importClass("android.nfc.NdefMessage");  
    let main = plus.android.runtimeMainActivity();  
    let intent = main.getIntent();  
    let that = this;  

    console.log("action type:" + intent.getAction());  

    if (package_TECH_DISCOVERED == intent.getAction()) {  
        console.log("readyWriteData=" + readyWriteData + " readyRead=" + readyRead)  
        if (readyWriteData) {  
            that.write(intent);  
            readyWriteData = false;  
        } else if (readyRead) {  

            that.read(intent);  
            readyRead = false;  
        }  
    }  
},  
write(intent) {  
    try {  
        toast('请勿移开标签 正在写入...');  
        console.log("text=" + text);  

        let textBytes = plus.android.invoke(text, "getBytes");  
        // image/jpeg text/plain    
        let textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,  
            plus.android.invoke("text/plain", "getBytes"),  
            plus.android.invoke("", "getBytes"), textBytes);  
        let message = new NdefMessage([textRecord]);  
        let Ndef = plus.android.importClass('android.nfc.tech.Ndef');  
        let NdefFormatable = plus.android.importClass('android.nfc.tech.NdefFormatable');  
        let tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  
        let ndef = Ndef.get(tag);  
        if (ndef != null) {  
            // 待写入的数据长度  
            let size = message.toByteArray().length;  
            ndef.connect();  
            if (!ndef.isWritable()) {  
                toast('tag不允许写入!');  
                return;  
            }  
            if (ndef.getMaxSize() < size) {  
                toast('文件大小超出容量!');  
                return;  
            }  
            ndef.writeNdefMessage(message);  
            toast('写入数据成功!');  
            return;  
        } else {  
            let format = NdefFormatable.get(tag);  
            if (format != null) {  
                try {  
                    format.connect();  
                    format.format(message);  
                    toast('格式化tag并且写入message');  
                    return;  
                } catch (e) {  
                    toast('格式化tag失败.');  
                    return;  
                }  
            } else {  
                toast('Tag不支持NDEF');  
                return;  
            }  
        }  
    } catch (e) {  
        toast('写入失败');  
        console.log("error=" + e);  
    }  

},  
read(intent) {  
    this.getData(intent);  
},  
byteArrayToHexString: function(inarray) { // converts byte arrays to string    
    let i, j, inn;  
    let hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];  
    let out = "";  

    for (j = 0; j < inarray.length; ++j) {  
        if(inarray[j]==0) continue;  
        inn = inarray[j] & 0xff;  
        i = (inn >>> 4) & 0x0f;  
        out += hex[i];  
        i = inn & 0x0f;  
        out += hex[i];  
    }  
    return out;  
},  
writeData: function() {  
    if (noNFC) {  
        toast('请检查设备是否支持并开启 NFC 功能!');  
        return;  
    }  
    // 监听事件,触发条件  
    readyWriteData = true;  
    toast('请将NFC标签靠近!');  
},  
readData: function() {  
    if (noNFC) {  
        toast('请检查设备是否支持并开启 NFC 功能!');  
        return;  
    }  
    // 监听事件,触发条件  
    readyRead = true;  
    toast('请将NFC标签靠近!');  

},  
getData: function(intent) {  
    var sector = 1;  
    var tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  
    let mc = plus.android.importClass('android.nfc.tech.MifareClassic');  
    let mfc = mc.get(tag);  
    console.log('mfc', mfc)  
    mfc.connect();  
    var cmdBytes = [0x6A, 0x69, 0x61, 0x6A, 0x75, 0x6E]  
    console.log('mfc', cmdBytes)  
    var auth = mfc.authenticateSectorWithKeyA(sector, cmdBytes)  

    console.log('auth', auth);  
    if (!auth) return;  
    try {  
        var tmpRet,result;  
        for (var i = 0; i < 3; i++) {  
            tmpRet = mfc.readBlock(sector * 4 + i);  
            result+=this.hexCharCodeToStr(this.byteArrayToHexString(tmpRet))  
        }  

        console.log('result',result);  
    } catch (e) {  
        this.ICERROR = e.message;  
        console.error(e);  
    } finally {  
        mfc.close();  
    }  
},  
//Key处理函数    
HexStringToByteArray: function(instr) {  
    var hexA = new Array();  
    var pos = 0;  
    var len = instr.length / 2;  
    for (var i = 0; i < len; i++) {  
        var s = instr.substr(pos, 2);  
        var v = parseInt(s, 16);  
        if (v >= 128)  
            v = v - 256;  
        hexA.push(v);  
        pos += 2;  
    }  
    return hexA;  
},  
hexCharCodeToStr: function(hexCharCodeStr) {  
    var trimedStr = hexCharCodeStr.trim();  
    var rawStr =  
        trimedStr.substr(0, 2).toLowerCase() === "0x" ?  
        trimedStr.substr(2) :  
        trimedStr;  
    var len = rawStr.length;  
    if (len % 2 !== 0) {  
        alert("Illegal Format ASCII Code!");  
        return "";  
    }  
    var curCharCode;  
    var resultStr = [];  
    for (var i = 0; i < len; i = i + 2) {  
        curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value  
        resultStr.push(String.fromCharCode(curCharCode));  
    }  
    return resultStr.join("");  
}  

}

function toast(content) {
uni.showToast({
title: content,
icon: 'none'
})
}

继续阅读 »

// 包路径
const package_NdefRecord = 'android.nfc.NdefRecord';
const package_NdefMessage = 'android.nfc.NdefMessage';
const package_TECH_DISCOVERED = 'android.nfc.action.TECH_DISCOVERED';
const package_Intent = 'android.content.Intent';
const package_Activity = 'android.app.Activity';
const package_PendingIntent = 'android.app.PendingIntent';
const package_IntentFilter = 'android.content.IntentFilter';
const package_NfcAdapter = 'android.nfc.NfcAdapter';
const package_Ndef = 'android.nfc.tech.Ndef';
const package_NdefFormatable = 'android.nfc.tech.NdefFormatable';
const package_Parcelable = 'android.os.Parcelable';
const package_String = 'java.lang.String';

let NfcAdapter;
let NdefRecord;
let NdefMessage;
let readyWriteData = false;
let readyRead = false;
let noNFC = false;
let techListsArray = [
["android.nfc.tech.IsoDep"],
["android.nfc.tech.NfcA"],
["android.nfc.tech.NfcB"],
["android.nfc.tech.NfcF"],
["android.nfc.tech.Ndef"],
["android.nfc.tech.NfcV"],
["android.nfc.tech.NdefFormatable"],
["android.nfc.tech.MifareClassic"],
["android.nfc.tech.MifareUltralight"]
];
// 要写入的数据
let text = '{id:123,name:nfc,stie:cssmini.com}';
let readResult = '';

export default {
listenNFCStatus: function() {
let that = this;
try {
let main = plus.android.runtimeMainActivity();
let Intent = plus.android.importClass('android.content.Intent');
let Activity = plus.android.importClass('android.app.Activity');
let PendingIntent = plus.android.importClass('android.app.PendingIntent');
let IntentFilter = plus.android.importClass('android.content.IntentFilter');
NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');
let nfcAdapter = NfcAdapter.getDefaultAdapter(main);

        if (nfcAdapter == null) {  
            uni.showToast({  
                title: '设备不支持NFC!',  
                icon: 'none'  
            })  
            noNFC = true;  
            return;  
        }  

        if (!nfcAdapter.isEnabled()) {  
            uni.showToast({  
                title: '请在系统设置中先启用NFC功能!',  
                icon: 'none'  
            });  
            noNFC = true;  
            return;  
        } else {  
            noNFC = false;  
        }  

        let intent = new Intent(main, main.getClass());  
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  
        let pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);  
        let ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");  
        ndef.addDataType("*/*");  
        let intentFiltersArray = [ndef];  

        plus.globalEvent.addEventListener('newintent', function() {  
            console.log('newintent running');  
            // 监听 NFC  
            setTimeout(that.nfcRuning(), 1000);  
        });  
        plus.globalEvent.addEventListener('pause', function(e) {  
            console.log('pause running');  
            if (nfcAdapter) {  
                //关闭前台调度系统  
                //恢复默认状态  
                nfcAdapter.disableForegroundDispatch(main);  
            }  
        });  
        plus.globalEvent.addEventListener('resume', function(e) {  
            console.log('resume running');  
            if (nfcAdapter) {  
                //开启前台调度系统  
                nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);  
            }  
        });  
        nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);  
    } catch (e) {  
        console.error(e);  
    }  
},  
nfcRuning: function() {  
    NdefRecord = plus.android.importClass("android.nfc.NdefRecord");  
    NdefMessage = plus.android.importClass("android.nfc.NdefMessage");  
    let main = plus.android.runtimeMainActivity();  
    let intent = main.getIntent();  
    let that = this;  

    console.log("action type:" + intent.getAction());  

    if (package_TECH_DISCOVERED == intent.getAction()) {  
        console.log("readyWriteData=" + readyWriteData + " readyRead=" + readyRead)  
        if (readyWriteData) {  
            that.write(intent);  
            readyWriteData = false;  
        } else if (readyRead) {  

            that.read(intent);  
            readyRead = false;  
        }  
    }  
},  
write(intent) {  
    try {  
        toast('请勿移开标签 正在写入...');  
        console.log("text=" + text);  

        let textBytes = plus.android.invoke(text, "getBytes");  
        // image/jpeg text/plain    
        let textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,  
            plus.android.invoke("text/plain", "getBytes"),  
            plus.android.invoke("", "getBytes"), textBytes);  
        let message = new NdefMessage([textRecord]);  
        let Ndef = plus.android.importClass('android.nfc.tech.Ndef');  
        let NdefFormatable = plus.android.importClass('android.nfc.tech.NdefFormatable');  
        let tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  
        let ndef = Ndef.get(tag);  
        if (ndef != null) {  
            // 待写入的数据长度  
            let size = message.toByteArray().length;  
            ndef.connect();  
            if (!ndef.isWritable()) {  
                toast('tag不允许写入!');  
                return;  
            }  
            if (ndef.getMaxSize() < size) {  
                toast('文件大小超出容量!');  
                return;  
            }  
            ndef.writeNdefMessage(message);  
            toast('写入数据成功!');  
            return;  
        } else {  
            let format = NdefFormatable.get(tag);  
            if (format != null) {  
                try {  
                    format.connect();  
                    format.format(message);  
                    toast('格式化tag并且写入message');  
                    return;  
                } catch (e) {  
                    toast('格式化tag失败.');  
                    return;  
                }  
            } else {  
                toast('Tag不支持NDEF');  
                return;  
            }  
        }  
    } catch (e) {  
        toast('写入失败');  
        console.log("error=" + e);  
    }  

},  
read(intent) {  
    this.getData(intent);  
},  
byteArrayToHexString: function(inarray) { // converts byte arrays to string    
    let i, j, inn;  
    let hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];  
    let out = "";  

    for (j = 0; j < inarray.length; ++j) {  
        if(inarray[j]==0) continue;  
        inn = inarray[j] & 0xff;  
        i = (inn >>> 4) & 0x0f;  
        out += hex[i];  
        i = inn & 0x0f;  
        out += hex[i];  
    }  
    return out;  
},  
writeData: function() {  
    if (noNFC) {  
        toast('请检查设备是否支持并开启 NFC 功能!');  
        return;  
    }  
    // 监听事件,触发条件  
    readyWriteData = true;  
    toast('请将NFC标签靠近!');  
},  
readData: function() {  
    if (noNFC) {  
        toast('请检查设备是否支持并开启 NFC 功能!');  
        return;  
    }  
    // 监听事件,触发条件  
    readyRead = true;  
    toast('请将NFC标签靠近!');  

},  
getData: function(intent) {  
    var sector = 1;  
    var tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  
    let mc = plus.android.importClass('android.nfc.tech.MifareClassic');  
    let mfc = mc.get(tag);  
    console.log('mfc', mfc)  
    mfc.connect();  
    var cmdBytes = [0x6A, 0x69, 0x61, 0x6A, 0x75, 0x6E]  
    console.log('mfc', cmdBytes)  
    var auth = mfc.authenticateSectorWithKeyA(sector, cmdBytes)  

    console.log('auth', auth);  
    if (!auth) return;  
    try {  
        var tmpRet,result;  
        for (var i = 0; i < 3; i++) {  
            tmpRet = mfc.readBlock(sector * 4 + i);  
            result+=this.hexCharCodeToStr(this.byteArrayToHexString(tmpRet))  
        }  

        console.log('result',result);  
    } catch (e) {  
        this.ICERROR = e.message;  
        console.error(e);  
    } finally {  
        mfc.close();  
    }  
},  
//Key处理函数    
HexStringToByteArray: function(instr) {  
    var hexA = new Array();  
    var pos = 0;  
    var len = instr.length / 2;  
    for (var i = 0; i < len; i++) {  
        var s = instr.substr(pos, 2);  
        var v = parseInt(s, 16);  
        if (v >= 128)  
            v = v - 256;  
        hexA.push(v);  
        pos += 2;  
    }  
    return hexA;  
},  
hexCharCodeToStr: function(hexCharCodeStr) {  
    var trimedStr = hexCharCodeStr.trim();  
    var rawStr =  
        trimedStr.substr(0, 2).toLowerCase() === "0x" ?  
        trimedStr.substr(2) :  
        trimedStr;  
    var len = rawStr.length;  
    if (len % 2 !== 0) {  
        alert("Illegal Format ASCII Code!");  
        return "";  
    }  
    var curCharCode;  
    var resultStr = [];  
    for (var i = 0; i < len; i = i + 2) {  
        curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value  
        resultStr.push(String.fromCharCode(curCharCode));  
    }  
    return resultStr.join("");  
}  

}

function toast(content) {
uni.showToast({
title: content,
icon: 'none'
})
}

收起阅读 »

plus 解决uni-app播放多音频背景音乐

音乐播放

plus 解决uni-app播放多音频背景音乐

播放音频文件


let audioPlayer = null;  

// #ifdef APP-PLUS  
// 背景音乐文件  
let path = plus.io.convertLocalFileSystemURL("_www/static/audio/background_music.mp3");  
if (plus.os.name == 'Android') {  
    let MediaPlayer = plus.android.importClass("android.media.MediaPlayer");  
    audioPlayer = new MediaPlayer()  
    audioPlayer.setDataSource(path); //指定音频文件路径  
    audioPlayer.setLooping(true); //设置为循环播放  
    audioPlayer.prepare(); //初始化播放器MediaPlayer  
    audioPlayer.start();  
    // 获取音乐的总时长  
    console.log(audioPlayer.getDuration());  
}  
if (plus.os.name == "iOS") {  
    let NSData = plus.ios.importClass("NSData");  
    let AVAudioPlayer = plus.ios.importClass("AVAudioPlayer");  
    let pathFileData = NSData.dataWithContentsOfFile(path);  
    audioPlayer = new AVAudioPlayer();  
    audioPlayer.initWithDataerror(pathFileData, null);  
    audioPlayer.setNumberOfLoops(-1); //-1:无限循环   
    audioPlayer.prepareToPlay(); //初始化播放器  
    audioPlayer.play();  
    // 获取音乐的总时长  
    console.log(audioPlayer.duration());  
}  
// #endif

调节系统媒体音量


let AudioManager = null;  
let audioManager = null;  

/// 获取系统音量控制  
// #ifdef APP-PLUS  
if (plus.os.name == 'Android') {  
    let context = plus.android.importClass("android.content.Context");  
    let main = plus.android.runtimeMainActivity();  
    AudioManager = plus.android.importClass("android.media.AudioManager");  
    audioManager = main.getSystemService(context.AUDIO_SERVICE);  
    // 调节是否显示调节ui  
    // audioManager.adjustStreamVolume (AudioManager.STREAM_MUSIC , AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI)  
    // 音量最大范围  
    let max = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);  
    // 当前音量值  
    let current = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);  
    console.log(max, current);  
}  
if (plus.os.name == "iOS") {  
    // 暂无查找  
}  
// #endif  

// 设置音量值  
// #ifdef APP-PLUS  
if (plus.os.name == 'Android') {  
    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 89, 0); // 89为音量值  
}  
if (plus.os.name == "iOS") {  
    // 暂无查找  
}  
// #endif  
继续阅读 »

plus 解决uni-app播放多音频背景音乐

播放音频文件


let audioPlayer = null;  

// #ifdef APP-PLUS  
// 背景音乐文件  
let path = plus.io.convertLocalFileSystemURL("_www/static/audio/background_music.mp3");  
if (plus.os.name == 'Android') {  
    let MediaPlayer = plus.android.importClass("android.media.MediaPlayer");  
    audioPlayer = new MediaPlayer()  
    audioPlayer.setDataSource(path); //指定音频文件路径  
    audioPlayer.setLooping(true); //设置为循环播放  
    audioPlayer.prepare(); //初始化播放器MediaPlayer  
    audioPlayer.start();  
    // 获取音乐的总时长  
    console.log(audioPlayer.getDuration());  
}  
if (plus.os.name == "iOS") {  
    let NSData = plus.ios.importClass("NSData");  
    let AVAudioPlayer = plus.ios.importClass("AVAudioPlayer");  
    let pathFileData = NSData.dataWithContentsOfFile(path);  
    audioPlayer = new AVAudioPlayer();  
    audioPlayer.initWithDataerror(pathFileData, null);  
    audioPlayer.setNumberOfLoops(-1); //-1:无限循环   
    audioPlayer.prepareToPlay(); //初始化播放器  
    audioPlayer.play();  
    // 获取音乐的总时长  
    console.log(audioPlayer.duration());  
}  
// #endif

调节系统媒体音量


let AudioManager = null;  
let audioManager = null;  

/// 获取系统音量控制  
// #ifdef APP-PLUS  
if (plus.os.name == 'Android') {  
    let context = plus.android.importClass("android.content.Context");  
    let main = plus.android.runtimeMainActivity();  
    AudioManager = plus.android.importClass("android.media.AudioManager");  
    audioManager = main.getSystemService(context.AUDIO_SERVICE);  
    // 调节是否显示调节ui  
    // audioManager.adjustStreamVolume (AudioManager.STREAM_MUSIC , AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI)  
    // 音量最大范围  
    let max = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);  
    // 当前音量值  
    let current = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);  
    console.log(max, current);  
}  
if (plus.os.name == "iOS") {  
    // 暂无查找  
}  
// #endif  

// 设置音量值  
// #ifdef APP-PLUS  
if (plus.os.name == 'Android') {  
    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 89, 0); // 89为音量值  
}  
if (plus.os.name == "iOS") {  
    // 暂无查找  
}  
// #endif  
收起阅读 »

uniapp云打包,软件闪退

在项目后期有次打包,结果打包后的apk闪退,最后发现项目中多了package.json和extension.js文件,将这两个文件删除后就行了

在项目后期有次打包,结果打包后的apk闪退,最后发现项目中多了package.json和extension.js文件,将这两个文件删除后就行了

uni.webView 有没有文档

uni.webView 这个有没有文档,
这个方法只在https://uniapp.dcloud.io/api/router?id=event-channel 提了一句话
在uniapp引入uni的H5页面 uni.webView 显示undefined
methods: {
back() {
console.log(uni.webView);
uni.webView.navigateBack();
}
}

undefined at webpack-internal:///./node_modules/babel-loader/lib/index.js!./node_modules/@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/index.js?!./node_modules/@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/index.js?!./node_modules/@dcloudio/vue-cli-plugin-uni/packages/webpack-uni-app-loader/using-components.js!./node_modules/@dcloudio/vue-cli-plugin-uni/packages/vue-loader/lib/index.js?!./node_modules/@dcloudio/vue-cli-plugin-uni/packages/webpack-scoped-loader/index.js!../../../pages/index/zhubotixianlogin.vue?vue&type=script&lang=js&:39
11:35:26.799 [Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'navigateBack' of undefined"
11:35:26.840 found in
11:35:26.881 ---> at pages/index/zhubotixianlogin.vue at http://192.168.0.108:8081/static/js/chunk-vendors.js:3883
11:35:26.902 [system] TypeError: Cannot read property 'navigateBack' of undefined at http://192.168.0.108:8081/static/js/chunk-vendors.js:124

继续阅读 »

uni.webView 这个有没有文档,
这个方法只在https://uniapp.dcloud.io/api/router?id=event-channel 提了一句话
在uniapp引入uni的H5页面 uni.webView 显示undefined
methods: {
back() {
console.log(uni.webView);
uni.webView.navigateBack();
}
}

undefined at webpack-internal:///./node_modules/babel-loader/lib/index.js!./node_modules/@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/index.js?!./node_modules/@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/index.js?!./node_modules/@dcloudio/vue-cli-plugin-uni/packages/webpack-uni-app-loader/using-components.js!./node_modules/@dcloudio/vue-cli-plugin-uni/packages/vue-loader/lib/index.js?!./node_modules/@dcloudio/vue-cli-plugin-uni/packages/webpack-scoped-loader/index.js!../../../pages/index/zhubotixianlogin.vue?vue&type=script&lang=js&:39
11:35:26.799 [Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'navigateBack' of undefined"
11:35:26.840 found in
11:35:26.881 ---> at pages/index/zhubotixianlogin.vue at http://192.168.0.108:8081/static/js/chunk-vendors.js:3883
11:35:26.902 [system] TypeError: Cannot read property 'navigateBack' of undefined at http://192.168.0.108:8081/static/js/chunk-vendors.js:124

收起阅读 »

nvue如何使用正确的使用vuex

nvue vuex

刚接触nuve的 新手想知道如何在 nvue 中使用vuex,大家肯定上官网搜索 方法,并且对官方人员发的文章深信不疑,过度依赖官方,嗯 我也是是这样的,导致了至始至终都是从自己身上找问题,结果焦躁一整天得不到解决!!

官方人员并不是神,也是有血有肉的人,程序开发过程难免会出现一些BUG,文章也是!!!

比如这个:https://ask.dcloud.net.cn/article/35021

我不止一次的提出改文章的问题,并且页得到官方的认可!!

这篇文章教你 在 uni-app 项目根目录下新建 store 目录,在 store 目录下创建 index.js 定义状态值

const store = new Vuex.Store({    
    state: {    
        login: false,    
        token: '',    
        avatarUrl: '',    
        userName: ''    
    },    
    mutations: {    
        login(state, provider) {    
            console.log(state)    
            console.log(provider)    
            state.login = true;    
            state.token = provider.token;    
            state.userName = provider.userName;    
            state.avatarUrl = provider.avatarUrl;    
        },    
        logout(state) {    
            state.login = false;    
            state.token = '';    
            state.userName = '';    
            state.avatarUrl = '';    
        }    
    }    
})

然后,需要在 main.js 挂载 Vuex

import store from './store'    
Vue.prototype.$store = store

如果你信了,直接复制粘贴,程序启动就报错了,不信你可以试试!!

其实正确的写法应该是这样:

import Vue from 'vue'  
import Vuex from 'vuex'  
Vue.use(Vuex)  
const store = new Vuex.Store({  
  state: {  
    value:''  
  },  
  mutations: {  
     setWebset(state, value) {  
         state.value = value  
     },  
  },  
  actions: {  

  },  
  modules: {  

  }  

})  
export default store

然后,需要在 main.js 挂载 Vuex

import store from './store'    
Vue.prototype.$store = store

这样写保你不报错!!

下面是测试赋值和取值的方法!

你可以在App.vue中赋值测试

onLaunch: function() {  
    this.$store.commit("setWebset", '赋值');  
},

然后在其他页面 取值

console.log(this.$store.state.value)

运行结果如下:

我发这个提示并不是纯粹的吐槽官方,同时也提供了解决方法!

继续阅读 »

刚接触nuve的 新手想知道如何在 nvue 中使用vuex,大家肯定上官网搜索 方法,并且对官方人员发的文章深信不疑,过度依赖官方,嗯 我也是是这样的,导致了至始至终都是从自己身上找问题,结果焦躁一整天得不到解决!!

官方人员并不是神,也是有血有肉的人,程序开发过程难免会出现一些BUG,文章也是!!!

比如这个:https://ask.dcloud.net.cn/article/35021

我不止一次的提出改文章的问题,并且页得到官方的认可!!

这篇文章教你 在 uni-app 项目根目录下新建 store 目录,在 store 目录下创建 index.js 定义状态值

const store = new Vuex.Store({    
    state: {    
        login: false,    
        token: '',    
        avatarUrl: '',    
        userName: ''    
    },    
    mutations: {    
        login(state, provider) {    
            console.log(state)    
            console.log(provider)    
            state.login = true;    
            state.token = provider.token;    
            state.userName = provider.userName;    
            state.avatarUrl = provider.avatarUrl;    
        },    
        logout(state) {    
            state.login = false;    
            state.token = '';    
            state.userName = '';    
            state.avatarUrl = '';    
        }    
    }    
})

然后,需要在 main.js 挂载 Vuex

import store from './store'    
Vue.prototype.$store = store

如果你信了,直接复制粘贴,程序启动就报错了,不信你可以试试!!

其实正确的写法应该是这样:

import Vue from 'vue'  
import Vuex from 'vuex'  
Vue.use(Vuex)  
const store = new Vuex.Store({  
  state: {  
    value:''  
  },  
  mutations: {  
     setWebset(state, value) {  
         state.value = value  
     },  
  },  
  actions: {  

  },  
  modules: {  

  }  

})  
export default store

然后,需要在 main.js 挂载 Vuex

import store from './store'    
Vue.prototype.$store = store

这样写保你不报错!!

下面是测试赋值和取值的方法!

你可以在App.vue中赋值测试

onLaunch: function() {  
    this.$store.commit("setWebset", '赋值');  
},

然后在其他页面 取值

console.log(this.$store.state.value)

运行结果如下:

我发这个提示并不是纯粹的吐槽官方,同时也提供了解决方法!

收起阅读 »

uni-app 通过vue-cli创建的vue3.0项目不支持的一些功能总结

  1. 通过defineComponents定义的组件导出的时候会提示"export 'defineComponent' was not found in 'vue'
    小程序开发工具会报错 TypeError: Object(...) is not a function

    <script>  
    import { defineComponent, toRefs } from 'vue'  
    export default defineComponent({  
    name: 'xxx',  
    props: {  
        tips: {  
            type: Array,  
            default: () => {  
                return []  
            }  
        }  
    },  
    setup(props, context) {  
        return {  
            ...toRefs(props)  
        }  
    }  
    })  
    </script>
  2. import { getCurrentInstance } from vue,uni-app框架下在vue中暂时拿不到getCurrentInstance这个函数,无法访问到getCurrentInstance

  3. v-model双向数据绑定默认用的还是原来的value属性和input事件,不是vue3.0中的v-bind:modelValue="xxx"的modelValue属性和update:modelValue事件;

  4. ref无法获取组件实例ref引用;

    
    <share ref="shareRef" ></share>  
    const shareRef = ref(null)  
    onMounted(() => {  
    console.log('onMounted, shareRef: ', shareRef.value)//此处打印null,undefined  
    })  
继续阅读 »
  1. 通过defineComponents定义的组件导出的时候会提示"export 'defineComponent' was not found in 'vue'
    小程序开发工具会报错 TypeError: Object(...) is not a function

    <script>  
    import { defineComponent, toRefs } from 'vue'  
    export default defineComponent({  
    name: 'xxx',  
    props: {  
        tips: {  
            type: Array,  
            default: () => {  
                return []  
            }  
        }  
    },  
    setup(props, context) {  
        return {  
            ...toRefs(props)  
        }  
    }  
    })  
    </script>
  2. import { getCurrentInstance } from vue,uni-app框架下在vue中暂时拿不到getCurrentInstance这个函数,无法访问到getCurrentInstance

  3. v-model双向数据绑定默认用的还是原来的value属性和input事件,不是vue3.0中的v-bind:modelValue="xxx"的modelValue属性和update:modelValue事件;

  4. ref无法获取组件实例ref引用;

    
    <share ref="shareRef" ></share>  
    const shareRef = ref(null)  
    onMounted(() => {  
    console.log('onMounted, shareRef: ', shareRef.value)//此处打印null,undefined  
    })  
收起阅读 »

window系统下 ios从入门到上线appstore

云打包 Appstore上传 iOS打包

感谢:我的好兄弟柳晨以及朱玉丹

有图有真相

前同事镇楼

第一步:

去下面这个网址 下载csr文件 免费的
https://www.yunedit.com/update/appstore/list

第二步:

1.苹果开发者网站 注册开发者 需要填写信息(太多了不做过多的描述)

https://developer.apple.com/account/#/overview/3T76S86992

红色框内选中注册

2.勾选 iOS Distribution (App Store and Ad Hoc)(上线到appsore) 一路next

下载 文件 ios_distribution.cer

回到第一步 上传cer 文件

3.点击 Identifiers 选中 App IDs app 填写 Bundle ID 一路next 保存即可 不需要下载

4.点击Profiles 两种选项 Development(开发) Distribution(生产)选中 App Store 下载mobileprovision

5.回到第一步生成.p12文件(不免费 一年大约29元人民币)同时生成密码

以上云打包ios上线所需要的文件 全部齐全

                                                                                                                                                                                           HBuildx:2.8.11.20200907  

                                                                                                                                                                                           联系邮箱:97272442@qq.com  
继续阅读 »

感谢:我的好兄弟柳晨以及朱玉丹

有图有真相

前同事镇楼

第一步:

去下面这个网址 下载csr文件 免费的
https://www.yunedit.com/update/appstore/list

第二步:

1.苹果开发者网站 注册开发者 需要填写信息(太多了不做过多的描述)

https://developer.apple.com/account/#/overview/3T76S86992

红色框内选中注册

2.勾选 iOS Distribution (App Store and Ad Hoc)(上线到appsore) 一路next

下载 文件 ios_distribution.cer

回到第一步 上传cer 文件

3.点击 Identifiers 选中 App IDs app 填写 Bundle ID 一路next 保存即可 不需要下载

4.点击Profiles 两种选项 Development(开发) Distribution(生产)选中 App Store 下载mobileprovision

5.回到第一步生成.p12文件(不免费 一年大约29元人民币)同时生成密码

以上云打包ios上线所需要的文件 全部齐全

                                                                                                                                                                                           HBuildx:2.8.11.20200907  

                                                                                                                                                                                           联系邮箱:97272442@qq.com  
收起阅读 »

uni-app滚动问题,切换tab让下面的内容滚动到相应位置

HTML部分

scroll-y="true" style="height: 500px;" :scroll-top="scrollTop" @scroll="scroll" 这四项都得有

高度需要设置一个具体值,可用变量,有时会用到uni.getSystemInfo获取屏幕高度进一步计算

<scroll-view scroll-y="true" style="height: 500px;" :scroll-top="scrollTop"  @scroll="scroll">  
</scroll-view>

data部分 俩变量

scrollTop: 100,  
old: {  
    scrollTop: 0  
},

methods部分

scroll(e) {  
    this.old.scrollTop = e.detail.scrollTop  
},
// 使页面元素滚动的方法(切换两个tab让下面的内容滚动到紧挨着tab下面)  
changeRuleItem(item, index) {  
                this.policyTitle.map( (current, cindex) => {  
                    if (index == cindex) {  
                        current.active = true;  
                    } else {  
                        current.active = false;  
                    }  
                })  
                var that = this;  
                this.scrollTop = this.old.scrollTop; // 先初始化scrollTop为上次滚动值  
                if (this.policyTitle[0].active) {  
                    uni.createSelectorQuery().select("#policy-begin").boundingClientRect(data=>{//目标节点  
                      uni.createSelectorQuery().select(".check-popup").boundingClientRect((res)=>{//最外层盒子节点  
                            setTimeout(gogogo, 100);  
                            function gogogo() {  
                                const query = uni.createSelectorQuery().in(that);  
                                query.select('#policy-pop').boundingClientRect(data => {  
                                    if (data) {  
                                        console.log()  
                                        that.scrollTop = res.top - data.top;  
                                    }  
                                }).exec();  
                            }  
                      }).exec()  
                    }).exec();  

                } else {  
                    uni.createSelectorQuery().select("#policy-luggage").boundingClientRect(data=>{//目标节点  
                      uni.createSelectorQuery().select("#policy-begin").boundingClientRect((res)=>{//最外层盒子节点  
                            setTimeout(gogogo, 100);  
                            function gogogo() {  
                                const query = uni.createSelectorQuery().in(that);  
                                query.select('#policy-pop').boundingClientRect(data1 => {  
                                    if (data) {  
                                        that.scrollTop = data.top - res.top;  
                                    }  
                                }).exec();  
                            }  
                      }).exec()  
                    }).exec();  
                }  
            }  

尚未解决的问题

  1. 没有滚动过程
  2. 没弄清楚怎么精确到指定位置
继续阅读 »

HTML部分

scroll-y="true" style="height: 500px;" :scroll-top="scrollTop" @scroll="scroll" 这四项都得有

高度需要设置一个具体值,可用变量,有时会用到uni.getSystemInfo获取屏幕高度进一步计算

<scroll-view scroll-y="true" style="height: 500px;" :scroll-top="scrollTop"  @scroll="scroll">  
</scroll-view>

data部分 俩变量

scrollTop: 100,  
old: {  
    scrollTop: 0  
},

methods部分

scroll(e) {  
    this.old.scrollTop = e.detail.scrollTop  
},
// 使页面元素滚动的方法(切换两个tab让下面的内容滚动到紧挨着tab下面)  
changeRuleItem(item, index) {  
                this.policyTitle.map( (current, cindex) => {  
                    if (index == cindex) {  
                        current.active = true;  
                    } else {  
                        current.active = false;  
                    }  
                })  
                var that = this;  
                this.scrollTop = this.old.scrollTop; // 先初始化scrollTop为上次滚动值  
                if (this.policyTitle[0].active) {  
                    uni.createSelectorQuery().select("#policy-begin").boundingClientRect(data=>{//目标节点  
                      uni.createSelectorQuery().select(".check-popup").boundingClientRect((res)=>{//最外层盒子节点  
                            setTimeout(gogogo, 100);  
                            function gogogo() {  
                                const query = uni.createSelectorQuery().in(that);  
                                query.select('#policy-pop').boundingClientRect(data => {  
                                    if (data) {  
                                        console.log()  
                                        that.scrollTop = res.top - data.top;  
                                    }  
                                }).exec();  
                            }  
                      }).exec()  
                    }).exec();  

                } else {  
                    uni.createSelectorQuery().select("#policy-luggage").boundingClientRect(data=>{//目标节点  
                      uni.createSelectorQuery().select("#policy-begin").boundingClientRect((res)=>{//最外层盒子节点  
                            setTimeout(gogogo, 100);  
                            function gogogo() {  
                                const query = uni.createSelectorQuery().in(that);  
                                query.select('#policy-pop').boundingClientRect(data1 => {  
                                    if (data) {  
                                        that.scrollTop = data.top - res.top;  
                                    }  
                                }).exec();  
                            }  
                      }).exec()  
                    }).exec();  
                }  
            }  

尚未解决的问题

  1. 没有滚动过程
  2. 没弄清楚怎么精确到指定位置
收起阅读 »