12 Commits

Author SHA1 Message Date
a83e021cd7 feat: 增加视频水印和防盗录 2026-06-09 17:22:21 +08:00
b78ad9a854 feat: 在 chapterDetailAndorid.vue 中添加用户 ID 和手机号码的计算属性 2026-06-04 17:18:55 +08:00
7eed35542b chore: 更新应用版本至2.0.51并调整依赖配置
- 将应用版本从2.0.49提升至2.0.51
- 修改edu-core依赖为本地文件引用
- 更新多个页面的下拉刷新和底部加载逻辑
- 优化VIP权限描述,明确不包含论坛权益
- 调整部分页面样式以提升用户体验
2026-05-20 13:27:06 +08:00
6274ac6cd6 feat(订单): 添加退款功能及相关页面
- 新增退款申请功能,用户可申请订单内所有商品退款
- 更新订单状态显示,增加“已退款”和“退款中”状态
- 新增退款去向页面,展示退款信息
- 更新依赖版本至v1.0.13
- 提升用户体验,优化多个页面的文本提示和样式
- 更新应用版本至2.0.49
2026-05-09 11:12:34 +08:00
a38187c13f chore: 视频播放下一集自动保持倍速设置;增加2.5倍速 2026-04-14 10:24:41 +08:00
3b5920cfa5 chore: 更新edu-core依赖至v1.0.11 2026-03-27 09:36:40 +08:00
6fddc1cb4a chore: 小班作业心得思考题等编辑框提示修改
- 将应用版本从2.0.46提升至2.0.47
- 更新edu-core依赖版本至1.0.10
- 在manifest.json中新增读取外部存储和媒体图片的权限
- 修改多个页面的文本提示以提高用户体验
2026-03-27 09:34:02 +08:00
32c625ab2a fix: 修复固定分类逻辑以确保正确处理当前索引和项目
- 优化了固定分类的判断逻辑,确保在当前索引为 null 或 undefined 时正确初始化,并在固定分类存在时调用 curseClick 方法。
2026-03-25 17:44:35 +08:00
2fd84c57e0 fix: 更新订单重复购买的确认按钮文本为继续购买
- 将订单提交组件中的确认按钮文本从“确定”修改为“继续购买”,以更清晰地表达用户操作意图。
2026-03-25 17:44:22 +08:00
ddb8bf6cab chore: remove launch.json configuration file
- Deleted the launch.json file which contained debugging configurations for various app types and launch types.
2026-03-25 17:42:56 +08:00
03e031ac81 feat(订单): 添加预售商品提示功能
- 在订单提交组件中添加预售商品提示弹窗
- 新增预售商品备注接口调用
- 修改VIP购买提示文本,明确不包含论坛权益
- 调整开发环境API配置
2026-03-24 18:46:08 +08:00
2b208f5dd6 chore: 用户观看时长上传和统计
- 在用户信息页面中,增加用户资料的显示,包括今日观看和总观看时长
- 优化课程详情页中视频组件的传递参数,确保课程ID和目录ID的正确传递
- 注释掉不必要的样式代码以提升可读性
2026-03-24 14:23:48 +08:00
936 changed files with 2550 additions and 25702 deletions

View File

@@ -1,38 +0,0 @@
{
// launch.json 配置了启动调试时相关设置configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtype项可配置值为local或remote, local代表前端连本地云函数remote代表前端连云端云函数
"version" : "0.0",
"configurations" : [
{
"app" : {
"launchtype" : "remote"
},
"app-plus" : {
"launchtype" : "remote"
},
"default" : {
"launchtype" : "local"
},
"h5" : {
"launchtype" : "remote"
},
"mp-weixin" : {
"launchtype" : "local"
},
"provider" : "aliyun",
"type" : "uniCloud"
},
{
"playground" : "custom",
"type" : "uni-app:app-ios"
},
{
"playground" : "custom",
"type" : "uni-app:app-android"
},
{
"playground" : "standard",
"type" : "uni-app:app-ios_simulator"
}
]
}

264
App.vue
View File

@@ -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>

View File

@@ -2,8 +2,10 @@ let baseUrl = "";
let socketUrl = ""; let socketUrl = "";
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
// 开发环境 // 开发环境
// baseUrl = "https://testapi.nuttyreading.com/"; // 线上测试
baseUrl = "https://api.nuttyreading.com/"; //线上正式' baseUrl = "https://api.nuttyreading.com/"; //线上正式'
// baseUrl = "http://192.168.110.100:9200/pb/"; //张川川 // baseUrl = "http://192.168.110.100:9200/pb/"; //张川川
// baseUrl = "http://192.168.110.131:9200/pb/"; // 王亚男
} else if (process.env.NODE_ENV === 'production') { } else if (process.env.NODE_ENV === 'production') {
// 生产环境11 // 生产环境11
baseUrl = "https://api.nuttyreading.com/"; //线上正式 baseUrl = "https://api.nuttyreading.com/"; //线上正式

View File

@@ -312,7 +312,8 @@ $http.dataFactory = async function(res) {
// 返回错误的结果(catch接受数据) // 返回错误的结果(catch接受数据)
return Promise.reject({ return Promise.reject({
statusCode: 0, statusCode: 0,
errMsg: "【request】" + (httpData.info || httpData.msg), // errMsg: "【request】" + (httpData.info || httpData.msg),
errMsg: (httpData.info || httpData.msg),
data: res.data data: res.data
}); });
} }

View File

@@ -92,6 +92,9 @@ Vue.component('common-order-submit', commonOrderSubmit);
import CommonCourseVideo from 'edu-core/components/course-video' import CommonCourseVideo from 'edu-core/components/course-video'
Vue.component('CommonCourseVideo', CommonCourseVideo); Vue.component('CommonCourseVideo', CommonCourseVideo);
import CommonRefundDestination from 'edu-core/components/order/refund-destination.vue'
Vue.component('common-refund-destination', CommonRefundDestination);
import commonCoupon from '@/pages/component/commonComponents/coupon/index.vue' import commonCoupon from '@/pages/component/commonComponents/coupon/index.vue'
Vue.component('common-coupon', commonCoupon); Vue.component('common-coupon', commonCoupon);
import commonGoodsList from '@/pages/component/commonComponents/goodsList.vue' import commonGoodsList from '@/pages/component/commonComponents/goodsList.vue'

View File

