From a99f04958934e5c7bd377aba55f9aa4836648405 Mon Sep 17 00:00:00 2001 From: huangzhuang_3rd Date: Thu, 13 Aug 2026 23:13:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20DAG=E7=94=BB=E5=B8=83=E5=B5=8C=E5=85=A5?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E8=AF=A6=E6=83=85=E9=A1=B5=EF=BC=8C=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E8=8A=82=E7=82=B9=E7=82=B9=E5=87=BB=E5=BC=B9=E8=AF=A6?= =?UTF-8?q?=E6=83=85Modal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/ProjectDetail.tsx | 117 +++++++++++++++++++-------- 1 file changed, 85 insertions(+), 32 deletions(-) diff --git a/frontend/src/pages/ProjectDetail.tsx b/frontend/src/pages/ProjectDetail.tsx index 483373c..ab09ab5 100644 --- a/frontend/src/pages/ProjectDetail.tsx +++ b/frontend/src/pages/ProjectDetail.tsx @@ -12,15 +12,20 @@ import { Tag, Empty, List, + Tabs, } from 'antd'; import { ArrowLeftOutlined, ReloadOutlined, + ApartmentOutlined, + ProfileOutlined, } from '@ant-design/icons'; -import { useNavigate, useParams } from 'react-router-dom'; +import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { projectApi, taskApi, artifactApi } from '@/api'; import type { Project, ProjectStats, Task, Artifact } from '@/types'; import { ProjectStatusTag, TaskStatusTag } from '@/components/constants'; +import DagCanvas from '@/pages/DagCanvas'; +import TaskDetailModal from '@/components/TaskDetailModal'; import dayjs from 'dayjs'; const { Title, Text } = Typography; @@ -28,11 +33,20 @@ const { Title, Text } = Typography; export default function ProjectDetail() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); + const [searchParams, setSearchParams] = useSearchParams(); + const activeTab = searchParams.get('tab') || 'overview'; const [loading, setLoading] = useState(true); const [project, setProject] = useState(null); const [stats, setStats] = useState(null); const [tasks, setTasks] = useState([]); const [artifacts, setArtifacts] = useState([]); + const [detailTaskId, setDetailTaskId] = useState(null); + const [detailOpen, setDetailOpen] = useState(false); + + const openTaskDetail = (taskId: number) => { + setDetailTaskId(taskId); + setDetailOpen(true); + }; useEffect(() => { if (!id) return; @@ -75,36 +89,8 @@ export default function ProjectDetail() { ].filter((item) => item.count > 0) : []; - return ( -
-
- - - - {project.name} - - - - -
- + const overviewTab = ( + <> {project.name} @@ -198,7 +184,7 @@ export default function ProjectDetail() { > navigate('/tasks')}>{task.title} + openTaskDetail(task.id)}>{task.title} } description={dayjs(task.created_at).format('MM-DD HH:mm')} /> @@ -231,6 +217,73 @@ export default function ProjectDetail() { + + ); + + return ( +
+
+ + + + {project.name} + + + + +
+ + setSearchParams({ tab: key })} + items={[ + { + key: 'overview', + label: ( + + 概览 + + ), + children: overviewTab, + }, + { + key: 'dag', + label: ( + + DAG 编排 + + ), + children: ( + + + + ), + }, + ]} + /> + + setDetailOpen(false)} + />
); }