From 967b2d9a0bfaa373a2d406182a38cf181af4a279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= Date: Tue, 8 Jul 2025 13:45:04 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E6=96=BD=E5=B7=A5=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/login/index.vue | 4 +- pages/workbench/construction/construction.vue | 331 +++++++++++++----- pages/workbench/construction/detail.vue | 217 +++++------- util/oaRequest.js | 18 +- 4 files changed, 361 insertions(+), 209 deletions(-) diff --git a/pages/login/index.vue b/pages/login/index.vue index dae9952..282ca87 100644 --- a/pages/login/index.vue +++ b/pages/login/index.vue @@ -220,8 +220,8 @@ export default { uni.switchTab({ url: "/pages/conversation/conversationList/index", }); - await getSMSCodeFromOa(this.loginInfo.phoneNumber); - await loginOaByPhone(this.loginInfo.phoneNumber) + await getSMSCodeFromOa(this.loginInfo.phoneNumber); + await loginOaByPhone(this.loginInfo.phoneNumber) this.loginInfo.password = ""; this.loading = false; diff --git a/pages/workbench/construction/construction.vue b/pages/workbench/construction/construction.vue index 7342f3a..b9ac424 100644 --- a/pages/workbench/construction/construction.vue +++ b/pages/workbench/construction/construction.vue @@ -3,38 +3,53 @@ - 点击对应的行可以查看详情 + 点击对应的卡片可以查看详情 + + + + + + + 新增汇报 + - - - - - 汇报标题 - 最近汇报时间 - 汇报日期 - 汇报人 - 涉及项目 - 备注 + + + {{ item.reportTitle || '-' }} + + + 最近汇报时间: + {{ formatDate(item.lastUpdateTime) }} - - - {{ item.reportTitle || '-' }} - {{ formatDate(item.lastUpdateTime) }} - {{ formatDate(item.reportDate) }} - {{ item.reporter || '-' }} - {{ item.projectName || '-' }} - {{ item.remark || '-' }} - + + 汇报日期: + {{ formatDate(item.reportDate) }} + + + 汇报人: + {{ item.reporter || '-' }} + + + 涉及项目: + {{ item.projectName || '-' }} + + + 备注: + {{ item.remark || '-' }} - + @@ -44,13 +59,75 @@ @loadmore="loadMore" > + + + + + 新增汇报 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 取消 + 确定 + + + @@ -180,62 +359,48 @@ export default { } } - -.table-wrapper { - background-color: #fff; - border-radius: 10rpx; - overflow: hidden; +.add-button-container { + display: flex; + justify-content: center; + margin-bottom: 30rpx; } -.table-scroll { - width: 100%; +.masonry-list { + column-count: 2; + column-gap: 24rpx; + padding: 10rpx 0; } -.table-container { - min-width: 1200rpx; // 设置最小宽度,确保表格内容不会被压缩 - .table-header { - display: flex; - background-color: #f8f9fa; - border-bottom: 1rpx solid #e9ecef; - .header-cell { - width: 200rpx; // 固定列宽 - padding: 20rpx 10rpx; - text-align: center; - font-weight: bold; - font-size: 28rpx; - flex-shrink: 0; // 防止列被压缩 - &.checkbox { - width: 100rpx; // 复选框列宽度 - } - } +.masonry-card { + width: calc(100%% - 18rpx); + margin-bottom: 24rpx; + background: #fff; + border-radius: 16rpx; + box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06); + display: inline-block; + break-inside: avoid; + padding: 32rpx 24rpx; + cursor: pointer; + transition: box-shadow 0.2s; + &:active { + box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.10); + background: #f8f9fa; } - .table-body { - .table-row { + .card-title { + font-size: 32rpx; + font-weight: bold; + margin-bottom: 16rpx; + color: #007bff; + } + .card-info { + display: flex; + flex-direction: column; + gap: 8rpx; + .info-row { display: flex; - border-bottom: 1rpx solid #e9ecef; - cursor: pointer; - transition: background-color 0.2s; - - &:hover { - background-color: #f8f9fa; - } - - &:active { - background-color: #e9ecef; - } - .table-cell { - width: 200rpx; // 固定列宽 - padding: 20rpx 10rpx; - text-align: center; - font-size: 26rpx; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; // 防止列被压缩 - word-break: break-all; // 长文本换行 - &.checkbox { - width: 100rpx; // 复选框列宽度 - } + .label { + color: #888; + min-width: 120rpx; } } } diff --git a/pages/workbench/construction/detail.vue b/pages/workbench/construction/detail.vue index ab5e1b2..f35a4ab 100644 --- a/pages/workbench/construction/detail.vue +++ b/pages/workbench/construction/detail.vue @@ -22,69 +22,49 @@ - - - 新增 - 删除 - + - - - - - - + + + + + + 设备编号: + {{ item.deviceCode || '-' }} - 设备编号 - 设备类别 - 汇报详情内容 - 图片概况 - 备注 - 操作 - - - - - - - - - {{ item.deviceCode || '-' }} - {{ item.category || '-' }} - - {{ item.reportDetail || '-' }} - - - - - - - {{ item.remark || '-' }} - - 删除 - + + 设备类别: + {{ item.category || '-' }} + + + 汇报详情内容: + {{ item.reportDetail || '-' }} + + + 图片概况: + + + - - - - + + 备注: + {{ item.remark || '-' }} + + + + @@ -94,6 +74,13 @@ @loadmore="loadMore" > + + + + + + + @@ -269,6 +256,9 @@ export default { this.reportDetailList = response.rows || []; this.total = response.total || 0; this.loading = false; + if (this.reportDetailList.length >= this.total) { + this.loadMoreStatus = 'nomore'; + } // 重置选中状态 this.selectedIds = []; this.selectAll = false; @@ -450,7 +440,8 @@ export default { this.reportDetailList = [...this.reportDetailList, ...newData]; this.total = response.total || 0; - if (newData.length < this.queryParams.pageSize) { + // 判断是否还有更多数据:当前获取的数据总数 >= 总数据量 + if (this.reportDetailList.length >= this.total) { this.loadMoreStatus = 'nomore'; } else { this.loadMoreStatus = 'loadmore'; @@ -549,76 +540,32 @@ export default { } } -.action-buttons { - display: flex; - gap: 20rpx; - margin-bottom: 20rpx; -} -.table-wrapper { - background-color: #fff; + +.list-wrapper { + background: #fff; border-radius: 10rpx; - overflow: hidden; + padding: 10rpx 0; } -.table-scroll { - width: 100%; -} - -.table-container { - min-width: 1400rpx; // 设置最小宽度,确保表格内容不会被压缩 - .table-header { +.detail-list-item { + padding: 32rpx 24rpx; + background: #fff; + border-radius: 12rpx; + margin-bottom: 16rpx; + border: 1rpx solid #e9ecef; + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06); + .item-row { display: flex; - background-color: #f8f9fa; - border-bottom: 1rpx solid #e9ecef; - - .header-cell { - width: 200rpx; // 固定列宽 - padding: 20rpx 10rpx; - text-align: center; - font-weight: bold; - font-size: 28rpx; - flex-shrink: 0; // 防止列被压缩 - - &.checkbox { - width: 100rpx; // 复选框列宽度 - } + align-items: center; + margin-bottom: 8rpx; + .item-label { + color: #888; + min-width: 140rpx; } - } - - .table-body { - .table-row { - display: flex; - border-bottom: 1rpx solid #e9ecef; - - &:hover { - background-color: #f8f9fa; - } - - .table-cell { - width: 200rpx; // 固定列宽 - padding: 20rpx 10rpx; - text-align: center; - font-size: 26rpx; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; // 防止列被压缩 - word-break: break-all; // 长文本换行 - - &.checkbox { - width: 100rpx; // 复选框列宽度 - } - - &.content-cell { - .content-text { - max-width: 180rpx; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - } - } + .item-value { + color: #333; + flex: 1; } } } @@ -696,4 +643,28 @@ export default { text-overflow: ellipsis; display: block; } + +.add-button-wrapper { + position: fixed; + bottom: 40rpx; + right: 40rpx; + z-index: 999; +} + +.add-button { + width: 120rpx; + height: 120rpx; + background: linear-gradient(135deg, #007bff, #0056b3); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4rpx 16rpx rgba(0, 123, 255, 0.3); + transition: all 0.3s ease; + + &:active { + transform: scale(0.95); + box-shadow: 0 2rpx 8rpx rgba(0, 123, 255, 0.4); + } +} \ No newline at end of file diff --git a/util/oaRequest.js b/util/oaRequest.js index 2de495e..4d3b5d1 100644 --- a/util/oaRequest.js +++ b/util/oaRequest.js @@ -1,6 +1,7 @@ import { getToken } from './auth' import errorCode from './errorCode' import { toast, showConfirm, tansParams } from './common' +import { getSMSCodeFromOa, loginOaByPhone } from '../api/oa/login' let timeout = 10000 const baseUrl = 'http://110.41.139.73:8080' @@ -42,8 +43,23 @@ const request = config => { const code = res.data.code || 200 const msg = errorCode[code] || res.data.msg || errorCode['default'] if (code === 401) { - showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => { + showConfirm('登录状态已过期,是否刷新登录状态').then(async res => { if (res.confirm) { + // 从store中获取phoneNumber,并依次调用getSMSCodeFromOa和loginOaByPhone + const store = require('@/store').default + const phoneNumber = store.getters.storeSelfInfo?.phoneNumber + if (phoneNumber) { + try { + await getSMSCodeFromOa(phoneNumber) + await loginOaByPhone(phoneNumber) + } catch (e) { + console.log('OA自动登录失败', e) + toast('OA自动登录失败') + } + } else { + toast('无法获取手机号,OA自动登录失败') + } + // 登录 // store.dispatch('LogOut').then(res => { // uni.reLaunch({ url: '/pages/login' }) // }) From 5f861c58eec37ba26796c1c056be6c0f075533d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= Date: Thu, 10 Jul 2025 15:49:39 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E5=BC=80=E9=80=9A=E4=BA=91=E5=87=BD?= =?UTF-8?q?=E6=95=B0=EF=BC=8C=E5=8F=98=E6=9B=B4appId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 37 +++++++- manifest.json | 10 +- pages/login/index.vue | 34 ++++++- pages/profile/index/index.vue | 17 ++++ uni_modules/uni-config-center/changelog.md | 6 ++ uni_modules/uni-config-center/package.json | 81 ++++++++++++++++ uni_modules/uni-config-center/readme.md | 93 +++++++++++++++++++ .../common/uni-config-center/index.js | 1 + .../common/uni-config-center/package.json | 13 +++ uni_modules/uni-id-common/changelog.md | 36 +++++++ uni_modules/uni-id-common/package.json | 84 +++++++++++++++++ uni_modules/uni-id-common/readme.md | 3 + .../common/uni-id-common/index.js | 1 + .../common/uni-id-common/package.json | 20 ++++ 14 files changed, 427 insertions(+), 9 deletions(-) create mode 100644 uni_modules/uni-config-center/changelog.md create mode 100644 uni_modules/uni-config-center/package.json create mode 100644 uni_modules/uni-config-center/readme.md create mode 100644 uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js create mode 100644 uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json create mode 100644 uni_modules/uni-id-common/changelog.md create mode 100644 uni_modules/uni-id-common/package.json create mode 100644 uni_modules/uni-id-common/readme.md create mode 100644 uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/index.js create mode 100644 uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json diff --git a/App.vue b/App.vue index d3fa14a..fc46699 100644 --- a/App.vue +++ b/App.vue @@ -29,10 +29,45 @@ export default { // #ifdef MP-WEIXIN console.error(`暂时不支持运行到小程序端`); // #endif + // 集成cid全局获取和存储 + uni.getPushClientId({ + success: (res) => { + console.log(res, 'app-Push-ID'); + if (res && res.cid) { + uni.setStorageSync('cid', res.cid); + } + }, + fail: (err) => { + console.log(err) + } + }) }, onShow: function () { console.log("App Show"); IMSDK.asyncApi(IMSDK.IMMethods.SetAppBackgroundStatus, IMSDK.uuid(), false); + uni.getPushClientId({ + success(res) { + console.log(res, 'app-Push-ID'); + }, + fail(err) { + console.log(err) + } + }) + //#ifdef APP-PLUS + var info = plus.push.getClientInfo() + plus.push.addEventListener("click", function(msg) { + console.log("click:" + JSON.stringify(msg)); + console.log(msg.payload); + console.log(JSON.stringify(msg)); + }, false); + // 监听在线消息事件 + plus.push.addEventListener("receive", function(msg) { + //业务代码 + console.log("recevice:" + JSON.stringify(msg)) + }, false); + //#endif + + }, onHide: function () { console.log("App Hide"); @@ -52,8 +87,6 @@ export default { ]), }, methods: { - - ...mapActions("message", ["pushNewMessage", "updateOneMessage"]), ...mapActions("conversation", ["updateCurrentMemberInGroup"]), ...mapActions("contact", [ diff --git a/manifest.json b/manifest.json index d3d3b8d..3999c3e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "name" : "德讯", - "appid" : "__UNI__D705A34", + "appid" : "__UNI__AF08DA3", "description" : "", "versionName" : "fad-im 4.0.0", "versionCode" : 345, @@ -21,7 +21,8 @@ "Camera" : {}, "Record" : {}, "Geolocation" : {}, - "Maps" : {} + "Maps" : {}, + "Push" : {} }, "distribute" : { "android" : { @@ -73,7 +74,6 @@ "speech" : {}, "push" : { "unipush" : { - "version" : "2", "offline" : true } } @@ -127,8 +127,8 @@ "description" : "OpenIM:由IM技术专家打造的基于 Go 实现的即时通讯(IM)项目,从服务端到客户端SDK开源即时通讯(IM)整体解决方案,可以轻松替代第三方IM云服务,打造具备聊天、社交功能的app。", "platforms" : "Android,iOS", "url" : "https://ext.dcloud.net.cn/plugin?id=6577", - "android_package_name" : "", - "ios_bundle_id" : "", + "android_package_name" : "fad.im", + "ios_bundle_id" : "fad.im", "isCloud" : true, "bought" : 1, "pid" : "6577", diff --git a/pages/login/index.vue b/pages/login/index.vue index 282ca87..7bc26d6 100644 --- a/pages/login/index.vue +++ b/pages/login/index.vue @@ -190,7 +190,6 @@ export default { this.loading = true; this.saveLoginInfo(); let data = {}; - data = await businessLogin({ phoneNumber: this.loginInfo.phoneNumber, email: this.loginInfo.email, @@ -221,7 +220,38 @@ export default { url: "/pages/conversation/conversationList/index", }); await getSMSCodeFromOa(this.loginInfo.phoneNumber); - await loginOaByPhone(this.loginInfo.phoneNumber) + const info = await loginOaByPhone(this.loginInfo.phoneNumber) + console.log('用户信息', info) + const oaUserId = info.userInfo.userId; + // 获取设备cid,调用云函数 + const cid = uni.getStorageSync('cid'); + uniCloud.callFunction({ + name: 'binding', + data: { + oaId: oaUserId, + deviceId: cid + }, + success: (res) => { + if (res.result.code === 200) { + uni.showToast({ + title: res.result.msg, + icon: 'success' + }); + } else { + uni.showToast({ + title: res.result.msg, + icon: 'none' + }); + } + }, + fail: (err) => { + uni.showToast({ + title: '云函数调用失败', + icon: 'none' + }); + console.error(err); + } + }); this.loginInfo.password = ""; this.loading = false; diff --git a/pages/profile/index/index.vue b/pages/profile/index/index.vue index 3813d40..b2847f0 100644 --- a/pages/profile/index/index.vue +++ b/pages/profile/index/index.vue @@ -67,6 +67,11 @@ export default { title: "关于我们", icon: require("static/images/profile_menu_about.png"), }, + { + idx: 5, + title: '测试推送', + icon: require("static/images/profile_menu_about.png") + }, { idx: 4, title: "退出登录", @@ -130,6 +135,18 @@ export default { url: "/pages/profile/about/index", }); break; + case 5: + uni.createPushMessage({ + content: '今天还没有报工哦', + title: "报工提醒", + success() { + console.log('推送成功') + }, + fail() { + console.log("推送失败") + } + }); + break; case 4: uni.showModal({ title: "提示", diff --git a/uni_modules/uni-config-center/changelog.md b/uni_modules/uni-config-center/changelog.md new file mode 100644 index 0000000..57dbcb5 --- /dev/null +++ b/uni_modules/uni-config-center/changelog.md @@ -0,0 +1,6 @@ +## 0.0.3(2022-11-11) +- 修复 config 方法获取根节点为数组格式配置时错误的转化为了对象的Bug +## 0.0.2(2021-04-16) +- 修改插件package信息 +## 0.0.1(2021-03-15) +- 初始化项目 diff --git a/uni_modules/uni-config-center/package.json b/uni_modules/uni-config-center/package.json new file mode 100644 index 0000000..bace866 --- /dev/null +++ b/uni_modules/uni-config-center/package.json @@ -0,0 +1,81 @@ +{ + "id": "uni-config-center", + "displayName": "uni-config-center", + "version": "0.0.3", + "description": "uniCloud 配置中心", + "keywords": [ + "配置", + "配置中心" +], + "repository": "", + "engines": { + "HBuilderX": "^3.1.0" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "type": "unicloud-template-function" + }, + "directories": { + "example": "../../../scripts/dist" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "u", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "u" + } + } + } + } +} diff --git a/uni_modules/uni-config-center/readme.md b/uni_modules/uni-config-center/readme.md new file mode 100644 index 0000000..03f7fc2 --- /dev/null +++ b/uni_modules/uni-config-center/readme.md @@ -0,0 +1,93 @@ +# 为什么使用uni-config-center + +实际开发中很多插件需要配置文件才可以正常运行,如果每个插件都单独进行配置的话就会产生下面这样的目录结构 + +```bash +cloudfunctions +└─────common 公共模块 + ├─plugin-a // 插件A对应的目录 + │ ├─index.js + │ ├─config.json // plugin-a对应的配置文件 + │ └─other-file.cert // plugin-a依赖的其他文件 + └─plugin-b // plugin-b对应的目录 + ├─index.js + └─config.json // plugin-b对应的配置文件 +``` + +假设插件作者要发布一个项目模板,里面使用了很多需要配置的插件,无论是作者发布还是用户使用都是一个大麻烦。 + +uni-config-center就是用了统一管理这些配置文件的,使用uni-config-center后的目录结构如下 + +```bash +cloudfunctions +└─────common 公共模块 + ├─plugin-a // 插件A对应的目录 + │ └─index.js + ├─plugin-b // plugin-b对应的目录 + │ └─index.js + └─uni-config-center + ├─index.js // config-center入口文件 + ├─plugin-a + │ ├─config.json // plugin-a对应的配置文件 + │ └─other-file.cert // plugin-a依赖的其他文件 + └─plugin-b + └─config.json // plugin-b对应的配置文件 +``` + +使用uni-config-center后的优势 + +- 配置文件统一管理,分离插件主体和配置信息,更新插件更方便 +- 支持对config.json设置schema,插件使用者在HBuilderX内编写config.json文件时会有更好的提示(后续HBuilderX会提供支持) + +# 用法 + +在要使用uni-config-center的公共模块或云函数内引入uni-config-center依赖,请参考:[使用公共模块](https://uniapp.dcloud.net.cn/uniCloud/cf-common) + +```js +const createConfig = require('uni-config-center') + +const uniIdConfig = createConfig({ + pluginId: 'uni-id', // 插件id + defaultConfig: { // 默认配置 + tokenExpiresIn: 7200, + tokenExpiresThreshold: 600, + }, + customMerge: function(defaultConfig, userConfig) { // 自定义默认配置和用户配置的合并规则,不设置的情况侠会对默认配置和用户配置进行深度合并 + // defaudltConfig 默认配置 + // userConfig 用户配置 + return Object.assign(defaultConfig, userConfig) + } +}) + + +// 以如下配置为例 +// { +// "tokenExpiresIn": 7200, +// "passwordErrorLimit": 6, +// "bindTokenToDevice": false, +// "passwordErrorRetryTime": 3600, +// "app-plus": { +// "tokenExpiresIn": 2592000 +// }, +// "service": { +// "sms": { +// "codeExpiresIn": 300 +// } +// } +// } + +// 获取配置 +uniIdConfig.config() // 获取全部配置,注意:uni-config-center内不存在对应插件目录时会返回空对象 +uniIdConfig.config('tokenExpiresIn') // 指定键值获取配置,返回:7200 +uniIdConfig.config('service.sms.codeExpiresIn') // 指定键值获取配置,返回:300 +uniIdConfig.config('tokenExpiresThreshold', 600) // 指定键值获取配置,如果不存在则取传入的默认值,返回:600 + +// 获取文件绝对路径 +uniIdConfig.resolve('custom-token.js') // 获取uni-config-center/uni-id/custom-token.js文件的路径 + +// 引用文件(require) +uniIDConfig.requireFile('custom-token.js') // 使用require方式引用uni-config-center/uni-id/custom-token.js文件。文件不存在时返回undefined,文件内有其他错误导致require失败时会抛出错误。 + +// 判断是否包含某文件 +uniIDConfig.hasFile('custom-token.js') // 配置目录是否包含某文件,true: 文件存在,false: 文件不存在 +``` \ No newline at end of file diff --git a/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js new file mode 100644 index 0000000..00ba62f --- /dev/null +++ b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js @@ -0,0 +1 @@ +"use strict";var t=require("fs"),r=require("path");function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n=e(t),o=e(r),i="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var u=function(t){var r={exports:{}};return t(r,r.exports),r.exports}((function(t,r){var e="__lodash_hash_undefined__",n=9007199254740991,o="[object Arguments]",u="[object Function]",c="[object Object]",a=/^\[object .+?Constructor\]$/,f=/^(?:0|[1-9]\d*)$/,s={};s["[object Float32Array]"]=s["[object Float64Array]"]=s["[object Int8Array]"]=s["[object Int16Array]"]=s["[object Int32Array]"]=s["[object Uint8Array]"]=s["[object Uint8ClampedArray]"]=s["[object Uint16Array]"]=s["[object Uint32Array]"]=!0,s[o]=s["[object Array]"]=s["[object ArrayBuffer]"]=s["[object Boolean]"]=s["[object DataView]"]=s["[object Date]"]=s["[object Error]"]=s[u]=s["[object Map]"]=s["[object Number]"]=s[c]=s["[object RegExp]"]=s["[object Set]"]=s["[object String]"]=s["[object WeakMap]"]=!1;var l="object"==typeof i&&i&&i.Object===Object&&i,h="object"==typeof self&&self&&self.Object===Object&&self,p=l||h||Function("return this")(),_=r&&!r.nodeType&&r,v=_&&t&&!t.nodeType&&t,d=v&&v.exports===_,y=d&&l.process,g=function(){try{var t=v&&v.require&&v.require("util").types;return t||y&&y.binding&&y.binding("util")}catch(t){}}(),b=g&&g.isTypedArray;function j(t,r,e){switch(e.length){case 0:return t.call(r);case 1:return t.call(r,e[0]);case 2:return t.call(r,e[0],e[1]);case 3:return t.call(r,e[0],e[1],e[2])}return t.apply(r,e)}var w,O,m,A=Array.prototype,z=Function.prototype,M=Object.prototype,x=p["__core-js_shared__"],C=z.toString,F=M.hasOwnProperty,U=(w=/[^.]+$/.exec(x&&x.keys&&x.keys.IE_PROTO||""))?"Symbol(src)_1."+w:"",S=M.toString,I=C.call(Object),P=RegExp("^"+C.call(F).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),T=d?p.Buffer:void 0,q=p.Symbol,E=p.Uint8Array,$=T?T.allocUnsafe:void 0,D=(O=Object.getPrototypeOf,m=Object,function(t){return O(m(t))}),k=Object.create,B=M.propertyIsEnumerable,N=A.splice,L=q?q.toStringTag:void 0,R=function(){try{var t=vt(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),G=T?T.isBuffer:void 0,V=Math.max,W=Date.now,H=vt(p,"Map"),J=vt(Object,"create"),K=function(){function t(){}return function(r){if(!xt(r))return{};if(k)return k(r);t.prototype=r;var e=new t;return t.prototype=void 0,e}}();function Q(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},X.prototype.set=function(t,r){var e=this.__data__,n=nt(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this},Y.prototype.clear=function(){this.size=0,this.__data__={hash:new Q,map:new(H||X),string:new Q}},Y.prototype.delete=function(t){var r=_t(this,t).delete(t);return this.size-=r?1:0,r},Y.prototype.get=function(t){return _t(this,t).get(t)},Y.prototype.has=function(t){return _t(this,t).has(t)},Y.prototype.set=function(t,r){var e=_t(this,t),n=e.size;return e.set(t,r),this.size+=e.size==n?0:1,this},Z.prototype.clear=function(){this.__data__=new X,this.size=0},Z.prototype.delete=function(t){var r=this.__data__,e=r.delete(t);return this.size=r.size,e},Z.prototype.get=function(t){return this.__data__.get(t)},Z.prototype.has=function(t){return this.__data__.has(t)},Z.prototype.set=function(t,r){var e=this.__data__;if(e instanceof X){var n=e.__data__;if(!H||n.length<199)return n.push([t,r]),this.size=++e.size,this;e=this.__data__=new Y(n)}return e.set(t,r),this.size=e.size,this};var it,ut=function(t,r,e){for(var n=-1,o=Object(t),i=e(t),u=i.length;u--;){var c=i[it?u:++n];if(!1===r(o[c],c,o))break}return t};function ct(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":L&&L in Object(t)?function(t){var r=F.call(t,L),e=t[L];try{t[L]=void 0;var n=!0}catch(t){}var o=S.call(t);n&&(r?t[L]=e:delete t[L]);return o}(t):function(t){return S.call(t)}(t)}function at(t){return Ct(t)&&ct(t)==o}function ft(t){return!(!xt(t)||function(t){return!!U&&U in t}(t))&&(zt(t)?P:a).test(function(t){if(null!=t){try{return C.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function st(t){if(!xt(t))return function(t){var r=[];if(null!=t)for(var e in Object(t))r.push(e);return r}(t);var r=yt(t),e=[];for(var n in t)("constructor"!=n||!r&&F.call(t,n))&&e.push(n);return e}function lt(t,r,e,n,o){t!==r&&ut(r,(function(i,u){if(o||(o=new Z),xt(i))!function(t,r,e,n,o,i,u){var a=gt(t,e),f=gt(r,e),s=u.get(f);if(s)return void rt(t,e,s);var l=i?i(a,f,e+"",t,r,u):void 0,h=void 0===l;if(h){var p=Ot(f),_=!p&&At(f),v=!p&&!_&&Ft(f);l=f,p||_||v?Ot(a)?l=a:Ct(j=a)&&mt(j)?l=function(t,r){var e=-1,n=t.length;r||(r=Array(n));for(;++e-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(pt);function jt(t,r){return t===r||t!=t&&r!=r}var wt=at(function(){return arguments}())?at:function(t){return Ct(t)&&F.call(t,"callee")&&!B.call(t,"callee")},Ot=Array.isArray;function mt(t){return null!=t&&Mt(t.length)&&!zt(t)}var At=G||function(){return!1};function zt(t){if(!xt(t))return!1;var r=ct(t);return r==u||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}function Mt(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=n}function xt(t){var r=typeof t;return null!=t&&("object"==r||"function"==r)}function Ct(t){return null!=t&&"object"==typeof t}var Ft=b?function(t){return function(r){return t(r)}}(b):function(t){return Ct(t)&&Mt(t.length)&&!!s[ct(t)]};function Ut(t){return mt(t)?tt(t,!0):st(t)}var St,It=(St=function(t,r,e){lt(t,r,e)},ht((function(t,r){var e=-1,n=r.length,o=n>1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=St.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!xt(e))return!1;var n=typeof r;return!!("number"==n?mt(e)&&dt(r,e.length):"string"==n&&r in e)&&jt(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++ec.call(t,r);class f{constructor({pluginId:t,defaultConfig:r={},customMerge:e,root:n}){this.pluginId=t,this.defaultConfig=r,this.pluginConfigPath=o.default.resolve(n||__dirname,t),this.customMerge=e,this._config=void 0}resolve(t){return o.default.resolve(this.pluginConfigPath,t)}hasFile(t){return n.default.existsSync(this.resolve(t))}requireFile(t){try{return require(this.resolve(t))}catch(t){if("MODULE_NOT_FOUND"===t.code)return;throw t}}_getUserConfig(){return this.requireFile("config.json")}config(t,r){if(!this._config){const t=this._getUserConfig();this._config=Array.isArray(t)?t:(this.customMerge||u)(this.defaultConfig,t)}let e=this._config;return t?function(t,r,e){if("number"==typeof r)return t[r];if("symbol"==typeof r)return a(t,r)?t[r]:e;const n="string"!=typeof(o=r)?o:o.split(".").reduce(((t,r)=>(r.split(/\[([^}]+)\]/g).forEach((r=>r&&t.push(r))),t)),[]);var o;let i=t;for(let t=0;tparseInt(e)):void 0}function o(e,t){const n=r(e),i=r(t);return n?i?function(e,t){const n=Math.max(e.length,t.length);for(let i=0;ir)return 1;if(n=e)throw new Error("Config error, tokenExpiresThreshold should be less than tokenExpiresIn");t>e/2&&console.warn(`Please check whether the tokenExpiresThreshold configuration is set too large, tokenExpiresThreshold: ${t}, tokenExpiresIn: ${e}`)}get customToken(){return this.uniId.interceptorMap.get("customToken")}isTokenInDb(e){return o(e,"1.0.10")>=0}async getUserRecord(){if(this.userRecord)return this.userRecord;const e=await C.doc(this.uid).get();if(this.userRecord=e.data[0],!this.userRecord)throw{errCode:n.ACCOUNT_NOT_EXISTS};switch(this.userRecord.status){case void 0:case 0:break;case 1:throw{errCode:n.ACCOUNT_BANNED};case 2:throw{errCode:n.ACCOUNT_AUDITING};case 3:throw{errCode:n.ACCOUNT_AUDIT_FAILED};case 4:throw{errCode:n.ACCOUNT_CLOSED}}if(this.oldTokenPayload){if(this.isTokenInDb(this.oldTokenPayload.uniIdVersion)){if(-1===(this.userRecord.token||[]).indexOf(this.oldToken))throw{errCode:n.CHECK_TOKEN_FAILED}}if(this.userRecord.valid_token_date&&this.userRecord.valid_token_date>1e3*this.oldTokenPayload.iat)throw{errCode:n.TOKEN_EXPIRED}}return this.userRecord}async updateUserRecord(e){await C.doc(this.uid).update(e)}async getUserPermission(){if(this.userPermission)return this.userPermission;const e=(await this.getUserRecord()).role||[];if(0===e.length)return this.userPermission={role:[],permission:[]},this.userPermission;if(e.includes("admin"))return this.userPermission={role:e,permission:[]},this.userPermission;const t=await T.where({role_id:I.in(e)}).get(),n=(i=t.data.reduce((e,t)=>(t.permission&&e.push(...t.permission),e),[]),Array.from(new Set(i)));var i;return this.userPermission={role:e,permission:n},this.userPermission}async _createToken({uid:e,role:t,permission:i}={}){if(!t||!i){const e=await this.getUserPermission();t=e.role,i=e.permission}let r={uid:e,role:t,permission:i};if(this.uniId.interceptorMap.has("customToken")){const n=this.uniId.interceptorMap.get("customToken");if("function"!=typeof n)throw new Error("Invalid custom token file");r=await n({uid:e,role:t,permission:i})}const o=Date.now(),{tokenSecret:s,tokenExpiresIn:c,maxTokenLength:a=10}=this.config,u=g({...r,uniIdVersion:"1.0.18"},s,{expiresIn:c}),d=await this.getUserRecord(),l=(d.token||[]).filter(e=>{try{const t=this._checkToken(e);if(d.valid_token_date&&d.valid_token_date>1e3*t.iat)return!1}catch(e){if(e.errCode===n.TOKEN_EXPIRED)return!1}return!0});return l.push(u),l.length>a&&l.splice(0,l.length-a),await this.updateUserRecord({last_login_ip:this.clientInfo.clientIP,last_login_date:o,token:l}),{token:u,tokenExpired:o+1e3*c}}async createToken({uid:e,role:t,permission:i}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"uid"}};this.uid=e;const{token:r,tokenExpired:o}=await this._createToken({uid:e,role:t,permission:i});return{errCode:0,token:r,tokenExpired:o}}async refreshToken({token:e}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"token"}};this.oldToken=e;const t=this._checkToken(e);this.uid=t.uid,this.oldTokenPayload=t;const{uid:i}=t,{role:r,permission:o}=await this.getUserPermission(),{token:s,tokenExpired:c}=await this._createToken({uid:i,role:r,permission:o});return{errCode:0,token:s,tokenExpired:c}}_checkToken(e){const{tokenSecret:t}=this.config;let i;try{i=k(e,t)}catch(e){if("TokenExpiredError"===e.name)throw{errCode:n.TOKEN_EXPIRED};throw{errCode:n.CHECK_TOKEN_FAILED}}return i}async checkToken(e,{autoRefresh:t=!0}={}){if(!e)throw{errCode:n.CHECK_TOKEN_FAILED};this.oldToken=e;const i=this._checkToken(e);this.uid=i.uid,this.oldTokenPayload=i;const{tokenExpiresThreshold:r}=this.config,{uid:o,role:s,permission:c}=i,a={role:s,permission:c};if(!s&&!c){const{role:e,permission:t}=await this.getUserPermission();a.role=e,a.permission=t}if(!r||!t){const e={code:0,errCode:0,...i,...a};return delete e.uniIdVersion,e}const u=Date.now();let d={};1e3*i.exp-u<1e3*r&&(d=await this._createToken({uid:o}));const l={code:0,errCode:0,...i,...a,...d};return delete l.uniIdVersion,l}}var m=Object.freeze({__proto__:null,checkToken:async function(e,{autoRefresh:t=!0}={}){return new E({uniId:this}).checkToken(e,{autoRefresh:t})},createToken:async function({uid:e,role:t,permission:n}={}){return new E({uniId:this}).createToken({uid:e,role:t,permission:n})},refreshToken:async function({token:e}={}){return new E({uniId:this}).refreshToken({token:e})}});const w=require("uni-config-center")({pluginId:"uni-id"});class x{constructor({context:e,clientInfo:t,config:n}={}){this._clientInfo=e?function(e){return{appId:e.APPID,platform:e.PLATFORM,locale:e.LOCALE,clientIP:e.CLIENTIP,deviceId:e.DEVICEID}}(e):t,this._config=n,this.config=this._getOriginConfig(),this.interceptorMap=new Map,w.hasFile("custom-token.js")&&this.setInterceptor("customToken",require(w.resolve("custom-token.js")));this._i18n=uniCloud.initI18n({locale:this._clientInfo.locale,fallbackLocale:"zh-Hans",messages:JSON.parse(JSON.stringify(d))}),d[this._i18n.locale]||this._i18n.setLocale("zh-Hans")}setInterceptor(e,t){this.interceptorMap.set(e,t)}_t(...e){return this._i18n.t(...e)}_parseOriginConfig(e){return Array.isArray(e)?e:e[0]?Object.values(e):e}_getOriginConfig(){if(this._config)return this._config;if(w.hasFile("config.json")){let e;try{e=w.config()}catch(e){throw new Error("Invalid uni-id config file\n"+e.message)}return this._parseOriginConfig(e)}try{return this._parseOriginConfig(require("uni-id/config.json"))}catch(e){throw new Error("Invalid uni-id config file")}}_getAppConfig(){const e=this._getOriginConfig();return Array.isArray(e)?e.find(e=>e.dcloudAppid===this._clientInfo.appId)||e.find(e=>e.isDefaultConfig):e}_getPlatformConfig(){const e=this._getAppConfig();if(!e)throw new Error(`Config for current app (${this._clientInfo.appId}) was not found, please check your config file or client appId`);let t;switch(["app-plus","app-android","app-ios"].indexOf(this._clientInfo.platform)>-1&&(this._clientInfo.platform="app"),"h5"===this._clientInfo.platform&&(this._clientInfo.platform="web"),this._clientInfo.platform){case"web":t="h5";break;case"app":t="app-plus"}const n=[{tokenExpiresIn:7200,tokenExpiresThreshold:1200,passwordErrorLimit:6,passwordErrorRetryTime:3600},e];t&&e[t]&&n.push(e[t]),n.push(e[this._clientInfo.platform]);const i=Object.assign(...n);return["tokenSecret","tokenExpiresIn"].forEach(e=>{if(!i||!i[e])throw new Error(`Config parameter missing, ${e} is required`)}),i}_getConfig(){return this._getPlatformConfig()}}for(const e in m)x.prototype[e]=m[e];function y(e){const t=new x(e);return new Proxy(t,{get(e,t){if(t in e&&0!==t.indexOf("_")){if("function"==typeof e[t])return(n=e[t],function(){let e;try{e=n.apply(this,arguments)}catch(e){if(a(e))return c.call(this,e),e;throw e}return i(e)?e.then(e=>(a(e)&&c.call(this,e),e),e=>{if(a(e))return c.call(this,e),e;throw e}):(a(e)&&c.call(this,e),e)}).bind(e);if("context"!==t&&"config"!==t)return e[t]}var n}})}x.prototype.createInstance=y;const O={createInstance:y};module.exports=O; diff --git a/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json b/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json new file mode 100644 index 0000000..7003ea0 --- /dev/null +++ b/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json @@ -0,0 +1,20 @@ +{ + "name": "uni-id-common", + "version": "1.0.18", + "description": "uni-id token生成、校验、刷新", + "main": "index.js", + "homepage": "https:\/\/uniapp.dcloud.io\/uniCloud\/uni-id-common.html", + "repository": { + "type": "git", + "url": "git+https:\/\/gitee.com\/dcloud\/uni-id-common.git" + }, + "author": "DCloud", + "license": "Apache-2.0", + "dependencies": { + "uni-config-center": "file:..\/..\/..\/..\/..\/uni-config-center\/uniCloud\/cloudfunctions\/common\/uni-config-center" + }, + "origin-plugin-dev-name": "uni-id-common", + "origin-plugin-version": "1.0.18", + "plugin-dev-name": "uni-id-common", + "plugin-version": "1.0.18" +} \ No newline at end of file From faab5b2bd175f18259d79ca50236534346472f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= Date: Thu, 10 Jul 2025 16:36:17 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 52 +++++++++++-------------- manifest.json | 3 +- pages/login/index.vue | 91 ++++++++++++++++++++++++++++--------------- 3 files changed, 84 insertions(+), 62 deletions(-) diff --git a/App.vue b/App.vue index fc46699..e014cf5 100644 --- a/App.vue +++ b/App.vue @@ -30,41 +30,33 @@ export default { console.error(`暂时不支持运行到小程序端`); // #endif // 集成cid全局获取和存储 - uni.getPushClientId({ - success: (res) => { - console.log(res, 'app-Push-ID'); - if (res && res.cid) { - uni.setStorageSync('cid', res.cid); - } - }, - fail: (err) => { - console.log(err) - } - }) + // uni.getPushClientId({ + // success: (res) => { + // console.log(res, 'app-Push-ID'); + // if (res && res.cid) { + // uni.setStorageSync('cid', res.cid); + // } + // }, + // fail: (err) => { + // console.log(err) + // } + // }) }, onShow: function () { console.log("App Show"); IMSDK.asyncApi(IMSDK.IMMethods.SetAppBackgroundStatus, IMSDK.uuid(), false); - uni.getPushClientId({ - success(res) { - console.log(res, 'app-Push-ID'); - }, - fail(err) { - console.log(err) - } - }) //#ifdef APP-PLUS - var info = plus.push.getClientInfo() - plus.push.addEventListener("click", function(msg) { - console.log("click:" + JSON.stringify(msg)); - console.log(msg.payload); - console.log(JSON.stringify(msg)); - }, false); - // 监听在线消息事件 - plus.push.addEventListener("receive", function(msg) { - //业务代码 - console.log("recevice:" + JSON.stringify(msg)) - }, false); + // var info = plus.push.getClientInfo() + // plus.push.addEventListener("click", function(msg) { + // console.log("click:" + JSON.stringify(msg)); + // console.log(msg.payload); + // console.log(JSON.stringify(msg)); + // }, false); + // // 监听在线消息事件 + // plus.push.addEventListener("receive", function(msg) { + // //业务代码 + // console.log("recevice:" + JSON.stringify(msg)) + // }, false); //#endif diff --git a/manifest.json b/manifest.json index 3999c3e..999013a 100644 --- a/manifest.json +++ b/manifest.json @@ -74,7 +74,8 @@ "speech" : {}, "push" : { "unipush" : { - "offline" : true + "offline" : true, + "oppo" : {} } } }, diff --git a/pages/login/index.vue b/pages/login/index.vue index 7bc26d6..88ea34f 100644 --- a/pages/login/index.vue +++ b/pages/login/index.vue @@ -216,42 +216,71 @@ export default { this.$store.dispatch("contact/getSentFriendApplications"); this.$store.dispatch("contact/getRecvGroupApplications"); this.$store.dispatch("contact/getSentGroupApplications"); + // 登录成功后,绑定deviceId与imId + // 获取设备cid,调用云函数 + // const cid = uni.getStorageSync('cid'); + // uniCloud.callFunction({ + // name: 'bindingIm', + // data: { + // deviceId: cid, + // imId: userID + // }, + // success: (res) => { + // if (res.result.code === 200) { + // uni.showToast({ + // title: res.result.msg, + // icon: 'success' + // }); + // } else { + // uni.showToast({ + // title: res.result.msg, + // icon: 'none' + // }); + // } + // }, + // fail: (err) => { + // uni.showToast({ + // title: '云函数调用失败', + // icon: 'none' + // }); + // console.error(err); + // } + // }); uni.switchTab({ url: "/pages/conversation/conversationList/index", }); await getSMSCodeFromOa(this.loginInfo.phoneNumber); const info = await loginOaByPhone(this.loginInfo.phoneNumber) - console.log('用户信息', info) - const oaUserId = info.userInfo.userId; - // 获取设备cid,调用云函数 - const cid = uni.getStorageSync('cid'); - uniCloud.callFunction({ - name: 'binding', - data: { - oaId: oaUserId, - deviceId: cid - }, - success: (res) => { - if (res.result.code === 200) { - uni.showToast({ - title: res.result.msg, - icon: 'success' - }); - } else { - uni.showToast({ - title: res.result.msg, - icon: 'none' - }); - } - }, - fail: (err) => { - uni.showToast({ - title: '云函数调用失败', - icon: 'none' - }); - console.error(err); - } - }); + // console.log('用户信息', info) + // const oaUserId = info.userInfo.userId; + + // uniCloud.callFunction({ + // name: 'binding', + // data: { + // oaId: oaUserId, + // deviceId: cid + // }, + // success: (res) => { + // if (res.result.code === 200) { + // uni.showToast({ + // title: res.result.msg, + // icon: 'success' + // }); + // } else { + // uni.showToast({ + // title: res.result.msg, + // icon: 'none' + // }); + // } + // }, + // fail: (err) => { + // uni.showToast({ + // title: '云函数调用失败', + // icon: 'none' + // }); + // console.error(err); + // } + // }); this.loginInfo.password = ""; this.loading = false; From 561601910fdf6fecdd8de456bed8321cf391b0e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= Date: Fri, 11 Jul 2025 10:07:03 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=BF=BD=E7=95=A5?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=EF=BC=8C=E6=8A=A5=E5=B7=A5=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 47 ++- api/oa/login.js | 1 + components/ReportCard/index.vue | 254 +++++++++++++++ components/ReportDetail/index.vue | 263 ++++++++++++++++ pages/profile/index/index.vue | 47 ++- pages/workbench/reportWork/reportWork.vue | 367 ++++++++++++++-------- 6 files changed, 849 insertions(+), 130 deletions(-) create mode 100644 components/ReportCard/index.vue create mode 100644 components/ReportDetail/index.vue diff --git a/App.vue b/App.vue index e014cf5..4f68a13 100644 --- a/App.vue +++ b/App.vue @@ -471,7 +471,7 @@ export default { }, }; -function checkUpdate() { +function checkUpdate(forceCheck = false) { const localVersion = plus.runtime.version; const localWgtVersion = uni.getStorageSync('wgtVersion') || localVersion; uni.request({ @@ -483,11 +483,19 @@ function checkUpdate() { const currentVersion = compareVersion(localWgtVersion, localVersion) > 0 ? localWgtVersion : localVersion; console.log('本地基座版本:', localVersion, '本地wgt版本:', localWgtVersion, '当前对比版本:', currentVersion, '远程版本:', remoteVersion); if (compareVersion(remoteVersion, currentVersion) > 0) { + // 检查是否已忽略当前版本(除非强制检查) + const ignoredVersion = uni.getStorageSync('ignoredVersion'); + if (!forceCheck && ignoredVersion === remoteVersion) { + console.log('用户已选择忽略此版本:', remoteVersion); + return; + } + uni.showModal({ title: '发现新版本', content: `检测到新版本(${remoteVersion}),是否立即下载并更新?`, confirmText: '立即更新', cancelText: '暂不更新', + showCancel: true, success: (modalRes) => { if (modalRes.confirm) { uni.showLoading({title: '正在下载更新包...'}); @@ -520,6 +528,20 @@ function checkUpdate() { uni.showToast({title: '下载失败'}); } }); + } else { + // 用户选择暂不更新,询问是否忽略此版本 + uni.showModal({ + title: '忽略更新', + content: `是否忽略版本 ${remoteVersion}?忽略后下次启动时将不再提示此版本更新。`, + confirmText: '忽略此版本', + cancelText: '下次提醒', + success: (ignoreRes) => { + if (ignoreRes.confirm) { + uni.setStorageSync('ignoredVersion', remoteVersion); + uni.showToast({title: '已忽略此版本更新'}); + } + } + }); } } }); @@ -550,6 +572,29 @@ function compareVersion(v1, v2) { } return 0; } + +// 更新管理工具函数 +function clearIgnoredVersion() { + uni.removeStorageSync('ignoredVersion'); + console.log('已清除忽略的版本设置'); +} + +function getIgnoredVersion() { + return uni.getStorageSync('ignoredVersion'); +} + +function setIgnoredVersion(version) { + uni.setStorageSync('ignoredVersion', version); + console.log('已设置忽略版本:', version); +} + +// 导出更新管理函数供其他页面使用 +uni.$updateManager = { + checkUpdate: (forceCheck = false) => checkUpdate(forceCheck), + clearIgnoredVersion, + getIgnoredVersion, + setIgnoredVersion +}; \ No newline at end of file diff --git a/components/ReportDetail/index.vue b/components/ReportDetail/index.vue new file mode 100644 index 0000000..ac312c4 --- /dev/null +++ b/components/ReportDetail/index.vue @@ -0,0 +1,263 @@ + + + + + \ No newline at end of file diff --git a/pages/profile/index/index.vue b/pages/profile/index/index.vue index b2847f0..a148115 100644 --- a/pages/profile/index/index.vue +++ b/pages/profile/index/index.vue @@ -66,6 +66,11 @@ export default { idx: 3, title: "关于我们", icon: require("static/images/profile_menu_about.png"), + }, + { + idx: 4, + title: "应用更新", + icon: require("static/images/profile_menu_about.png"), }, { idx: 5, @@ -73,7 +78,7 @@ export default { icon: require("static/images/profile_menu_about.png") }, { - idx: 4, + idx: 6, title: "退出登录", icon: require("static/images/profile_menu_logout.png"), }, @@ -134,6 +139,9 @@ export default { uni.navigateTo({ url: "/pages/profile/about/index", }); + break; + case 4: + this.showUpdateOptions(); break; case 5: uni.createPushMessage({ @@ -147,7 +155,7 @@ export default { } }); break; - case 4: + case 6: uni.showModal({ title: "提示", content: "确定要退出当前账号吗?", @@ -169,6 +177,41 @@ export default { url: `/pages/common/userOrGroupQrCode/index`, }); }, + showUpdateOptions() { + const ignoredVersion = uni.$updateManager.getIgnoredVersion(); + let content = '选择更新操作:'; + if (ignoredVersion) { + content += `\n当前忽略版本:${ignoredVersion}`; + } + + uni.showActionSheet({ + itemList: ['检查更新', '清除忽略版本', '取消'], + success: (res) => { + switch (res.tapIndex) { + case 0: + // 检查更新(强制检查) + uni.$updateManager.checkUpdate(true); + break; + case 1: + // 清除忽略版本 + uni.showModal({ + title: '确认操作', + content: '确定要清除忽略的版本设置吗?清除后将重新提示所有版本更新。', + success: (modalRes) => { + if (modalRes.confirm) { + uni.$updateManager.clearIgnoredVersion(); + uni.showToast({title: '已清除忽略版本设置'}); + } + } + }); + break; + case 2: + // 取消 + break; + } + } + }); + }, }, }; diff --git a/pages/workbench/reportWork/reportWork.vue b/pages/workbench/reportWork/reportWork.vue index 789fed5..c0dd73b 100644 --- a/pages/workbench/reportWork/reportWork.vue +++ b/pages/workbench/reportWork/reportWork.vue @@ -1,55 +1,58 @@ diff --git a/pages/workbench/reportWork/reportWork.vue b/pages/workbench/reportWork/reportWork.vue index c0dd73b..fe903b7 100644 --- a/pages/workbench/reportWork/reportWork.vue +++ b/pages/workbench/reportWork/reportWork.vue @@ -227,8 +227,8 @@ export default { const tabHeight = 100; // tab高度 const containerPadding = 40; // 容器padding // 悬浮按钮是固定定位,不需要预留空间,让卡片列表到达底部 - // 我也不知道为什么要 + 100, 不然滚动高度下面一大片空白,这个不太好调试 - this.scrollHeight = systemInfo.windowHeight - tabHeight - containerPadding + 100; + // 我也不知道为什么要 + 80, 不然滚动高度下面一大片空白,这个不太好调试 + this.scrollHeight = systemInfo.windowHeight - tabHeight - containerPadding + 80; }, // 切换tab diff --git a/pages/workbench/task/create.vue b/pages/workbench/task/create.vue new file mode 100644 index 0000000..d0758b6 --- /dev/null +++ b/pages/workbench/task/create.vue @@ -0,0 +1,972 @@ +