
安卓微信支付-100 问题解决经历
之前没有用过安卓微信支付,这次接入以为和小程序之类的差不多,结果就疯狂报-100
查了很多资料,官网给的说法基本是检查参数
最后发现用安卓公共证书是不能调起的
自己生成了一个开发证书 并修改开放平台的签名,有十分钟的生效时间
然后杀死所有APP 包括微信。
重新调用就可以了
附上生成开发证书的地址。自己生成jdk版本过高也不行。到处是坑。
http://www.applicationloader.net/appuploader/keystore.php
之前没有用过安卓微信支付,这次接入以为和小程序之类的差不多,结果就疯狂报-100
查了很多资料,官网给的说法基本是检查参数
最后发现用安卓公共证书是不能调起的
自己生成了一个开发证书 并修改开放平台的签名,有十分钟的生效时间
然后杀死所有APP 包括微信。
重新调用就可以了
附上生成开发证书的地址。自己生成jdk版本过高也不行。到处是坑。
http://www.applicationloader.net/appuploader/keystore.php

h5+app 上传图片,使用io文件管理时,在真机运行环境可以正常读取文件但是在打包apk后就无法读取到文件了
"targetSdkVersion" : 28
这个不要选到最新29 换成28就可以了
"targetSdkVersion" : 28
这个不要选到最新29 换成28就可以了

利用webview的跳转的方式开发应用
通过webview界面跳转的方式开发本地界面,为什么偶尔会产生应用死掉,点解任何按钮都没有反应的情况,只能重新杀掉应用重新打开,才能恢复功能。
请大神们解惑!
webview = plus.webview.create('/pages/add_device.html', 'add_device', {
titleNView: {
backgroundColor: '#0055ff',
titleText: '搜索设备',
titleColor: '#ffffff',
autoBackButton: true
}
}, {
group_id: w.group_id,
group_name: w.group_name,
});
webview&&webview.show(as, null, function(){
webview=null;//避免快速点击打开多个页面
});
通过webview界面跳转的方式开发本地界面,为什么偶尔会产生应用死掉,点解任何按钮都没有反应的情况,只能重新杀掉应用重新打开,才能恢复功能。
请大神们解惑!
webview = plus.webview.create('/pages/add_device.html', 'add_device', {
titleNView: {
backgroundColor: '#0055ff',
titleText: '搜索设备',
titleColor: '#ffffff',
autoBackButton: true
}
}, {
group_id: w.group_id,
group_name: w.group_name,
});
webview&&webview.show(as, null, function(){
webview=null;//避免快速点击打开多个页面
});
收起阅读 »

