173 lines
5.1 KiB
JavaScript
173 lines
5.1 KiB
JavaScript
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
|