
jdk17新版本获取签名MD5
安装好jdk,设置好环境变量以后,新版本不提供md5的查看
想要查看需要使用新命令
keytool -exportcert -keystore 你的名称.keystore | openssl dgst -md5
如果提示openssl 不是内部命令
就要安装openssl
安装方法:(偷个懒 大家去看大佬的博客)
https://blog.csdn.net/qq_46550964/article/details/111507119
安装好jdk,设置好环境变量以后,新版本不提供md5的查看
想要查看需要使用新命令
keytool -exportcert -keystore 你的名称.keystore | openssl dgst -md5
如果提示openssl 不是内部命令
就要安装openssl
安装方法:(偷个懒 大家去看大佬的博客)
https://blog.csdn.net/qq_46550964/article/details/111507119

v-show和v-for用在用一个元素上,实现input搜索功能
- <van-field
- class="date-selector"
- v-model="search.kdgtName"
- placeholder="请输入搜索内容" />
- <van-cell
- v-show="item.name.includes(search.kdgtName)"
- key="i"
v-for="(item,i) in kdgtNameList"
class="date-item"
@click="setkdgtName(item)">
<span class="item-text">{{item.name}}</span>
</van-cell>
通过 v-show和 v-for以及includes的使用,实现input搜索功能。
注意:这只适合数据量较少的情况下。
固定定位下的水平垂直居中,可以试一试:
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
- <van-field
- class="date-selector"
- v-model="search.kdgtName"
- placeholder="请输入搜索内容" />
- <van-cell
- v-show="item.name.includes(search.kdgtName)"
- key="i"
v-for="(item,i) in kdgtNameList"
class="date-item"
@click="setkdgtName(item)">
<span class="item-text">{{item.name}}</span>
</van-cell>
通过 v-show和 v-for以及includes的使用,实现input搜索功能。
注意:这只适合数据量较少的情况下。
固定定位下的水平垂直居中,可以试一试:
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;

window.open 下载文件
通过window.open方法进行文件下载,例如:
window.open("https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-dc-site/bf4ed9a0-4fdb-11eb-8a36-ebb87efcf8c0.png?attname=1.png");
注意:加上?attname=1.png可以下载一个命名为1的图片。
不是每个资源文件都可以window.open方法进行文件下载,但是通过加attname属性就可以
通过window.open方法进行文件下载,例如:
window.open("https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-dc-site/bf4ed9a0-4fdb-11eb-8a36-ebb87efcf8c0.png?attname=1.png");
注意:加上?attname=1.png可以下载一个命名为1的图片。
不是每个资源文件都可以window.open方法进行文件下载,但是通过加attname属性就可以

UNIAPP 局域网打印
我是采用CLodop 插件开发局域网打印的, 需要手持设备,一台打印服务器,打印机在同一个局域网内即可。
目前测试稳定性还可以,满足业务使用
引用一个js文件即可,其他调用方式同CLodop调用方式一样。
我是采用CLodop 插件开发局域网打印的, 需要手持设备,一台打印服务器,打印机在同一个局域网内即可。
目前测试稳定性还可以,满足业务使用
引用一个js文件即可,其他调用方式同CLodop调用方式一样。

官方支持了google pay,但是没有支持google play支付,需要自己写原生插件
google play 的支付用于商店内的应用或应用内购买,多用于虚拟物品,游戏币等区域。
google pay 官方目的是用于线下/线上的实物类交易。
google play 的支付用于商店内的应用或应用内购买,多用于虚拟物品,游戏币等区域。
google pay 官方目的是用于线下/线上的实物类交易。

H5调用摄像头扫描条形码
参考文献:https://github.com/maslick/koder
识别效率相对较高
参考文献:https://github.com/maslick/koder
识别效率相对较高

