linux使用安卓虚拟机可以开发h5+app
安装安卓模拟器https://github.com/anbox/anbox/blob/master/docs/install.md
安装完成之后安装adb:
sudo apt install android-tools-adb
本人电脑环境ubuntu20,04安装的deepin-wine环境 ,可以使用官方的方法安装wine环境运行HBubilderx运行之后可识别到安卓模拟器.缺点是电脑上测试扫码等硬件功能不好用。不知道官方为什么不开发出通过无线的方式同步app,之前使用的别的混合开发框架能够实现,效果很好,希望官方能考虑下。 安装安卓模拟器https://github.com/anbox/anbox/blob/master/docs/install.md
安装完成之后安装adb:
sudo apt install android-tools-adb
本人电脑环境ubuntu20,04安装的deepin-wine环境 ,可以使用官方的方法安装wine环境运行HBubilderx运行之后可识别到安卓模拟器.缺点是电脑上测试扫码等硬件功能不好用。不知道官方为什么不开发出通过无线的方式同步app,之前使用的别的混合开发框架能够实现,效果很好,希望官方能考虑下。 收起阅读 »
uniapp 安卓端实现应用保活
插件链接: https://ext.dcloud.net.cn/plugin?id=2930
插件解决的问题
app切换到后台、锁屏之后,系统经常会杀死app,导致app通信,定时任务、后台定位定位等无法正常运行。
插件链接: https://ext.dcloud.net.cn/plugin?id=2930
插件解决的问题
app切换到后台、锁屏之后,系统经常会杀死app,导致app通信,定时任务、后台定位定位等无法正常运行。
建议 movable-area 支持 app-nvue平台 手势缩放
建议官方 movable-area组件 支持 app-nvue平台 手势缩放
建议官方 movable-area组件 支持 app-nvue平台 手势缩放
H5 中,下拉刷新的转圈图标颜色修改
在文档中没有找到配置的地方(这个一般是刚需吧?差评)
所以不用想那么多,既然是 H5,那就可以使用样式覆盖。
通过观察元素样式,可以看到有两个地方的颜色需要修改。
在 App.vue 中设置样式进行覆盖
.uni-page-refresh-inner {
svg {
fill: #1192b8 !important;
}
circle {
stroke: #1192b8 !important;
}
}

在文档中没有找到配置的地方(这个一般是刚需吧?差评)
所以不用想那么多,既然是 H5,那就可以使用样式覆盖。
通过观察元素样式,可以看到有两个地方的颜色需要修改。
在 App.vue 中设置样式进行覆盖
.uni-page-refresh-inner {
svg {
fill: #1192b8 !important;
}
circle {
stroke: #1192b8 !important;
}
}

