import { baseUrl, globalImgUrl } from "../../../request"; Page({ data: { countdown: "", orderId: 0, orderObj: {}, // 订单详情对象 _secondsRemaining: 0, // 内部倒计时秒数 _hasShownTimeout: false, // 是否已弹过“超时未支付”弹窗(本次页面停留期内) globalImgUrl, isMaskVisible: false, _isActive: false // 页面是否处于可见状态 }, // —— 非 data 状态,避免无谓 setData _timer: null, onLoad(options) { this.setData({ orderId: options.id || 0 }); this.getOrderDetail(); }, onShow() { this.setData({ _isActive: true }); }, onHide() { this.setData({ _isActive: false }); this._clearTimer(); }, onUnload() { this.setData({ _isActive: false }); this._clearTimer(); }, onPullDownRefresh() { this.getOrderDetail(); // stopPullDownRefresh 放到 complete 里,更稳 }, // ====== 工具函数 ====== _clearTimer() { if (this._timer) { clearInterval(this._timer); this._timer = null; } }, _pad2(n) { return String(n).padStart(2, "0"); }, _format(sec) { const m = Math.floor(sec / 60); const s = sec % 60; return `${this._pad2(m)}分${this._pad2(s)}秒`; }, // ====== 拉取订单详情并初始化倒计时 ====== getOrderDetail() { wx.request({ url: baseUrl + "/courseOrder/query/detail", method: "POST", data: { id: this.data.orderId }, header: { Authorization: wx.getStorageSync("token") }, success: (res) => { if (res.data.code !== 1) { wx.showToast({ title: res.data.message || "获取失败", icon: "none" }); return; } const order = res.data.data || {}; this.setData({ orderObj: order }); // 只有“待支付”才需要倒计时;其它状态关掉计时器并清空文案 if (order.orderStatus === "待支付") { this._initFromCreateTime(order.createTime); } else { this._clearTimer(); this.setData({ countdown: "" }); } }, fail: () => wx.showToast({ title: "网络错误", icon: "none" }), complete: () => wx.stopPullDownRefresh(), }); }, // 计算剩余秒数并启动定时器 _initFromCreateTime(createTime) { const ts = new Date(String(createTime).replace(/-/g, "/")).getTime(); const createMs = Number.isFinite(ts) ? ts : Date.now(); const ttlMs = 15 * 60 * 1000; // 15分钟有效 const now = Date.now(); let diff = Math.floor((createMs + ttlMs - now) / 1000); diff = Math.max(0, diff); // 初始化阶段:如果已过期,静默转“交易关闭”(不弹窗,避免干扰) if (diff === 0) { const o = { ...this.data.orderObj, orderStatus: "交易关闭" }; this._clearTimer(); this.setData({ orderObj: o, countdown: "" }); return; } // 未过期:初始化倒计时并启动 this._clearTimer(); this.setData({ _secondsRemaining: diff, countdown: this._format(diff), _hasShownTimeout: false, // 重置本页弹窗标记 }); this._startTimer(); }, // 每秒递减 _startTimer() { this._clearTimer(); this._timer = setInterval(() => { const sec = this.data._secondsRemaining - 1; if (sec <= 0) { this._clearTimer(); this._handleTimeout(); // 到点且在当前页,才弹窗 return; } this.setData({ _secondsRemaining: sec, countdown: this._format(sec), }); }, 1000); }, // 超时处理:仅在当前页可见时弹一次,并把状态改为“交易关闭” _handleTimeout() { const { _isActive, _hasShownTimeout } = this.data; // 更新状态并隐藏倒计时 const o = { ...this.data.orderObj, orderStatus: "交易关闭" }; this.setData({ orderObj: o, countdown: "" }); // 只在当前页面 & 未弹过 时弹一次 if (_isActive && !_hasShownTimeout) { wx.showModal({ title: "提示", content: "订单超时未支付,已关闭", showCancel: false, complete: () => { // 标记已弹 this.setData({ _hasShownTimeout: true }); }, }); } else { this.setData({ _hasShownTimeout: true }); } }, // ====== 支付相关 ====== showIsPayModal() { const { orderId } = this.data; 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 }, // 若后端用 orderId,则把键名改为 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" }); }, }); }, // ====== 取消、退款(示例) ====== cancelOrder() { wx.showModal({ title: "取消订单", content: "是否要取消订单?", success: (res) => { if (res.confirm) { wx.request({ url: baseUrl + "/courseOrder/cancel", method: "POST", header: { Authorization: wx.getStorageSync("token") }, data: { id: this.data.orderId }, // 后端如果需要 { orderId },改键名 success: (r) => { if (!r.data || r.data.code !== 1) { wx.showToast({ title: (r.data && r.data.message) || "取消失败", icon: "none" }); } this.getOrderDetail(); }, fail: () => wx.showToast({ title: "网络错误", icon: "none" }), }); } }, }); }, goPay() { wx.showToast({ title: "支付功能稍后开放", icon: "none" }); }, refundOrder() { wx.showToast({ title: "退款功能稍后开放", icon: "none" }); }, });