另一种思路,100%好用的项目迁移方案,从wepy转uniapp
如果关注过项目迁移,都见过有那种工具转换的,比如官方也给出了参考工具:
https://uniapp.dcloud.io/translate
但实际项目中,这些根本是行不通的,比如wepy,uniapp 实现原理不同,转换出来的脚本就很难通用。
下面给出另一个思路,只针对微信小程序,不论是哪种工程,最终编译出来的结果,一定是微信能解析的。那如果我把两个不同工程编译输出的结果合并,并且解决依赖及冲突,就意味着是可行的。
我这里实际操作的是把原有的wepy工程,整合到uniapp中,理论上如果是其他项目,也可以采用类似的思路。
下面就是顺着这个思路,依次解决:
第一步, 整合两个工程
1、通过 cli 命令行新建uniapp工程,方法参照官方文档:
https://uniapp.dcloud.io/quickstart-cli
打开 package.json,添加 wepy 核心依赖:
"wepy": "^1.7.2",
"wepy-async-function": "^1.4.7",
"wepy-plugin-filemin": "^1.3.14"
2、uniapp 工程根目录下创建 wepy 目录,把wepy工程代码放在这下面,像这样:
第二步,让wepy的编译输出和uniapp一致
把wepy.config.js 移到 uniapp 根目录,修改wepy.config.js,根据编译环境,设置不同的输出,如下:
if (process.env.NODE_ENV === 'production') {
module.exports.target = 'dist/build/mp-weixin/'
} else {
module.exports.target = 'dist/dev/mp-weixin/'
}
这样当编译 wepy 时,就会和uniapp 输出一致了。
第三步,整合页面信息 pages/xxxx 路径
uniapp 有一个 src/manifest.json ,在 mp-weixin 节点,添加 pages,把原有 app.wpy 里的pages 复制过来,如果有分包,也一样,注意字符串添加双引号,符合json规范,如下:
"pages": [
"pages/guide",
"pages/index",
"pages/login",
"pages/trends/index",
...
"subPackages": [
{
"root": "packageA",
"pages": [
"pages/read/interact",
"pages/read/badge"
]
},
第四步、完善uniapp的 src/App.vue
这一步最核心,前后次序,逻辑不能有错。需要按照 wepy 逻辑,注入相关核心。
1、整合 globalData,uniapp 和 wepy 都有自己的全局,把wepy 的globalData 完整复制给 uniapp,如下:
2、高光的魔术时刻。在 Uniapp 的 App.vue => onLaunch 中通过如下代码注入 wepy的核心:
注意,原有 wepy 中 import 的包,在 uniapp 里一定要用 non_webpack_require,这只是单纯的路径引用。
如果Uniapp里直接 import,会被webpack 编入代码。如果不太理解,按我说的操作即可。
this.globalData.sentry = sentry
// 构建 wepy 核心
let wepy = __non_webpack_require__('./../npm/wepy/lib/wepy.js')
__non_webpack_require__('./../npm/wepy-async-function/index.js')
let $wepyApp = wepy.default.$createApp(wepy.default.app, {
"noPromiseAPI": ["createSelectorQuery"],
"baseUrl": process.env.SERVER_URL + 'api/', // 一些项目中用到的参数,根据自己需要设置
"oriUrl": process.env.SERVER_URL,
"indexTitle": "你的应用名",
"isDev": process.env.NODE_ENV !== 'production'
})
// 注入 globalData
wepy.default.$instance.globalData = this.globalData
wepy.default.$instance.use('promisify')
const wepyPage = __non_webpack_require__('./../npm/wepy/lib/page.js')
App($wepyApp);
this.globalData.systemInfo = uni.getSystemInfoSync();
注意promisy 这个,如果用了,必须引用下 non_webpack_require('./../npm/wepy-async-function/index.js')。
全局css就按需要写就好,css一般不会有什么冲突,可以完全copy。注意下语法是 scss 还是 less 就好,然后通过 <style lang="scss">
指定
其他 wepy app.wpy中的业务代码部分,自己根据需要些,总之要完全替换好 App.vue。两个工程整合成否与否的关键,就是 App.vue,因为这个必须使用 Uniapp的。
最后一步,如何编译
1、打开 package.json,
修改 mp-weixin,注意必须加参数 --clean=0 (表示编译时,不清空输出目录)
添加 wepy 编译,加参数 -s wepy 是表示指定编译的源码路径 wepy,最后如下:
"dev:wepy": "cross-env NODE_ENV=development wepy build -s wepy --no-cache --watch",
"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --clean=0 --watch",
"build:wepy": "rimraf ./dist/build/mp-weixin/* && cross-env NODE_ENV=production wepy build -s wepy --no-cache",
"build:mp-weixin": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build --clean=0"
2、编译次序与发布
当开发环境时
先 npm run dev:wepy
再打开一个窗口: npm run dev:mp-weixin
无论修改哪个工程,都会热更新。但通常wepy不需要修改源码时,wepy 不用一直开着。
当产线发布时
先 npm run build:wepy
,再运行 npm run build:mp-weixin
如果关注过项目迁移,都见过有那种工具转换的,比如官方也给出了参考工具:
https://uniapp.dcloud.io/translate
但实际项目中,这些根本是行不通的,比如wepy,uniapp 实现原理不同,转换出来的脚本就很难通用。
下面给出另一个思路,只针对微信小程序,不论是哪种工程,最终编译出来的结果,一定是微信能解析的。那如果我把两个不同工程编译输出的结果合并,并且解决依赖及冲突,就意味着是可行的。
我这里实际操作的是把原有的wepy工程,整合到uniapp中,理论上如果是其他项目,也可以采用类似的思路。
下面就是顺着这个思路,依次解决:
第一步, 整合两个工程
1、通过 cli 命令行新建uniapp工程,方法参照官方文档:
https://uniapp.dcloud.io/quickstart-cli
打开 package.json,添加 wepy 核心依赖:
"wepy": "^1.7.2",
"wepy-async-function": "^1.4.7",
"wepy-plugin-filemin": "^1.3.14"
2、uniapp 工程根目录下创建 wepy 目录,把wepy工程代码放在这下面,像这样:
第二步,让wepy的编译输出和uniapp一致
把wepy.config.js 移到 uniapp 根目录,修改wepy.config.js,根据编译环境,设置不同的输出,如下:
if (process.env.NODE_ENV === 'production') {
module.exports.target = 'dist/build/mp-weixin/'
} else {
module.exports.target = 'dist/dev/mp-weixin/'
}
这样当编译 wepy 时,就会和uniapp 输出一致了。
第三步,整合页面信息 pages/xxxx 路径
uniapp 有一个 src/manifest.json ,在 mp-weixin 节点,添加 pages,把原有 app.wpy 里的pages 复制过来,如果有分包,也一样,注意字符串添加双引号,符合json规范,如下:
"pages": [
"pages/guide",
"pages/index",
"pages/login",
"pages/trends/index",
...
"subPackages": [
{
"root": "packageA",
"pages": [
"pages/read/interact",
"pages/read/badge"
]
},
第四步、完善uniapp的 src/App.vue
这一步最核心,前后次序,逻辑不能有错。需要按照 wepy 逻辑,注入相关核心。
1、整合 globalData,uniapp 和 wepy 都有自己的全局,把wepy 的globalData 完整复制给 uniapp,如下:
2、高光的魔术时刻。在 Uniapp 的 App.vue => onLaunch 中通过如下代码注入 wepy的核心:
注意,原有 wepy 中 import 的包,在 uniapp 里一定要用 non_webpack_require,这只是单纯的路径引用。
如果Uniapp里直接 import,会被webpack 编入代码。如果不太理解,按我说的操作即可。
this.globalData.sentry = sentry
// 构建 wepy 核心
let wepy = __non_webpack_require__('./../npm/wepy/lib/wepy.js')
__non_webpack_require__('./../npm/wepy-async-function/index.js')
let $wepyApp = wepy.default.$createApp(wepy.default.app, {
"noPromiseAPI": ["createSelectorQuery"],
"baseUrl": process.env.SERVER_URL + 'api/', // 一些项目中用到的参数,根据自己需要设置
"oriUrl": process.env.SERVER_URL,
"indexTitle": "你的应用名",
"isDev": process.env.NODE_ENV !== 'production'
})
// 注入 globalData
wepy.default.$instance.globalData = this.globalData
wepy.default.$instance.use('promisify')
const wepyPage = __non_webpack_require__('./../npm/wepy/lib/page.js')
App($wepyApp);
this.globalData.systemInfo = uni.getSystemInfoSync();
注意promisy 这个,如果用了,必须引用下 non_webpack_require('./../npm/wepy-async-function/index.js')。
全局css就按需要写就好,css一般不会有什么冲突,可以完全copy。注意下语法是 scss 还是 less 就好,然后通过 <style lang="scss">
指定
其他 wepy app.wpy中的业务代码部分,自己根据需要些,总之要完全替换好 App.vue。两个工程整合成否与否的关键,就是 App.vue,因为这个必须使用 Uniapp的。
最后一步,如何编译
1、打开 package.json,
修改 mp-weixin,注意必须加参数 --clean=0 (表示编译时,不清空输出目录)
添加 wepy 编译,加参数 -s wepy 是表示指定编译的源码路径 wepy,最后如下:
"dev:wepy": "cross-env NODE_ENV=development wepy build -s wepy --no-cache --watch",
"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --clean=0 --watch",
"build:wepy": "rimraf ./dist/build/mp-weixin/* && cross-env NODE_ENV=production wepy build -s wepy --no-cache",
"build:mp-weixin": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build --clean=0"
2、编译次序与发布
当开发环境时
先 npm run dev:wepy
再打开一个窗口: npm run dev:mp-weixin
无论修改哪个工程,都会热更新。但通常wepy不需要修改源码时,wepy 不用一直开着。
当产线发布时
先 npm run build:wepy
,再运行 npm run build:mp-weixin

小说网站源码+全自动采集规则+H5手机版页面
小说网站源码是一个基于web的系统,使用PHP、BootStrap、CSS、JavaScript和MySQL为数据库开发。它包含两个方面,即管理员端和用户端。这个PHP/MySQLi环境下的在小说站旨在帮助管理员一个简单的方法来更新和维护所有的在线图书,以供阅读者查阅。
源码:xsymz.icu
PHP中的在线小说站源码是一个使用PHP、JavaScript和CSS开发的简单项目。该项目包含管理员和用户端。管理员端管理所有的管理,如添加书籍、删除书籍和编辑书籍的详细信息,管理员在这个小说站系统的管理中扮演着重要的角色。
对于用户部分,如果用户已经有账号,可以以用户身份登录,否则,他/她必须填写注册表以注册为用户。用户可以浏览已发行书籍的详细信息及其归还状态。该项目为学生和小说站做好图书记录、借阅和归还工作提供了方便。
我们中的许多人最有可能的一天是通过阅读一本书来度过的,无论它是一个幻想系列、小说、惊悚片、浪漫和更多的选择。获得所有这些资源的最佳地点是在线小说站。我们都知道管理一个小说是不容易的,无论是资源站还是搜索站,这时,一套稳定高效的小说网站源码就是至关重要的。在这个PHP/MySQLi环境下的小说管理系统,管理员有权在所有交易中从借书、还书和图书类别。他还拥有管理所有书籍、管理借贷者和管理所有用户的能力。同时,用户可以根据自己想要的图书类型,方便地通过网上借阅图书,甚至可以在登录系统后更新自己的个人资料。
小说网站源码系统结构:
管理端
1、仪表板
2、借来的书
3、还书
4、图书种类
5、管理书籍
6、管理借款人
7、管理用户
8、登录和注销
阅读段
1、加书
2、图书过滤
3、关于我们
4、联系人管理
5、简况
6、借书
7、借阅图书一览表
8、登录和注销
小说站源码的安装方法:
1、下载zip文件;
2、下载并安装XAMPP;
3、运行XAMPP控制面板并启动MySQL和Apache;
4、去C:\xampp\htdocs并提取下载的zip文件(图书馆系统)在文件夹内;
5、打开浏览器并转到localhost/phpmyadmin/创建数据库;
6、单击新建以创建数据库;
7、命名数据库数据库库;
8、单击“导入”以导入sql语言文件;
9、单击“选择文件”,然后选择可以在图书馆系统文件夹;
10、单击go;
11、打开浏览器并转到localhost/LibrarySystem/admin/
访问管理员帐户
用户名:admin
密码:admin
12、打开浏览器并转到localhost/LibrarySystem/
访问管理员帐户
你可以注册。
关于源码
这个小说网站源码使用PHP、JavaScript和CSS,并自动集成了多套采集规则。在介绍本系统的特点时,它包括管理部分和用户部分。所有的编辑更新,管理书籍作者都来自管理部门,这套源码的设计很简单,所以用户在工作时不会遇到任何困难。
小说网站源码是一个基于web的系统,使用PHP、BootStrap、CSS、JavaScript和MySQL为数据库开发。它包含两个方面,即管理员端和用户端。这个PHP/MySQLi环境下的在小说站旨在帮助管理员一个简单的方法来更新和维护所有的在线图书,以供阅读者查阅。
源码:xsymz.icu
PHP中的在线小说站源码是一个使用PHP、JavaScript和CSS开发的简单项目。该项目包含管理员和用户端。管理员端管理所有的管理,如添加书籍、删除书籍和编辑书籍的详细信息,管理员在这个小说站系统的管理中扮演着重要的角色。
对于用户部分,如果用户已经有账号,可以以用户身份登录,否则,他/她必须填写注册表以注册为用户。用户可以浏览已发行书籍的详细信息及其归还状态。该项目为学生和小说站做好图书记录、借阅和归还工作提供了方便。
我们中的许多人最有可能的一天是通过阅读一本书来度过的,无论它是一个幻想系列、小说、惊悚片、浪漫和更多的选择。获得所有这些资源的最佳地点是在线小说站。我们都知道管理一个小说是不容易的,无论是资源站还是搜索站,这时,一套稳定高效的小说网站源码就是至关重要的。在这个PHP/MySQLi环境下的小说管理系统,管理员有权在所有交易中从借书、还书和图书类别。他还拥有管理所有书籍、管理借贷者和管理所有用户的能力。同时,用户可以根据自己想要的图书类型,方便地通过网上借阅图书,甚至可以在登录系统后更新自己的个人资料。
小说网站源码系统结构:
管理端
1、仪表板
2、借来的书
3、还书
4、图书种类
5、管理书籍
6、管理借款人
7、管理用户
8、登录和注销
阅读段
1、加书
2、图书过滤
3、关于我们
4、联系人管理
5、简况
6、借书
7、借阅图书一览表
8、登录和注销
小说站源码的安装方法:
1、下载zip文件;
2、下载并安装XAMPP;
3、运行XAMPP控制面板并启动MySQL和Apache;
4、去C:\xampp\htdocs并提取下载的zip文件(图书馆系统)在文件夹内;
5、打开浏览器并转到localhost/phpmyadmin/创建数据库;
6、单击新建以创建数据库;
7、命名数据库数据库库;
8、单击“导入”以导入sql语言文件;
9、单击“选择文件”,然后选择可以在图书馆系统文件夹;
10、单击go;
11、打开浏览器并转到localhost/LibrarySystem/admin/
访问管理员帐户
用户名:admin
密码:admin
12、打开浏览器并转到localhost/LibrarySystem/
访问管理员帐户
你可以注册。
关于源码
这个小说网站源码使用PHP、JavaScript和CSS,并自动集成了多套采集规则。在介绍本系统的特点时,它包括管理部分和用户部分。所有的编辑更新,管理书籍作者都来自管理部门,这套源码的设计很简单,所以用户在工作时不会遇到任何困难。

字节抖音小程序使用$refs报错解决办法
我做抖音小程序遇到这个问题,开发工具里一切正常,一旦真机使用时运行到$refs就报错
解决办法如下(困扰了我三天):
参考官网的“.sync修饰符”
父组件:
<form-item ref="formItem" :isfromok.sync="isfromok"></form-item>
components: {
formItem
},
data() {
return {
isfromok: false //是否填写表单
};
},
子组件(直接修改父组件的值):
let data = 123456;
_this.$emit('update:isfromok',datas);
在父组件内可直接判断isfromok的值是否符合预期,不用再使用$refs了
如果需要执行子组件的方法,可以使用watch监听来实现,希望能够帮助更多的人
我做抖音小程序遇到这个问题,开发工具里一切正常,一旦真机使用时运行到$refs就报错
解决办法如下(困扰了我三天):
参考官网的“.sync修饰符”
父组件:
<form-item ref="formItem" :isfromok.sync="isfromok"></form-item>
components: {
formItem
},
data() {
return {
isfromok: false //是否填写表单
};
},
子组件(直接修改父组件的值):
let data = 123456;
_this.$emit('update:isfromok',datas);
在父组件内可直接判断isfromok的值是否符合预期,不用再使用$refs了
如果需要执行子组件的方法,可以使用watch监听来实现,希望能够帮助更多的人

分享下安卓下文件和目录的读取,写入,移动,删除
分享下安卓下目录和文件读取
注意需要安装排序库natsort.min.js,和 vm.$u.date 时间函数,可以用自己的函数代替
// #ifdef APP-PLUS
//只能用于安卓 导入java类
let File = plus.android.importClass("java.io.File");
let BufferedReader = plus.android.importClass("java.io.BufferedReader");
let FileReader = plus.android.importClass("java.io.FileReader");
let FileWriter = plus.android.importClass("java.io.FileWriter");
// 安卓11及一下可以在任意地方创建文件夹 /sdcard/自己的文件夹/1.txt
// 安卓11(百度安卓目录限制) /storage/emulated/0/Download/自己的文件夹/1.txt
//新建文件 newFiles("/sdcard/修止符/配置.json")
let newFiles = (name) => {
let directory = new File(name);
if (!directory.exists()) {
return directory.mkdirs(); //不存在创建目录
}
return false;
};
//读取txt文件 readFile ("/sdcard/修止符/配置.json")
let readFile = (fileName) => {
let readFr = new File(fileName);
try {
let reader = new BufferedReader(new FileReader(readFr));
let txt;
let retxt = '';
while (true) {
txt = reader.readLine(); //读取文件
if (txt == null) {
break;
}
retxt = retxt + '\r\n' + txt;
}
return retxt;
} catch (e) {
console.log(e)
return '';
}
};
//写文件 whiteFile("/sdcard/修止符/配置.json",{"主键":"值"})
let whiteFile = (fileName, res) => {
res = res ? JSON.stringify(res) : ''; //对象转换为json文本
try {
//不加根目录创建文件(即用相对地址)的话directory.exists()这个判断一值都是false
let n = fileName.lastIndexOf("/");
if (n != -1) {
let fileDirs = fileName.substring(0, n);
let directory = new File(fileDirs);
if (!directory.exists()) {
directory.mkdirs(); //不存在创建目录
}
}
let file = new File(fileName);
if (!file.exists()) {
file.createNewFile(); //创建文件
}
let fos = new FileWriter(fileName, false);
fos.write(res);
fos.close();
return true;
} catch (e) {
console.log(e);
return false;
}
return false;
};
//删除文件或文件夹 deleteFile ("/sdcard/修止符/待删除/配置.json")
let deleteFile = (fileName) => {
console.log(fileName);
let file = new File(fileName.replace('//', '/'));
if (file.isFile() && file.exists()) {
return file.delete();
} else if (file.isDirectory()) {
let flag = true;
let files = file.listFiles();
let lenI = files.length
for (let i = 0; i < lenI; i++) {
//删除子目录和文件
flag = deleteFile(files[i].getAbsolutePath());
if (!flag) break;
}
if (!flag) return false;
//删除当前空目录
return file.delete();
}
};
//移动文件 moveFile ("/sdcard/修止符/待删除/配置.json","/sdcard/修止符/配置.json")
let moveFile = (oldfile, newfile) => {
let n = newfile.lastIndexOf("/");
if (n != -1) {
let fileDirs = newfile.substring(0, n);
let directory = new File(fileDirs);
if (!directory.exists()) {
directory.mkdirs(); //不存在创建目录
}
}
let file = new File(oldfile);
let nfile = new File(newfile);
return file.renameTo(nfile);
};
//读取目录 readFileList ("/sdcard/修止符/") 注意需要安装排序库natsort.min.js, vm.$u.date 时间函数
let readFileList = (fileName) => {
let directory;
let path = vm.vuex_xzfdir;
let empty = vm.$u.test.isEmpty(fileName)
if (empty) {
directory = new File(vm.vuex_xzfdir);
} else {
path = fileName;
directory = new File(path);
}
if (!directory.exists()) {
directory.mkdirs();
}
let files = directory.listFiles();
//对文件和文件夹进行分类
let lenI = files.length
let folderArr = [];
let fileArr = [];
for (let i = 0; i < lenI; ++i) {
if (files[i].isFile()) {
fileArr.push({
id: i,
show: false,
icon: 'file-text',
path: path,
fileName: files[i].getName(),
CreationTime: vm.$u.date(new Date(files[i].lastModified()), 'yyyy年mm月dd日 hh时MM分ss秒')
});
} else {
folderArr.push({
id: i,
show: false,
icon: 'list-dot',
path: path,
fileName: files[i].getName(),
CreationTime: vm.$u.date(new Date(files[i].lastModified()), 'yyyy年mm月dd日 hh时MM分ss秒')
});
}
}
//对文件进行排序 需要安装排序库natsort.min.js
let sorter = natsort({
desc: vm.vuex_desc
});
fileArr.sort((a, b) => {
return sorter(a.fileName, b.fileName);
});
folderArr.sort((a, b) => {
return sorter(a.fileName, b.fileName);
})
let resultArr = folderArr.concat(fileArr);
return resultArr;
}
// #endif
分享下安卓下目录和文件读取
注意需要安装排序库natsort.min.js,和 vm.$u.date 时间函数,可以用自己的函数代替
// #ifdef APP-PLUS
//只能用于安卓 导入java类
let File = plus.android.importClass("java.io.File");
let BufferedReader = plus.android.importClass("java.io.BufferedReader");
let FileReader = plus.android.importClass("java.io.FileReader");
let FileWriter = plus.android.importClass("java.io.FileWriter");
// 安卓11及一下可以在任意地方创建文件夹 /sdcard/自己的文件夹/1.txt
// 安卓11(百度安卓目录限制) /storage/emulated/0/Download/自己的文件夹/1.txt
//新建文件 newFiles("/sdcard/修止符/配置.json")
let newFiles = (name) => {
let directory = new File(name);
if (!directory.exists()) {
return directory.mkdirs(); //不存在创建目录
}
return false;
};
//读取txt文件 readFile ("/sdcard/修止符/配置.json")
let readFile = (fileName) => {
let readFr = new File(fileName);
try {
let reader = new BufferedReader(new FileReader(readFr));
let txt;
let retxt = '';
while (true) {
txt = reader.readLine(); //读取文件
if (txt == null) {
break;
}
retxt = retxt + '\r\n' + txt;
}
return retxt;
} catch (e) {
console.log(e)
return '';
}
};
//写文件 whiteFile("/sdcard/修止符/配置.json",{"主键":"值"})
let whiteFile = (fileName, res) => {
res = res ? JSON.stringify(res) : ''; //对象转换为json文本
try {
//不加根目录创建文件(即用相对地址)的话directory.exists()这个判断一值都是false
let n = fileName.lastIndexOf("/");
if (n != -1) {
let fileDirs = fileName.substring(0, n);
let directory = new File(fileDirs);
if (!directory.exists()) {
directory.mkdirs(); //不存在创建目录
}
}
let file = new File(fileName);
if (!file.exists()) {
file.createNewFile(); //创建文件
}
let fos = new FileWriter(fileName, false);
fos.write(res);
fos.close();
return true;
} catch (e) {
console.log(e);
return false;
}
return false;
};
//删除文件或文件夹 deleteFile ("/sdcard/修止符/待删除/配置.json")
let deleteFile = (fileName) => {
console.log(fileName);
let file = new File(fileName.replace('//', '/'));
if (file.isFile() && file.exists()) {
return file.delete();
} else if (file.isDirectory()) {
let flag = true;
let files = file.listFiles();
let lenI = files.length
for (let i = 0; i < lenI; i++) {
//删除子目录和文件
flag = deleteFile(files[i].getAbsolutePath());
if (!flag) break;
}
if (!flag) return false;
//删除当前空目录
return file.delete();
}
};
//移动文件 moveFile ("/sdcard/修止符/待删除/配置.json","/sdcard/修止符/配置.json")
let moveFile = (oldfile, newfile) => {
let n = newfile.lastIndexOf("/");
if (n != -1) {
let fileDirs = newfile.substring(0, n);
let directory = new File(fileDirs);
if (!directory.exists()) {
directory.mkdirs(); //不存在创建目录
}
}
let file = new File(oldfile);
let nfile = new File(newfile);
return file.renameTo(nfile);
};
//读取目录 readFileList ("/sdcard/修止符/") 注意需要安装排序库natsort.min.js, vm.$u.date 时间函数
let readFileList = (fileName) => {
let directory;
let path = vm.vuex_xzfdir;
let empty = vm.$u.test.isEmpty(fileName)
if (empty) {
directory = new File(vm.vuex_xzfdir);
} else {
path = fileName;
directory = new File(path);
}
if (!directory.exists()) {
directory.mkdirs();
}
let files = directory.listFiles();
//对文件和文件夹进行分类
let lenI = files.length
let folderArr = [];
let fileArr = [];
for (let i = 0; i < lenI; ++i) {
if (files[i].isFile()) {
fileArr.push({
id: i,
show: false,
icon: 'file-text',
path: path,
fileName: files[i].getName(),
CreationTime: vm.$u.date(new Date(files[i].lastModified()), 'yyyy年mm月dd日 hh时MM分ss秒')
});
} else {
folderArr.push({
id: i,
show: false,
icon: 'list-dot',
path: path,
fileName: files[i].getName(),
CreationTime: vm.$u.date(new Date(files[i].lastModified()), 'yyyy年mm月dd日 hh时MM分ss秒')
});
}
}
//对文件进行排序 需要安装排序库natsort.min.js
let sorter = natsort({
desc: vm.vuex_desc
});
fileArr.sort((a, b) => {
return sorter(a.fileName, b.fileName);
});
folderArr.sort((a, b) => {
return sorter(a.fileName, b.fileName);
})
let resultArr = folderArr.concat(fileArr);
return resultArr;
}
// #endif
收起阅读 »

新版lib.5plus.base-release.aar插件导致android离线打包隐私弹窗中对应链接点击后为空白页(包含解决办法)
现象:
使用3.1.2配置使用正常
使用3.1.13+版本,安装应用后的隐私弹窗,点击其中的链接跳到空白页面,复制网址提示复制null
通过与3.1.2版本互换插件,将问题定位到lib.5plus.base-release.aar上
奇怪的是这个问题在as自带的模拟器上不存在,在真机上才存在
原因:
因为我们应用使用的是uniapp范例中的文案,所以一直以为是我们在strings.xml中的配置项目与新版插件不兼容导致
实际上本质是,我们的配置项目根本就没生效,看到的是lib.5plus.base-release.aar中携带的默认值,变更文案后可以发现模拟器中变更了,但是真机还是原样
造成原因是:我们的string配置按照demo写在了res/values/下,
3.1.2的lib.5plus.base-release.aar自带字符串资源只有values(中文) 和values-en(英文),编译时资源合并顺序最后写入自定义配置,可以生效。
而新版的lib.5plus.base-release.aar自带字符串资源有values(默认,英文?) 和values-en(英文),以及values-zh(中文)。
因为values的定义发生了变化,而离线打包sdk中demo使用的还是values,因此我们配置的项目,只会覆盖value的默认项目,并不会覆盖values-zh
而实际上真机因为是中文系统会默认使用values-zh,导致使用的字符串dcloud_privacy_prompt_message还是lib.5plus.base-release.aar中的默认值,其中对应的href是"",自然到了浏览器就是空值
解决办法:
res下的values目录复制一份更名为values-zh
这个问题应该是官方想要增强多语言的支持能力修订了相关的定义导致。
因为过于诡异,而且更诡异的是社区完全看不到类似的问题,特此提交一个说明,希望能够帮到有需要的人。
也希望官方能够在后续处理此类问题时兼顾考虑demo和相关配置文档的修订。
现象:
使用3.1.2配置使用正常
使用3.1.13+版本,安装应用后的隐私弹窗,点击其中的链接跳到空白页面,复制网址提示复制null
通过与3.1.2版本互换插件,将问题定位到lib.5plus.base-release.aar上
奇怪的是这个问题在as自带的模拟器上不存在,在真机上才存在
原因:
因为我们应用使用的是uniapp范例中的文案,所以一直以为是我们在strings.xml中的配置项目与新版插件不兼容导致
实际上本质是,我们的配置项目根本就没生效,看到的是lib.5plus.base-release.aar中携带的默认值,变更文案后可以发现模拟器中变更了,但是真机还是原样
造成原因是:我们的string配置按照demo写在了res/values/下,
3.1.2的lib.5plus.base-release.aar自带字符串资源只有values(中文) 和values-en(英文),编译时资源合并顺序最后写入自定义配置,可以生效。
而新版的lib.5plus.base-release.aar自带字符串资源有values(默认,英文?) 和values-en(英文),以及values-zh(中文)。
因为values的定义发生了变化,而离线打包sdk中demo使用的还是values,因此我们配置的项目,只会覆盖value的默认项目,并不会覆盖values-zh
而实际上真机因为是中文系统会默认使用values-zh,导致使用的字符串dcloud_privacy_prompt_message还是lib.5plus.base-release.aar中的默认值,其中对应的href是"",自然到了浏览器就是空值
解决办法:
res下的values目录复制一份更名为values-zh
这个问题应该是官方想要增强多语言的支持能力修订了相关的定义导致。
因为过于诡异,而且更诡异的是社区完全看不到类似的问题,特此提交一个说明,希望能够帮到有需要的人。
也希望官方能够在后续处理此类问题时兼顾考虑demo和相关配置文档的修订。

Uniapp 添加自定义参数,添加 webpack 插件,用 vue.config.js
实际项目中,我们需要加入一些自定义的参数。比如针对 ENV=production / NODE_ENV=development ,两种编译方式,设置不同的参数。
1、当 ENV=production,api 使用域名 app.example.com
2、当 NODE_ENV=development,api 使用域名 dev.example.com
可以这样实现,在项目根目录下创建文件 vue.config.js,添加如下代码:
const webpack = require('webpack')
module.exports = {
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
"process.env": {
'SERVER_URL': process.env.NODE_ENV == 'production' ?
JSON.stringify('https://app.example.com/') : JSON.stringify('https://dev.example.com/')
}
})
]
}
}
需要调用的地方,直接使用 process.env.SERVER_URL
,比如我在 config.js 中这样:
var config = {
apiUrl: process.env.SERVER_URL 'api/',
}
export default config
webpack 会在编译的时候替换掉 process.env.SERVER_URL,你可以在 dist 输出目录搜索 "example.com",就可以验证是否成功了。
使用Webpack PWA等其他插件
PWA 仅是针对Web发布的技术,chrome,firefox,微软Edge 都支持,而且可以直接加入系统的应用列表,入口和电脑应用一样,方便直接启动。
Webpack 有针对pwa的插件,在 uniapp 下,同样可以再 vue.config.js
中添加,代码参考如下:
注:参考代码里的 CopyWebpackPlugin,是无需编译,直接copy发布用的,也可以参考。
const webpack = require('webpack')
const path = require('path')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
const WebpackPwaManifest = require('webpack-pwa-manifest');
const {
getManifestJson,
parseManifestJson
} = require('@dcloudio/uni-cli-shared/lib/manifest');
const manifest = parseManifestJson(getManifestJson());
module.exports = {
configureWebpack: {
plugins: [
new CopyWebpackPlugin([
{
from: path.join(__dirname, 'src/packages/static'),
to: path.join(__dirname, 'dist', process.env.NODE_ENV === 'production' ? 'build' : 'dev', process.env.UNI_PLATFORM, 'static')
}
]),
new SWPrecacheWebpackPlugin(
{
cacheId: 'bookcapt-cids',
dontCacheBustUrlsMatching: /\.\w{8}\./,
filename: 'service-worker.js',
minify: false,
navigateFallback: manifest.h5.router.base,
staticFileGlobsIgnorePatterns: [/\.map$/, /manifest\.json$/, /automator\.json/]
}
),
new WebpackPwaManifest({
name: '布克船长CIDAS',
short_name: '布克船长CIDAS',
description: '布克船长核心能力测评系统(CIDAS)',
background_color: '#f8f8f8',
theme_color: '#f8f8f8',
orientation: "landscape",
display: "standalone",
start_url: manifest.h5.router.base,
icons: [
{
src: path.resolve('src/static/pwa/logo.png'),
sizes: [96, 128, 192],
destination: path.join('assets', 'icons')
}
]
})
]
}
}
实际项目中,我们需要加入一些自定义的参数。比如针对 ENV=production / NODE_ENV=development ,两种编译方式,设置不同的参数。
1、当 ENV=production,api 使用域名 app.example.com
2、当 NODE_ENV=development,api 使用域名 dev.example.com
可以这样实现,在项目根目录下创建文件 vue.config.js,添加如下代码:
const webpack = require('webpack')
module.exports = {
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
"process.env": {
'SERVER_URL': process.env.NODE_ENV == 'production' ?
JSON.stringify('https://app.example.com/') : JSON.stringify('https://dev.example.com/')
}
})
]
}
}
需要调用的地方,直接使用 process.env.SERVER_URL
,比如我在 config.js 中这样:
var config = {
apiUrl: process.env.SERVER_URL 'api/',
}
export default config
webpack 会在编译的时候替换掉 process.env.SERVER_URL,你可以在 dist 输出目录搜索 "example.com",就可以验证是否成功了。
使用Webpack PWA等其他插件
PWA 仅是针对Web发布的技术,chrome,firefox,微软Edge 都支持,而且可以直接加入系统的应用列表,入口和电脑应用一样,方便直接启动。
Webpack 有针对pwa的插件,在 uniapp 下,同样可以再 vue.config.js
中添加,代码参考如下:
注:参考代码里的 CopyWebpackPlugin,是无需编译,直接copy发布用的,也可以参考。
const webpack = require('webpack')
const path = require('path')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
const WebpackPwaManifest = require('webpack-pwa-manifest');
const {
getManifestJson,
parseManifestJson
} = require('@dcloudio/uni-cli-shared/lib/manifest');
const manifest = parseManifestJson(getManifestJson());
module.exports = {
configureWebpack: {
plugins: [
new CopyWebpackPlugin([
{
from: path.join(__dirname, 'src/packages/static'),
to: path.join(__dirname, 'dist', process.env.NODE_ENV === 'production' ? 'build' : 'dev', process.env.UNI_PLATFORM, 'static')
}
]),
new SWPrecacheWebpackPlugin(
{
cacheId: 'bookcapt-cids',
dontCacheBustUrlsMatching: /\.\w{8}\./,
filename: 'service-worker.js',
minify: false,
navigateFallback: manifest.h5.router.base,
staticFileGlobsIgnorePatterns: [/\.map$/, /manifest\.json$/, /automator\.json/]
}
),
new WebpackPwaManifest({
name: '布克船长CIDAS',
short_name: '布克船长CIDAS',
description: '布克船长核心能力测评系统(CIDAS)',
background_color: '#f8f8f8',
theme_color: '#f8f8f8',
orientation: "landscape",
display: "standalone",
start_url: manifest.h5.router.base,
icons: [
{
src: path.resolve('src/static/pwa/logo.png'),
sizes: [96, 128, 192],
destination: path.join('assets', 'icons')
}
]
})
]
}
}
PWA页面见:https://app.readlevel.com/exam/#/
收起阅读 »
[uni-app]-安卓原生app特有的bug描述
[uni-app]-安卓原生app,在彼显现(v-if)此隐藏(v-else)的两个结构相似的doc对象中,在相同位置的同类型组件(特别是如 image、input 等这些组件)会进行复用,复用组件的v-if属性和样式会进行混用,动态切换的时候就会出现各种缺陷(明明是显示的组件其特有功能失效、呈现样式与预期的不一样,但微信小程序和苹果app的功能和呈现样式都正常)。
<!-- 动态切换loginStatus的时候 图片圆角与预期的不一样 -->
<image v-if="loginStatus" class="head-img-1" />
<image v-else class="head-img-2" />
<style>
.head-img-1 {
width: 80rpx;
height: 80rpx;
background-color: #999999;
border-radius: 40rpx;
}
.head-img-2 {
width: 80rpx;
height: 80rpx;
background-color: #999999;
border-radius: 8rpx;
}
</style>
[uni-app]-安卓原生app,在彼显现(v-if)此隐藏(v-else)的两个结构相似的doc对象中,在相同位置的同类型组件(特别是如 image、input 等这些组件)会进行复用,复用组件的v-if属性和样式会进行混用,动态切换的时候就会出现各种缺陷(明明是显示的组件其特有功能失效、呈现样式与预期的不一样,但微信小程序和苹果app的功能和呈现样式都正常)。
<!-- 动态切换loginStatus的时候 图片圆角与预期的不一样 -->
<image v-if="loginStatus" class="head-img-1" />
<image v-else class="head-img-2" />
<style>
.head-img-1 {
width: 80rpx;
height: 80rpx;
background-color: #999999;
border-radius: 40rpx;
}
.head-img-2 {
width: 80rpx;
height: 80rpx;
background-color: #999999;
border-radius: 8rpx;
}
</style>
收起阅读 »