Sfoglia il codice sorgente

docs: 添加图像注释保存与重现功能的需求文档和测试方案

新增文档:
- docs/需求/图像注释保存与重现功能需求.md - 详细的功能需求文档,包含用户角色、功能需求、用例场景等
- docs/测试/图像注释保存与重现功能测试方案.md - 完整的测试方案,包含24个测量工具的测试用例、7个测试套件共26个测试用例

文档概述:
- 需求文档: 从业务和用户角度描述注释功能,包含9个功能需求(FR-01至FR-09)
- 测试文档: 基于实际代码MeasurementPanel.tsx,列出所有24个真实的测量工具及其测试方案
dengdx 4 settimane fa
parent
commit
ab77b8bfd6

+ 1347 - 0
docs/测试/图像注释保存与重现功能测试方案.md

@@ -0,0 +1,1347 @@
+# 图像注释保存与重现功能测试方案
+
+## 文档信息
+
+- **测试方案版本**: 1.0
+- **创建日期**: 2025-12-16
+- **最后更新**: 2025-12-16
+- **相关需求文档**: [图像注释保存与重现功能需求](../需求/图像注释保存与重现功能需求.md)
+- **相关实现文档**: [保存注释功能实现文档](../实现/保存注释功能实现文档.md)
+
+---
+
+## 1. 测试概述
+
+### 1.1 测试目标
+
+验证图像注释的创建、保存、加载、重现、编辑和删除功能,确保所有类型的注释工具都能正常工作,并且注释数据能够正确持久化和恢复。
+
+### 1.2 测试范围
+
+- 所有注释工具的创建功能
+- 注释自动保存机制
+- 注释数据的加载和重现
+- 注释编辑功能
+- 注释删除功能
+- 注释数据格式验证
+- API调用验证
+- Redux状态管理验证
+
+### 1.3 测试环境
+
+- **浏览器**: Chrome 90+, Edge 90+, Firefox 88+
+- **测试框架**: Cypress E2E
+- **Mock工具**: Cypress Intercept
+- **前端框架**: React + Redux Toolkit
+- **图像工具库**: Cornerstone Tools
+
+---
+
+## 2. 注释工具类型清单
+
+基于实际代码 `src/pages/view/components/MeasurementPanel.tsx`,系统支持以下测量工具:
+
+### 2.1 基础测量工具
+
+| 工具名称 | 工具标识(action) | 图标名称 | 描述 | 优先级 |
+|---------|-----------------|---------|------|--------|
+| **线段测量** | 线段测量 | btn_LineMeasurement | 测量两点之间的直线距离 | P0 |
+| **角度测量** | 角度测量 | btn_AngleMeasurement | 测量三点形成的角度 | P0 |
+| **清除测量** | 清除测量 | btn_ClearMeasurement | 清除所有测量标记 | P0 |
+| **测量校正** | 测量校正 | MeasurementCalibration | 校正测量比例 | P1 |
+
+### 2.2 专业测量工具
+
+| 工具名称 | 工具标识(action) | 图标名称 | 描述 | 优先级 |
+|---------|-----------------|---------|------|--------|
+| **Cobb角** | Cobb角 | btn_Cobbangle | 脊柱侧弯角度测量 | P1 |
+
+### 2.3 宠物专用测量工具
+
+| 工具名称 | 工具标识(action) | 图标名称 | 描述 | 优先级 |
+|---------|-----------------|---------|------|--------|
+| **髋臼水平角** | 髋臼水平角 | btn_DAR | 髋关节发育评估 | P1 |
+| **胫骨平台夹角** | 胫骨平台夹角 | btn_TPA | 膝关节角度测量 | P1 |
+| **髋关节牵引指数** | 髋关节牵引指数 | btn_HDI | 髋关节松弛度评估 | P1 |
+| **髋关节水平角** | 髋关节水平角 | btn_NHA | 髋关节角度测量 | P1 |
+| **心锥比** | 心锥比 | btn_VHS | 心脏大小评估 | P1 |
+| **胫骨平台骨切开术** | 胫骨平台骨切开术 | btn_TPLO | TPLO手术规划 | P2 |
+| **胫骨结节前移术** | 胫骨结节前移术 | btn_TTA | TTA手术规划 | P2 |
+| **胫骨结节前移术5点测量法** | 胫骨结节前移术5点测量法 | btn_TTA2 | TTA手术规划(5点法) | P2 |
+| **水平截骨术** | 水平截骨术 | btn_CBLO | CBLO手术规划 | P2 |
+| **股骨头覆盖率** | 股骨头覆盖率 | btn_DLS | 髋关节覆盖评估 | P2 |
+| **髋臼背覆盖** | 髋臼背覆盖 | btn_DAC | 髋关节覆盖评估 | P2 |
+| **拆线长度测量** | 拆线长度测量 | btn_FoldLine | 折线长度测量 | P1 |
+| **多边形长度测量** | 多边形长度测量 | btn_Polygon | 多边形周长测量 | P1 |
+| **找圆心** | 找圆心 | btn_CenterCircle | 定位圆形中心点 | P1 |
+| **找中线** | 找中线 | btn_CenterLine | 计算中线位置 | P1 |
+| **找中点** | 找中点 | btn_Midpoint | 计算线段中点 | P1 |
+| **直线垂直倾斜度** | 直线垂直倾斜度 | btn_VerticalInclination | 垂直倾斜角度 | P1 |
+| **直线水平倾斜度** | 直线水平倾斜度 | btn_HorizontalInclination | 水平倾斜角度 | P1 |
+| **矩形区域灰度** | 矩形区域灰度 | btn_RectangularGrayscale | 矩形区域灰度分析 | P1 |
+| **直线灰度** | 直线灰度 | btn_LineGrayscale | 直线灰度分布分析 | P1 |
+
+**工具总数**: 24个 (4个基础工具 + 1个专业工具 + 19个宠物专用工具)
+
+**注意**: 这些测量工具主要用于宠物医学影像分析,包括骨科手术规划、心脏评估、髋关节评估等专业应用场景。
+
+---
+
+## 3. 测试套件设计
+
+### 测试套件 1: 注释创建功能测试
+
+**文件路径**: `cypress/e2e/process/annotation-creation.cy.ts`
+
+#### TC-ANN-CREATE-01: 长度测量工具创建
+
+**测试目标**: 验证LengthTool创建长度测量注释
+
+**前置条件**:
+- 已登录系统
+- 已打开图像处理页面
+- 已加载测试图像
+
+**测试步骤**:
+1. 选择长度测量工具
+2. 在图像上点击两个点创建测量线
+3. 验证测量值实时显示
+4. 验证注释保存API被调用
+
+**验证点**:
+- ✅ 工具被正确激活
+- ✅ 可以在图像上创建测量线
+- ✅ 测量值正确显示(格式: "XX.X mm")
+- ✅ API调用: `POST /dr/api/v1/auth/image/{id}/annotation`
+- ✅ 请求体包含正确的toolName: "LengthTool"
+- ✅ 包含handles.points坐标数据
+- ✅ 包含cachedStats.length测量结果
+
+**Mock配置**:
+```typescript
+cy.intercept('POST', '/dr/api/v1/auth/image/*/annotation', {
+  statusCode: 200,
+  body: {
+    code: '0x000000',
+    description: 'Success',
+    data: {}
+  }
+}).as('saveAnnotation');
+```
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-CREATE-02: 角度测量工具创建
+
+**测试目标**: 验证AngleTool创建角度测量注释
+
+**前置条件**: 同TC-ANN-CREATE-01
+
+**测试步骤**:
+1. 选择角度测量工具
+2. 在图像上点击三个点创建角度测量
+3. 验证角度值实时显示
+4. 验证注释保存API被调用
+
+**验证点**:
+- ✅ 工具被正确激活
+- ✅ 可以在图像上创建角度测量
+- ✅ 角度值正确显示(格式: "XX.X°")
+- ✅ toolName: "AngleTool"
+- ✅ handles.points包含3个坐标点
+- ✅ cachedStats.angle包含角度值
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-CREATE-03: 文本标签工具创建
+
+**测试目标**: 验证LabelTool创建文本标注
+
+**前置条件**: 同TC-ANN-CREATE-01
+
+**测试步骤**:
+1. 选择文本标签工具
+2. 在图像上点击位置
+3. 输入文本内容: "测试标注"
+4. 确认输入
+5. 验证注释保存API被调用
+
+**验证点**:
+- ✅ 工具被正确激活
+- ✅ 可以在图像上放置文本标签
+- ✅ 文本内容正确显示
+- ✅ toolName: "LabelTool"
+- ✅ label字段包含文本内容
+- ✅ handles.textBox包含文本框位置
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-CREATE-04: Cobb角测量工具创建
+
+**测试目标**: 验证Cobb角测量工具创建专业测量注释
+
+**前置条件**: 同TC-ANN-CREATE-01
+
+**测试步骤**:
+1. 选择Cobb角测量工具
+2. 按照工具要求标记脊柱关键点
+3. 验证Cobb角度值自动计算并显示
+4. 验证注释保存API被调用
+
+**验证点**:
+- ✅ 工具被正确激活
+- ✅ 可以标记所有必需的解剖点
+- ✅ Cobb角度值正确计算并显示
+- ✅ action: "Cobb角"
+- ✅ handles.points包含脊柱关键点
+- ✅ cachedStats包含角度值
+- ✅ 包含元数据: viewPlaneNormal, viewUp等
+
+**优先级**: P1 (中)
+
+---
+
+#### TC-ANN-CREATE-05: 宠物专用测量工具创建(髋关节水平角)
+
+**测试目标**: 验证宠物专用测量工具(以髋关节水平角为例)创建专业测量
+
+**前置条件**: 同TC-ANN-CREATE-01
+
+**测试步骤**:
+1. 选择髋关节水平角测量工具
+2. 按照工具要求标记关键解剖点
+3. 验证角度值自动计算并显示
+4. 验证注释保存API被调用
+
+**验证点**:
+- ✅ 工具被正确激活
+- ✅ 可以标记所有必需的解剖点
+- ✅ 角度值正确计算并显示
+- ✅ action: "髋关节水平角"
+- ✅ handles.points包含关键解剖点
+- ✅ cachedStats包含测量结果
+- ✅ 包含元数据: viewPlaneNormal, viewUp等
+
+**优先级**: P1 (中)
+
+**注**: 其他宠物专用测量工具(如胫骨平台夹角、心锥比、矩形区域灰度等)的测试方法类似,主要验证:
+- 工具正确激活
+- 关键点标记
+- 测量结果计算
+- 注释保存
+
+---
+
+### 测试套件 2: 注释保存功能测试
+
+**文件路径**: `cypress/e2e/process/annotation-save.cy.ts`
+
+#### TC-ANN-SAVE-01: 自动保存机制验证
+
+**测试目标**: 验证注释创建后自动保存
+
+**前置条件**: 同TC-ANN-CREATE-01
+
+**测试步骤**:
+1. 创建一个长度测量注释
+2. 等待保存API调用
+3. 验证API请求体数据格式
+
+**验证点**:
+- ✅ 创建注释后1秒内触发保存API
+- ✅ API请求方法: POST
+- ✅ API路径: `/dr/api/v1/auth/image/{sopInstanceUid}/annotation`
+- ✅ 请求体为JSON格式
+- ✅ 包含必需字段: id, toolName, sopInstanceUid, handles, metadata
+- ✅ 包含时间戳: createdAt, updatedAt
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-SAVE-02: 防抖保存机制
+
+**测试目标**: 验证编辑注释时的防抖保存
+
+**前置条件**: 已创建一个注释
+
+**测试步骤**:
+1. 拖拽注释手柄修改位置
+2. 连续快速拖拽多次
+3. 验证保存API调用次数
+
+**验证点**:
+- ✅ 连续修改不会立即保存
+- ✅ 停止修改后1秒触发保存
+- ✅ 只发送一次保存请求(防抖)
+- ✅ 请求体包含最新的修改数据
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-SAVE-03: 批量保存优化
+
+**测试目标**: 验证多个注释的批量保存
+
+**前置条件**: 同TC-ANN-CREATE-01
+
+**测试步骤**:
+1. 快速创建3个不同类型的注释
+2. 验证保存API调用
+
+**验证点**:
+- ✅ 可以同时创建多个注释
+- ✅ 保存请求合理优化(批量或防抖)
+- ✅ 所有注释数据都被保存
+- ✅ 无重复保存请求
+
+**优先级**: P1 (中)
+
+---
+
+#### TC-ANN-SAVE-04: 保存失败处理
+
+**测试目标**: 验证保存失败时的错误处理
+
+**前置条件**: Mock保存API返回错误
+
+**测试步骤**:
+1. 创建一个注释
+2. Mock API返回500错误
+3. 验证错误处理机制
+
+**验证点**:
+- ✅ 捕获API错误
+- ✅ 显示错误提示(可选)
+- ✅ 注释数据保留在本地
+- ✅ 用户可以重试保存
+- ✅ Redux状态标记为保存失败
+
+**Mock配置**:
+```typescript
+cy.intercept('POST', '/dr/api/v1/auth/image/*/annotation', {
+  statusCode: 500,
+  body: {
+    code: '0x000001',
+    description: 'Internal Server Error'
+  }
+}).as('saveAnnotationFail');
+```
+
+**优先级**: P0 (高)
+
+---
+
+### 测试套件 3: 注释加载和重现功能测试
+
+**文件路径**: `cypress/e2e/process/annotation-load.cy.ts`
+
+#### TC-ANN-LOAD-01: 自动加载注释
+
+**测试目标**: 验证打开图像时自动加载注释
+
+**前置条件**:
+- 已登录系统
+- Mock注释数据
+
+**测试步骤**:
+1. 打开图像处理页面
+2. 验证加载注释API被调用
+3. 验证注释显示在图像上
+
+**验证点**:
+- ✅ 图像加载完成后立即调用获取注释API
+- ✅ API路径: `GET /dr/api/v1/auth/image/{sopInstanceUid}/annotation`
+- ✅ 返回的注释数据被正确解析
+- ✅ 所有注释显示在图像上
+- ✅ 注释位置准确
+- ✅ 测量值正确显示
+
+**Mock数据示例**:
+```json
+{
+  "code": "0x000000",
+  "description": "Success",
+  "data": [
+    {
+      "id": "ann-001",
+      "toolName": "LengthTool",
+      "sopInstanceUid": "1.2.3.4.5",
+      "handles": {
+        "points": [
+          {"x": 100, "y": 100, "z": 0},
+          {"x": 200, "y": 200, "z": 0}
+        ]
+      },
+      "metadata": {
+        "viewPlaneNormal": [0, 0, 1],
+        "viewUp": [0, -1, 0],
+        "FrameOfReferenceUID": "1.2.3",
+        "referencedImageId": "image-1"
+      },
+      "cachedStats": {
+        "length": 141.42
+      },
+      "createdAt": "2025-12-16T10:00:00Z",
+      "updatedAt": "2025-12-16T10:00:00Z"
+    }
+  ]
+}
+```
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-LOAD-02: 加载多个注释
+
+**测试目标**: 验证同时加载多个不同类型的注释
+
+**前置条件**: Mock包含3个不同类型注释的数据
+
+**测试步骤**:
+1. 打开图像
+2. 验证所有注释都被加载和显示
+
+**验证点**:
+- ✅ 所有类型的注释都能正确加载
+- ✅ LengthTool注释正确显示
+- ✅ AngleTool注释正确显示
+- ✅ LabelTool注释正确显示
+- ✅ 注释顺序与数据顺序一致
+- ✅ 不同注释互不干扰
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-LOAD-03: 空注释数据处理
+
+**测试目标**: 验证图像无注释时的处理
+
+**前置条件**: Mock返回空注释列表
+
+**测试步骤**:
+1. 打开图像
+2. 验证处理空数据的逻辑
+
+**验证点**:
+- ✅ API返回空数组不报错
+- ✅ 图像正常显示
+- ✅ 无注释显示在图像上
+- ✅ 用户可以创建新注释
+
+**Mock配置**:
+```typescript
+cy.intercept('GET', '/dr/api/v1/auth/image/*/annotation', {
+  statusCode: 200,
+  body: {
+    code: '0x000000',
+    description: 'Success',
+    data: []
+  }
+}).as('getEmptyAnnotations');
+```
+
+**优先级**: P1 (中)
+
+---
+
+#### TC-ANN-LOAD-04: 加载失败处理
+
+**测试目标**: 验证加载注释失败时的处理
+
+**前置条件**: Mock API返回错误
+
+**测试步骤**:
+1. 打开图像
+2. Mock API返回500错误
+3. 验证错误处理
+
+**验证点**:
+- ✅ 捕获API错误
+- ✅ 图像仍然正常显示
+- ✅ 显示错误提示(可选)
+- ✅ 用户可以重试加载
+- ✅ 不影响其他功能
+
+**优先级**: P1 (中)
+
+---
+
+#### TC-ANN-LOAD-05: 注释数据验证
+
+**测试目标**: 验证加载的注释数据格式验证
+
+**前置条件**: Mock包含格式错误的注释数据
+
+**测试步骤**:
+1. Mock返回缺少必需字段的注释
+2. 验证数据验证机制
+
+**验证点**:
+- ✅ 识别数据格式错误
+- ✅ 跳过无效注释
+- ✅ 继续加载有效注释
+- ✅ 记录错误日志
+- ✅ 不崩溃或阻塞
+
+**优先级**: P1 (中)
+
+---
+
+### 测试套件 4: 注释编辑功能测试
+
+**文件路径**: `cypress/e2e/process/annotation-edit.cy.ts`
+
+#### TC-ANN-EDIT-01: 拖拽修改注释位置
+
+**测试目标**: 验证通过拖拽手柄修改注释
+
+**前置条件**: 已加载包含注释的图像
+
+**测试步骤**:
+1. 选择一个长度测量注释
+2. 拖拽手柄修改端点位置
+3. 验证测量值更新
+4. 验证保存API被调用
+
+**验证点**:
+- ✅ 可以选中注释
+- ✅ 手柄可拖拽
+- ✅ 测量值实时更新
+- ✅ 触发保存API(防抖)
+- ✅ 新位置数据正确保存
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-EDIT-02: 修改文本标签内容
+
+**测试目标**: 验证修改文本标注的内容
+
+**前置条件**: 已加载包含文本标注的图像
+
+**测试步骤**:
+1. 双击文本标注
+2. 修改文本内容
+3. 确认修改
+4. 验证保存API被调用
+
+**验证点**:
+- ✅ 可以编辑文本内容
+- ✅ 文本立即更新显示
+- ✅ 触发保存API
+- ✅ 新文本内容正确保存
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-EDIT-03: 并发编辑冲突处理
+
+**测试目标**: 验证多用户编辑冲突的处理
+
+**前置条件**: Mock服务器返回版本冲突
+
+**测试步骤**:
+1. 修改一个注释
+2. Mock服务器返回版本冲突错误
+3. 验证冲突处理机制
+
+**验证点**:
+- ✅ 检测到版本冲突
+- ✅ 提示用户冲突情况
+- ✅ 提供冲突解决选项(可选)
+- ✅ 防止数据丢失
+
+**优先级**: P2 (低)
+
+---
+
+### 测试套件 5: 注释删除功能测试
+
+**文件路径**: `cypress/e2e/process/annotation-delete.cy.ts`
+
+#### TC-ANN-DELETE-01: 单个注释删除
+
+**测试目标**: 验证删除单个注释
+
+**前置条件**: 已加载包含注释的图像
+
+**测试步骤**:
+1. 选中一个注释
+2. 按Delete键或点击删除按钮
+3. 确认删除(如有提示)
+4. 验证注释被删除
+
+**验证点**:
+- ✅ 可以选中注释
+- ✅ 删除操作生效
+- ✅ 注释从图像上消失
+- ✅ 调用删除API(如果是已保存的注释)
+- ✅ Redux状态更新
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-DELETE-02: 批量删除注释
+
+**测试目标**: 验证批量删除多个注释
+
+**前置条件**: 已加载包含多个注释的图像
+
+**测试步骤**:
+1. 选择多个注释(Ctrl+点击)
+2. 执行批量删除
+3. 验证所有选中的注释被删除
+
+**验证点**:
+- ✅ 可以多选注释
+- ✅ 批量删除生效
+- ✅ 所有选中注释被删除
+- ✅ 未选中注释保留
+- ✅ 批量调用删除API或单次批量删除
+
+**优先级**: P1 (中)
+
+---
+
+#### TC-ANN-DELETE-03: 删除确认提示
+
+**测试目标**: 验证删除确认对话框
+
+**前置条件**: 配置启用删除确认
+
+**测试步骤**:
+1. 尝试删除注释
+2. 验证弹出确认对话框
+3. 点击取消
+4. 验证注释未被删除
+5. 再次删除并确认
+6. 验证注释被删除
+
+**验证点**:
+- ✅ 删除前显示确认对话框
+- ✅ 取消操作保留注释
+- ✅ 确认操作删除注释
+- ✅ 对话框文本清晰明确
+
+**优先级**: P1 (中)
+
+---
+
+### 测试套件 6: 数据格式和API测试
+
+**文件路径**: `cypress/e2e/process/annotation-api.cy.ts`
+
+#### TC-ANN-API-01: 保存API请求格式验证
+
+**测试目标**: 验证保存注释的API请求格式
+
+**前置条件**: 已创建注释
+
+**测试步骤**:
+1. 拦截保存API请求
+2. 验证请求格式
+
+**验证点**:
+- ✅ 请求方法: POST
+- ✅ Content-Type: application/json
+- ✅ 请求体包含所有必需字段
+- ✅ sopInstanceUid正确
+- ✅ toolName正确
+- ✅ handles数据格式正确
+- ✅ metadata数据格式正确
+- ✅ 时间戳格式正确(ISO 8601)
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-API-02: 获取API响应格式验证
+
+**测试目标**: 验证获取注释的API响应处理
+
+**前置条件**: Mock正确格式的响应
+
+**测试步骤**:
+1. 打开图像触发获取API
+2. 验证响应数据处理
+
+**验证点**:
+- ✅ 正确解析响应JSON
+- ✅ 正确处理data数组
+- ✅ 正确反序列化注释对象
+- ✅ 坐标数据正确转换
+- ✅ 元数据正确恢复
+
+**优先级**: P0 (高)
+
+---
+
+#### TC-ANN-API-03: API错误码处理
+
+**测试目标**: 验证各种API错误码的处理
+
+**前置条件**: Mock不同错误响应
+
+**测试步骤**:
+1. Mock不同错误码(401, 403, 404, 500等)
+2. 验证错误处理逻辑
+
+**验证点**:
+- ✅ 401: 提示重新登录
+- ✅ 403: 提示权限不足
+- ✅ 404: 提示资源不存在
+- ✅ 500: 提示服务器错误
+- ✅ 网络错误: 提示网络问题
+- ✅ 所有错误都有用户友好提示
+
+**优先级**: P1 (中)
+
+---
+
+### 测试套件 7: 性能和边界测试
+
+**文件路径**: `cypress/e2e/process/annotation-performance.cy.ts`
+
+#### TC-ANN-PERF-01: 大量注释加载性能
+
+**测试目标**: 验证加载大量注释时的性能
+
+**前置条件**: Mock包含100个注释的数据
+
+**测试步骤**:
+1. 打开包含100个注释的图像
+2. 测量加载和渲染时间
+
+**验证点**:
+- ✅ 加载时间 < 3秒
+- ✅ 所有注释正确显示
+- ✅ UI不卡顿
+- ✅ 内存使用合理
+
+**优先级**: P1 (中)
+
+---
+
+#### TC-ANN-PERF-02: 注释数据大小限制
+
+**测试目标**: 验证注释数据大小限制
+
+**前置条件**: 尝试创建超大注释
+
+**测试步骤**:
+1. 创建包含大量坐标点的注释
+2. 验证大小限制机制
+
+**验证点**:
+- ✅ 单个注释 < 100KB
+- ✅ 超过限制时提示用户
+- ✅ 防止创建过大的注释
+
+**优先级**: P2 (低)
+
+---
+
+#### TC-ANN-PERF-03: 并发操作性能
+
+**测试目标**: 验证快速连续操作的性能
+
+**前置条件**: 已加载图像
+
+**测试步骤**:
+1. 快速连续创建多个注释
+2. 快速连续修改注释
+3. 验证系统响应
+
+**验证点**:
+- ✅ 操作响应及时
+- ✅ 防抖机制有效
+- ✅ 不会重复保存
+- ✅ UI保持流畅
+
+**优先级**: P1 (中)
+
+---
+
+## 4. 测试数据准备
+
+### 4.1 Mock注释数据模板
+
+#### 长度测量注释
+```json
+{
+  "id": "length-001",
+  "toolName": "LengthTool",
+  "sopInstanceUid": "1.2.840.10008.5.1.4.1.1.2.1",
+  "handles": {
+    "points": [
+      {"x": 100, "y": 100, "z": 0},
+      {"x": 200, "y": 200, "z": 0}
+    ]
+  },
+  "metadata": {
+    "viewPlaneNormal": [0, 0, 1],
+    "viewUp": [0, -1, 0],
+    "FrameOfReferenceUID": "1.2.3.4.5",
+    "referencedImageId": "wadouri:http://example.com/image.dcm"
+  },
+  "cachedStats": {
+    "length": 141.42
+  },
+  "label": "Length Measurement",
+  "createdAt": "2025-12-16T10:00:00.000Z",
+  "updatedAt": "2025-12-16T10:00:00.000Z",
+  "userId": "user-001"
+}
+```
+
+#### 角度测量注释
+```json
+{
+  "id": "angle-001",
+  "toolName": "AngleTool",
+  "sopInstanceUid": "1.2.840.10008.5.1.4.1.1.2.1",
+  "handles": {
+    "points": [
+      {"x": 100, "y": 100, "z": 0},
+      {"x": 150, "y": 150, "z": 0},
+      {"x": 200, "y": 100, "z": 0}
+    ]
+  },
+  "metadata": {
+    "viewPlaneNormal": [0, 0, 1],
+    "viewUp": [0, -1, 0],
+    "FrameOfReferenceUID": "1.2.3.4.5",
+    "referencedImageId": "wadouri:http://example.com/image.dcm"
+  },
+  "cachedStats": {
+    "angle": 90.0
+  },
+  "label": "Angle Measurement",
+  "createdAt": "2025-12-16T10:01:00.000Z",
+  "updatedAt": "2025-12-16T10:01:00.000Z",
+  "userId": "user-001"
+}
+```
+
+#### 文本标注
+```json
+{
+  "id": "label-001",
+  "toolName": "LabelTool",
+  "sopInstanceUid": "1.2.840.10008.5.1.4.1.1.2.1",
+  "handles": {
+    "points": [
+      {"x": 150, "y": 150, "z": 0}
+    ],
+    "textBox": {"x": 160, "y": 150}
+  },
+  "metadata": {
+    "viewPlaneNormal": [0, 0, 1],
+    "viewUp": [0, -1, 0],
+    "FrameOfReferenceUID": "1.2.3.4.5",
+    "referencedImageId": "wadouri:http://example.com/image.dcm"
+  },
+  "label": "疑似结节",
+  "createdAt": "2025-12-16T10:02:00.000Z",
+  "updatedAt": "2025-12-16T10:02:00.000Z",
+  "userId": "user-001"
+}
+```
+
+### 4.2 Mock Handlers
+
+#### 文件: `cypress/support/mock/handlers/annotation.ts`
+
+```typescript
+/**
+ * Mock获取注释成功
+ */
+export const mockGetAnnotationsSuccess = (annotations: any[]) => {
+  cy.intercept('GET', '/dr/api/v1/auth/image/*/annotation', {
+    statusCode: 200,
+    body: {
+      code: '0x000000',
+      description: 'Success',
+      data: annotations
+    }
+  }).as('getAnnotations');
+};
+
+/**
+ * Mock保存注释成功
+ */
+export const mockSaveAnnotationSuccess = () => {
+  cy.intercept('POST', '/dr/api/v1/auth/image/*/annotation', {
+    statusCode: 200,
+    body: {
+      code: '0x000000',
+      description: 'Success',
+      data: {}
+    }
+  }).as('saveAnnotation');
+};
+
+/**
+ * Mock删除注释成功
+ */
+export const mockDeleteAnnotationSuccess = () => {
+  cy.intercept('DELETE', '/dr/api/v1/auth/image/*/annotation/*', {
+    statusCode: 200,
+    body: {
+      code: '0x000000',
+      description: 'Success',
+      data: {}
+    }
+  }).as('deleteAnnotation');
+};
+
+/**
+ * Mock API失败
+ */
+export const mockAnnotationAPIFail = (statusCode: number = 500) => {
+  cy.intercept('**/annotation**', {
+    statusCode: statusCode,
+    body: {
+      code: '0x000001',
+      description: 'Internal Server Error'
+    }
+  }).as('annotationAPIFail');
+};
+```
+
+---
+
+## 5. Page Object Model
+
+### ProcessPage扩展
+
+**文件**: `cypress/support/pageObjects/ProcessPage.ts`
+
+```typescript
+class ProcessPage {
+  // 工具选择
+  selectLengthTool() {
+    cy.get('[data-testid="length-tool-btn"]').click();
+  }
+
+  selectAngleTool() {
+    cy.get('[data-testid="angle-tool-btn"]').click();
+  }
+
+  selectLabelTool() {
+    cy.get('[data-testid="label-tool-btn"]').click();
+  }
+
+  selectAreaTool() {
+    cy.get('[data-testid="area-tool-btn"]').click();
+  }
+
+  // 注释操作
+  createLengthAnnotation(point1: {x: number, y: number}, point2: {x: number, y: number}) {
+    this.selectLengthTool();
+    cy.get('.viewport-canvas').click(point1.x, point1.y);
+    cy.get('.viewport-canvas').click(point2.x, point2.y);
+  }
+
+  createAngleAnnotation(
+    point1: {x: number, y: number},
+    point2: {x: number, y: number},
+    point3: {x: number, y: number}
+  ) {
+    this.selectAngleTool();
+    cy.get('.viewport-canvas').click(point1.x, point1.y);
+    cy.get('.viewport-canvas').click(point2.x, point2.y);
+    cy.get('.viewport-canvas').click(point3.x, point3.y);
+  }
+
+  createLabelAnnotation(position: {x: number, y: number}, text: string) {
+    this.selectLabelTool();
+    cy.get('.viewport-canvas').click(position.x, position.y);
+    cy.get('input[type="text"]').type(text);
+    cy.get('input[type="text"]').type('{enter}');
+  }
+
+  // 验证注释显示
+  verifyAnnotationVisible(toolName: string) {
+    cy.get(`.annotation-${toolName.toLowerCase()}`).should('be.visible');
+  }
+
+  verifyMeasurementValue(value: string) {
+    cy.get('.measurement-value').should('contain', value);
+  }
+
+  // 注释编辑
+  selectAnnotation(annotationId: string) {
+    cy.get(`[data-annotation-id="${annotationId}"]`).click();
+  }
+
+  deleteSelectedAnnotation() {
+    cy.get('body').type('{del}');
+  }
+
+  // Redux状态验证
+  verifyAnnotationInStore(annotationId: string) {
+    cy.window().its('store').invoke('getState')
+      .its('annotations').its('list')
+      .should('contain', annotationId);
+  }
+
+  // API调用验证
+  waitForSaveAnnotation() {
+    cy.wait('@saveAnnotation');
+  }
+
+  waitForLoadAnnotations() {
+    cy.wait('@getAnnotations');
+  }
+
+  verifyAnnotationCount(count: number) {
+    cy.get('.annotation-item').should('have.length', count);
+  }
+}
+
+export default ProcessPage;
+```
+
+---
+
+## 6. 测试执行计划
+
+### 第一阶段: 核心功能测试 (优先级: P0)
+
+**时间**: 3-4天
+
+1. ✅ TC-ANN-CREATE-01: 长度测量工具创建
+2. ✅ TC-ANN-CREATE-02: 角度测量工具创建
+3. ✅ TC-ANN-CREATE-03: 文本标签工具创建
+4. ✅ TC-ANN-SAVE-01: 自动保存机制
+5. ✅ TC-ANN-SAVE-02: 防抖保存机制
+6. ✅ TC-ANN-SAVE-04: 保存失败处理
+7. ✅ TC-ANN-LOAD-01: 自动加载注释
+8. ✅ TC-ANN-LOAD-02: 加载多个注释
+9. ✅ TC-ANN-EDIT-01: 拖拽修改注释
+10. ✅ TC-ANN-EDIT-02: 修改文本内容
+11. ✅ TC-ANN-DELETE-01: 单个注释删除
+12. ✅ TC-ANN-API-01: 保存API格式验证
+13. ✅ TC-ANN-API-02: 获取API响应验证
+
+### 第二阶段: 扩展功能测试 (优先级: P1)
+
+**时间**: 2-3天
+
+14. ✅ TC-ANN-CREATE-04: 面积测量工具
+15. ✅ TC-ANN-CREATE-05: 髋关节角度测量
+16. ✅ TC-ANN-SAVE-03: 批量保存优化
+17. ✅ TC-ANN-LOAD-03: 空注释数据处理
+18. ✅ TC-ANN-LOAD-04: 加载失败处理
+19. ✅ TC-ANN-LOAD-05: 数据验证
+20. ✅ TC-ANN-DELETE-02: 批量删除
+21. ✅ TC-ANN-DELETE-03: 删除确认
+22. ✅ TC-ANN-API-03: 错误码处理
+23. ✅ TC-ANN-PERF-01: 大量注释性能
+24. ✅ TC-ANN-PERF-03: 并发操作性能
+
+### 第三阶段: 边界和优化测试 (优先级: P2)
+
+**时间**: 1-2天
+
+25. ✅ TC-ANN-EDIT-03: 并发编辑冲突
+26. ✅ TC-ANN-PERF-02: 数据大小限制
+27. 浏览器兼容性测试
+28. 性能基准测试
+
+---
+
+## 7. 测试覆盖率目标
+
+- **功能覆盖**: 100% - 所有注释类型和操作
+- **场景覆盖**:
+  - 正常场景: 100%
+  - 边界场景: 90%+
+  - 异常场景: 85%+
+- **API覆盖**: 100% - 所有注释相关API
+- **工具覆盖**: 100% - 所有24种测量工具
+
+---
+
+## 8. 验收标准
+
+### 8.1 功能验收
+
+- [ ] 所有P0测试用例通过 (100%)
+- [ ] 至少90%的P1测试用例通过
+- [ ] 所有注释工具可正常创建注释
+- [ ] 注释保存和加载功能稳定
+- [ ] 注释编辑和删除功能正常
+- [ ] API调用格式正确
+
+### 8.2 性能验收
+
+- [ ] 单个注释创建响应时间 < 100ms
+- [ ] 注释保存时间 < 1s
+- [ ] 加载50个注释 < 1s
+- [ ] 加载200个注释 < 5s
+- [ ] UI操作流畅,无明显卡顿
+
+### 8.3 稳定性验收
+
+- [ ] 所有测试用例可重复执行
+- [ ] 无随机失败的测试
+- [ ] 错误处理机制完善
+- [ ] 无内存泄漏
+- [ ] 长时间运行稳定
+
+### 8.4 用户体验验收
+
+- [ ] 工具选择直观
+- [ ] 注释创建流畅
+- [ ] 测量值准确显示
+- [ ] 错误提示清晰
+- [ ] 操作可撤销(如适用)
+
+---
+
+## 9. 风险评估
+
+### 9.1 技术风险
+
+| 风险项 | 影响 | 概率 | 缓解措施 |
+|--------|------|------|----------|
+| Cornerstone Tools集成问题 | 高 | 中 | 深入学习Cornerstone API,准备降级方案 |
+| 坐标系转换错误 | 高 | 中 | 详细测试各种图像类型,验证坐标精度 |
+| 大数据量性能问题 | 中 | 中 | 实现虚拟化渲染,分批加载 |
+| 浏览器兼容性问题 | 中 | 低 | 多浏览器测试,使用polyfill |
+
+### 9.2 业务风险
+
+| 风险项 | 影响 | 概率 | 缓解措施 |
+|--------|------|------|----------|
+| 需求变更 | 中 | 中 | 模块化设计,易于扩展 |
+| 用户接受度低 | 中 | 低 | 用户测试,收集反馈 |
+| 数据丢失 | 高 | 低 | 实现本地缓存,离线支持 |
+
+---
+
+## 10. 测试环境搭建
+
+### 10.1 依赖的Mock Handlers
+
+1. **用户认证**: mockLoginSuccess()
+2. **国际化**: mockI18nSuccess()
+3. **配额**: mockQuotaCheck()
+4. **图像加载**: mockImageLoad()
+5. **注释API**: mockGetAnnotationsSuccess(), mockSaveAnnotationSuccess()
+
+### 10.2 测试数据要求
+
+- 至少3种不同类型的注释数据
+- 包含正常、边界、异常情况的数据
+- 足够的数据量进行性能测试
+
+### 10.3 环境配置
+
+```typescript
+// cypress.config.ts
+export default {
+  e2e: {
+    baseUrl: 'http://localhost:3000',
+    viewportWidth: 1920,
+    viewportHeight: 1080,
+    video: false,
+    defaultCommandTimeout: 10000
+  }
+};
+```
+
+---
+
+## 11. 测试执行指南
+
+### 11.1 运行所有注释测试
+
+```bash
+npx cypress run --spec "cypress/e2e/process/annotation-*.cy.ts"
+```
+
+### 11.2 运行特定测试套件
+
+```bash
+# 创建功能测试
+npx cypress run --spec "cypress/e2e/process/annotation-creation.cy.ts"
+
+# 保存功能测试
+npx cypress run --spec "cypress/e2e/process/annotation-save.cy.ts"
+
+# 加载功能测试
+npx cypress run --spec "cypress/e2e/process/annotation-load.cy.ts"
+```
+
+### 11.3 在Cypress UI中运行
+
+```bash
+npx cypress open
+```
+
+然后选择相应的测试文件。
+
+---
+
+## 12. 测试报告
+
+### 12.1 测试结果记录表
+
+| 测试套件 | 用例总数 | 通过 | 失败 | 跳过 | 通过率 | 执行时间 |
+|---------|---------|------|------|------|--------|----------|
+| 注释创建 | 5 | - | - | - | - | - |
+| 注释保存 | 4 | - | - | - | - | - |
+| 注释加载 | 5 | - | - | - | - | - |
+| 注释编辑 | 3 | - | - | - | - | - |
+| 注释删除 | 3 | - | - | - | - | - |
+| API测试 | 3 | - | - | - | - | - |
+| 性能测试 | 3 | - | - | - | - | - |
+| **总计** | **26** | **-** | **-** | **-** | **-** | **-** |
+
+### 12.2 缺陷记录模板
+
+```
+缺陷ID: BUG-ANN-XXX
+测试用例: TC-ANN-XXX
+严重程度: Critical / Major / Minor
+优先级: P0 / P1 / P2
+
+复现步骤:
+1. ...
+2. ...
+3. ...
+
+实际结果: ...
+预期结果: ...
+附件: (截图/视频)
+```
+
+---
+
+## 13. 附录
+
+### A. 注释数据结构参考
+
+```typescript
+interface AnnotationData {
+  // 基础信息
+  id: string;
+  toolName: string;
+  sopInstanceUid: string;
+
+  // 几何数据
+  handles: {
+    points: Point3[];
+    activeHandleIndex?: number;
+    textBox?: Point2;
+  };
+
+  // 元数据
+  metadata: {
+    viewPlaneNormal: Point3;
+    viewUp: Point3;
+    FrameOfReferenceUID: string;
+    referencedImageId: string;
+  };
+
+  // 计算结果
+  cachedStats?: {
+    length?: number;
+    angle?: number;
+    area?: number;
+  };
+
+  // 显示属性
+  label?: string;
+  highlighted?: boolean;
+  isSelected?: boolean;
+
+  // 时间戳
+  createdAt: string;
+  updatedAt: string;
+  userId?: string;
+}
+```
+
+### B. API接口文档
+
+#### 获取注释
+
+**请求**:
+```
+GET /dr/api/v1/auth/image/{sopInstanceUid}/annotation
+```
+
+**响应**:
+```json
+{
+  "code": "0x000000",
+  "description": "Success",
+  "data": [AnnotationData]
+}
+```
+
+#### 保存注释
+
+**请求**:
+```
+POST /dr/api/v1/auth/image/{sopInstanceUid}/annotation
+Content-Type: application/json
+
+AnnotationData
+```
+
+**响应**:
+```json
+{
+  "code": "0x000000",
+  "description": "Success",
+  "data": {}
+}
+```
+
+#### 删除注释
+
+**请求**:
+```
+DELETE /dr/api/v1/auth/image/{sopInstanceUid}/annotation/{annotationId}
+```
+
+**响应**:
+```json
+{
+  "code": "0x000000",
+  "description": "Success",
+  "data": {}
+}
+```
+
+---
+
+## 文档版本
+
+- **版本**: 1.0.0
+- **创建日期**: 2025-12-16
+- **最后更新**: 2025-12-16
+- **作者**: Cline AI Assistant
+- **审核状态**: ⏳ 待审核
+
+---
+
+**测试方案状态**: ✅ 已完成

