Files
Pre_Seg_Server/doc/11-frontend-interaction-state-machines.md
admin c8a78a1038 修复AI模型不可用状态交互
- AI智能分割页禁用不可用SAM2.1模型变体,并在模型状态未可用时阻止推理请求。

- 分割工作区AI自动推理在提交传播前校验模型状态,所有模型不可用时禁用入口,当前权重不可用时禁用开始传播。

- 传播权重下拉标记并禁用不可用权重,避免提交后无结果的假可用状态。

- 补充AI页和工作区模型不可用回归测试,扩展默认测试状态覆盖四个SAM2.1变体。

- 更新前端元素审计、交互状态机、测试计划和Docker/GPU部署说明。
2026-05-07 17:08:40 +08:00

111 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端交互与状态机
本文档记录当前前端真实交互规则,重点覆盖那些不会直接体现在接口契约里的 UI 细节。测试以本文件、`doc/07-current-requirements-freeze.md``doc/09-test-plan.md` 为准。
## 全局状态
| 状态字段 | 所在文件 | 含义 |
|----------|----------|------|
| `activeModule` | `src/store/useStore.ts` | 当前页面模块;登录后默认 `dashboard`。 |
| `currentProject` / `frames` / `currentFrameIndex` | `src/store/useStore.ts` | 当前工作项目、帧序列和当前帧。 |
| `activeTool` | `src/store/useStore.ts` | 工作区当前工具。 |
| `selectedMaskIds` | `src/store/useStore.ts` | 当前选中的 mask id 列表Canvas、本体面板和 AI 页共享。 |
| `activeTemplateId` / `activeClass` | `src/store/useStore.ts` | 当前模板和后续新建 mask 使用的语义类别。 |
| `maskHistory` / `maskFuture` | `src/store/useStore.ts` | 撤销/重做栈。 |
## 工作区工具自动机
| 状态 | 进入事件 | 可用动作 | 退出事件 | 测试 |
|------|----------|----------|----------|------|
| `idle/no-selection` | 初始、`Esc`、左侧“取消选中”、删除 mask、切帧无对应传播结果 | 右侧语义树只设置后续新建类别;清空遮罩作用于当前帧全部 mask | 点击 mask、AI 推送、创建新 mask | `CanvasArea.test.tsx``OntologyInspector.test.tsx` |
| `mask-selected` | `move/edit_polygon` 下点击 mask、新建 mask 完成、AI 候选选中 | 右侧语义树给已选 mask 换类Delete/Backspace/DEL 删除;橡皮擦可扣除;顶点可编辑;创建工具的新几何会并入当前 mask | `Esc`、左侧“取消选中”、删除 mask、切帧无对应传播结果 | `CanvasArea.test.tsx` |
| `polygon-drawing` | `create_polygon` 下点击画布 | 继续加点;三点后 Enter 或点击首点闭合 | Enter/首点在有选中 mask 时并入选中 mask无选中时创建新 mask 并显示边界点;`Esc` 放弃临时点并清选区 | `CanvasArea.test.tsx` |
| `shape-dragging` | `create_rectangle/create_circle` 下按下鼠标 | 拖拽预览形状 | 鼠标释放时有选中 mask 则并入选中 mask无选中时创建新 mask 并显示边界点;切工具取消临时状态 | `CanvasArea.test.tsx` |
| `brush-stroking` | `brush` 且已有 `activeClass` 或当前选中 mask 时按下鼠标 | 采样图像范围内圆形笔触 | 鼠标释放时有选中 mask 则并入选中 mask无选中时创建新的当前类别 mask闭合成中空区域时保留内洞 ring图外落笔不创建`Esc` 取消笔触和选区 | `CanvasArea.test.tsx` |
| `eraser-stroking` | `eraser` 且已有选中 mask 时按下鼠标 | 采样图像范围内圆形笔触 | 鼠标释放从选中 mask 扣除;扣空则删除该 mask`Esc` 取消笔触和选区 | `CanvasArea.test.tsx` |
| `boolean-selecting` | `area_merge/area_remove` | 选择多个 mask主区域黄色实线参与区域红色虚线 | 当前帧执行、所有传播帧、按帧范围、取消、切换工具 | `CanvasArea.test.tsx``VideoWorkspace.test.tsx` |
### 细节规则
- `Esc` 是取消当前交互状态,不是删除:清空 `selectedMaskIds`、临时多边形点、矩形/圆拖拽状态、画笔/橡皮擦笔触和顶点选择;保留已有 mask、当前 `activeClass` 和当前工具。
- 切换到 `create_polygon``create_rectangle``create_circle` 会保留旧 mask 选区;用户若想新建独立 mask需要先按 `Esc` 或点击“取消选中”。
- 多边形、矩形、圆和画笔创建完成后,有选中 mask 时会并入选中 mask无选中 mask 时会自动选中新创建的 mask。
- 画笔和形状创建遵循同一规则:有选中 mask 时并入选中 mask没有选中 mask 时才新建独立 mask。
- 橡皮擦只作用于当前选中 mask不会在无选区时启动。
- 绘制类工具点击已有 mask 时继续绘制,不触发 mask 选择。
## 右侧语义分类树自动机
| 状态 | 点击分类结果 | 后续效果 | 测试 |
|------|--------------|----------|------|
| 无选中 mask | 仅更新 `activeClass` | 后续新建 mask 使用该类别;已有 mask 不变 | `OntologyInspector.test.tsx` |
| 有选中 mask | 更新已选 mask 的 class/label/color同传播链对应 mask 同步更新 | 已保存 mask 标记为 dirty已选 mask 移到前端渲染数组末尾 | `OntologyInspector.test.tsx` |
| 当前 mask 的类别被删除 | 工作区回显时降级为 `maskid:0` “待分类” | 保留几何并等待用户重新分类保存 | `VideoWorkspace.test.tsx` |
## 键盘交互
| 按键 | 前置状态 | 行为 | 测试 |
|------|----------|------|------|
| `Esc` / 左侧“取消选中” | 任意 Canvas 工具 | 取消选中 mask 和临时绘制状态,不删除 mask不清 active class | `CanvasArea.test.tsx``ToolsPalette.test.tsx` |
| `Enter` | 多边形已有至少 3 点 | 闭合并创建新 mask | `CanvasArea.test.tsx` |
| `Delete/Backspace` | 选中顶点 | 删除该顶点,保持 polygon 至少 3 点 | `CanvasArea.test.tsx` |
| `Delete/Backspace` | 选中整块 mask | 删除 mask传播链 mask 走范围确认;人工/AI 帧按确认策略处理 | `CanvasArea.test.tsx``VideoWorkspace.test.tsx` |
| `Ctrl/Cmd+Z` | 工作区且非输入控件聚焦 | 撤销 mask 历史 | `VideoWorkspace.test.tsx``keyboardShortcuts.test.ts` |
| `Ctrl/Cmd+Shift+Z` / `Ctrl/Cmd+Y` | 工作区且非输入控件聚焦 | 重做 mask 历史 | `VideoWorkspace.test.tsx``keyboardShortcuts.test.ts` |
| 左/右方向键 | 工作区时间轴 | 切换上一帧/下一帧 | `VideoWorkspace.test.tsx` |
## 工作区范围选择自动机
`VideoWorkspace``rangeSelectionMode` 区分四类范围选择:`propagation``export``boolean``clear`
| 模式 | 进入事件 | 顶栏状态 | 时间轴行为 | 确认行为 | 测试 |
|------|----------|----------|------------|----------|------|
| `propagation` | 左侧“AI自动推理” | 显示传播权重、向前/向后帧数和“开始传播” | 拖拽/点击设置传播起止帧 | 先校验当前 SAM 2.1 权重状态;可用才保存参考帧 draft/dirty seed 并提交 Celery 传播任务 | `VideoWorkspace.test.tsx` |
| `export` | 打开导出菜单并选择“特定范围帧” | 导出菜单保持打开 | 拖拽/点击设置导出起止帧 | “开始导出”保存待归档 mask 后下载 ZIP | `VideoWorkspace.test.tsx` |
| `boolean` | 区域合并/去除选择“按帧范围选择” | 显示“确认区域合并/确认重叠区域去除” | 拖拽/点击设置布尔操作范围 | 弹最终确认,只同步范围内对应传播帧,保留传播 metadata | `CanvasArea.test.tsx``VideoWorkspace.test.tsx` |
| `clear` | 清空/DEL 选择“按帧范围选择” | 显示“确认清空” | 拖拽/点击设置清空范围 | 弹最终确认;如范围含人工/AI 帧,再询问是否删除这些帧 | `VideoWorkspace.test.tsx` |
取消规则:
- 关闭导出菜单会退出 `export` 范围选择。
- 在布尔范围确认前重新点击“合并选中/从主区域去除”,会取消旧的顶栏范围请求。
- 清空/删除传播链时选择“取消”不会删除任何 mask。
## AI 智能分割自动机
| 状态 | 进入事件 | 主要行为 | 退出事件 | 测试 |
|------|----------|----------|----------|------|
| `no-prompt` | 打开 AI 页或清空提示 | 等待正点/负点/框选 | 放置提示或框选 | `AISegmentation.test.tsx` |
| `box-prompt` | 框选完成 | 仅框选时发送 `box` prompt | 加正/负点后转 interactive | `AISegmentation.test.tsx` |
| `interactive-prompt` | 框选后加点或直接点选 | 发送累计正/负点;负点启用背景过滤 | 空结果移除旧候选 | `AISegmentation.test.tsx` |
| `candidate-selected` | 推理返回 mask 或点击候选 | 可通过语义树换标签;可删除候选 | 推送工作区、删除候选、重新推理 | `AISegmentation.test.tsx` |
| `send-blocked` | 候选缺少语义分类时点击推送 | 显示 error toast不切模块、不改工具 | 选择语义分类 | `AISegmentation.test.tsx` |
| `model-unavailable` | `/api/ai/models/status` 返回所选 SAM 2.1 变体不可用 | 禁用不可用模型按钮和执行按钮;不调用 `/api/ai/predict` | 后端模型状态恢复可用或切换到可用变体 | `AISegmentation.test.tsx` |
## 模板与项目确认流
| 交互 | 状态机 | 测试 |
|------|--------|------|
| 切换激活模板 | 无 mask 直接切换;有任意 mask 时弹确认;确认后删除项目所有本地/后端标注再切换;取消则保持原模板 | `OntologyInspector.test.tsx` |
| 删除模板 | 站内确认后删除;系统默认模板可由演示恢复出厂设置恢复 | `TemplateRegistry.test.tsx`、后端模板/管理员测试 |
| 复制模板 | 鼠标点击复制入口生成当前用户私有副本并保留分类颜色、maskid 和层级 | `TemplateRegistry.test.tsx` |
| 项目复制 | 项目删除按钮旁复制入口;可选“新项目重置”或“全内容复制” | `ProjectLibrary.test.tsx` |
| 演示恢复出厂设置 | 管理员危险区二次确认并要求输入 `RESET_DEMO_FACTORY`;后端也校验 confirmation | `UserAdmin.test.tsx``backend/tests/test_admin.py` |
## 文件与导入导出交互
| 交互 | 状态机 | 测试 |
|------|--------|------|
| 视频/DICOM 上传 | 选择文件后显示上传进度DICOM 显示有效文件数量;上传后继续轮询解析任务进度 | `ProjectLibrary.test.tsx` |
| 显式生成帧/重新生成帧 | 只对有源视频的视频项目显示项目名称编辑状态不显示DICOM 项目不显示;已有帧时显示“重新生成帧”并提示会清空旧帧、标注和 mask入队后轮询解析任务成功后刷新项目列表并立即显示新封面 | `ProjectLibrary.test.tsx` |
| GT Mask 导入 | 选择文件后预览并选择未知 maskid 策略;非法格式返回错误;尺寸不一致最近邻拉伸;导入结果与普通 mask 同体验 | `VideoWorkspace.test.tsx`、后端 AI 测试 |
| 分割结果导出 | 默认当前帧;可选整体/范围;范围可用时间轴;导出前保存待归档 mask按钮带导出图标和绿色强调背景 | `VideoWorkspace.test.tsx``api.test.ts`、后端导出测试 |
## 维护要求
新增或修改前端交互时,应同步做三件事:
1. 更新本文件中对应状态机或规则。
2.`doc/09-test-plan.md` 的覆盖矩阵中写明测试归属。
3. 添加或更新组件测试,至少覆盖状态转移的进入条件、退出条件和副作用。