auto_trade_sys/frontend/src/components/AccountSelector.jsx
2026-02-03 13:12:36 +08:00

125 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { api } from '../services/api'
import {
setAccountId,
setAccounts,
selectFirstAccount,
selectAccountId,
selectAccounts,
selectCurrentUser,
selectIsAdmin,
} from '../store/appSlice'
const AccountSelector = ({ onChanged }) => {
const dispatch = useDispatch()
const accountId = useSelector(selectAccountId)
const accounts = useSelector(selectAccounts)
const currentUser = useSelector(selectCurrentUser)
const isAdmin = useSelector(selectIsAdmin)
// 加载当前用户的账号列表
useEffect(() => {
const load = () => {
api.getAccounts()
.then((list) => {
const accountsList = Array.isArray(list) ? list : []
dispatch(setAccounts(accountsList))
// 如果当前没有选中的账号,或者选中的账号不在列表中,自动选择第一个账号
if (accountsList.length > 0) {
const currentAccount = accountsList.find((a) => a.id === accountId)
if (!currentAccount) {
dispatch(selectFirstAccount())
}
}
})
.catch(() => dispatch(setAccounts([])))
}
load()
// 配置页创建/更新账号后会触发该事件,用于即时刷新下拉列表
const onUpdated = () => load()
window.addEventListener('ats:accounts:updated', onUpdated)
return () => window.removeEventListener('ats:accounts:updated', onUpdated)
}, [dispatch, accountId])
// 当 accountId 变化时,调用 onChanged 回调
useEffect(() => {
if (typeof onChanged === 'function') {
onChanged(accountId)
}
}, [accountId, onChanged])
const list = Array.isArray(accounts) ? accounts : []
const options = list.reduce((acc, cur) => {
if (!cur || !cur.id) return acc
if (acc.some((x) => x.id === cur.id)) return acc
acc.push(cur)
return acc
}, [])
const optionsKey = options.map((x) => x.id).join(',')
useEffect(() => {
if (!options.length) {
// 如果没有账号,清空 accountId
if (accountId) {
dispatch(setAccountId(null))
}
return
}
// 检查当前选中的账号是否在新列表中
const currentAccount = options.find((a) => a.id === accountId)
if (currentAccount) {
// 账号在新列表中保持选中不管是否disabled
return
}
// 如果当前账号不在新列表中选择第一个账号不管是否disabled
const firstAccount = options[0]
if (firstAccount) {
dispatch(setAccountId(parseInt(String(firstAccount.id || ''), 10)))
} else {
// 如果没有账号,清空 accountId
dispatch(setAccountId(null))
}
}, [optionsKey, accountId, dispatch])
return (
<div className="nav-account">
<span className="nav-account-label">账号</span>
<select
className="nav-account-select"
value={accountId || ''}
onChange={(e) => {
const v = parseInt(e.target.value, 10)
if (Number.isFinite(v) && v > 0) {
// 允许选择任何账号包括disabled由各个页面根据账号状态决定是否展示内容
dispatch(setAccountId(v))
} else {
dispatch(setAccountId(null))
}
}}
title="切换账号后:配置/持仓/交易记录/统计会按账号隔离;推荐仍是全局"
>
{options.length === 0 ? (
<option value="">暂无账号</option>
) : (
options.map((a) => {
const isDisabled = String(a?.status || 'active') === 'disabled'
return (
<option key={a.id} value={a.id}>
#{a.id} {a.name || 'account'}
{isDisabled ? '(已禁用)' : ''}
</option>
)
})
)}
</select>
</div>
)
}
export default AccountSelector