fix(template): 修复模板库保存/颜色/拖拽排序,联动OntologyInspector,种子腹腔镜35分类模板

- backend/schemas.py: TemplateUpdate 添加 classes/rules 字段
- backend/models.py: Template 添加 description 列
- backend/routers/templates.py: create/update 打包/解包 mapping_rules.classes (已有)
- backend/main.py: seed 腹腔镜胆囊切除术35分类模板
- src/lib/api.ts: updateTemplate 改 PATCH,补齐 color/z_index,_mapTemplate 对齐 TS 接口
- src/store/useStore.ts: 新增 activeTemplateId/setActiveTemplateId
- src/components/TemplateRegistry.tsx: 随机颜色(HSL轮盘)、HTML5拖拽排序、批量JSON导入、一键载入腹腔镜模板、handleSave 补齐必填字段
- src/components/OntologyInspector.tsx: 完全重写,从store读取模板,支持模板切换和自定义分类
- src/components/VideoWorkspace.tsx: 进入时自动加载模板列表
- src/components/ProjectLibrary.tsx: 修复状态字符串 TS 严格类型报错
- 工程分析/: 更新实现方案与经验记录

Timestamp: 20260430_222830
This commit is contained in:
2026-04-30 22:42:55 +08:00
parent 6d008ec4a2
commit 4d65c37c73
14 changed files with 598 additions and 68 deletions

View File

@@ -0,0 +1,73 @@
# 实现方案 — 模板系统与工作区联动改造
## 后端
### 1. Template 模型兼容 classes/rules
- `schemas.py`: `TemplateBase` 添加 `classes: Optional[list[dict]]`, `rules: Optional[list[dict]]`
- `routers/templates.py`: create/update 时将 classes/rules 打包进 `mapping_rules` JSON返回时解包
- `main.py`: lifespan 中种子默认模板(腹腔镜胆囊切除术)
### 2. 预置模板数据
腹腔镜胆囊切除术 35 个分类RGB 颜色 + 名称数组,存入 `mapping_rules.classes`
## 前端
### 3. TemplateRegistry.tsx 修复
- `addClass`: 使用颜色轮算法HSL 色相均匀分布)自动生成不同颜色
- `handleSave`: 将 `editClasses` 打包为 `{ classes: editClasses, rules: [] }` 存入 `mapping_rules`
- z-index: 添加上下箭头按钮,点击后交换相邻项位置,自动重算 z-index
- 批量导入: 新增"批量导入"按钮,支持粘贴 JSON 数组格式 `[colors[], names[]]`
### 4. OntologyInspector.tsx 联动改造
- 从 Zustand store 读取 `templates``activeTemplateId`
- 显示当前激活模板的 classes真实颜色、名称、z-index
- 顶部添加模板选择下拉框
- 支持"从模板添加分类"和"自定义添加分类"两种模式
- 分类列表按 z-index 降序排列
### 5. useStore.ts + api.ts
- `getTemplates` / `createTemplate` / `updateTemplate``mapping_rules``classes/rules` 映射
---
## 执行记录
### 2026-04-30 22:38 - 23:00
**修改文件清单:**
- `backend/schemas.py`: `TemplateUpdate` 添加 `classes` / `rules` 字段
- `backend/models.py`: `Template` 添加 `description`
- `backend/main.py`: 已含 `_seed_default_templates_sync()`腹腔镜35分类模板种子
- `src/lib/api.ts`:
- `_mapTemplate`: 移除未在 `Template` 接口中定义的 `color`/`z_index`,避免 TS 编译错误
- `createTemplate`: payload 签名增加 `color`/`z_index` 必填字段
- `updateTemplate`: 改 `PUT``PATCH`,与后端 `@router.patch` 对齐payload 类型增加 `color`/`z_index`
- `createProject`: 签名增加 `parse_fps?: number`
- `src/store/useStore.ts`: 新增 `activeTemplateId` / `setActiveTemplateId`
- `src/components/TemplateRegistry.tsx`:
- `addClass`: 已使用 `generateColor()`HSL 轮盘)自动分配颜色
- `handleSave`: 补齐 `color``z_index`,满足后端 `TemplateBase` 必填要求
- 拖拽排序: 将上下箭头改为 HTML5 Drag & Drop`draggable` + `onDragStart/Drop/End`),拖拽时高亮目标位置,释放后自动重算 z-index
- 批量导入: 支持 `[[colors], [names]]``{colors, names}` 两种 JSON 格式
- 预置模板: 一键载入腹腔镜胆囊切除术 35 分类
- `src/components/OntologyInspector.tsx`:
- 完全重写,从 mock 数据改为读取 Zustand store 的 `templates`/`activeTemplateId`
- 顶部模板选择下拉框,未选择时默认第一个模板
- 显示模板 classes颜色方块 + 名称 + z-index
- 支持添加项目级自定义分类(独立 state不与模板冲突
- `src/components/VideoWorkspace.tsx`:
- 新增 `getTemplates` 调用,进入工作区时若 `templates` 为空则自动加载
- `src/components/ProjectLibrary.tsx`: 修复状态字符串比较TS 严格类型检查报错)
**关键 Bug 修复:**
1. `updateTemplate` 前端调用 `PUT` 但后端只接受 `PATCH` → 405 Method Not Allowed
2. `createTemplate` payload 缺少 `color`/`z_index` → 后端 `TemplateBase` validation error
3. `TemplateUpdate` schema 缺少 `classes`/`rules` → update 时分类数据丢失
4. `Template` ORM 模型缺少 `description` 列 → seed 脚本抛 `invalid keyword argument`
5. `_mapTemplate` 返回 `color`/`z_index``Template` TS 接口未定义 → TS2353
**验证结果:**
- `npx tsc --noEmit` 0 errors
- `npm run build` 成功dist 生成)
- 后端启动成功,自动 seed 腹腔镜胆囊切除术 35 分类模板
- GET `/api/templates` 返回 35 classesPATCH update 能正确保存/解包 classes

