import React, { useState, useEffect } from 'react' import { View, Text, ScrollView } from '@tarojs/components' import Taro, { useDidShow } from '@tarojs/taro' import { getMyRegistrations, payEventRegistration, getPayStatusLabel } from '@/api/shop/shopEvent' import type { EventRegistration, EventFormField } from '@/api/shop/shopEvent' definePageConfig({ navigationBarTitleText: '我的报名' }) const MyRegistrationsPage: React.FC = () => { const [list, setList] = useState([]) const [loading, setLoading] = useState(true) const [paying, setPaying] = useState(null) useDidShow(() => { fetchList() }) const fetchList = async () => { try { const data = await getMyRegistrations() setList(data || []) } catch (err: any) { Taro.showToast({ title: err.message || '加载失败', icon: 'none' }) } finally { setLoading(false) } } const handleRepay = async (reg: EventRegistration) => { setPaying(reg.id) try { const wxParams = await payEventRegistration(reg.id) // 后端返回已支付(回调丢失自动修复场景) if ((wxParams as any).paid === 'true') { Taro.showToast({ title: '支付成功', icon: 'success' }) setList(prev => prev.map(r => r.id === reg.id ? { ...r, payStatus: 1, paidAt: new Date().toISOString() } : r)) fetchList() return } await Taro.requestPayment({ timeStamp: wxParams.timeStamp, nonceStr: wxParams.nonceStr, package: wxParams.package, signType: wxParams.signType as any, paySign: wxParams.paySign, }) // 支付成功后立即更新本地状态,避免后端回调延迟导致仍显示"待缴费" setList(prev => prev.map(r => r.id === reg.id ? { ...r, payStatus: 1, paidAt: new Date().toISOString() } : r)) Taro.showToast({ title: '支付成功', icon: 'success' }) fetchList() } catch (err: any) { if (!err?.errMsg?.includes('cancel')) { Taro.showToast({ title: err.message || '支付失败', icon: 'none' }) } } finally { setPaying(null) } } const formatDate = (dateStr: string) => { const d = new Date(dateStr) return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}` } const fieldLabelMap: Record = { name: '姓名', phone: '手机号', idCard: '身份证号', size: '服装尺码', email: '邮箱', gender: '性别', age: '年龄', address: '地址', company: '单位/公司', job: '职业', remark: '备注', emergencyContact: '紧急联系人', emergencyPhone: '紧急联系人电话', wechat: '微信号', team: '团队/队伍', } if (loading) { return ( 加载中... ) } return ( {list.length === 0 ? ( 🏆 暂无报名记录 Taro.navigateTo({ url: '/pages/event/list/index' })} > 去报名赛事 ) : ( list.map(reg => { // 后端支付回调可能延迟,paidAt 有值即视为已缴费 const effectivePayStatus = reg.paidAt ? 1 : reg.payStatus const payInfo = getPayStatusLabel(effectivePayStatus) return ( {reg.eventName || '赛事'} {payInfo.label} {/* 动态表单数据展示 */} {(() => { let formData: Record = {} if (reg.formData) { if (typeof reg.formData === 'string') { try { formData = JSON.parse(reg.formData) } catch { formData = {} } } else { formData = reg.formData as Record } } // 去重:过滤掉与英文 key 重复的中文 label key const labelToKey: Record = {} Object.entries(fieldLabelMap).forEach(([k, v]) => { labelToKey[v] = k }) return Object.entries(formData).filter(([key]) => { if (fieldLabelMap[key]) return true // 英文 key 保留 if (labelToKey[key]) return false // 中文 label key 跳过(会由英文 key 渲染) return true // 自定义字段保留 }).map(([key, value]) => ( {fieldLabelMap[key] || key}:{value} )) })()} 报名费:{reg.entryFee > 0 ? `¥${reg.entryFee}` : '免费'} 报名时间:{formatDate(reg.createTime)} {reg.paidAt && 缴费时间:{formatDate(reg.paidAt)}} {effectivePayStatus === 0 && ( handleRepay(reg)} > {paying === reg.id ? '支付中...' : `重新支付 ¥${reg.entryFee}`} )} ) }) )} ) } export default MyRegistrationsPage