HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

uni-file-picker自定义上传时,展示进度条

实现思路:根据源码得知,进度条状态通过文件 uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue 中的setProgress设置。修改思路也是基于此方法。

  1. 自定义上传时,自定义一个回调方法,拿到progress,接下来会用到。
    /**  
    * @description 文件上传  
    * @param filePath 文件路径  
    * @param uuid 文件uuid  
    * @param progressCallBack 上传进度回调  
    */  
    export function uploadFile(filePath, uuid, progressCallBack) {  
    return new Promise(resolve => {  
        const uploadTask = uni.uploadFile({  
            header: {  
                'token': uni.getStorageSync('token'),  
                'enterpriseId': 'test'  
            },  
            url: `${baseUrl}/file-serv/file/upload`, // 上传图片的接口  
            filePath,  
            formData: {  
                name: 'file'  
            },  
            success: async (uploadFileRes) => {  
                // 获取图片list  
                const {  
                    data  
                } = uploadFileRes  
                const {  
                    code,  
                    data: d  
                } = JSON.parse(data)  
                if (code == 200) {  
                    resolve({  
                        url: d.url,  
                        uuid  
                    })  
                }  
            }  
        })  
        // 通过uploadTask 监听上传进度   
        uploadTask.onProgressUpdate(res => {  
            progressCallBack(res)  
        })  
    })  
    }

    上传文件时调用:

    async onSelect(e) { // 组件回调方法,在这里做文件上传动作  
    const _this = this  
    const uuid = e.tempFiles[0]['uuid']  
    const res = await uploadFile(e.tempFilePaths[0], uuid, function(progress) {  
        console.log('progress:', progress)  
        _this.$refs.uploadFile.setProgressByCustomUplaod(uuid, progress.progress) // 通过组件实例调用设置进度条的方法  
    })  
    },
  2. 在组件中设置ref,目的是得到组件实例。通过实例即可调用组件方法setProgress。为了与源代码区分,定义新的方法setProgressByCustomUplaod
    <uni-file-picker ref="uploadFile" fileMediatype="image" @select="onSelect" @delete="onDelete" :limit="5" />

    调用:_this.$refs.uploadFile.setProgressByCustomUplaod(uuid, progress.progress)

  3. uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue文件中新增方法setProgressByCustomUplaod
    /**  
    * @description 自定义上传时,设置进度条状态  
    * @param uuid 文件uuid,目的是通过uuid从文件列表中取出当前正在上传的文件  
    * @param progress 上传进度  
    */  
    setProgressByCustomUplaod(uuid, progress) {  
    const currentFile = this.files.find(item => item.uuid == uuid)  
    if (currentFile) {  
        currentFile.progress = progress  
    }  
    }
继续阅读 »

实现思路:根据源码得知,进度条状态通过文件 uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue 中的setProgress设置。修改思路也是基于此方法。

  1. 自定义上传时,自定义一个回调方法,拿到progress,接下来会用到。
    /**  
    * @description 文件上传  
    * @param filePath 文件路径  
    * @param uuid 文件uuid  
    * @param progressCallBack 上传进度回调  
    */  
    export function uploadFile(filePath, uuid, progressCallBack) {  
    return new Promise(resolve => {  
        const uploadTask = uni.uploadFile({  
            header: {  
                'token': uni.getStorageSync('token'),  
                'enterpriseId': 'test'  
            },  
            url: `${baseUrl}/file-serv/file/upload`, // 上传图片的接口  
            filePath,  
            formData: {  
                name: 'file'  
            },  
            success: async (uploadFileRes) => {  
                // 获取图片list  
                const {  
                    data  
                } = uploadFileRes  
                const {  
                    code,  
                    data: d  
                } = JSON.parse(data)  
                if (code == 200) {  
                    resolve({  
                        url: d.url,  
                        uuid  
                    })  
                }  
            }  
        })  
        // 通过uploadTask 监听上传进度   
        uploadTask.onProgressUpdate(res => {  
            progressCallBack(res)  
        })  
    })  
    }

    上传文件时调用:

    async onSelect(e) { // 组件回调方法,在这里做文件上传动作  
    const _this = this  
    const uuid = e.tempFiles[0]['uuid']  
    const res = await uploadFile(e.tempFilePaths[0], uuid, function(progress) {  
        console.log('progress:', progress)  
        _this.$refs.uploadFile.setProgressByCustomUplaod(uuid, progress.progress) // 通过组件实例调用设置进度条的方法  
    })  
    },
  2. 在组件中设置ref,目的是得到组件实例。通过实例即可调用组件方法setProgress。为了与源代码区分,定义新的方法setProgressByCustomUplaod
    <uni-file-picker ref="uploadFile" fileMediatype="image" @select="onSelect" @delete="onDelete" :limit="5" />

    调用:_this.$refs.uploadFile.setProgressByCustomUplaod(uuid, progress.progress)

  3. uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue文件中新增方法setProgressByCustomUplaod
    /**  
    * @description 自定义上传时,设置进度条状态  
    * @param uuid 文件uuid,目的是通过uuid从文件列表中取出当前正在上传的文件  
    * @param progress 上传进度  
    */  
    setProgressByCustomUplaod(uuid, progress) {  
    const currentFile = this.files.find(item => item.uuid == uuid)  
    if (currentFile) {  
        currentFile.progress = progress  
    }  
    }
收起阅读 »

使用uni.downloadFile在微信小程序内下载文件发现一个很神奇的现象

downloadFile

小程序内使用wx.downloadFile是限制最大文件200M的


我在fail回调内做了判断用来提示用户

在实际使用中我发现,哪怕文件超过200M,uni.downloadFile这个API也并不会进入fail回调中,而是会直接开始下载,在将超时时间设置的足够久以后,多大的文件都能下载成功并保存至相册。

所以不清楚是uni.downloadFile这个API没有文件200M以内的限制呢,还是微信那边取消了200M以内的限制

继续阅读 »

小程序内使用wx.downloadFile是限制最大文件200M的


我在fail回调内做了判断用来提示用户

在实际使用中我发现,哪怕文件超过200M,uni.downloadFile这个API也并不会进入fail回调中,而是会直接开始下载,在将超时时间设置的足够久以后,多大的文件都能下载成功并保存至相册。

所以不清楚是uni.downloadFile这个API没有文件200M以内的限制呢,还是微信那边取消了200M以内的限制

收起阅读 »

多客交友社交系统/H5多端圈子社区论坛系统交友/博客/社交/陌生人社交即时聊天私域话题社区论

DUOKE多客圈子论坛社区系统,含完整的后台PHP系统。功能:小程序授权登陆,H5和APP,手机号登陆,发帖,建圈子、发活动。圈主可置顶推荐帖子,关注、粉丝、点赞等。可作为圈子贴吧、小红书等自媒体。

多客圈子论坛社区(交友、博客、社交、陌生人社交、即时聊天)前后端开源PHP - 更新日志
1.9(2023-05-16)
1.修复头像上传问题。 2.修复上传图片问题

1.8(2023-03-30)
修改小程序获取头像和昵称接口。可直接单独读取头像和昵称。

1.7(2023-01-13)
增加后台添加帖子 增加后台帖子处理 完善七牛审核

1.3(2022-12-08)
1、取消七牛审核功能,因大家都说不方便。 最新版后端请去gie仓库拿后台。 2、增加微信登录后无法获得头像和昵称,改为新用户强制填写资料。 开源版不易,如果你不喜欢出门左转,请勿恶意差评、诋毁。

1.2.91(2022-11-21)
小程序收回获取头像昵称功能,后端也做相应调整,重新登录时不在获取新昵称。

1.2.9(2022-11-09)
1、优化发帖模式

2、增加圈子展示高度

3、关联关注及点赞数量

1.2.8(2022-10-28)
更新头像上传返回空白 增加部分新功能

1.2.7(2022-10-18)
修复后台上传图片编辑器路径不对。

1.2.6(2022-10-13)
修复安卓打包不能看帖子问题 修复发布活动选择地址问题 请在app设置里配置你的高德地图。