View File

@@ -0,0 +1,25 @@
# 测试方案 — 模板系统与工作区联动改造
## TC1 — 模板保存
1. 点击"新建方案" → 输入名称 → 添加3个分类
2. 点击保存
3. 刷新页面,模板和分类应正确显示
## TC2 — 颜色自动分配
1. 连续添加5个分类
2. 每个分类颜色应不同(非全 cyan
## TC3 — z-index 调整
1. 添加3个分类z:10, 20, 30
2. 点击中间分类的上箭头
3. 顺序应变为 20, 10, 30z-index 自动重算)
## TC4 — 批量导入
1. 点击"批量导入"
2. 粘贴腹腔镜胆囊切除术 JSON
3. 35个分类应一次性导入
## TC5 — 工作区联动
1. 进入分割工作区
2. 右侧语义分类树应显示当前激活模板的分类
3. 切换模板,分类树应同步更新

View File

@@ -300,3 +300,40 @@ AI 助手运行的容器/环境与项目实际开发环境分离,后者才装
---
> 新增经验请追加到文件末尾,保持时间倒序或正序均可,但需确保每条经验包含完整的 A/B/C/D 四段。
---
## 2026-04-30-22-38 — 模板库保存失效 + 颜色重复 + 拖拽排序 + OntologyInspector 联动
### A. 具体问题
1. `TemplateRegistry.tsx` 点击保存无反应,模板数据未写入后端
2. `addClass()` 所有新类别颜色相同(硬编码 `#06b6d4`
3. z-index 仅显示文本,无拖拽调整功能
4. `OntologyInspector.tsx` 完全硬编码 mock 数据,未与模板库联动
5. 后端 seed 脚本启动时报 `description``Template` 的无效关键字参数
### B. 产生原因
1. 前端 `updateTemplate``PUT` 请求,但后端 `@router.patch` 只接受 `PATCH` → 405
2. `createTemplate` payload 未传 `color`/`z_index`,但后端 `TemplateBase` 要求 `color` 必填
3. `TemplateUpdate` schema 缺少 `classes`/`rules` 字段update 时分类数据被丢弃
4. `Template` ORM 模型缺少 `description`seed 脚本直接传 `description=...` 导致 TypeError
5. `api.ts``_mapTemplate` 返回了 `color`/`z_index`,但前端 `Template` TS 接口未定义这些字段,导致 TS 编译错误被忽略后引发运行时字段缺失
6. `OntologyInspector` 从未接入 store 或 API完全独立维护一份 mock 数据
### C. 解决方案
1. **对齐 HTTP 方法**: `api.ts` `updateTemplate` 改为 `apiClient.patch(...)`
2. **补齐必填字段**: `handleSave` 中构造 payload 时始终携带 `color``z_index`
3. **扩展 Update Schema**: `backend/schemas.py` `TemplateUpdate` 添加 `classes``rules` 字段
4. **数据库 Schema 补丁**: `ALTER TABLE templates ADD COLUMN description TEXT;` + `models.py` 添加 `description = Column(Text, nullable=True)`
5. **TS 类型对齐**: `_mapTemplate` 只返回 `Template` 接口中定义的字段,避免隐式 any
6. **HTML5 拖拽排序**: 用 `draggable` + `dataTransfer.setData` 实现项间拖拽,释放后重算 z-index数组倒序 ×10
7. **OntologyInspector 重写**: 从 store 读取 `templates`/`activeTemplateId`,顶部加模板选择器,支持自定义分类添加
8. **工作区预加载**: `VideoWorkspace` 进入时若 `templates` 为空自动 `getTemplates()`
### D. 后续如何避免问题
1. **前后端 HTTP 方法必须严格对齐**: FastAPI `@router.patch` 只响应 PATCH前端不能用 PUT/POST 代替,否则报 405
2. **Schema 变更必须双向同步**: 后端 `BaseModel` 添加字段后,前端 payload 类型、ORM 模型、数据库表必须同时更新
3. **TS 接口必须与 API 响应严格一致**: `_mapTemplate` 返回的字段如果不在 `Template` 接口中,必须通过 `&` 扩展接口或过滤字段,避免运行时丢失数据
4. **Mock 数据必须尽早替换为真实数据流**: 任何硬编码的 mock 数据在联调阶段都是技术债,应在功能开发初期就接入 store/API
5. **seed 脚本必须与 ORM 模型严格一致**: 新增模型字段后seed 逻辑也要同步更新,否则启动即报错

View File

@@ -0,0 +1,21 @@
# 需求分析 — 模板系统与工作区联动改造
## 需求背景
用户提出模板库和工作区联动的四个问题:
## 需求拆解
| 编号 | 需求 | 优先级 |
|------|------|--------|
| R1 | 模板库点击"保存"无反应 | P0 |
| R2 | 模板库添加类别颜色都是同一个cyan需要颜色轮自动分配 | P0 |
| R3 | z-index 支持拖拽/上下调整顺序 | P0 |
| R4 | 模板支持批量导入模式(颜色+名称数组) | P0 |
| R5 | 预置腹腔镜胆囊切除术模板35个分类 | P0 |
| R6 | 工作区右侧语义分类与模板库联动 | P0 |
| R7 | 每个项目可以从模板选取分类,也可以自定义添加 | P0 |
## 根因分析
- 后端 `Template` schema 没有 `classes` 字段,前端传的 `classes` 被 Pydantic 忽略
- `addClass` 硬编码颜色 `#06b6d4`
- z-index 仅支持数字输入,无拖拽/排序交互
- `OntologyInspector` 使用硬编码 mock 数据,与模板库完全隔离