From fba3589d0d69e8b2943a230ee760c85beaeaab26 Mon Sep 17 00:00:00 2001 From: duxingchen Date: Mon, 10 Aug 2026 13:26:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=84=A6=E7=82=B9/=E5=85=A8=E6=99=AF?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E5=8F=8C=E7=BF=BCflex-col=E7=BA=B5=E5=90=91?= =?UTF-8?q?=E5=A0=86=E5=8F=A0+SVG=E7=AE=AD=E5=A4=B4+=E5=AE=9E=E7=BA=BF?= =?UTF-8?q?=E8=99=9A=E7=BA=BF=E5=8C=BA=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/TaskTree/TaskFlowView.tsx | 74 +++++++++++-------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/frontend/src/components/TaskTree/TaskFlowView.tsx b/frontend/src/components/TaskTree/TaskFlowView.tsx index d452241..ab7f23e 100644 --- a/frontend/src/components/TaskTree/TaskFlowView.tsx +++ b/frontend/src/components/TaskTree/TaskFlowView.tsx @@ -14,6 +14,10 @@ import type { ModalTarget } from "./TaskTreeViewer"; function fmtTime(d: string | null) { if (!d) return ""; const dt = new Date(d); const pad = (n: number) => String(n).padStart(2, "0"); return `${dt.getFullYear()}-${pad(dt.getMonth() + 1)}-${pad(dt.getDate())} ${pad(dt.getHours())}:${pad(dt.getMinutes())}`; } function isMain(t: TaskResponse) { return !t.parent_task_id || t.task_type === "TRANSFER" || t.task_type === "RECOVERY" || (!t.task_type && !!t.parent_task_id); } function active(s: string) { return s === "WIP" || s === "PENDING"; } +/** 微型右箭头 SVG */ +function ArrowRight({ color = "#9ca3af" }: { color?: string }) { + return ; +} function parseImages(s: string | null | undefined): string[] { if (!s) return []; try { return JSON.parse(s); } catch { return []; } } function imageUrl(u: string) { if (!u) return ""; return u.startsWith("http") ? u : import.meta.env.VITE_API_BASE_URL + (u.startsWith("/") ? u : "/" + u); } @@ -121,43 +125,50 @@ export const TaskFlowView = memo(function TaskFlowView({ tasks, onAction, curren {/* ─── 焦点模式 ─── */} {!showFullMap && ( -
+
{legacySubs.length > 0 && (

⚠ {legacySubs.length} 个遗留分支仍在进行中

)} - {/* 每个活跃主线一行:左翼 + 中央 + 右翼 */} {activeMain.map(mainTask => { const allSubs = [...activeSubs, ...legacySubs]; const leftSubs = allSubs.filter((_, i) => i % 2 === 0); const rightSubs = allSubs.filter((_, i) => i % 2 === 1); return ( -
- {/* 左翼 */} -
+
+ {/* 左翼:flex-col 纵向堆叠,右对齐 */} +
{leftSubs.map(t => { const isLegacy = legacySubs.includes(t); return (
- -
+ + {/* 连线+箭头 → 右侧指向中央 */} +
+
+ +
); })}
{/* 中央主干 */}
- +
- {/* 右翼 */} -
+ {/* 右翼:flex-col 纵向堆叠,左对齐 */} +
{rightSubs.map(t => { const isLegacy = legacySubs.includes(t); return (
-
- + {/* 连线+箭头 → 右侧指向外侧 */} +
+ +
+
+
); })} @@ -177,47 +188,50 @@ export const TaskFlowView = memo(function TaskFlowView({ tasks, onAction, curren const hasLegacyActive = children.some(c => !isMain(c) && !active(mainTask.status)); const leftChildren = children.filter((_, i) => i % 2 === 0); const rightChildren = children.filter((_, i) => i % 2 === 1); + const lineStyle = hasLegacyActive && !active(mainTask.status); return (
{/* 垂直轴线贯穿中央 */}
- {/* 水平一行:左翼 + 中央 + 右翼 */} -
- {/* 左翼分支 */} -
+
+ {/* 左翼:flex-col */} +
{leftChildren.map(c => (
- -
+ +
+
+ +
))}
- {/* 中央主干 */} + {/* 中央 */}
- + {active(mainTask.status) && (
)}
- {/* 右翼分支 */} -
+ {/* 右翼:flex-col */} +
{rightChildren.map(c => (
-
- +
+ +
+
+
))}
- {/* 区间连接 ▼ */} {allMains.indexOf(mainTask) < allMains.length - 1 && (