This commit is contained in:
2026-04-21 10:30:12 +08:00
parent ae28dab032
commit 13bc79306f
49 changed files with 3691 additions and 1357 deletions

View File

@@ -0,0 +1,169 @@
# 前端逻辑后移实施方案2026-04-21
更新时间:`2026-04-21`
## 1. 目标
本方案只回答一件事:
**怎样把当前仍残留在前端的正式运行时逻辑、正式会话真相与正式生成编排,继续收回到 Express 后端。**
这份文档不是泛泛而谈的方向说明,而是直接面向本轮与后续几轮编码落地的实施基线。
---
## 2. 本轮确定的硬边界
根据仓库约束与当前审计结果,本轮继续冻结以下边界:
1. 前端只负责表现、输入采集、临时 UI 状态与服务端结果渲染。
2. 后端负责正式鉴权、正式会话、正式运行时快照、正式任务生成、正式运行时物品意图生成、正式自定义世界生成。
3. 浏览器内不再保存 access token不再把浏览历史作为本地正式真相不再保留正式 quest / runtime item / custom world 生成编排。
4. 运行时主链必须继续向“前端提交意图,后端解释快照并返回展示模型”收敛。
---
## 3. 现状拆分
当前残留问题已经收敛为三批:
### 3.1 第一批:正式真相仍在前端
1. `src/services/apiClient.ts`
- 浏览器仍保存 access token并拼接 `Authorization: Bearer ...`
2. `src/services/authService.ts`
- 登录、微信绑定等流程仍把 access token 当作前端真相
3. `src/components/game-shell/PreGameSelectionFlow.tsx`
- 浏览历史仍是本地写入 + 后端回填的双真相
4. `src/services/platformBrowseHistory.ts`
- 维护浏览历史本地存储、迁移标记与同步状态
### 3.2 第二批:运行时主链仍依赖前端预写快照
1. `src/hooks/story/runtimeStoryCoordinator.ts`
- 在请求 runtime state / runtime action 前,仍先 `PUT /runtime/save/snapshot`
2. `src/hooks/story/npcEncounterActions.ts`
- 待接委托的“更换任务”“放弃任务”仍由前端正式结算
### 3.3 第三批:正式生成编排仍残留在浏览器
1. `src/services/questDirector.ts`
2. `src/services/runtimeItemAiDirector.ts`
3. `src/services/aiService.ts` 的 custom world profile 生成入口
4. `src/services/ai.ts` 中仍保留的浏览器侧 legacy AI orchestration
---
## 4. 分批实施策略
## 4.1 第一批:先收正式真相
### 鉴权
目标状态:
1. 后端通过 HttpOnly Cookie 持有 refresh session 与 access session。
2. 前端请求层不再读写 access token。
3. 前端只监听鉴权状态事件,不解释 token 生命周期。
本批涉及:
1. `server-node/src/auth/accessSessionCookie.ts`
2. `server-node/src/routes/authRoutes.ts`
3. `server-node/src/middleware/auth.ts`
4. `src/services/apiClient.ts`
5. `src/services/authService.ts`
6. `src/components/auth/AuthGate.tsx`
### 浏览历史
目标状态:
1. 浏览历史唯一真相在 `runtimeRepository`
2. 前端不再保留本地浏览历史、迁移标记、同步标记。
3. 浏览历史只通过 `storageService` 读取和写入。
本批涉及:
1. `src/components/game-shell/PreGameSelectionFlow.tsx`
2. `src/components/game-shell/PlatformHomeView.tsx`
3. `src/services/storageService.ts`
4. `src/services/platformBrowseHistory.ts`
## 4.2 第二批:把 runtime story 快照解释权收回后端
目标状态:
1. 前端不再通过单独的 `PUT /runtime/save/snapshot` 预写快照再触发动作。
2. runtime state / runtime action 允许前端提交当前快照上下文,由后端内部决定是否写入、如何解释、何时持久化。
3. NPC 待接委托的 replace / abandon / accept 全部走后端 runtime action。
建议实施方式:
1. 扩展 `packages/shared/src/contracts/story.ts`
- `RuntimeStoryActionRequest` 增加可选 `snapshot`
- 新增 `RuntimeStoryStateRequest`
2. 新增 `POST /api/runtime/story/state/resolve`
3. `storyActionService` 内部统一处理“请求携带快照上下文时的服务端同步”
4.`npc_chat_quest_offer_replace` / `npc_chat_quest_offer_abandon` 接到后端 runtime action
## 4.3 第三批:把正式生成编排收成后端唯一出口
目标状态:
1. `questDirector` 只保留轻量 SDK。
2. `runtimeItemAiDirector` 只保留轻量 SDK。
3. custom world profile 正式生成走后端 route。
4. 浏览器侧 `src/services/ai.ts` 不再承担正式浏览器主链。
建议实施方式:
1. `server-node/src/routes/runtimeRoutes.ts`
-`custom-world/profile` 正式 route
2. `src/services/aiService.ts`
- custom world 入口改走后端
3. `src/services/questDirector.ts`
- 只请求 `/api/runtime/quests/generate`
4. `src/services/runtimeItemAiDirector.ts`
- 只请求 `/api/runtime/items/runtime-intent`
---
## 5. 本轮落地范围
本轮优先完成以下内容:
1. 鉴权 access token 从前端 localStorage 后移到后端 Cookie。
2. 浏览历史从前端本地真相后移到后端唯一真相。
3. custom world profile 正式生成入口补齐后端 route并把前端收成 SDK。
4. `questDirector` / `runtimeItemAiDirector` 收缩为前端 SDK。
5. runtime story contract 开始补“随请求提交快照上下文”的后端承接能力,并把 NPC 待接委托 replace / abandon 接到后端。
---
## 6. 验收标准
### 第一批验收
1. 浏览器中不再保存 access token。
2. `fetchWithApiAuth` 不再拼接 Bearer token。
3. 浏览历史仅通过远端接口读写。
4. `src/services/platformBrowseHistory.ts` 不再是正式链路依赖。
### 第二批验收
1. `runtimeStoryCoordinator.ts` 不再在动作前独立 `PUT /runtime/save/snapshot`
2. `NPC` 待接委托 replace / abandon / accept 都以后端返回结果为准。
### 第三批验收
1. `questDirector.ts``runtimeItemAiDirector.ts` 不再保留正式 fallback orchestration。
2. custom world profile 的浏览器正式入口不再直接 import legacy `./ai`
---
## 7. 一句话结论
这轮迁移的重点不是“把几个 helper 挪到 server-node 目录”,而是:
**把前端里仍然承担正式真相、正式运行时解释和正式生成编排的那一层职责,继续收回到 Express 后端。**