import { FC, useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { BillingService } from '../../services/billingService'; import { UserAccount, UserType, RechargeRecord } from '../../types/billing'; const MobileRecharge: FC = () => { const navigate = useNavigate(); const billingService = BillingService.getInstance(); const [userAccount, setUserAccount] = useState(null); const [selectedAmount, setSelectedAmount] = useState(0); const [customAmount, setCustomAmount] = useState(''); const [selectedPayment, setSelectedPayment] = useState<'wechat' | 'alipay' | 'card'>('wechat'); const [rechargeHistory, setRechargeHistory] = useState([]); const [isProcessing, setIsProcessing] = useState(false); // 预设充值金额(分) const presetAmounts = [ { value: 5000, label: '¥50', bonus: 0, popular: false }, { value: 10000, label: '¥100', bonus: 500, popular: true }, { value: 20000, label: '¥200', bonus: 1500, popular: false }, { value: 50000, label: '¥500', bonus: 5000, popular: false }, { value: 100000, label: '¥1000', bonus: 15000, popular: false }, ]; const paymentMethods = [ { id: 'wechat', name: '微信支付', icon: '💚', color: '#07c160' }, { id: 'alipay', name: '支付宝', icon: '💙', color: '#1677ff' }, { id: 'card', name: '银行卡', icon: '💳', color: '#722ed1' }, ]; useEffect(() => { const account = billingService.getUserAccount(); setUserAccount(account); // 模拟充值历史 const mockHistory: RechargeRecord[] = [ { id: '1', userId: account?.id || '1', amount: 10000, bonus: 500, paymentMethod: 'wechat', status: 'completed', createdAt: new Date(Date.now() - 86400000), // 1天前 }, { id: '2', userId: account?.id || '1', amount: 5000, bonus: 0, paymentMethod: 'alipay', status: 'completed', createdAt: new Date(Date.now() - 7 * 86400000), // 7天前 }, ]; setRechargeHistory(mockHistory); }, []); const formatCurrency = (cents: number) => { return (cents / 100).toFixed(2); }; const handleAmountSelect = (amount: number) => { setSelectedAmount(amount); setCustomAmount(''); }; const handleCustomAmountChange = (value: string) => { const numValue = parseFloat(value); if (!isNaN(numValue) && numValue > 0) { setSelectedAmount(Math.round(numValue * 100)); setCustomAmount(value); } else { setSelectedAmount(0); setCustomAmount(value); } }; const getBonus = (amount: number) => { const preset = presetAmounts.find(p => p.value === amount); return preset?.bonus || 0; }; const getTotalAmount = () => { return selectedAmount + getBonus(selectedAmount); }; const handleRecharge = async () => { if (selectedAmount < 100) { // 最低1元 alert('充值金额不能少于1元'); return; } if (!userAccount) { alert('用户账户信息未加载'); return; } setIsProcessing(true); try { // 模拟支付处理 await new Promise(resolve => setTimeout(resolve, 2000)); // 执行充值 const success = billingService.rechargeAccount(selectedAmount); if (success) { // 更新用户账户 setUserAccount(billingService.getUserAccount()); // 添加充值记录 const newRecord: RechargeRecord = { id: Date.now().toString(), userId: userAccount.id, amount: selectedAmount, bonus: getBonus(selectedAmount), paymentMethod: selectedPayment, status: 'completed', createdAt: new Date(), }; setRechargeHistory(prev => [newRecord, ...prev]); alert(`充值成功!到账金额:¥${formatCurrency(getTotalAmount())}`); setSelectedAmount(0); setCustomAmount(''); } else { alert('充值失败,请重试'); } } catch (error) { alert('充值失败,请重试'); } finally { setIsProcessing(false); } }; const getStatusColor = (status: string) => { switch (status) { case 'completed': return '#52c41a'; case 'pending': return '#fa8c16'; case 'failed': return '#ff4d4f'; default: return '#d9d9d9'; } }; const getStatusText = (status: string) => { switch (status) { case 'completed': return '成功'; case 'pending': return '处理中'; case 'failed': return '失败'; default: return '未知'; } }; const styles = { container: { padding: '16px', backgroundColor: '#f5f5f5', minHeight: '100vh', }, header: { display: 'flex', alignItems: 'center', marginBottom: '20px', }, backButton: { background: 'none', border: 'none', fontSize: '24px', cursor: 'pointer', marginRight: '12px', }, title: { fontSize: '20px', fontWeight: '600' as const, color: '#333', }, balanceCard: { backgroundColor: 'white', borderRadius: '16px', padding: '20px', marginBottom: '20px', textAlign: 'center' as const, boxShadow: '0 2px 12px rgba(0, 0, 0, 0.1)', }, balanceLabel: { fontSize: '14px', color: '#666', marginBottom: '8px', }, balanceAmount: { fontSize: '32px', fontWeight: '700' as const, color: '#1890ff', marginBottom: '8px', }, userType: { fontSize: '12px', color: '#999', backgroundColor: '#f0f8ff', padding: '4px 12px', borderRadius: '12px', display: 'inline-block', }, section: { backgroundColor: 'white', borderRadius: '16px', padding: '20px', marginBottom: '20px', boxShadow: '0 2px 12px rgba(0, 0, 0, 0.1)', }, sectionTitle: { fontSize: '18px', fontWeight: '600' as const, color: '#333', marginBottom: '16px', }, amountGrid: { display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '12px', marginBottom: '16px', }, amountCard: (selected: boolean, popular: boolean) => ({ padding: '16px', borderRadius: '12px', border: selected ? '2px solid #1890ff' : '2px solid transparent', backgroundColor: selected ? '#e6f7ff' : '#fafafa', cursor: 'pointer', textAlign: 'center' as const, position: 'relative' as const, ...(popular && { borderColor: '#fa8c16', backgroundColor: '#fff7e6', }), }), popularBadge: { position: 'absolute' as const, top: '-8px', right: '-8px', backgroundColor: '#fa8c16', color: 'white', fontSize: '10px', padding: '2px 6px', borderRadius: '8px', fontWeight: '500' as const, }, amountValue: { fontSize: '18px', fontWeight: '600' as const, color: '#333', marginBottom: '4px', }, bonusText: { fontSize: '12px', color: '#52c41a', fontWeight: '500' as const, }, customAmountInput: { width: '100%', padding: '12px', borderRadius: '8px', border: '1px solid #d9d9d9', fontSize: '16px', marginBottom: '16px', }, paymentMethods: { display: 'flex', gap: '12px', marginBottom: '20px', }, paymentMethod: (selected: boolean, color: string) => ({ flex: 1, padding: '16px', borderRadius: '12px', border: selected ? `2px solid ${color}` : '2px solid #f0f0f0', backgroundColor: selected ? `${color}10` : 'white', cursor: 'pointer', textAlign: 'center' as const, }), paymentIcon: { fontSize: '24px', marginBottom: '8px', }, paymentName: { fontSize: '14px', fontWeight: '500' as const, color: '#333', }, summaryCard: { backgroundColor: '#f8f9fa', borderRadius: '12px', padding: '16px', marginBottom: '20px', }, summaryRow: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '8px', }, summaryLabel: { fontSize: '14px', color: '#666', }, summaryValue: { fontSize: '14px', fontWeight: '500' as const, color: '#333', }, totalRow: { borderTop: '1px solid #e8e8e8', paddingTop: '8px', marginTop: '8px', }, totalValue: { fontSize: '18px', fontWeight: '600' as const, color: '#1890ff', }, rechargeButton: { width: '100%', padding: '16px', borderRadius: '12px', border: 'none', backgroundColor: selectedAmount > 0 && !isProcessing ? '#1890ff' : '#d9d9d9', color: 'white', fontSize: '16px', fontWeight: '600' as const, cursor: selectedAmount > 0 && !isProcessing ? 'pointer' : 'not-allowed', marginBottom: '20px', }, historyItem: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '16px 0', borderBottom: '1px solid #f0f0f0', }, historyLeft: { flex: 1, }, historyAmount: { fontSize: '16px', fontWeight: '600' as const, color: '#333', marginBottom: '4px', }, historyDate: { fontSize: '12px', color: '#999', }, historyStatus: (status: string) => ({ fontSize: '12px', fontWeight: '500' as const, color: getStatusColor(status), backgroundColor: `${getStatusColor(status)}15`, padding: '2px 8px', borderRadius: '8px', }), }; return (
{/* 头部 */}
账户充值
{/* 余额显示 */}
当前余额
¥{userAccount ? formatCurrency(userAccount.balance) : '0.00'}
{userAccount?.userType === UserType.ENTERPRISE ? '企业用户' : '个人用户'}
{/* 充值金额选择 */}
选择充值金额
{presetAmounts.map((amount) => (
handleAmountSelect(amount.value)} > {amount.popular &&
推荐
}
{amount.label}
{amount.bonus > 0 && (
送¥{formatCurrency(amount.bonus)}
)}
))}
handleCustomAmountChange(e.target.value)} />
{/* 支付方式 */}
选择支付方式
{paymentMethods.map((method) => (
setSelectedPayment(method.id as any)} >
{method.icon}
{method.name}
))}
{/* 费用明细 */} {selectedAmount > 0 && (
充值金额 ¥{formatCurrency(selectedAmount)}
{getBonus(selectedAmount) > 0 && (
赠送金额 +¥{formatCurrency(getBonus(selectedAmount))}
)}
到账金额 ¥{formatCurrency(getTotalAmount())}
)} {/* 充值按钮 */} {/* 充值历史 */}
充值记录
{rechargeHistory.map((record) => (
+¥{formatCurrency(record.amount + record.bonus)}
{record.createdAt.toLocaleDateString()} {record.createdAt.toLocaleTimeString()}
{getStatusText(record.status)}
))}
); }; export default MobileRecharge;