可视化编辑照片书
照片编辑可视化小程序,前端uniapp,后端PHP,一款综合全面的图片编辑软件,支持裁剪、旋转、改尺寸、压缩体积、文字、贴纸、边框等图片编辑功能。软件汇集了大量的模板和装饰素材,采用可视化的设计界面,用户只需导入图片编辑即可制作成书。软件支持快速排版,简单易用,适合制作个性杂志、个性台历、纪念册、个性笔记本等。照片书排版是一款功能强大的照片书制作工具。软件汇集了大量的模板和装饰素材,采用可视化的设计界面,用户只需导入图片编辑即可制作成书。软件支持快速排版,简单易用,适合制作个性杂志、个性台历、纪念册、个性笔记本等。可以打包app,目前已有现成小程序可以体验,欢迎有需要的人士前来询问,V:zpj2220
照片编辑可视化小程序,前端uniapp,后端PHP,一款综合全面的图片编辑软件,支持裁剪、旋转、改尺寸、压缩体积、文字、贴纸、边框等图片编辑功能。软件汇集了大量的模板和装饰素材,采用可视化的设计界面,用户只需导入图片编辑即可制作成书。软件支持快速排版,简单易用,适合制作个性杂志、个性台历、纪念册、个性笔记本等。照片书排版是一款功能强大的照片书制作工具。软件汇集了大量的模板和装饰素材,采用可视化的设计界面,用户只需导入图片编辑即可制作成书。软件支持快速排版,简单易用,适合制作个性杂志、个性台历、纪念册、个性笔记本等。可以打包app,目前已有现成小程序可以体验,欢迎有需要的人士前来询问,V:zpj2220
收起阅读 »
使用uniapp开发ZEBRA(斑马 TC21/TC26)PDA,开启/关闭激光红外,接收扫描数据
公司要为斑马PDA开发app,使用技术是uniapp,需求是当管理后台给PDA分配扫码权限后,PDA才能启动激光红外扫码功能,否则不能启动扫码,最开始的实现思路是当拥有扫码权限,就处理扫描出来的数据,没有扫码权限就不处理扫描出来的数据(注:当没有扫码权限时,按下物理的扫描按键也会出现激光),老板说不行,必须是没有权限不能启动激光红外线,也就是没有权限,按了物理的扫描按键,也不能出现激光。
带着需求在斑马官网找到了对应的API,因此记录一下自己开发过程,方便以后查找,也方便即将遇到同样问题的同学
1、拿出斑马PDA充电、并开机,手指在主屏幕上,向上滑动,找到应用“DataWedge”,如图

