Files
2026-01-22 10:52:58 +08:00

314 lines
10 KiB
JavaScript

import { queryById } from '@/config/api/order.js'
/**
* 订单监控服务
* 用于在后台监控订单状态变化,特别是归还完成状态
*/
class OrderMonitor {
constructor() {
this.activeOrders = new Map() // 存储活跃订单 Map<orderId, {orderData, pageName}>
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;
}
}
// 无论是否需要弹窗提醒,都要触发全局订单完成事件(用于订单列表、详情等页面刷新)
uni.$emit('orderCompleted', orderData)
if (shouldNotify) {
// 显示全局通知
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 || APP-PLUS
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 H5
// H5环境下通过路由监听实现页面切换检测
if (typeof window !== 'undefined') {
const updateActivePageForH5 = () => {
const pagePath = window.location.pathname || window.location.hash
const pageSegments = pagePath.split('/')
const pageName = pageSegments[pageSegments.length - 1].replace(/[?#].*$/, '')
if (pageName) {
orderMonitor.setActivePage(pageName)
console.log('页面切换(H5):', pagePath, '当前活跃页面:', pageName)
}
}
// 监听 popstate 事件(浏览器前进后退)
window.addEventListener('popstate', updateActivePageForH5)
// 监听 hashchange 事件(hash 模式路由)
window.addEventListener('hashchange', updateActivePageForH5)
// 初始化时执行一次
updateActivePageForH5()
}
// #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()