Files
xiaoxia-saas/apps/web/src/pages/workspace/ProjectTasks.tsx
T
CI Test e418577097
CI/CD Pipeline / Validate Code Quality And Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
Deploy / Deploy Staging (push) Has been cancelled
Deploy / Build Production Runtime Images (push) Has been cancelled
Deploy / Deploy Production (push) Has been cancelled
Deploy / Production Browser E2E (push) Has been cancelled
Tests / lint (push) Failing after 1924h15m56s
Tests / test (push) Failing after 1924h15m58s
fix: resolve TypeScript unused variable errors in ProjectGeneration.tsx and ProjectTasks.tsx
2026-06-28 11:14:47 +08:00

132 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 项目任务中心 - V21 UI
*/
import React from 'react';
import { Alert, Button, List, Progress, Space, Tag, Typography } from 'antd';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useParams } from 'react-router-dom';
import { getProjectTasks, retryProjectTask } from '@/api/tasks';
import '@/components/business/business.css';
import './ProjectTasks.css';
const statusMap: Record<string, { label: string; color: string }> = {
pending: { label: '排队中', color: 'default' },
processing: { label: '处理中', color: 'processing' },
running: { label: '运行中', color: 'processing' },
completed: { label: '已完成', color: 'success' },
failed: { label: '失败', color: 'error' },
cancelled: { label: '已取消', color: 'default' },
};
const taskTypeLabels: Record<string, string> = {
ingest: '素材导入',
generation: '视频生成',
};
const ProjectTasks: React.FC = () => {
const { id } = useParams<{ id: string }>();
const projectId = id || '';
const queryClient = useQueryClient();
const tasksQuery = useQuery({
queryKey: ['project-tasks', projectId],
queryFn: () => getProjectTasks(projectId),
enabled: !!projectId,
refetchInterval: 5000,
});
const retryMutation = useMutation({
mutationFn: ({ taskType, sourceId }: { taskType: string; sourceId: string }) =>
retryProjectTask(taskType, sourceId),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['project-tasks', projectId] }),
});
return (
<div className="xx-project-tasks">
<div className="xx-page-head">
<div>
<h2>任务中心</h2>
<p>查看和管理项目中的所有任务</p>
</div>
<Button className="xx-ghost-btn" onClick={() => tasksQuery.refetch()}>
刷新
</Button>
</div>
<div className="xx-card">
{tasksQuery.isError && (
<Alert style={{ marginBottom: 16 }} type="error" showIcon message="任务列表加载失败" />
)}
{tasksQuery.data?.some((task) => task.retryable) && (
<Alert
style={{ marginBottom: 16 }}
type="warning"
showIcon
message="部分任务可重试"
description={"失败任务可通过「重试」重新排队;系统会保留原始失败原因方便排查。"}
/>
)}
<List
loading={tasksQuery.isLoading}
dataSource={tasksQuery.data || []}
locale={{
emptyText: (
<div className="xx-empty-state">
<div className="xx-empty-state-icon">📋</div>
<p>暂无任务,上传素材或发起生成后会出现在这里</p>
</div>
),
}}
renderItem={(task) => {
const status = statusMap[task.status] || { label: task.status, color: 'default' };
return (
<List.Item className="xx-task-item">
<List.Item.Meta
title={
<Space wrap className="xx-task-title">
<span className="xx-task-type">{taskTypeLabels[task.task_type] || task.task_type}</span>
<Tag color={status.color} className="xx-tag">{status.label}</Tag>
<Tag className="xx-tag xx-tag-indigo">{task.current_step}</Tag>
{task.retryable && (
<Button
size="small"
className="xx-ghost-btn"
loading={retryMutation.isPending}
onClick={() =>
retryMutation.mutate({ taskType: task.task_type, sourceId: task.source_id })
}
>
重试
</Button>
)}
</Space>
}
description={
<Space direction="vertical" style={{ width: '100%' }} className="xx-task-desc">
<Progress
percent={Math.round(task.progress || 0)}
size="small"
status={task.status === 'failed' ? 'exception' : undefined}
strokeColor={task.status === 'failed' ? '#ef4444' : '#4f46e5'}
/>
{task.user_message ? (
<Typography.Text type="danger">{task.user_message}</Typography.Text>
) : null}
<Typography.Text type="secondary" copyable style={{ fontSize: 12 }}>
任务 ID:{task.source_id}
</Typography.Text>
</Space>
}
/>
</List.Item>
);
}}
/>
</div>
</div>
);
};
export const Component = ProjectTasks;
export default ProjectTasks;