From 598450e1a3436c25b9dd857e76cf602e39e18efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E6=98=8E=E6=98=8E?= <970899069@qq.com> Date: Mon, 24 Apr 2023 15:48:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=89=88=E6=9C=AC=E6=A3=80?= =?UTF-8?q?=E6=B5=8B=EF=BC=8C=E5=90=88=E5=90=8C=E8=AE=B0=E5=BD=95=EF=BC=8C?= =?UTF-8?q?=E4=B8=9A=E7=BB=A9=E8=B4=A6=E6=88=B7=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apis/index.js | 4 +- apis/interfaces/user.js | 17 ++ manifest.json | 21 ++- pages.json | 26 +++- pages/user/contract.vue | 146 ++++++++++++++++++ pages/user/index.vue | 144 +++++++++++++---- pages/user/set.vue | 8 + pages/user/signLog.vue | 80 ++++++++++ pages/user/team.vue | 3 + static/icons/user_nav_08.png | Bin 0 -> 5246 bytes .../uni-usercapturescreen/changelog.md | 10 ++ uni_modules/uni-usercapturescreen/index.d.ts | 18 +++ .../uni-usercapturescreen/package.json | 92 +++++++++++ uni_modules/uni-usercapturescreen/readme.md | 21 +++ .../utssdk/app-android/config.json | 3 + .../utssdk/app-android/index.uts | 139 +++++++++++++++++ .../utssdk/app-ios/config.json | 3 + .../utssdk/app-ios/index.uts | 146 ++++++++++++++++++ .../utssdk/interface.uts | 122 +++++++++++++++ .../utssdk/mp-weixin/index.js | 7 + 20 files changed, 969 insertions(+), 41 deletions(-) create mode 100644 pages/user/contract.vue create mode 100644 pages/user/signLog.vue create mode 100644 static/icons/user_nav_08.png create mode 100644 uni_modules/uni-usercapturescreen/changelog.md create mode 100644 uni_modules/uni-usercapturescreen/index.d.ts create mode 100644 uni_modules/uni-usercapturescreen/package.json create mode 100644 uni_modules/uni-usercapturescreen/readme.md create mode 100644 uni_modules/uni-usercapturescreen/utssdk/app-android/config.json create mode 100644 uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts create mode 100644 uni_modules/uni-usercapturescreen/utssdk/app-ios/config.json create mode 100644 uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts create mode 100644 uni_modules/uni-usercapturescreen/utssdk/interface.uts create mode 100644 uni_modules/uni-usercapturescreen/utssdk/mp-weixin/index.js diff --git a/apis/index.js b/apis/index.js index 917ef93..bc86f66 100644 --- a/apis/index.js +++ b/apis/index.js @@ -10,8 +10,8 @@ import router from '../router' // 基础配置 const config = { - apiUrl : 'https://douhuo.douhuofalv.com/api/', - // apiUrl : 'https://api.douhuotest.douhuofalv.com/api/', //测试环境 + // apiUrl : 'https://douhuo.douhuofalv.com/api/', + apiUrl : 'https://api.douhuotest.douhuofalv.com/api/', //测试环境 timeout : 60000 } diff --git a/apis/interfaces/user.js b/apis/interfaces/user.js index d44b187..68b244d 100644 --- a/apis/interfaces/user.js +++ b/apis/interfaces/user.js @@ -157,6 +157,21 @@ const getTeamLogs = data => { }) } +// 签约记录 +const getSignLogs = data => { + return request({ + url: 'business/flows', + data + }) +} + +// 获取签约合同 +const getFlows = id => { + return request({ + url: 'e-signs/flows/' + id + }) +} + export { relations, code, @@ -176,4 +191,6 @@ export { submitTeamName, getTeam, getTeamLogs, + getSignLogs, + getFlows } diff --git a/manifest.json b/manifest.json index e857f83..52e1489 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "name" : "抖火", "appid" : "__UNI__C305C03", "description" : "纵有疾风起,人生不言弃", - "versionName" : "1.4.1", + "versionName" : "1.4.2", "versionCode" : 104, "transformPx" : false, /* 5+App特有相关 */ @@ -43,7 +43,8 @@ "", "" ], - "schemes" : "doufire" + "schemes" : "doufire", + "minSdkVersion" : 21 }, /* ios打包配置 */ "ios" : { @@ -92,6 +93,22 @@ } } } + }, + "nativePlugins" : { + "Pdf-Plugin" : { + "__plugin_info__" : { + "name" : "Pdf-Plugin", + "description" : "此插件为uni小程序Android原生插件,用于加载网络pdf,支持水印和缩放", + "platforms" : "Android", + "url" : "https://ext.dcloud.net.cn/plugin?id=11384", + "android_package_name" : "io.douhuofalv.com", + "ios_bundle_id" : "io.douhuofalv.com", + "isCloud" : true, + "bought" : 1, + "pid" : "11384", + "parameters" : {} + } + } } }, /* 快应用特有相关 */ diff --git a/pages.json b/pages.json index 76495de..9eca141 100644 --- a/pages.json +++ b/pages.json @@ -343,7 +343,7 @@ "navigationBarTitleText": "机构信息", "enablePullDownRefresh": false, "navigationBarBackgroundColor": "#446EFE", - "navigationBarTextStyle": "white" + "navigationBarTextStyle": "white" } }, { "path": "pages/work/perfectBasis", @@ -353,7 +353,7 @@ "navigationBarTitleText": "基础信息", "enablePullDownRefresh": false, "navigationBarBackgroundColor": "#446EFE", - "navigationBarTextStyle": "white" + "navigationBarTextStyle": "white" } }, { "path": "pages/transfers/lists", @@ -545,10 +545,26 @@ "navigationBarBackgroundColor": "#FFFFFF" } }, { - "path": "pages/im/msg", + "path": "pages/im/msg", "name": "ImMsg", - "style": { + "style": { "navigationBarTitleText": "消息", + "enablePullDownRefresh": false, + "navigationBarBackgroundColor": "#FFFFFF" + } + }, { + "path": "pages/user/signLog", + "name": "SignLog", + "style": { + "navigationBarTitleText": "合同记录", + "enablePullDownRefresh": false, + "navigationBarBackgroundColor": "#FFFFFF" + } + }, { + "path": "pages/user/contract", + "name": "SignContract", + "style": { + "navigationBarTitleText": "合同", "enablePullDownRefresh": false, "navigationBarBackgroundColor": "#FFFFFF" } @@ -590,4 +606,4 @@ "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue" }, "uniIdRouter": {} -} +} \ No newline at end of file diff --git a/pages/user/contract.vue b/pages/user/contract.vue new file mode 100644 index 0000000..6e6c72e --- /dev/null +++ b/pages/user/contract.vue @@ -0,0 +1,146 @@ + + + + + diff --git a/pages/user/index.vue b/pages/user/index.vue index 6e57c1e..0631be2 100644 --- a/pages/user/index.vue +++ b/pages/user/index.vue @@ -99,7 +99,16 @@ - + + + + 版本检测 + + + V{{version}} + + + 设置 @@ -160,23 +169,20 @@ @@ -446,7 +518,15 @@ margin-right: $margin; margin-top: 5rpx; } - } + } + .nav-text{ + display: flex; + justify-content: flex-end; + align-items: center; + color: #999; + font-size: 30rpx; + text{ padding-right: 10rpx; } + } } // 用户信息 diff --git a/pages/user/set.vue b/pages/user/set.vue index 3aaf955..36247c5 100644 --- a/pages/user/set.vue +++ b/pages/user/set.vue @@ -30,6 +30,14 @@ + + + + + + + + diff --git a/pages/user/signLog.vue b/pages/user/signLog.vue new file mode 100644 index 0000000..1213dd3 --- /dev/null +++ b/pages/user/signLog.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/pages/user/team.vue b/pages/user/team.vue index 52a0724..0f802b6 100644 --- a/pages/user/team.vue +++ b/pages/user/team.vue @@ -19,6 +19,7 @@ 普通用户 顾问 + 团队业绩:{{ item.show_perf ? item.perf: '身份不符暂无业绩' }} 联系电话:{{item.username}} 注册时间:{{item.created_at}} @@ -74,6 +75,8 @@ page : this.page.current }).then(res => { let { users, count } = res; + + console.log(users) let atList = users.page.current == 1 ? [] : this.users this.count = count this.users = atList.concat(users.data) diff --git a/static/icons/user_nav_08.png b/static/icons/user_nav_08.png new file mode 100644 index 0000000000000000000000000000000000000000..9d77edb9490277b0ddded68802360146d43101a9 GIT binary patch literal 5246 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 void +} + +declare interface Uni { + /** + * 监听用户主动截屏事件,用户使用系统截屏按键截屏时触发此事件。 + * + * 文档: [https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen](https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen) + */ + onUserCaptureScreen(callback: UniNamespace.OnUserCaptureScreenCallback): void; + /** + * 用户主动截屏事件。取消事件监听。 + * + * 文档: [https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen](https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen) + */ + offUserCaptureScreen(callback: UniNamespace.OnUserCaptureScreenCallback): void; +} diff --git a/uni_modules/uni-usercapturescreen/package.json b/uni_modules/uni-usercapturescreen/package.json new file mode 100644 index 0000000..3285c78 --- /dev/null +++ b/uni_modules/uni-usercapturescreen/package.json @@ -0,0 +1,92 @@ +{ + "id": "uni-usercapturescreen", + "displayName": "uni-usercapturescreen", + "version": "1.0.4", + "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": "onUserCaptureScreen", + "offUserCaptureScreen": "offUserCaptureScreen", + "setUserCaptureScreen": "setUserCaptureScreen" + } + }, + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "n", + "vue3": "y" + }, + "App": { + "app-android": { + "minVersion": "19" + }, + "app-ios": { + "minVersion": "9" + } + }, + "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" + } + } + } + } +} diff --git a/uni_modules/uni-usercapturescreen/readme.md b/uni_modules/uni-usercapturescreen/readme.md new file mode 100644 index 0000000..eda987a --- /dev/null +++ b/uni_modules/uni-usercapturescreen/readme.md @@ -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) diff --git a/uni_modules/uni-usercapturescreen/utssdk/app-android/config.json b/uni_modules/uni-usercapturescreen/utssdk/app-android/config.json new file mode 100644 index 0000000..7ed4299 --- /dev/null +++ b/uni_modules/uni-usercapturescreen/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "19" +} \ No newline at end of file diff --git a/uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts b/uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts new file mode 100644 index 0000000..99cf531 --- /dev/null +++ b/uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts @@ -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"; + + +/** + * 文件监听器 + */ +let observer : ScreenFileObserver | null = null; +/** + * 记录文件监听器上次监听的时间戳,避免重复监听 + */ +let lastObserverTime : number = 0; +/** + * 截屏回调 + */ +let listener : UserCaptureScreenCallback | null = null; + +/** + * android 文件监听实现 + */ +class ScreenFileObserver extends FileObserver { + + /** + * 截屏文件目录 + */ + private screenFile : File; + + constructor(screenFile : File) { + super(screenFile); + this.screenFile = screenFile; + } + + 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); + 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); + } + } +} diff --git a/uni_modules/uni-usercapturescreen/utssdk/app-ios/config.json b/uni_modules/uni-usercapturescreen/utssdk/app-ios/config.json new file mode 100644 index 0000000..721b81e --- /dev/null +++ b/uni_modules/uni-usercapturescreen/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "9" +} \ No newline at end of file diff --git a/uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts b/uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts new file mode 100644 index 0000000..544fb21 --- /dev/null +++ b/uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts @@ -0,0 +1,146 @@ +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, SetUserCaptureScreenFail } from "../interface.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!) + let rect = rootView!.frame + secureView!.frame = UIScreen.main.bounds + rootView!.frame = rect + } + } + 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: SetUserCaptureScreenFail = { + errCode: 12001, + errSubject: "uni-usercapturescreen", + errMsg: "setUserCaptureScreen:system not support" + } + options.fail?.(res); + options.complete?.(res); + + } else if (UIDevice.current.systemVersion == "15.1") { + let res: SetUserCaptureScreenFail = { + errCode: 12010, + errSubject: "uni-usercapturescreen", + errMsg: "setUserCaptureScreen:system internal error" + } + options.fail?.(res); + options.complete?.(res); + } else { + if (options.enable == true) { + CaptureScreenTool.offAntiScreenshot(options) + } else { + CaptureScreenTool.onAntiScreenshot(options) + } + } +} + diff --git a/uni_modules/uni-usercapturescreen/utssdk/interface.uts b/uni_modules/uni-usercapturescreen/utssdk/interface.uts new file mode 100644 index 0000000..235b782 --- /dev/null +++ b/uni_modules/uni-usercapturescreen/utssdk/interface.uts @@ -0,0 +1,122 @@ +/** + * uni.onUserCaptureScreen/uni.offUserCaptureScreen回调参数 + */ +export type OnUserCaptureScreenCallbackResult = { + /** + * 截屏文件路径(仅Android返回) + */ + path ?: string +} + +/** + * uni.onUserCaptureScreen/uni.offUserCaptureScreen回调函数定义 + */ +export type UserCaptureScreenCallback = (res : OnUserCaptureScreenCallbackResult) => void + +/** + * uni.onUserCaptureScreen函数定义 + * 开启截屏监听 + * + * @param {UserCaptureScreenCallback} callback + * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen + * @platforms APP-IOS = ^9.0,APP-ANDROID = ^4.4 + * @since 3.7.7 + */ +export type OnUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void + +/** + * uni.offUserCaptureScreen函数定义 + * 关闭截屏监听 + * + * @param {UserCaptureScreenCallback} callback + * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen + * @platforms APP-IOS = ^9.0,APP-ANDROID = ^4.4 + * @since 3.7.7 + */ +export type OffUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void + +/** + * uni.setUserCaptureScreen成功回调参数 + */ +export type SetUserCaptureScreenSuccess = { +} + +/** + * uni.setUserCaptureScreen失败回调参数 + */ +export type SetUserCaptureScreenFail = { + /** + * 错误码 + * 12001:system not support + * 12010:system internal error + */ + errCode : number, + /** + * 调用API的名称 + */ + errSubject : string, + /** + * 错误的详细信息 + */ + errMsg : string, +} + +/** + * uni.setUserCaptureScreen成功回调函数定义 + */ +export type SetUserCaptureScreenSuccessCallback = (res : SetUserCaptureScreenSuccess) => void + +/** + * uni.setUserCaptureScreen失败回调函数定义 + */ +export type SetUserCaptureScreenFailCallback = (res : SetUserCaptureScreenFail) => 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 +} + + +/** + * * uni.setUserCaptureScreen函数定义 + + * 设置防截屏 + * + * @param {SetUserCaptureScreenOptions} options + * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen + * @platforms APP-IOS = ^13.0,APP-ANDROID = ^4.4 + * @since 3.7.7 + */ +export type SetUserCaptureScreen = (options : SetUserCaptureScreenOptions) => void + +export interface Uni { + onUserCaptureScreen : OnUserCaptureScreen, + offUserCaptureScreen : OffUserCaptureScreen, + setUserCaptureScreen : SetUserCaptureScreen +} \ No newline at end of file diff --git a/uni_modules/uni-usercapturescreen/utssdk/mp-weixin/index.js b/uni_modules/uni-usercapturescreen/utssdk/mp-weixin/index.js new file mode 100644 index 0000000..6aa57b3 --- /dev/null +++ b/uni_modules/uni-usercapturescreen/utssdk/mp-weixin/index.js @@ -0,0 +1,7 @@ +export function onUserCaptureScreen (callback) { + return wx.onUserCaptureScreen(callback) +} + +export function offUserCaptureScreen (callback) { + return wx.offUserCaptureScreen(callback) +}