a
This commit is contained in:
parent
d051be3f65
commit
1c1580b344
|
|
@ -107,11 +107,37 @@ const AccountSelector = ({ onChanged }) => {
|
||||||
const optionsKey = options.map((x) => x.id).join(',')
|
const optionsKey = options.map((x) => x.id).join(',')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!options.length) return
|
if (!options.length) {
|
||||||
if (options.some((a) => a.id === accountId)) return
|
// 如果没有账号,清空 accountId
|
||||||
const firstActive = options.find((a) => String(a?.status || 'active') === 'active') || options[0]
|
if (accountId) {
|
||||||
|
dispatch(setAccountId(null))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查当前选中的账号是否在新列表中且是 active 的
|
||||||
|
const currentAccount = options.find((a) => a.id === accountId)
|
||||||
|
if (currentAccount) {
|
||||||
|
// 如果当前账号是 disabled,需要切换到 active 账号
|
||||||
|
if (String(currentAccount?.status || 'active') === 'disabled') {
|
||||||
|
const firstActive = options.find((a) => String(a?.status || 'active') === 'active')
|
||||||
if (firstActive) {
|
if (firstActive) {
|
||||||
dispatch(setAccountId(parseInt(String(firstActive.id || ''), 10)))
|
dispatch(setAccountId(parseInt(String(firstActive.id || ''), 10)))
|
||||||
|
} else {
|
||||||
|
// 如果没有 active 账号,清空 accountId
|
||||||
|
dispatch(setAccountId(null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果当前账号不在新列表中,选择第一个 active 账号
|
||||||
|
const firstActive = options.find((a) => String(a?.status || 'active') === 'active')
|
||||||
|
if (firstActive) {
|
||||||
|
dispatch(setAccountId(parseInt(String(firstActive.id || ''), 10)))
|
||||||
|
} else {
|
||||||
|
// 如果没有 active 账号,清空 accountId
|
||||||
|
dispatch(setAccountId(null))
|
||||||
}
|
}
|
||||||
}, [optionsKey, accountId, dispatch])
|
}, [optionsKey, accountId, dispatch])
|
||||||
|
|
||||||
|
|
@ -123,20 +149,46 @@ const AccountSelector = ({ onChanged }) => {
|
||||||
value={accountId || ''}
|
value={accountId || ''}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const v = parseInt(e.target.value, 10)
|
const v = parseInt(e.target.value, 10)
|
||||||
dispatch(setAccountId(Number.isFinite(v) && v > 0 ? v : 1))
|
if (Number.isFinite(v) && v > 0) {
|
||||||
|
// 检查选中的账号是否是 disabled
|
||||||
|
const selectedAccount = options.find((a) => a.id === v)
|
||||||
|
if (selectedAccount && String(selectedAccount?.status || 'active') === 'disabled') {
|
||||||
|
// 如果选中的是 disabled 账号,不允许选择,保持当前值
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dispatch(setAccountId(v))
|
||||||
|
} else {
|
||||||
|
dispatch(setAccountId(null))
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
title="切换账号后:配置/持仓/交易记录/统计会按账号隔离;推荐仍是全局"
|
title="切换账号后:配置/持仓/交易记录/统计会按账号隔离;推荐仍是全局"
|
||||||
disabled={isAdmin && !effectiveUserId}
|
disabled={isAdmin && !effectiveUserId}
|
||||||
>
|
>
|
||||||
{options.length === 0 ? (
|
{options.length === 0 ? (
|
||||||
<option value="">{isAdmin && !effectiveUserId ? '请先选择用户' : '暂无账号'}</option>
|
<option value="">{isAdmin && !effectiveUserId ? '请先选择用户' : '暂无账号'}</option>
|
||||||
) : (
|
) : accountId === null ? (
|
||||||
options.map((a) => (
|
<>
|
||||||
<option key={a.id} value={a.id}>
|
<option value="">请选择账号</option>
|
||||||
|
{options.map((a) => {
|
||||||
|
const isDisabled = String(a?.status || 'active') === 'disabled'
|
||||||
|
return (
|
||||||
|
<option key={a.id} value={a.id} disabled={isDisabled}>
|
||||||
#{a.id} {a.name || 'account'}
|
#{a.id} {a.name || 'account'}
|
||||||
{String(a?.status || 'active') === 'disabled' ? '(已禁用)' : ''}
|
{isDisabled ? '(已禁用)' : ''}
|
||||||
</option>
|
</option>
|
||||||
))
|
)
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
options.map((a) => {
|
||||||
|
const isDisabled = String(a?.status || 'active') === 'disabled'
|
||||||
|
return (
|
||||||
|
<option key={a.id} value={a.id} disabled={isDisabled}>
|
||||||
|
#{a.id} {a.name || 'account'}
|
||||||
|
{isDisabled ? '(已禁用)' : ''}
|
||||||
|
</option>
|
||||||
|
)
|
||||||
|
})
|
||||||
)}
|
)}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -361,18 +361,30 @@ const GlobalConfig = () => {
|
||||||
|
|
||||||
const loadConfigs = async () => {
|
const loadConfigs = async () => {
|
||||||
try {
|
try {
|
||||||
// 管理员全局配置:使用全局策略账号的配置,不依赖当前 account
|
// 管理员全局配置:始终使用全局策略账号的配置,不依赖当前 account
|
||||||
if (isAdmin && configMeta?.global_strategy_account_id) {
|
// 即使 configMeta 还没加载完成,也使用默认值 1
|
||||||
const globalAccountId = parseInt(String(configMeta?.global_strategy_account_id || '1'), 10) || 1
|
if (isAdmin) {
|
||||||
|
const globalAccountId = configMeta?.global_strategy_account_id
|
||||||
|
? parseInt(String(configMeta.global_strategy_account_id || '1'), 10) || 1
|
||||||
|
: 1 // 如果 configMeta 还没加载,使用默认值 1
|
||||||
const data = await api.getGlobalConfigs(globalAccountId)
|
const data = await api.getGlobalConfigs(globalAccountId)
|
||||||
setConfigs(data)
|
setConfigs(data)
|
||||||
} else {
|
} else {
|
||||||
// 非管理员或未加载 configMeta 时,使用默认方式
|
// 非管理员:使用默认方式(会受当前 account 影响,但非管理员不应该访问这个页面)
|
||||||
const data = await api.getConfigs()
|
const data = await api.getConfigs()
|
||||||
setConfigs(data)
|
setConfigs(data)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load configs:', error)
|
console.error('Failed to load configs:', error)
|
||||||
|
// 如果加载失败,尝试使用默认值 1 重试一次
|
||||||
|
if (isAdmin) {
|
||||||
|
try {
|
||||||
|
const data = await api.getGlobalConfigs(1)
|
||||||
|
setConfigs(data)
|
||||||
|
} catch (retryError) {
|
||||||
|
console.error('Retry load configs with accountId=1 failed:', retryError)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -440,11 +452,20 @@ const GlobalConfig = () => {
|
||||||
loadAccounts()
|
loadAccounts()
|
||||||
// 只有管理员才加载配置和系统状态
|
// 只有管理员才加载配置和系统状态
|
||||||
if (isAdmin) {
|
if (isAdmin) {
|
||||||
// 先加载 configMeta,再加载 configs(因为 loadConfigs 需要 global_strategy_account_id)
|
// 立即加载 configs(不等待 configMeta,使用默认值 1)
|
||||||
|
// 同时加载 configMeta,加载完成后会触发重新加载 configs(如果 global_strategy_account_id 不是 1)
|
||||||
|
loadConfigs().catch(() => {})
|
||||||
loadConfigMeta()
|
loadConfigMeta()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// configMeta 加载完成后,再加载 configs
|
// configMeta 加载完成后,如果 global_strategy_account_id 不是 1,重新加载 configs
|
||||||
|
// 这样可以确保使用正确的全局策略账号ID
|
||||||
|
const globalAccountId = configMeta?.global_strategy_account_id
|
||||||
|
? parseInt(String(configMeta.global_strategy_account_id || '1'), 10) || 1
|
||||||
|
: 1
|
||||||
|
// 如果 globalAccountId 不是 1,说明之前加载的是默认值,需要重新加载
|
||||||
|
if (globalAccountId !== 1) {
|
||||||
loadConfigs().catch(() => {})
|
loadConfigs().catch(() => {})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {}) // 静默失败
|
.catch(() => {}) // 静默失败
|
||||||
loadSystemStatus().catch(() => {}) // 静默失败
|
loadSystemStatus().catch(() => {}) // 静默失败
|
||||||
|
|
@ -608,12 +629,15 @@ const GlobalConfig = () => {
|
||||||
}
|
}
|
||||||
}).filter(Boolean)
|
}).filter(Boolean)
|
||||||
|
|
||||||
// 管理员全局配置:应用到全局策略账号
|
// 管理员全局配置:始终使用全局策略账号,即使 configMeta 还没加载也使用默认值 1
|
||||||
let response
|
let response
|
||||||
if (isAdmin && configMeta?.global_strategy_account_id) {
|
if (isAdmin) {
|
||||||
const globalAccountId = parseInt(String(configMeta?.global_strategy_account_id || '1'), 10) || 1
|
const globalAccountId = configMeta?.global_strategy_account_id
|
||||||
|
? parseInt(String(configMeta.global_strategy_account_id || '1'), 10) || 1
|
||||||
|
: 1
|
||||||
response = await api.updateGlobalConfigsBatch(configItems, globalAccountId)
|
response = await api.updateGlobalConfigsBatch(configItems, globalAccountId)
|
||||||
} else {
|
} else {
|
||||||
|
// 非管理员不应该访问这个页面,但为了安全还是处理一下
|
||||||
response = await api.updateConfigsBatch(configItems)
|
response = await api.updateConfigsBatch(configItems)
|
||||||
}
|
}
|
||||||
setMessage(response.message || `已应用${preset.name}`)
|
setMessage(response.message || `已应用${preset.name}`)
|
||||||
|
|
@ -654,10 +678,12 @@ const GlobalConfig = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildConfigSnapshot = async (includeSecrets) => {
|
const buildConfigSnapshot = async (includeSecrets) => {
|
||||||
// 管理员全局配置:使用全局策略账号的配置
|
// 管理员全局配置:始终使用全局策略账号的配置,即使 configMeta 还没加载也使用默认值 1
|
||||||
let data
|
let data
|
||||||
if (isAdmin && configMeta?.global_strategy_account_id) {
|
if (isAdmin) {
|
||||||
const globalAccountId = parseInt(String(configMeta?.global_strategy_account_id || '1'), 10) || 1
|
const globalAccountId = configMeta?.global_strategy_account_id
|
||||||
|
? parseInt(String(configMeta.global_strategy_account_id || '1'), 10) || 1
|
||||||
|
: 1
|
||||||
data = await api.getGlobalConfigs(globalAccountId)
|
data = await api.getGlobalConfigs(globalAccountId)
|
||||||
} else {
|
} else {
|
||||||
data = await api.getConfigs()
|
data = await api.getConfigs()
|
||||||
|
|
@ -1169,10 +1195,16 @@ const GlobalConfig = () => {
|
||||||
try {
|
try {
|
||||||
setSaving(true)
|
setSaving(true)
|
||||||
setMessage('')
|
setMessage('')
|
||||||
// 检查 configMeta 是否存在,如果不存在则使用默认值 1
|
// 管理员始终使用全局策略账号,即使 configMeta 还没加载也使用默认值 1
|
||||||
const globalAccountId = configMeta?.global_strategy_account_id
|
const globalAccountId = isAdmin
|
||||||
? parseInt(String(configMeta?.global_strategy_account_id || '1'), 10) || 1
|
? (configMeta?.global_strategy_account_id
|
||||||
: 1
|
? parseInt(String(configMeta.global_strategy_account_id || '1'), 10) || 1
|
||||||
|
: 1)
|
||||||
|
: null
|
||||||
|
if (!isAdmin || !globalAccountId) {
|
||||||
|
setMessage('只有管理员可以修改全局配置')
|
||||||
|
return
|
||||||
|
}
|
||||||
await api.updateGlobalConfigsBatch([{
|
await api.updateGlobalConfigsBatch([{
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,13 @@ const appSlice = createSlice({
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// 如果 accountId 为 null,清空 localStorage
|
||||||
|
try {
|
||||||
|
localStorage.removeItem(ACCOUNT_ID_STORAGE_KEY)
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setAccounts: (state, action) => {
|
setAccounts: (state, action) => {
|
||||||
|
|
@ -97,8 +104,9 @@ const appSlice = createSlice({
|
||||||
// 等待账号列表加载完成后再切换
|
// 等待账号列表加载完成后再切换
|
||||||
},
|
},
|
||||||
// 切换用户后,账号列表加载完成,自动选择第一个active账号
|
// 切换用户后,账号列表加载完成,自动选择第一个active账号
|
||||||
|
// 如果没有 active 账号,不改变当前 accountId(保持为 null 或之前的值)
|
||||||
selectFirstActiveAccount: (state) => {
|
selectFirstActiveAccount: (state) => {
|
||||||
const firstActive = state.accounts.find((a) => String(a?.status || 'active') === 'active') || state.accounts[0]
|
const firstActive = state.accounts.find((a) => String(a?.status || 'active') === 'active')
|
||||||
if (firstActive) {
|
if (firstActive) {
|
||||||
const nextAccountId = parseInt(String(firstActive.id || ''), 10)
|
const nextAccountId = parseInt(String(firstActive.id || ''), 10)
|
||||||
if (Number.isFinite(nextAccountId) && nextAccountId > 0) {
|
if (Number.isFinite(nextAccountId) && nextAccountId > 0) {
|
||||||
|
|
@ -115,6 +123,14 @@ const appSlice = createSlice({
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// 如果没有 active 账号,清空 accountId
|
||||||
|
state.accountId = null
|
||||||
|
try {
|
||||||
|
localStorage.removeItem(ACCOUNT_ID_STORAGE_KEY)
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user