实现了传输队列中的【重试发送任务】功能,允许用户选择失败的发送任务并重新提交到后端执行。
src/pages/patient/OutputList.tsx
)
OutputOperationPanel (src/pages/patient/components/OutputOperationPanel.tsx
)
OutputActionPanel (src/pages/patient/components/OutputActionPanel.tsx
)
sendJobSlice (src/states/output/sendJob/slices/sendJobSlice.ts
)
retrySendJobThunk
: 重试任务的异步 ThunkcreateRetryHandlers
: 处理重试结果的 handlers
Redux Store
sendJobSelection.selectedIds
: 维护选中的任务 IDssendJobEntities.data
: 存储任务数据src/API/output/sendJobActions.ts
)
retrySendTask(taskId)
: 调用后端重试接口RetrySendTaskRequest
: 请求参数类型RetrySendTaskResponse
: 响应数据类型src/domain/output/sendJob.ts
)
task_id
、status
、retry_count
等字段文件: src/API/output/sendJobActions.ts
// 修改后 export interface RetrySendTaskRequest { task_id: string; }
2. **修改 retrySendTask 函数**
```typescript
// 修改前
export const retrySendTask = async (
instanceUid: string
): Promise<RetrySendTaskResponse> => {
const response = await axiosInstance.post<RetrySendTaskResponse>(
'/auth/scp/store_reply',
{ instance_uid: instanceUid }
);
// ...
}
// 修改后
export const retrySendTask = async (
taskId: string
): Promise<RetrySendTaskResponse> => {
const response = await axiosInstance.post<RetrySendTaskResponse>(
'/auth/scp/store_reply',
{ task_id: taskId }
);
// ...
}
文件: src/states/output/sendJob/slices/sendJobSlice.ts
// 修改后 export const retrySendJobThunk = createAsyncThunk( 'sendJob/retry', async (taskId: string) => {
const result = await retrySendTask(taskId);
return { taskId, result };
} );
### 2.3 组件层修改
**文件:** `src/pages/patient/components/OutputActionPanel.tsx`
#### 修改内容:
1. **添加必要的导入**
```typescript
import { message } from 'antd';
import { useAppDispatch, useAppSelector } from '@/states/store';
import { retrySendJobThunk } from '@/states/output/sendJob/slices/sendJobSlice';
// 处理重试按钮点击 const handleRetry = async () => {
// 校验是否有选中的任务
if (selectedIds.length === 0) {
message.warning('请先选择要重试的任务');
return;
}
try {
// 遍历选中的任务,逐个调用重试 API
const retryPromises = selectedIds.map((taskId) =>
dispatch(retrySendJobThunk(taskId)).unwrap()
);
await Promise.all(retryPromises);
message.success(`成功提交 ${selectedIds.length} 个重试任务`);
} catch (error) {
console.error('重试任务失败:', error);
message.error('重试任务失败,请稍后再试');
}
};
return (
// ...
); };
3. **添加按钮点击事件**
```typescript
<Button
type="default"
icon={/* ... */}
aria-label="重试"
style={{ width: '1.5rem', height: '1.5rem' }}
onClick={handleRetry} // 添加此行
/>
sequenceDiagram
participant User as 用户
participant Button as 重试按钮
participant Handler as handleRetry
participant Redux as Redux Store
participant Thunk as retrySendJobThunk
participant API as retrySendTask API
participant Backend as 后端服务
User->>Button: 1. 点击重试按钮
Button->>Handler: 2. 触发 onClick
Handler->>Redux: 3. 获取 selectedIds
alt 没有选中任务
Handler->>User: 4a. 显示警告消息
else 有选中任务
loop 每个选中的任务
Handler->>Thunk: 4b. dispatch(retrySendJobThunk(taskId))
Thunk->>API: 5. 调用 retrySendTask(taskId)
API->>Backend: 6. POST /auth/scp/store_reply
Backend-->>API: 7. 返回结果
API-->>Thunk: 8. 返回 response
Thunk->>Redux: 9. 更新任务状态
end
Handler->>User: 10. 显示成功消息
end
1. 用户选择任务
└─> handleRowClick (OutputList)
└─> dispatch(setSelectedIds([taskId]))
└─> Redux: sendJobSelection.selectedIds = [taskId]
2. 用户点击重试
└─> handleRetry (OutputActionPanel)
└─> 读取 selectedIds
└─> 遍历并 dispatch(retrySendJobThunk(taskId))
└─> retrySendTask(taskId) API 调用
└─> POST /auth/scp/store_reply { task_id }
└─> 后端处理并返回结果
└─> Redux 更新任务状态
└─> 表格自动刷新
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 RetrySendTaskRequest {
task_id: string;
}
// 响应数据
interface RetrySendTaskResponse {
code: string; // 响应码:0x000000 表示成功
description: string; // 描述信息
solution: string; // 解决方案
data: StoreReplyData;
}
interface StoreReplyData {
'@type': string;
ok: boolean; // 是否成功
output: string; // 输出信息
}
// 选中状态
interface SelectionState {
selectedIds: string[]; // 选中的 task_id 数组
}
// 任务列表状态
interface EntitiesState<SendJob> {
data: SendJob[]; // 任务数组
total: number; // 总数
}
校验提示
成功反馈
错误处理
批量操作
Promise.all
并行执行,提高效率重试成功后,Redux Store 会自动更新:
status
更新为 'SENDING'
retry_count
自动增加 1正常流程
边界情况
错误处理
与表格的集成
与分页的集成
端点: POST /auth/scp/store_reply
请求体:
{
"task_id": "0199cd46-82f0-76c5-b1d3-9399668a1a05"
}
响应示例(成功):
{
"code": "0x000000",
"description": "Success",
"solution": "",
"data": {
"@type": "StoreReply",
"ok": true,
"output": "Successfully retried task"
}
}
响应示例(失败):
{
"code": "0x000001",
"description": "Task not found",
"solution": "Please check the task ID",
"data": {
"@type": "StoreReply",
"ok": false,
"output": "Task does not exist"
}
}
参数变更
instance_uid
,实际实现改为使用 task_id
task_id
参数状态更新
SENDING
,而非 SUCCESS
并发控制
Promise.all
并行重试Promise.allSettled
或限流权限控制
加载状态
单独重试
重试策略
结果反馈
本次实现完成了传输队列的重试发送任务功能,主要包括:
instance_uid
改为 task_id
该功能已完全集成到现有的传输队列管理系统中,遵循了项目的架构设计和编码规范。
实现日期: 2025-10-11
实现人员: Cline
文档版本: 1.0