feat: 增加视频水印和防盗录
264
App.vue
@@ -22,10 +22,15 @@ export default {
|
|||||||
platform: null, // 系统
|
platform: null, // 系统
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
onShow: function() {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
// screenshot.onAntiScreenshot()
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
onLaunch: function (e) {
|
onLaunch: function (e) {
|
||||||
// 检测自动更新
|
// 检测自动更新
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
updata();
|
updata();
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
|
|
||||||
@@ -33,62 +38,62 @@ export default {
|
|||||||
store.commit("setCacheData");
|
store.commit("setCacheData");
|
||||||
|
|
||||||
|
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
const agreed = uni.getStorageSync('privacy_agreed') || (store.state.userInfo && store.state.userInfo.id);
|
const agreed = uni.getStorageSync('privacy_agreed') || (store.state.userInfo && store.state.userInfo.id);
|
||||||
console.log('检测用户是否同意隐私协议', agreed)
|
console.log('检测用户是否同意隐私协议', agreed)
|
||||||
if (agreed) {
|
if (agreed) {
|
||||||
console.log('同意隐私协议,开始调用极光推送', agreed)
|
console.log('同意隐私协议,开始调用极光推送', agreed)
|
||||||
jpushModule.initJPushService();
|
jpushModule.initJPushService();
|
||||||
jpushModule.setLoggerEnable(true);
|
jpushModule.setLoggerEnable(true);
|
||||||
plus.screen.lockOrientation("portrait-primary");
|
plus.screen.lockOrientation("portrait-primary");
|
||||||
// 设置别名
|
// 设置别名
|
||||||
jpushModule.setAlias({
|
jpushModule.setAlias({
|
||||||
'alias': this.lxzl.getUserInfo().userId + '',
|
'alias': this.lxzl.getUserInfo().userId + '',
|
||||||
'sequence': 1
|
'sequence': 1
|
||||||
})
|
})
|
||||||
//监听 极光推送连接状态
|
//监听 极光推送连接状态
|
||||||
this.getNotificationEnabled();
|
this.getNotificationEnabled();
|
||||||
jpushModule.addConnectEventListener(result => {
|
jpushModule.addConnectEventListener(result => {
|
||||||
let connectEnable = result.connectEnable
|
let connectEnable = result.connectEnable
|
||||||
uni.$emit('connectStatusChange', connectEnable)
|
uni.$emit('connectStatusChange', connectEnable)
|
||||||
});
|
});
|
||||||
jpushModule.addNotificationListener(result => { //极光推送的消息通知回调
|
jpushModule.addNotificationListener(result => { //极光推送的消息通知回调
|
||||||
jpushModule.setBadge(0);
|
jpushModule.setBadge(0);
|
||||||
plus.runtime.setBadgeNumber(0);
|
plus.runtime.setBadgeNumber(0);
|
||||||
let notificationEventType = result.notificationEventType
|
let notificationEventType = result.notificationEventType
|
||||||
let woopId = result.extras && result.extras.dataType === 'woop' && result.extras.value;
|
let woopId = result.extras && result.extras.dataType === 'woop' && result.extras.value;
|
||||||
console.log("通知", result, notificationEventType)
|
console.log("通知", result, notificationEventType)
|
||||||
// 点击事件
|
// 点击事件
|
||||||
if (notificationEventType == 'notificationOpened') {
|
if (notificationEventType == 'notificationOpened') {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/taskDetail/taskDetail?' + 'woopId=' + woopId
|
url: '/pages/taskDetail/taskDetail?' + 'woopId=' + woopId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
uni.$on('connectStatusChange', (connectStatus) => {
|
uni.$on('connectStatusChange', (connectStatus) => {
|
||||||
var connectStr = ''
|
var connectStr = ''
|
||||||
if (connectStatus == true) {
|
if (connectStatus == true) {
|
||||||
connectStr = '已连接'
|
connectStr = '已连接'
|
||||||
// this.getRegistrationID()
|
// this.getRegistrationID()
|
||||||
} else {
|
} else {
|
||||||
connectStr = '未连接'
|
connectStr = '未连接'
|
||||||
}
|
}
|
||||||
console.log('监听到了连接状态变化 --- ', connectStr)
|
console.log('监听到了连接状态变化 --- ', connectStr)
|
||||||
this.connectStatus = connectStr
|
this.connectStatus = connectStr
|
||||||
})
|
})
|
||||||
jpushModule.isPushStopped(res => {
|
jpushModule.isPushStopped(res => {
|
||||||
// code 0已停止推送 1未停止推送
|
// code 0已停止推送 1未停止推送
|
||||||
const { code } = res
|
const { code } = res
|
||||||
console.log(res, '安卓连接状态');
|
console.log(res, '安卓连接状态');
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
uni.getSystemInfo({
|
uni.getSystemInfo({
|
||||||
success(res) {
|
success(res) {
|
||||||
Vue.prototype.winWidth = res.screenWidth;
|
Vue.prototype.winWidth = res.screenWidth;
|
||||||
Vue.prototype.winHeight = res.screenHeight;
|
Vue.prototype.winHeight = res.screenHeight;
|
||||||
Vue.prototype.statusBarHeight = res.statusBarHeight;
|
Vue.prototype.statusBarHeight = res.statusBarHeight || 0;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -169,84 +174,83 @@ export default {
|
|||||||
console.log("页面销毁");
|
console.log("页面销毁");
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 处理通知权限
|
// 处理通知权限
|
||||||
getRegistrationID() { //获取registerID
|
getRegistrationID() { //获取registerID
|
||||||
jpushModule.getRegistrationID(result => {
|
jpushModule.getRegistrationID(result => {
|
||||||
let registerID = result.registerID
|
let registerID = result.registerID
|
||||||
console.log(registerID)
|
console.log(registerID)
|
||||||
this.registrationID = registerID
|
this.registrationID = registerID
|
||||||
uni.setStorageSync("registerID", registerID)
|
uni.setStorageSync("registerID", registerID)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getNotificationEnabled() {
|
getNotificationEnabled() {
|
||||||
if (uni.getSystemInfoSync().platform == "ios") {
|
if (uni.getSystemInfoSync().platform == "ios") {
|
||||||
jpushModule.requestNotificationAuthorization((result) => {
|
jpushModule.requestNotificationAuthorization((result) => {
|
||||||
let status = result.status
|
let status = result.status
|
||||||
if (status < 2) {
|
if (status < 2) {
|
||||||
this.noticMsgTool()
|
this.noticMsgTool()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
jpushModule.isNotificationEnabled((result) => { //判断android是否打开权限
|
jpushModule.isNotificationEnabled((result) => { //判断android是否打开权限
|
||||||
if (result.code == 0) { //如果为0则表示 未打开通知权限
|
if (result.code == 0) { //如果为0则表示 未打开通知权限
|
||||||
this.noticMsgTool()
|
this.noticMsgTool()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
noticMsgTool() {
|
noticMsgTool() {
|
||||||
if (uni.getSystemInfoSync().platform == "ios") {
|
if (uni.getSystemInfoSync().platform == "ios") {
|
||||||
//苹果打开对应的通知栏
|
//苹果打开对应的通知栏
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '通知权限开启提醒',
|
title: '通知权限开启提醒',
|
||||||
content: '您还没有开启通知权限,无法接受到消息通知,请前往设置!',
|
content: '您还没有开启通知权限,无法接受到消息通知,请前往设置!',
|
||||||
showCancel: false,
|
showCancel: false,
|
||||||
confirmText: '去设置',
|
confirmText: '去设置',
|
||||||
success: function(res) {
|
success: function(res) {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
var app = plus.ios.invoke('UIApplication', 'sharedApplication');
|
var app = plus.ios.invoke('UIApplication', 'sharedApplication');
|
||||||
var setting = plus.ios.invoke('NSURL', 'URLWithString:', 'app-settings:');
|
var setting = plus.ios.invoke('NSURL', 'URLWithString:', 'app-settings:');
|
||||||
plus.ios.invoke(app, 'openURL:', setting);
|
plus.ios.invoke(app, 'openURL:', setting);
|
||||||
plus.ios.deleteObject(setting);
|
plus.ios.deleteObject(setting);
|
||||||
plus.ios.deleteObject(app);
|
plus.ios.deleteObject(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
//android打开对应的通知栏
|
//android打开对应的通知栏
|
||||||
var main = plus.android.runtimeMainActivity();
|
var main = plus.android.runtimeMainActivity();
|
||||||
var pkName = main.getPackageName();
|
var pkName = main.getPackageName();
|
||||||
var uid = main.getApplicationInfo().plusGetAttribute("uid");
|
var uid = main.getApplicationInfo().plusGetAttribute("uid");
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '通知权限开启提醒',
|
title: '通知权限开启提醒',
|
||||||
content: '您还没有开启通知权限,无法接受到消息通知,请前往设置!',
|
content: '您还没有开启通知权限,无法接受到消息通知,请前往设置!',
|
||||||
showCancel: false,
|
showCancel: false,
|
||||||
confirmText: '去设置',
|
confirmText: '去设置',
|
||||||
success: function(res) {
|
success: function(res) {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
var Intent = plus.android.importClass('android.content.Intent');
|
var Intent = plus.android.importClass('android.content.Intent');
|
||||||
var Build = plus.android.importClass("android.os.Build");
|
var Build = plus.android.importClass("android.os.Build");
|
||||||
//android 8.0引导
|
//android 8.0引导
|
||||||
if (Build.VERSION.SDK_INT >= 26) {
|
if (Build.VERSION.SDK_INT >= 26) {
|
||||||
var intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
|
var intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
|
||||||
intent.putExtra('android.provider.extra.APP_PACKAGE', pkName);
|
intent.putExtra('android.provider.extra.APP_PACKAGE', pkName);
|
||||||
} else if (Build.VERSION.SDK_INT >= 21) { //android 5.0-7.0
|
} else if (Build.VERSION.SDK_INT >= 21) { //android 5.0-7.0
|
||||||
var intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
|
var intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
|
||||||
intent.putExtra("app_package", pkName);
|
intent.putExtra("app_package", pkName);
|
||||||
intent.putExtra("app_uid", uid);
|
intent.putExtra("app_uid", uid);
|
||||||
} else { //(<21)其他--跳转到该应用管理的详情页
|
} else { //(<21)其他--跳转到该应用管理的详情页
|
||||||
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
|
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
|
||||||
intent.setData(uri);
|
intent.setData(uri);
|
||||||
}
|
}
|
||||||
// 跳转到该应用的系统通知设置页
|
// 跳转到该应用的系统通知设置页
|
||||||
main.startActivity(intent);
|
main.startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
"src" : "图片路径"
|
"src" : "图片路径"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versionName" : "2.0.51",
|
"versionName" : "2.0.52",
|
||||||
"versionCode" : 2051,
|
"versionCode" : 2052,
|
||||||
"sassImplementationName" : "node-sass",
|
"sassImplementationName" : "node-sass",
|
||||||
"app-plus" : {
|
"app-plus" : {
|
||||||
"nvueCompiler" : "uni-app",
|
"nvueCompiler" : "uni-app",
|
||||||
|
|||||||
20
package-lock.json
generated
@@ -11,7 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"e-peanut": "file:",
|
"e-peanut": "file:",
|
||||||
"edu-core": "file:../edu-core",
|
"edu-core": "git+https://git.nuttyreading.com/chenghuan/edu-core.git#v1.0.14",
|
||||||
"element-plus": "^2.9.6",
|
"element-plus": "^2.9.6",
|
||||||
"epubjs": "^0.3.93",
|
"epubjs": "^0.3.93",
|
||||||
"jquery": "^2.2.4",
|
"jquery": "^2.2.4",
|
||||||
@@ -23,11 +23,6 @@
|
|||||||
" ../edu-core": {
|
" ../edu-core": {
|
||||||
"extraneous": true
|
"extraneous": true
|
||||||
},
|
},
|
||||||
"../edu-core": {
|
|
||||||
"version": "1.0.13",
|
|
||||||
"license": "ISC",
|
|
||||||
"devDependencies": {}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/helper-string-parser": {
|
"node_modules/@babel/helper-string-parser": {
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
"resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||||
@@ -440,8 +435,9 @@
|
|||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
"node_modules/edu-core": {
|
"node_modules/edu-core": {
|
||||||
"resolved": "../edu-core",
|
"version": "1.0.14",
|
||||||
"link": true
|
"resolved": "git+https://git.nuttyreading.com/chenghuan/edu-core.git#eb9eccdc3d281fe84127a93e019650512859ff0c",
|
||||||
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/element-plus": {
|
"node_modules/element-plus": {
|
||||||
"version": "2.11.5",
|
"version": "2.11.5",
|
||||||
@@ -4177,7 +4173,7 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"e-peanut": "file:",
|
"e-peanut": "file:",
|
||||||
"edu-core": "file:../edu-core",
|
"edu-core": "git+https://git.nuttyreading.com/chenghuan/edu-core.git#v1.0.14",
|
||||||
"element-plus": "^2.9.6",
|
"element-plus": "^2.9.6",
|
||||||
"epubjs": "^0.3.93",
|
"epubjs": "^0.3.93",
|
||||||
"jquery": "^2.2.4",
|
"jquery": "^2.2.4",
|
||||||
@@ -4498,7 +4494,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"edu-core": {
|
"edu-core": {
|
||||||
"version": "file:../edu-core"
|
"version": "git+https://git.nuttyreading.com/chenghuan/edu-core.git#eb9eccdc3d281fe84127a93e019650512859ff0c",
|
||||||
|
"from": "edu-core@git+https://git.nuttyreading.com/chenghuan/edu-core.git#v1.0.14"
|
||||||
},
|
},
|
||||||
"element-plus": {
|
"element-plus": {
|
||||||
"version": "2.11.5",
|
"version": "2.11.5",
|
||||||
@@ -7259,7 +7256,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"edu-core": {
|
"edu-core": {
|
||||||
"version": "file:../edu-core"
|
"version": "git+https://git.nuttyreading.com/chenghuan/edu-core.git#eb9eccdc3d281fe84127a93e019650512859ff0c",
|
||||||
|
"from": "edu-core@git+https://git.nuttyreading.com/chenghuan/edu-core.git#v1.0.14"
|
||||||
},
|
},
|
||||||
"element-plus": {
|
"element-plus": {
|
||||||
"version": "2.11.5",
|
"version": "2.11.5",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"e-peanut": "file:",
|
"e-peanut": "file:",
|
||||||
"edu-core": "file:../edu-core",
|
"edu-core": "git+https://git.nuttyreading.com/chenghuan/edu-core.git#v1.0.14",
|
||||||
"element-plus": "^2.9.6",
|
"element-plus": "^2.9.6",
|
||||||
"epubjs": "^0.3.93",
|
"epubjs": "^0.3.93",
|
||||||
"jquery": "^2.2.4",
|
"jquery": "^2.2.4",
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
// "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
|
// "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
|
||||||
// },
|
// },
|
||||||
"pages": [
|
"pages": [
|
||||||
|
// {
|
||||||
|
// "path": "pages/test/test",
|
||||||
|
// "style": {
|
||||||
|
// "navigationBarTitleText": "测试页"
|
||||||
|
// }
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
"path": "pages/peanut/home",
|
"path": "pages/peanut/home",
|
||||||
"style": {
|
"style": {
|
||||||
@@ -813,7 +819,6 @@
|
|||||||
"navigationBarTitleText" : "数据迁移"
|
"navigationBarTitleText" : "数据迁移"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
"navigationBarTextStyle": "black",
|
"navigationBarTextStyle": "black",
|
||||||
|
|||||||
@@ -20,8 +20,7 @@
|
|||||||
:course="{courseTitle:options.navTitle, chapterTitle: curriculumData.title, catalogueId: curriculumData.catalogueId || '', courseId: curriculumData.courseId || options.courseId || ''}"
|
:course="{courseTitle:options.navTitle, chapterTitle: curriculumData.title, catalogueId: curriculumData.catalogueId || '', courseId: curriculumData.courseId || options.courseId || ''}"
|
||||||
:cover="options.curriculumImgUrl || ''"
|
:cover="options.curriculumImgUrl || ''"
|
||||||
:http="$http"
|
:http="$http"
|
||||||
:user-id="watermarkUserId"
|
:user-info="userInfo"
|
||||||
:mobile="watermarkMobile"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<view class="" style="border-top: 2px solid #2979ff;">
|
<view class="" style="border-top: 2px solid #2979ff;">
|
||||||
@@ -173,6 +172,7 @@
|
|||||||
import {
|
import {
|
||||||
mapState
|
mapState
|
||||||
} from "vuex";
|
} from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
courseDescription, //课程说明
|
courseDescription, //课程说明
|
||||||
@@ -332,7 +332,6 @@
|
|||||||
},
|
},
|
||||||
onHide() {
|
onHide() {
|
||||||
console.log('回去了 .....................');
|
console.log('回去了 .....................');
|
||||||
|
|
||||||
},
|
},
|
||||||
onPullDownRefresh() {
|
onPullDownRefresh() {
|
||||||
uni.stopPullDownRefresh();
|
uni.stopPullDownRefresh();
|
||||||
@@ -344,12 +343,6 @@
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["userInfo"]),
|
...mapState(["userInfo"]),
|
||||||
watermarkUserId() {
|
|
||||||
return this.userInfo.id || this.userInfo.userId || this.userInfo.uid || ''
|
|
||||||
},
|
|
||||||
watermarkMobile() {
|
|
||||||
return this.userInfo.phone || this.userInfo.tel || this.userInfo.mobile || ''
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
editorIput(e){
|
editorIput(e){
|
||||||
|
|||||||
79
pages/test/test.vue
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
<view class="content">
|
||||||
|
<view class="btn" @click="onAntiScreenshot"><text>开启防截屏</text></view>
|
||||||
|
<view class="btn" @click="onAntiScreenshot2"><text>开启防截屏</text></view>
|
||||||
|
<view class="btn" @click="offAntiScreenshot"><text>关闭防截屏</text></view>
|
||||||
|
<view class="btn" @click="offAntiScreenshot2"><text>关闭防截屏</text></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onAntiScreenshot() {
|
||||||
|
console.log('点击了开启按钮')
|
||||||
|
// screenshot.onAntiScreenshot()
|
||||||
|
// screenGuard.onAntiScreenshot()
|
||||||
|
uni.setUserCaptureScreen({
|
||||||
|
enable: false,
|
||||||
|
success() {
|
||||||
|
console.log('截屏录屏功能已禁用');
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
console.error('禁用截屏录屏功能失败', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
offAntiScreenshot() {
|
||||||
|
console.log('点击了关闭按钮')
|
||||||
|
// screenshot.offAntiScreenshot()
|
||||||
|
// screenGuard.offAntiScreenshot()
|
||||||
|
uni.setUserCaptureScreen({
|
||||||
|
enable: true,
|
||||||
|
success() {
|
||||||
|
console.log('截屏录屏功能已启用');
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
console.error('启用截屏录屏功能失败', err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onAntiScreenshot2() {
|
||||||
|
console.log('点击了开启按钮')
|
||||||
|
// screenshot.onAntiScreenshot()
|
||||||
|
screenGuard.onAntiScreenshot()
|
||||||
|
},
|
||||||
|
offAntiScreenshot2() {
|
||||||
|
console.log('点击了关闭按钮')
|
||||||
|
// screenshot.offAntiScreenshot()
|
||||||
|
|
||||||
|
screenGuard.offAntiScreenshot()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: antiquewhite;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
width: 690rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
14
uni_modules/uni-usercapturescreen/changelog.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
## 1.0.6(2024-11-22)
|
||||||
|
- 修复 HarmonyOS Next 上调用 setUserCaptureScreen 报错的 Bug
|
||||||
|
## 1.0.5(2024-10-14)
|
||||||
|
- 新增 支持 HarmonyOS Next 调用
|
||||||
|
## 1.0.4(2023-03-24)
|
||||||
|
新增开启/关闭防截屏功能
|
||||||
|
## 1.0.3(2023-03-17)
|
||||||
|
修复android平台 部分场景下js可能报错的问题
|
||||||
|
## 1.0.2(2023-03-16)
|
||||||
|
修复Android平台在小米设备无法监听的问题 修复Android平台调用uni.onUserCaptureScreen必然会触发回调的问题
|
||||||
|
## 1.0.1(2022-10-27)
|
||||||
|
修改插件描述
|
||||||
|
## 1.0.0(2022-10-26)
|
||||||
|
支持安卓、iOS、微信小程序平台
|
||||||
157
uni_modules/uni-usercapturescreen/index.d.ts
vendored
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
declare namespace UniNamespace {
|
||||||
|
/**
|
||||||
|
* uni.onUserCaptureScreen/uni.offUserCaptureScreen回调参数
|
||||||
|
*/
|
||||||
|
type OnUserCaptureScreenCallbackResult = {
|
||||||
|
/**
|
||||||
|
* 截屏文件路径(仅Android返回)
|
||||||
|
*/
|
||||||
|
path ?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.onUserCaptureScreen/uni.offUserCaptureScreen回调函数定义
|
||||||
|
*/
|
||||||
|
type UserCaptureScreenCallback = (res : OnUserCaptureScreenCallbackResult) => void
|
||||||
|
|
||||||
|
type OnUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void
|
||||||
|
|
||||||
|
type OffUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.setUserCaptureScreen成功回调参数
|
||||||
|
*/
|
||||||
|
type SetUserCaptureScreenSuccess = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.setUserCaptureScreen成功回调函数定义
|
||||||
|
*/
|
||||||
|
type SetUserCaptureScreenSuccessCallback = (res : SetUserCaptureScreenSuccess) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码
|
||||||
|
* - 12001 "setUserCaptureScreen:system not support"
|
||||||
|
* - 12010 "setUserCaptureScreen:system internal error"
|
||||||
|
*/
|
||||||
|
type SetUserCaptureScreenErrorCode = 12001 | 12010;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SetUserCaptureScreen 的错误回调参数
|
||||||
|
*/
|
||||||
|
interface SetUserCaptureScreenFail {
|
||||||
|
errCode : SetUserCaptureScreenErrorCode
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.setUserCaptureScreen失败回调函数定义
|
||||||
|
*/
|
||||||
|
type SetUserCaptureScreenFailCallback = (res : SetUserCaptureScreenFail) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.setUserCaptureScreen完成回调函数定义
|
||||||
|
*/
|
||||||
|
type SetUserCaptureScreenCompleteCallback = (res : any) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.setUserCaptureScreen参数
|
||||||
|
*/
|
||||||
|
type SetUserCaptureScreenOptions = {
|
||||||
|
/**
|
||||||
|
* true: 允许用户截屏 false: 不允许用户截屏,防止用户截屏到应用页面内容
|
||||||
|
*/
|
||||||
|
enable : boolean;
|
||||||
|
/**
|
||||||
|
* 接口调用成功的回调函数
|
||||||
|
*/
|
||||||
|
// success : SetUserCaptureScreenSuccessCallback | null,
|
||||||
|
success ?: SetUserCaptureScreenSuccessCallback,
|
||||||
|
/**
|
||||||
|
* 接口调用失败的回调函数
|
||||||
|
*/
|
||||||
|
// fail : SetUserCaptureScreenFailCallback | null,
|
||||||
|
fail ?: SetUserCaptureScreenFailCallback,
|
||||||
|
/**
|
||||||
|
* 接口调用结束的回调函数(调用成功、失败都会执行)
|
||||||
|
*/
|
||||||
|
// complete : SetUserCaptureScreenSuccessCallback | SetUserCaptureScreenFailCallback | null
|
||||||
|
complete ?: SetUserCaptureScreenCompleteCallback
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetUserCaptureScreen = (options : SetUserCaptureScreenOptions) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface Uni {
|
||||||
|
/**
|
||||||
|
* 开启截屏监听
|
||||||
|
*
|
||||||
|
* @param {UserCaptureScreenCallback} callback
|
||||||
|
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen
|
||||||
|
* @uniPlatform {
|
||||||
|
* "app": {
|
||||||
|
* "android": {
|
||||||
|
* "osVer": "4.4.4",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "3.9.0"
|
||||||
|
* },
|
||||||
|
* "ios": {
|
||||||
|
* "osVer": "9.0",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "x"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @uniVersion 3.7.7
|
||||||
|
* @uniVueVersion 2,3 //支持的vue版本
|
||||||
|
* @autotest { expectCallback: true }
|
||||||
|
*/
|
||||||
|
onUserCaptureScreen(callback : UniNamespace.UserCaptureScreenCallback | null) : void,
|
||||||
|
/**
|
||||||
|
* 关闭截屏监听
|
||||||
|
*
|
||||||
|
* @param {UserCaptureScreenCallback} callback
|
||||||
|
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen
|
||||||
|
* @uniPlatform {
|
||||||
|
* "app": {
|
||||||
|
* "android": {
|
||||||
|
* "osVer": "4.4.4",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "3.9.0"
|
||||||
|
* },
|
||||||
|
* "ios": {
|
||||||
|
* "osVer": "9.0",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "x"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @uniVersion 3.7.7
|
||||||
|
* @uniVueVersion 2,3 //支持的vue版本
|
||||||
|
* @autotest { expectCallback: true }
|
||||||
|
*/
|
||||||
|
offUserCaptureScreen(callback : UniNamespace.UserCaptureScreenCallback | null) : void,
|
||||||
|
/**
|
||||||
|
* 设置防截屏
|
||||||
|
*
|
||||||
|
* @param {SetUserCaptureScreenOptions} options
|
||||||
|
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen
|
||||||
|
* @uniPlatform {
|
||||||
|
* "app": {
|
||||||
|
* "android": {
|
||||||
|
* "osVer": "4.4.4",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "3.9.0"
|
||||||
|
* },
|
||||||
|
* "ios": {
|
||||||
|
* "osVer": "13.0",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "x"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @uniVersion 3.7.7
|
||||||
|
* @uniVueVersion 2,3 //支持的vue版本
|
||||||
|
*/
|
||||||
|
setUserCaptureScreen(options : UniNamespace.SetUserCaptureScreenOptions) : void
|
||||||
|
}
|
||||||
97
uni_modules/uni-usercapturescreen/package.json
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
{
|
||||||
|
"id": "uni-usercapturescreen",
|
||||||
|
"displayName": "uni-usercapturescreen",
|
||||||
|
"version": "1.0.6",
|
||||||
|
"description": "用户主动截屏事件监听",
|
||||||
|
"keywords": [
|
||||||
|
"截屏"
|
||||||
|
],
|
||||||
|
"repository": "",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.7.7"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"type": "uts",
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "插件不采集任何数据",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": ""
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"uni-ext-api":{
|
||||||
|
"uni": {
|
||||||
|
"onUserCaptureScreen": {
|
||||||
|
"web": false
|
||||||
|
},
|
||||||
|
"offUserCaptureScreen": {
|
||||||
|
"web": false
|
||||||
|
},
|
||||||
|
"setUserCaptureScreen": {
|
||||||
|
"web": false,
|
||||||
|
"mp-weixin": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": [],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y",
|
||||||
|
"alipay": "n"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
},
|
||||||
|
"App": {
|
||||||
|
"app-android": "y",
|
||||||
|
"app-ios": "y",
|
||||||
|
"app-harmony": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "n",
|
||||||
|
"Android Browser": "n",
|
||||||
|
"微信浏览器(Android)": "n",
|
||||||
|
"QQ浏览器(Android)": "n"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "n",
|
||||||
|
"IE": "n",
|
||||||
|
"Edge": "n",
|
||||||
|
"Firefox": "n",
|
||||||
|
"Safari": "n"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "n",
|
||||||
|
"百度": "n",
|
||||||
|
"字节跳动": "n",
|
||||||
|
"QQ": "n",
|
||||||
|
"钉钉": "n",
|
||||||
|
"快手": "n",
|
||||||
|
"飞书": "n",
|
||||||
|
"京东": "n"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "n",
|
||||||
|
"联盟": "n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
uni_modules/uni-usercapturescreen/readme.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# uni-usercapturescreen
|
||||||
|
|
||||||
|
用户主动截屏事件监听
|
||||||
|
|
||||||
|
### uni.onUserCaptureScreen
|
||||||
|
|
||||||
|
监听用户主动截屏事件,用户使用系统截屏按键截屏时触发此事件。
|
||||||
|
|
||||||
|
> 使用文档:[https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen](https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen)
|
||||||
|
|
||||||
|
### uni.offUserCaptureScreen
|
||||||
|
|
||||||
|
用户主动截屏事件。取消事件监听。
|
||||||
|
|
||||||
|
> 使用文档:[https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen](https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen)
|
||||||
|
|
||||||
|
### uni.setUserCaptureScreen
|
||||||
|
|
||||||
|
开启/关闭防截屏。
|
||||||
|
|
||||||
|
> 使用文档:[https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen](https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen)
|
||||||
139
uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
import { UTSAndroid } from "io.dcloud.uts";
|
||||||
|
import ActivityCompat from "androidx.core.app.ActivityCompat";
|
||||||
|
import Manifest from "android.Manifest";
|
||||||
|
import PackageManager from "android.content.pm.PackageManager";
|
||||||
|
import Build from "android.os.Build";
|
||||||
|
import FileObserver from "android.os.FileObserver";
|
||||||
|
import File from "java.io.File";
|
||||||
|
import Environment from "android.os.Environment";
|
||||||
|
import System from 'java.lang.System';
|
||||||
|
import WindowManager from 'android.view.WindowManager';
|
||||||
|
import { OnUserCaptureScreenCallbackResult, UserCaptureScreenCallback, OnUserCaptureScreen, OffUserCaptureScreen, SetUserCaptureScreenSuccess, SetUserCaptureScreenOptions, SetUserCaptureScreen } from "../interface.uts";
|
||||||
|
import string from 'android.R.string';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件监听器
|
||||||
|
*/
|
||||||
|
let observer : ScreenFileObserver | null = null;
|
||||||
|
/**
|
||||||
|
* 记录文件监听器上次监听的时间戳,避免重复监听
|
||||||
|
*/
|
||||||
|
let lastObserverTime : number = 0;
|
||||||
|
/**
|
||||||
|
* 截屏回调
|
||||||
|
*/
|
||||||
|
let listener : UserCaptureScreenCallback | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* android 文件监听实现
|
||||||
|
*/
|
||||||
|
class ScreenFileObserver extends FileObserver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 截屏文件目录
|
||||||
|
*/
|
||||||
|
private screenFile : File;
|
||||||
|
|
||||||
|
constructor(screenFileStr : string) {
|
||||||
|
super(screenFileStr);
|
||||||
|
this.screenFile = new File(screenFileStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
override onEvent(event : Int, path : string | null) : void {
|
||||||
|
// 只监听文件新增事件
|
||||||
|
if (event == FileObserver.CREATE) {
|
||||||
|
if (path != null) {
|
||||||
|
const currentTime = System.currentTimeMillis();
|
||||||
|
if ((currentTime - lastObserverTime) < 1000) {
|
||||||
|
// 本地截屏行为比上一次超过1000ms, 才认为是一个有效的时间
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastObserverTime = currentTime;
|
||||||
|
|
||||||
|
const screenShotPath = new File(this.screenFile, path).getPath();
|
||||||
|
const res : OnUserCaptureScreenCallbackResult = {
|
||||||
|
path: screenShotPath
|
||||||
|
}
|
||||||
|
listener?.(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开启截图监听
|
||||||
|
*/
|
||||||
|
export const onUserCaptureScreen : OnUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) {
|
||||||
|
// 检查相关权限是否已授予
|
||||||
|
if (ActivityCompat.checkSelfPermission(UTSAndroid.getAppContext()!, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
// 无权限,申请权限
|
||||||
|
ActivityCompat.requestPermissions(UTSAndroid.getUniActivity()!, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1001);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 更新监听
|
||||||
|
listener = callback;
|
||||||
|
|
||||||
|
let directory_screenshot : File;
|
||||||
|
if (Build.MANUFACTURER.toLowerCase() == "xiaomi") {
|
||||||
|
// @Suppress("DEPRECATION")
|
||||||
|
directory_screenshot = new File(new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DCIM), "Screenshots");
|
||||||
|
} else {
|
||||||
|
// @Suppress("DEPRECATION")
|
||||||
|
directory_screenshot = new File(new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_PICTURES), "Screenshots");
|
||||||
|
}
|
||||||
|
// 先结束监听 再开启监听
|
||||||
|
observer?.stopWatching();
|
||||||
|
observer = new ScreenFileObserver(directory_screenshot.getPath());
|
||||||
|
observer?.startWatching();
|
||||||
|
|
||||||
|
|
||||||
|
UTSAndroid.onAppActivityDestroy(function(){
|
||||||
|
observer?.stopWatching()
|
||||||
|
observer = null
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭截屏监听
|
||||||
|
*/
|
||||||
|
export const offUserCaptureScreen : OffUserCaptureScreen = function (_ : UserCaptureScreenCallback | null) {
|
||||||
|
// android10以上,关闭监听通过移除文件监听器实现
|
||||||
|
observer?.stopWatching();
|
||||||
|
observer = null;
|
||||||
|
lastObserverTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置是否禁止截屏
|
||||||
|
*/
|
||||||
|
export const setUserCaptureScreen : SetUserCaptureScreen = function (option : SetUserCaptureScreenOptions) {
|
||||||
|
// 切换到UI线程
|
||||||
|
UTSAndroid.getUniActivity()?.runOnUiThread(new SetUserCaptureScreenRunnable(option.enable));
|
||||||
|
const res : SetUserCaptureScreenSuccess = {}
|
||||||
|
option.success?.(res);
|
||||||
|
option.complete?.(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetUserCaptureScreenRunnable extends Runnable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ture: 允许用户截屏
|
||||||
|
* false: 不允许用户截屏,防止用户截屏到应用页面内容
|
||||||
|
*/
|
||||||
|
private enable : boolean;
|
||||||
|
|
||||||
|
constructor(enable : boolean) {
|
||||||
|
super();
|
||||||
|
this.enable = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
override run() : void {
|
||||||
|
if (this.enable) {
|
||||||
|
UTSAndroid.getUniActivity()?.getWindow()?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
||||||
|
} else {
|
||||||
|
UTSAndroid.getUniActivity()?.getWindow()?.addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import { display } from '@kit.ArkUI';
|
||||||
|
import { window } from '@kit.ArkUI';
|
||||||
|
import { Callback, BusinessError } from '@kit.BasicServicesKit';
|
||||||
|
|
||||||
|
import { getAbilityContext } from '@dcloudio/uni-runtime';
|
||||||
|
|
||||||
|
import {
|
||||||
|
OnUserCaptureScreen, UserCaptureScreenCallback,
|
||||||
|
OffUserCaptureScreen,
|
||||||
|
SetUserCaptureScreen, SetUserCaptureScreenOptions, SetUserCaptureScreenSuccess
|
||||||
|
} from '../interface.uts';
|
||||||
|
|
||||||
|
const onUserCaptureScreenCallbacks: Function[] = []
|
||||||
|
|
||||||
|
const harmonyCaptureStatusChange: Callback<boolean> = (captureStatus: boolean) => {
|
||||||
|
if (captureStatus) {
|
||||||
|
onUserCaptureScreenCallbacks.forEach(cb => {
|
||||||
|
typeof cb === 'function' && cb()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
display.on('captureStatusChange', harmonyCaptureStatusChange)
|
||||||
|
|
||||||
|
export const onUserCaptureScreen: OnUserCaptureScreen = function (callback: UserCaptureScreenCallback | null) {
|
||||||
|
if (callback) {
|
||||||
|
onUserCaptureScreenCallbacks.push(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const offUserCaptureScreen: OffUserCaptureScreen = function (callback: UserCaptureScreenCallback | null) {
|
||||||
|
if (callback) {
|
||||||
|
const index = onUserCaptureScreenCallbacks.indexOf(callback)
|
||||||
|
if (index > -1) {
|
||||||
|
onUserCaptureScreenCallbacks.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const setUserCaptureScreen: SetUserCaptureScreen = function (options: SetUserCaptureScreenOptions) {
|
||||||
|
const errSubject = 'uni-usercapturescreen'
|
||||||
|
const setUserCaptureScreenSuccess: SetUserCaptureScreenSuccess = {}
|
||||||
|
window.getLastWindow(getAbilityContext()!, (err, window) => {
|
||||||
|
const errCode: number = err.code;
|
||||||
|
if (errCode) {
|
||||||
|
options.fail?.({
|
||||||
|
errCode: (err as BusinessError).code,
|
||||||
|
errSubject,
|
||||||
|
errMsg: `setUserCaptureScreen:fail ${(err as BusinessError).message}`
|
||||||
|
} as IUniError)
|
||||||
|
options.complete?.(setUserCaptureScreenSuccess);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
UTSHarmony.requestSystemPermission(['ohos.permission.PRIVACY_WINDOW'], (allRight: boolean, _grantedList: string[]) => {
|
||||||
|
if (allRight) {
|
||||||
|
window.setWindowPrivacyMode(!options.enable, (err: BusinessError) => {
|
||||||
|
const errCode: number = err.code;
|
||||||
|
if (errCode) {
|
||||||
|
options.fail?.({
|
||||||
|
errCode: err.code,
|
||||||
|
errSubject,
|
||||||
|
errMsg: `setUserCaptureScreen:fail ${err.message}`
|
||||||
|
} as IUniError)
|
||||||
|
options.complete?.(setUserCaptureScreenSuccess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
options.success?.(setUserCaptureScreenSuccess);
|
||||||
|
options.complete?.(setUserCaptureScreenSuccess);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error('permission denied')
|
||||||
|
}
|
||||||
|
}, (_doNotAskAgain: boolean, _grantedList: string[]) => {
|
||||||
|
throw new Error('permission denied');
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
options.fail?.({
|
||||||
|
errCode: (err as BusinessError).code,
|
||||||
|
errSubject,
|
||||||
|
errMsg: `setUserCaptureScreen:fail ${(err as BusinessError).message}`
|
||||||
|
} as IUniError)
|
||||||
|
options.complete?.(setUserCaptureScreenSuccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
141
uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
import { NotificationCenter } from 'Foundation';
|
||||||
|
import { CGRect } from "CoreFoundation";
|
||||||
|
import { UIApplication, UIView, UITextField, UIScreen, UIDevice } from "UIKit"
|
||||||
|
import { UTSiOS } from "DCloudUTSFoundation"
|
||||||
|
import { DispatchQueue } from 'Dispatch';
|
||||||
|
import { SetUserCaptureScreenOptions, OnUserCaptureScreenCallbackResult, OnUserCaptureScreen, OffUserCaptureScreen, SetUserCaptureScreen, UserCaptureScreenCallback, SetUserCaptureScreenSuccess } from "../interface.uts"
|
||||||
|
import { SetUserCaptureScreenFailImpl } from "../unierror.uts"
|
||||||
|
/**
|
||||||
|
* 定义监听截屏事件工具类
|
||||||
|
*/
|
||||||
|
class CaptureScreenTool {
|
||||||
|
static listener : UserCaptureScreenCallback | null;
|
||||||
|
static secureView : UIView | null;
|
||||||
|
|
||||||
|
// 监听截屏
|
||||||
|
static listenCaptureScreen(callback : UserCaptureScreenCallback | null) {
|
||||||
|
this.listener = callback
|
||||||
|
|
||||||
|
// 注册监听截屏事件及回调方法
|
||||||
|
// target-action 回调方法需要通过 Selector("方法名") 构建
|
||||||
|
const method = Selector("userDidTakeScreenshot")
|
||||||
|
NotificationCenter.default.addObserver(this, selector = method, name = UIApplication.userDidTakeScreenshotNotification, object = null)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 捕获截屏回调的方法
|
||||||
|
// target-action 的方法前需要添加 @objc 前缀
|
||||||
|
@objc static userDidTakeScreenshot() {
|
||||||
|
// 回调
|
||||||
|
const res: OnUserCaptureScreenCallbackResult = {
|
||||||
|
}
|
||||||
|
this.listener?.(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除监听事件
|
||||||
|
static removeListen(callback : UserCaptureScreenCallback | null) {
|
||||||
|
this.listener = null
|
||||||
|
NotificationCenter.default.removeObserver(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
static createSecureView() : UIView | null {
|
||||||
|
let field = new UITextField(frame = CGRect.zero)
|
||||||
|
field.isSecureTextEntry = true
|
||||||
|
if (field.subviews.length > 0 && UIDevice.current.systemVersion != '15.1') {
|
||||||
|
let view = field.subviews[0]
|
||||||
|
view.subviews.forEach((item) => {
|
||||||
|
item.removeFromSuperview()
|
||||||
|
})
|
||||||
|
view.isUserInteractionEnabled = true
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开启防截屏
|
||||||
|
static onAntiScreenshot(option : SetUserCaptureScreenOptions) {
|
||||||
|
// uts方法默认会在子线程中执行,涉及 UI 操作必须在主线程中运行,通过 DispatchQueue.main.async 方法可将代码在主线程中运行
|
||||||
|
DispatchQueue.main.async(execute = () : void => {
|
||||||
|
let secureView = this.createSecureView()
|
||||||
|
let window = UTSiOS.getKeyWindow()
|
||||||
|
let rootView = window.rootViewController == null ? null : window.rootViewController!.view
|
||||||
|
if (secureView != null && rootView != null) {
|
||||||
|
let rootSuperview = rootView!.superview
|
||||||
|
if (rootSuperview != null) {
|
||||||
|
this.secureView = secureView
|
||||||
|
rootSuperview!.addSubview(secureView!)
|
||||||
|
rootView!.removeFromSuperview()
|
||||||
|
secureView!.addSubview(rootView!)
|
||||||
|
// secureView 充满父视图并随父视图宽高自适应(横竖屏、全屏切换时自动跟随)
|
||||||
|
secureView!.frame = rootSuperview!.bounds
|
||||||
|
secureView!.autoresizingMask = [UIView.AutoresizingMask.flexibleWidth, UIView.AutoresizingMask.flexibleHeight]
|
||||||
|
// rootView 充满 secureView 并自适应,避免全屏时被固定在竖屏尺寸而缩到角落
|
||||||
|
rootView!.frame = secureView!.bounds
|
||||||
|
rootView!.autoresizingMask = [UIView.AutoresizingMask.flexibleWidth, UIView.AutoresizingMask.flexibleHeight]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let res: SetUserCaptureScreenSuccess = {
|
||||||
|
}
|
||||||
|
option.success?.(res)
|
||||||
|
option.complete?.(res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭防截屏
|
||||||
|
static offAntiScreenshot(option : SetUserCaptureScreenOptions) {
|
||||||
|
DispatchQueue.main.async(execute = () : void => {
|
||||||
|
if (this.secureView != null) {
|
||||||
|
let window = UTSiOS.getKeyWindow()
|
||||||
|
let rootView = window.rootViewController == null ? null : window.rootViewController!.view
|
||||||
|
if (rootView != null && this.secureView!.superview != null) {
|
||||||
|
let rootSuperview = this.secureView!.superview
|
||||||
|
if (rootSuperview != null) {
|
||||||
|
rootSuperview!.addSubview(rootView!)
|
||||||
|
this.secureView!.removeFromSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.secureView = null
|
||||||
|
}
|
||||||
|
let res: SetUserCaptureScreenSuccess = {
|
||||||
|
}
|
||||||
|
option.success?.(res)
|
||||||
|
option.complete?.(res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开启截图监听
|
||||||
|
*/
|
||||||
|
export const onUserCaptureScreen : OnUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) {
|
||||||
|
CaptureScreenTool.listenCaptureScreen(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭截屏监听
|
||||||
|
*/
|
||||||
|
export const offUserCaptureScreen : OffUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) {
|
||||||
|
CaptureScreenTool.removeListen(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开启/关闭防截屏
|
||||||
|
*/
|
||||||
|
export const setUserCaptureScreen : SetUserCaptureScreen = function (options : SetUserCaptureScreenOptions) {
|
||||||
|
if (UIDevice.current.systemVersion < "13.0") {
|
||||||
|
let res = new SetUserCaptureScreenFailImpl(12001)
|
||||||
|
options.fail?.(res);
|
||||||
|
options.complete?.(res);
|
||||||
|
|
||||||
|
} else if (UIDevice.current.systemVersion == "15.1") {
|
||||||
|
let res = new SetUserCaptureScreenFailImpl(12010)
|
||||||
|
options.fail?.(res);
|
||||||
|
options.complete?.(res);
|
||||||
|
} else {
|
||||||
|
if (options.enable == true) {
|
||||||
|
CaptureScreenTool.offAntiScreenshot(options)
|
||||||
|
} else {
|
||||||
|
CaptureScreenTool.onAntiScreenshot(options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
170
uni_modules/uni-usercapturescreen/utssdk/interface.uts
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/**
|
||||||
|
* uni.onUserCaptureScreen/uni.offUserCaptureScreen回调参数
|
||||||
|
*/
|
||||||
|
export type OnUserCaptureScreenCallbackResult = {
|
||||||
|
/**
|
||||||
|
* 截屏文件路径(仅Android返回)
|
||||||
|
*/
|
||||||
|
path ?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.onUserCaptureScreen/uni.offUserCaptureScreen回调函数定义
|
||||||
|
*/
|
||||||
|
export type UserCaptureScreenCallback = (res : OnUserCaptureScreenCallbackResult) => void
|
||||||
|
|
||||||
|
export type OnUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void
|
||||||
|
|
||||||
|
export type OffUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.setUserCaptureScreen成功回调参数
|
||||||
|
*/
|
||||||
|
export type SetUserCaptureScreenSuccess = {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.setUserCaptureScreen成功回调函数定义
|
||||||
|
*/
|
||||||
|
export type SetUserCaptureScreenSuccessCallback = (res : SetUserCaptureScreenSuccess) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.setUserCaptureScreen失败回调函数定义
|
||||||
|
*/
|
||||||
|
export type SetUserCaptureScreenFailCallback = (res : IUniError) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.setUserCaptureScreen完成回调函数定义
|
||||||
|
*/
|
||||||
|
export type SetUserCaptureScreenCompleteCallback = (res : any) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uni.setUserCaptureScreen参数
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type SetUserCaptureScreenOptions = {
|
||||||
|
/**
|
||||||
|
* true: 允许用户截屏 false: 不允许用户截屏,防止用户截屏到应用页面内容
|
||||||
|
*/
|
||||||
|
enable : boolean;
|
||||||
|
/**
|
||||||
|
* 接口调用成功的回调函数
|
||||||
|
*/
|
||||||
|
// success : SetUserCaptureScreenSuccessCallback | null,
|
||||||
|
success ?: SetUserCaptureScreenSuccessCallback,
|
||||||
|
/**
|
||||||
|
* 接口调用失败的回调函数
|
||||||
|
*/
|
||||||
|
// fail : SetUserCaptureScreenFailCallback | null,
|
||||||
|
fail ?: SetUserCaptureScreenFailCallback,
|
||||||
|
/**
|
||||||
|
* 接口调用结束的回调函数(调用成功、失败都会执行)
|
||||||
|
*/
|
||||||
|
// complete : SetUserCaptureScreenSuccessCallback | SetUserCaptureScreenFailCallback | null
|
||||||
|
complete ?: SetUserCaptureScreenCompleteCallback
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码
|
||||||
|
* - 12001 "setUserCaptureScreen:system not support"
|
||||||
|
* - 12010 "setUserCaptureScreen:system internal error"
|
||||||
|
*/
|
||||||
|
export type SetUserCaptureScreenErrorCode = 12001 | 12010;
|
||||||
|
/**
|
||||||
|
* SetUserCaptureScreen 的错误回调参数
|
||||||
|
*/
|
||||||
|
export interface SetUserCaptureScreenFail extends IUniError {
|
||||||
|
errCode : SetUserCaptureScreenErrorCode
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SetUserCaptureScreen = (options : SetUserCaptureScreenOptions) => void
|
||||||
|
|
||||||
|
export interface Uni {
|
||||||
|
/**
|
||||||
|
* 开启截屏监听
|
||||||
|
*
|
||||||
|
* @param {UserCaptureScreenCallback} callback
|
||||||
|
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen
|
||||||
|
* @uniPlatform {
|
||||||
|
* "app": {
|
||||||
|
* "android": {
|
||||||
|
* "osVer": "4.4.4",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "3.9.0"
|
||||||
|
* },
|
||||||
|
* "ios": {
|
||||||
|
* "osVer": "12.0",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "4.11"
|
||||||
|
* },
|
||||||
|
* "harmony": {
|
||||||
|
* "osVer": "3.0",
|
||||||
|
* "uniVer": "4.25",
|
||||||
|
* "unixVer": "x"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @uniVersion 3.7.7
|
||||||
|
* @uniVueVersion 2,3 //支持的vue版本
|
||||||
|
* @autotest { expectCallback: true }
|
||||||
|
*/
|
||||||
|
onUserCaptureScreen(callback : UserCaptureScreenCallback | null) : void,
|
||||||
|
/**
|
||||||
|
* 关闭截屏监听
|
||||||
|
*
|
||||||
|
* @param {UserCaptureScreenCallback} callback
|
||||||
|
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen
|
||||||
|
* @uniPlatform {
|
||||||
|
* "app": {
|
||||||
|
* "android": {
|
||||||
|
* "osVer": "4.4.4",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "3.9.0"
|
||||||
|
* },
|
||||||
|
* "ios": {
|
||||||
|
* "osVer": "12.0",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "4.11"
|
||||||
|
* },
|
||||||
|
* "harmony": {
|
||||||
|
* "osVer": "3.0",
|
||||||
|
* "uniVer": "4.25",,
|
||||||
|
* "unixVer": "x"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @uniVersion 3.7.7
|
||||||
|
* @uniVueVersion 2,3 //支持的vue版本
|
||||||
|
* @autotest { expectCallback: true }
|
||||||
|
*/
|
||||||
|
offUserCaptureScreen(callback : UserCaptureScreenCallback | null) : void,
|
||||||
|
/**
|
||||||
|
* 设置防截屏
|
||||||
|
*
|
||||||
|
* @param {SetUserCaptureScreenOptions} options
|
||||||
|
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen
|
||||||
|
* @uniPlatform {
|
||||||
|
* "app": {
|
||||||
|
* "android": {
|
||||||
|
* "osVer": "4.4.4",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "3.9.0"
|
||||||
|
* },
|
||||||
|
* "ios": {
|
||||||
|
* "osVer": "13.0",
|
||||||
|
* "uniVer": "3.7.7",
|
||||||
|
* "unixVer": "4.11"
|
||||||
|
* },
|
||||||
|
* "harmony": {
|
||||||
|
* "osVer": "3.0",
|
||||||
|
* "uniVer": "4.25",
|
||||||
|
* "unixVer": "x"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @uniVersion 3.7.7
|
||||||
|
* @uniVueVersion 2,3 //支持的vue版本
|
||||||
|
*/
|
||||||
|
setUserCaptureScreen(options : SetUserCaptureScreenOptions) : void
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export function onUserCaptureScreen (callback) {
|
||||||
|
return wx.onUserCaptureScreen(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function offUserCaptureScreen (callback) {
|
||||||
|
return wx.offUserCaptureScreen(callback)
|
||||||
|
}
|
||||||
35
uni_modules/uni-usercapturescreen/utssdk/unierror.uts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { SetUserCaptureScreenErrorCode, SetUserCaptureScreenFail } from "./interface.uts"
|
||||||
|
/**
|
||||||
|
* 错误主题
|
||||||
|
*/
|
||||||
|
export const UniErrorSubject = 'uni-usercapturescreen';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误信息
|
||||||
|
* @UniError
|
||||||
|
*/
|
||||||
|
export const UniErrors : Map<SetUserCaptureScreenErrorCode, string> = new Map([
|
||||||
|
/**
|
||||||
|
* 错误码及对应的错误信息
|
||||||
|
*/
|
||||||
|
[12001, 'setUserCaptureScreen:system not support'],
|
||||||
|
[12010, 'setUserCaptureScreen:system internal error'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误对象实现
|
||||||
|
*/
|
||||||
|
export class SetUserCaptureScreenFailImpl extends UniError implements SetUserCaptureScreenFail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误对象构造函数
|
||||||
|
*/
|
||||||
|
constructor(errCode : SetUserCaptureScreenErrorCode) {
|
||||||
|
super();
|
||||||
|
this.errSubject = UniErrorSubject;
|
||||||
|
this.errCode = errCode;
|
||||||
|
this.errMsg = UniErrors[errCode] ?? "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -1,25 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="zh-CN">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<script>
|
|
||||||
var __UniViewStartTime__ = Date.now();
|
|
||||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
|
||||||
CSS.supports('top: constant(a)'))
|
|
||||||
document.write(
|
|
||||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
|
||||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
|
||||||
</script>
|
|
||||||
<title>View</title>
|
|
||||||
<link rel="stylesheet" href="view.css" />
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script src="__uniappes6.js"></script>
|
|
||||||
<script src="view.umd.min.js"></script>
|
|
||||||
<script src="app-view.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"prompt" : "template"
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
(function(e){function r(r){for(var n,l,i=r[0],p=r[1],a=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in p)Object.prototype.hasOwnProperty.call(p,n)&&(e[n]=p[n]);f&&f(r);while(s.length)s.shift()();return u.push.apply(u,a||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var p=t[i];0!==o[p]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={"app-config":0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e["default"]}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonp"]=this["webpackJsonp"]||[],p=i.push.bind(i);i.push=r,i=i.slice();for(var a=0;a<i.length;a++)r(i[a]);var f=p;t()})([]);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__48F690A","name":"E-peanut","version":{"name":"1.1.0","code":110},"description":"E-peanut-案例","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"Payment":{},"OAuth":{},"Messaging":{},"VideoPlayer":{},"Share":{},"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"autoclose":false,"waiting":true},"popGesture":"close","launchwebview":{"id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#FFFFFF"},"compatible":{"ignoreVersion":true},"privacy":{"prompt":"template","template":{"title":"用户协议和隐私政策","message":"请你务必审慎阅读、充分理解“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/> 你可阅读<a href='https://www.twin-ui.com'>《用户协议》</a>和<a href='https://www.twin-ui.com'>《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。","buttonAccept":"同意","buttonRefuse":"暂不同意"}},"compilerVersion":3,"allowsInlineMediaPlayback":true,"safearea":{"background":"#ffffff","bottom":{"offset":"auto"}},"uni-app":{"compilerVersion":"3.5.3","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"fast"},"tabBar":{"color":"#444444","selectedColor":"#079307","borderStyle":"rgba(0,0,0,0.4)","backgroundColor":"#ffffff","list":[{"pagePath":"pages/peanut/home","iconPath":"static/icon/tab/icon1_n.png","selectedIconPath":"static/icon/tab/icon1_y.png","text":"首页"},{"pagePath":"pages/peanut/shopping","iconPath":"static/icon/tab/icon2_n.png","selectedIconPath":"static/icon/tab/icon2_y.png","text":"购物车"},{"pagePath":"pages/peanut/bookshelf","iconPath":"static/icon/tab/icon3_n.png","selectedIconPath":"static/icon/tab/icon3_y.png","text":"我的书架"},{"pagePath":"pages/peanut/mine","iconPath":"static/icon/tab/icon4_n.png","selectedIconPath":"static/icon/tab/icon4_y.png","text":"我的"}],"height":"50px","child":["lauchwebview"],"selected":0},"launch_path":"__uniappview.html"}}
|
|
||||||
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 209 KiB |
|
Before Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 831 B |
|
Before Width: | Height: | Size: 186 B |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 703 B |
|
Before Width: | Height: | Size: 757 B |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 804 B |
|
Before Width: | Height: | Size: 781 B |
|
Before Width: | Height: | Size: 944 B |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 853 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 480 B |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 286 B |
|
Before Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 391 KiB |
|
Before Width: | Height: | Size: 330 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 547 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 839 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 355 B |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1009 B |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 30 KiB |