@@ -12,8 +12,8 @@
"src" : "图片路径" "src" : "图片路径"
} }
], ],
"versionName" : "2.0.43", "versionName" : "2.0.52",
"versionCode" : 2043, "versionCode" : 2052,
"sassImplementationName" : "node-sass", "sassImplementationName" : "node-sass",
"app-plus" : { "app-plus" : {
"nvueCompiler" : "uni-app", "nvueCompiler" : "uni-app",
@@ -63,6 +63,7 @@
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>", "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>", "<uses-permission android:name=\"android.permission.CAMERA\"/>",
"",
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
@@ -70,6 +71,8 @@
"<uses-permission android:name=\"android.permission.INTERNET\"/>", "<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>", "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
"<uses-permission android:name=\"android.permission.READ_MEDIA_IMAGES\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\"/>", "<uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\"/>",
"<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>", "<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>",
@@ -437,7 +440,9 @@
"uniStatistics" : { "uniStatistics" : {
"enable" : true "enable" : true
} }
} },
"fallbackLocale" : "zh-Hans",
"locale" : "zh-Hans"
} }
// 小程序特有相关 // 小程序特有相关

20
package-lock.json generated
View File

@@ -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.7",
"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",

View File

@@ -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",

View File

@@ -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": {
@@ -26,13 +32,7 @@
"path": "pages/mine/vip/index", "path": "pages/mine/vip/index",
"style": { "style": {
"navigationBarTitleText": "VIP", "navigationBarTitleText": "VIP",
"enablePullDownRefresh": true, "enablePullDownRefresh": false
"onReachBottomDistance": 100,
"app-plus": {
"bounce": "none",
"titleNView": false,
"popGesture": "none"
}
} }
}, },
{ {
@@ -163,6 +163,19 @@
"style": { "style": {
"navigationBarTitleText": "我的订单", "navigationBarTitleText": "我的订单",
"enablePullDownRefresh": false, "enablePullDownRefresh": false,
"onReachBottomDistance": 120,
"app-plus": {
"bounce": "none",
"titleNView": false,
"popGesture": "none"
}
}
},
{
"path": "pages/bookShop/refundDestination",
"style": {
"navigationBarTitleText": "钱款去向",
"enablePullDownRefresh": false,
"app-plus": { "app-plus": {
"bounce": "none", "bounce": "none",
"titleNView": false, "titleNView": false,
@@ -379,7 +392,8 @@
{ {
"path": "pages/course/superVip", "path": "pages/course/superVip",
"style": { "style": {
"navigationBarTitleText": "超V介绍" "navigationBarTitleText": "超V介绍",
"enablePullDownRefresh": false
} }
}, },
{ {
@@ -421,7 +435,8 @@
{ {
"path": "pages/course/outline", "path": "pages/course/outline",
"style": { "style": {
"navigationBarTitleText": "课程大纲" "navigationBarTitleText": "课程大纲",
"enablePullDownRefresh": false
} }
}, },
{ {
@@ -803,8 +818,7 @@
"style": { "style": {
"navigationBarTitleText" : "数据迁移" "navigationBarTitleText" : "数据迁移"
} }
} }
], ],
"globalStyle": { "globalStyle": {
"navigationBarTextStyle": "black", "navigationBarTextStyle": "black",

View File

@@ -90,6 +90,16 @@
v-if="orderContet.orderStatus == 5" v-if="orderContet.orderStatus == 5"
>已超时</text >已超时</text
> >
<text
class="orderState orderState6"
v-if="orderContet.orderStatus == 6"
>已退款</text
>
<text
class="orderState orderState7"
v-if="orderContet.orderStatus == 7"
>退款中</text
>
</view> </view>
<view <view
class="orderContent" class="orderContent"
@@ -775,6 +785,8 @@ export default {
this.OverOrder(); this.OverOrder();
} else if (data.text == "查看物流") { } else if (data.text == "查看物流") {
this.seeExpressDetail(this.orderContet); this.seeExpressDetail(this.orderContet);
} else if (data.text == "申请退款") {
this.confirmApplyRefund();
} }
}, },
async clickIcon(data) { async clickIcon(data) {
@@ -783,6 +795,53 @@ export default {
this.kefu(); this.kefu();
} }
}, },
confirmApplyRefund() {
uni.showModal({
title: "提示",
content: "确认申请订单内所有商品退款吗?",
confirmText: "确认",
cancelText: "取消",
success: (res) => {
if (res.confirm) {
this.submitOrderRefund();
}
},
});
},
submitOrderRefund() {
if (!this.orderContet || !this.orderContet.orderId) return;
this.$http
.request({
url: "book/buyOrder/refundOrder",
method: "POST",
data: {
order_id: this.orderContet.orderId,
},
header: {
"Content-Type": "application/json",
},
})
.then((res) => {
if (res.code == 0) {
uni.showToast({
icon: "none",
title: "退款成功",
});
this.getOrderList();
return;
}
uni.showToast({
icon: "none",
title: (res && (res.msg || res.errMsg)) || "退款失败",
});
})
.catch((e) => {
uni.showToast({
icon: "none",
title: (e && (e.msg || e.errMsg)) || "退款失败",
});
});
},
// 复制到剪切板 // 复制到剪切板
copyData(data) { copyData(data) {
uni.setClipboardData({ uni.setClipboardData({
@@ -1188,10 +1247,19 @@ export default {
text: "继续付款", text: "继续付款",
}); });
} }
if (this.orderContet.orderStatus == 0) { // medicine注释取消订单按钮
// if (this.orderContet.orderStatus == 0) {
// this.customButton.push({
// width: "160rpx",
// text: "取消订单",
// color: "#333",
// backgroundColor: "#f0f0f0",
// });
// }
if (this.orderContet.refundableStatus === true) {
this.customButton.push({ this.customButton.push({
width: "160rpx", width: "160rpx",
text: "取消订单", text: "申请退款",
color: "#333", color: "#333",
backgroundColor: "#f0f0f0", backgroundColor: "#f0f0f0",
}); });
@@ -1214,6 +1282,10 @@ export default {
this.titleStat = "待收到"; this.titleStat = "待收到";
} else if (this.orderContet.orderStatus == 3) { } else if (this.orderContet.orderStatus == 3) {
this.titleStat = "已完成"; this.titleStat = "已完成";
} else if (this.orderContet.orderStatus == 6) {
this.titleStat = "已退款";
} else if (this.orderContet.orderStatus == 7) {
this.titleStat = "退款中";
} }
if ( if (
this.orderContet.orderStatus >= 2 && this.orderContet.orderStatus >= 2 &&
@@ -1256,10 +1328,28 @@ export default {
}, },
}); });
}, },
checkPayTimeout(payItem) {
const createTime = payItem && payItem.createTime;
if (!createTime) return true;
const createdAt = new Date(String(createTime).replace(/-/g, "/")).getTime();
if (!createdAt) return true;
const expired = Date.now() - createdAt > 10 * 60 * 1000;
if (expired) {
uni.showModal({
title: "提示",
content: "订单已超时,不能继续支付,请重新下单",
confirmText: "知道了",
showCancel: false,
});
return false;
}
return true;
},
// 支付 // 支付
goPay(payItem) { goPay(payItem) {
console.log(payItem, "订单数据"); console.log(payItem, "订单数据");
if (!this.checkPayTimeout(payItem)) return;
if (payItem.paymentMethod == 2) { if (payItem.paymentMethod == 2) {
console.log("阿里支付"); console.log("阿里支付");
setPay( setPay(
@@ -1403,6 +1493,12 @@ export default {
.orderState5 { .orderState5 {
background-color: #787878; background-color: #787878;
} }
.orderState6 {
background-color: #f56c6c;
}
.orderState7 {
background-color: #f56c6c;
}
.guoqi { .guoqi {
font-size: 28rpx; font-size: 28rpx;
align-items: center; align-items: center;

View File

@@ -1,6 +1,6 @@
<template> <template>
<view <view
class="container commonPageBox commonDetailPage" class="container commonPageBox commonDetailPage order-list-page"
style="background-color: #f6f7fb" style="background-color: #f6f7fb"
> >
<!-- 公共组件-每个页面必须引入 --> <!-- 公共组件-每个页面必须引入 -->
@@ -12,7 +12,7 @@
</z-nav-bar> </z-nav-bar>
<view class="cateList flexbox"> <view class="cateList flexbox">
<common-sticky <common-sticky
itemStyle="width:20%; height: 68rpx;font-size:24rpx;" itemStyle="width:auto; padding: 0 20rpx; height: 68rpx;font-size:22rpx;"
:list="ordersTabs" :list="ordersTabs"
label="name" label="name"
:currentCateIndex="currentCateIndex" :currentCateIndex="currentCateIndex"
@@ -25,7 +25,6 @@
<!-- <view v-if="ordersListTab == 1"> --> <!-- <view v-if="ordersListTab == 1"> -->
<view <view
class="order_box" class="order_box"
:style="`height: calc(100% - ${(80 + statusBarHeight) * 2}rpx);`"
style="background-color: #f2f2f2" style="background-color: #f2f2f2"
> >
<common-list <common-list
@@ -111,6 +110,16 @@
v-show="slotProps.row.orderStatus == 5" v-show="slotProps.row.orderStatus == 5"
>已过期</text >已过期</text
> >
<text
class="orderstatus"
v-show="slotProps.row.orderStatus == 6"
>已退款</text
>
<text
class="orderstatus"
v-show="slotProps.row.orderStatus == 7"
>退款中</text
>
</view> </view>
</view> </view>
<view v-if="slotProps.row.orderType == 'trainingClass'" class="bookinfolist"> <view v-if="slotProps.row.orderType == 'trainingClass'" class="bookinfolist">
@@ -392,17 +401,12 @@
</view> </view>
<view <view
class="operation_box boxShadow" class="btns flexbox"
v-if="slotProps.row.isShowMore == true" :class="{ 'btns-no-more': !hasMoreActions(slotProps.row) }"
style="margin-top: 10rpx"
> >
<view <view
v-if="slotProps.row.orderStatus == 0" v-if="hasMoreActions(slotProps.row)"
@click.native.stop="canceOrder(slotProps.row)"
>取消订单</view
>
</view>
<view class="btns flexbox" style="margin-top: 10rpx">
<view
class="left" class="left"
style="color: #c0c4cc" style="color: #c0c4cc"
@click.native.stop=" @click.native.stop="
@@ -442,6 +446,21 @@
v-if="slotProps.row.orderStatus == 3" v-if="slotProps.row.orderStatus == 3"
>申请售后</view >申请售后</view
> >
<view
class="orderstatusbtn"
v-if="
slotProps.row.orderStatus == 6 ||
slotProps.row.orderStatus == 7
"
@click.stop="goRefundDestination(slotProps.row)"
>钱款去向</view
>
<view
class="orderstatusbtn"
v-if="slotProps.row.refundableStatus === true"
@click.stop="confirmApplyRefund(slotProps.row)"
>申请退款</view
>
<!-- <view <!-- <view
class="orderstatusbtn" class="orderstatusbtn"
v-if="item.orderStatus == 3 && userRecordid == null" v-if="item.orderStatus == 3 && userRecordid == null"
@@ -615,12 +634,7 @@ export default {
come: "2", come: "2",
isShowTab: false, isShowTab: false,
isLoadingHide: false, isLoadingHide: false,
moreList: [ moreList: [],
{
name: "取消订单",
key: "false",
},
],
currentCateIndex: 0, currentCateIndex: 0,
pagination: { pagination: {
// 请求参数 // 请求参数
@@ -671,6 +685,16 @@ export default {
value: 3, value: 3,
badge: {}, badge: {},
}, },
{
name: "已退款",
value: 6,
badge: {},
},
{
name: "退款中",
value: 7,
badge: {},
},
], ],
selectOrderInfo: {}, selectOrderInfo: {},
ordersListTab: 1, ordersListTab: 1,
@@ -696,14 +720,14 @@ export default {
}, },
onPullDownRefresh() { onPullDownRefresh() {
uni.stopPullDownRefresh(); uni.stopPullDownRefresh();
this.pagination.page = 1;
this.newestpage = 1; this.newestpage = 1;
this.newList = []; this.newList = [];
this.getBookList(this.ordersListTab, false); this.getBookList(this.ordersListTab, false);
}, },
onReachBottom() { onReachBottom() {
this.newestpage++; // App 端由页面滚动触底加载;与 scroll-view 的 @lower 共用同一套分页逻辑
this.getBookList(this.ordersListTab, false); this.onReachBottom1();
}, },
onLoad(e) { onLoad(e) {
this.windowWidth = uni.getSystemInfoSync().windowWidth; this.windowWidth = uni.getSystemInfoSync().windowWidth;
@@ -742,21 +766,31 @@ export default {
}, },
selectClick(index) { selectClick(index) {
console.log("index at line 609:", index); console.log("index at line 609:", index);
if (index.key == "false") { if (index.key == "cancelOrder") {
this.isShowMore = false; this.isShowMore = false;
this.canceOrder(this.selectOrderInfo); this.canceOrder(this.selectOrderInfo);
} }
}, },
openMore(row, index) { openMore(row, index) {
const actions = this.getMoreActions(row);
if (!actions.length) return;
this.moreList = actions;
this.selectOrderInfo = row; this.selectOrderInfo = row;
this.isShowMore = true; this.isShowMore = true;
}, },
hasMoreActions(row) {
return this.getMoreActions(row).length > 0;
},
getMoreActions(row) {
const actions = [];
// 取消订单功能已屏蔽,更多操作为空时不展示“更多”按钮
return actions;
},
handleCopy(value, title) { handleCopy(value, title) {
this.$commonJS.handleCopy(value, title); this.$commonJS.handleCopy(value, title);
}, },
onReachBottom1() { onReachBottom1() {
// 上拉加载 // 上拉加载H5 走 scroll-view @lowerApp 走页面 onReachBottom
// 当列表数量不大于或等于总数量,则再次调用接口请求数据
if (this.newList.length >= this.pagination.total) return; if (this.newList.length >= this.pagination.total) return;
this.pagination.page++; this.pagination.page++;
this.getBookList(this.ordersListTab, false); this.getBookList(this.ordersListTab, false);
@@ -813,6 +847,60 @@ export default {
val.orderSn, val.orderSn,
}); });
}, },
goRefundDestination(row) {
uni.navigateTo({
url: "/pages/bookShop/refundDestination?orderId=" + row.orderId,
});
},
confirmApplyRefund(row) {
uni.showModal({
title: "提示",
content: "确认申请订单内所有商品退款吗?",
confirmText: "确认",
cancelText: "取消",
success: (res) => {
if (res.confirm) {
this.submitOrderRefund(row);
}
},
});
},
submitOrderRefund(orderRow) {
if (!orderRow || !orderRow.orderId) return;
this.$http
.request({
url: "book/buyOrder/refundOrder",
method: "POST",
data: {
orderId: orderRow.orderId,
},
header: {
"Content-Type": "application/json",
},
})
.then((res) => {
if (res.code == 0) {
uni.showToast({
icon: "none",
title: "退款成功",
});
this.pagination.page = 1;
this.newList = [];
this.getBookList(this.ordersListTab, false);
return;
}
uni.showToast({
icon: "none",
title: (res && (res.msg || res.errMsg)) || "退款失败",
});
})
.catch((e) => {
uni.showToast({
icon: "none",
title: (e && (e.msg || e.errMsg)) || "退款失败",
});
});
},
getBookList(flag, refreshflag) { getBookList(flag, refreshflag) {
this.isLoadingHide = false; this.isLoadingHide = false;
var that = this; var that = this;
@@ -843,6 +931,8 @@ export default {
// * 3已完成 // * 3已完成
// * 4: 交易失败 // * 4: 交易失败
// * 5: 已过期 // * 5: 已过期
// * 6: 已退款
// * 7: 退款中
console.log("res at line 757:", res); console.log("res at line 757:", res);
that.map = res.data; that.map = res.data;
@@ -872,7 +962,7 @@ export default {
var params = { var params = {
userId: this.userInfo.id, userId: this.userInfo.id,
come: this.come, come: this.come,
orderStatus: flag == -1 ? "" : flag, //传null为全部订单状态 0-未付款 1-待发出 2-待收到 3-交易成功 4-交易失败 5-过期 orderStatus: flag == -1 ? "" : flag, //传null为全部订单状态 0-未付款 1-待发出 2-待收到 3-交易成功 4-交易失败 5-过期 6-已退款 7-退款中
...this.pagination, ...this.pagination,
// limit: 10, // limit: 10,
// page: this.newestpage, // page: this.newestpage,
@@ -908,9 +998,27 @@ export default {
console.log(e); console.log(e);
}); });
}, },
checkPayTimeout(payItem) {
const createTime = payItem && payItem.createTime;
if (!createTime) return true;
const createdAt = new Date(String(createTime).replace(/-/g, "/")).getTime();
if (!createdAt) return true;
const expired = Date.now() - createdAt > 10 * 60 * 1000;
if (expired) {
uni.showModal({
title: "提示",
content: "订单已超时,不能继续支付,请重新下单",
confirmText: "知道了",
showCancel: false,
});
return false;
}
return true;
},
// 支付 // 支付
goPay(payItem) { goPay(payItem) {
console.log(payItem, "订单数据"); console.log(payItem, "订单数据");
if (!this.checkPayTimeout(payItem)) return;
if (payItem.paymentMethod == 2) { if (payItem.paymentMethod == 2) {
console.log("阿里支付"); console.log("阿里支付");
setPay( setPay(
@@ -1542,6 +1650,15 @@ export default {
} }
} }
} }
.btns.btns-no-more {
justify-content: flex-end;
.right {
width: auto;
max-width: 100%;
}
}
} }
.mb30 { .mb30 {
@@ -1584,16 +1701,19 @@ export default {
} }
/deep/.u-tabs__wrapper__nav__item { /deep/.u-tabs__wrapper__nav__item {
padding: 0 !important; // padding: 0 !important;
} }
.commonDetailPage { .order-list-page.commonDetailPage {
background-color: $themeBgColor; background-color: $themeBgColor;
height: calc(100vh); height: auto !important;
min-height: 100vh;
} }
.order_box { .order_box {
height: auto;
padding: 20rpx; padding: 20rpx;
padding-bottom: 40rpx;
} }
/deep/.order_box .list_item { /deep/.order_box .list_item {

View File

@@ -0,0 +1,27 @@
<template>
<view class="page-wrap">
<public-module></public-module>
<common-refund-destination :order-id="orderId" :http="$http" />
</view>
</template>
<script>
export default {
data() {
return {
orderId: '',
}
},
onLoad(options) {
if (options && options.orderId != null) {
this.orderId = options.orderId
}
},
}
</script>
<style scoped>
.page-wrap {
min-height: 100vh;
}
</style>

View File

@@ -519,6 +519,17 @@
</view> </view>
</view> </view>
</u-popup> </u-popup>
<u-modal
:show="presaleRemarkModalShow"
title="提示"
:content="presaleRemarkModalContent"
:showCancelButton="true"
confirmText="继续购买"
cancelText="取消"
@confirm="handlePresaleRemarkConfirm"
@cancel="handlePresaleRemarkCancel"
@close="handlePresaleRemarkCancel"
></u-modal>
</view> </view>
</template> </template>
@@ -616,6 +627,9 @@
orderModalShowInfo: {}, orderModalShowInfo: {},
orderModalShow: false, orderModalShow: false,
presaleRemarkModalShow: false,
presaleRemarkModalContent: "",
presaleRemarkModalResolve: null,
payType: 1, payType: 1,
freightNum: 0, freightNum: 0,
addressData: { addressData: {
@@ -1350,6 +1364,62 @@
this.content = this.remark; this.content = this.remark;
} }
}, },
openPresaleRemarkModal(content) {
this.presaleRemarkModalContent = content;
this.presaleRemarkModalShow = true;
return new Promise((resolve) => {
this.presaleRemarkModalResolve = resolve;
});
},
handlePresaleRemarkConfirm() {
this.presaleRemarkModalShow = false;
if (this.presaleRemarkModalResolve) {
const resolve = this.presaleRemarkModalResolve;
this.presaleRemarkModalResolve = null;
resolve(true);
}
},
handlePresaleRemarkCancel() {
this.presaleRemarkModalShow = false;
if (this.presaleRemarkModalResolve) {
const resolve = this.presaleRemarkModalResolve;
this.presaleRemarkModalResolve = null;
resolve(false);
}
},
async checkPresaleRemark() {
if (this.pageType != "goods") {
return true;
}
const productIds = this.goodsDataList
.map((e) => e.productId)
.filter((id) => id)
.join(",");
if (!productIds || !this.urlList.presaleRemark) {
return true;
}
try {
const res = await this.$http.request({
url: `${this.urlList.presaleRemark}`,
method: "POST",
data: {
productIds,
},
header: {
"Content-Type": "application/json",
},
});
const remark =
res && typeof res.remark == "string" ? res.remark.trim() : "";
if (!remark) {
return true;
}
return await this.openPresaleRemarkModal(remark);
} catch (error) {
console.log("presaleRemark error:", error);
return true;
}
},
async goBuyJie() { async goBuyJie() {
if (this.pageType == "vip") { if (this.pageType == "vip") {
if (this.radioValue != "1") { if (this.radioValue != "1") {
@@ -1457,6 +1527,11 @@
}); });
thisproduct = thisproduct.join(","); thisproduct = thisproduct.join(",");
} }
const passPresaleRemark = await this.checkPresaleRemark();
if (!passPresaleRemark) {
this.buyingFlag = false;
return;
}
if ( if (
this.historyOrderInfo && this.historyOrderInfo &&
thisproduct == this.historyOrderInfo.product && thisproduct == this.historyOrderInfo.product &&
@@ -2437,4 +2512,4 @@
font-size: 24rpx; font-size: 24rpx;
} }
</style> </style>

View File

@@ -249,9 +249,9 @@ export default {
gotoDetail(v) { gotoDetail(v) {
this.$emit("hancleClick", v); this.$emit("hancleClick", v);
}, },
onHandleClickBuy() { onHandleClickBuy(e) {
this.$emit("selectGoodsData", this.selectGoodsData); this.$emit("selectGoodsData", this.selectGoodsData);
this.$emit("onHandleClickBuy"); this.$emit("onHandleClickBuy", e);
}, },
}, },
onBackPress() { onBackPress() {
@@ -430,4 +430,8 @@ export default {
font-weight: 700; font-weight: 700;
} }
} }
.title_list {
margin-bottom: 20rpx;
}
</style> </style>

View File

@@ -1,6 +1,6 @@
<template> <template>
<!-- <scroll-view class="scroll-view_H cateList" scroll-x="true" scroll-left="0"> --> <!-- <scroll-view class="scroll-view_H cateList" scroll-x="true" scroll-left="0"> -->
<view class="" style="background-color: #fff; width: 100%"> <view class="" style="background-color: #fff; width: 100%; padding: 0 20rpx;">
<u-tabs <u-tabs
lineWidth="30" lineWidth="30"
lineColor="#258feb" lineColor="#258feb"

View File

@@ -17,9 +17,10 @@
<CommonCourseVideo <CommonCourseVideo
:video-list="videoArray" :video-list="videoArray"
:current-index="currentCateIndex !== null ? currentCateIndex : 0" :current-index="currentCateIndex !== null ? currentCateIndex : 0"
:course="{courseTitle:options.navTitle, chapterTitle: curriculumData.title}" :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-info="userInfo"
/> />
<view class="" style="border-top: 2px solid #2979ff;"> <view class="" style="border-top: 2px solid #2979ff;">
@@ -120,7 +121,7 @@
<view class="page-body"> <view class="page-body">
<view class='wrapper'> <view class='wrapper'>
<view class="editor-wrapper"> <view class="editor-wrapper">
<editor @input="editorIput" id="editor" class="ql-container" placeholder="请输入您的见解..." <editor @input="editorIput" id="editor" class="ql-container" placeholder="请您一次性提交答题内容,提交后会进入评分流程"
show-img-size show-img-toolbar show-img-resize show-img-size show-img-toolbar show-img-resize
@statuschange="onStatusChange" :read-only="readOnly" @statuschange="onStatusChange" :read-only="readOnly"
@ready="onEditorReady"> @ready="onEditorReady">
@@ -171,6 +172,7 @@
import { import {
mapState mapState
} from "vuex"; } from "vuex";
export default { export default {
components: { components: {
courseDescription, //课程说明 courseDescription, //课程说明
@@ -327,11 +329,9 @@
this.hideNextVideo() this.hideNextVideo()
}, },
onUnload() { onUnload() {
}, },
onHide() { onHide() {
console.log('回去了 .....................'); console.log('回去了 .....................');
}, },
onPullDownRefresh() { onPullDownRefresh() {
uni.stopPullDownRefresh(); uni.stopPullDownRefresh();
@@ -412,7 +412,7 @@
}, },
getMyQuestAnswer(chapterId) { getMyQuestAnswer(chapterId) {
$http.request({ $http.request({
url: "/common/class/getQuesReplyInfo", url: "common/class/getQuesReplyInfo",
method: "POST", method: "POST",
data: { data: {
"relationId": chapterId, "relationId": chapterId,
@@ -934,9 +934,9 @@
} }
.u-grid-list { // .u-grid-list {
// height: 40rpx; // // height: 40rpx;
} // }
.searchList { .searchList {
.item { .item {
@@ -1133,7 +1133,8 @@
button { button {
font-size: 32rpx; font-size: 32rpx;
@include theme('btn_bg') color: #fff; @include theme('btn_bg');
color: #fff;
height: 80rpx; height: 80rpx;
line-height: 80rpx; line-height: 80rpx;
border-radius: 50rpx; border-radius: 50rpx;
@@ -1236,11 +1237,11 @@
// align-items: center; // align-items: center;
} }
.headImage { // .headImage {
// height: 400rpx !important; // // height: 400rpx !important;
} // }
.commonDetailPage {} // .commonDetailPage {}
.curriulum_box { .curriulum_box {
margin-top: 20rpx; margin-top: 20rpx;
@@ -1263,9 +1264,9 @@
} }
} }
/deep/.titleItem { // /deep/.titleItem {
// width: calc(100% - 120rpx) !important; // // width: calc(100% - 120rpx) !important;
} // }
/deep/.scroll-view-item:nth-child(2n-1) { /deep/.scroll-view-item:nth-child(2n-1) {
background-color: transparent !important; background-color: transparent !important;
@@ -1396,7 +1397,7 @@
width: calc(100% - 150rpx) !important; width: calc(100% - 150rpx) !important;
.aui-text-danger { .aui-text-danger {
display: inline-block; // display: inline-block;
float: right; float: right;
} }
} }

View File

@@ -1263,8 +1263,10 @@
role = '心理学'; role = '心理学';
}else if(type==9){ }else if(type==9){
role = '中西汇通学'; role = '中西汇通学';
}else if(type==10){
role = '妇幼生殖';
} }
this.goBuyTitle = '尊贵的'+role+'VIP您的有效期到'+res.userVip.endTime; this.goBuyTitle = '尊贵的'+role+'VIP您的有效期到'+res.userVip.endTime+'(不包含论坛)';
this.goBuyType = 1; this.goBuyType = 1;
}else{ //否则没有开通vip }else{ //否则没有开通vip
this.goBuyTitle = ''; this.goBuyTitle = '';
@@ -1303,12 +1305,15 @@
text = '心理学'; text = '心理学';
}else if(item=='9'){ }else if(item=='9'){
text = '中西汇通学'; text = '中西汇通学';
}else if(item=='10'){
text = '妇幼生殖';
} }
this.textList.push(text); this.textList.push(text);
}); });
const joinedText = this.textList.join('/'); const joinedText = this.textList.join('/');
this.goBuyTitle = '购买'+joinedText+'VIP即可畅享更多专属权益'; this.goBuyTitle = '购买'+joinedText+'VIP即可畅享更多专属权益(不包含论坛)';
} }
}) })
}, },

