import { queryById } from '@/config/api/order.js' /** * 订单监控服务 * 用于在后台监控订单状态变化,特别是归还完成状态 */ class OrderMonitor { constructor() { this.activeOrders = new Map() // 存储活跃订单 Map this.timer = null this.checkInterval = 5000 // 5秒检查一次,更及时地发现订单完成 this.isRunning = false this.currentPage = null // 当前活跃页面 } /** * 添加订单到监控队列 * @param {Object} orderData 订单数据对象,必须包含orderId字段 * @param {String} pageName 关联的页面名称,默认为'detail'(订单详情页) */ addOrder(orderData, pageName = 'detail') { if (!orderData || !orderData.orderId) { console.error('添加订单监控失败:无效的订单数据') return } console.log(`添加订单到监控队列: ${orderData.orderId}, 页面: ${pageName}`) this.activeOrders.set(orderData.orderId, { ...orderData, pageName }) // 如果监控服务尚未启动,则启动 if (!this.isRunning) { this.start() } } /** * 移除订单的监控 * @param {Object} params 包含orderId或pageName的对象 */ removeOrder(params) { if (!params) return // 如果提供了orderId,直接删除该订单 if (params.orderId && this.activeOrders.has(params.orderId)) { console.log('从监控队列移除订单:', params.orderId) this.activeOrders.delete(params.orderId) } // 如果提供了pageName,删除该页面关联的所有订单 else if (params.pageName) { console.log('从监控队列移除页面相关订单:', params.pageName) for (const [orderId, data] of this.activeOrders.entries()) { if (data.pageName === params.pageName) { this.activeOrders.delete(orderId) } } } // 如果没有订单需要监控了,停止服务 if (this.activeOrders.size === 0) { this.stop() } } /** * 设置当前活跃页面 * @param {String} pageName 页面名称 */ setActivePage(pageName) { this.currentPage = pageName console.log('设置当前活跃页面:', pageName) } /** * 启动监控服务 */ start() { if (this.isRunning) return console.log('启动订单监控服务') this.isRunning = true this.checkOrders() this.timer = setInterval(() => { this.checkOrders() }, this.checkInterval) } /** * 停止监控服务 */ stop() { if (!this.isRunning) return console.log('停止订单监控服务') this.isRunning = false if (this.timer) { clearInterval(this.timer) this.timer = null } } /** * 检查所有活跃订单的状态 */ async checkOrders() { if (this.activeOrders.size === 0) return console.log(`检查 ${this.activeOrders.size} 个活跃订单状态, 当前页面: ${this.currentPage}`) // 检查所有活跃订单,不限制页面 // 主要监控订单详情页(detail)和其他相关页面 for (const [orderId, data] of this.activeOrders.entries()) { try { // 检查所有使用中的订单状态 // 不限制页面,因为用户可能在任何页面时订单完成归还 await this.checkOrderStatus(orderId) } catch (error) { console.error(`检查订单状态失败: ${orderId}`, error) } } } /** * 检查单个订单的状态 * @param {String} orderId 订单ID */ async checkOrderStatus(orderId) { try { // 检查登录状态,避免在未登录时发起请求导致跳转到登录页 const token = uni.getStorageSync('token') if (!token) { console.log('用户未登录,停止订单监控') // 清理缓存的订单ID try { uni.removeStorageSync('activeOrderId') } catch (e) {} // 停止监控服务 this.stop() // 清空监控队列 this.activeOrders.clear() return } const currentTime = new Date(); console.log(`检查订单 ${orderId} 的状态`) const result = await queryById(orderId) if (result.code === 200 && result.data) { const orderData = result.data const existingData = this.activeOrders.get(orderId) const pageName = existingData ? existingData.pageName : null // 更新本地存储的订单数据,保留页面关联信息 this.activeOrders.set(orderId, { ...orderData, pageName }) // 检查订单是否已完成 if (orderData.orderStatus === 'used_done' || orderData.orderStatus === 'used_down') { console.log(`订单 ${orderId} 已完成!`) // 检查endTime与当前时间的差异 let shouldNotify = true; if (orderData.endTime) { const endTime = new Date(orderData.endTime); const timeDiff = Math.abs(currentTime - endTime) / (1000 * 60); // 时间差(分钟) // 如果时间差超过1分钟,不进行提醒 if (timeDiff > 3) { console.log(`订单 ${orderId} 完成时间与当前时间相差${timeDiff.toFixed(2)}分钟,超过3分钟,不进行提醒`); shouldNotify = false; } } if (shouldNotify) { // 触发全局事件(订单详情页会监听此事件自动刷新) uni.$emit('orderCompleted', orderData) // 显示全局通知 uni.showToast({ title: '风扇归还成功', icon: 'success', duration: 2000 }) // 播放通知声音(如果需要) // const innerAudioContext = uni.createInnerAudioContext() // innerAudioContext.src = '/static/audio/return_success.mp3' // innerAudioContext.play() // 如果用户不在订单详情页,则显示归还成功弹窗 // 如果在订单详情页,页面自己会处理状态变化 setTimeout(() => { if (this.currentPage !== 'detail') { uni.showModal({ title: '归还成功', content: '风扇已归还成功,剩余押金将退还到您的账户', confirmText: '查看详情', cancelText: '我知道了', success: (res) => { if (res.confirm) { // 跳转到订单详情页面查看详情 uni.navigateTo({ url: `/pages/order/detail?orderId=${orderId}` }) } } }) } else { console.log('当前在订单详情页,不显示弹窗,页面会自动刷新') } }, 500) } // 无论是否提醒,完成的订单都不再需要监控 this.removeOrder({orderId}) } } else if (result.code === 401 || result.code === 40101) { // 认证失败,停止监控并清理缓存 console.log('认证失败,停止订单监控') try { uni.removeStorageSync('activeOrderId') } catch (e) {} this.stop() this.activeOrders.clear() } } catch (error) { console.error(`检查订单 ${orderId} 状态出错:`, error) // 如果是网络错误或认证错误,清理并停止监控 if (error && (error.statusCode === 401 || error.code === 401)) { console.log('检查订单时认证失败,停止监控') try { uni.removeStorageSync('activeOrderId') } catch (e) {} this.stop() this.activeOrders.clear() } } } } // 导出单例实例 export const orderMonitor = new OrderMonitor() // 监听页面切换事件(仅微信小程序支持) // #ifdef MP-WEIXIN if (typeof uni.onAppRoute === 'function') { uni.onAppRoute((route) => { const pagePath = route.path || '' const pageSegments = pagePath.split('/') const pageName = pageSegments[pageSegments.length - 1] // 设置当前活跃页面 orderMonitor.setActivePage(pageName || null) console.log('页面切换:', pagePath, '当前活跃页面:', pageName) }) } // #endif // #ifdef MP-ALIPAY // 支付宝小程序不支持 onAppRoute,通过页面生命周期手动设置 // 各个页面需要在 onShow 中调用 orderMonitor.setActivePage() // #endif // 页面加载时自动恢复监控上次的活跃订单(如果有) const initOrderMonitor = () => { // 检查用户是否已登录 const token = uni.getStorageSync('token') if (!token) { console.log('用户未登录,跳过订单监控初始化') // 清理可能存在的旧订单ID缓存 try { uni.removeStorageSync('activeOrderId') } catch (e) {} return } const lastActiveOrderId = uni.getStorageSync('activeOrderId') if (lastActiveOrderId) { const lastOrderData = { orderId: lastActiveOrderId } orderMonitor.addOrder(lastOrderData, 'detail') console.log('恢复监控上次活跃订单:', lastActiveOrderId) } } // 初始化 initOrderMonitor()