本文档详细记录了删除发送任务功能的实现过程,包括架构设计、数据流、交互流程和具体实现细节。
实现传输队列中的删除功能:
OutputOperationPanel (容器组件)
src/pages/patient/components/OutputOperationPanel.tsx
OutputActionPanel (操作面板组件)
src/pages/patient/components/OutputActionPanel.tsx
handleDelete
方法Modal
组件和 deleteSendJobThunk
src/states/output/sendJob/slices/sendJobSlice.ts
deleteSendJobThunk
- 删除任务的异步 thunk(已存在)sendJobEntitiesSlice
- 管理发送任务数据sendJobSelectionSlice
- 管理选中的任务 IDsrc/API/output/sendJobActions.ts
deleteSendTask(taskIds: string[])
- 调用删除接口(已存在)src/domain/output/sendJob.ts
task_id
: 任务唯一标识patient_name
: 患者姓名status
: 任务状态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
┌─────────────┐
│ 用户操作 │
│ 勾选任务 │
└──────┬──────┘
│
▼
┌─────────────────────────────┐
│ 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 重新渲染 │
│ 显示成功消息 │
└─────────────────────┘
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 节点
}
// 选中状态
interface SelectionState {
selectedIds: string[]; // 选中的任务 ID 列表
}
// 实体状态
interface EntitiesState<SendJob> {
data: SendJob[]; // 任务列表
total: number; // 总数
}
// UI 状态
interface UIState {
loading: boolean;
error: string | null;
}
// DELETE /auth/scp/task
// Content-Type: application/json
// Body: string[] (任务 ID 数组)
例如:
["0199cd46-82f0-76c5-b1d3-9399668a1a05", "0199cd46-460d-770e-ac8e-549939a4a7d4"]
interface BaseResponse {
code: string; // '0x000000' 表示成功
description: string; // 描述信息
solution: string; // 解决方案
data: Record<string, any>;
}
// 新增 Modal 组件和 deleteSendJobThunk
import { Tooltip, Button, Space, message, Modal } from 'antd';
import { retrySendJobThunk, deleteSendJobThunk } from '@/states/output/sendJob/slices/sendJobSlice';
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('删除任务失败,请稍后再试');
}
},
});
};
<Button
type="default"
icon={<Icon name="Delete" />}
onClick={handleDelete} // 绑定删除处理函数
/>
// src/states/output/sendJob/slices/sendJobSlice.ts
export const deleteSendJobThunk = createDeleteThunk(
'sendJob',
async (ids: string[]) => {
await deleteSendTask(ids);
store.dispatch(sendJobSelectionSlice.actions.clearSelection());
}
);
// 在 createEntityListSlices 中自动处理
builder.addCase(
deleteThunk.fulfilled,
(state, action: PayloadAction<string[]>) => {
// 从数据列表中过滤掉已删除的任务
state.data = state.data.filter(
(item) => !action.payload.includes(item.task_id)
);
}
);
// 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;
}
};
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 个任务"
特性 | 重试功能 (handleRetry) | 删除功能 (handleDelete) |
---|---|---|
操作方式 | 逐个任务重试 | 批量删除 |
API 调用 | retrySendTask(taskId) 循环调用 |
deleteSendTask(taskIds) 一次性调用 |
状态更新 | 更新任务状态为 SENDING | 从列表中移除任务 |
确认对话框 | 不需要 | 需要(不可逆操作) |
选中状态 | 不清空 | 清空 selectedIds |
错误提示 | "重试任务失败,请稍后再试" | "删除任务失败,请稍后再试" |
成功提示 | "成功提交 N 个重试任务" | "成功删除 N 个任务" |
src/pages/patient/components/OutputActionPanel.tsx
Modal
组件和 deleteSendJobThunk
handleDelete
方法onClick
事件src/states/output/sendJob/slices/sendJobSlice.ts
- deleteSendJobThunksrc/API/output/sendJobActions.ts
- deleteSendTask APIsrc/domain/output/sendJob.ts
- SendJob 数据模型文档版本:v1.0
创建时间:2025-10-11
最后更新:2025-10-11
作者:Cline