2、点击“DataWedge”,启动Profile0(default)文件,并配置Intent输出,禁用Launcher和DWDemo配置文件,如图
3、好了,斑马PDA已经设置好了,现在开始用uniapp做开发了,主要代码如下
var scanObj = {};
//是否开启激光红外线扫描,true开启,false关闭
Vue.prototype.isOpenLaserScan = (isOpen) => {
scanObj.main = plus.android.runtimeMainActivity();//获取activity
var Intent = plus.android.importClass('android.content.Intent');
scanObj.intent = new Intent();
scanObj.intent.setAction("com.symbol.datawedge.api.ACTION");
scanObj.intent.putExtra("com.symbol.datawedge.api.ENABLE_DATAWEDGE", isOpen);
scanObj.main.sendBroadcast(scanObj.intent);
}
//初始化扫描设备
Vue.prototype.initScan = (fun) => {
scanObj.main = plus.android.runtimeMainActivity();//获取activity
var IntentFilter = plus.android.importClass('android.content.IntentFilter');
scanObj.filter = new IntentFilter();
scanObj.filter.addAction("com.dwexample.ACTION"); // 换你的广播动作 com.service.scanner.data(海康威视的PDA)
scanObj.receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver',{
onReceive: function(context, intent) {
plus.android.importClass(intent);
let code = intent.getStringExtra("com.motorolasolutions.emdk.datawedge.data_string");// 换你的广播标签 ScanCode(海康威视的PDA)
if(typeof(fun) === 'function'){
fun(code);
}
}});
}
//启动扫描设备
Vue.prototype.startScan = () => {
try{
scanObj.main.registerReceiver(scanObj.receiver,scanObj.filter);
}catch(e){
//TODO handle the exception
}
}
//停止扫描设备
Vue.prototype.stopScan = () => {
try{
scanObj.main.unregisterReceiver(scanObj.receiver);
}catch(e){
//TODO handle the exception
}
}
4、在生命周期onShow函数中调用扫码,页面调用如下
onShow(){
//监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面
let _this = this;
//是否开启激光红外线扫描,默认开启
_this.isOpenLaserScan(true);
//判断是否拥有当前页面的扫码权限,这里是自己业务的权限判断
if (!_this.hasPerm('PutBaseFlour:scan')) {
uni.showModal({
title: '提示',
content: '你没有扫码权限,无法开启激光扫码,请联系管理员!',
showCancel: false
});
setTimeout(() => {
//是否开启激光红外线扫描,没有相应的权限则关闭
_this.isOpenLaserScan(false);
}, 500);
return;
}
_this.initScan((code) => {
//处理自己的业务逻辑
//code为扫码取得的值
});
_this.startScan();
}
5、使用完成后需要销毁,由于app、h5、ios、微信等所支持的生命周期有所不同,建议在以下生命周期中销毁防止没有销毁掉的情况,避免多次进入页面扫码后取得多个值
onHide(){
//监听页面隐藏
if (this.hasPerm('PutBaseFlour:scan')) {
this.stopScan();
}
},
onUnload(){
//监听页面卸载
if (this.hasPerm('PutBaseFlour:scan')) {
this.stopScan();
}
},
onBackPress(){
//监听页面返回
if (this.hasPerm('PutBaseFlour:scan')) {
this.stopScan();
}
},
destroyed:function(){
//页面退出时一定要卸载监听,否则下次进来时会重复,造成扫一次出2个以上的结果
if (this.hasPerm('PutBaseFlour:scan')) {
this.stopScan();
}
}
公司要为斑马PDA开发app,使用技术是uniapp,需求是当管理后台给PDA分配扫码权限后,PDA才能启动激光红外扫码功能,否则不能启动扫码,最开始的实现思路是当拥有扫码权限,就处理扫描出来的数据,没有扫码权限就不处理扫描出来的数据(注:当没有扫码权限时,按下物理的扫描按键也会出现激光),老板说不行,必须是没有权限不能启动激光红外线,也就是没有权限,按了物理的扫描按键,也不能出现激光。
带着需求在斑马官网找到了对应的API,因此记录一下自己开发过程,方便以后查找,也方便即将遇到同样问题的同学
1、拿出斑马PDA充电、并开机,手指在主屏幕上,向上滑动,找到应用“DataWedge”,如图
2、点击“DataWedge”,启动Profile0(default)文件,并配置Intent输出,禁用Launcher和DWDemo配置文件,如图
3、好了,斑马PDA已经设置好了,现在开始用uniapp做开发了,主要代码如下
var scanObj = {};
//是否开启激光红外线扫描,true开启,false关闭
Vue.prototype.isOpenLaserScan = (isOpen) => {
scanObj.main = plus.android.runtimeMainActivity();//获取activity
var Intent = plus.android.importClass('android.content.Intent');
scanObj.intent = new Intent();
scanObj.intent.setAction("com.symbol.datawedge.api.ACTION");
scanObj.intent.putExtra("com.symbol.datawedge.api.ENABLE_DATAWEDGE", isOpen);
scanObj.main.sendBroadcast(scanObj.intent);
}
//初始化扫描设备
Vue.prototype.initScan = (fun) => {
scanObj.main = plus.android.runtimeMainActivity();//获取activity
var IntentFilter = plus.android.importClass('android.content.IntentFilter');
scanObj.filter = new IntentFilter();
scanObj.filter.addAction("com.dwexample.ACTION"); // 换你的广播动作 com.service.scanner.data(海康威视的PDA)
scanObj.receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver',{
onReceive: function(context, intent) {
plus.android.importClass(intent);
let code = intent.getStringExtra("com.motorolasolutions.emdk.datawedge.data_string");// 换你的广播标签 ScanCode(海康威视的PDA)
if(typeof(fun) === 'function'){
fun(code);
}
}});
}
//启动扫描设备
Vue.prototype.startScan = () => {
try{
scanObj.main.registerReceiver(scanObj.receiver,scanObj.filter);
}catch(e){
//TODO handle the exception
}
}
//停止扫描设备
Vue.prototype.stopScan = () => {
try{
scanObj.main.unregisterReceiver(scanObj.receiver);
}catch(e){
//TODO handle the exception
}
}
4、在生命周期onShow函数中调用扫码,页面调用如下
onShow(){
//监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面
let _this = this;
//是否开启激光红外线扫描,默认开启
_this.isOpenLaserScan(true);
//判断是否拥有当前页面的扫码权限,这里是自己业务的权限判断
if (!_this.hasPerm('PutBaseFlour:scan')) {
uni.showModal({
title: '提示',
content: '你没有扫码权限,无法开启激光扫码,请联系管理员!',
showCancel: false
});
setTimeout(() => {
//是否开启激光红外线扫描,没有相应的权限则关闭
_this.isOpenLaserScan(false);
}, 500);
return;
}
_this.initScan((code) => {
//处理自己的业务逻辑
//code为扫码取得的值
});
_this.startScan();
}
5、使用完成后需要销毁,由于app、h5、ios、微信等所支持的生命周期有所不同,建议在以下生命周期中销毁防止没有销毁掉的情况,避免多次进入页面扫码后取得多个值
onHide(){
//监听页面隐藏
if (this.hasPerm('PutBaseFlour:scan')) {
this.stopScan();
}
},
onUnload(){
//监听页面卸载
if (this.hasPerm('PutBaseFlour:scan')) {
this.stopScan();
}
},
onBackPress(){
//监听页面返回
if (this.hasPerm('PutBaseFlour:scan')) {
this.stopScan();
}
},
destroyed:function(){
//页面退出时一定要卸载监听,否则下次进来时会重复,造成扫一次出2个以上的结果
if (this.hasPerm('PutBaseFlour:scan')) {
this.stopScan();
}
}

