# 前端优化建议

本文档基于对当前前端代码的检查，给出可执行的优化建议，按优先级和类别组织。

---

## 一、已修复问题

### 1. 项目设置保存 API 路径错误

- **位置**：`frontend/src/components/canvas/panels/management/project-details/tabs/SettingsTab.tsx`
- **问题**：使用 `fetch(\`${OpenAPI.BASE}/api/projects/${projectId}\`)` 请求的是 `/api/projects/:id`，而后端路由为 `/api/v1/projects/:id`，导致 404。
- **修复**：改为使用生成的 API 客户端 `DefaultService.updateProject(projectId, updateData)`，保证请求路径为 `/api/v1/projects/:id`。
- **说明**：若后端需要持久化 `type`、`status`、`defaultImageModel` 等，需在 `UpdateProjectRequest` 中声明对应字段。

---

## 二、配置与一致性

### 2. API Base URL 与 Rewrites 统一（已落地）

- **现状**：
  - `next.config.mjs` 使用 `API_URL`（无 `NEXT_PUBLIC_`）做 rewrites。
  - `frontend/src/lib/client.ts` 使用 `NEXT_PUBLIC_API_URL || 'http://localhost:8000'` 设置 `OpenAPI.BASE`。
- **已做**：
  - `client.ts` 改为 `OpenAPI.BASE = process.env.NEXT_PUBLIC_API_URL ?? ''`，默认走同源 + rewrites。
  - `next.config.mjs` 增加注释说明 `API_URL` 与 `NEXT_PUBLIC_API_URL` 的职责。
  - 新增 `frontend/.env.example`，说明 `API_URL`（服务端 rewrites）与 `NEXT_PUBLIC_API_URL`（浏览器端，不设则用同源）。

### 3. 依赖声明（已落地）

- **现状**：`canvasStore.ts` 使用 `lodash-es`（如 `debounce`），但 `package.json` 中只有 `@types/lodash-es`（devDependency），`lodash-es` 为间接依赖。
- **已做**：在 `dependencies` 中显式添加 `lodash-es: ^4.17.21`。

---

## 三、数据请求与状态

### 4. 项目页用 React Query 替代手写 fetch（已落地）

- **位置**：`frontend/src/app/project/[id]/page.tsx`
- **已做**：
  - 新增 `useProjectWorkspace(projectId)`（`useProjects.ts`），内部使用 `useQuery` + `getProject(id, false, true)`，缓存 key 为 `projectKeys.workspace(id)`，与列表/详情隔离。
  - 项目页改为使用该 hook，无 projectId 时展示「无效的项目」，loading 时展示 `LoadingState`，error 时展示错误文案 +「重试」按钮（调用 `refetch`）。
  - 数据同步到 `useProjectStore` 在 hook 的 `useEffect` 中完成，依赖仅 `projectId` 与 `query.data`，避免 setter 导致重复请求。

### 5. 项目页初始化逻辑（已落地）

- **已做**：在 `useProjectWorkspace` 内用 `initialEpisodeSetRef` 保证「有集数据且当前无选中集时自动选中第一集」只执行一次；切换 `projectId` 时重置该 ref，避免 refetch 覆盖用户已选集。

---

## 四、性能与包体积

### 6. 大组件与动态加载（已落地）

- **现状**：`Canvas.tsx`、`AppNode.tsx` 已对部分重量级组件使用 `next/dynamic`（ImageCropper、SketchEditor、SettingsModal、ProjectDetailsModal、ExpandedView、RightSidebar、各 Node Renderer），方向正确。
- **已做**：
  - **Canvas**：底部输入栏 `InteractionInput` 改为 `next/dynamic` 按需加载，首屏不阻塞；展示「加载输入栏...」占位。
  - **InteractionInput**：`ChatDisplay` 改为 `next/dynamic`，仅在用户打开「助手」聊天时加载对应 chunk。
  - **next.config.mjs**：`optimizePackageImports` 增加 `@radix-ui/react-dialog`、`@radix-ui/react-dropdown-menu`、`@radix-ui/react-select`、`@radix-ui/react-tabs`，与现有 `@lobehub/icons`、`lucide-react`、`framer-motion` 一起做 barrel 优化；可定期检查是否再加大库。

