diff --git a/src/stores/chat/__tests__/chat-machine.transitions.test.ts b/src/stores/chat/__tests__/chat-machine.transitions.test.ts index 57bf9bdd..eed2dcd4 100644 --- a/src/stores/chat/__tests__/chat-machine.transitions.test.ts +++ b/src/stores/chat/__tests__/chat-machine.transitions.test.ts @@ -164,6 +164,30 @@ describe("chatMachine transitions", () => { actor.stop(); }); + it("ignores repeated user login while an authenticated user session is active", async () => { + const actor = createActor(createTestChatMachine()).start(); + + actor.send({ type: "ChatUserLogin", token: "token" }); + await waitFor(actor, (snapshot) => + snapshot.matches({ userSession: "ready" }), + ); + + actor.send({ type: "ChatSendMessage", content: "keep this message" }); + await waitFor( + actor, + (snapshot) => snapshot.context.messages.length === 1, + ); + + actor.send({ type: "ChatUserLogin", token: "another-token" }); + + expect(actor.getSnapshot().matches({ userSession: "ready" })).toBe(true); + expect(actor.getSnapshot().context.messages).toMatchObject([ + { content: "keep this message", isFromAI: false }, + ]); + + actor.stop(); + }); + it("allows multiple messages to be queued without leaving ready state", async () => { const actor = createActor(createTestChatMachine()).start(); diff --git a/src/stores/chat/chat-auth-sync.tsx b/src/stores/chat/chat-auth-sync.tsx index fe81d0cc..fe47e785 100644 --- a/src/stores/chat/chat-auth-sync.tsx +++ b/src/stores/chat/chat-auth-sync.tsx @@ -10,7 +10,7 @@ import { useEffect, useRef } from "react"; import { usePathname, useRouter } from "next/navigation"; -import { AuthStorage } from "@/data/storage/auth/auth_storage"; +import { AuthStorage } from "@/data/storage/auth"; import { useAuthState } from "@/stores/auth/auth-context"; import { PROTECTED_ROUTES, ROUTES, type StaticRoute } from "@/router/routes"; diff --git a/src/stores/chat/chat-machine.ts b/src/stores/chat/chat-machine.ts index 86dc79ed..09946577 100644 --- a/src/stores/chat/chat-machine.ts +++ b/src/stores/chat/chat-machine.ts @@ -1,17 +1,10 @@ /** * Chat 状态机(XState v5) * - * 鉴权解耦(事件驱动): - * chat 机器不感知鉴权 —— 由 派生 loginStatus - * ChatAuthSync 派发登录态生命周期事件: - * - `ChatGuestLogin` → 游客会话 - * - `ChatUserLogin { token }` → 其他登录用户会话 - * - `ChatLogout` → 正式登录用户登出 - * * 登录态流转约束: * - 未登录:可以进入游客登录 / 其他登录。 * - 游客登录:只可以升级为其他登录,不响应退出。 - * - 其他登录:可以退出,不响应游客登录。 + * - 其他登录:可以退出,不响应游客登录 / 重复其他登录。 * * 状态结构(parent state 模式): * - `idle`:屏没挂 / 登出 @@ -363,11 +356,6 @@ export const chatMachine = setup({ target: "#chat.idle", actions: "clearChatSession", }, - ChatUserLogin: { - target: "#chat.userSession", - reenter: true, - actions: "startUserSession", - }, ChatQueuedSendStarted: { actions: "markQueuedSendStarted", },