feat: DAG画布嵌入项目详情页,任务节点点击弹详情Modal
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Modal, Descriptions, Spin, Tag, Typography, Empty } from 'antd';
|
||||
import { taskApi } from '@/api';
|
||||
import type { Task } from '@/types';
|
||||
import { TaskStatusTag, PriorityTag } from '@/components/constants';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const { Paragraph, Text } = Typography;
|
||||
|
||||
interface Props {
|
||||
taskId: number | null;
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
/** 任务详情弹窗:在 DAG 画布/项目页内点击任务卡片时弹出,不跳转页面 */
|
||||
export default function TaskDetailModal({ taskId, open, onClose }: Props) {
|
||||
const [task, setTask] = useState<Task | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open || taskId == null) return;
|
||||
setLoading(true);
|
||||
setTask(null);
|
||||
taskApi
|
||||
.get(taskId)
|
||||
.then(setTask)
|
||||
.catch(() => setTask(null))
|
||||
.finally(() => setLoading(false));
|
||||
}, [open, taskId]);
|
||||
|
||||
const renderJsonBlock = (raw?: string) => {
|
||||
if (!raw) return <Text type="secondary">无</Text>;
|
||||
let pretty = raw;
|
||||
try {
|
||||
pretty = JSON.stringify(JSON.parse(raw), null, 2);
|
||||
} catch {
|
||||
/* keep raw */
|
||||
}
|
||||
return (
|
||||
<pre
|
||||
style={{
|
||||
background: '#f6f8fa',
|
||||
border: '1px solid #e8e8e8',
|
||||
borderRadius: 6,
|
||||
padding: 12,
|
||||
maxHeight: 260,
|
||||
overflow: 'auto',
|
||||
fontSize: 12,
|
||||
margin: 0,
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-all',
|
||||
}}
|
||||
>
|
||||
{pretty}
|
||||
</pre>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={task ? `任务 #${task.id} ${task.title}` : '任务详情'}
|
||||
open={open}
|
||||
onCancel={onClose}
|
||||
footer={null}
|
||||
width={720}
|
||||
destroyOnClose
|
||||
>
|
||||
{loading ? (
|
||||
<div style={{ textAlign: 'center', padding: 40 }}>
|
||||
<Spin />
|
||||
</div>
|
||||
) : !task ? (
|
||||
<Empty description="任务不存在或加载失败" />
|
||||
) : (
|
||||
<div>
|
||||
<Descriptions column={2} bordered size="small">
|
||||
<Descriptions.Item label="状态">
|
||||
<TaskStatusTag status={task.status} />
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="优先级">
|
||||
<PriorityTag priority={task.priority} />
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="任务类型">{task.task_type}</Descriptions.Item>
|
||||
<Descriptions.Item label="需要审核">
|
||||
{task.requires_review ? (
|
||||
<Tag color="purple">是</Tag>
|
||||
) : (
|
||||
<Tag>否</Tag>
|
||||
)}
|
||||
</Descriptions.Item>
|
||||
{task.review_status && (
|
||||
<Descriptions.Item label="审核状态">{task.review_status}</Descriptions.Item>
|
||||
)}
|
||||
{task.worker_id && (
|
||||
<Descriptions.Item label="AI Worker">#{task.worker_id}</Descriptions.Item>
|
||||
)}
|
||||
{task.due_date && (
|
||||
<Descriptions.Item label="截止时间">
|
||||
{dayjs(task.due_date).format('YYYY-MM-DD HH:mm')}
|
||||
</Descriptions.Item>
|
||||
)}
|
||||
{task.started_at && (
|
||||
<Descriptions.Item label="开始时间">
|
||||
{dayjs(task.started_at).format('YYYY-MM-DD HH:mm')}
|
||||
</Descriptions.Item>
|
||||
)}
|
||||
{task.completed_at && (
|
||||
<Descriptions.Item label="完成时间">
|
||||
{dayjs(task.completed_at).format('YYYY-MM-DD HH:mm')}
|
||||
</Descriptions.Item>
|
||||
)}
|
||||
<Descriptions.Item label="创建时间">
|
||||
{dayjs(task.created_at).format('YYYY-MM-DD HH:mm')}
|
||||
</Descriptions.Item>
|
||||
{task.description && (
|
||||
<Descriptions.Item label="描述" span={2}>
|
||||
{task.description}
|
||||
</Descriptions.Item>
|
||||
)}
|
||||
</Descriptions>
|
||||
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<Paragraph strong style={{ marginBottom: 8 }}>
|
||||
输入(Prompt / 参数)
|
||||
</Paragraph>
|
||||
{renderJsonBlock(task.input_data)}
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<Paragraph strong style={{ marginBottom: 8 }}>
|
||||
输出结果
|
||||
</Paragraph>
|
||||
{renderJsonBlock(task.output_data)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user