226 lines
6.9 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.

const { API } = require('../../../utils/constants');
const { request } = require('../../../utils/http');
function toNumber(v, fallback = 0) {
const n = Number(v);
return Number.isFinite(n) ? n : fallback;
}
function formatMoney(v) {
const n = toNumber(v, 0);
return (Math.round(n * 100) / 100).toFixed(2).replace(/\.00$/, '');
}
function genderText(v) {
if (v == null) return '';
const s = String(v).toLowerCase();
if (s === 'male' || s === 'm' || s === '1') return '男';
if (s === 'female' || s === 'f' || s === '2') return '女';
return '';
}
Page({
data: {
registrationId: null,
loading: true,
refundRulesText: '退款规则以赛事说明为准',
// items: [{ itemKey, projectName, pills: [{ pillKey, label, price, selected }] }]
items: [],
selectAll: false,
selectedCount: 0,
refundAmount: '0'
},
onLoad(options) {
const registrationId = Number(options.registrationId);
this.setData({ registrationId });
if (!registrationId) {
this.setData({ loading: false });
wx.showToast({ title: '参数错误', icon: 'none' });
return;
}
this.fetchRegistrationDetail(registrationId);
},
fetchRegistrationDetail(registrationId) {
this.setData({ loading: true });
request({
path: API.myRegistrationDetail(registrationId),
method: 'GET',
needAuth: true
})
.then((detail) => {
const d = detail && typeof detail === 'object' ? detail : {};
// 检查报名状态,如果已取消(PaymentStatus=3),则提示用户
const paymentStatus = d.paymentStatus != null ? Number(d.paymentStatus) : null;
if (paymentStatus === 3) {
wx.showModal({
title: '提示',
content: '该报名已取消,无法继续操作',
showCancel: false,
confirmText: '确定',
success: () => {
wx.navigateBack();
}
});
this.setData({ loading: false });
return;
}
const rawItems = Array.isArray(d.items) ? d.items : [];
const items = rawItems.map((it, idx) => {
const projectName = it.projectName || it.ProjectName || `项目${idx + 1}`;
const groupName = it.groupName || it.GroupName || '';
const price = it.price != null ? toNumber(it.price, 0) : 0;
const persons = Array.isArray(it.persons) ? it.persons : [];
const pills =
persons.length > 0
? persons.map((p, pi) => {
const gender = genderText(p.gender);
const label = [groupName, gender].filter(Boolean).join(' | ') || groupName || '参赛人';
return {
pillKey: `i-${idx}-p-${pi}`,
label,
price,
selected: true
};
})
: [
{
pillKey: `i-${idx}-g`,
label: groupName || '组别',
price,
selected: true
}
];
return {
itemKey: `it-${idx}`,
projectName,
pills
};
});
// 使用后端返回的退款金额和规则
const refundRulesText = d.refundRulesText || d.RefundRulesText || '退款规则以赛事说明为准';
const refundAmountFromBackend = d.refundAmount != null ? toNumber(d.refundAmount) : (d.RefundAmount != null ? toNumber(d.RefundAmount) : null);
// 默认全选
this.setData({
items,
selectAll: items.length > 0,
refundRulesText,
loading: false
});
// 优先使用后端计算的退款金额,否则使用前端计算
if (refundAmountFromBackend != null) {
const all = [];
this.data.items.forEach((it) => it.pills.forEach((p) => all.push(p)));
const selected = all.filter((p) => p.selected);
const selectAll = all.length > 0 && selected.length === all.length;
this.setData({
selectedCount: selected.length,
selectAll,
refundAmount: formatMoney(refundAmountFromBackend)
});
} else {
this.recalc();
}
})
.catch((err) => {
this.setData({ loading: false, items: [] });
wx.showToast({ title: (err && err.message) || '加载失败', icon: 'none' });
});
},
onTogglePill(e) {
const pillKey = e.currentTarget.dataset.pillkey;
if (!pillKey) return;
const items = this.data.items.map((it) => ({
...it,
pills: it.pills.map((p) => (p.pillKey === pillKey ? { ...p, selected: !p.selected } : p))
}));
this.setData({ items });
this.recalc();
},
onToggleAll() {
const next = !this.data.selectAll;
const items = this.data.items.map((it) => ({
...it,
pills: it.pills.map((p) => ({ ...p, selected: next }))
}));
this.setData({ items, selectAll: next });
this.recalc();
},
recalc() {
const all = [];
this.data.items.forEach((it) => it.pills.forEach((p) => all.push(p)));
const selected = all.filter((p) => p.selected);
const sum = selected.reduce((acc, p) => acc + toNumber(p.price, 0), 0);
const selectAll = all.length > 0 && selected.length === all.length;
this.setData({
selectedCount: selected.length,
selectAll,
refundAmount: formatMoney(sum)
});
},
onConfirmCancel() {
if (this.data.selectedCount === 0) return;
wx.showModal({
title: '确认取消报名?',
content: `本次预计退款金额 ¥${this.data.refundAmount}`,
cancelText: '取消',
confirmText: '确定',
success: (res) => {
if (!res || !res.confirm) return;
this.submitCancelRegistration();
}
});
},
submitCancelRegistration() {
wx.showLoading({ title: '提交中...' });
request({
path: API.cancelRegistrationRefund,
method: 'POST',
needAuth: true,
data: {
registrationId: this.data.registrationId,
refundReason: '用户取消报名'
}
})
.then(() => {
wx.hideLoading();
wx.showToast({ title: '退款申请已提交', icon: 'success' });
setTimeout(() => {
// 返回上一页并刷新数据
const pages = getCurrentPages();
if (pages.length > 1) {
const prevPage = pages[pages.length - 2];
// 如果上一页是 records 页面,通知它刷新
if (prevPage && prevPage.route && prevPage.route.includes('records')) {
if (prevPage.initData) {
prevPage.initData(true);
}
}
}
wx.navigateBack();
}, 1500);
})
.catch((err) => {
wx.hideLoading();
wx.showToast({ title: (err && err.message) || '提交失败,请稍后重试', icon: 'none' });
});
}
});