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

@@ -62,6 +62,7 @@ export async function getProjects(): Promise<Project[]> {
export async function createProject(payload: {
name: string;
description?: string;
parse_fps?: number;
}): Promise<Project> {
const response = await apiClient.post('/api/projects', payload);
const p = response.data;
@@ -92,23 +93,39 @@ export async function deleteProject(id: string): Promise<void> {
}
// Templates
function _mapTemplate(t: any): Template {
const mapping = t.mapping_rules || {};
return {
id: String(t.id),
name: t.name,
description: t.description,
classes: mapping.classes || [],
rules: mapping.rules || [],
createdAt: t.created_at,
updatedAt: t.updated_at,
};
}
export async function getTemplates(): Promise<Template[]> {
const response = await apiClient.get('/api/templates');
return response.data;
return response.data.map(_mapTemplate);
}
export async function createTemplate(payload: {
name: string;
description?: string;
color: string;
z_index: number;
classes?: { name: string; color: string; zIndex: number; category?: string }[];
rules?: any[];
}): Promise<Template> {
const response = await apiClient.post('/api/templates', payload);
return response.data;
return _mapTemplate(response.data);
}
export async function updateTemplate(id: string, payload: Partial<Template>): Promise<Template> {
const response = await apiClient.put(`/api/templates/${id}`, payload);
return response.data;
export async function updateTemplate(id: string, payload: Partial<Template> & { color?: string; z_index?: number }): Promise<Template> {
const response = await apiClient.patch(`/api/templates/${id}`, payload);
return _mapTemplate(response.data);
}
export async function deleteTemplate(id: string): Promise<void> {