在manifest,json中填入的密钥,打包成apk后被解包,在AndroidManifest.xml中可以明文看到
如题,请问这个问题作为开发者要怎么规避?
在manifest,json中填入的密钥,打包成apk后被解包,在AndroidManifest.xml中可以明文看到
如题,请问这个问题作为开发者要怎么规避?
在manifest,json中填入的密钥,打包成apk后被解包,在AndroidManifest.xml中可以明文看到
经纬度圆形围栏校验
<el-popover
placement="right"
width="400"
trigger="click">
<el-table :data="gridData">
<el-table-column width="150" property="date" label="日期"></el-table-column>
<el-table-column width="100" property="name" label="姓名"></el-table-column>
<el-table-column width="300" property="address" label="地址"></el-table-column>
</el-table>
<el-button slot="reference">click 激活</el-button>
</el-popover>
// 计算点到圆心的距离的函数
function distance(lat1, lng1, lat2, lng2) {
const radius = 6378137.0; // 地球半径
const rad = Math.PI / 180.0;
const lat1rad = lat1 rad;
const lat2rad = lat2 rad;
const a = Math.sin(lat1rad) Math.sin(lat2rad) + Math.cos(lat1rad) Math.cos(lat2rad) Math.cos((lng2 - lng1) rad);
return radius * Math.acos(a);
}
// 检查点是否在圆内的函数
function isPointInCircle(lat, lng, circleLat, circleLng, radius) {
const d = distance(lat, lng, circleLat, circleLng);
return d <= radius;
}
// 使用示例
const pointLat = 39.9903; // 点的纬度
const pointLng = 116.4814; // 点的经度
const circleLat = 39.9109; // 圆心的纬度
const circleLng = 116.4119; // 圆心的经度
const radius = 1000; // 圆的半径,单位为米
const isInside = isPointInCircle(pointLat, pointLng, circleLat, circleLng, radius);
console.log(isInside ? '点在圆内' : '点在圆外');
<dv-scroll-board :config="config" style="width:500px;height:220px" /> headerBGC oddRowBGC evenRowBGC waitTime rowNum
时间禁用
timeRange: '', // 绑定值
pickerOptions: {
// 时间跨度限制为2天
onPick: time => {
if (time.minDate && !time.maxDate) {
// 当选择开始日期时,设置结束日期的最小值为开始日期
this.timeRange = time.minDate;
} else if (time.maxDate) {
// 当选择结束日期时,清除开始日期的值
this.timeRange = '';
}
},
disabledDate: time => {
const today = new Date(); // 当前日期
if (this.timeRange) {
// 如果设置了开始日期,则禁止选择今天的日期之前的日期作为结束日期
return time.getTime() < today.getTime();
} else {
// 如果没有设置开始日期,则允许选择任何日期(这里可以根据需求自定义)
return false;
}
}
}
- @@@@
- <el-upload
- action="https://jsonplaceholder.typicode.com/posts/"
- list-type="picture-card"
- on-preview="handlePictureCardPreview"
- on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
<script>
export default {
data() {
return {
dialogImageUrl: '',
dialogVisible: false
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
}
}
}
</script>
<el-popover
placement="right"
width="400"
trigger="click">
<el-table :data="gridData">
<el-table-column width="150" property="date" label="日期"></el-table-column>
<el-table-column width="100" property="name" label="姓名"></el-table-column>
<el-table-column width="300" property="address" label="地址"></el-table-column>
</el-table>
<el-button slot="reference">click 激活</el-button>
</el-popover>
// 计算点到圆心的距离的函数
function distance(lat1, lng1, lat2, lng2) {
const radius = 6378137.0; // 地球半径
const rad = Math.PI / 180.0;
const lat1rad = lat1 rad;
const lat2rad = lat2 rad;
const a = Math.sin(lat1rad) Math.sin(lat2rad) + Math.cos(lat1rad) Math.cos(lat2rad) Math.cos((lng2 - lng1) rad);
return radius * Math.acos(a);
}
// 检查点是否在圆内的函数
function isPointInCircle(lat, lng, circleLat, circleLng, radius) {
const d = distance(lat, lng, circleLat, circleLng);
return d <= radius;
}
// 使用示例
const pointLat = 39.9903; // 点的纬度
const pointLng = 116.4814; // 点的经度
const circleLat = 39.9109; // 圆心的纬度
const circleLng = 116.4119; // 圆心的经度
const radius = 1000; // 圆的半径,单位为米
const isInside = isPointInCircle(pointLat, pointLng, circleLat, circleLng, radius);
console.log(isInside ? '点在圆内' : '点在圆外');
<dv-scroll-board :config="config" style="width:500px;height:220px" /> headerBGC oddRowBGC evenRowBGC waitTime rowNum
时间禁用
timeRange: '', // 绑定值
pickerOptions: {
// 时间跨度限制为2天
onPick: time => {
if (time.minDate && !time.maxDate) {
// 当选择开始日期时,设置结束日期的最小值为开始日期
this.timeRange = time.minDate;
} else if (time.maxDate) {
// 当选择结束日期时,清除开始日期的值
this.timeRange = '';
}
},
disabledDate: time => {
const today = new Date(); // 当前日期
if (this.timeRange) {
// 如果设置了开始日期,则禁止选择今天的日期之前的日期作为结束日期
return time.getTime() < today.getTime();
} else {
// 如果没有设置开始日期,则允许选择任何日期(这里可以根据需求自定义)
return false;
}
}
}
- @@@@
- <el-upload
- action="https://jsonplaceholder.typicode.com/posts/"
- list-type="picture-card"
- on-preview="handlePictureCardPreview"
- on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
<script>
export default {
data() {
return {
dialogImageUrl: '',
dialogVisible: false
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
}
}
}
</script>
【安卓权限说明顶部蒙层】uniapp(vue2)项目全局监听权限,HBuilderX (4.0+) android 平台支持;上架华为应用市场审核所需
安卓离线打包(本地打包)需要添加一些sdk,具体看这篇文章https://ask.dcloud.net.cn/article/41380
更新时间:2024-08-12 14:29
旧版时间:2024-08-12 14:06
测试部分,可能有bug
目前发现bug未解决
1、保存代码,代码热更新后,触发监听会报Error: [JS Framework] Failed to receiveTasks, instance (1) is not available.这个错误,重新编译正常
模拟器效果截图
permissionListener.js
/**
* @author cai
* @time 2024-08-12 14:29
* uni.createRequestPermissionListener()
* 文档地址:https://uniapp.dcloud.net.cn/api/system/create-request-permission-listener.html
* 注意:HBuilderX (4.0+) android 平台支持;HBuilderX 4.01 Vue2项目需要使用自定义基座测试监听权限申请的功能,标准基座暂不支持测试。
*/
// #ifndef APP
export default null;
// #endif
// #ifdef APP
const { osName } = uni.getSystemInfoSync();
let permissionListener = null;
// 是安卓平台,同时有uni.createRequestPermissionListener这个api
if (osName === "android" && uni.createRequestPermissionListener) {
permissionListener = uni.createRequestPermissionListener();
}
let canRunListener = true; // 是否可以执行所有监听方法
let canStopListener = true; // 是否可以执行取消所有监听方法,避免唤起权限会触发App.vue的onHide生命周期
const permissionEnums = {
"ACCESS_COARSE_LOCATION": {
name: "定位",
explain: "展示附近店铺、填写收货地址等相关功能"
},
"ACCESS_FINE_LOCATION": {
name: "定位",
explain: "展示附近店铺、填写收货地址等相关功能"
},
"READ_EXTERNAL_STORAGE": {
name: "存储",
explain: "上传图片、上传视频等相关功能"
},
"CAMERA": {
name: "相机",
explain: "扫二维码、拍摄图片等相关功能"
},
"WRITE_EXTERNAL_STORAGE": {
name: "存储",
explain: "把图片保存到相册等相关功能"
}
}
/**
* 权限说明文字
* @param {String} = permissionName 例如:ACCESS_COARSE_LOCATION
*/
const texts = (permissionName) => {
let title = "";
let content = "";
let permissionInfo = permissionEnums[permissionName] || null;
if (permissionInfo) {
const { name, explain } = permissionInfo;
title = `${name}权限使用说明`;
content = `将获取${name}权限,用于${explain}`;
} else {
title = "";
content = "";
}
return {
title,
content
}
};
/**
* 绘画顶部权限说明
* 文档地址:https://www.html5plus.org/doc/zh_cn/nativeobj.html
* @function drawView title标题,content描述使用说明
* @function hideView 隐藏顶部权限说明
*/
let view = null;
const drawView = ({ title, content }) => {
console.log("drawView方法的参数值:", title, content);
if (view || !title || !content) return; // 没有标题和内容则return出去
const { windowTop, windowWidth, statusBarHeight } = uni.getSystemInfoSync();
const topHeight = windowTop + statusBarHeight;
const distance = {
box: 10, // 盒子距离视图两边的距离
text: 20 // 文字距离视图两边的距离
}
// 标题的相关样式
const titleStyle = {
size: 16,
height: 16,
top: `${topHeight + 22}`,
color: "#000",
}
// 内容的相关样式
const contentStyle = {
size: 14,
height: 0,
top: `${parseInt(titleStyle.top) + titleStyle.height + 6}`,
color: "#656563",
}
const contentLength = content.length; // 权限说明内容文字长度
const contentWidth = windowWidth - distance.text * 2; // 内容的宽度
const contentRowCount = Math.floor(contentWidth / contentStyle.size); // 一行占几个文字
const contentRows = Math.ceil(contentLength / contentRowCount); // 当前内容占几行
contentStyle.height = contentRows * (contentStyle.size + 4); // 内容的高度
/**
* @description 计算盒子的高度
* 获取content到盒子顶部距离:parseInt(contentStyle.top) - topHeight - distance.box
* content的高度:contentStyle.height
* 获取content到盒子底部的距离:(distance.text - distance.box)
*/
const boxHeight = (parseInt(contentStyle.top) - topHeight - distance.box) + contentStyle.height + (distance.text - distance.box);
view = new plus.nativeObj.View('per-modal', {
top: '0',
left: '0',
width: '100%',
backgroundColor: 'rgba(0,0,0,0.2)'
})
view.drawRect({
color: '#fff',
radius: '5px',
}, {
top: `${topHeight + distance.box}px`,
left: `${distance.box}px`,
right: `${distance.box}px`,
height: `${boxHeight}px`
})
view.drawText(title, {
top: `${titleStyle.top}px`,
left: `${distance.text}px`,
left: `${distance.text}px`,
height: `${titleStyle.height}px`
}, {
size: `${titleStyle.size}px`,
align: "left",
color: titleStyle.color,
weight: "bold"
})
view.drawText(content, {
top: `${contentStyle.top}px`,
left: `${distance.text}px`,
right: `${distance.text}px`,
height: `${contentStyle.height}px`,
}, {
size: `${contentStyle.size}px`,
lineSpacing: "2px",
align: "left",
color: contentStyle.color,
verticalAlign: "top",
whiteSpace: "normal"
})
let timer = setTimeout(() => {
view && view.show();
clearTimeout(timer);
timer = null;
}, 200)
}
// 关闭顶部权限说明
const hideView = () => {
if (view) {
view.hide();
view = null;
}
}
// 监听权限方法
const listenerFunc = () => {
stopFunc(); // 取消所有监听方法
if (canRunListener && permissionListener) {
let permissionName = ""; // 权限名称
let hasConfirm = false; // 是否有权限弹窗(触发permissionListener.onConfirm这个回调)
canRunListener = false;
canStopListener = false;
// 监听申请系统权限
permissionListener.onRequest((e) => {
console.log("permissionListener.onRequest回调:", e);
if (Array.isArray(e) && e.length > 0) {
const stringToArray = e[0].split(".");
permissionName = stringToArray[stringToArray.length - 1];
console.log("权限名称:", permissionName);
}
});
// 监听弹出系统权限授权框
permissionListener.onConfirm((e) => {
console.log("permissionListener.onConfirm回调:", e);
hasConfirm = true;
if (permissionName) {
drawView(texts(permissionName));
}
});
// 监听权限申请完成
permissionListener.onComplete((e) => {
console.log("permissionListener.onComplete回调:", e);
// e.length === 0:权限列表无值,则不继续做相对逻辑
if (e.length === 0) return;
let name = ""; // 权限名称
let explain = ""; // 权限说明
if (permissionName && permissionEnums[permissionName]) {
name = permissionEnums[permissionName].name;
explain = permissionEnums[permissionName].explain;
}
const Manifest = plus.android.importClass("android.Manifest");
const MainActivity = plus.android.runtimeMainActivity();
const permissionStatus = MainActivity.checkSelfPermission(Manifest.permission[permissionName]);
console.log("当前权限状态:", permissionStatus);
/**
* @description 永久拒绝该权限,则引导用户前往设置页
* permissionStatus != 0:权限状态是拒绝
* !hasConfirm:没有permissionListener.onConfirm这个回调
*/
if (permissionStatus != 0 && !hasConfirm && name && explain) {
uni.showModal({
title: "温馨提示",
content: `开启${name}权限后,才能${explain}`,
showCancel: true,
confirmText: "去设置",
success: (res) => {
if (res.confirm) {
uni.openAppAuthorizeSetting();
}
}
})
return;
}
canStopListener = true;
hideView();
});
}
}
// 取消所有监听方法
const stopFunc = () => {
if (canStopListener && permissionListener) {
console.log("执行permissionListener.stop()方法");
canRunListener = true;
hideView();
permissionListener.stop();
}
}
let exportObj = null;
if (permissionListener) {
exportObj = {
listenerFunc,
stopFunc
};
} else {
exportObj = null;
}
export default exportObj;
// #endif
App.vue
/**
* @author cai
* @time 2024-07-24 10:52
*/
import permissionListener from "@/utils/permissionListener.js";
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
permissionListener && permissionListener.listenerFunc();
console.log('App Show')
},
onHide: function() {
permissionListener && permissionListener.stopFunc();
console.log('App Hide')
}
}
↓↓↓ 各位大佬点点赞
安卓离线打包(本地打包)需要添加一些sdk,具体看这篇文章https://ask.dcloud.net.cn/article/41380
更新时间:2024-08-12 14:29
旧版时间:2024-08-12 14:06
测试部分,可能有bug
目前发现bug未解决
1、保存代码,代码热更新后,触发监听会报Error: [JS Framework] Failed to receiveTasks, instance (1) is not available.这个错误,重新编译正常
模拟器效果截图
permissionListener.js
/**
* @author cai
* @time 2024-08-12 14:29
* uni.createRequestPermissionListener()
* 文档地址:https://uniapp.dcloud.net.cn/api/system/create-request-permission-listener.html
* 注意:HBuilderX (4.0+) android 平台支持;HBuilderX 4.01 Vue2项目需要使用自定义基座测试监听权限申请的功能,标准基座暂不支持测试。
*/
// #ifndef APP
export default null;
// #endif
// #ifdef APP
const { osName } = uni.getSystemInfoSync();
let permissionListener = null;
// 是安卓平台,同时有uni.createRequestPermissionListener这个api
if (osName === "android" && uni.createRequestPermissionListener) {
permissionListener = uni.createRequestPermissionListener();
}
let canRunListener = true; // 是否可以执行所有监听方法
let canStopListener = true; // 是否可以执行取消所有监听方法,避免唤起权限会触发App.vue的onHide生命周期
const permissionEnums = {
"ACCESS_COARSE_LOCATION": {
name: "定位",
explain: "展示附近店铺、填写收货地址等相关功能"
},
"ACCESS_FINE_LOCATION": {
name: "定位",
explain: "展示附近店铺、填写收货地址等相关功能"
},
"READ_EXTERNAL_STORAGE": {
name: "存储",
explain: "上传图片、上传视频等相关功能"
},
"CAMERA": {
name: "相机",
explain: "扫二维码、拍摄图片等相关功能"
},
"WRITE_EXTERNAL_STORAGE": {
name: "存储",
explain: "把图片保存到相册等相关功能"
}
}
/**
* 权限说明文字
* @param {String} = permissionName 例如:ACCESS_COARSE_LOCATION
*/
const texts = (permissionName) => {
let title = "";
let content = "";
let permissionInfo = permissionEnums[permissionName] || null;
if (permissionInfo) {
const { name, explain } = permissionInfo;
title = `${name}权限使用说明`;
content = `将获取${name}权限,用于${explain}`;
} else {
title = "";
content = "";
}
return {
title,
content
}
};
/**
* 绘画顶部权限说明
* 文档地址:https://www.html5plus.org/doc/zh_cn/nativeobj.html
* @function drawView title标题,content描述使用说明
* @function hideView 隐藏顶部权限说明
*/
let view = null;
const drawView = ({ title, content }) => {
console.log("drawView方法的参数值:", title, content);
if (view || !title || !content) return; // 没有标题和内容则return出去
const { windowTop, windowWidth, statusBarHeight } = uni.getSystemInfoSync();
const topHeight = windowTop + statusBarHeight;
const distance = {
box: 10, // 盒子距离视图两边的距离
text: 20 // 文字距离视图两边的距离
}
// 标题的相关样式
const titleStyle = {
size: 16,
height: 16,
top: `${topHeight + 22}`,
color: "#000",
}
// 内容的相关样式
const contentStyle = {
size: 14,
height: 0,
top: `${parseInt(titleStyle.top) + titleStyle.height + 6}`,
color: "#656563",
}
const contentLength = content.length; // 权限说明内容文字长度
const contentWidth = windowWidth - distance.text * 2; // 内容的宽度
const contentRowCount = Math.floor(contentWidth / contentStyle.size); // 一行占几个文字
const contentRows = Math.ceil(contentLength / contentRowCount); // 当前内容占几行
contentStyle.height = contentRows * (contentStyle.size + 4); // 内容的高度
/**
* @description 计算盒子的高度
* 获取content到盒子顶部距离:parseInt(contentStyle.top) - topHeight - distance.box
* content的高度:contentStyle.height
* 获取content到盒子底部的距离:(distance.text - distance.box)
*/
const boxHeight = (parseInt(contentStyle.top) - topHeight - distance.box) + contentStyle.height + (distance.text - distance.box);
view = new plus.nativeObj.View('per-modal', {
top: '0',
left: '0',
width: '100%',
backgroundColor: 'rgba(0,0,0,0.2)'
})
view.drawRect({
color: '#fff',
radius: '5px',
}, {
top: `${topHeight + distance.box}px`,
left: `${distance.box}px`,
right: `${distance.box}px`,
height: `${boxHeight}px`
})
view.drawText(title, {
top: `${titleStyle.top}px`,
left: `${distance.text}px`,
left: `${distance.text}px`,
height: `${titleStyle.height}px`
}, {
size: `${titleStyle.size}px`,
align: "left",
color: titleStyle.color,
weight: "bold"
})
view.drawText(content, {
top: `${contentStyle.top}px`,
left: `${distance.text}px`,
right: `${distance.text}px`,
height: `${contentStyle.height}px`,
}, {
size: `${contentStyle.size}px`,
lineSpacing: "2px",
align: "left",
color: contentStyle.color,
verticalAlign: "top",
whiteSpace: "normal"
})
let timer = setTimeout(() => {
view && view.show();
clearTimeout(timer);
timer = null;
}, 200)
}
// 关闭顶部权限说明
const hideView = () => {
if (view) {
view.hide();
view = null;
}
}
// 监听权限方法
const listenerFunc = () => {
stopFunc(); // 取消所有监听方法
if (canRunListener && permissionListener) {
let permissionName = ""; // 权限名称
let hasConfirm = false; // 是否有权限弹窗(触发permissionListener.onConfirm这个回调)
canRunListener = false;
canStopListener = false;
// 监听申请系统权限
permissionListener.onRequest((e) => {
console.log("permissionListener.onRequest回调:", e);
if (Array.isArray(e) && e.length > 0) {
const stringToArray = e[0].split(".");
permissionName = stringToArray[stringToArray.length - 1];
console.log("权限名称:", permissionName);
}
});
// 监听弹出系统权限授权框
permissionListener.onConfirm((e) => {
console.log("permissionListener.onConfirm回调:", e);
hasConfirm = true;
if (permissionName) {
drawView(texts(permissionName));
}
});
// 监听权限申请完成
permissionListener.onComplete((e) => {
console.log("permissionListener.onComplete回调:", e);
// e.length === 0:权限列表无值,则不继续做相对逻辑
if (e.length === 0) return;
let name = ""; // 权限名称
let explain = ""; // 权限说明
if (permissionName && permissionEnums[permissionName]) {
name = permissionEnums[permissionName].name;
explain = permissionEnums[permissionName].explain;
}
const Manifest = plus.android.importClass("android.Manifest");
const MainActivity = plus.android.runtimeMainActivity();
const permissionStatus = MainActivity.checkSelfPermission(Manifest.permission[permissionName]);
console.log("当前权限状态:", permissionStatus);
/**
* @description 永久拒绝该权限,则引导用户前往设置页
* permissionStatus != 0:权限状态是拒绝
* !hasConfirm:没有permissionListener.onConfirm这个回调
*/
if (permissionStatus != 0 && !hasConfirm && name && explain) {
uni.showModal({
title: "温馨提示",
content: `开启${name}权限后,才能${explain}`,
showCancel: true,
confirmText: "去设置",
success: (res) => {
if (res.confirm) {
uni.openAppAuthorizeSetting();
}
}
})
return;
}
canStopListener = true;
hideView();
});
}
}
// 取消所有监听方法
const stopFunc = () => {
if (canStopListener && permissionListener) {
console.log("执行permissionListener.stop()方法");
canRunListener = true;
hideView();
permissionListener.stop();
}
}
let exportObj = null;
if (permissionListener) {
exportObj = {
listenerFunc,
stopFunc
};
} else {
exportObj = null;
}
export default exportObj;
// #endif
App.vue
/**
* @author cai
* @time 2024-07-24 10:52
*/
import permissionListener from "@/utils/permissionListener.js";
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
permissionListener && permissionListener.listenerFunc();
console.log('App Show')
},
onHide: function() {
permissionListener && permissionListener.stopFunc();
console.log('App Hide')
}
}
↓↓↓ 各位大佬点点赞
收起阅读 »小程序开发需求,找公司或工作室首次开发和长期维护
微信小程序开发需求,前端+运营端+服务器端
前端uniapp,运营管理端H5, 后端uniCloud/或其他nodejs框架
找公司或工作室首次开发,前端页面完成了大概70%,需要按照功能/页面细化及对接后端,并完成未完成的页面部分。后端未有,可使用uniCloud-admin。
首次开发后,可合作长期维护迭代,因此需要稳定的公司或者工作室。
具体需求见附件。
有合适的公司或工作室请留下联系方式或email到618457@qq.com。
微信小程序开发需求,前端+运营端+服务器端
前端uniapp,运营管理端H5, 后端uniCloud/或其他nodejs框架
找公司或工作室首次开发,前端页面完成了大概70%,需要按照功能/页面细化及对接后端,并完成未完成的页面部分。后端未有,可使用uniCloud-admin。
首次开发后,可合作长期维护迭代,因此需要稳定的公司或者工作室。
具体需求见附件。
有合适的公司或工作室请留下联系方式或email到618457@qq.com。
android 和 ios app 打开唤起支付宝支付就差个s,无语...
var alipay=this.iosOrAndroid()?'alipay':'alipays'
plus.runtime.openURL(alipay+"://platformapi/startapp?appId=20000067&url=" +
encodeURIComponent(this.shareUrl('/pages/index/payMember1?record_id='+res.data.record_id+'&level='+this.parmar.level+'&days='+this.parmar.days)))
var alipay=this.iosOrAndroid()?'alipay':'alipays'
plus.runtime.openURL(alipay+"://platformapi/startapp?appId=20000067&url=" +
encodeURIComponent(this.shareUrl('/pages/index/payMember1?record_id='+res.data.record_id+'&level='+this.parmar.level+'&days='+this.parmar.days)))
收起阅读 »
uni-app-x webview组件不支持获取网页内容解决方案
问题
uni-app-x的webview组件貌似少了很多的接口,其中就包括获取网页信息,包括dom节点等等
思路
当webview加载完毕之后使用webview上下文向页面注入uni.webview.1.5.5.js代码,然后再注入一段操作dom的js代码,并将结果通过postmessage接口传回uts。话不多说,直接上代码
<template>
<web-view id="web-view" :src="url" :webview-styles="styles" @load="Load" @message="Message"></web-view>
</template>
<script>
let fs = uni.getFileSystemManager()
export default {
data() {
return {
url: '',
src: '',
styles: { progress: { color: "#07C160" } },
webviewContext: null as WebviewContext | null,
javascriptString: `
!function(document) {
var title = document.title;
uni.webView.postMessage({
data: {
documentTitle: title
}
})
}(document)
`
};
},
onLoad(options : OnLoadOptions) {
// 接受url参数
this.url = options["url"] ?? ""
},
onReady() {
// 创建webview上下文对象
this.webviewContext = uni.createWebviewContext('web-view', this)
},
methods: {
Load(e : UniWebViewLoadEvent) {
// 页面重新加载时获取页面链接地址
this.src = e.detail.src
// 读取库文件内容
fs.readFile({
encoding: 'utf-8',
filePath: '/hybrid/html/uni.webview.1.5.5.js',
success: (res : ReadFileSuccessResult) => {
// 将库文件代码和执行代码注入到网页
this.webviewContext?.evalJS(res.data + this.javascriptString)
}
} as ReadFileOptions)
},
// 接收网页传入的消息
Message(e : UniWebViewMessageEvent) {
let documentTitle = e.detail.data[0]['documentTitle'] as string
if (documentTitle == '') {
documentTitle = this.src
}
// 设置网页标题
uni.setNavigationBarTitle({
title: documentTitle
})
}
}
}
</script>
<style lang="scss">
</style>
问题
uni-app-x的webview组件貌似少了很多的接口,其中就包括获取网页信息,包括dom节点等等
思路
当webview加载完毕之后使用webview上下文向页面注入uni.webview.1.5.5.js代码,然后再注入一段操作dom的js代码,并将结果通过postmessage接口传回uts。话不多说,直接上代码
<template>
<web-view id="web-view" :src="url" :webview-styles="styles" @load="Load" @message="Message"></web-view>
</template>
<script>
let fs = uni.getFileSystemManager()
export default {
data() {
return {
url: '',
src: '',
styles: { progress: { color: "#07C160" } },
webviewContext: null as WebviewContext | null,
javascriptString: `
!function(document) {
var title = document.title;
uni.webView.postMessage({
data: {
documentTitle: title
}
})
}(document)
`
};
},
onLoad(options : OnLoadOptions) {
// 接受url参数
this.url = options["url"] ?? ""
},
onReady() {
// 创建webview上下文对象
this.webviewContext = uni.createWebviewContext('web-view', this)
},
methods: {
Load(e : UniWebViewLoadEvent) {
// 页面重新加载时获取页面链接地址
this.src = e.detail.src
// 读取库文件内容
fs.readFile({
encoding: 'utf-8',
filePath: '/hybrid/html/uni.webview.1.5.5.js',
success: (res : ReadFileSuccessResult) => {
// 将库文件代码和执行代码注入到网页
this.webviewContext?.evalJS(res.data + this.javascriptString)
}
} as ReadFileOptions)
},
// 接收网页传入的消息
Message(e : UniWebViewMessageEvent) {
let documentTitle = e.detail.data[0]['documentTitle'] as string
if (documentTitle == '') {
documentTitle = this.src
}
// 设置网页标题
uni.setNavigationBarTitle({
title: documentTitle
})
}
}
}
</script>
<style lang="scss">
</style>
收起阅读 »
zui-svg-icon自动生成icon
做了个监听文件改动的webpack插件,监听 /assets/svg-icons 下的文件改动,自动执行 npm run svgicon
就不用每次新增icon都跑一遍脚本
文件一: 根目录下创建:build/icon-watcher.js
const fs = require('fs');
const path = require('path');
const {
exec
} = require('child_process');
let timer = null;
const watchDir = path.resolve(__dirname, '../assets/svg-icons');
const projectRoot = path.resolve(__dirname, '../');
class IconWatcherPlugin {
apply(compiler) {
compiler.hooks.afterEmit.tap('IconWatcherPlugin', () => {
console.log('zui-svg-icon 开始监听/assets/svg-icons文件改动')
fs.watch(watchDir, {
recursive: true
}, (eventType, filename) => {
if (filename) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
console.log(`zui-svg-icon 改动类型: ${eventType}`);
console.log(`zui-svg-icon 文件名: ${filename}`);
exec('npm run svgicon', {
cwd: projectRoot
}, (error, stdout, stderr) => {
if (error) {
console.error(`zui-svg-icon exec error: ${error}`);
console.error(`zui-svg-icon stderr: ${stderr}`);
return;
}
console.log(`zui-svg-icon stdout: ${stdout}`);
});
}, 500)
}
});
});
}
}
module.exports = IconWatcherPlugin;
vue.config.js中引入
javascript
const IconWatcherPlugin = require('./build/icon-watcher');
module.exports = {
// ....
configureWebpack: {
plugins: [new IconWatcherPlugin()],
}
}
package.json中配置脚本
json
{
"scripts": {
"svgicon": "node ./uni_modules/zui-svg-icon/tools/generate-svg-icon.js"
}
}
做了个监听文件改动的webpack插件,监听 /assets/svg-icons 下的文件改动,自动执行 npm run svgicon
就不用每次新增icon都跑一遍脚本
文件一: 根目录下创建:build/icon-watcher.js
const fs = require('fs');
const path = require('path');
const {
exec
} = require('child_process');
let timer = null;
const watchDir = path.resolve(__dirname, '../assets/svg-icons');
const projectRoot = path.resolve(__dirname, '../');
class IconWatcherPlugin {
apply(compiler) {
compiler.hooks.afterEmit.tap('IconWatcherPlugin', () => {
console.log('zui-svg-icon 开始监听/assets/svg-icons文件改动')
fs.watch(watchDir, {
recursive: true
}, (eventType, filename) => {
if (filename) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
console.log(`zui-svg-icon 改动类型: ${eventType}`);
console.log(`zui-svg-icon 文件名: ${filename}`);
exec('npm run svgicon', {
cwd: projectRoot
}, (error, stdout, stderr) => {
if (error) {
console.error(`zui-svg-icon exec error: ${error}`);
console.error(`zui-svg-icon stderr: ${stderr}`);
return;
}
console.log(`zui-svg-icon stdout: ${stdout}`);
});
}, 500)
}
});
});
}
}
module.exports = IconWatcherPlugin;
vue.config.js中引入
javascript
const IconWatcherPlugin = require('./build/icon-watcher');
module.exports = {
// ....
configureWebpack: {
plugins: [new IconWatcherPlugin()],
}
}
package.json中配置脚本
json
{
"scripts": {
"svgicon": "node ./uni_modules/zui-svg-icon/tools/generate-svg-icon.js"
}
}
收起阅读 »
hbuilderx开发的app获取公钥和MD5的方法
阿里云提示需要安装jadx-gui和使用mac来获取app的公钥和MD5这些信息。
这样就比较麻烦了,使用uniapp开发就是为了跨系统开发,假如还需要mac或jadx-gui,就不灵活了。
所以这里建议使用下面方式来获取公钥和md5值
ios查询方法:
https://www.yunedit.com/iosmd5
android查询方法:
https://www.yunedit.com/androidmd5
阿里云提示需要安装jadx-gui和使用mac来获取app的公钥和MD5这些信息。
这样就比较麻烦了,使用uniapp开发就是为了跨系统开发,假如还需要mac或jadx-gui,就不灵活了。
所以这里建议使用下面方式来获取公钥和md5值
ios查询方法:
https://www.yunedit.com/iosmd5
android查询方法:
https://www.yunedit.com/androidmd5
收起阅读 »