From c24113d96fa5c8adc72defe85da4bccd2696208f Mon Sep 17 00:00:00 2001 From: syruan <15555146157@163.com> Date: Mon, 10 Nov 2025 13:32:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 335 +++++++++++++++++++++++++++ app.json | 29 ++- pages/device/add/add.json | 11 +- pages/device/detail/detail.json | 9 +- pages/device/list/list.json | 11 +- pages/index/index.json | 8 +- pages/profile/index/index.js | 158 ++++++++++++- pages/profile/index/index.json | 9 +- pages/profile/index/index.wxml | 29 ++- pages/profile/index/index.wxss | 6 + pages/statistics/index/index.json | 5 +- pages/warning/list/list.json | 9 +- pages/warning/settings/settings.js | 164 ++++++++++++- pages/warning/settings/settings.json | 8 +- pages/warning/settings/settings.wxml | 42 +++- pages/warning/settings/settings.wxss | 4 + 16 files changed, 805 insertions(+), 32 deletions(-) diff --git a/app.js b/app.js index 2c70df4..cdc19b9 100644 --- a/app.js +++ b/app.js @@ -1,10 +1,345 @@ import gulpError from './utils/gulpError'; + App({ + globalData: { + userInfo: null, + authInfo: null + }, + + onLaunch(options) { + console.log('小程序启动', options); + + // 检查登录状态 + this.checkLoginStatus(); + + // 检查更新 + this.checkUpdate(); + }, + onShow() { if (gulpError !== 'gulpErrorPlaceHolder') { wx.redirectTo({ url: `/pages/gulp-error/index?gulpError=${gulpError}`, }); + return; + } + + // 刷新登录状态 + this.refreshLoginStatus(); + }, + + // ==================== 认证相关方法 ==================== + + /** + * 检查是否已登录 + */ + isLoggedIn() { + const userInfo = wx.getStorageSync('userInfo'); + const authInfo = wx.getStorageSync('authInfo'); + return !!(userInfo && authInfo); + }, + + /** + * 获取用户信息 + */ + getUserInfo() { + return wx.getStorageSync('userInfo') || this.globalData.userInfo; + }, + + /** + * 保存用户信息 + */ + saveUserInfo(userInfo) { + wx.setStorageSync('userInfo', userInfo); + this.globalData.userInfo = userInfo; + }, + + /** + * 获取认证信息 + */ + getAuthInfo() { + return wx.getStorageSync('authInfo') || this.globalData.authInfo; + }, + + /** + * 保存认证信息 + */ + saveAuthInfo(authInfo) { + wx.setStorageSync('authInfo', authInfo); + this.globalData.authInfo = authInfo; + }, + + /** + * 用户登录 + */ + login() { + return new Promise((resolve, reject) => { + // 1. 先获取用户信息(必须在同步上下文中) + wx.getUserProfile({ + desc: '用于完善用户资料', + success: userProfileRes => { + const userInfo = userProfileRes.userInfo; + this.saveUserInfo(userInfo); + console.log('获取用户信息成功', userInfo); + + // 2. 再执行 wx.login + wx.login({ + success: loginRes => { + console.log('登录成功,code:', loginRes.code); + + // TODO: 将 code 发送到后端,换取 openId 和 session_key + // 这里使用模拟数据 + const authInfo = { + token: 'mock_token_' + Date.now(), + openId: 'mock_openid_' + Date.now(), + sessionKey: 'mock_session_key', + loginTime: Date.now() + }; + + this.saveAuthInfo(authInfo); + console.log('保存认证信息成功'); + + resolve({ + success: true, + userInfo: userInfo, + authInfo: authInfo + }); + }, + fail: loginErr => { + console.error('wx.login 失败', loginErr); + reject(loginErr); + } + }); + }, + fail: userProfileErr => { + console.error('获取用户信息失败', userProfileErr); + reject(userProfileErr); + } + }); + }); + }, + + /** + * 静默登录(不需要用户授权) + */ + silentLogin() { + return new Promise((resolve, reject) => { + wx.login({ + success: res => { + console.log('静默登录成功,code:', res.code); + + // TODO: 将 code 发送到后端 + const authInfo = { + token: 'mock_token_' + Date.now(), + openId: 'mock_openid_' + Date.now(), + sessionKey: 'mock_session_key', + loginTime: Date.now() + }; + + this.saveAuthInfo(authInfo); + resolve({ success: true, authInfo }); + }, + fail: reject + }); + }); + }, + + /** + * 检查登录状态 + */ + checkLoginStatus() { + if (this.isLoggedIn()) { + this.globalData.userInfo = this.getUserInfo(); + this.globalData.authInfo = this.getAuthInfo(); + console.log('用户已登录', this.globalData.userInfo); + } else { + console.log('用户未登录'); } }, + + /** + * 刷新登录状态 + */ + async refreshLoginStatus() { + try { + // 检查会话是否有效 + const sessionValid = await this.checkSession(); + if (!sessionValid) { + // 会话过期,静默登录 + await this.silentLogin(); + } + this.checkLoginStatus(); + } catch (error) { + console.error('刷新登录状态失败', error); + } + }, + + /** + * 检查会话是否有效 + */ + checkSession() { + return new Promise(resolve => { + wx.checkSession({ + success: () => { + console.log('会话未过期'); + resolve(true); + }, + fail: () => { + console.log('会话已过期'); + resolve(false); + } + }); + }); + }, + + /** + * 退出登录 + */ + logout() { + wx.removeStorageSync('userInfo'); + wx.removeStorageSync('authInfo'); + this.globalData.userInfo = null; + this.globalData.authInfo = null; + + wx.reLaunch({ + url: '/pages/login/login' + }); + }, + + // ==================== 消息推送相关方法 ==================== + + /** + * 订阅消息模板ID + */ + TEMPLATE_IDS: { + INSPECTION_REMINDER: 'YOUR_TEMPLATE_ID_1', + WARNING_NOTICE: 'YOUR_TEMPLATE_ID_2', + INSPECTION_COMPLETE: 'YOUR_TEMPLATE_ID_3' + }, + + /** + * 请求订阅消息 + */ + requestSubscribeMessage(tmplIds) { + return new Promise((resolve, reject) => { + wx.requestSubscribeMessage({ + tmplIds: tmplIds, + success: res => { + console.log('订阅消息成功', res); + resolve(res); + }, + fail: err => { + console.error('订阅消息失败', err); + reject(err); + } + }); + }); + }, + + /** + * 订阅所有消息 + */ + async subscribeAllMessages() { + try { + const result = await this.requestSubscribeMessage([ + this.TEMPLATE_IDS.INSPECTION_REMINDER, + this.TEMPLATE_IDS.WARNING_NOTICE, + this.TEMPLATE_IDS.INSPECTION_COMPLETE + ]); + + // 保存订阅状态 + const subscriptionStatus = { + inspectionReminder: result[this.TEMPLATE_IDS.INSPECTION_REMINDER] === 'accept', + warningNotice: result[this.TEMPLATE_IDS.WARNING_NOTICE] === 'accept', + inspectionComplete: result[this.TEMPLATE_IDS.INSPECTION_COMPLETE] === 'accept', + updateTime: Date.now() + }; + + wx.setStorageSync('subscription_status', subscriptionStatus); + return { success: true, subscriptionStatus }; + } catch (error) { + console.error('订阅失败', error); + return { success: false, error }; + } + }, + + /** + * 获取订阅状态 + */ + getSubscriptionStatus() { + return wx.getStorageSync('subscription_status') || { + inspectionReminder: false, + warningNotice: false, + inspectionComplete: false + }; + }, + + /** + * 检查是否已订阅 + */ + isSubscribed() { + const status = this.getSubscriptionStatus(); + return status.inspectionReminder || status.warningNotice || status.inspectionComplete; + }, + + /** + * 获取消息推送设置 + */ + getNotificationSettings() { + return wx.getStorageSync('notification_settings') || { + enabled: true, + inspectionReminder: true, + warningNotice: true, + advanceDays: 7 + }; + }, + + /** + * 保存消息推送设置 + */ + saveNotificationSettings(settings) { + wx.setStorageSync('notification_settings', settings); + }, + + // ==================== 其他方法 ==================== + + /** + * 检查小程序更新 + */ + checkUpdate() { + if (wx.canIUse('getUpdateManager')) { + const updateManager = wx.getUpdateManager(); + + updateManager.onCheckForUpdate(res => { + console.log('检查更新', res.hasUpdate); + }); + + updateManager.onUpdateReady(() => { + wx.showModal({ + title: '更新提示', + content: '新版本已经准备好,是否重启应用?', + success: res => { + if (res.confirm) { + updateManager.applyUpdate(); + } + } + }); + }); + + updateManager.onUpdateFailed(() => { + wx.showModal({ + title: '更新失败', + content: '新版本下载失败,请检查网络后重试', + showCancel: false + }); + }); + } + }, + + /** + * 设置用户信息 + */ + setUserInfo(userInfo) { + this.saveUserInfo(userInfo); + } }); diff --git a/app.json b/app.json index 8edf531..644b4f0 100644 --- a/app.json +++ b/app.json @@ -1,6 +1,7 @@ { "darkmode": true, "pages": [ + "pages/login/login", "pages/index/index", "pages/device/list/list", "pages/device/detail/detail", @@ -19,23 +20,33 @@ "list": [ { "pagePath": "pages/index/index", - "text": "首页" + "text": "首页", + "iconPath": "assets/icons/home.png", + "selectedIconPath": "assets/icons/home-active.png" }, { "pagePath": "pages/device/list/list", - "text": "设备" + "text": "设备", + "iconPath": "assets/icons/device.png", + "selectedIconPath": "assets/icons/device-active.png" }, { "pagePath": "pages/statistics/index/index", - "text": "统计" + "text": "统计", + "iconPath": "assets/icons/chart.png", + "selectedIconPath": "assets/icons/chart-active.png" }, { "pagePath": "pages/warning/list/list", - "text": "预警" + "text": "预警", + "iconPath": "assets/icons/warning.png", + "selectedIconPath": "assets/icons/warning-active.png" }, { "pagePath": "pages/profile/index/index", - "text": "我的" + "text": "我的", + "iconPath": "assets/icons/user.png", + "selectedIconPath": "assets/icons/user-active.png" } ] }, @@ -66,6 +77,14 @@ "navigationBarTextStyle": "white", "backgroundColor": "#F5F5F5" }, + "permission": { + "scope.userLocation": { + "desc": "你的位置信息将用于设备定位" + } + }, + "requiredPrivateInfos": [ + "getLocation" + ], "sitemapLocation": "sitemap.json", "lazyCodeLoading": "requiredComponents" } diff --git a/pages/device/add/add.json b/pages/device/add/add.json index dfd6268..5530045 100644 --- a/pages/device/add/add.json +++ b/pages/device/add/add.json @@ -1,4 +1,13 @@ { - "navigationBarTitleText": "添加设备" + "navigationBarTitleText": "添加设备", + "usingComponents": { + "t-input": "tdesign-miniprogram/input/input", + "t-picker": "tdesign-miniprogram/picker/picker", + "t-picker-item": "tdesign-miniprogram/picker-item/picker-item", + "t-date-time-picker": "tdesign-miniprogram/date-time-picker/date-time-picker", + "t-button": "tdesign-miniprogram/button/button", + "t-cell": "tdesign-miniprogram/cell/cell", + "t-cell-group": "tdesign-miniprogram/cell-group/cell-group" + } } diff --git a/pages/device/detail/detail.json b/pages/device/detail/detail.json index 2357806..bf574b5 100644 --- a/pages/device/detail/detail.json +++ b/pages/device/detail/detail.json @@ -1,4 +1,11 @@ { - "navigationBarTitleText": "设备详情" + "navigationBarTitleText": "设备详情", + "usingComponents": { + "t-icon": "tdesign-miniprogram/icon/icon", + "t-tag": "tdesign-miniprogram/tag/tag", + "t-button": "tdesign-miniprogram/button/button", + "t-cell": "tdesign-miniprogram/cell/cell", + "t-cell-group": "tdesign-miniprogram/cell-group/cell-group" + } } diff --git a/pages/device/list/list.json b/pages/device/list/list.json index 6415e67..643424d 100644 --- a/pages/device/list/list.json +++ b/pages/device/list/list.json @@ -1,6 +1,15 @@ { "navigationBarTitleText": "设备台账", "enablePullDownRefresh": true, - "backgroundColor": "#F5F5F5" + "backgroundColor": "#F5F5F5", + "usingComponents": { + "t-icon": "tdesign-miniprogram/icon/icon", + "t-search": "tdesign-miniprogram/search/search", + "t-tabs": "tdesign-miniprogram/tabs/tabs", + "t-tab-panel": "tdesign-miniprogram/tab-panel/tab-panel", + "t-tag": "tdesign-miniprogram/tag/tag", + "t-empty": "tdesign-miniprogram/empty/empty", + "t-loading": "tdesign-miniprogram/loading/loading" + } } diff --git a/pages/index/index.json b/pages/index/index.json index 9dcc108..a10c914 100644 --- a/pages/index/index.json +++ b/pages/index/index.json @@ -1,6 +1,12 @@ { "navigationBarTitleText": "工作台", "enablePullDownRefresh": true, - "backgroundColor": "#F5F5F5" + "backgroundColor": "#F5F5F5", + "usingComponents": { + "t-icon": "tdesign-miniprogram/icon/icon", + "t-tag": "tdesign-miniprogram/tag/tag", + "t-empty": "tdesign-miniprogram/empty/empty", + "t-button": "tdesign-miniprogram/button/button" + } } diff --git a/pages/profile/index/index.js b/pages/profile/index/index.js index c220877..d77201a 100644 --- a/pages/profile/index/index.js +++ b/pages/profile/index/index.js @@ -1,5 +1,117 @@ // pages/profile/index/index.js +const app = getApp(); + Page({ + data: { + isLoggedIn: false, + userInfo: null, + isSubscribed: false + }, + + onLoad() { + this.loadUserInfo(); + }, + + onShow() { + this.loadUserInfo(); + this.checkSubscriptionStatus(); + }, + + /** + * 加载用户信息 + */ + loadUserInfo() { + const isLoggedIn = app.isLoggedIn(); + const userInfo = app.getUserInfo(); + + this.setData({ + isLoggedIn, + userInfo: userInfo || { + nickName: '未登录', + avatarUrl: '' + } + }); + }, + + /** + * 检查订阅状态 + */ + checkSubscriptionStatus() { + const isSubscribed = app.isSubscribed(); + this.setData({ + isSubscribed + }); + }, + + /** + * 点击头部区域 + */ + handleHeaderTap() { + if (!this.data.isLoggedIn) { + wx.navigateTo({ + url: '/pages/login/login' + }); + } + }, + + /** + * 消息通知设置 + */ + goToNotificationSettings() { + if (!this.data.isLoggedIn) { + wx.showModal({ + title: '提示', + content: '请先登录', + confirmText: '去登录', + success: res => { + if (res.confirm) { + wx.navigateTo({ + url: '/pages/login/login' + }); + } + } + }); + return; + } + + wx.showModal({ + title: '消息通知', + content: '是否开启消息推送通知?开启后可以及时接收设备检验预警提醒', + confirmText: '开启', + cancelText: '取消', + success: async res => { + if (res.confirm) { + try { + await app.subscribeAllMessages(); + this.setData({ isSubscribed: true }); + wx.showToast({ + title: '订阅成功', + icon: 'success' + }); + } catch (error) { + console.error('订阅失败', error); + wx.showToast({ + title: '订阅失败', + icon: 'none' + }); + } + } + } + }); + }, + + /** + * 预警设置 + */ + goToWarningSettings() { + wx.navigateTo({ + url: '/pages/warning/settings/settings' + }); + }, + + /** + * 单位管理 + */ goToUnitManage() { wx.showToast({ title: '功能开发中', @@ -7,19 +119,35 @@ Page({ }); }, - goToWarningSettings() { - wx.navigateTo({ - url: '/pages/warning/settings/settings' - }); - }, - + /** + * 数据导出 + */ exportData() { + if (!this.data.isLoggedIn) { + wx.showModal({ + title: '提示', + content: '请先登录', + confirmText: '去登录', + success: res => { + if (res.confirm) { + wx.navigateTo({ + url: '/pages/login/login' + }); + } + } + }); + return; + } + wx.showToast({ title: '功能开发中', icon: 'none' }); }, + /** + * 关于我们 + */ goToAbout() { wx.showModal({ title: '关于我们', @@ -28,11 +156,29 @@ Page({ }); }, + /** + * 帮助中心 + */ goToHelp() { wx.showToast({ title: '功能开发中', icon: 'none' }); + }, + + /** + * 退出登录 + */ + handleLogout() { + wx.showModal({ + title: '确认退出', + content: '确定要退出登录吗?', + success: res => { + if (res.confirm) { + app.logout(); + } + } + }); } }); diff --git a/pages/profile/index/index.json b/pages/profile/index/index.json index 7a20af3..8f69dfd 100644 --- a/pages/profile/index/index.json +++ b/pages/profile/index/index.json @@ -1,4 +1,11 @@ { - "navigationBarTitleText": "我的" + "navigationBarTitleText": "我的", + "usingComponents": { + "t-icon": "tdesign-miniprogram/icon/icon", + "t-cell": "tdesign-miniprogram/cell/cell", + "t-cell-group": "tdesign-miniprogram/cell-group/cell-group", + "t-tag": "tdesign-miniprogram/tag/tag", + "t-button": "tdesign-miniprogram/button/button" + } } diff --git a/pages/profile/index/index.wxml b/pages/profile/index/index.wxml index 0d84436..adf8882 100644 --- a/pages/profile/index/index.wxml +++ b/pages/profile/index/index.wxml @@ -1,22 +1,31 @@ - + - + + + - - + + + + 已开启 + 未开启 + - + + + + @@ -35,6 +44,12 @@ + + + 退出登录 + + + 版本号:v1.0.0 diff --git a/pages/profile/index/index.wxss b/pages/profile/index/index.wxss index a414d0a..d707c1f 100644 --- a/pages/profile/index/index.wxss +++ b/pages/profile/index/index.wxss @@ -20,6 +20,12 @@ align-items: center; justify-content: center; margin-right: 32rpx; + overflow: hidden; +} + +.avatar-img { + width: 100%; + height: 100%; } .user-info { diff --git a/pages/statistics/index/index.json b/pages/statistics/index/index.json index 01a12a4..01be1de 100644 --- a/pages/statistics/index/index.json +++ b/pages/statistics/index/index.json @@ -1,4 +1,7 @@ { - "navigationBarTitleText": "统计分析" + "navigationBarTitleText": "统计分析", + "usingComponents": { + "t-icon": "tdesign-miniprogram/icon/icon" + } } diff --git a/pages/warning/list/list.json b/pages/warning/list/list.json index 28e66b8..cbf8dc5 100644 --- a/pages/warning/list/list.json +++ b/pages/warning/list/list.json @@ -1,4 +1,11 @@ { - "navigationBarTitleText": "预警中心" + "navigationBarTitleText": "预警中心", + "usingComponents": { + "t-icon": "tdesign-miniprogram/icon/icon", + "t-tabs": "tdesign-miniprogram/tabs/tabs", + "t-tab-panel": "tdesign-miniprogram/tab-panel/tab-panel", + "t-tag": "tdesign-miniprogram/tag/tag", + "t-empty": "tdesign-miniprogram/empty/empty" + } } diff --git a/pages/warning/settings/settings.js b/pages/warning/settings/settings.js index 3c56c3d..7882ba1 100644 --- a/pages/warning/settings/settings.js +++ b/pages/warning/settings/settings.js @@ -1,9 +1,50 @@ // pages/warning/settings/settings.js +const app = getApp(); + Page({ data: { - warningDays: 30 + warningDays: 30, + subscriptionStatus: { + inspection: false, + warning: false + } }, + onLoad() { + this.loadSettings(); + }, + + onShow() { + this.checkSubscriptionStatus(); + }, + + /** + * 加载设置 + */ + loadSettings() { + const settings = app.getNotificationSettings(); + this.setData({ + warningDays: settings.advanceDays || 30 + }); + }, + + /** + * 检查订阅状态 + */ + checkSubscriptionStatus() { + const status = app.getSubscriptionStatus(); + + this.setData({ + subscriptionStatus: { + inspection: status.inspectionReminder, + warning: status.warningNotice + } + }); + }, + + /** + * 显示天数选择器 + */ showDaysPicker() { wx.showActionSheet({ itemList: ['7天', '15天', '30天', '60天', '90天'], @@ -18,10 +59,125 @@ Page({ }); }, - goToMessageSettings() { + /** + * 订阅检验提醒 + */ + async subscribeInspection() { + if (!app.isLoggedIn()) { + this.showLoginTip(); + return; + } + + try { + await app.requestSubscribeMessage([ + app.TEMPLATE_IDS.INSPECTION_REMINDER + ]); + + this.checkSubscriptionStatus(); + + wx.showToast({ + title: '订阅成功', + icon: 'success' + }); + } catch (error) { + console.error('订阅失败', error); + wx.showToast({ + title: '订阅失败', + icon: 'none' + }); + } + }, + + /** + * 订阅预警通知 + */ + async subscribeWarning() { + if (!app.isLoggedIn()) { + this.showLoginTip(); + return; + } + + try { + await app.requestSubscribeMessage([ + app.TEMPLATE_IDS.WARNING_NOTICE + ]); + + this.checkSubscriptionStatus(); + + wx.showToast({ + title: '订阅成功', + icon: 'success' + }); + } catch (error) { + console.error('订阅失败', error); + wx.showToast({ + title: '订阅失败', + icon: 'none' + }); + } + }, + + /** + * 订阅所有消息 + */ + async subscribeAll() { + if (!app.isLoggedIn()) { + this.showLoginTip(); + return; + } + + try { + await app.subscribeAllMessages(); + + this.checkSubscriptionStatus(); + + wx.showToast({ + title: '订阅成功', + icon: 'success' + }); + } catch (error) { + console.error('订阅失败', error); + wx.showToast({ + title: '订阅失败', + icon: 'none' + }); + } + }, + + /** + * 保存设置 + */ + saveSettings() { + const settings = { + enabled: true, + inspectionReminder: this.data.subscriptionStatus.inspection, + warningNotice: this.data.subscriptionStatus.warning, + advanceDays: this.data.warningDays + }; + + app.saveNotificationSettings(settings); + wx.showToast({ - title: '功能开发中', - icon: 'none' + title: '保存成功', + icon: 'success' + }); + }, + + /** + * 显示登录提示 + */ + showLoginTip() { + wx.showModal({ + title: '提示', + content: '请先登录', + confirmText: '去登录', + success: res => { + if (res.confirm) { + wx.navigateTo({ + url: '/pages/login/login' + }); + } + } }); } }); diff --git a/pages/warning/settings/settings.json b/pages/warning/settings/settings.json index 16d37d3..b4c7594 100644 --- a/pages/warning/settings/settings.json +++ b/pages/warning/settings/settings.json @@ -1,4 +1,10 @@ { - "navigationBarTitleText": "预警设置" + "navigationBarTitleText": "预警设置", + "usingComponents": { + "t-icon": "tdesign-miniprogram/icon/icon", + "t-cell": "tdesign-miniprogram/cell/cell", + "t-cell-group": "tdesign-miniprogram/cell-group/cell-group", + "t-button": "tdesign-miniprogram/button/button" + } } diff --git a/pages/warning/settings/settings.wxml b/pages/warning/settings/settings.wxml index f2fe198..16f6fc0 100644 --- a/pages/warning/settings/settings.wxml +++ b/pages/warning/settings/settings.wxml @@ -4,7 +4,38 @@ 预警设置 - + + + + + 消息推送设置 + + + + + + + + + + @@ -15,9 +46,16 @@ • 系统会在设备检验到期前提前预警 - • 可以设置消息推送,及时接收预警通知 + • 订阅消息后才能接收推送通知 • 建议提前30天进行预警设置 + • 设置后立即生效 + + + + 保存设置 + + diff --git a/pages/warning/settings/settings.wxss b/pages/warning/settings/settings.wxss index b96071b..127d6b7 100644 --- a/pages/warning/settings/settings.wxss +++ b/pages/warning/settings/settings.wxss @@ -48,3 +48,7 @@ line-height: 1.6; } +.save-section { + margin-top: 48rpx; +} +