### 7. 画布相关 memo 与订阅（已落地）

- **现状**：Canvas 已对 Sidebar、RightSidebar、CanvasContextMenu 使用 `memo`；Zustand 需注意选择器粒度。
- **已做**：
  - **单字段订阅**：画布相关 hooks 与组件中，凡只用 store 单一字段的，一律改为 `useProjectStore((s) => s.xxx)` / `useCanvasStore((s) => s.xxx)`（如 `useNodeExecution`、`useCanvasPersistence`、`useGenerationHistory`、`CanvasManager`、`StoryboardDetails`、`CreateAssetForm`）。
  - **多字段订阅**：需要多个字段的改用 `useShallow`，避免整 store 订阅导致无关变更触发重渲染。已改：`useNodeActions`、`useCanvasInitialization`、`useAssetSaver`、`StoryboardsTab`、`ScriptTab`、`AssetsTab`、`ProjectDetailsModal`、`EpisodeDetails`、`CanvasRightDock`、`OverviewTab`、`SettingsTab`。
  - **回调稳定性**：上述从 store 取出的 action（如 `updateAsset`、`setProject`）由 Zustand 提供，引用稳定，子组件不会因回调引用变而多余重渲染。

---

## 五、错误处理与健壮性

### 8. 使用 ErrorBoundary 包裹画布（已落地）

- **位置**：`frontend/src/app/project/[id]/page.tsx`
- **已做**：项目页已用 `CanvasErrorBoundary` 包裹 `<Canvas />`，画布渲染异常会展示 fallback，不再直接白屏。

### 9. 控制台与类型（进行中）

- **已做（第一批）**：
  - `logger` 参数类型从 `any[]` 收紧为 `unknown[]`。
  - 核心链路改造为 `logger`：`OfflineSyncProvider`、`CanvasPersistenceService`、`useCanvasInitialization`。
- **后续**：其余 `console.*` 与 `any` 仍较多，建议按模块持续替换（交互输入、项目管理、设置页优先）。

---

## 六、代码结构与可维护性

### 10. 超大类/文件拆分（进行中）

- **现状**：`InteractionInput.tsx`、`AutoResizeTextarea.tsx` 等单文件超过 700 行，逻辑多、状态多。
- **风险**：
  - 修改任意一处逻辑都可能影响到完全无关的功能，容易产生回归。
  - 代码评审成本高，新同学上手困难。
  - 无法对局部逻辑做针对性单测或 Storybook。
- **建议（结构拆分）**：
  - 按“Tab/模式”（如 text / image / video / audio）、或“编辑态 vs 创建态”拆成子组件或自定义 hooks（如 `useInteractionEditMode`、`useGenerationSubmit`），主文件只做组合与布局。
  - 将 **通用逻辑**（如输入框自适应高度、回车发送、快捷键、草稿保存）沉淀为 `useXXX` hooks 或 `components/common/` 下的基础组件，避免在多个页面重复实现。
  - 对于复用度低但逻辑复杂的块（如“生成参数面板”“节点执行状态展示”），放到 `components/canvas/interaction/` 等子目录中，以“目录 + index 组件”形式归类。
- **建议（渐进式重构策略）**：
  - 以“**先抽 hooks 再拆 UI**”为原则：先把明显的纯业务逻辑（如表单状态、提交节流、API 调用）抽到 hooks，再将 View 拆分为多个视觉组件。
  - 每次 PR 控制拆分粒度（例如一次只拆出一个 Tab 或一个大功能块），并配合简单的回归路径说明（“本次拆分仅影响 xx Tab 的输入与发送”）。
  - 对已拆分出的 hooks/子组件，在命名与文件路径上保持稳定，避免后续再次大规模移动。

