import { baseUrl } from "../../../request"; const { notLogin } = require('../../../utils/util') // pages/course/courseOrderList/courseOrderList.js Page({ data: { orderList: [], // 后端返回的订单列表 hasModalShown: false, // 本次停留页面只弹一次 isMaskVisible: false }, // —— 内部状态(不放 data,避免多余 setData) _timer: null, _isActive: false, // 页面是否处于“可见/激活”状态 _justEnteredAt: 0, // 进入页面时刻(可按需使用) onLoad() { this._isActive = true; this._justEnteredAt = Date.now(); this.fetchOrders(); }, onShow() { this._isActive = true; this.fetchOrders(); // 如不想重复拉取可注释 }, onHide() { this._isActive = false; this._clearTimer(); }, onUnload() { this._isActive = false; this._clearTimer(); }, onPullDownRefresh() { this.fetchOrders(); // stopPullDownRefresh 在 complete 里 }, // ========= 工具函数 ========= _clearTimer() { if (this._timer) { clearInterval(this._timer); this._timer = null; } }, _pad2(n) { return String(n).padStart(2, '0'); }, _fmtCountDownStr(totalSec) { const sec = Math.max(0, totalSec | 0); const m = Math.floor(sec / 60); const s = sec % 60; return `${this._pad2(m)}分${this._pad2(s)}秒`; }, // ========= 拉单 ========= fetchOrders() { wx.request({ url: baseUrl + '/courseOrder/query/list', method: 'POST', header: { Authorization: wx.getStorageSync('token') }, success: res => { if (res.data.code === 1) { const now = Date.now(); const list = (res.data.data || []).map(it => { // 解析时间(iOS 兼容 + NaN 兜底) const ts = new Date(String(it.createTime).replace(/-/g, '/')).getTime(); const createMs = Number.isFinite(ts) ? ts : now; // 统一按 15 分钟有效期(若后端返回 expireTime,建议直接用) const ttlMs = 15 * 60 * 1000; let diff = Math.floor((createMs + ttlMs - now) / 1000); diff = Math.max(0, diff); if (it.orderStatus === '待支付') { it.countDown = diff; it.countDownStr = this._fmtCountDownStr(diff); it._expiredNotified = false; // 每单的本地防重复标记 // 初始化阶段:如果已经超时(diff=0),静默转关闭,不弹窗 if (diff === 0) { it.orderStatus = '交易关闭'; it.countDownStr = ''; } } else { it.countDown = 0; it.countDownStr = ''; } return it; }); // 渲染 + 启动定时器 this.setData({ orderList: list }, () => this._startTimer()); } else { notLogin(res.data.message); } }, fail: () => { wx.showToast({ title: '网络错误', icon: 'none' }); }, complete: () => { wx.stopPullDownRefresh(); } }); }, // ========= 定时器刷新 ========= _startTimer() { this._clearTimer(); // 如果已经没有“待支付”的订单,就不启动定时器 const hasPending = this.data.orderList.some(o => o.orderStatus === '待支付' && o.countDown > 0); if (!hasPending) return; this._timer = setInterval(() => { // 不在激活页时不做任何 UI 相关动作(同时兜底不弹窗) if (!this._isActive) return; let needRerender = false; const updated = this.data.orderList.map(item => { if (item.orderStatus === '待支付' && item.countDown > 0) { const next = item.countDown - 1; item.countDown = next; item.countDownStr = this._fmtCountDownStr(next); needRerender = true; if (next <= 0) { item.orderStatus = '交易关闭'; item.countDownStr = ''; // —— 仅在“当前页面可见”时弹一次,并且每单只弹一次;本页全局也只弹一次 if (this._isActive && !item._expiredNotified && !this.data.hasModalShown) { item._expiredNotified = true; wx.showModal({ title: '提示', content: '订单超时未支付,已关闭', showCancel: false }); this.setData({ hasModalShown: true }); } } } return item; }); if (needRerender) { this.setData({ orderList: updated }, () => { // 如果已经没有可继续倒计时的订单,关掉定时器 const stillPending = this.data.orderList.some(o => o.orderStatus === '待支付' && o.countDown > 0); if (!stillPending) this._clearTimer(); }); } else { // 没有需要更新的也关掉 this._clearTimer(); } }, 1000); }, // ========= 支付相关 ========= showIsPayModal(e) { const orderId = e.currentTarget.dataset.orderId; wx.showModal({ title: '确认支付', content: '是否立即支付该订单?', cancelText: '取消', confirmText: '去支付', success: (res) => { if (res.confirm) { this.payOrder(orderId); } else if (res.cancel) { this.setData({ isMaskVisible: false }); } }, fail: () => { wx.hideLoading(); wx.showToast({ title: '网络错误', icon: 'none' }); } }); }, payOrder(orderId) { this.setData({ isMaskVisible: true }); wx.showLoading({ title: '支付中...' }); wx.request({ url: baseUrl + '/courseOrder/payment', method: 'POST', header: { Authorization: wx.getStorageSync('token') }, data: { id: orderId }, // 与后端约定:支付接口传 id;若传 orderId 则改键名 success: res => { wx.hideLoading(); if (res.data.code === 1) { wx.redirectTo({ url: `/pages/course/orderDetail/orderDetail?id=${orderId}`, complete: () => { this.setData({ isMaskVisible: false }); } }); } else { this.setData({ isMaskVisible: false }); wx.showToast({ title: res.data.message || '支付失败', icon: 'none' }); } }, fail: () => { wx.hideLoading(); this.setData({ isMaskVisible: false }); wx.showToast({ title: '网络错误,支付失败', icon: 'none' }); } }); }, // ========= 跳转 & 取消 ========= gotoOrderDetail(e) { const orderId = e.currentTarget.dataset.id; wx.navigateTo({ url: `/pages/course/orderDetail/orderDetail?id=${orderId}`, }); }, cancelOrder(e) { const id = e.currentTarget.dataset.id; wx.showModal({ title: '取消订单', content: '是否要取消该订单?', success: res => { if (res.confirm) { wx.request({ url: baseUrl + "/courseOrder/cancel", method: 'POST', header: { Authorization: wx.getStorageSync('token') }, data: { id }, // 如果后端需要 { orderId: id },改这里的键名即可 success: r => { if (r.data && r.data.code !== 1) { wx.showToast({ title: r.data.message || '取消失败', icon: 'none' }); } this.fetchOrders(); }, fail: () => wx.showToast({ title: '网络错误', icon: 'none' }) }); } } }); } });