import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { isNull, omitBy } from "lodash"; import { KEY_EXPIRE, KEY_PWA_INSTALLED, KEY_LOGIN_USER, KEY_REFRESH_TOKEN, KEY_TOKEN, KEY_UID } from "../config"; import { AuthData, RenewTokenResponse } from "../../types/auth"; import { User } from "../../types/user"; import { updateUsersByLogs } from './users'; interface State { initialized: boolean; guest: boolean; user: User | undefined; token: string; expireTime: number; refreshToken: string; roleChanged: boolean; } const loginUser = localStorage.getItem(KEY_LOGIN_USER) || ""; const initialState: State = { initialized: true, guest: loginUser ? JSON.parse(loginUser).create_by == "guest" : false, user: loginUser ? JSON.parse(loginUser) : undefined, token: localStorage.getItem(KEY_TOKEN) || "", expireTime: Number(localStorage.getItem(KEY_EXPIRE) || +new Date()), refreshToken: localStorage.getItem(KEY_REFRESH_TOKEN) || "", roleChanged: false }; const emptyState: State = { initialized: true, guest: false, user: undefined, token: "", expireTime: +new Date(), refreshToken: "", roleChanged: false }; const authDataSlice = createSlice({ name: "authData", initialState, reducers: { setAuthData(state, { payload }: PayloadAction) { const { initialized = true, user, token, refresh_token, expired_in = 0 } = payload; const { uid, create_by } = user; state.initialized = initialized; state.user = user; state.guest = create_by == "guest"; state.token = token; state.refreshToken = refresh_token; // 当前时间往后推expire时长 const expireTime = +new Date() + Number(expired_in) * 1000; state.expireTime = expireTime; // set local data localStorage.setItem(KEY_LOGIN_USER, JSON.stringify(user)); localStorage.setItem(KEY_EXPIRE, `${expireTime}`); localStorage.setItem(KEY_TOKEN, token); localStorage.setItem(KEY_REFRESH_TOKEN, refresh_token); localStorage.setItem(KEY_UID, `${uid}`); }, updateLoginUser(state, { payload }: PayloadAction>) { if (!state.user) return; const obj = { ...state.user, ...payload }; Object.keys(obj).forEach(key => { // @ts-ignore if (obj[key] === undefined) { // @ts-ignore delete obj[key]; } }); console.log("upppp", obj); state.user = obj; localStorage.setItem(KEY_LOGIN_USER, JSON.stringify(obj)); }, resetRoleChanged(state) { state.roleChanged = false; }, resetAuthData() { // remove local data localStorage.removeItem(KEY_EXPIRE); localStorage.removeItem(KEY_TOKEN); localStorage.removeItem(KEY_REFRESH_TOKEN); localStorage.removeItem(KEY_UID); localStorage.removeItem(KEY_PWA_INSTALLED); return emptyState; }, updateInitialized(state, action: PayloadAction) { state.initialized = action.payload; }, updateToken(state, action: PayloadAction) { const { token, refresh_token, expired_in } = action.payload; state.token = token; const et = +new Date() + Number(expired_in) * 1000; state.expireTime = et; state.refreshToken = refresh_token; localStorage.setItem(KEY_EXPIRE, `${et}`); localStorage.setItem(KEY_TOKEN, token); localStorage.setItem(KEY_REFRESH_TOKEN, refresh_token); } }, extraReducers: (builder) => { builder.addCase(updateUsersByLogs, (state, action) => { const changeLogs = action.payload; const currUid = Number(localStorage.getItem(KEY_UID) ?? 0); changeLogs.forEach(({ action, uid, ...rest }) => { if (uid == currUid && action == "update") { const vals = omitBy(rest, isNull); const logId = state.user?.log_id ?? 0; Object.keys(vals).forEach((k) => { if (k == "is_admin" && vals.log_id > logId && vals.is_admin !== state.user?.is_admin) { console.log("upppp 2 ", vals, state.user?.is_bot, state.user?.log_id); // 用户角色有变化 state.roleChanged = true; } }); } }); }); } }); export const { updateInitialized, updateLoginUser, setAuthData, resetAuthData, updateToken, resetRoleChanged } = authDataSlice.actions; export default authDataSlice.reducer;