- **已做（第一步）**：
  - 将 `AutoResizeTextarea` 中 mention 解析与 chip 构建抽离到 `controls/interaction-input/mentionUtils.ts`，减少主组件体积并提高复用性。

### 11. API 调用方式统一

- **现状**：绝大多数使用 `DefaultService.*`，仅 SettingsTab 曾用裸 `fetch`（已改为 DefaultService）。
- **风险**：
  - 手写 URL（如 `/api/v1/...`）容易与后端路由或版本前缀不一致，导致线上才暴露问题。
  - 缺失统一的错误处理与类型约束，不利于后续做全局 toast、重试等能力。
- **建议（编码规范）**：
  - 新功能 **一律优先使用** 生成的 `DefaultService`/各 Service，不再手写 `fetch` + 字符串路径。
  - 仅在极少数场景（如第三方 webhook、中转代理）允许使用裸 `fetch`，并在代码上方用注释说明原因。
  - 不在组件内直接使用 `fetch`，而是封装到 `frontend/src/lib/api/xxx.ts` 或对应 Service wrapper 中，组件只关心“调用哪个方法”。
- **建议（基础设施）**：
  - 如有需要，可在 `lib/client.ts` 或单独文件中，封装统一的 `request`/`mutation` helper（例如整合 React Query、错误提示、埋点等），再由 `DefaultService` 在内部复用。
  - 为常用的实体（如 Project、Episode、Asset）提供对应 `useProjectQuery`、`useProjectMutation` 等 hooks，对外只暴露 hooks，不暴露底层 Service 调用细节。
  - 在代码评审 Checklist 中增加一项：“**是否使用了生成的 Service，而不是手写 fetch**”，借此约束新增代码。

### 12. 国际化 (i18n)

- **现状**：已接入 i18next，部分文案使用 `useTranslation`，同时存在大量中文硬编码。
- **建议**：若计划多语言，逐步将界面文案迁到 i18n key；若短期仅中文，可在文档中说明当前策略，避免混用导致维护成本增加。

---

## 七、测试与质量

### 13. React Query 默认配置（已落地）

- **已做**：
  - `QueryProvider` 默认值调整为更保守策略：`staleTime: 1min`、`retry: 1`、`refetchOnReconnect: true`。
  - 在 `useProjects` / `useProject` / `useProjectWorkspace` 上显式配置 `staleTime`、`retry`、`retryDelay`、`refetchOnReconnect`；其中 workspace 查询单独设置 `staleTime: 60s`，避免沿用全局一刀切。

### 14. 端到端与关键路径（进行中）

- **已做（基线）**：
  - 新增 Playwright 配置：`frontend/playwright.config.ts`。
  - 新增关键路径 E2E：`frontend/tests/e2e/project-canvas.spec.ts`（进入项目 → 载入画布 → 新增提示词节点 → 编辑内容 → 触发保存并断言保存请求）。
  - 新增脚本：`frontend/package.json` 中 `e2e` / `e2e:headed`。
- **后续**：补充分镜编辑、素材拖拽、失败重试等场景。

---

## 八、小结优先级

| 优先级 | 项 | 说明 |
|--------|----|------|
| 高 | 项目设置 API 路径 | 已修复 |
| 高 | 项目页 loading/error 与 React Query | 已落地 |
| 高 | 画布 ErrorBoundary | 避免白屏 |
| 中 | API Base 与 env 说明 | 减少部署/联调困惑 |
| 中 | lodash-es 显式依赖 | 依赖健康 |
| 中 | 大组件与动态加载 | 已落地 |
| 中 | 画布 memo 与细粒度订阅 | 已落地 |
| 中 | 大组件拆分（超大类拆 hooks/子组件） | 性能与可维护性 |
| 低 | console → logger、减少 any | 长期可维护性 |
| 低 | i18n 策略统一 | 若有多语言计划 |

如需对某一项做具体改动（例如贴出 patch 或分步实现），可以指定编号或文件路径继续细化。
