diff --git a/frontend/src/components/AdminDashboard.jsx b/frontend/src/components/AdminDashboard.jsx index 9cebfd7..9c370e1 100644 --- a/frontend/src/components/AdminDashboard.jsx +++ b/frontend/src/components/AdminDashboard.jsx @@ -2,6 +2,143 @@ import React, { useEffect, useState } from 'react' import { api } from '../services/api' import './AdminDashboard.css' +const UserAccountGroup = ({ user, onServiceAction }) => { + const [expanded, setExpanded] = useState(true) + const [processing, setProcessing] = useState(false) + + const handleUserAction = async (action) => { + if (!window.confirm(`确定要${action === 'start' ? '启动' : '停止'}用户 ${user.username} 下所有账号的交易服务吗?`)) return + + setProcessing(true) + try { + // 并行执行 + const promises = user.accounts.map(acc => + api.post(`/accounts/${acc.id}/service/${action}`) + .catch(e => console.error(`Failed to ${action} account ${acc.id}:`, e)) + ) + await Promise.all(promises) + // 触发刷新(通过父组件回调或简单的延迟刷新,这里父组件会定时刷新,或者我们可以在父组件传递 refresh) + // 这里简单点,父组件会定时刷新,或者我们可以手动触发父组件刷新 + // 由于 onServiceAction 只是单个操作,我们这里最好能通知父组件刷新。 + // 暂时依赖父组件的定时刷新或手动刷新。 + if (onServiceAction) onServiceAction(null, 'refresh') // Hacky way to trigger refresh if supported + } catch (e) { + alert(`操作失败: ${e.message}`) + } finally { + setProcessing(false) + } + } + + // 计算该用户下所有账号的汇总状态 + const allRunning = user.accounts.every(a => a.serviceStatus?.running) + const allStopped = user.accounts.every(a => !a.serviceStatus?.running) + + return ( +
| ID | +名称 | +账户状态 | +服务状态 | +总资产 | +总盈亏 | +持仓数 | +操作 | +
|---|---|---|---|---|---|---|---|
| {acc.id} | +{acc.name} | ++ + {acc.status === 'active' ? '启用' : '禁用'} + + | ++ {acc.serviceStatus ? ( + + {acc.serviceStatus.state} + + ) : ( + UNKNOWN + )} + | +{Number(acc.total_balance).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | += 0 ? 'profit' : 'loss'}> + {Number(acc.total_pnl) > 0 ? '+' : ''}{Number(acc.total_pnl).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} + | +{acc.open_positions} | +
+
+
+
+
+ |
+
| ID | -名称 | -账户状态 | -服务状态 | -总资产 | -总盈亏 | -持仓数 | -操作 | -
|---|---|---|---|---|---|---|---|
| {acc.id} | -{acc.name} | -- - {acc.status === 'active' ? '启用' : '禁用'} - - | -- {acc.serviceStatus ? ( - - {acc.serviceStatus.state} - - ) : ( - UNKNOWN - )} - | -{Number(acc.total_balance).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | -= 0 ? 'profit' : 'loss'}> - {Number(acc.total_pnl) > 0 ? '+' : ''}{Number(acc.total_pnl).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} - | -{acc.open_positions} | -
-
-
-
-
- |
-