更新最新版本后,uniapp安心打包报错
[Info] 正在制作apk安装包...
[Info] I: Using Apktool 2.4.1 on __UNI__2DB9CA0_cm.apk
[Info] I: Loading resource table...
[Info] I: Decoding AndroidManifest.xml with resources...
[Info] I: Loading resource table from file: C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\apktool\1.apk
[Info] I: Regular manifest package...
[Info] I: Decoding file-resources...
[Info] I: Decoding values */* XMLs...
[Info] I: Copying raw classes.dex file...
[Info] I: Copying raw classes2.dex file...
[Info] I: Copying raw classes3.dex file...
[Info] I: Copying raw assets/39285EFA.dex file...
[Info] I: Copying assets and libs...
[Info] I: Copying unknown files...
[Info] I: Copying original files...
[Info] begin replace files to apk...
[Info] begin copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-hdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-hdpi/icon.png]...
[Info] copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-hdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-hdpi/icon.png] success.
[Info] begin copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xhdpi/icon.png]...
[Info] copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xhdpi/icon.png] success.
[Info] begin copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xxhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xxhdpi/icon.png]...
[Info] copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xxhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xxhdpi/icon.png] success.
[Info] begin copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xxxhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xxxhdpi/icon.png]...
[Info] copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xxxhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xxxhdpi/icon.png] success.
[Info] begin update files to apk...
[Error] try compile package:0
[Info] I: Using Apktool 2.4.1
[Info] I: Copying C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm classes.dex file...
[Info] I: Copying C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm classes2.dex file...
[Info] I: Copying C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm classes3.dex file...
[Info] I: Checking whether resources has changed...
[Info] I: Building resources...
[Error] W: C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml:48: Tag <action> attribute name has invalid character '*'.
[Error] brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [C:\Users\FGHF\AppData\Local\Temp\brut_util_Jar_13841587595912769514.tmp, p, --forced-package-id, 127, --min-sdk-version, 19, --target-sdk-version, 28, --version-code, 32, --version-name, 3.1.0, --no-version-vectors, -F, C:\Users\FGHF\AppData\Local\Temp\APKTOOL640673907049858768.tmp, -e, C:\Users\FGHF\AppData\Local\Temp\APKTOOL11117073117559654397.tmp, -0, arsc, -I, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\apktool\1.apk, -S, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\res, -M, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml]
[Error] try compile package:1
[Info] I: Using Apktool 2.4.1
[Info] I: Checking whether resources has changed...
[Info] I: Building resources...
[Error] W: C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml:48: Tag <action> attribute name has invalid character '*'.
[Error] brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [C:\Users\FGHF\AppData\Local\Temp\brut_util_Jar_1364484411461162108.tmp, p, --forced-package-id, 127, --min-sdk-version, 19, --target-sdk-version, 28, --version-code, 32, --version-name, 3.1.0, --no-version-vectors, -F, C:\Users\FGHF\AppData\Local\Temp\APKTOOL9195127418260236703.tmp, -e, C:\Users\FGHF\AppData\Local\Temp\APKTOOL13100643559112781843.tmp, -0, arsc, -I, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\apktool\1.apk, -S, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\res, -M, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml]
[Error] try compile package:2
[Info] I: Using Apktool 2.4.1
[Info] I: Checking whether resources has changed...
[Info] I: Building resources...
[Error] W: C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml:48: Tag <action> attribute name has invalid character '*'.
[Error] brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [C:\Users\FGHF\AppData\Local\Temp\brut_util_Jar_8421301333268526767.tmp, p, --forced-package-id, 127, --min-sdk-version, 19, --target-sdk-version, 28, --version-code, 32, --version-name, 3.1.0, --no-version-vectors, -F, C:\Users\FGHF\AppData\Local\Temp\APKTOOL15143234046447346603.tmp, -e, C:\Users\FGHF\AppData\Local\Temp\APKTOOL5501540500666506840.tmp, -0, arsc, -I, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\apktool\1.apk, -S, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\res, -M, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml]
[Error] Apk tool compile package to apk failed
[Error] 制作结果:Failed. Reason:
[Info] 正在制作apk安装包...
[Info] I: Using Apktool 2.4.1 on __UNI__2DB9CA0_cm.apk
[Info] I: Loading resource table...
[Info] I: Decoding AndroidManifest.xml with resources...
[Info] I: Loading resource table from file: C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\apktool\1.apk
[Info] I: Regular manifest package...
[Info] I: Decoding file-resources...
[Info] I: Decoding values */* XMLs...
[Info] I: Copying raw classes.dex file...
[Info] I: Copying raw classes2.dex file...
[Info] I: Copying raw classes3.dex file...
[Info] I: Copying raw assets/39285EFA.dex file...
[Info] I: Copying assets and libs...
[Info] I: Copying unknown files...
[Info] I: Copying original files...
[Info] begin replace files to apk...
[Info] begin copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-hdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-hdpi/icon.png]...
[Info] copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-hdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-hdpi/icon.png] success.
[Info] begin copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xhdpi/icon.png]...
[Info] copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xhdpi/icon.png] success.
[Info] begin copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xxhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xxhdpi/icon.png]...
[Info] copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xxhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xxhdpi/icon.png] success.
[Info] begin copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xxxhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xxxhdpi/icon.png]...
[Info] copy file[E:/work_wkz/yg_h5_v2/unpackage/cache/wgt/__UNI__2DB9CA0/.manifest/icon-android-xxxhdpi.png] to [C:/Users/FGHF/AppData/Local/HBuilder X/AndroidPackWork/cache/__UNI__2DB9CA0/packge_cache/__NONE__/__UNI__2DB9CA0_cm/res/drawable-xxxhdpi/icon.png] success.
[Info] begin update files to apk...
[Error] try compile package:0
[Info] I: Using Apktool 2.4.1
[Info] I: Copying C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm classes.dex file...
[Info] I: Copying C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm classes2.dex file...
[Info] I: Copying C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm classes3.dex file...
[Info] I: Checking whether resources has changed...
[Info] I: Building resources...
[Error] W: C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml:48: Tag <action> attribute name has invalid character '*'.
[Error] brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [C:\Users\FGHF\AppData\Local\Temp\brut_util_Jar_13841587595912769514.tmp, p, --forced-package-id, 127, --min-sdk-version, 19, --target-sdk-version, 28, --version-code, 32, --version-name, 3.1.0, --no-version-vectors, -F, C:\Users\FGHF\AppData\Local\Temp\APKTOOL640673907049858768.tmp, -e, C:\Users\FGHF\AppData\Local\Temp\APKTOOL11117073117559654397.tmp, -0, arsc, -I, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\apktool\1.apk, -S, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\res, -M, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml]
[Error] try compile package:1
[Info] I: Using Apktool 2.4.1
[Info] I: Checking whether resources has changed...
[Info] I: Building resources...
[Error] W: C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml:48: Tag <action> attribute name has invalid character '*'.
[Error] brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [C:\Users\FGHF\AppData\Local\Temp\brut_util_Jar_1364484411461162108.tmp, p, --forced-package-id, 127, --min-sdk-version, 19, --target-sdk-version, 28, --version-code, 32, --version-name, 3.1.0, --no-version-vectors, -F, C:\Users\FGHF\AppData\Local\Temp\APKTOOL9195127418260236703.tmp, -e, C:\Users\FGHF\AppData\Local\Temp\APKTOOL13100643559112781843.tmp, -0, arsc, -I, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\apktool\1.apk, -S, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\res, -M, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml]
[Error] try compile package:2
[Info] I: Using Apktool 2.4.1
[Info] I: Checking whether resources has changed...
[Info] I: Building resources...
[Error] W: C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml:48: Tag <action> attribute name has invalid character '*'.
[Error] brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [C:\Users\FGHF\AppData\Local\Temp\brut_util_Jar_8421301333268526767.tmp, p, --forced-package-id, 127, --min-sdk-version, 19, --target-sdk-version, 28, --version-code, 32, --version-name, 3.1.0, --no-version-vectors, -F, C:\Users\FGHF\AppData\Local\Temp\APKTOOL15143234046447346603.tmp, -e, C:\Users\FGHF\AppData\Local\Temp\APKTOOL5501540500666506840.tmp, -0, arsc, -I, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\apktool\1.apk, -S, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\res, -M, C:\Users\FGHF\AppData\Local\HBuilder X\AndroidPackWork\cache\__UNI__2DB9CA0\packge_cache\__NONE__\__UNI__2DB9CA0_cm\AndroidManifest.xml]
[Error] Apk tool compile package to apk failed
[Error] 制作结果:Failed. Reason:
收起阅读 »