View File

@@ -91,10 +91,7 @@
// 隐藏原生的tabbar // 隐藏原生的tabbar
uni.hideTabBar(); uni.hideTabBar();
}, },
onPullDownRefresh() { components: {
uni.stopPullDownRefresh()
},
components: {
// musicPlay // musicPlay
}, },
//方法 //方法

View File

@@ -35,13 +35,13 @@
<view class="vip_qx"> <view class="vip_qx">
<text class="font_bold" style=" display: block;" v-if="item.type==1||item.type==2">超级VIP权限</text> <text class="font_bold" style=" display: block;" v-if="item.type==1||item.type==2">超级VIP权限</text>
<text class="font_bold" style=" display: block;" v-else>VIP权限</text> <text class="font_bold" style=" display: block;" v-else>VIP权限</text>
<view class="vip_qx_v" v-if="item.type==1">无限制观看吴门医述APP中医学中西汇通学针灸学肿瘤学四个板块任意课程</view> <view class="vip_qx_v" v-if="item.type==1">无限制观看吴门医述APP中医学中西汇通学针灸学肿瘤学妇幼生殖五个板块任意课程不包含论坛;</view>
<view class="vip_qx_v" v-else-if="item.type==2">无限制观看众妙之门APP与心灵空间APP任意课程</view> <view class="vip_qx_v" v-else-if="item.type==2">无限制观看众妙之门APP与心灵空间APP任意课程不包含论坛</view>
<view class="vip_qx_v" v-else-if="item.type==7">无限制观看众妙之门APP任意课程</view> <view class="vip_qx_v" v-else-if="item.type==7">无限制观看众妙之门APP任意课程不包含论坛</view>
<view class="vip_qx_v" v-else-if="item.type == 8" <view class="vip_qx_v" v-else-if="item.type == 8"
>无限制观看心灵空间APP任意课程</view >无限制观看心灵空间APP任意课程不包含论坛</view
> >
<view class="vip_qx_v" v-else>无限制观看吴门医述APP{{item.title.replace(/VIP/g, '')}}板块任意课程</view> <view class="vip_qx_v" v-else>无限制观看吴门医述APP{{item.title.replace(/VIP/g, '')}}板块任意课程不包含论坛</view>
<view class="vip_qx_v"> <view class="vip_qx_v">
<text v-if="item.type==1||item.type==2">{{item.title.replace(/超级VIP/g, '')}}</text> <text v-if="item.type==1||item.type==2">{{item.title.replace(/超级VIP/g, '')}}</text>

