Files
qingcheng-xiaochengxu/pages/course/orderDetail/orderDetail.js
2025-08-16 22:14:42 +08:00

240 lines
6.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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" });
},
});