226 lines
6.9 KiB
JavaScript
226 lines
6.9 KiB
JavaScript
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' });
|
||
});
|
||
}
|
||
});
|
||
|