解决cli项目下配合uniCloud开发时云函数上传下载过于麻烦的问题
一、要解决的问题
uniapp cli vue3 开发小程序时,大多采用的编辑器时vscode 如果此时同时使用unicloud,那么需要两个IDE来回切换,因此制作了一个小工具,原理上是对hbuilder cli 进行封装,从而可以更便捷的上传下载云函数
二、图片介绍
三、使用方法
务必将Hbuilder路径设在在环境变量内,否则会提示版本冲突
下载Releases内最符合您操作系统的版本,将uc.exe 文件放置在您的运行目录下即可使用如下方法进行操作
1. 列举资源信息
uc.exe -l [resource]
如 uc.exe -l cf
表示:列举当前项目中所有云端函数
2. 资源上传[默认覆盖非跳过]
uc.exe -u [resource] [name]
如 uc.exe -u cf test
表示:上传名称为test的云函数,如果云端存在同名函数则覆盖
3. 资源下载[默认覆盖非跳过]
uc.exe -d [resource] [name]
如 uc.exe -d cf test
表示:下载名称为test的云函数,如果本地存在同名函数则覆盖
4. resource的取值如下
resource | 含义 |
---|---|
cf 或 cloudfunction | 云函数 |
cm 或 common | 云函数的公共模块 |
db | 数据集合Schema |
vf | 数据库校验函数 |
ac 或 action | 数据库触发条件 |
sp 或 space | 云空间 |
四、链接下载地址
可以点击链接下载,或者下载附件内的压缩文件使用
github UC
一、要解决的问题
uniapp cli vue3 开发小程序时,大多采用的编辑器时vscode 如果此时同时使用unicloud,那么需要两个IDE来回切换,因此制作了一个小工具,原理上是对hbuilder cli 进行封装,从而可以更便捷的上传下载云函数
二、图片介绍
三、使用方法
务必将Hbuilder路径设在在环境变量内,否则会提示版本冲突
下载Releases内最符合您操作系统的版本,将uc.exe 文件放置在您的运行目录下即可使用如下方法进行操作
1. 列举资源信息
uc.exe -l [resource]
如 uc.exe -l cf
表示:列举当前项目中所有云端函数
2. 资源上传[默认覆盖非跳过]
uc.exe -u [resource] [name]
如 uc.exe -u cf test
表示:上传名称为test的云函数,如果云端存在同名函数则覆盖
3. 资源下载[默认覆盖非跳过]
uc.exe -d [resource] [name]
如 uc.exe -d cf test
表示:下载名称为test的云函数,如果本地存在同名函数则覆盖
4. resource的取值如下
resource | 含义 |
---|---|
cf 或 cloudfunction | 云函数 |
cm 或 common | 云函数的公共模块 |
db | 数据集合Schema |
vf | 数据库校验函数 |
ac 或 action | 数据库触发条件 |
sp 或 space | 云空间 |
四、链接下载地址
可以点击链接下载,或者下载附件内的压缩文件使用
github UC

