|
@@ -0,0 +1,489 @@
|
|
|
|
+# 删除发送任务功能实现文档
|
|
|
|
+
|
|
|
|
+## 概述
|
|
|
|
+
|
|
|
|
+本文档详细记录了**删除发送任务**功能的实现过程,包括架构设计、数据流、交互流程和具体实现细节。
|
|
|
|
+
|
|
|
|
+## 功能需求
|
|
|
|
+
|
|
|
|
+实现传输队列中的删除功能:
|
|
|
|
+- 用户可以在表格中选择一个或多个发送任务
|
|
|
|
+- 点击删除按钮后,弹出确认对话框
|
|
|
|
+- 确认后调用后端接口批量删除选中的任务
|
|
|
|
+- 删除成功后更新 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<SendJob> {
|
|
|
|
+ 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<string, any>;
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+## 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
|
|
|
|
+<Button
|
|
|
|
+ type="default"
|
|
|
|
+ icon={<Icon name="Delete" />}
|
|
|
|
+ onClick={handleDelete} // 绑定删除处理函数
|
|
|
|
+/>
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### 5.2 Redux 层(已存在,无需修改)
|
|
|
|
+
|
|
|
|
+#### deleteSendJobThunk 实现
|
|
|
|
+```typescript
|
|
|
|
+// src/states/output/sendJob/slices/sendJobSlice.ts
|
|
|
|
+export const deleteSendJobThunk = createDeleteThunk(
|
|
|
|
+ 'sendJob',
|
|
|
|
+ async (ids: string[]) => {
|
|
|
|
+ await deleteSendTask(ids);
|
|
|
|
+ store.dispatch(sendJobSelectionSlice.actions.clearSelection());
|
|
|
|
+ }
|
|
|
|
+);
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+#### Redux Slice 配置
|
|
|
|
+```typescript
|
|
|
|
+// 在 createEntityListSlices 中自动处理
|
|
|
|
+builder.addCase(
|
|
|
|
+ deleteThunk.fulfilled,
|
|
|
|
+ (state, action: PayloadAction<string[]>) => {
|
|
|
|
+ // 从数据列表中过滤掉已删除的任务
|
|
|
|
+ state.data = state.data.filter(
|
|
|
|
+ (item) => !action.payload.includes(item.task_id)
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+);
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### 5.3 API 层(已存在,无需修改)
|
|
|
|
+
|
|
|
|
+```typescript
|
|
|
|
+// src/API/output/sendJobActions.ts
|
|
|
|
+export const deleteSendTask = async (
|
|
|
|
+ taskIds: string[]
|
|
|
|
+): Promise<BaseResponse> => {
|
|
|
|
+ try {
|
|
|
|
+ const response = await axiosInstance.delete<BaseResponse>(
|
|
|
|
+ '/auth/scp/task',
|
|
|
|
+ {
|
|
|
|
+ data: taskIds, // 传递任务 ID 数组
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ if (response.data.code !== '0x000000') {
|
|
|
|
+ throw new Error(`删除发送任务失败: ${response.data.description}`);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return response.data;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('Error deleting send task:', error);
|
|
|
|
+ throw error;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+## 6. 功能执行流程
|
|
|
|
+
|
|
|
|
+### 起点:用户操作
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+1. 用户在传输队列表格中勾选任务
|
|
|
|
+ ├─ 触发 checkbox onChange
|
|
|
|
+ └─ 更新 Redux: selectedIds = ['id1', 'id2', ...]
|
|
|
|
+
|
|
|
|
+2. 用户点击删除按钮
|
|
|
|
+ └─ 调用 handleDelete()
|
|
|
|
+
|
|
|
|
+3. 前置校验
|
|
|
|
+ ├─ 检查 selectedIds.length === 0
|
|
|
|
+ │ └─ 是:显示警告消息 "请先选择要删除的任务"
|
|
|
|
+ │ └─ 否:继续下一步
|
|
|
|
+
|
|
|
|
+4. 显示确认对话框
|
|
|
|
+ ├─ 标题:确认删除
|
|
|
|
+ ├─ 内容:确定要删除选中的 N 个任务吗?此操作不可恢复。
|
|
|
|
+ └─ 按钮:[取消] [确定]
|
|
|
|
+
|
|
|
|
+5. 用户选择
|
|
|
|
+ ├─ 点击取消:关闭对话框,不执行删除
|
|
|
|
+ └─ 点击确定:执行删除操作
|
|
|
|
+
|
|
|
|
+6. 执行删除
|
|
|
|
+ ├─ dispatch(deleteSendJobThunk(selectedIds))
|
|
|
|
+ ├─ 调用 API: deleteSendTask(taskIds)
|
|
|
|
+ ├─ 发送 HTTP DELETE 请求
|
|
|
|
+ └─ 等待响应
|
|
|
|
+
|
|
|
|
+7. 后端处理
|
|
|
|
+ ├─ 验证请求合法性
|
|
|
|
+ ├─ 从数据库删除任务记录
|
|
|
|
+ └─ 返回响应 {code: '0x000000'}
|
|
|
|
+
|
|
|
|
+8. Redux Store 更新
|
|
|
|
+ ├─ deleteSendJobThunk.fulfilled 触发
|
|
|
|
+ ├─ 从 entities.data 过滤掉已删除的任务
|
|
|
|
+ │ state.data = state.data.filter(item => !deletedIds.includes(item.task_id))
|
|
|
|
+ └─ 清空 selectedIds
|
|
|
|
+ store.dispatch(sendJobSelectionSlice.actions.clearSelection())
|
|
|
|
+
|
|
|
|
+9. UI 反馈
|
|
|
|
+ ├─ 表格重新渲染(已删除的行消失)
|
|
|
|
+ ├─ 选中状态清除
|
|
|
|
+ └─ 显示成功消息:"成功删除 N 个任务"
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+## 7. 设计决策
|
|
|
|
+
|
|
|
|
+### 7.1 为什么使用确认对话框?
|
|
|
|
+- **防止误操作**:删除是不可逆操作,需要二次确认
|
|
|
|
+- **用户体验**:明确告知将删除多少个任务
|
|
|
|
+- **行业最佳实践**:关键操作都应有确认机制
|
|
|
|
+
|
|
|
|
+### 7.2 为什么批量删除而不是逐个删除?
|
|
|
|
+- **性能考虑**:减少 HTTP 请求次数
|
|
|
|
+- **原子性**:批量操作更容易保证数据一致性
|
|
|
|
+- **后端设计**:API 已支持批量删除(接收数组参数)
|
|
|
|
+
|
|
|
|
+### 7.3 为什么在删除后清空 selectedIds?
|
|
|
|
+- **逻辑合理性**:已删除的任务不应继续保持选中状态
|
|
|
|
+- **防止二次操作**:避免用户再次点击删除时操作到不存在的任务
|
|
|
|
+- **参考重试功能**:deleteSendJobThunk 内部已实现此逻辑
|
|
|
|
+
|
|
|
|
+### 7.4 错误处理策略
|
|
|
|
+- **前置校验**:在操作前检查是否有选中任务
|
|
|
|
+- **API 错误**:catch 捕获并显示友好的错误消息
|
|
|
|
+- **日志记录**:console.error 记录详细错误信息便于调试
|
|
|
|
+
|
|
|
|
+## 8. 与重试功能的对比
|
|
|
|
+
|
|
|
|
+| 特性 | 重试功能 (handleRetry) | 删除功能 (handleDelete) |
|
|
|
|
+|------|----------------------|------------------------|
|
|
|
|
+| 操作方式 | 逐个任务重试 | 批量删除 |
|
|
|
|
+| API 调用 | `retrySendTask(taskId)` 循环调用 | `deleteSendTask(taskIds)` 一次性调用 |
|
|
|
|
+| 状态更新 | 更新任务状态为 SENDING | 从列表中移除任务 |
|
|
|
|
+| 确认对话框 | 不需要 | 需要(不可逆操作) |
|
|
|
|
+| 选中状态 | 不清空 | 清空 selectedIds |
|
|
|
|
+| 错误提示 | "重试任务失败,请稍后再试" | "删除任务失败,请稍后再试" |
|
|
|
|
+| 成功提示 | "成功提交 N 个重试任务" | "成功删除 N 个任务" |
|
|
|
|
+
|
|
|
|
+## 9. 测试要点
|
|
|
|
+
|
|
|
|
+### 9.1 功能测试
|
|
|
|
+- [ ] 未选中任务时点击删除,显示警告消息
|
|
|
|
+- [ ] 选中单个任务后点击删除,显示确认对话框
|
|
|
|
+- [ ] 选中多个任务后点击删除,显示正确的任务数量
|
|
|
|
+- [ ] 确认对话框中点击"取消",不执行删除
|
|
|
|
+- [ ] 确认对话框中点击"确定",成功删除任务
|
|
|
|
+- [ ] 删除成功后,表格中的任务消失
|
|
|
|
+- [ ] 删除成功后,selectedIds 被清空
|
|
|
|
+- [ ] API 失败时,显示错误消息
|
|
|
|
+
|
|
|
|
+### 9.2 边界测试
|
|
|
|
+- [ ] 删除全部任务后,列表为空
|
|
|
|
+- [ ] 网络异常时的错误处理
|
|
|
|
+- [ ] 并发删除(快速多次点击删除按钮)
|
|
|
|
+
|
|
|
|
+### 9.3 用户体验测试
|
|
|
|
+- [ ] 确认对话框的文案清晰易懂
|
|
|
|
+- [ ] 成功/失败消息显示时机正确
|
|
|
|
+- [ ] 删除按钮在没有选中任务时的反馈
|
|
|
|
+
|
|
|
|
+## 10. 后续优化建议
|
|
|
|
+
|
|
|
|
+### 10.1 功能增强
|
|
|
|
+1. **软删除**:实现撤销功能,允许用户恢复误删的任务
|
|
|
|
+2. **批量操作进度**:显示删除进度条(任务数量多时)
|
|
|
|
+3. **权限控制**:根据用户角色控制删除按钮的可见性
|
|
|
|
+4. **审计日志**:记录删除操作的用户和时间戳
|
|
|
|
+
|
|
|
|
+### 10.2 性能优化
|
|
|
|
+1. **防抖处理**:防止用户快速多次点击删除按钮
|
|
|
|
+2. **乐观更新**:先更新 UI,再调用 API(提升响应速度)
|
|
|
|
+3. **分页处理**:删除后自动刷新当前页数据
|
|
|
|
+
|
|
|
|
+### 10.3 用户体验优化
|
|
|
|
+1. **快捷键支持**:支持 Delete 键快速删除
|
|
|
|
+2. **批量操作提示**:删除数量超过阈值时额外提醒
|
|
|
|
+3. **加载状态**:删除过程中显示 loading 状态
|
|
|
|
+
|
|
|
|
+## 11. 总结
|
|
|
|
+
|
|
|
|
+### 实现要点
|
|
|
|
+1. **复用现有架构**:充分利用已有的 Redux 模板和 thunk 工厂
|
|
|
|
+2. **参考重试功能**:删除功能与重试功能结构相似,但有关键差异
|
|
|
|
+3. **用户体验优先**:添加确认对话框防止误操作
|
|
|
|
+4. **完善错误处理**:各个环节都有相应的错误捕获和用户提示
|
|
|
|
+
|
|
|
|
+### 修改文件
|
|
|
|
+- ✅ `src/pages/patient/components/OutputActionPanel.tsx`
|
|
|
|
+ - 导入 `Modal` 组件和 `deleteSendJobThunk`
|
|
|
|
+ - 新增 `handleDelete` 方法
|
|
|
|
+ - 绑定删除按钮的 `onClick` 事件
|
|
|
|
+
|
|
|
|
+### 无需修改(已存在)
|
|
|
|
+- `src/states/output/sendJob/slices/sendJobSlice.ts` - deleteSendJobThunk
|
|
|
|
+- `src/API/output/sendJobActions.ts` - deleteSendTask API
|
|
|
|
+- `src/domain/output/sendJob.ts` - SendJob 数据模型
|
|
|
|
+
|
|
|
|
+### 关键代码行数
|
|
|
|
+- 新增代码:约 30 行
|
|
|
|
+- 修改代码:1 行(添加 onClick)
|
|
|
|
+- 总变更:轻量级,高度可维护
|
|
|
|
+
|
|
|
|
+---
|
|
|
|
+
|
|
|
|
+**文档版本**:v1.0
|
|
|
|
+**创建时间**:2025-10-11
|
|
|
|
+**最后更新**:2025-10-11
|
|
|
|
+**作者**:Cline
|