refactor: 合并多语言支持的显示名称字段,优化奖池手动爆发功能的返回数据结构,增强管理端权限控制

This commit is contained in:
2026-05-25 14:31:24 +08:00
parent 7d01e5c47e
commit ddedef824e
101 changed files with 3033 additions and 641 deletions

View File

@@ -4,6 +4,7 @@
* - **组件内**`useAdminProfile()`、`useAdminSessionStore(...)`
* - **组件外**axios、工具函数`getAdminProfile()`、`useAdminSessionStore.getState()`
*/
import { isAxiosError } from "axios";
import { create } from "zustand";
import { getAdminMe } from "@/api/admin-auth";
@@ -12,6 +13,37 @@ import { readProfile, writeProfile } from "@/stores/admin-profile";
import { readToken, writeToken } from "@/stores/admin-token";
import type { AdminProfile } from "@/types/api/admin-auth";
/** 避免 rehydrate 先用 localStorage 里的旧 navigation 渲染侧栏 */
function profileForRehydrate(profile: AdminProfile | null): AdminProfile | null {
if (!profile) {
return null;
}
return {
...profile,
navigation: [],
};
}
function isAdminAuthRejected(err: unknown): boolean {
if (!isAxiosError(err)) {
return false;
}
const status = err.response?.status;
if (status === 401 || status === 403) {
return true;
}
const body = err.response?.data;
if (body && typeof body === "object" && "code" in body) {
const code = (body as { code?: unknown }).code;
return code === 401 || code === 403;
}
return false;
}
export type AdminSessionState = {
bearerToken: string | null;
adminProfile: AdminProfile | null;
@@ -62,7 +94,7 @@ export const useAdminSessionStore = create<AdminSessionState>((set, get) => ({
const profile = readProfile();
if (token) {
setAdminBearerToken(token);
set({ bearerToken: token, adminProfile: profile });
set({ bearerToken: token, adminProfile: profileForRehydrate(profile) });
void get().refreshAdminProfile();
} else {
setAdminBearerToken(null);
@@ -80,8 +112,18 @@ export const useAdminSessionStore = create<AdminSessionState>((set, get) => ({
const result = await getAdminMe();
writeProfile(result.admin);
set({ adminProfile: result.admin });
} catch {
// 兼容旧缓存失败时不打断页面,留给后续登录态处理。
} catch (err) {
if (isAdminAuthRejected(err)) {
get().clearSession();
return;
}
const cached = get().adminProfile ?? readProfile();
if (cached) {
const withoutNav = profileForRehydrate(cached);
writeProfile(withoutNav);
set({ adminProfile: withoutNav });
}
}
},