+ 484 - 0
docs/需求/图像注释保存与重现功能需求.md

@@ -0,0 +1,484 @@
+# 图像注释保存与重现功能需求文档
+
+## 文档信息
+
+- **文档版本**: 1.0
+- **创建日期**: 2025-12-16
+- **最后更新**: 2025-12-16
+- **相关实现文档**: [保存注释功能实现文档](../实现/保存注释功能实现文档.md)
+
+---
+
+## 1. 功能概述
+
+### 1.1 功能简介
+
+为医学影像工作站提供图像注释的持久化功能,允许用户在图像上添加各种测量和标注,并在后续打开同一图像时自动重现这些注释。
+
+### 1.2 业务价值
+
+- **提高工作效率**: 医生的测量和标注结果可以保存,避免重复操作
+- **支持协作**: 多个医生可以查看和参考之前的注释
+- **临床决策支持**: 历史测量数据为诊断提供参考依据
+- **合规性**: 满足医疗影像归档和审计要求
+
+### 1.3 适用场景
+
+- 放射科医生进行影像测量和标注
+- 多个医生协作诊断同一患者
+- 复查患者历史影像
+- 影像报告撰写和审核
+
+---
+
+## 2. 用户角色
+
+| 角色 | 描述 | 主要需求 |
+|------|------|----------|
+| **放射科医生** | 进行影像诊断的主要用户 | 添加测量、标注,查看历史注释 |
+| **技师** | 进行图像质量检查 | 添加质量标记,测量参数 |
+| **科室主任** | 审核报告 | 查看和验证注释数据 |
+
+---
+
+## 3. 功能需求
+
+### 3.1 注释创建
+
+#### FR-01: 支持多种注释类型
+
+**需求描述**: 系统应支持多种类型的图像注释工具
+
+**注释类型**:
+- ✅ **测量工具**
+  - 长度测量(直线距离)
+  - 角度测量
+  - 面积测量
+  - 圆形/椭圆测量
+- ✅ **标注工具**
+  - 文本标签(自由文本)
+  - 预定义标记(L/R、时间戳等)
+  - 箭头指示
+- ✅ **专业测量工具**
+  - 髋关节角度测量(HipNHAAngleMeasurementTool)
+  - 其他临床专用测量工具
+
+**优先级**: P0(核心功能)
+
+#### FR-02: 实时注释反馈
+
+**需求描述**: 用户创建注释时,应实时显示测量结果
+
+**交互要求**:
+- 绘制过程中实时显示测量值
+- 完成后显示最终测量结果
+- 测量值自动标注在注释旁边
+- 支持测量单位显示(mm、度等)
+
+**优先级**: P0
+
+### 3.2 注释保存
+
+#### FR-03: 自动保存机制
+
+**需求描述**: 用户创建或修改注释后,系统应自动保存到后端
+
+**功能要求**:
+- ✅ 创建注释后立即触发保存
+- ✅ 修改注释后延迟保存(防抖机制)
+- ✅ 删除注释后同步删除
+- ✅ 批量保存优化(避免频繁API调用)
+
+**用户体验**:
+- 保存过程不阻塞用户操作
+- 显示保存状态指示(可选)
+- 保存失败时提示用户
+
+**优先级**: P0
+
+#### FR-04: 离线支持(可选)
+
+**需求描述**: 网络不可用时,注释应暂存本地,待网络恢复后同步
+
+**功能要求**:
+- 检测网络状态
+- 本地缓存未保存的注释
+- 网络恢复后自动同步
+- 同步失败时提示用户
+
+**优先级**: P2(增强功能)
+
+### 3.3 注释加载与重现
+
+#### FR-05: 自动加载注释
+
+**需求描述**: 打开图像时,自动加载并显示该图像的所有注释
+
+**功能要求**:
+- ✅ 图像加载完成后立即获取注释数据
+- ✅ 支持多个注释同时显示
+- ✅ 注释位置和测量结果准确还原
+- ✅ 注释样式和颜色保持一致
+
+**性能要求**:
+- 注释数量 < 50 时,加载时间 < 1秒
+- 注释数量 > 50 时,分批加载或虚拟化渲染
+
+**优先级**: P0
+
+#### FR-06: 注释可见性控制
+
+**需求描述**: 用户可以控制注释的显示和隐藏
+
+**功能要求**:
+- 全局显示/隐藏所有注释
+- 按类型筛选显示(仅测量、仅标注等)
+- 单个注释的显示/隐藏
+- 注释列表管理界面
+
+**优先级**: P1
+
+### 3.4 注释管理
+
+#### FR-07: 注释编辑
+
+**需求描述**: 用户可以编辑已有的注释
+
+**功能要求**:
+- ✅ 选择注释进行编辑
+- ✅ 拖拽调整注释位置和形状
+- ✅ 修改文本内容
+- ✅ 修改后自动保存
+
+**优先级**: P0
+
+#### FR-08: 注释删除
+
+**需求描述**: 用户可以删除不需要的注释
+
+**功能要求**:
+- ✅ 单个注释删除
+- ✅ 批量删除(可选)
+- ✅ 删除确认提示(可配置)
+- ✅ 删除后同步到后端
+
+**优先级**: P0
+
+#### FR-09: 注释导出(可选)
+
+**需求描述**: 支持将注释数据导出为结构化格式
+
+**功能要求**:
+- 导出为JSON格式
+- 导出为PDF报告(包含图像和注释)
+- 导出为DICOM SR(结构化报告)
+
+**优先级**: P3(未来增强)
+
+---
+
+## 4. 用户交互流程
+
+### 4.1 创建和保存注释流程
+
+```mermaid
+sequenceDiagram
+    participant 用户
+    participant 工作站UI
+    participant 后端API
+    participant 数据库
+
+    用户->>工作站UI: 1. 选择注释工具
+    工作站UI->>工作站UI: 2. 激活工具
+    用户->>工作站UI: 3. 在图像上绘制注释
+    工作站UI->>工作站UI: 4. 实时显示测量结果
+    用户->>工作站UI: 5. 完成绘制
+    工作站UI->>后端API: 6. 自动保存注释数据
+    后端API->>数据库: 7. 存储注释
+    数据库-->>后端API: 8. 保存成功
+    后端API-->>工作站UI: 9. 返回确认
+    工作站UI-->>用户: 10. 显示保存状态(可选)
+```
+
+### 4.2 打开图像并重现注释流程
+
+```mermaid
+sequenceDiagram
+    participant 用户
+    participant 工作站UI
+    participant 后端API
+    participant 数据库
+
+    用户->>工作站UI: 1. 打开图像
+    工作站UI->>工作站UI: 2. 加载图像
+    工作站UI->>后端API: 3. 请求注释数据
+    后端API->>数据库: 4. 查询注释
+    数据库-->>后端API: 5. 返回注释数据
+    后端API-->>工作站UI: 6. 返回JSON数据
+    工作站UI->>工作站UI: 7. 解析并重现注释
+    工作站UI-->>用户: 8. 显示图像和注释
+```
+
+---
+
+## 5. 数据要求
+
+### 5.1 注释数据结构
+
+每个注释应包含以下信息:
+
+| 字段 | 类型 | 必需 | 说明 |
+|------|------|------|------|
+| **id** | String | ✅ | 注释唯一标识符 |
+| **toolName** | String | ✅ | 工具类型(LengthTool、AngleTool等) |
+| **sopInstanceUid** | String | ✅ | 关联的图像标识 |
+| **handles** | Object | ✅ | 几何数据(坐标点、文本框位置等) |
+| **metadata** | Object | ✅ | 元数据(视图平面、参考帧等) |
+| **cachedStats** | Object | ❌ | 测量结果(长度、角度、面积等) |
+| **label** | String | ❌ | 显示标签 |
+| **createdAt** | DateTime | ✅ | 创建时间 |
+| **updatedAt** | DateTime | ✅ | 更新时间 |
+| **userId** | String | ❌ | 创建用户 |
+
+### 5.2 数据存储格式
+
+- **格式**: JSON
+- **编码**: UTF-8
+- **大小限制**: 单个注释 < 100KB,单张图像所有注释 < 5MB
+
+---
+
+## 6. 性能要求
+
+### 6.1 响应时间
+
+| 操作 | 目标时间 | 最大时间 |
+|------|----------|----------|
+| 创建注释并保存 | < 500ms | < 1s |
+| 加载注释(< 50个) | < 500ms | < 1s |
+| 加载注释(> 50个) | < 2s | < 5s |
+| 编辑注释 | 即时 | < 100ms |
+| 删除注释 | < 300ms | < 1s |
+
+### 6.2 并发支持
+
+- 支持多用户同时查看同一图像
+- 检测并发编辑冲突
+- 提供冲突解决机制(后保存覆盖/提示用户选择)
+
+---
+
+## 7. 非功能性需求
+
+### 7.1 可用性
+
+- **易用性**: 注释操作应直观,无需培训即可使用
+- **一致性**: 注释交互与其他图像操作保持一致
+- **反馈**: 所有操作应有明确的视觉反馈
+
+### 7.2 可靠性
+
+- **数据完整性**: 确保注释数据不丢失
+- **容错性**: 网络错误时自动重试(最多3次)
+- **数据验证**: 保存前验证数据完整性和有效性
+
+### 7.3 兼容性
+
+- **浏览器**: Chrome 90+, Edge 90+, Firefox 88+
+- **设备**: 桌面端优先,支持触摸屏操作
+- **DICOM标准**: 兼容DICOM Structured Report(未来)
+
+### 7.4 安全性
+
+- **访问控制**: 仅授权用户可查看和编辑注释
+- **数据加密**: 传输过程使用HTTPS加密
+- **审计日志**: 记录注释的创建、修改、删除操作(可选)
+
+---
+
+## 8. 用例场景
+
+### 8.1 用例1: 肺部结节测量
+
+**场景**: 放射科医生在胸部CT图像上测量肺部结节大小
+
+**前置条件**:
+- 用户已登录系统
+- 已打开患者的胸部CT图像
+
+**操作步骤**:
+1. 医生选择"长度测量"工具
+2. 在结节上绘制测量线,获得直径12.5mm
+3. 选择"文本标注"工具,添加备注"疑似恶性结节"
+4. 系统自动保存测量和标注
+5. 医生关闭图像,继续诊断其他患者
+6. 第二天复查时,打开同一图像,自动显示昨天的测量和标注
+
+**预期结果**:
+- ✅ 测量值准确显示为12.5mm
+- ✅ 文本标注正确显示
+- ✅ 注释位置与原始位置一致
+
+### 8.2 用例2: 髋关节角度评估
+
+**场景**: 骨科医生测量髋关节角度以评估发育异常
+
+**前置条件**:
+- 用户已登录系统
+- 已打开患者的髋关节X光图像
+
+**操作步骤**:
+1. 医生选择"髋关节角度测量"工具(HipNHAAngleMeasurementTool)
+2. 按照工具要求标记关键解剖点
+3. 工具自动计算并显示角度值:135°
+4. 医生添加文本标注:"角度正常范围"
+5. 系统自动保存测量结果
+6. 打印报告时,测量数据自动包含在报告中
+
+**预期结果**:
+- ✅ 角度值自动计算准确
+- ✅ 关键点位置准确保存
+- ✅ 可在报告中引用测量数据
+
+### 8.3 用例3: 多医生协作诊断
+
+**场景**: 主治医生的初步诊断需要科室主任审核
+
+**前置条件**:
+- 主治医生已完成初步诊断并添加注释
+- 科室主任有权限查看该患者图像
+
+**操作步骤**:
+1. 主治医生完成测量和标注,保存后离开
+2. 科室主任打开同一图像
+3. 系统自动加载主治医生的所有注释
+4. 主任查看测量值和标注
+5. 主任添加新的注释表示审核意见
+6. 两组注释同时保存在系统中
+
+**预期结果**:
+- ✅ 主治医生的注释完整显示
+- ✅ 主任的新注释也被保存
+- ✅ 可区分不同医生的注释(通过用户ID)
+
+---
+
+## 9. 验收标准
+
+### 9.1 功能验收
+
+- [ ] **FR-01**: 所有列出的注释类型均可正常使用
+- [ ] **FR-02**: 测量工具实时显示测量值,单位正确
+- [ ] **FR-03**: 创建/编辑注释后自动保存,保存成功率 > 99%
+- [ ] **FR-05**: 打开图像后3秒内加载并显示所有注释
+- [ ] **FR-07**: 注释可正常编辑,修改后准确保存
+- [ ] **FR-08**: 注释可正常删除,删除后不再显示
+
+### 9.2 性能验收
+
+- [ ] 保存注释响应时间 < 1秒(90%的情况)
+- [ ] 加载50个注释的时间 < 1秒
+- [ ] 加载200个注释的时间 < 5秒
+- [ ] 编辑注释无明显延迟(< 100ms)
+
+### 9.3 兼容性验收
+
+- [ ] Chrome浏览器测试通过
+- [ ] Edge浏览器测试通过
+- [ ] Firefox浏览器测试通过
+- [ ] 支持4K分辨率显示
+
+### 9.4 稳定性验收
+
+- [ ] 网络断开后,注释数据不丢失(本地缓存)
+- [ ] 网络恢复后,自动同步成功
+- [ ] API错误时,有友好的错误提示
+- [ ] 长时间使用无内存泄漏
+
+---
+
+## 10. 边界条件和约束
+
+### 10.1 数据量限制
+
+| 限制项 | 值 | 说明 |
+|--------|-----|------|
+| 单张图像最大注释数 | 500 | 超过后性能可能下降 |
+| 单个注释最大大小 | 100KB | JSON序列化后 |
+| 单张图像注释总大小 | 5MB | 超过后需优化 |
+| 文本标注最大字符数 | 1000 | 防止滥用 |
+
+### 10.2 异常情况处理
+
+| 异常情况 | 处理策略 |
+|----------|----------|
+| **网络断开** | 本地缓存,网络恢复后重试 |
+| **API超时** | 重试3次,失败后提示用户 |
+| **数据格式错误** | 记录错误日志,跳过该注释,继续加载其他 |
+| **并发编辑冲突** | 后保存覆盖(默认),或提示用户选择 |
+| **存储空间不足** | 提示用户删除旧注释 |
+
+### 10.3 权限控制
+
+- 创建注释:需要图像查看权限
+- 编辑注释:需要编辑权限(可配置为仅创建者可编辑)
+- 删除注释:需要删除权限(可配置为仅创建者可删除)
+- 查看注释:所有有图像查看权限的用户
+
+---
+
+## 11. 未来扩展
+
+### 11.1 规划中的功能(P2-P3)
+
+1. **注释模板**: 预定义常用测量组合
+2. **智能测量**: AI辅助自动识别和测量
+3. **DICOM SR支持**: 导出为DICOM结构化报告
+4. **注释历史版本**: 查看和恢复历史版本
+5. **注释协作**: 多用户实时协作标注
+6. **注释统计**: 生成测量数据的统计报告
+7. **语音标注**: 语音输入文本标注
+
+### 11.2 技术优化方向
+
+1. **性能优化**: 虚拟化渲染大量注释
+2. **离线功能**: 完整的离线支持和冲突解决
+3. **移动端适配**: 支持平板和手机操作
+4. **3D注释**: 支持3D影像(CT/MRI)的体积注释
+
+---
+
+## 12. 参考资料
+
+- [保存注释功能实现文档](../实现/保存注释功能实现文档.md) - 技术实现细节
+- [Cornerstone Tools文档](https://www.cornerstonejs.org/) - 图像工具库
+- DICOM PS3.11 - Media Storage and File Format for Media Interchange
+- DICOM PS3.16 - Content Mapping Resource
+
+---
+
+## 附录
+
+### A. 术语表
+
+| 术语 | 英文 | 说明 |
+|------|------|------|
+| **注释** | Annotation | 在图像上添加的测量、标记或文本 |
+| **测量工具** | Measurement Tool | 用于测量长度、角度、面积等的工具 |
+| **标注** | Label/Mark | 文本或图形标记 |
+| **重现** | Restore/Render | 从存储的数据恢复显示注释 |
+| **序列化** | Serialization | 将注释对象转换为JSON格式 |
+| **反序列化** | Deserialization | 从JSON格式恢复注释对象 |
+| **SOP Instance UID** | SOP Instance UID | DICOM图像唯一标识符 |
+
+### B. 变更历史
+
+| 版本 | 日期 | 作者 | 变更说明 |
+|------|------|------|----------|
+| 1.0 | 2025-12-16 | Development Team | 初始版本,基于实现文档提炼 |
+
+---
+
+**文档状态**: ✅ 已完成  
+**审核状态**: ⏳ 待审核  
+**批准状态**: ⏳ 待批准