/* Copyright (C) 2025 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import React, { useState, useEffect, useMemo } from 'react'; import { Modal, Table, Badge, Typography, Toast, Empty, Button, Input, } from '@douyinfe/semi-ui'; import { IllustrationNoResult, IllustrationNoResultDark, } from '@douyinfe/semi-illustrations'; import { Coins } from 'lucide-react'; import { IconSearch } from '@douyinfe/semi-icons'; import { API, timestamp2string } from '../../../helpers'; import { isAdmin } from '../../../helpers/utils'; import { useIsMobile } from '../../../hooks/common/useIsMobile'; const { Text } = Typography; // 状态映射配置 const STATUS_CONFIG = { success: { type: 'success', key: '成功' }, pending: { type: 'warning', key: '待支付' }, expired: { type: 'danger', key: '已过期' }, }; // 支付方式映射 const PAYMENT_METHOD_MAP = { stripe: 'Stripe', alipay: '支付宝', wxpay: '微信', }; const TopupHistoryModal = ({ visible, onCancel, t }) => { const [loading, setLoading] = useState(false); const [topups, setTopups] = useState([]); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(10); const [keyword, setKeyword] = useState(''); const isMobile = useIsMobile(); const loadTopups = async (currentPage, currentPageSize) => { setLoading(true); try { const base = isAdmin() ? '/api/user/topup' : '/api/user/topup/self'; const qs = `p=${currentPage}&page_size=${currentPageSize}` + (keyword ? `&keyword=${encodeURIComponent(keyword)}` : ''); const endpoint = `${base}?${qs}`; const res = await API.get(endpoint); const { success, message, data } = res.data; if (success) { setTopups(data.items || []); setTotal(data.total || 0); } else { Toast.error({ content: message || t('加载失败') }); } } catch (error) { console.error('Load topups error:', error); Toast.error({ content: t('加载账单失败') }); } finally { setLoading(false); } }; useEffect(() => { if (visible) { loadTopups(page, pageSize); } }, [visible, page, pageSize, keyword]); const handlePageChange = (currentPage) => { setPage(currentPage); }; const handlePageSizeChange = (currentPageSize) => { setPageSize(currentPageSize); setPage(1); }; const handleKeywordChange = (value) => { setKeyword(value); setPage(1); }; // 管理员补单 const handleAdminComplete = async (tradeNo) => { try { const res = await API.post('/api/user/topup/complete', { trade_no: tradeNo, }); const { success, message } = res.data; if (success) { Toast.success({ content: t('补单成功') }); await loadTopups(page, pageSize); } else { Toast.error({ content: message || t('补单失败') }); } } catch (e) { Toast.error({ content: t('补单失败') }); } }; const confirmAdminComplete = (tradeNo) => { Modal.confirm({ title: t('确认补单'), content: t('是否将该订单标记为成功并为用户入账?'), onOk: () => handleAdminComplete(tradeNo), }); }; // 渲染状态徽章 const renderStatusBadge = (status) => { const config = STATUS_CONFIG[status] || { type: 'primary', key: status }; return ( {t(config.key)} ); }; // 渲染支付方式 const renderPaymentMethod = (pm) => { const displayName = PAYMENT_METHOD_MAP[pm]; return {displayName ? t(displayName) : pm || '-'}; }; // 检查是否为管理员 const userIsAdmin = useMemo(() => isAdmin(), []); const columns = useMemo(() => { const baseColumns = [ { title: t('订单号'), dataIndex: 'trade_no', key: 'trade_no', render: (text) => {text}, }, { title: t('支付方式'), dataIndex: 'payment_method', key: 'payment_method', render: renderPaymentMethod, }, { title: t('充值额度'), dataIndex: 'amount', key: 'amount', render: (amount) => ( {amount} ), }, { title: t('支付金额'), dataIndex: 'money', key: 'money', render: (money) => ¥{money.toFixed(2)}, }, { title: t('状态'), dataIndex: 'status', key: 'status', render: renderStatusBadge, }, ]; // 管理员才显示操作列 if (userIsAdmin) { baseColumns.push({ title: t('操作'), key: 'action', render: (_, record) => { if (record.status !== 'pending') return null; return ( confirmAdminComplete(record.trade_no)} > {t('补单')} ); }, }); } baseColumns.push({ title: t('创建时间'), dataIndex: 'create_time', key: 'create_time', render: (time) => timestamp2string(time), }); return baseColumns; }, [t, userIsAdmin]); return ( } placeholder={t('订单号')} value={keyword} onChange={handleKeywordChange} showClear /> } darkModeImage={ } description={t('暂无充值记录')} style={{ padding: 30 }} /> } /> ); }; export default TopupHistoryModal;