1.2.5(2022-10-08)
修复头像上传问题,增加头像剪裁 增加评论回复按钮 修复UI错位

1.2.4(2022-10-03)
1、修复禁言后发帖功能 2、修复linxun系统首页问题。 3、增加常见问答

1.2.3(2022-09-28)
1、更新APP打包后地图打不开问题 2、更新APP版本发帖按钮问题 3、更新APP打开活动地图无法显示问题。

1.2.2(2022-09-27)
1、修复打包APP不能进入登录页问题 2、修复首页切换热门不能读取帖子问题 3、修复一直UI问题。

1.2.1(2022-09-26)
1、增加勋章功能和领取 2、增加等级,根据经验值获得,经验值在后台填写 3、增加圈主可置顶 删除本圈下面的任意帖子。 4、其他BUG

                                                                            **  多客圈子社区系统免费开源版4.2版**  

● 多客开源团队(www.51duoke.cn)2022年伤肝之作!系统基于TP6 Uni-app框架开发;客户移动端采用uni-app开发,管理后台TH6开发。
● 系统支持微信公众号端、微信小程序端、H5端、PC端多端账号同步,可快速打包生成APP。
● 我们为你准备了完善的后台管理,不需要你懂PHP,按照教程10分钟安装完即可使用,堪比深夜的杜蕾斯还方便。
● 我们为你准备漂亮的UI前端,导入UNI,2分钟编译为小程序,3分钟编译为安卓app,5分钟编译为ios系统。
● 如果,我是说如果,你啥都不会,服务器不会架设,数据库也不会操作,打包也不会,联系我们即可。我们提供一整套安装调试上架服务。
● 当然我们也有商业pro版,已增加各种酷炫功能。
● 当然我们也会接二次定制开发的版本,满足各种需求,展开您的想象,您就可以拥有。

免费开源基础版后端演示
http://quan.51duoke.cn/admin 账号demo 密码demo (仅有查看权限)

后端下载地址:https://gitee.com/multi-customer-open-source/multi-social

后端程序目录
系统需求

PHP >= 7.2.5
MySQL >= 5.6.3
Redis
uniapp安装
将前端UNI目录导入到你的HBuilder里

修改tools/siteinfo.js 里的域名为你的域名即可

如果打包小程序及app 请参考uniapp官方文档

后端安装
将后端php代码放到你的网站根目录即可

====运行WEB目录==== public

====数据库==== 导入目录下的 db.sql 文件 修改目录下的 .env 数据库配置

配置文件路径/.env

APP_DEBUG = true

[APP]
DEFAULT_TIMEZONE = Asia/Shanghai

