From b947fe820594b1737342609ebf8407217fc5e026 Mon Sep 17 00:00:00 2001 From: hailin Date: Tue, 6 Jan 2026 10:30:35 -0800 Subject: [PATCH] feat(admin-web): add system account transfer management page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add system-transfer page with transfer form and order history - Add SystemWithdrawalService for API calls - Add useSystemWithdrawal hooks for React Query integration - Add system-withdrawal types definitions - Add navigation menu item for system transfer 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../app/(dashboard)/system-transfer/page.tsx | 690 ++++++++++++++++++ .../system-transfer.module.scss | 427 +++++++++++ .../src/components/layout/Sidebar/Sidebar.tsx | 1 + frontend/admin-web/src/hooks/index.ts | 1 + .../src/hooks/useSystemWithdrawal.ts | 71 ++ .../src/infrastructure/api/endpoints.ts | 12 + .../src/services/systemWithdrawalService.ts | 60 ++ .../src/types/system-withdrawal.types.ts | 84 +++ 8 files changed, 1346 insertions(+) create mode 100644 frontend/admin-web/src/app/(dashboard)/system-transfer/page.tsx create mode 100644 frontend/admin-web/src/app/(dashboard)/system-transfer/system-transfer.module.scss create mode 100644 frontend/admin-web/src/hooks/useSystemWithdrawal.ts create mode 100644 frontend/admin-web/src/services/systemWithdrawalService.ts create mode 100644 frontend/admin-web/src/types/system-withdrawal.types.ts diff --git a/frontend/admin-web/src/app/(dashboard)/system-transfer/page.tsx b/frontend/admin-web/src/app/(dashboard)/system-transfer/page.tsx new file mode 100644 index 00000000..31aebbba --- /dev/null +++ b/frontend/admin-web/src/app/(dashboard)/system-transfer/page.tsx @@ -0,0 +1,690 @@ +'use client'; + +import { useState, useCallback } from 'react'; +import { Modal, toast, Button } from '@/components/common'; +import { PageContainer } from '@/components/layout'; +import { cn } from '@/utils/helpers'; +import { formatDateTime } from '@/utils/formatters'; +import { + useSystemWithdrawalAccounts, + useSystemWithdrawalOrders, + useRequestSystemWithdrawal, +} from '@/hooks/useSystemWithdrawal'; +import { + SystemWithdrawalOrder, + SystemWithdrawalStatus, + SystemAccount, + getSystemWithdrawalStatusInfo, +} from '@/types/system-withdrawal.types'; +import styles from './system-transfer.module.scss'; + +type TabType = 'transfer' | 'orders'; + +/** + * 系统账户划转管理页面 + */ +export default function SystemTransferPage() { + // 当前标签页 + const [activeTab, setActiveTab] = useState('transfer'); + + // 筛选状态 + const [filters, setFilters] = useState({ + fromAccountSequence: '', + toAccountSequence: '', + status: '' as SystemWithdrawalStatus | '', + page: 1, + limit: 20, + }); + + // 表单状态 + const [selectedAccount, setSelectedAccount] = useState(null); + const [transferForm, setTransferForm] = useState({ + toAccountSequence: '', + amount: '', + memo: '', + }); + const [formErrors, setFormErrors] = useState>({}); + + // 弹窗状态 + const [viewingOrder, setViewingOrder] = useState(null); + const [confirmModalOpen, setConfirmModalOpen] = useState(false); + + // 数据查询 + const accountsQuery = useSystemWithdrawalAccounts(); + const ordersQuery = useSystemWithdrawalOrders({ + fromAccountSequence: filters.fromAccountSequence || undefined, + toAccountSequence: filters.toAccountSequence || undefined, + status: filters.status || undefined, + page: filters.page, + limit: filters.limit, + }); + + // Mutations + const requestMutation = useRequestSystemWithdrawal(); + + // 表单验证 + const validateForm = (): boolean => { + const errors: Record = {}; + + if (!selectedAccount) { + errors.fromAccount = '请选择源账户'; + } + + if (!transferForm.toAccountSequence) { + errors.toAccountSequence = '请输入目标账户序列号'; + } else if (!/^D\d{11}$/.test(transferForm.toAccountSequence)) { + errors.toAccountSequence = '账户序列号格式不正确,应为 D + 11位数字'; + } + + if (!transferForm.amount) { + errors.amount = '请输入划转金额'; + } else { + const amount = parseFloat(transferForm.amount); + if (isNaN(amount) || amount <= 0) { + errors.amount = '请输入有效的金额'; + } else if (amount < 1) { + errors.amount = '最小划转金额为 1 USDT'; + } + } + + setFormErrors(errors); + return Object.keys(errors).length === 0; + }; + + // 提交划转请求 + const handleSubmitTransfer = async () => { + if (!validateForm() || !selectedAccount) return; + + try { + await requestMutation.mutateAsync({ + fromAccountSequence: selectedAccount.accountSequence, + toAccountSequence: transferForm.toAccountSequence, + amount: transferForm.amount, + memo: transferForm.memo || undefined, + }); + toast.success('划转请求已提交,等待区块链确认'); + setConfirmModalOpen(false); + // 重置表单 + setSelectedAccount(null); + setTransferForm({ toAccountSequence: '', amount: '', memo: '' }); + setFormErrors({}); + // 切换到订单列表查看 + setActiveTab('orders'); + } catch (err) { + toast.error((err as Error).message || '划转失败'); + } + }; + + // 打开确认弹窗 + const handleOpenConfirm = () => { + if (validateForm()) { + setConfirmModalOpen(true); + } + }; + + // 搜索 + const handleSearch = useCallback(() => { + setFilters((prev) => ({ ...prev, page: 1 })); + }, []); + + // 翻页 + const handlePageChange = (page: number) => { + setFilters((prev) => ({ ...prev, page })); + }; + + // 渲染账户选择卡片 + const renderAccountCards = () => { + if (accountsQuery.isLoading) { + return
加载账户列表...
; + } + + if (accountsQuery.error) { + return ( +
+ {(accountsQuery.error as Error).message || '加载失败'} + +
+ ); + } + + const accounts = accountsQuery.data || []; + if (accounts.length === 0) { + return
暂无可划转账户
; + } + + return ( +
+ {accounts.map((account) => ( +
setSelectedAccount(account)} + > +
{account.name}
+
{account.accountSequence}
+ {account.balance && ( +
+ 余额: {parseFloat(account.balance).toFixed(2)} USDT +
+ )} +
+ ))} +
+ ); + }; + + // 渲染划转表单 + const renderTransferForm = () => { + return ( + <> +
+ 从系统账户划转资金到用户账户,资金将通过区块链转账,完成后会自动记录分类账。 +
+ +

1. 选择源账户

+ {renderAccountCards()} + {formErrors.fromAccount && ( +
{formErrors.fromAccount}
+ )} + +

2. 填写划转信息

+
+
+ + { + setTransferForm({ ...transferForm, toAccountSequence: e.target.value }); + setFormErrors({ ...formErrors, toAccountSequence: '' }); + }} + placeholder="例如:D25121400005" + /> +
输入用户的账户序列号(D开头+11位数字)
+ {formErrors.toAccountSequence && ( +
{formErrors.toAccountSequence}
+ )} +
+ +
+ + { + setTransferForm({ ...transferForm, amount: e.target.value }); + setFormErrors({ ...formErrors, amount: '' }); + }} + placeholder="例如:100" + min="1" + step="0.01" + /> +
最小划转金额为 1 USDT
+ {formErrors.amount && ( +
{formErrors.amount}
+ )} +
+ +
+ +