Files
lotteryFront/src/stores/player-session-store.ts
kang 14c297fe1a feat: 接入玩家入口与API代理
- 新增 /api 重写代理,支持 LOTTERY_API_PROXY_TARGET 配置
- 玩家首页切换为 EntryGate,并移除 layout 对 PlayerAppShell 的包裹
- 请求层拆分语言头与玩家鉴权注入逻辑,引入 zustand 依赖
- 允许提交 .env.example 供本地配置参考
2026-05-09 10:17:39 +08:00

102 lines
2.9 KiB
TypeScript

import { create } from "zustand";
import { setPlayerBearerToken } from "@/lib/lottery-auth";
import {
clearPersistedPlayerBearerToken,
persistPlayerBearerToken,
readPersistedPlayerBearerToken,
} from "@/lib/player-session";
import type { PlayerMeData } from "@/types/api/player-me";
export type PlayerEntryPhase = "loading" | "error" | "success";
export type PlayerEntryStepId = "token" | "account" | "hall";
export type PlayerEntryStepStatus = "pending" | "active" | "done";
export type PlayerEntryStep = {
id: PlayerEntryStepId;
label: string;
status: PlayerEntryStepStatus;
};
type PlayerSessionState = {
bearerToken: string | null;
profile: PlayerMeData | null;
phase: PlayerEntryPhase;
progress: number;
errorMessage: string | null;
steps: PlayerEntryStep[];
setBearerToken: (token: string | null) => void;
restoreBearerToken: () => string | null;
clearBearerToken: () => void;
setProfile: (profile: PlayerMeData | null) => void;
setPhase: (phase: PlayerEntryPhase) => void;
setProgress: (progress: number) => void;
setErrorMessage: (message: string | null) => void;
updateStep: (id: PlayerEntryStepId, status: PlayerEntryStepStatus) => void;
resetEntryFlow: () => void;
};
function initialSteps(): PlayerEntryStep[] {
return [
{ id: "token", label: "校验登录凭证", status: "active" },
{ id: "account", label: "同步玩家账号", status: "pending" },
{ id: "hall", label: "加载彩票大厅", status: "pending" },
];
}
export const usePlayerSessionStore = create<PlayerSessionState>((set) => ({
bearerToken: null,
profile: null,
phase: "loading",
progress: 0,
errorMessage: null,
steps: initialSteps(),
setBearerToken: (token) => {
const normalized = token?.trim() || null;
setPlayerBearerToken(normalized);
if (normalized) {
persistPlayerBearerToken(normalized);
} else {
clearPersistedPlayerBearerToken();
}
set({ bearerToken: normalized });
},
restoreBearerToken: () => {
const raw = readPersistedPlayerBearerToken();
const normalized = raw?.trim() || null;
if (normalized) {
setPlayerBearerToken(normalized);
set({ bearerToken: normalized });
return normalized;
}
setPlayerBearerToken(null);
set({ bearerToken: null });
return null;
},
clearBearerToken: () => {
setPlayerBearerToken(null);
clearPersistedPlayerBearerToken();
set({ bearerToken: null, profile: null });
},
setProfile: (profile) => set({ profile }),
setPhase: (phase) => set({ phase }),
setProgress: (progress) => set({ progress: Math.max(0, Math.min(100, progress)) }),
setErrorMessage: (errorMessage) => set({ errorMessage }),
updateStep: (id, status) =>
set((state) => ({
steps: state.steps.map((step) =>
step.id === id ? { ...step, status } : step,
),
})),
resetEntryFlow: () =>
set({
phase: "loading",
progress: 0,
errorMessage: null,
steps: initialSteps(),
}),
}));