关于动态取消checkbox选中状态代码实现~~~~~~
记住文档的一句话:checkbox的checked只做默认选中状态功能
业务逻辑是,在列表中选择学生,但是选中人数有限定,当选中事件触发后,判断当前选中人数是否超过限定人数,如果有,则将新选中的学生取消选中
核心逻辑是:
记录前几次选中的ID,找出最新选中的下标,然后将列表list清空,并根据前几次选中情况重新赋值新变量存数组,并将前几次选中的学生赋值为选中状态,在页面渲染完成后,在赋值给list
相当于对list的指针做了修改,达到页面同步更新的目的
<template>
<view class="cflex content">
<view class="w100 p25 cflex aifs w100 info-box jcsb">
<view>{{info.title}}</view>
<view class="rflex jcfs info-status">
<view>状态:{{info.statusName}}</view>
<view class="split">|</view>
<view>可投票:{{info.voteNum}}人</view>
</view>
</view>
<view class="line"></view>
<view class="p30 w100">
<checkbox-group @change="checkStudent">
<template v-for="item in list">
<label>
<view class="w100 score-item p30 cflex jcsa aifs" :key="item.studentId">
<view class="list-title rflex jcsb">
<text>{{item.studentName}}</text>
<checkbox :value="item.studentId.toString()" color="#fff" :checked="item.checked"/>
</view>
<view class="rflex aic w100">
<view>姓名:{{item.studentName}}</view>
<view class="split">|</view>
<view>性别:{{item.sexName}}</view>
</view>
</view>
</label>
</template>
</checkbox-group>
</view>
<view class="w100 cflex">
<view class="submit-btn cflex">
<text>继续学习</text>
</view>
</view>
</view>
</template>
<script>
import $cache from '@/common/js/cache.js';
import $studentTheory from '@/common/js/import/studentTheory.js';
export default {
onShow() {
let courseInfo = $cache.getCourseCache();
if (courseInfo) {
this.courseInfo = courseInfo;
let evaluationCache = $cache.getEvaluationCache();
if (evaluationCache) {
this.info = evaluationCache;
this.getDetail();
} else {
this.$common.backTips('未找到互评信息');
}
} else {
this.$common.backTips('未找到课程信息');
}
},
data() {
return {
info: {},
courseInfo: {},
list: [],
submitData: {
checkList: []
}
}
},
methods: {
getDetail() {
let statusConfig = {
1: '未开始',
2: '互评中',
3: '已结束'
};
this.$common.loading();
$studentTheory.evaluationDetail({courseEvaluationId: this.info.courseEvaluationId}, (res) => {
if (res.code == 200) {
res.data.statusName = statusConfig[res.data.status] != null ? statusConfig[res.data.status] : '';
this.info = Object.assign({}, this.info, res.data);
this.$common.getDict('sex', (dict) => {
$studentTheory.evaluationClassStudent({}, (res) => {
this.$common.loading(false);
if (res.code == 200) {
this.$each(res.data, (item) => {
item.checked = false;
item.sexName = dict[item.sex] ? dict[item.sex].dictValue : '';
});
this.list = res.data;
} else {
this.$common.backTips(res.msg);
}
});
});
} else {
this.$common.backTips(res.msg);
}
});
},
checkStudent(val) {
let valArr = val.detail.value;
//取出新增项下标
let addIndex = -1;
if (valArr.length > this.submitData.checkList.length) {
this.$each(valArr, (id, index) => {
if (!this.submitData.checkList.includes(id)) {
addIndex = index;
return false;
}
});
}
let num = valArr.length;
if (num > this.info.voteNum) {
let lastIndex = valArr.length - 1;
valArr.splice(addIndex, 1); //删除新增项
this.$common.tips('最多只能选择 ' + this.info.voteNum + ' 人');
let tmpArr = Object.assign([], this.list);
this.$each(tmpArr, (item, index) => {
item.checked = false;
if (valArr.includes(item.studentId.toString())) {
item.checked = true;
}
});
this.list = [];
this.$nextTick(() => {
this.list = tmpArr;
});
}
this.submitData.checkList = valArr;
}
}
}
</script>
记住文档的一句话:checkbox的checked只做默认选中状态功能
业务逻辑是,在列表中选择学生,但是选中人数有限定,当选中事件触发后,判断当前选中人数是否超过限定人数,如果有,则将新选中的学生取消选中
核心逻辑是:
记录前几次选中的ID,找出最新选中的下标,然后将列表list清空,并根据前几次选中情况重新赋值新变量存数组,并将前几次选中的学生赋值为选中状态,在页面渲染完成后,在赋值给list
相当于对list的指针做了修改,达到页面同步更新的目的
<template>
<view class="cflex content">
<view class="w100 p25 cflex aifs w100 info-box jcsb">
<view>{{info.title}}</view>
<view class="rflex jcfs info-status">
<view>状态:{{info.statusName}}</view>
<view class="split">|</view>
<view>可投票:{{info.voteNum}}人</view>
</view>
</view>
<view class="line"></view>
<view class="p30 w100">
<checkbox-group @change="checkStudent">
<template v-for="item in list">
<label>
<view class="w100 score-item p30 cflex jcsa aifs" :key="item.studentId">
<view class="list-title rflex jcsb">
<text>{{item.studentName}}</text>
<checkbox :value="item.studentId.toString()" color="#fff" :checked="item.checked"/>
</view>
<view class="rflex aic w100">
<view>姓名:{{item.studentName}}</view>
<view class="split">|</view>
<view>性别:{{item.sexName}}</view>
</view>
</view>
</label>
</template>
</checkbox-group>
</view>
<view class="w100 cflex">
<view class="submit-btn cflex">
<text>继续学习</text>
</view>
</view>
</view>
</template>
<script>
import $cache from '@/common/js/cache.js';
import $studentTheory from '@/common/js/import/studentTheory.js';
export default {
onShow() {
let courseInfo = $cache.getCourseCache();
if (courseInfo) {
this.courseInfo = courseInfo;
let evaluationCache = $cache.getEvaluationCache();
if (evaluationCache) {
this.info = evaluationCache;
this.getDetail();
} else {
this.$common.backTips('未找到互评信息');
}
} else {
this.$common.backTips('未找到课程信息');
}
},
data() {
return {
info: {},
courseInfo: {},
list: [],
submitData: {
checkList: []
}
}
},
methods: {
getDetail() {
let statusConfig = {
1: '未开始',
2: '互评中',
3: '已结束'
};
this.$common.loading();
$studentTheory.evaluationDetail({courseEvaluationId: this.info.courseEvaluationId}, (res) => {
if (res.code == 200) {
res.data.statusName = statusConfig[res.data.status] != null ? statusConfig[res.data.status] : '';
this.info = Object.assign({}, this.info, res.data);
this.$common.getDict('sex', (dict) => {
$studentTheory.evaluationClassStudent({}, (res) => {
this.$common.loading(false);
if (res.code == 200) {
this.$each(res.data, (item) => {
item.checked = false;
item.sexName = dict[item.sex] ? dict[item.sex].dictValue : '';
});
this.list = res.data;
} else {
this.$common.backTips(res.msg);
}
});
});
} else {
this.$common.backTips(res.msg);
}
});
},
checkStudent(val) {
let valArr = val.detail.value;
//取出新增项下标
let addIndex = -1;
if (valArr.length > this.submitData.checkList.length) {
this.$each(valArr, (id, index) => {
if (!this.submitData.checkList.includes(id)) {
addIndex = index;
return false;
}
});
}
let num = valArr.length;
if (num > this.info.voteNum) {
let lastIndex = valArr.length - 1;
valArr.splice(addIndex, 1); //删除新增项
this.$common.tips('最多只能选择 ' + this.info.voteNum + ' 人');
let tmpArr = Object.assign([], this.list);
this.$each(tmpArr, (item, index) => {
item.checked = false;
if (valArr.includes(item.studentId.toString())) {
item.checked = true;
}
});
this.list = [];
this.$nextTick(() => {
this.list = tmpArr;
});
}
this.submitData.checkList = valArr;
}
}
}
</script>
收起阅读 »