[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1 #数据库连接地址
DATABASE = test #数据库名称
USERNAME = username #数据库登录账号
PASSWORD = password #数据库登录密码
HOSTPORT = 3306 #数据库端口
CHARSET = utf8
DEBUG = true

[LANG]
default_lang = zh-cn

[REDIS]
REDIS_HOSTNAME = 127.0.0.1 # redis链接地址
PORT = 6379 #端口号
REDIS_PASSWORD = 123456 #密码
SELECT = 0 #数据库
3.修改目录权限(linux系统)777 /public

====后台登陆==== http://域名/admin 默认账号:admin 密码:6192652

功能简介
1、采用uniapp开发前端,可打包成小程序、APP安卓、app苹果、支付宝小程序等。具体请到uniapp官网查看

2、APP采用短信验证登录,小程序采用微信授权登录。

3、圈子支持后台建立和前台用户新建

4、用户发布帖子可选择圈子和话题,

5、帖子可后台添加和审核,及推荐和热门等操作

6、上传集成阿里云oss和七牛云,也可以本地储存

7、发布内容自动安全检测,采用七牛内容检测接口。

8、支持图片多图上传和拖动排序

9、支持会员等级

10、帖子支持圈子管理员前端推荐和置顶

11、支持勋章和用户等级

Admin(后台功能)
├─ 管理首页
| ├─介绍版本信息、数据统计、常用模块、Echart数据概览
├─ 菜单管理
| ├─后台权限菜单管理 编辑访客权限,处理菜单父子关系,被权限系统依赖(极为重要)
├─ 系统管理
| ├─ 用户管理 - 添加新用户,封号,删号以及给账号分配权限组
| ├─ 权限管理 - 权限组管理,给权限组添加权限,将用户提出权限组
| └─ 上传管理 - 记录所有上传的图片文件信息、定位文件位置大小以及上传时间
├─ 配置管理
| ├─ 基本设置 - 配置网站基本信息:标题、域名、客服电话、前端主题配色、前端字体颜色等前端基础配置信息修改
| ├─ 上传配置 - 文件存储方式选择:本地存储、阿里云OSS、七牛云配置
| └─ 操作日志 - 记录管理员的操作,用于追责,回溯和备案
├─ 站点设置
| ├─ 广告管理 - 删改查
| ├─ 首页管理 - ....
| └─ 单页管理 - ....
├─ 圈子管理
| ├─ 圈子列表 - ....
| └─ 话题管理 - ....
├─ 会员管理
| ├─ 会员列表 - ....
| └─ 勋章管理 - ....
├─ ......

前端页面展示
首页和广场

文档
TP6开发手册

uniapp开发手册

安装使用常见问答
1、关于敏感词过滤问题? 答:请到七牛云注册账号,在我的里会有AccessKey和AccessKeySecret,填写到我们后台的 上传配置七牛云那里,点击保存。 如果是想使用七牛云的图片储存请继续填写后面的空间名和域名等信息,如果不想使用七牛云储存,只需要填写key和secret。然后在选择储存方式为本地。 意思是七牛云这个必填。否则无法过滤。

如果不想过滤请到app/controller/user.php 这个接口文件里搜索 checkCloseSpeck 并把这一行注释掉。

2、关于APP版 发布活动选择地址和查看地址失效问题? 答:请在Hbiuder里 打开manifest.json, 点击APP模块配置,选中maps,选择你要使用那个地图,一般推荐高德和腾讯。请到高德或腾讯开放平台 注册账号,并添加应用。获取到key填写到这里。 因为APP采用的是sdk地图。小程序不需要考虑,是直接用微信的地图。

3、关于短信登录问题? 答:后台关闭短信验证,是为了测试使用的,或者是短信通道临时故障之类使用。就是用户不需要接收短信,直接可以登录。当正式版本发布后,建议你开启短信验证,并去阿里云购买短信,填写在后台即可使用。

4、我们的演示APP或者小程序为啥不能发帖子? 答:演示已经关闭发布功能,因为测试的人太多,天天乱发,影响测试的美观。 请自己搭建后 自己发布到你的数据库去。

5、linux系统需要配置伪静态代码 location / { if (!-e request_filename){ rewrite ^(.*) /index.php?s=$1 last; break; } }

6、windows系统设置伪静态。

请在宝塔里设置伪静态选择TH6 。

7、出现api接口读取500错误,

答:原因很多,大部分是 没有设置伪静态,请看第5条。或者是数据库没连接上。

8、安装后台后访问出现404找不到页面

答:大部分使用为宝塔的网站管理开启了防跨站,请关闭。

不断更新中....

特别鸣谢
排名不分先后,感谢这些软件的开发者:thinkphp、小牛admin、图鸟UI、vue、mysql、redis、uniapp等!

开源版使用须知
1.允许用于个人学习、毕业设计、教学案例、公益事业、商业使用;

2.如果商用必须保留版权信息,请自觉遵守;

3.禁止将本项目的代码和资源进行任何形式的出售,产生的一切任何后果责任由侵权者自负。

版权信息
版权所有Copyright © 2016-2022 by 四川掌上时代科技有限公司旗下多客开源事业部 (http://www.51duoke.cn http://www.siyibang.com)

All rights reserved。

著作权所有者为四川掌上时代科技有限公司。

继续阅读 »

DUOKE多客圈子论坛社区系统,含完整的后台PHP系统。功能:小程序授权登陆,H5和APP,手机号登陆,发帖,建圈子、发活动。圈主可置顶推荐帖子,关注、粉丝、点赞等。可作为圈子贴吧、小红书等自媒体。

多客圈子论坛社区(交友、博客、社交、陌生人社交、即时聊天)前后端开源PHP - 更新日志
1.9(2023-05-16)
1.修复头像上传问题。 2.修复上传图片问题

1.8(2023-03-30)
修改小程序获取头像和昵称接口。可直接单独读取头像和昵称。

1.7(2023-01-13)
增加后台添加帖子 增加后台帖子处理 完善七牛审核

1.3(2022-12-08)
1、取消七牛审核功能,因大家都说不方便。 最新版后端请去gie仓库拿后台。 2、增加微信登录后无法获得头像和昵称,改为新用户强制填写资料。 开源版不易,如果你不喜欢出门左转,请勿恶意差评、诋毁。

1.2.91(2022-11-21)
小程序收回获取头像昵称功能,后端也做相应调整,重新登录时不在获取新昵称。

1.2.9(2022-11-09)
1、优化发帖模式

2、增加圈子展示高度

3、关联关注及点赞数量

1.2.8(2022-10-28)
更新头像上传返回空白 增加部分新功能

1.2.7(2022-10-18)
修复后台上传图片编辑器路径不对。

1.2.6(2022-10-13)
修复安卓打包不能看帖子问题 修复发布活动选择地址问题 请在app设置里配置你的高德地图。

1.2.5(2022-10-08)
修复头像上传问题,增加头像剪裁 增加评论回复按钮 修复UI错位

1.2.4(2022-10-03)
1、修复禁言后发帖功能 2、修复linxun系统首页问题。 3、增加常见问答

1.2.3(2022-09-28)
1、更新APP打包后地图打不开问题 2、更新APP版本发帖按钮问题 3、更新APP打开活动地图无法显示问题。

1.2.2(2022-09-27)
1、修复打包APP不能进入登录页问题 2、修复首页切换热门不能读取帖子问题 3、修复一直UI问题。

1.2.1(2022-09-26)
1、增加勋章功能和领取 2、增加等级,根据经验值获得,经验值在后台填写 3、增加圈主可置顶 删除本圈下面的任意帖子。 4、其他BUG

                                                                            **  多客圈子社区系统免费开源版4.2版**  

● 多客开源团队(www.51duoke.cn)2022年伤肝之作!系统基于TP6 Uni-app框架开发;客户移动端采用uni-app开发,管理后台TH6开发。
● 系统支持微信公众号端、微信小程序端、H5端、PC端多端账号同步,可快速打包生成APP。
● 我们为你准备了完善的后台管理,不需要你懂PHP,按照教程10分钟安装完即可使用,堪比深夜的杜蕾斯还方便。
● 我们为你准备漂亮的UI前端,导入UNI,2分钟编译为小程序,3分钟编译为安卓app,5分钟编译为ios系统。
● 如果,我是说如果,你啥都不会,服务器不会架设,数据库也不会操作,打包也不会,联系我们即可。我们提供一整套安装调试上架服务。
● 当然我们也有商业pro版,已增加各种酷炫功能。
● 当然我们也会接二次定制开发的版本,满足各种需求,展开您的想象,您就可以拥有。

免费开源基础版后端演示
http://quan.51duoke.cn/admin 账号demo 密码demo (仅有查看权限)

后端下载地址:https://gitee.com/multi-customer-open-source/multi-social

后端程序目录
系统需求

PHP >= 7.2.5
MySQL >= 5.6.3
Redis
uniapp安装
将前端UNI目录导入到你的HBuilder里

修改tools/siteinfo.js 里的域名为你的域名即可

如果打包小程序及app 请参考uniapp官方文档

后端安装
将后端php代码放到你的网站根目录即可

====运行WEB目录==== public

====数据库==== 导入目录下的 db.sql 文件 修改目录下的 .env 数据库配置

配置文件路径/.env

APP_DEBUG = true

[APP]
DEFAULT_TIMEZONE = Asia/Shanghai

[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1 #数据库连接地址
DATABASE = test #数据库名称
USERNAME = username #数据库登录账号
PASSWORD = password #数据库登录密码
HOSTPORT = 3306 #数据库端口
CHARSET = utf8
DEBUG = true

[LANG]
default_lang = zh-cn

[REDIS]
REDIS_HOSTNAME = 127.0.0.1 # redis链接地址
PORT = 6379 #端口号
REDIS_PASSWORD = 123456 #密码
SELECT = 0 #数据库
3.修改目录权限(linux系统)777 /public

====后台登陆==== http://域名/admin 默认账号:admin 密码:6192652

功能简介
1、采用uniapp开发前端,可打包成小程序、APP安卓、app苹果、支付宝小程序等。具体请到uniapp官网查看

2、APP采用短信验证登录,小程序采用微信授权登录。

3、圈子支持后台建立和前台用户新建

4、用户发布帖子可选择圈子和话题,

5、帖子可后台添加和审核,及推荐和热门等操作

6、上传集成阿里云oss和七牛云,也可以本地储存

7、发布内容自动安全检测,采用七牛内容检测接口。

8、支持图片多图上传和拖动排序

9、支持会员等级

10、帖子支持圈子管理员前端推荐和置顶

11、支持勋章和用户等级

Admin(后台功能)
├─ 管理首页
| ├─介绍版本信息、数据统计、常用模块、Echart数据概览
├─ 菜单管理
| ├─后台权限菜单管理 编辑访客权限,处理菜单父子关系,被权限系统依赖(极为重要)
├─ 系统管理
| ├─ 用户管理 - 添加新用户,封号,删号以及给账号分配权限组
| ├─ 权限管理 - 权限组管理,给权限组添加权限,将用户提出权限组
| └─ 上传管理 - 记录所有上传的图片文件信息、定位文件位置大小以及上传时间
├─ 配置管理
| ├─ 基本设置 - 配置网站基本信息:标题、域名、客服电话、前端主题配色、前端字体颜色等前端基础配置信息修改
| ├─ 上传配置 - 文件存储方式选择:本地存储、阿里云OSS、七牛云配置
| └─ 操作日志 - 记录管理员的操作,用于追责,回溯和备案
├─ 站点设置
| ├─ 广告管理 - 删改查
| ├─ 首页管理 - ....
| └─ 单页管理 - ....
├─ 圈子管理
| ├─ 圈子列表 - ....
| └─ 话题管理 - ....
├─ 会员管理
| ├─ 会员列表 - ....
| └─ 勋章管理 - ....
├─ ......

前端页面展示
首页和广场

文档
TP6开发手册

uniapp开发手册

安装使用常见问答
1、关于敏感词过滤问题? 答:请到七牛云注册账号,在我的里会有AccessKey和AccessKeySecret,填写到我们后台的 上传配置七牛云那里,点击保存。 如果是想使用七牛云的图片储存请继续填写后面的空间名和域名等信息,如果不想使用七牛云储存,只需要填写key和secret。然后在选择储存方式为本地。 意思是七牛云这个必填。否则无法过滤。

如果不想过滤请到app/controller/user.php 这个接口文件里搜索 checkCloseSpeck 并把这一行注释掉。

2、关于APP版 发布活动选择地址和查看地址失效问题? 答:请在Hbiuder里 打开manifest.json, 点击APP模块配置,选中maps,选择你要使用那个地图,一般推荐高德和腾讯。请到高德或腾讯开放平台 注册账号,并添加应用。获取到key填写到这里。 因为APP采用的是sdk地图。小程序不需要考虑,是直接用微信的地图。

3、关于短信登录问题? 答:后台关闭短信验证,是为了测试使用的,或者是短信通道临时故障之类使用。就是用户不需要接收短信,直接可以登录。当正式版本发布后,建议你开启短信验证,并去阿里云购买短信,填写在后台即可使用。

4、我们的演示APP或者小程序为啥不能发帖子? 答:演示已经关闭发布功能,因为测试的人太多,天天乱发,影响测试的美观。 请自己搭建后 自己发布到你的数据库去。

5、linux系统需要配置伪静态代码 location / { if (!-e request_filename){ rewrite ^(.*) /index.php?s=$1 last; break; } }

6、windows系统设置伪静态。

请在宝塔里设置伪静态选择TH6 。

7、出现api接口读取500错误,

答:原因很多,大部分是 没有设置伪静态,请看第5条。或者是数据库没连接上。

8、安装后台后访问出现404找不到页面

答:大部分使用为宝塔的网站管理开启了防跨站,请关闭。

不断更新中....

特别鸣谢
排名不分先后,感谢这些软件的开发者:thinkphp、小牛admin、图鸟UI、vue、mysql、redis、uniapp等!

开源版使用须知
1.允许用于个人学习、毕业设计、教学案例、公益事业、商业使用;

2.如果商用必须保留版权信息,请自觉遵守;

3.禁止将本项目的代码和资源进行任何形式的出售,产生的一切任何后果责任由侵权者自负。

版权信息
版权所有Copyright © 2016-2022 by 四川掌上时代科技有限公司旗下多客开源事业部 (http://www.51duoke.cn http://www.siyibang.com)

All rights reserved。

著作权所有者为四川掌上时代科技有限公司。

收起阅读 »

renderjs 使用记录


<template>  
    <view>  
        <view @tap="MyRenderjsModule.eventChange" style="width: 300rpx;height: 120rpx;background-color: rgb(0, 255, 0);display: flex;justify-content: center;align-content: center;align-items: center;">Click Me, Please</view>  

        <view :prop="mainTag" :change:prop="MyRenderjsModule.mainTagUpdate"></view>  
    </view>  
</template>  

<script module="MyRenderjsModule" lang="renderjs">  
    export default {  
        data() {  
            return {  
                renderTag: ''  
            }  
        },  
        mounted() {  

        },  
        methods: {  
            mainTagUpdate(newVal, oldVal, ownerInstance, instance) {  
                console.log(`renderTag will update form ${oldVal} to ${newVal} by prop mainTag`)  
                this.renderTag = newVal  

                let mainTag = ''  
                // #ifdef APP-PLUS  
                mainTag = plus.storage.getItem('mainTag')  
                // #endif  
                // #ifndef APP-PLUS  
                mainTag = uni.getStorageSync('mainTag')  
                // #endif  

                console.log(`mainTagUpdate call cache mainTag = ${mainTag}`)  
            },  
            eventChange(event, ownerInstance) {  
                console.log(`Event "eventChange" triggered`)  

                ownerInstance?.callMethod('mainCallBack', {param: 'abc'})  
            },  
        },  
    }  
</script>  

<script>  
    export default {  
        data() {  
            return {  
                mainTag: ''  
            }  
        },  
        onLoad(options) {  

            setInterval(()=>{  
                this.mainTag = (new Date()).toString()  

                // #ifdef APP-PLUS  
                plus.storage.setItem('mainTag', this.mainTag)  
                // #endif  
                // #ifndef APP-PLUS  
                uni.setStorageSync('mainTag', this.mainTag)  
                // #endif  

            }, 3000)  
        },  
        methods: {  
            mainCallBack(obj = {}){  
                console.log(`Event "mainCallBack" triggered by renderjs call "mainCallBack"`)  
            }  
        }  
    }  
</script>  

<style>  

</style>  
继续阅读 »

<template>  
    <view>  
        <view @tap="MyRenderjsModule.eventChange" style="width: 300rpx;height: 120rpx;background-color: rgb(0, 255, 0);display: flex;justify-content: center;align-content: center;align-items: center;">Click Me, Please</view>  

        <view :prop="mainTag" :change:prop="MyRenderjsModule.mainTagUpdate"></view>  
    </view>  
</template>  

<script module="MyRenderjsModule" lang="renderjs">  
    export default {  
        data() {  
            return {  
                renderTag: ''  
            }  
        },  
        mounted() {  

        },  
        methods: {  
            mainTagUpdate(newVal, oldVal, ownerInstance, instance) {  
                console.log(`renderTag will update form ${oldVal} to ${newVal} by prop mainTag`)  
                this.renderTag = newVal  

                let mainTag = ''  
                // #ifdef APP-PLUS  
                mainTag = plus.storage.getItem('mainTag')  
                // #endif  
                // #ifndef APP-PLUS  
                mainTag = uni.getStorageSync('mainTag')  
                // #endif  

                console.log(`mainTagUpdate call cache mainTag = ${mainTag}`)  
            },  
            eventChange(event, ownerInstance) {  
                console.log(`Event "eventChange" triggered`)  

                ownerInstance?.callMethod('mainCallBack', {param: 'abc'})  
            },  
        },  
    }  
</script>  

<script>  
    export default {  
        data() {  
            return {  
                mainTag: ''  
            }  
        },  
        onLoad(options) {  

            setInterval(()=>{  
                this.mainTag = (new Date()).toString()  

                // #ifdef APP-PLUS  
                plus.storage.setItem('mainTag', this.mainTag)  
                // #endif  
                // #ifndef APP-PLUS  
                uni.setStorageSync('mainTag', this.mainTag)  
                // #endif  

            }, 3000)  
        },  
        methods: {  
            mainCallBack(obj = {}){  
                console.log(`Event "mainCallBack" triggered by renderjs call "mainCallBack"`)  
            }  
        }  
    }  
</script>  

<style>  

</style>  
收起阅读 »

安卓APP模拟接口数据另类思路

以下仅仅是自己开发实践中的一点想法,如有错误,请指正:

uniapp开发中,对于h5应用,通常可以使用mocker-api和mockjs来拦截网络请求,但是APP一般都说不支持,我们开发中主要以app为主,有时候需要mock数据做演示包,思考了很久,突然发现uniapp中有一个拦截器,感觉可以用其来实现数据的mock,思路如下:

/**  
 * app mock思路  
 * 常规的拦截只支持h5,不支持app  
 * 可以使用uni自带的拦截器,利用不存在的网址快速失败从而mock结果数据  
 * 接口虽然失败,但是业务可以拿到mock数据  
 */  
let otherMockFlag = true;  
uni.addInterceptor('request', {  
      invoke(args) {  
        // request 触发前拼接 url   
        let mockUrl = '${可以复用自定义的mockjs}'  
        if(otherMockFlag && args.url === mockUrl){  
            args.url = 'http://localhost/mock' + args.url;  
            //快速失败  
            args.timeout = 1;  
            //模拟接口延迟1000毫秒  
            setTimeout(() => {  
                //可以从mockjs自定义的api里面提取数据  
                args.success({  
                    data: {  
                        code: 0,  
                        data: {  
                            a:1,  
                            b:2  
                        }  
                    }  
                })  
            },1000)  
        }  
      },  
      success(args) {  
        //console.log(JSON.stringify(args));  
      },   
      fail(err) {  
        //console.log('interceptor-fail',err)  
      },   
      complete(res) {  
        //console.log('interceptor-complete',res)  
      }  
})

打包app测试,可以mock数据,就是不知道这样有没有其它的问题

继续阅读 »

以下仅仅是自己开发实践中的一点想法,如有错误,请指正:

uniapp开发中,对于h5应用,通常可以使用mocker-api和mockjs来拦截网络请求,但是APP一般都说不支持,我们开发中主要以app为主,有时候需要mock数据做演示包,思考了很久,突然发现uniapp中有一个拦截器,感觉可以用其来实现数据的mock,思路如下:

/**  
 * app mock思路  
 * 常规的拦截只支持h5,不支持app  
 * 可以使用uni自带的拦截器,利用不存在的网址快速失败从而mock结果数据  
 * 接口虽然失败,但是业务可以拿到mock数据  
 */  
let otherMockFlag = true;  
uni.addInterceptor('request', {  
      invoke(args) {  
        // request 触发前拼接 url   
        let mockUrl = '${可以复用自定义的mockjs}'  
        if(otherMockFlag && args.url === mockUrl){  
            args.url = 'http://localhost/mock' + args.url;  
            //快速失败  
            args.timeout = 1;  
            //模拟接口延迟1000毫秒  
            setTimeout(() => {  
                //可以从mockjs自定义的api里面提取数据  
                args.success({  
                    data: {  
                        code: 0,  
                        data: {  
                            a:1,  
                            b:2  
                        }  
                    }  
                })  
            },1000)  
        }  
      },  
      success(args) {  
        //console.log(JSON.stringify(args));  
      },   
      fail(err) {  
        //console.log('interceptor-fail',err)  
      },   
      complete(res) {  
        //console.log('interceptor-complete',res)  
      }  
})

打包app测试,可以mock数据,就是不知道这样有没有其它的问题

收起阅读 »

用HBuilder运行到浏览器调试代码正常,没有报错,但是上传网站到服务器,用域名打开,操作就报错

新打开页面会报错,报错后刷新页面又正常,好奇怪!!

新打开页面会报错,报错后刷新页面又正常,好奇怪!!

给dcloud官方的一点建议

用户建议

首先来说,我不是来找喷的,我只是希望dcloud越做越好,如有冒犯那就都是我错了。

  1. 建议拥抱开源,而不是疯狂的想把开发者绑定在dcloud的开发环境上。
    • 作为开发者都有自己的开发习惯,和自己喜欢的IDE。比如我是一个全栈,java是主语言,我就带着很多idea的热键习惯去看HBuilder。如果你做不到把ide做的比vs code好或者比idea好,那就试着接受市场的现状。
    • 已经有npm了,那么dcloud的插件市场就显得很多余。而且,你可以认真去看看插件市场的代码质量真的惨不忍睹。同样的,你做不到比npm好用,大厂的前端就不可能给dcloud贡献代码,甚至直接放弃uni-app转手去用cordova。
    • 包管理混乱。傻傻的分不清uni_modles为啥不能用package.json替代。这甚至导致我没办法使用ci工具来完成打包工作,这就又导致用uni-app生态的同学只能局限为外包,难以反哺dcloud社区。而且这种包管理方式非常占用git
继续阅读 »

首先来说,我不是来找喷的,我只是希望dcloud越做越好,如有冒犯那就都是我错了。

  1. 建议拥抱开源,而不是疯狂的想把开发者绑定在dcloud的开发环境上。
    • 作为开发者都有自己的开发习惯,和自己喜欢的IDE。比如我是一个全栈,java是主语言,我就带着很多idea的热键习惯去看HBuilder。如果你做不到把ide做的比vs code好或者比idea好,那就试着接受市场的现状。
    • 已经有npm了,那么dcloud的插件市场就显得很多余。而且,你可以认真去看看插件市场的代码质量真的惨不忍睹。同样的,你做不到比npm好用,大厂的前端就不可能给dcloud贡献代码,甚至直接放弃uni-app转手去用cordova。
    • 包管理混乱。傻傻的分不清uni_modles为啥不能用package.json替代。这甚至导致我没办法使用ci工具来完成打包工作,这就又导致用uni-app生态的同学只能局限为外包,难以反哺dcloud社区。而且这种包管理方式非常占用git
收起阅读 »

app打包后出现拨打电话无反应

APP拨打电话需要勾选两个权限,但文档上只写了一个,对不熟悉app的开发者真是个大坑!
需要添加的另一个权限:<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
希望官方赶紧更新文档!

继续阅读 »

APP拨打电话需要勾选两个权限,但文档上只写了一个,对不熟悉app的开发者真是个大坑!
需要添加的另一个权限:<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
希望官方赶紧更新文档!

收起阅读 »

app中使用subNVue原生子窗体实现全局弹窗,所有页面皆可显示遮罩

定位弹窗 popup 弹窗提示 全局组件

!!!!产品需求描述:

1、所有接口请求时把当前版本号和这个接口是否检查更新参数等加上,后端拿到数据后与当前数据库存储的最新版本号是否一致,不一致则抛错并带有最新版本信息。
2、前端在拦截器中进入判断弹窗弹出流程,(h5页面使用全局组件注册即可,当时以为在App上也可以正常显示,哪知道不行),随即使用subNVue原生子窗体实现。过程中遇到一些问题如下。

!!!!开发过程中问题描述:

1、因在拦截器中做处理,会存在多个请求发出,所以需要定义一个弹窗是否已经显示过弹窗,第一个接口触发版本不对时,未弹起过,则唤起弹窗。反之后面的接口触发版本不对则不再弹起弹窗。
2、注意在index文件中无法获取到最新的vuex内容无法实时更新,所以改用uni.getStorageSync()和uni.setStorageSync(),获取最新的值或内容。
3、subNVue原生子窗体,在每次onLaunch时都会初始化,所以在里面使用vuex数据也是不可靠的。得使用uni.getStorageSync()和uni.setStorageSync(),获取最新的值或内容。
4、2,3条建议用来缓存实现一些不重要比较,变化不频繁的数据。
5、具体更新传递弹窗页面信息,使用页面通信,uni.$on(),uni.$emit()。来实现弹窗内容是最新版本信息。若使用uni.getStorageSync()和uni.setStorageSync(),会导致显示更新内容滞后,显示的其实是上一次的。

此文为实现需求的具体实现思路

1.新建原生子窗体目录文件

a.配置 nvue 文件路径,nvue 文件需放置到使用 subNvue 的页面文件目录下,

b.创建文件,文件路径:pages/subNVue/popup.nvue

2.subNVue 子窗体的 pages.json 配置,建议直接配置在首页路径下,其他配置注意事项查看官方文档

{    
    "pages": [{    
        "path": "pages/index/index", //首页    
        "style": {    
            "app-plus": {    
                "subNVues":[{    
                    "id": "concat", // 唯一标识    
                    "path": "pages/index/subnvue/concat", // 页面路径    
                    /*"type": "popup",  这里不需要*/    
                    "style": {    
                        "position": "absolute",    
                        "dock": "right",    
                        "width": "100rpx",    
                        "height": "150rpx",    
                        "background": "transparent"  //实测在为transparent时,tabbar页面唤起自带遮罩,  
                    }    
                }]    
            }    
        }    
    },  
//放在tabar路径后面  
// #ifdef APP-PLUS  
        {  
            "path": "pages/subnvue/popup",  
            "style": {  
                "navigationBarTitleText": "",  
                "disableScroll": true,  
                "bounce":"none",  
                "navigationStyle": "custom"  
            }  
        },  
// #endif  
    ]    
}

3.在App.vue页面配置,页面注册事件监听方法

onShow: function() {  
            console.log('App Show')  
            // 获取用户信息if  
            // #ifdef APP-PLUS || APP-NVUE  
            // app每次onshow先关闭之前注册的事件监听,然后重新注册  
            uni.$off('popup')  
            // 用于接收原生子窗体页面发出的页面通信事件,用于关闭全局弹窗  
            uni.$on('popup', (data) => {  
                if (!data.isShow) {  
                    const subNVue = uni.getSubNVueById('popup');  
                    subNVue.hide('popup', 300)  
                }  
            })  
            // #endif  
            // #ifdef APP-PLUS  
            hotUpdate.versionAutoUpdate(this.versionCode)//热更新方法  
            // #endif  
        },

4. 拦截器中接口校验到新版本抛错

if (res.statusCode == 412) {  
    // 用于判断是否已经弹过弹窗  
    const isShowPromptPopup = uni.getStorageSync('isShowPromptPopup')  
    // 为第一次检验到,且没有弹过窗走一下校验  
    if (!isShowPromptPopup) {  
        // #ifdef H5  
        setTimeout(() => {  
            promptPopup.open({  
                show: true  
            })  
        }, 1000)  
        // #endif  
        // #ifdef APP-PLUS || APP-NVUE  
        // 处理弹窗title,更新内容  
        let showInfo = {  
            title:'',  
            arr:[],  
            setBac:false  
        }  
        let descCn = res.data.error.desc.split(';')[0]  
        let descEn = res.data.error.desc.split(';')[1]  
        showInfo.title = res.data.error.title  
        if (uni.getStorageSync("lang") == 'ch') {  
            showInfo.arr = descCn.split(',')  
        } else {  
            showInfo.arr = descEn.split(',')  
        }  
        // 在 subNVue/vue 页面触发事件  
        if (store.state.whiteList.findIndex(item => item == route) != -1) {  
                             //因为路由白名单为固定内容,所以可以使用vuex数据,当前路由通过uni的api获取。  
            // 判断路由白名单是否显示遮罩,使用原生子窗体,挂载在tabbar页面的话只能在tabbar页面显示遮罩,这时需要手动控制其他页面额外手动设置遮罩  
            showInfo.setBac = false  
            uni.$emit('subPromptmsg', showInfo);  
        } else {  
            showInfo.setBac = true  
            uni.$emit('subPromptmsg', showInfo);  
        }  
        setTimeout(() => {  
            const subNVue = uni.getSubNVueById('popup');  
            subNVue.show('slide-in-center', 200, () => {})  
        }, 1000)  
        // #endif  
    }  
    uni.setStorageSync('isShowPromptPopup', true)  
    return  
}  

5.原生子窗体页面

<template>  
    <view style="flex-direction: column;align-items: center;justify-content: center;" @click.stop="" :style="setBac?'background-color: rgba(0, 0, 0, 0.5);':''">  
        <view style="width: 540rpx;height: 790rpx;border-radius: 24rpx;" class="">  
            <view style="width: 540rpx;height: 379rpx;">  
                <image style="width: 540rpx;height: 379rpx;" src="../../static/imgs/upDataModel.png"></image>  
            </view>  
            <view  
                style="width: 540rpx;height: 411rpx; background-color: #FFFFFF;border-radius: 0rpx 0rpx 24rpx 24rpx;position: relative;">  
                <view class="" style="flex-direction: row; justify-content: center;">  
                    <view class="title">{{lang == 'ch'?errorInfo.title:'New Version'}}</view>  
                    <view style="width: 32rpx;height: 32rpx;margin-left: 4rpx;">  
                        <image style="width: 32rpx;height: 32rpx;" src="../../static/imgs/upDataTips.png"></image>  
                    </view>  
                </view>  
                <view class="" style="margin-top: 35rpx; padding-left: 50rpx; padding-right: 50rpx;">  
                    <view style="flex-direction: row; width: 440rpx;" v-for="(item,index) in errorInfo.arr" :key="index">  
                        <text class="decs-text" style="width: 18rpx;">{{index 1}}</text>  
                        <text class="decs-text">、</text>  
                        <text class="decs-text" style="width: 400rpx;">{{item}}</text>  
                    </view>  
                </view>  
                <view class="flex_c_m" style="position: absolute;bottom: 40rpx;width: 540rpx;height: max-content;">  
                    <view class="bg-ebuy flex_c_m" style="width: 440rpx; height: 80rpx; border-radius: 10rpx;"  
                        @click="confirmprint">  
                        <text class="btn">{{lang == 'ch'?'立即更新':'Update Now'}}</text>  
                    </view>  
                    <text class="fs-22 pa-t12 fc-999">{{lang == 'ch'?"建议连接wifi更快哦":"It's faster to connect to wifi"}}</text>  
                </view>  
            </view>  
        </view>  
    </view>  
</template>  

<script>  
    import {  
        mapState  
    } from 'vuex';  
    import hotUpdate from '@/js_sdk/hot-update.js'  
    export default {  
        data() {  
            return {  
                setBac:false,  
                errorInfo:{  
                    title:'',  
                    arr:[]  
                }  
            }  
        },  
        computed: {  
            ...mapState({  
                lang: 'lang',  
            }),  
        },  
        created() {  
            // 在 subNVue/vue 页面注册事件监听方法    
            // $on(eventName, callback)    
            // 使用 uni.$off 移除之前事件监听器。  
            uni.$off('subPromptmsg', () => {})    
            // 用于接收拦截器发出的页面通信事件,用于接受拦截器发出的最新版本信息  
            uni.$on('subPromptmsg', (data) => {    
              this.setBac = data.setBac  
              this.errorInfo = data  
            })    
        },  
        methods: {  
            closeShowPopup() {  
                uni.$emit('popup', {  
                    isShow: false,  
                });  
            },  
                         //确认更新  
            confirmprint() {  
                uni.showLoading({  
                    title: this.lang == 'ch' ? '更新中...' : 'updating...'  
                })  
                uni.$emit('popup', {  
                    isShow: false,  
                });  
                hotUpdate.versionAutoUpdate(this.versionCode)  
            }  
        }  
    }  
</script>  

<style>  
    .btn {  
        font-size: 32rpx;  
        font-weight: 500;  
        color: #FFFFFF;  
        line-height: 45rpx;  
    }  

    .title {  
        font-size: 40rpx;  
        font-weight: 600;  
        color: #000000;  
        line-height: 56rpx;  
        /* #ifndef APP-NVUE */  
        letter-spacing: 4rpx;  
        /* #endif */  
    }  

    .decs-text {  
        font-size: 24rpx;  
        font-weight: 500;  
        color: #666666;  
        line-height: 40rpx;  
    }  
</style>  

仅为个人实现需求的方法,如有不对之处。欢迎大家进行审查和指正,并尽可能给出一些反馈和建议,以便改进代码的质量和可用性。

继续阅读 »

!!!!产品需求描述:

1、所有接口请求时把当前版本号和这个接口是否检查更新参数等加上,后端拿到数据后与当前数据库存储的最新版本号是否一致,不一致则抛错并带有最新版本信息。
2、前端在拦截器中进入判断弹窗弹出流程,(h5页面使用全局组件注册即可,当时以为在App上也可以正常显示,哪知道不行),随即使用subNVue原生子窗体实现。过程中遇到一些问题如下。

!!!!开发过程中问题描述:

1、因在拦截器中做处理,会存在多个请求发出,所以需要定义一个弹窗是否已经显示过弹窗,第一个接口触发版本不对时,未弹起过,则唤起弹窗。反之后面的接口触发版本不对则不再弹起弹窗。
2、注意在index文件中无法获取到最新的vuex内容无法实时更新,所以改用uni.getStorageSync()和uni.setStorageSync(),获取最新的值或内容。
3、subNVue原生子窗体,在每次onLaunch时都会初始化,所以在里面使用vuex数据也是不可靠的。得使用uni.getStorageSync()和uni.setStorageSync(),获取最新的值或内容。
4、2,3条建议用来缓存实现一些不重要比较,变化不频繁的数据。
5、具体更新传递弹窗页面信息,使用页面通信,uni.$on(),uni.$emit()。来实现弹窗内容是最新版本信息。若使用uni.getStorageSync()和uni.setStorageSync(),会导致显示更新内容滞后,显示的其实是上一次的。

此文为实现需求的具体实现思路

1.新建原生子窗体目录文件

a.配置 nvue 文件路径,nvue 文件需放置到使用 subNvue 的页面文件目录下,

b.创建文件,文件路径:pages/subNVue/popup.nvue

2.subNVue 子窗体的 pages.json 配置,建议直接配置在首页路径下,其他配置注意事项查看官方文档

{    
    "pages": [{    
        "path": "pages/index/index", //首页    
        "style": {    
            "app-plus": {    
                "subNVues":[{    
                    "id": "concat", // 唯一标识    
                    "path": "pages/index/subnvue/concat", // 页面路径    
                    /*"type": "popup",  这里不需要*/    
                    "style": {    
                        "position": "absolute",    
                        "dock": "right",    
                        "width": "100rpx",    
                        "height": "150rpx",    
                        "background": "transparent"  //实测在为transparent时,tabbar页面唤起自带遮罩,  
                    }    
                }]    
            }    
        }    
    },  
//放在tabar路径后面  
// #ifdef APP-PLUS  
        {  
            "path": "pages/subnvue/popup",  
            "style": {  
                "navigationBarTitleText": "",  
                "disableScroll": true,  
                "bounce":"none",  
                "navigationStyle": "custom"  
            }  
        },  
// #endif  
    ]    
}

3.在App.vue页面配置,页面注册事件监听方法

onShow: function() {  
            console.log('App Show')  
            // 获取用户信息if  
            // #ifdef APP-PLUS || APP-NVUE  
            // app每次onshow先关闭之前注册的事件监听,然后重新注册  
            uni.$off('popup')  
            // 用于接收原生子窗体页面发出的页面通信事件,用于关闭全局弹窗  
            uni.$on('popup', (data) => {  
                if (!data.isShow) {  
                    const subNVue = uni.getSubNVueById('popup');  
                    subNVue.hide('popup', 300)  
                }  
            })  
            // #endif  
            // #ifdef APP-PLUS  
            hotUpdate.versionAutoUpdate(this.versionCode)//热更新方法  
            // #endif  
        },

4. 拦截器中接口校验到新版本抛错

if (res.statusCode == 412) {  
    // 用于判断是否已经弹过弹窗  
    const isShowPromptPopup = uni.getStorageSync('isShowPromptPopup')  
    // 为第一次检验到,且没有弹过窗走一下校验  
    if (!isShowPromptPopup) {  
        // #ifdef H5  
        setTimeout(() => {  
            promptPopup.open({  
                show: true  
            })  
        }, 1000)  
        // #endif  
        // #ifdef APP-PLUS || APP-NVUE  
        // 处理弹窗title,更新内容  
        let showInfo = {  
            title:'',  
            arr:[],  
            setBac:false  
        }  
        let descCn = res.data.error.desc.split(';')[0]  
        let descEn = res.data.error.desc.split(';')[1]  
        showInfo.title = res.data.error.title  
        if (uni.getStorageSync("lang") == 'ch') {  
            showInfo.arr = descCn.split(',')  
        } else {  
            showInfo.arr = descEn.split(',')  
        }  
        // 在 subNVue/vue 页面触发事件  
        if (store.state.whiteList.findIndex(item => item == route) != -1) {  
                             //因为路由白名单为固定内容,所以可以使用vuex数据,当前路由通过uni的api获取。  
            // 判断路由白名单是否显示遮罩,使用原生子窗体,挂载在tabbar页面的话只能在tabbar页面显示遮罩,这时需要手动控制其他页面额外手动设置遮罩  
            showInfo.setBac = false  
            uni.$emit('subPromptmsg', showInfo);  
        } else {  
            showInfo.setBac = true  
            uni.$emit('subPromptmsg', showInfo);  
        }  
        setTimeout(() => {  
            const subNVue = uni.getSubNVueById('popup');  
            subNVue.show('slide-in-center', 200, () => {})  
        }, 1000)  
        // #endif  
    }  
    uni.setStorageSync('isShowPromptPopup', true)  
    return  
}  

5.原生子窗体页面

<template>  
    <view style="flex-direction: column;align-items: center;justify-content: center;" @click.stop="" :style="setBac?'background-color: rgba(0, 0, 0, 0.5);':''">  
        <view style="width: 540rpx;height: 790rpx;border-radius: 24rpx;" class="">  
            <view style="width: 540rpx;height: 379rpx;">  
                <image style="width: 540rpx;height: 379rpx;" src="../../static/imgs/upDataModel.png"></image>  
            </view>  
            <view  
                style="width: 540rpx;height: 411rpx; background-color: #FFFFFF;border-radius: 0rpx 0rpx 24rpx 24rpx;position: relative;">  
                <view class="" style="flex-direction: row; justify-content: center;">  
                    <view class="title">{{lang == 'ch'?errorInfo.title:'New Version'}}</view>  
                    <view style="width: 32rpx;height: 32rpx;margin-left: 4rpx;">  
                        <image style="width: 32rpx;height: 32rpx;" src="../../static/imgs/upDataTips.png"></image>  
                    </view>  
                </view>  
                <view class="" style="margin-top: 35rpx; padding-left: 50rpx; padding-right: 50rpx;">  
                    <view style="flex-direction: row; width: 440rpx;" v-for="(item,index) in errorInfo.arr" :key="index">  
                        <text class="decs-text" style="width: 18rpx;">{{index 1}}</text>  
                        <text class="decs-text">、</text>  
                        <text class="decs-text" style="width: 400rpx;">{{item}}</text>  
                    </view>  
                </view>  
                <view class="flex_c_m" style="position: absolute;bottom: 40rpx;width: 540rpx;height: max-content;">  
                    <view class="bg-ebuy flex_c_m" style="width: 440rpx; height: 80rpx; border-radius: 10rpx;"  
                        @click="confirmprint">  
                        <text class="btn">{{lang == 'ch'?'立即更新':'Update Now'}}</text>  
                    </view>  
                    <text class="fs-22 pa-t12 fc-999">{{lang == 'ch'?"建议连接wifi更快哦":"It's faster to connect to wifi"}}</text>  
                </view>  
            </view>  
        </view>  
    </view>  
</template>  

<script>  
    import {  
        mapState  
    } from 'vuex';  
    import hotUpdate from '@/js_sdk/hot-update.js'  
    export default {  
        data() {  
            return {  
                setBac:false,  
                errorInfo:{  
                    title:'',  
                    arr:[]  
                }  
            }  
        },  
        computed: {  
            ...mapState({  
                lang: 'lang',  
            }),  
        },  
        created() {  
            // 在 subNVue/vue 页面注册事件监听方法    
            // $on(eventName, callback)    
            // 使用 uni.$off 移除之前事件监听器。  
            uni.$off('subPromptmsg', () => {})    
            // 用于接收拦截器发出的页面通信事件,用于接受拦截器发出的最新版本信息  
            uni.$on('subPromptmsg', (data) => {    
              this.setBac = data.setBac  
              this.errorInfo = data  
            })    
        },  
        methods: {  
            closeShowPopup() {  
                uni.$emit('popup', {  
                    isShow: false,  
                });  
            },  
                         //确认更新  
            confirmprint() {  
                uni.showLoading({  
                    title: this.lang == 'ch' ? '更新中...' : 'updating...'  
                })  
                uni.$emit('popup', {  
                    isShow: false,  
                });  
                hotUpdate.versionAutoUpdate(this.versionCode)  
            }  
        }  
    }  
</script>  

<style>  
    .btn {  
        font-size: 32rpx;  
        font-weight: 500;  
        color: #FFFFFF;  
        line-height: 45rpx;  
    }  

    .title {  
        font-size: 40rpx;  
        font-weight: 600;  
        color: #000000;  
        line-height: 56rpx;  
        /* #ifndef APP-NVUE */  
        letter-spacing: 4rpx;  
        /* #endif */  
    }  

    .decs-text {  
        font-size: 24rpx;  
        font-weight: 500;  
        color: #666666;  
        line-height: 40rpx;  
    }  
</style>  

仅为个人实现需求的方法,如有不对之处。欢迎大家进行审查和指正,并尽可能给出一些反馈和建议,以便改进代码的质量和可用性。

收起阅读 »

Dcloud 一键认证常见问题

一键登录

Dcloud 一键认证常见问题

一、基础问题

1.隐私政策声明参考

https://ask.dcloud.net.cn/article/39484

2.基础错误码:

-20201 未插手机电话卡
-20202 未开启蜂窝网络
-20203 不支持的运营商,请检查手机是否成功连接运营商、以及sdk支持该运营商,必须使用真机调试,模拟器没有手机卡,是不能获取到运营商信息的

3."errMsg": "preLogin:fail -20102其他错误","errCode": 30004, "code": 30004

Android:证书签名和添加应用时候的签名不一样
原因:证书签名和添加应用时候的签名(dcloud一键认证后台,应用管理处)不一样
【推荐】签名获取工具参考:https://github.com/kaikramer/keystore-explorer/releases/tag/v5.6.0
可以参考这个获取下证书签名:https://ask.dcloud.net.cn/article/39291
https://ask.dcloud.net.cn/article/38778
Ios: 包名不对应或者需要重新打自定义基座

4."errMsg": "preLogin:fail -20102appid配置获取错误,请联系技术支持","errCode": 30005,"code": 30005

多次调了一键登录,第二次重复调的就会返回这个错误,每次登录之前都要先进行预登录
建议打自定义基座解决

5."errMsg": "preLogin:fail -10003预登录失败","errCode": 30005,"code": 30005

网络问题,关闭然后打开飞行模式,或者使用手机流量网络重新试下

6."login:fail -20301一键登录失败"

-20301是授权页退出,重复调了login

7."errMsg": "login:fail -10006一键登录失败"

重复调login了,-10006 上一个请求正在进行中,请稍后重试,一键登入成功后,需要主动调用关闭授权页面接口后,再重新进行登入

8.{errno=0, data={msg=gyuid不合法, result=40009}

客户端生成openid(gyuid)的应用信息与服务端请求登录的应用信息不匹配

9.{-20104一键登录失败}

先预登录成功,再一键登录

继续阅读 »

Dcloud 一键认证常见问题

一、基础问题

1.隐私政策声明参考

https://ask.dcloud.net.cn/article/39484

2.基础错误码:

-20201 未插手机电话卡
-20202 未开启蜂窝网络
-20203 不支持的运营商,请检查手机是否成功连接运营商、以及sdk支持该运营商,必须使用真机调试,模拟器没有手机卡,是不能获取到运营商信息的

3."errMsg": "preLogin:fail -20102其他错误","errCode": 30004, "code": 30004

Android:证书签名和添加应用时候的签名不一样
原因:证书签名和添加应用时候的签名(dcloud一键认证后台,应用管理处)不一样
【推荐】签名获取工具参考:https://github.com/kaikramer/keystore-explorer/releases/tag/v5.6.0
可以参考这个获取下证书签名:https://ask.dcloud.net.cn/article/39291
https://ask.dcloud.net.cn/article/38778
Ios: 包名不对应或者需要重新打自定义基座

4."errMsg": "preLogin:fail -20102appid配置获取错误,请联系技术支持","errCode": 30005,"code": 30005

多次调了一键登录,第二次重复调的就会返回这个错误,每次登录之前都要先进行预登录
建议打自定义基座解决

5."errMsg": "preLogin:fail -10003预登录失败","errCode": 30005,"code": 30005

网络问题,关闭然后打开飞行模式,或者使用手机流量网络重新试下

6."login:fail -20301一键登录失败"

-20301是授权页退出,重复调了login

7."errMsg": "login:fail -10006一键登录失败"

重复调login了,-10006 上一个请求正在进行中,请稍后重试,一键登入成功后,需要主动调用关闭授权页面接口后,再重新进行登入

8.{errno=0, data={msg=gyuid不合法, result=40009}

客户端生成openid(gyuid)的应用信息与服务端请求登录的应用信息不匹配

9.{-20104一键登录失败}

先预登录成功,再一键登录

收起阅读 »

uni.push后台配置ios证书一直报证书环境错误排除方案

Push

如果您在使用uni-push配置iOS证书时遇到了证书环境错误的问题,可能是因为以下原因之一:

证书文件格式不正确:证书文件应该是PEM格式或P12格式。如果您的证书文件不是这两种格式,就会导致证书环境错误。

证书文件密码错误:如果您的证书文件设置了密码,并且您在配置证书时输入了错误的密码,就会导致证书环境错误。

证书文件与App ID不匹配:在配置iOS证书时,需要确保证书文件与您的App ID匹配。如果证书文件与App ID不匹配,就会导致证书环境错误。

针对这些问题,您可以尝试以下解决方案:

检查证书文件格式是否正确:您可以通过打开证书文件并查看其内容,来确定证书文件的格式。如果证书文件不是PEM格式或P12格式,可以尝试将其转换为正确的格式。

确认证书文件密码是否正确:如果您在配置证书时输入了密码,可以尝试重新输入密码,并确保密码正确。

确认证书文件与App ID是否匹配:您可以登录苹果开发者中心,检查您的证书文件是否与App ID匹配。如果不匹配,可以尝试重新生成证书文件。

除此之外,您还可以尝试在UniPush后台重新上传证书文件,或者联系UniPush官方客服获取进一步帮助。

继续阅读 »

如果您在使用uni-push配置iOS证书时遇到了证书环境错误的问题,可能是因为以下原因之一:

证书文件格式不正确:证书文件应该是PEM格式或P12格式。如果您的证书文件不是这两种格式,就会导致证书环境错误。

证书文件密码错误:如果您的证书文件设置了密码,并且您在配置证书时输入了错误的密码,就会导致证书环境错误。

证书文件与App ID不匹配:在配置iOS证书时,需要确保证书文件与您的App ID匹配。如果证书文件与App ID不匹配,就会导致证书环境错误。

针对这些问题,您可以尝试以下解决方案:

检查证书文件格式是否正确:您可以通过打开证书文件并查看其内容,来确定证书文件的格式。如果证书文件不是PEM格式或P12格式,可以尝试将其转换为正确的格式。

确认证书文件密码是否正确:如果您在配置证书时输入了密码,可以尝试重新输入密码,并确保密码正确。

确认证书文件与App ID是否匹配:您可以登录苹果开发者中心,检查您的证书文件是否与App ID匹配。如果不匹配,可以尝试重新生成证书文件。

除此之外,您还可以尝试在UniPush后台重新上传证书文件,或者联系UniPush官方客服获取进一步帮助。

收起阅读 »

plus.runtime.launchApplication安卓调用其他app code为-99

h5+

plus.runtime.launchApplication 是在 HBuilderX 开发环境中的 mui 扩展 API,用于调用其他应用程序。code -99 的返回值通常表示应用程序未能成功启动。

这个问题可能是由以下原因导致的:

您可能没有将要启动的应用程序正确地安装在您的设备上。请检查应用程序是否已成功安装,并且您正在调用正确的应用程序包名。

应用程序可能需要特定的权限才能启动。如果您的应用程序需要这些权限,请确保在 AndroidManifest.xml 文件中声明了这些权限。

应用程序可能需要更高的安卓版本才能运行。请检查您的设备是否满足应用程序的最低版本要求。

您可能正在调用一个无效的应用程序 URI。请确保您正在使用正确的 URI,并且您正在调用支持 URI 的应用程序。

您可以通过调用应用程序的 URI 来启动应用程序,如下所示:

var uri = "weixin://";  
mui.plusReady(function() {  
  plus.runtime.launchApplication({  
    action: uri  
  }, function(e) {  
    console.log("启动失败");  
    console.log(JSON.stringify(e));  
  });  
});

我们调用微信应用程序。您可以根据需要更改 URI。如果应用程序已安装且可用,它应该会启动。如果应用程序未能启动,请检查您的应用程序是否存在以上列出的问题。

继续阅读 »

plus.runtime.launchApplication 是在 HBuilderX 开发环境中的 mui 扩展 API,用于调用其他应用程序。code -99 的返回值通常表示应用程序未能成功启动。

这个问题可能是由以下原因导致的:

您可能没有将要启动的应用程序正确地安装在您的设备上。请检查应用程序是否已成功安装,并且您正在调用正确的应用程序包名。

应用程序可能需要特定的权限才能启动。如果您的应用程序需要这些权限,请确保在 AndroidManifest.xml 文件中声明了这些权限。

应用程序可能需要更高的安卓版本才能运行。请检查您的设备是否满足应用程序的最低版本要求。

您可能正在调用一个无效的应用程序 URI。请确保您正在使用正确的 URI,并且您正在调用支持 URI 的应用程序。

您可以通过调用应用程序的 URI 来启动应用程序,如下所示:

var uri = "weixin://";  
mui.plusReady(function() {  
  plus.runtime.launchApplication({  
    action: uri  
  }, function(e) {  
    console.log("启动失败");  
    console.log(JSON.stringify(e));  
  });  
});

我们调用微信应用程序。您可以根据需要更改 URI。如果应用程序已安装且可用,它应该会启动。如果应用程序未能启动,请检查您的应用程序是否存在以上列出的问题。

收起阅读 »