View File

@@ -790,8 +790,13 @@ export default {
this.$refs.commonSelectGoods.open(); this.$refs.commonSelectGoods.open();
}, },
//点击下单按钮 //点击下单按钮
onHandleClickBuy() { onHandleClickBuy(e) {
if(this.buttonType==0){ //如果是加入购物车 if (e && e.content && e.content.text === "购物车") {
this.onHandleClick();
return;
}
const clickType = typeof (e && e.index) === "number" ? e.index : this.buttonType;
if(clickType==0){ //如果是加入购物车
console.log('剩余', this.selectGoodsData.productStock) console.log('剩余', this.selectGoodsData.productStock)
if(this.selectGoodsData.productStock==0){ if(this.selectGoodsData.productStock==0){
uni.showToast({ uni.showToast({

View File

@@ -132,6 +132,7 @@ export default {
list: "app/phone.do?getCourseDetail_new", list: "app/phone.do?getCourseDetail_new",
initPrepareOrder: "common/buyOrder/initPrepareOrder", initPrepareOrder: "common/buyOrder/initPrepareOrder",
buyOrder: "book/buyOrder/placeOrder", buyOrder: "book/buyOrder/placeOrder",
presaleRemark: "book/buyOrder/presaleRemark",
curriculumInfo: "app/phone.do?getCourseInfo", curriculumInfo: "app/phone.do?getCourseInfo",
detailInfo: "app/phoneDoctor.do?getTaiHuClassInfo_new", detailInfo: "app/phoneDoctor.do?getTaiHuClassInfo_new",
userInfo: "common/user/getUserInfo", userInfo: "common/user/getUserInfo",

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,12 @@
</view> </view>
<view class="userInfoBox" style="margin-left: 20rpx;"> <view class="userInfoBox" style="margin-left: 20rpx;">
<template> <template>
<view class="name">{{ userMes.nickname ? userMes.nickname : "未设置" }}</view> <view class="name">
{{ userMes.nickname ? userMes.nickname : "未设置" }}
<text v-if="userMes.profile" class="user-profile">({{userMes.profile}})</text>
</view>
<!-- <u-tag v-if="userMes.profile" :text="userMes.profile" size="mini" plain plainFill type="success"></u-tag> -->
</template> </template>
<template v-if="userMes.tel"> <template v-if="userMes.tel">
<view class="phone">手机号({{ userMes.tel }})</view> <view class="phone">手机号({{ userMes.tel }})</view>
@@ -41,6 +46,12 @@
</view> </view>
</view> </view>
</template> </template>
<template>
<view>
<u-tag v-if="userMes.todayWatch" :text="userMes.todayWatch" size="mini" plain plainFill type="success" class="watch-time"></u-tag>
<u-tag v-if="userMes.totalWatch" :text="userMes.totalWatch" size="mini" plain plainFill class="watch-time"></u-tag>
</view>
</template>
</view> </view>
</view> </view>
@@ -128,13 +139,14 @@
<view class="xiugai boxShadow box_fillet"> <view class="xiugai boxShadow box_fillet">
<common-list :dataList="pageList" @hancleClick="handleClickTab" label="name"> <common-list :dataList="pageList" @hancleClick="handleClickTab" label="name">
<template slot="rightSlot" slot-scope="slotProps"> <template slot="rightSlot" slot-scope="slotProps">
              <text <text
                class="fdButtonBox aui-text-success" v-if="slotProps.row.contentType&&slotProps.row.contentType == 'hufen'&&hufenNumber>0"
                v-if="slotProps.row.contentType&&slotProps.row.contentType == 'hufen'&&hufenNumber>0" class="fdButtonBox aui-text-success"
                style="line-height: 40rpx; font-size: 40rpx;color: #258feb;float: right;" style="line-height: 40rpx; font-size: 40rpx;color: #258feb;float: right;"
                >{{ hufenNumber }}<text style="font-size: 30rpx;margin-left: 4rpx;">湖分</text></text >
              > {{ hufenNumber }}<text style="font-size: 30rpx;margin-left: 4rpx;">湖分</text>
            </template> </text>
</template>
</common-list> </common-list>
</view> </view>
</view> </view>
@@ -483,6 +495,9 @@
if (this.userInfo.id != undefined) { if (this.userInfo.id != undefined) {
this.$http.post("common/user/getUserInfo").then((res) => { this.$http.post("common/user/getUserInfo").then((res) => {
this.userMes = res.result; this.userMes = res.result;
this.userMes.profile = res.des || '';
this.userMes.todayWatch = res.todayWatch || '';
this.userMes.totalWatch = res.totalWatch || '';
}); });
} }
}, },
@@ -599,9 +614,12 @@
}else if(item.type=='9'){ }else if(item.type=='9'){
item.text = '中西汇通学'; item.text = '中西汇通学';
this.textList.push(item.text); this.textList.push(item.text);
}else if(item.type=='1'){ } else if (item.type == "10") {
item.text = "妇幼生殖";
this.textList.push(item.text);
} else if(item.type=='1'){
item.text = '医学S'; item.text = '医学S';
}else if(item.type=='2'){ } else if(item.type=='2'){
item.text = '国学心理学S'; item.text = '国学心理学S';
} }
}); });
@@ -636,15 +654,23 @@
view { view {
.name { .name {
width: 100%; width: 90%;
font-weight: bold; font-weight: bold;
font-size: 32rpx; font-size: 32rpx;
color: #6990c7 !important; color: #6990c7 !important;
line-height: 1.2;
}
.user-profile{
font-size: 28rpx;
font-weight: normal;
display: inline-block;
} }
.phone { .phone {
font-size: 26rpx; font-size: 26rpx;
color: #6990c7 !important; color: #6990c7 !important;
margin: 6rpx 0;
} }
.per_user_img { .per_user_img {
@@ -654,6 +680,12 @@
margin-left: 10rpx; margin-left: 10rpx;
vertical-align: super; vertical-align: super;
} }
.watch-time {
margin-top: 6rpx;
display: inline-block;
margin-right: 10rpx;
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -88,21 +88,21 @@
> >
<text class="font_bold" style="display: block" v-else>VIP权限</text> <text class="font_bold" style="display: block" v-else>VIP权限</text>
<view class="vip_qx_v" v-if="item.type == 1" <view class="vip_qx_v" v-if="item.type == 1"
>无限制观看吴门医述APP中医学中西汇通学针灸学肿瘤学四个板块任意课程</view >无限制观看吴门医述APP中医学中西汇通学针灸学肿瘤学妇幼生殖五个板块任意课程不包含论坛</view
> >
<view class="vip_qx_v" v-else-if="item.type == 2" <view class="vip_qx_v" v-else-if="item.type == 2"
>无限制观看众妙之门APP与心灵空间APP任意课程</view >无限制观看众妙之门APP与心灵空间APP任意课程不包含论坛</view
> >
<view class="vip_qx_v" v-else-if="item.type == 7" <view class="vip_qx_v" v-else-if="item.type == 7"
>无限制观看众妙之门APP任意课程</view >无限制观看众妙之门APP任意课程不包含论坛</view
> >
<view class="vip_qx_v" v-else-if="item.type == 8" <view class="vip_qx_v" v-else-if="item.type == 8"
>无限制观看心灵空间APP任意课程</view >无限制观看心灵空间APP任意课程不包含论坛</view
> >
<view class="vip_qx_v" v-else <view class="vip_qx_v" v-else
>无限制观看吴门医述APP{{ >无限制观看吴门医述APP{{
item.title.replace(/VIP/g, "") item.title.replace(/VIP/g, "")
}}板块任意课程</view }}板块任意课程不包含论坛</view
> >
<view class="vip_qx_v"> <view class="vip_qx_v">

View File

@@ -71,17 +71,19 @@
> >
<template slot="labelSlot" slot-scope="slotProps"> <template slot="labelSlot" slot-scope="slotProps">
<view class="label_content AC_List"> <view class="label_content AC_List">
<view class="left"> <view style=" display: flex; align-items: center; justify-content: space-between;">
<view class="title" v-if="slotProps.row.productName">{{ slotProps.row.productName }}</view> <view class="left">
<view class="title" v-else>{{ slotProps.row.orderType }}</view> <view class="title">{{ slotProps.row.productName || slotProps.row.orderType}}</view>
</view> </view>
<view <view
:class="`right ${ :class="`right ${
slotProps.row.changeAmount > 0 ? 'Hot' : '' slotProps.row.changeAmount > 0 ? 'Hot' : ''
}`" }`"
> >
<text v-if="slotProps.row.changeAmount > 0">+</text> <text v-if="slotProps.row.changeAmount > 0">+</text>
<text>{{ slotProps.row.changeAmount }}</text> </view> <text>{{ slotProps.row.changeAmount }}</text>
</view>
</view>
<view class="AC_mark" v-if="slotProps.row.remark">{{slotProps.row.remark}}</view> <view class="AC_mark" v-if="slotProps.row.remark">{{slotProps.row.remark}}</view>
<view class="AC_note" v-if="slotProps.row.note&&slotProps.row.note!='null'">说明{{slotProps.row.note}}</view> <view class="AC_note" v-if="slotProps.row.note&&slotProps.row.note!='null'">说明{{slotProps.row.note}}</view>
<view class="AC_time">{{ slotProps.row.createTime }}</view> <view class="AC_time">{{ slotProps.row.createTime }}</view>
@@ -339,6 +341,12 @@ export default {
.AC_List { .AC_List {
overflow: hidden; overflow: hidden;
.title,
.AC_note,
.AC_mark {
word-break: break-word;
overflow-wrap: break-word;
}
.left { .left {
width: calc(100% - 120rpx) !important; width: calc(100% - 120rpx) !important;
font-weight: 700; font-weight: 700;
@@ -355,6 +363,19 @@ export default {
font-size: 32rpx; font-size: 32rpx;
font-weight: 700; font-weight: 700;
color: #333; color: #333;
}
> view:first-child {
.left {
flex: 1;
min-width: 0;
width: auto !important;
float: none;
}
.right {
flex-shrink: 0;
float: none;
width: auto !important;
}
} }
.AC_title { .AC_title {

View File

@@ -46,9 +46,9 @@
<view class="in"> <view class="in">
<view class="uni-textarea"> <view class="uni-textarea">
<textarea v-show="false" placeholder-style="font-size:26rpx" v-model="form.content" <textarea v-show="false" placeholder-style="font-size:26rpx" v-model="form.content"
auto-height placeholder="请输入内容" /> auto-height placeholder="请您一次性提交答题内容,提交后会进入评分流程" />
<view class="editor-wrapper"> <view class="editor-wrapper">
<editor @input="editorIput" id="editor" class="ql-container" placeholder="请输入内容..." show-img-size <editor @input="editorIput" id="editor" class="ql-container" placeholder="请您一次性提交答题内容,提交后会进入评分流程" show-img-size
show-img-toolbar show-img-resize @statuschange="onStatusChange" show-img-toolbar show-img-resize @statuschange="onStatusChange"
:read-only="readOnly" @ready="onEditorReady"> :read-only="readOnly" @ready="onEditorReady">
</editor> </editor>
@@ -537,4 +537,4 @@
} }
} }
} }
</style> </style>

View File

@@ -1116,14 +1116,14 @@ export default {
}, },
// 改变班级状态 // 改变班级状态
changeClassStatu(statusCode) { changeClassStatu(statusCode) {
if(this.classStatus){ if(this.classStatus){
return return
} }
this.classStatus = true; this.classStatus = true;
debounce(async () => { debounce(async () => {
let that = this; let that = this;
that.opClass(statusCode); that.opClass(statusCode);
}, 300); }, 300);
}, },
// 未开班和进行中状态下,学员的信息,带买课标识 // 未开班和进行中状态下,学员的信息,带买课标识
async getStudentsList() { async getStudentsList() {

View File

@@ -111,7 +111,7 @@
<view class="in"> <view class="in">
<view class="uni-textarea"> <view class="uni-textarea">
<textarea placeholder-style="font-size:26rpx" v-model="form.content" maxlength="-1" <textarea placeholder-style="font-size:26rpx" v-model="form.content" maxlength="-1"
auto-height placeholder="请输入内容" /> auto-height placeholder="请您一次性提交答题内容,提交后会进入评分流程" />
</view> </view>
</view> </view>
@@ -750,4 +750,4 @@
background-image: linear-gradient(30deg, #d4eaf0 0%, #d4eaf0 50%, #fdf0ed 100%); background-image: linear-gradient(30deg, #d4eaf0 0%, #d4eaf0 50%, #fdf0ed 100%);
min-height: 100vh; min-height: 100vh;
} }
</style> </style>

View File

@@ -642,11 +642,16 @@ export default {
//存储的需要固定分类 //存储的需要固定分类
this.fixed = uni.getStorageSync("fixed"); this.fixed = uni.getStorageSync("fixed");
//固定分类 //固定分类
if (this.fixed) { if (this.currentIndex === null || this.currentIndex === undefined) {
this.curseClick(this.currentItem, this.currentIndex);
} else {
this.currentIndex = 0; this.currentIndex = 0;
this.currentItem = null; }
if (
this.fixed &&
this.currentItem &&
this.currentIndex !== null &&
this.currentIndex !== undefined
) {
this.curseClick(this.currentItem, this.currentIndex);
} }
uni.hideTabBar(); uni.hideTabBar();
// #ifdef APP-PLUS // #ifdef APP-PLUS

79
pages/test/test.vue Normal file
View 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>

View File

@@ -389,4 +389,6 @@ button::after {
} }
} }
uni-text {
white-space: normal;
}

View File

@@ -0,0 +1,14 @@
## 1.0.62024-11-22
- 修复 HarmonyOS Next 上调用 setUserCaptureScreen 报错的 Bug
## 1.0.52024-10-14
- 新增 支持 HarmonyOS Next 调用
## 1.0.42023-03-24
新增开启/关闭防截屏功能
## 1.0.32023-03-17
修复android平台 部分场景下js可能报错的问题
## 1.0.22023-03-16
修复Android平台在小米设备无法监听的问题 修复Android平台调用uni.onUserCaptureScreen必然会触发回调的问题
## 1.0.12022-10-27
修改插件描述
## 1.0.02022-10-26
支持安卓、iOS、微信小程序平台

View 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
}

View 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"
}
}
}
}
}

View 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)

View 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);
}
}
}

View File

@@ -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);
}
}
})
}

View 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)
}
}
}

View 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
}

View File

@@ -0,0 +1,7 @@
export function onUserCaptureScreen (callback) {
return wx.onUserCaptureScreen(callback)
}
export function offUserCaptureScreen (callback) {
return wx.offUserCaptureScreen(callback)
}

View 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] ?? "";
}
}

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -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>

View File

@@ -1,3 +0,0 @@
{
"prompt" : "template"
}

File diff suppressed because one or more lines are too long

View File

@@ -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()})([]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -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"}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 703 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Some files were not shown because too many files have changed in this diff Show More