switchTab H5可以正常调整,真机测试无法正常跳转
uni.switchTab({
url:'../xxxx/xxx'
})
这样是不行的
必须得是
uni.switchTab({
url:'/pages/xxxx/xxx'
})
uni.switchTab({
url:'../xxxx/xxx'
})
这样是不行的
必须得是
uni.switchTab({
url:'/pages/xxxx/xxx'
})
作为一个程序员,请不要相信神鬼现象
程序员经常会遇到一些莫名其妙的问题,百思不得其解,谓之神鬼现象。
但在01构成的数字世界,其实没有神鬼。
揭穿神鬼,找到本源,是一个优秀程序员的必备修炼过程。
有两个广为流传的故事:
故事一:香草冰激凌
有一天,美国通用汽车公司收到一封客户抱怨信,上面是这样写的:
这是我为了同一件事第二次写信给你,我不会怪你们为什么没有回信给我,因为我也觉得这样别人会认为我疯了,但这的确是一个事实。
我们家有一个传统的习惯,就是我们每天在吃完晚餐后,都会以冰淇淋来当我们的饭后甜点。
由于冰淇淋的口味很多,所以我们家每天在饭后才投票决定要吃哪一种口味,等大家决定后我就开车去买。
但自从最近我买了一部新的通用汽车后,在我去买冰淇淋的这段路程问题就发生了。
你知道吗?每当我买的冰淇淋是香草口味时,我从店里出来车子就发不动。但如果我买的是其他的口味,车子发动就顺得很。
我要让你知道,我对这件事情是非常认真的,尽管这个问题听起来很猪头。
为什么这部通用汽车当我买了香草冰淇淋它就秀逗,而我不管什么时候买其它口味的冰淇淋,它就一尾活龙?为什么?为什么?
这听起来很神鬼,汽车怎么会对香草冰激凌过敏?
虽然通用汽车的高层领导对这封信心存怀疑,但他还是派了一位工程师去查看究竟。
当工程师去找这位仁兄时,很惊讶的发现这封信是出自于一位事业成功且受了高等教育人。
工程师安排与这位仁兄的见面时间刚好是在用完晚餐的时间,两人于是一个箭步跃上车,往冰淇淋店开去。
那个晚上投票结果是香草口味,当买好香草冰淇淋回到车上后,车子又秀逗了。
这位工程师之后又依约来了三个晚上。
第一晚,巧克力冰淇淋,车子没事。
第二晚,草莓冰淇淋,车子也没事。
第三晚,香草冰淇淋,车子秀逗。
这位思考有逻辑的工程师,到目前还是死不相信这位仁兄的车子对香草过敏。因此,他仍然不放弃继续安排相同的行程,希望能够将这个问题解决。
工程师开始记下从头到现在所发生的种种详细资料,如时间、车子使用油的种类、车子开出及开回的时间……
根据资料显示他有了一个结论,这位仁兄买香草冰淇淋所花的时间比其它口味的要少。
为什么呢?原因是出在这家冰淇淋店的内部设置的问题。
因为,香草冰淇淋是所有冰淇淋口味中最畅销的口味。
店家为了让顾客每次都能很快的取拿,将香草口味特别分开陈列在单独的冰柜,并将冰柜放置在店的前端。至于其它口味则放置在距离收银台较远的后端。
现在,工程师所要知道的疑问是,为什么这部车会因为从熄火到重新激活的时间较短时就会秀逗?
原因很清楚,绝对不是因为香草冰淇淋的关系,工程师很快地由心中浮现出,答案应该是“蒸气锁”。
因为当这位仁兄买其它口味时,由于时间较久,引擎有足够的时间散热,重新发动时就没有太大的问题。
但是买香草口味时,由于花的时间较短,引擎太热以至于还无法让“ 蒸气琐 ”有足够的散热时间。
故事二:自动重启的电脑
一天,微软的工程师接到了一个客户的电话,说他的计算机系统每到夜里就会自动重新启动,夜夜如此,非常奇怪。
工程师帮助客户仔细检查了各种系统报告,发现的确重启过,但是原因不明。
排查了一段时间,但系统还是每天一到半夜就出问题,仿佛灵异事件一般。
客户很着急,这位工程师建议客户,找一个人夜里守在计算机旁边,看看系统出故障当时到底是怎么回事。客户想了想,也就答应了,也许别无他法。
于是,客户安排了一名IT人员带着报纸,拿着相机,当晚整夜地坐在计算机旁边,等候问题发生。如果有任何问题,这名值班人员就会用相机把屏幕照下来。
奇怪的事情发生了!夜夜重启的系统,当晚安然度过!
工程师、客户都在问这名值班人员做了什么,他却丈二和尚摸不着头脑地说:“我就是看了看报纸,什么也没做啊!”
也许系统自动好了?实在想不通,大家就让这名值班人员回去休息了。
万万没想到的是,第二天晚上,系统再次出了问题,症状与从前一模一样!
于是,只要客户安排人员在计算机旁边守候,夜夜平安;只要一夜无人,必有故障。
其实,一切神鬼现象背后都有一个未被揭穿的谜底。
后来聪明的工程师仔细排查,分析到底那个值班人员有意、或无意做了什么,保护了系统。
终于发现,原来问题的根本原因是“空调”!!!
这个客户的机房原来平常是不开空调的。但是每当值班人员守夜的时候,因为机房太热,他就会打开空调看报纸,一直到第二天清晨。
如果没有开空调,机器的 CPU 过热就会出问题,这个问题自从入夏就反复发生。打开空调,系统就会安然无恙。
建议
西天取经要经历九九八十一难,在通往优秀工程师的道路,经历被神鬼现象折磨并成功揭穿谜底的磨难,是必修之路。
遇到神鬼现象,我们要做的第一件事是保持耐心。
然后采集数据、分析数据、寻找规律、提出假设、反复验真和验伪,真相就不会遥远。
现代的应用开发,依赖的环节越来越多。芯片、传感器、网络、rom、DCloud的引擎、小程序平台、各种插件、以及你的代码.....到处都可能是故障点。
需要对多套环境做对比实验,才能命中准确的故障点。
回到DCloud社区的问题反馈上,DCloud并非微软或通用那样的商业公司,无法派出客服人员去现场查看问题。此时,尤为依赖开发者提供精准的问题反馈。
即便是线上沟通,DCloud的技术人员每天也被大量无效反馈淹没,导致真正的bug得不到发现。
我们期待开发者,在社区报bug时:
- 做过仔细的验证,确定是DCloud引擎问题。实际上大部分报Bug的情况,如果开发者自己仔细做了验证,就不会在DCloud社区报bug了。避免DCloud技术人员投入无效精力去分析这些并非DCloud产品原因的问题
- 详细描述问题、提供重现方式
希望广大开发者和DCloud配合,每天让DCloud发现有效bug的数量提升更多,假以时日,让DCloud的产品问题越来越少。
共勉!
程序员经常会遇到一些莫名其妙的问题,百思不得其解,谓之神鬼现象。
但在01构成的数字世界,其实没有神鬼。
揭穿神鬼,找到本源,是一个优秀程序员的必备修炼过程。
有两个广为流传的故事:
故事一:香草冰激凌
有一天,美国通用汽车公司收到一封客户抱怨信,上面是这样写的:
这是我为了同一件事第二次写信给你,我不会怪你们为什么没有回信给我,因为我也觉得这样别人会认为我疯了,但这的确是一个事实。
我们家有一个传统的习惯,就是我们每天在吃完晚餐后,都会以冰淇淋来当我们的饭后甜点。
由于冰淇淋的口味很多,所以我们家每天在饭后才投票决定要吃哪一种口味,等大家决定后我就开车去买。
但自从最近我买了一部新的通用汽车后,在我去买冰淇淋的这段路程问题就发生了。
你知道吗?每当我买的冰淇淋是香草口味时,我从店里出来车子就发不动。但如果我买的是其他的口味,车子发动就顺得很。
我要让你知道,我对这件事情是非常认真的,尽管这个问题听起来很猪头。
为什么这部通用汽车当我买了香草冰淇淋它就秀逗,而我不管什么时候买其它口味的冰淇淋,它就一尾活龙?为什么?为什么?
这听起来很神鬼,汽车怎么会对香草冰激凌过敏?
虽然通用汽车的高层领导对这封信心存怀疑,但他还是派了一位工程师去查看究竟。
当工程师去找这位仁兄时,很惊讶的发现这封信是出自于一位事业成功且受了高等教育人。
工程师安排与这位仁兄的见面时间刚好是在用完晚餐的时间,两人于是一个箭步跃上车,往冰淇淋店开去。
那个晚上投票结果是香草口味,当买好香草冰淇淋回到车上后,车子又秀逗了。
这位工程师之后又依约来了三个晚上。
第一晚,巧克力冰淇淋,车子没事。
第二晚,草莓冰淇淋,车子也没事。
第三晚,香草冰淇淋,车子秀逗。
这位思考有逻辑的工程师,到目前还是死不相信这位仁兄的车子对香草过敏。因此,他仍然不放弃继续安排相同的行程,希望能够将这个问题解决。
工程师开始记下从头到现在所发生的种种详细资料,如时间、车子使用油的种类、车子开出及开回的时间……
根据资料显示他有了一个结论,这位仁兄买香草冰淇淋所花的时间比其它口味的要少。
为什么呢?原因是出在这家冰淇淋店的内部设置的问题。
因为,香草冰淇淋是所有冰淇淋口味中最畅销的口味。
店家为了让顾客每次都能很快的取拿,将香草口味特别分开陈列在单独的冰柜,并将冰柜放置在店的前端。至于其它口味则放置在距离收银台较远的后端。
现在,工程师所要知道的疑问是,为什么这部车会因为从熄火到重新激活的时间较短时就会秀逗?
原因很清楚,绝对不是因为香草冰淇淋的关系,工程师很快地由心中浮现出,答案应该是“蒸气锁”。
因为当这位仁兄买其它口味时,由于时间较久,引擎有足够的时间散热,重新发动时就没有太大的问题。
但是买香草口味时,由于花的时间较短,引擎太热以至于还无法让“ 蒸气琐 ”有足够的散热时间。
故事二:自动重启的电脑
一天,微软的工程师接到了一个客户的电话,说他的计算机系统每到夜里就会自动重新启动,夜夜如此,非常奇怪。
工程师帮助客户仔细检查了各种系统报告,发现的确重启过,但是原因不明。
排查了一段时间,但系统还是每天一到半夜就出问题,仿佛灵异事件一般。
客户很着急,这位工程师建议客户,找一个人夜里守在计算机旁边,看看系统出故障当时到底是怎么回事。客户想了想,也就答应了,也许别无他法。
于是,客户安排了一名IT人员带着报纸,拿着相机,当晚整夜地坐在计算机旁边,等候问题发生。如果有任何问题,这名值班人员就会用相机把屏幕照下来。
奇怪的事情发生了!夜夜重启的系统,当晚安然度过!
工程师、客户都在问这名值班人员做了什么,他却丈二和尚摸不着头脑地说:“我就是看了看报纸,什么也没做啊!”
也许系统自动好了?实在想不通,大家就让这名值班人员回去休息了。
万万没想到的是,第二天晚上,系统再次出了问题,症状与从前一模一样!
于是,只要客户安排人员在计算机旁边守候,夜夜平安;只要一夜无人,必有故障。
其实,一切神鬼现象背后都有一个未被揭穿的谜底。
后来聪明的工程师仔细排查,分析到底那个值班人员有意、或无意做了什么,保护了系统。
终于发现,原来问题的根本原因是“空调”!!!
这个客户的机房原来平常是不开空调的。但是每当值班人员守夜的时候,因为机房太热,他就会打开空调看报纸,一直到第二天清晨。
如果没有开空调,机器的 CPU 过热就会出问题,这个问题自从入夏就反复发生。打开空调,系统就会安然无恙。
建议
西天取经要经历九九八十一难,在通往优秀工程师的道路,经历被神鬼现象折磨并成功揭穿谜底的磨难,是必修之路。
遇到神鬼现象,我们要做的第一件事是保持耐心。
然后采集数据、分析数据、寻找规律、提出假设、反复验真和验伪,真相就不会遥远。
现代的应用开发,依赖的环节越来越多。芯片、传感器、网络、rom、DCloud的引擎、小程序平台、各种插件、以及你的代码.....到处都可能是故障点。
需要对多套环境做对比实验,才能命中准确的故障点。
回到DCloud社区的问题反馈上,DCloud并非微软或通用那样的商业公司,无法派出客服人员去现场查看问题。此时,尤为依赖开发者提供精准的问题反馈。
即便是线上沟通,DCloud的技术人员每天也被大量无效反馈淹没,导致真正的bug得不到发现。
我们期待开发者,在社区报bug时:
- 做过仔细的验证,确定是DCloud引擎问题。实际上大部分报Bug的情况,如果开发者自己仔细做了验证,就不会在DCloud社区报bug了。避免DCloud技术人员投入无效精力去分析这些并非DCloud产品原因的问题
- 详细描述问题、提供重现方式
希望广大开发者和DCloud配合,每天让DCloud发现有效bug的数量提升更多,假以时日,让DCloud的产品问题越来越少。
共勉!
收起阅读 »标梵微信插件开发教程5:建立全局css风格
设置全局css样式。目的在于统一所有page页面page,text,view,navigator,swiper,swiper-item,image等组件的padding、margin和border-size样式。标梵微信插件开发教程5:建立全局css风格
1 设置全局边距
我们需要在app.wxss中设置page,text,view,navigator,swiper,swiper-item,image等组件的全局padding为0px,margin为0px,border-sizing为border-box 。
page,text,view,navigator,swiper,swiper-item,image{
/设置组件全局边距/
margin: 0px;
padding: 0px;
/*
- 指定元素的宽或高包含padding和border,不包含mmargin。
- 如果不设置默认为content-box,元素的宽或高不包含padding和border
/
box-sizing: border-box;
}
因为border-sizing全局样式设置为border-box,所以全局pages默认情况下:
(1)组件总宽度 = 边框border + 内边距pardding + 内容宽度
(2)组件总高度 = 边框border + 内边距pardding + 内容高度
下图为网上找的截图,可以看到border-sizing属性两个值(content-box和border-box)的区别!
2 设置text标签全局字体大小
为了统一整个app小程序页面的字体大小,我们需要在app.wxss中设置page和text标签内容的全局字体大小为:30rpx。如下:
/全局page和text内容字体大小/
page,text{
font-size: 30rpx;
}
3 app.wxss全局样式全部代码
/app.wxss/
page,text,view,navigator,swiper,swiper-item,image{
/设置组件全局边距/
margin: 0px;
padding: 0px;
/ - 指定元素的宽或高包含padding和border,不包含mmargin。
- 如果不设置默认为content-box,元素的宽或高不包含padding和border
/
box-sizing: border-box;
}
/全局page和text内容字体大小*/
page,text{
font-size: 30rpx;
}
本文来源:标梵互动(https://www.biaofun.com/)
设置全局css样式。目的在于统一所有page页面page,text,view,navigator,swiper,swiper-item,image等组件的padding、margin和border-size样式。标梵微信插件开发教程5:建立全局css风格
1 设置全局边距
我们需要在app.wxss中设置page,text,view,navigator,swiper,swiper-item,image等组件的全局padding为0px,margin为0px,border-sizing为border-box 。
page,text,view,navigator,swiper,swiper-item,image{
/设置组件全局边距/
margin: 0px;
padding: 0px;
/*
- 指定元素的宽或高包含padding和border,不包含mmargin。
- 如果不设置默认为content-box,元素的宽或高不包含padding和border
/
box-sizing: border-box;
}
因为border-sizing全局样式设置为border-box,所以全局pages默认情况下:
(1)组件总宽度 = 边框border + 内边距pardding + 内容宽度
(2)组件总高度 = 边框border + 内边距pardding + 内容高度
下图为网上找的截图,可以看到border-sizing属性两个值(content-box和border-box)的区别!
2 设置text标签全局字体大小
为了统一整个app小程序页面的字体大小,我们需要在app.wxss中设置page和text标签内容的全局字体大小为:30rpx。如下:
/全局page和text内容字体大小/
page,text{
font-size: 30rpx;
}
3 app.wxss全局样式全部代码
/app.wxss/
page,text,view,navigator,swiper,swiper-item,image{
/设置组件全局边距/
margin: 0px;
padding: 0px;
/ - 指定元素的宽或高包含padding和border,不包含mmargin。
- 如果不设置默认为content-box,元素的宽或高不包含padding和border
/
box-sizing: border-box;
}
/全局page和text内容字体大小*/
page,text{
font-size: 30rpx;
}
本文来源:标梵互动(https://www.biaofun.com/)
大白话web开发和uniapp开发有什么区别?什么是打包?什么时候需要重新打包自定义基座?
网页依赖于浏览器,本身仅能提供多媒体的展示,没有“直接”与硬件交互的能力。
比如微信有摇一摇功能因为安卓/苹果语言可以和手机的陀螺仪通讯,附近的人的功能是与手机GPS硬件的通讯等等。
想必这时候你要说微信公众号是网页语言开发,但是也能具备以上功能吧。答案是:微信公众号之所以可以实现摇一摇地理位置的监测属于“间接”而非直接,是由js将命令发给微信(此时微信就是该网页的浏览器),由浏览器完成后将数据调回给网页。典型的例子还有dcloud的h5+plus详情:http://www.html5plus.org/doc/h5p.html
和超级强大的uni-app,详情:https://uniapp.dcloud.io/
什么是打包?什么时候需要重新打包
一款app有自己的包名,签名,证书,应用图标等这一系列内容设定的过程就是app打包的过程。
典型的:微信支付功能开发,需要设置app的包名和签名等,所以参数一旦不正确就需要重新打包。
同理什么时候需要【重新编译】或者【重启】后生效,比如写了原生子窗体subnvue或者原生导航等原生相关内容。
网页依赖于浏览器,本身仅能提供多媒体的展示,没有“直接”与硬件交互的能力。
比如微信有摇一摇功能因为安卓/苹果语言可以和手机的陀螺仪通讯,附近的人的功能是与手机GPS硬件的通讯等等。
想必这时候你要说微信公众号是网页语言开发,但是也能具备以上功能吧。答案是:微信公众号之所以可以实现摇一摇地理位置的监测属于“间接”而非直接,是由js将命令发给微信(此时微信就是该网页的浏览器),由浏览器完成后将数据调回给网页。典型的例子还有dcloud的h5+plus详情:http://www.html5plus.org/doc/h5p.html
和超级强大的uni-app,详情:https://uniapp.dcloud.io/
什么是打包?什么时候需要重新打包
一款app有自己的包名,签名,证书,应用图标等这一系列内容设定的过程就是app打包的过程。
典型的:微信支付功能开发,需要设置app的包名和签名等,所以参数一旦不正确就需要重新打包。
同理什么时候需要【重新编译】或者【重启】后生效,比如写了原生子窗体subnvue或者原生导航等原生相关内容。
收起阅读 »uniapp 使用vant weapp 做app时 又发现一个bug
uniapp 导入vant weapp 后 调用 van-dropdown-menu
菜单头能显示,点击时报:
TypeError: Object [object HTMLUnknownElement] has no method 'matches' at view.umd.min.js:1
uniapp 导入vant weapp 后 调用 van-dropdown-menu
菜单头能显示,点击时报:
TypeError: Object [object HTMLUnknownElement] has no method 'matches' at view.umd.min.js:1
uni.chooseImage 相机相册选择图片弹框国际化
自己封装的一个实现选择图片弹框国际化的方法,返回的格式与 uni.chooseImage 相同,因此可以把 uni.chooseImage 替换掉,在main.js挂到了Vue原型上:
/** 封装国际化选择图片
* @param {Object} self 组件中的 this
* @param {Object} params 配置参数
*/
Vue.prototype.selectImage = (self, params = {}) => {
let count = params.count || 9; // 数量
let sizeType = params.sizeType || ['original', 'compressed']; // 原图和压缩图
let sourceType = params.sourceType || ['camera', 'album']; // 相册和相机
let success = params.success || function success(){}; // 成功回调
let fail = params.fail || function fail(){}; // 失败回调
let option = {
cancel: self.$t('prompt.btn2'), // i18n取消文字
buttons: [{
title: self.$t('prompt.imgBtn1') // i18n相机文字
},
{
title: self.$t('prompt.imgBtn2') // i18n相册文字
}
]
};
if(!sourceType.includes('camera')) delete option.buttons[0];
if(!sourceType.includes('album')) delete option.buttons[1];
plus.nativeUI.actionSheet(option,
async (tap) => {
if(sourceType.length === 2) {
if( tap.index === 1) {
// 拍照
const cmr = plus.camera.getCamera();
cmr.captureImage((path) => {
plus.io.getFileInfo({
filePath: path,
success: res => {
let result = {
errMsg: "chooseImage:ok",
tempFilePaths: [path],
tempFiles: [{
path: path,
size: res.size
}]
};
success(result);
},
fail: err => fail(err)
});
}, (err) => {fail(err)});
} else if (tap.index === 2) {
// 从相册选择
plus.gallery.pick(
(res) => {
let filesList = res.files;
let tempFiles = [];
for (let path of filesList) {
plus.io.getFileInfo({
filePath: path,
success: r => {
tempFiles.push({
path: path,
size: r.size
});
if(tempFiles.length === filesList.length) {
success({
errMsg: "chooseImage:ok",
tempFilePaths: filesList,
tempFiles
})
}
},
fail: err => fail(err)
});
}
}, (err) => {fail(err)},{
filter: "image",
multiple: true,
maximum: count,
system: false,
});
}
} else if (sourceType.length === 1) {
if(sourceType.includes('camera')) {
// 拍照
const cmr = plus.camera.getCamera();
cmr.captureImage((path) => {
plus.io.getFileInfo({
filePath: path,
success: res => {
let result = {
errMsg: "chooseImage:ok",
tempFilePaths: [path],
tempFiles: [{
path: path,
size: res.size
}]
};
success(result);
},
fail: err => fail(err)
});
}, (err) => {fail(err)});
} else {
// 从相册选择
plus.gallery.pick(
(res) => {
let filesList = res.files;
let tempFiles = [];
for (let path of filesList) {
plus.io.getFileInfo({
filePath: path,
success: r => {
tempFiles.push({
path: path,
size: r.size
});
if(tempFiles.length === filesList.length) {
success({
errMsg: "chooseImage:ok",
tempFilePaths: filesList,
tempFiles
})
}
},
fail: err => fail(err)
});
}
}, (err) => {fail(err)},{
filter: "image",
multiple: true,
maximum: count,
system: false,
});
}
}
});
} 自己封装的一个实现选择图片弹框国际化的方法,返回的格式与 uni.chooseImage 相同,因此可以把 uni.chooseImage 替换掉,在main.js挂到了Vue原型上:
/** 封装国际化选择图片
* @param {Object} self 组件中的 this
* @param {Object} params 配置参数
*/
Vue.prototype.selectImage = (self, params = {}) => {
let count = params.count || 9; // 数量
let sizeType = params.sizeType || ['original', 'compressed']; // 原图和压缩图
let sourceType = params.sourceType || ['camera', 'album']; // 相册和相机
let success = params.success || function success(){}; // 成功回调
let fail = params.fail || function fail(){}; // 失败回调
let option = {
cancel: self.$t('prompt.btn2'), // i18n取消文字
buttons: [{
title: self.$t('prompt.imgBtn1') // i18n相机文字
},
{
title: self.$t('prompt.imgBtn2') // i18n相册文字
}
]
};
if(!sourceType.includes('camera')) delete option.buttons[0];
if(!sourceType.includes('album')) delete option.buttons[1];
plus.nativeUI.actionSheet(option,
async (tap) => {
if(sourceType.length === 2) {
if( tap.index === 1) {
// 拍照
const cmr = plus.camera.getCamera();
cmr.captureImage((path) => {
plus.io.getFileInfo({
filePath: path,
success: res => {
let result = {
errMsg: "chooseImage:ok",
tempFilePaths: [path],
tempFiles: [{
path: path,
size: res.size
}]
};
success(result);
},
fail: err => fail(err)
});
}, (err) => {fail(err)});
} else if (tap.index === 2) {
// 从相册选择
plus.gallery.pick(
(res) => {
let filesList = res.files;
let tempFiles = [];
for (let path of filesList) {
plus.io.getFileInfo({
filePath: path,
success: r => {
tempFiles.push({
path: path,
size: r.size
});
if(tempFiles.length === filesList.length) {
success({
errMsg: "chooseImage:ok",
tempFilePaths: filesList,
tempFiles
})
}
},
fail: err => fail(err)
});
}
}, (err) => {fail(err)},{
filter: "image",
multiple: true,
maximum: count,
system: false,
});
}
} else if (sourceType.length === 1) {
if(sourceType.includes('camera')) {
// 拍照
const cmr = plus.camera.getCamera();
cmr.captureImage((path) => {
plus.io.getFileInfo({
filePath: path,
success: res => {
let result = {
errMsg: "chooseImage:ok",
tempFilePaths: [path],
tempFiles: [{
path: path,
size: res.size
}]
};
success(result);
},
fail: err => fail(err)
});
}, (err) => {fail(err)});
} else {
// 从相册选择
plus.gallery.pick(
(res) => {
let filesList = res.files;
let tempFiles = [];
for (let path of filesList) {
plus.io.getFileInfo({
filePath: path,
success: r => {
tempFiles.push({
path: path,
size: r.size
});
if(tempFiles.length === filesList.length) {
success({
errMsg: "chooseImage:ok",
tempFilePaths: filesList,
tempFiles
})
}
},
fail: err => fail(err)
});
}
}, (err) => {fail(err)},{
filter: "image",
multiple: true,
maximum: count,
system: false,
});
}
}
});
} 收起阅读 »





