# 删除发送任务功能实现文档 ## 概述 本文档详细记录了**删除发送任务**功能的实现过程,包括架构设计、数据流、交互流程和具体实现细节。 ## 功能需求 实现传输队列中的删除功能: - 用户可以在表格中选择一个或多个发送任务 - 点击删除按钮后,弹出确认对话框 - 确认后调用后端接口批量删除选中的任务 - 删除成功后更新 UI 并清空选中状态 ## 1. 架构分析 ### 1.1 涉及的参与者(从粗到细) #### UI 层 - **OutputOperationPanel** (容器组件) - 位置:`src/pages/patient/components/OutputOperationPanel.tsx` - 职责:组织和布局操作面板 - **OutputActionPanel** (操作面板组件) - 位置:`src/pages/patient/components/OutputActionPanel.tsx` - 职责:渲染操作按钮(重试、删除)并处理用户交互 - 修改内容: - 新增 `handleDelete` 方法 - 导入 `Modal` 组件和 `deleteSendJobThunk` - 绑定删除按钮的 onClick 事件 #### 状态管理层 - **sendJobSlice** (Redux Slice) - 位置:`src/states/output/sendJob/slices/sendJobSlice.ts` - 参与者: - `deleteSendJobThunk` - 删除任务的异步 thunk(已存在) - `sendJobEntitiesSlice` - 管理发送任务数据 - `sendJobSelectionSlice` - 管理选中的任务 ID #### API 层 - **sendJobActions** - 位置:`src/API/output/sendJobActions.ts` - 方法:`deleteSendTask(taskIds: string[])` - 调用删除接口(已存在) #### 数据模型层 - **SendJob** (发送任务实体) - 位置:`src/domain/output/sendJob.ts` - 核心属性: - `task_id`: 任务唯一标识 - `patient_name`: 患者姓名 - `status`: 任务状态 ## 2. 交互流程 ### 泳道图 ```mermaid sequenceDiagram participant User as 用户 participant UI as OutputActionPanel participant Modal as 确认对话框 participant Redux as Redux Store participant Thunk as deleteSendJobThunk participant API as deleteSendTask participant Backend as 后端服务 User->>UI: 1. 勾选表格中的任务 UI->>Redux: 2. 更新 selectedIds User->>UI: 3. 点击删除按钮 UI->>UI: 4. 校验 selectedIds.length > 0 alt 无选中任务 UI->>User: 显示警告:请先选择要删除的任务 else 有选中任务 UI->>Modal: 5. 显示确认对话框 Modal->>User: 展示:确定要删除 N 个任务吗? alt 用户取消 User->>Modal: 点击取消 Modal->>UI: 关闭对话框 else 用户确认 User->>Modal: 点击确定 Modal->>Redux: 6. dispatch(deleteSendJobThunk(selectedIds)) Redux->>Thunk: 7. 执行删除 thunk Thunk->>API: 8. 调用 deleteSendTask(taskIds) API->>Backend: 9. DELETE /auth/scp/task Backend-->>API: 10. 返回结果 {code: '0x000000'} API-->>Thunk: 11. 返回响应 alt 删除成功 Thunk->>Redux: 12. fulfilled - 更新 state Redux->>Redux: 13. 过滤掉已删除的任务 Redux->>Redux: 14. 清空 selectedIds Redux-->>UI: 15. 触发重新渲染 UI->>User: 16. 显示成功消息 else 删除失败 Thunk->>Redux: rejected Redux-->>UI: 错误信息 UI->>User: 显示错误消息 end end end ``` ## 3. 数据流 ``` ┌─────────────┐ │ 用户操作 │ │ 勾选任务 │ └──────┬──────┘ │ ▼ ┌─────────────────────────────┐ │ Redux State 更新 │ │ selectedIds = ['id1', 'id2'] │ └──────┬──────────────────────┘ │ │ 用户点击删除按钮 ▼ ┌─────────────────────┐ │ handleDelete 校验 │ │ selectedIds.length │ └──────┬──────────────┘ │ ▼ ┌─────────────────────┐ │ Modal.confirm │ │ 显示确认对话框 │ └──────┬──────────────┘ │ │ 用户确认 ▼ ┌─────────────────────────────────────┐ │ dispatch(deleteSendJobThunk(ids)) │ └──────┬──────────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ API 层 │ │ deleteSendTask(taskIds) │ └──────┬──────────────────┘ │ ▼ ┌─────────────────────────────────┐ │ HTTP DELETE 请求 │ │ /auth/scp/task │ │ body: ['id1', 'id2'] │ └──────┬──────────────────────────┘ │ ▼ ┌─────────────────────┐ │ 后端处理并返回 │ │ {code: '0x000000'} │ └──────┬──────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ Redux Store 更新 │ │ - entities.data (过滤已删除项) │ │ - selection.selectedIds = [] │ └──────┬──────────────────────────────┘ │ ▼ ┌─────────────────────┐ │ UI 重新渲染 │ │ 显示成功消息 │ └─────────────────────┘ ``` ## 4. 核心数据结构 ### 4.1 SendJob (发送任务实体) ```typescript interface SendJob { task_id: string; // 任务唯一标识 patient_name: string; // 患者姓名 patient_id: string; // 患者 ID priority: SendJobPriority; // 优先级: 'High' | 'Medium' | 'Low' status: SendJobStatus; // 状态: 'ARRIVED' | 'SENDING' | 'FAILED' | 'SUCCESS' retry_count?: number; // 重试次数 destination: string; // 目标 PACS 节点 } ``` ### 4.2 Redux State 结构 ```typescript // 选中状态 interface SelectionState { selectedIds: string[]; // 选中的任务 ID 列表 } // 实体状态 interface EntitiesState { data: SendJob[]; // 任务列表 total: number; // 总数 } // UI 状态 interface UIState { loading: boolean; error: string | null; } ``` ### 4.3 API 接口 #### 请求 ```typescript // DELETE /auth/scp/task // Content-Type: application/json // Body: string[] (任务 ID 数组) 例如: ["0199cd46-82f0-76c5-b1d3-9399668a1a05", "0199cd46-460d-770e-ac8e-549939a4a7d4"] ``` #### 响应 ```typescript interface BaseResponse { code: string; // '0x000000' 表示成功 description: string; // 描述信息 solution: string; // 解决方案 data: Record; } ``` ## 5. 具体实现 ### 5.1 组件修改:OutputActionPanel.tsx #### 导入依赖 ```typescript // 新增 Modal 组件和 deleteSendJobThunk import { Tooltip, Button, Space, message, Modal } from 'antd'; import { retrySendJobThunk, deleteSendJobThunk } from '@/states/output/sendJob/slices/sendJobSlice'; ``` #### 实现 handleDelete 方法 ```typescript const handleDelete = async () => { // 第 1 步:校验是否有选中的任务 if (selectedIds.length === 0) { message.warning('请先选择要删除的任务'); return; } // 第 2 步:显示确认对话框 Modal.confirm({ title: '确认删除', content: `确定要删除选中的 ${selectedIds.length} 个任务吗?此操作不可恢复。`, okText: '确定', cancelText: '取消', onOk: async () => { try { // 第 3 步:调用删除 thunk await dispatch(deleteSendJobThunk(selectedIds)).unwrap(); // 第 4 步:显示成功消息 message.success(`成功删除 ${selectedIds.length} 个任务`); } catch (error) { // 第 5 步:错误处理 console.error('删除任务失败:', error); message.error('删除任务失败,请稍后再试'); } }, }); }; ``` #### 绑定事件处理器 ```typescript