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 : {}; 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 }; }); // 默认全选 this.setData({ items, selectAll: items.length > 0, loading: false }); 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(() => { wx.navigateBack(); }, 1500); }) .catch((err) => { // wx.hideLoading(); wx.showToast({ title: (err && err.message) || '提交失败,请稍后重试', icon: 'none' }); }); } });