const AIChatSocket = require('./utils/chatmsg.js') const API = require('./utils/api.js') const request = require('./utils/request.js') App({ onLaunch() { // request 层遇到 code 401(token 已失效)时回调这里:静默重登后自动重试原请求。 // 登录逻辑只在 app 里有一份,request 层不碰 request.setUnauthorizedHandler(() => this.silentSignin()) let appId = wx.getStorageSync('attendant-appid') if (!appId) { appId = 'app_' + Date.now().toString(36) + Math.random().toString(36).substr(2, 9) wx.setStorageSync('attendant-appid', appId) } this.globalData.appId = appId this.globalData.servicesReady = new Promise((resolve) => { API.resource.getServices().then((data) => { this.globalData.services = data.data.services resolve(data.data.services) }).catch((err) => { console.error('获取服务列表失败', err) resolve([]) }) }) this.globalData.agreementReady = new Promise((resolve) => { API.resource.getAgreement().then((data) => { this.globalData.agreement = data.data.agreement resolve(data.data.agreement) }).catch((err) => { console.error('获取服务协议失败', err) resolve(null) }) }) this.globalData.hospitalInfoReady = new Promise((resolve) => { API.resource.getHospitalInfo().then((data) => { this.globalData.hospitalInfo = data.data.hospitalInfo resolve(data.data.hospitalInfo) }).catch((err) => { console.error('获取医院信息失败', err) resolve([]) }) }) this.globalData.hospitalRankingReady = new Promise((resolve) => { API.resource.getHospitalRanking().then((data) => { this.globalData.hospitalRanking = data.data.hospitalRanking resolve(data.data.hospitalRanking) }).catch((err) => { console.error('获取医院排名失败', err) resolve([]) }) }) this.globalData.departmentRankingsReady = new Promise((resolve) => { API.resource.getDepartmentRankings().then((data) => { this.globalData.departmentRankings = data.data.departmentRankings resolve(data.data.departmentRankings) }).catch((err) => { console.error('获取科室排名失败', err) resolve([]) }) }) this.checkUpdate(); }, onShow() { this.silentSignin() this.initChatSocket() }, // 静默重登:app.onShow 与 request 层的 401 兜底共用这一个入口 // (wxsignin 只凭 code 换到 openid 就能签发 token,见 api/user/handler/users.js)。 // // 单飞:并发只发一次——每次 wxsignin 都会重签 token 覆盖上一次, // 两个请求重叠时 DB 里存的是后保存的那个、而 globalData 存的是后返回的那个, // 一旦错位本机就拿着作废的 token,之后所有接口都 401。 // // 用户主动退出过(has_logout)就不再静默重登,否则「我的」页的退出登录 // 会被切后台/重进抵消;用户在「我的」页重新授权成功时会清掉这个标记 silentSignin() { if (wx.getStorageSync('has_logout')) { return Promise.resolve(false) } if (this.signinPromise) { return this.signinPromise } this.signinPromise = new Promise((resolve) => { wx.login({ success: res => { if (!res.code) { console.log('登录失败!' + res.errMsg) resolve(false) return } API.user.wxSignin({ code: res.code }) .then((data) => { if (data.code == 0) { this.globalData.user = data.data.user resolve(true) } else { console.log('error:', data) resolve(false) } }) .catch((err) => { console.log('请求失败', err) resolve(false) }) }, fail: (err) => { console.log('登录失败!' + err.errMsg) resolve(false) } }) }).then((ok) => { this.signinPromise = null return ok }) return this.signinPromise }, initChatSocket() { if (this.globalData.chatSocket) return const socket = new AIChatSocket() socket.onOpen(() => { console.log('[App] Chat WebSocket connected') }) socket.onClose((res) => { console.log('[App] Chat WebSocket closed', res) }) socket.onError((err) => { console.error('[App] Chat WebSocket error', err) }) socket.connect().catch((err) => { console.error('[App] Chat WebSocket connect failed', err) }) this.globalData.chatSocket = socket }, checkUpdate() { // 获取小程序更新管理器实例 const updateManager = wx.getUpdateManager(); // 监听检查更新事件,当小程序有新版本时会触发此回调 updateManager.onCheckForUpdate(function (res) { // 请求完新版本信息的回调 console.log(res.hasUpdate); // 打印是否有新版本 }); // 监听更新准备就绪事件,当新版本下载完成时会触发此回调 updateManager.onUpdateReady(function () { wx.showModal({ title: '更新提示', content: '新版本已经准备好,可以重启应用小程序了!', success(res) { if (res.confirm) { // 用户确认更新,调用 applyUpdate 应用新版本并重启小程序 updateManager.applyUpdate(); } } }); }); // 监听更新失败事件,当新版本下载失败时会触发此回调 updateManager.onUpdateFailed(function () { // 新版本下载失败,可以在这里处理失败逻辑,例如提示用户稍后再试 }); }, globalData: { appId: '', user: null, chatSocket: null, services: [], agreement: null, hospitalInfo: [], hospitalRanking: [], departmentRankings: [], } })