diff --git a/backend/api/routes/accounts.py b/backend/api/routes/accounts.py index 441ab9b..f3469f6 100644 --- a/backend/api/routes/accounts.py +++ b/backend/api/routes/accounts.py @@ -87,8 +87,8 @@ async def list_accounts(user: Dict[str, Any] = Depends(get_current_user)) -> Lis r = Account.get(int(aid)) if not r: continue - # 普通用户:不返回密钥相关字段 - _, _, use_testnet = Account.get_credentials(int(aid)) + # 普通用户:不返回密钥明文,但返回“是否已配置”的状态,方便前端提示 + api_key, api_secret, use_testnet = Account.get_credentials(int(aid)) out.append( { "id": int(aid), @@ -96,6 +96,8 @@ async def list_accounts(user: Dict[str, Any] = Depends(get_current_user)) -> Lis "status": r.get("status") or "active", "use_testnet": bool(use_testnet), "role": membership_map.get(int(aid), "viewer"), + "has_api_key": bool(api_key), + "has_api_secret": bool(api_secret), } ) return out diff --git a/frontend/src/components/ConfigPanel.jsx b/frontend/src/components/ConfigPanel.jsx index 02b1ec0..1a2b2cd 100644 --- a/frontend/src/components/ConfigPanel.jsx +++ b/frontend/src/components/ConfigPanel.jsx @@ -15,6 +15,7 @@ const ConfigPanel = ({ currentUser }) => { const [systemBusy, setSystemBusy] = useState(false) const [accountTradingStatus, setAccountTradingStatus] = useState(null) const [accountTradingErr, setAccountTradingErr] = useState('') + const [currentAccountMeta, setCurrentAccountMeta] = useState(null) // 多账号:当前账号(仅用于配置页提示;全局切换器在顶部导航) const [accountId, setAccountId] = useState(getCurrentAccountId()) @@ -220,6 +221,21 @@ const ConfigPanel = ({ currentUser }) => { } } + const loadCurrentAccountMeta = async () => { + try { + const list = await api.getAccounts() + const accounts = Array.isArray(list) ? list : [] + const meta = accounts.find((a) => parseInt(String(a?.id || '0'), 10) === parseInt(String(accountId || '0'), 10)) + setCurrentAccountMeta(meta || null) + // 同步 testnet 开关到表单(仅在未输入时同步,避免打断正在输入) + if (meta && !credForm.api_key && !credForm.api_secret) { + setCredForm((prev) => ({ ...prev, use_testnet: !!meta.use_testnet })) + } + } catch (e) { + setCurrentAccountMeta(null) + } + } + const handleAccountTradingEnsure = async () => { setSystemBusy(true) setMessage('') @@ -235,6 +251,12 @@ const ConfigPanel = ({ currentUser }) => { } const handleAccountTradingStart = async () => { + const hasKey = !!currentAccountMeta?.has_api_key + const hasSecret = !!currentAccountMeta?.has_api_secret + if (!hasKey || !hasSecret) { + setMessage('请先在“账号密钥(当前账号)”中配置 BINANCE_API_KEY 与 BINANCE_API_SECRET,然后再启动交易进程') + return + } setSystemBusy(true) setMessage('') try { @@ -263,6 +285,12 @@ const ConfigPanel = ({ currentUser }) => { } const handleAccountTradingRestart = async () => { + const hasKey = !!currentAccountMeta?.has_api_key + const hasSecret = !!currentAccountMeta?.has_api_secret + if (!hasKey || !hasSecret) { + setMessage('请先在“账号密钥(当前账号)”中配置 BINANCE_API_KEY 与 BINANCE_API_SECRET,然后再重启交易进程') + return + } setSystemBusy(true) setMessage('') try { @@ -359,6 +387,7 @@ const ConfigPanel = ({ currentUser }) => { } loadBackendStatus() loadAccountTradingStatus() + loadCurrentAccountMeta() const timer = setInterval(() => { if (isAdmin) { @@ -366,6 +395,7 @@ const ConfigPanel = ({ currentUser }) => { } loadBackendStatus() loadAccountTradingStatus() + loadCurrentAccountMeta() }, 3000) return () => clearInterval(timer) @@ -395,9 +425,12 @@ const ConfigPanel = ({ currentUser }) => { setLoading(true) loadConfigs() checkFeasibility() - loadSystemStatus() + if (isAdmin) { + loadSystemStatus() + } loadBackendStatus() loadAccountTradingStatus() + loadCurrentAccountMeta() }, [accountId]) // 顶部导航切换账号时(localStorage更新),这里做一个轻量同步 @@ -829,20 +862,26 @@ const ConfigPanel = ({ currentUser }) => {