auto_trade_sys/frontend/src/store/appSlice.js
2026-02-03 13:12:36 +08:00

173 lines
5.1 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 { createSlice } from '@reduxjs/toolkit'
import { setCurrentAccountIdFromStore } from '../services/api'
const VIEWING_USER_ID_KEY = 'ats_viewing_user_id'
const ACCOUNT_ID_STORAGE_KEY = 'ats_account_id'
// 从 localStorage 读取初始值
const getInitialViewingUserId = () => {
try {
const stored = localStorage.getItem(VIEWING_USER_ID_KEY)
if (stored) {
const parsed = parseInt(stored, 10)
if (Number.isFinite(parsed) && parsed > 0) return parsed
}
} catch (e) {
// ignore
}
return null
}
const getInitialAccountId = () => {
try {
const v = localStorage.getItem(ACCOUNT_ID_STORAGE_KEY)
const n = parseInt(v, 10)
return Number.isFinite(n) && n > 0 ? n : null
} catch (e) {
return null
}
}
const initialAccountId = getInitialAccountId()
// 初始化时同步到 api.js
setCurrentAccountIdFromStore(initialAccountId)
const initialState = {
currentUser: null, // 当前登录用户
viewingUserId: getInitialViewingUserId(), // 管理员查看的用户ID
accountId: initialAccountId, // 当前选中的账号ID
accounts: [], // 当前用户的账号列表
users: [], // 用户列表(管理员可见)
}
const appSlice = createSlice({
name: 'app',
initialState,
reducers: {
setCurrentUser: (state, action) => {
state.currentUser = action.payload
},
setViewingUserId: (state, action) => {
const userId = action.payload
state.viewingUserId = userId
if (userId) {
try {
localStorage.setItem(VIEWING_USER_ID_KEY, String(userId))
} catch (e) {
// ignore
}
} else {
try {
localStorage.removeItem(VIEWING_USER_ID_KEY)
} catch (e) {
// ignore
}
}
},
setAccountId: (state, action) => {
const accountId = action.payload
state.accountId = accountId
// 同步到 api.js 的全局变量,确保 API 请求使用最新的 accountId
setCurrentAccountIdFromStore(accountId)
if (accountId) {
try {
localStorage.setItem(ACCOUNT_ID_STORAGE_KEY, String(accountId))
} catch (e) {
// ignore
}
// 触发自定义事件,保持向后兼容
try {
window.dispatchEvent(new CustomEvent('ats:account:changed', { detail: { accountId } }))
} catch (e) {
// ignore
}
} else {
// 如果 accountId 为 null清空 localStorage
try {
localStorage.removeItem(ACCOUNT_ID_STORAGE_KEY)
} catch (e) {
// ignore
}
}
},
setAccounts: (state, action) => {
state.accounts = action.payload
},
setUsers: (state, action) => {
state.users = action.payload
},
// 切换用户时自动选择第一个active账号
switchUser: (state, action) => {
const userId = action.payload
state.viewingUserId = userId
if (userId) {
try {
localStorage.setItem(VIEWING_USER_ID_KEY, String(userId))
} catch (e) {
// ignore
}
}
// 账号列表会在组件中异步加载这里不自动切换accountId
// 等待账号列表加载完成后再切换
},
// 切换用户后账号列表加载完成自动选择第一个账号不管是否disabled
selectFirstAccount: (state) => {
const firstAccount = state.accounts[0]
if (firstAccount) {
const nextAccountId = parseInt(String(firstAccount.id || ''), 10)
if (Number.isFinite(nextAccountId) && nextAccountId > 0) {
state.accountId = nextAccountId
// 同步到 api.js 的全局变量
setCurrentAccountIdFromStore(nextAccountId)
try {
localStorage.setItem(ACCOUNT_ID_STORAGE_KEY, String(nextAccountId))
} catch (e) {
// ignore
}
// 触发自定义事件
try {
window.dispatchEvent(new CustomEvent('ats:account:changed', { detail: { accountId: nextAccountId } }))
} catch (e) {
// ignore
}
}
} else {
// 如果没有账号,清空 accountId
state.accountId = null
setCurrentAccountIdFromStore(null)
try {
localStorage.removeItem(ACCOUNT_ID_STORAGE_KEY)
} catch (e) {
// ignore
}
}
},
},
})
export const {
setCurrentUser,
setViewingUserId,
setAccountId,
setAccounts,
setUsers,
switchUser,
selectFirstAccount,
} = appSlice.actions
// Selectors
export const selectCurrentUser = (state) => state.app.currentUser
export const selectViewingUserId = (state) => state.app.viewingUserId
export const selectAccountId = (state) => state.app.accountId
export const selectAccounts = (state) => state.app.accounts
export const selectUsers = (state) => state.app.users
export const selectIsAdmin = (state) => (state.app.currentUser?.role || '') === 'admin'
export const selectEffectiveUserId = (state) => {
const isAdmin = (state.app.currentUser?.role || '') === 'admin'
return isAdmin && state.app.viewingUserId
? state.app.viewingUserId
: parseInt(String(state.app.currentUser?.id || ''), 10)
}
export default appSlice.reducer