From f762a76ecfce8543107561235501fb7b8f9ca593 Mon Sep 17 00:00:00 2001 From: Administrator Date: Thu, 18 Jun 2026 16:19:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BB=BB=E5=8A=A1=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E5=8C=BA=20UI=20=E7=BB=86=E5=8C=96(=E5=BA=95=E9=83=A8=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E4=B8=BB=E9=A2=98=E8=89=B2/=E5=B7=A6=E4=B8=8A?= =?UTF-8?q?=E4=B8=9A=E5=8A=A1=E5=90=8D/=E5=8F=B3=E4=BE=A7=E6=99=BA?= =?UTF-8?q?=E8=83=BD=E4=BD=93=E4=BF=A1=E6=81=AF=E9=BB=98=E8=AE=A4=E6=94=B6?= =?UTF-8?q?=E8=B5=B7/xdfx=E7=9B=AE=E7=9A=84=E5=BC=B9=E6=A1=86=E6=8C=89?= =?UTF-8?q?=E8=A1=8C=E5=8A=A8id=E8=A7=A3=E6=9E=90)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 底部「快捷跳转」按钮改用主题色 var(--color-main)(随红/蓝主题自适配),hover 用 --brand-950 - 三个工作区左上角标明当前分析页面(任务分析/三情分析/行动分析) - 进入任务工作区(taskGate/taskBind)时右侧「智能体信息」面板默认收起(AgentDetailPanel defaultCollapsed) - xdfx「弹框查看」目的树:先用行动id换回任务id 再查(TaskPurposeDialog resolveFromActionId); 仅深链原始行动id(≠任务id)时触发,切换业务进入不误解析 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../workspace/agents/agent-detail-panel.tsx | 5 +++- frontend-web/src/pages/AgentChatPage.tsx | 1 + .../task-components/TaskFxWorkspace.tsx | 23 ++++++++++++-- .../task-components/TaskPurposePanel.tsx | 30 +++++++++++++++---- 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/frontend-web/src/components/workspace/agents/agent-detail-panel.tsx b/frontend-web/src/components/workspace/agents/agent-detail-panel.tsx index f9a3292e..9a40afc3 100644 --- a/frontend-web/src/components/workspace/agents/agent-detail-panel.tsx +++ b/frontend-web/src/components/workspace/agents/agent-detail-panel.tsx @@ -131,14 +131,17 @@ export function AgentDetailPanel({ agentName, onAskQuestion, disabled, + defaultCollapsed, }: { agent: Agent | null | undefined; agentName: string; onAskQuestion: (text: string) => void; disabled?: boolean; + /** 初始收起(任务工作区进入时默认收起智能体信息面板)。 */ + defaultCollapsed?: boolean; }) { const router = useRouter(); - const [collapsed, setCollapsed] = useState(false); + const [collapsed, setCollapsed] = useState(defaultCollapsed ?? false); const [mobileOpen, setMobileOpen] = useState(false); const [editing, setEditing] = useState(false); const [draft, setDraft] = useState(null); diff --git a/frontend-web/src/pages/AgentChatPage.tsx b/frontend-web/src/pages/AgentChatPage.tsx index b169212e..12c09a2b 100644 --- a/frontend-web/src/pages/AgentChatPage.tsx +++ b/frontend-web/src/pages/AgentChatPage.tsx @@ -435,6 +435,7 @@ export default function AgentChatPage({ agentName={agentDisplayName} disabled={thread.isLoading || isDemoMode} onAskQuestion={(text) => handleSubmit({ text, files: [] })} + defaultCollapsed={taskCtxOn} /> diff --git a/frontend-web/src/strategy-components/components/task-components/TaskFxWorkspace.tsx b/frontend-web/src/strategy-components/components/task-components/TaskFxWorkspace.tsx index 637dad94..ace8bd25 100644 --- a/frontend-web/src/strategy-components/components/task-components/TaskFxWorkspace.tsx +++ b/frontend-web/src/strategy-components/components/task-components/TaskFxWorkspace.tsx @@ -36,6 +36,7 @@ import { type TaskDeeplinkConfig, } from "@/core/auth/task-deeplink-config"; import { + TASK_BUSINESSES, buttonsForBusiness, resolveTaskButtons, runTaskButton, @@ -120,6 +121,10 @@ function TaskJumpBar({ business, taskId }: { business: TaskBusiness; taskId: str // 目的树弹框(purpose 类型按钮)由组件层打开。 const [purposeOpen, setPurposeOpen] = useState(false); + // xdfx:深链原始「行动id」(与解析后的任务id 不同才算真行动id),弹框据此换回任务id 再查目的。 + const ctxActionId = readTaskContext()?.actionId; + const purposeActionId = + business === "xdfx" && ctxActionId && ctxActionId !== taskId ? ctxActionId : undefined; if (jumpButtons.length === 0) return null; @@ -141,7 +146,7 @@ function TaskJumpBar({ business, taskId }: { business: TaskBusiness; taskId: str {jumpButtons.map((btn) => ( ))} - + ); } @@ -168,21 +178,29 @@ function TaskConversationsList({ taskId, agentId, chatsBase, + business, lite, }: { taskId: string; agentId: string; chatsBase: string; + business: TaskBusiness; lite?: boolean; }) { const { pathname } = useLocation(); const navigate = useNavigate(); const { threads, isLoading } = useTaskThreads(taskId, agentId); const currentThreadId = useMemo(() => parseThreadId(pathname, chatsBase), [pathname, chatsBase]); + const businessName = TASK_BUSINESSES.find((b) => b.code === business)?.name ?? ""; return (
+ {/* 左上角标明当前是哪个分析页面 */} +
+ + {businessName} +
@@ -318,6 +336,7 @@ export function TaskFxWorkspace({ taskId={taskId} agentId={agentId} chatsBase={chatsBase} + business={business} lite={lite} />
diff --git a/frontend-web/src/strategy-components/components/task-components/TaskPurposePanel.tsx b/frontend-web/src/strategy-components/components/task-components/TaskPurposePanel.tsx index 178b13a5..56bc1f1c 100644 --- a/frontend-web/src/strategy-components/components/task-components/TaskPurposePanel.tsx +++ b/frontend-web/src/strategy-components/components/task-components/TaskPurposePanel.tsx @@ -30,6 +30,7 @@ import { type PurposeTreeNode, type TaskPurposeResult, } from "@/core/auth/task-purpose"; +import { fetchTaskIdFromAction } from "@/core/auth/task-deeplink"; import { cn } from "@/lib/utils"; /** 目的树表格:拍平成行,列数随数据自适应;层级缺失补空、字段变动不崩。 */ @@ -98,32 +99,49 @@ export function TaskPurposeDialog({ taskId, open, onOpenChange, + resolveFromActionId, }: { taskId: string; open: boolean; onOpenChange: (open: boolean) => void; + /** xdfx:深链原始「行动id」。提供时弹框先用它换出真正「任务id」再查目的树。 */ + resolveFromActionId?: string; }) { const [loading, setLoading] = useState(false); const [result, setResult] = useState(null); + const [resolvedTaskId, setResolvedTaskId] = useState(taskId); useEffect(() => { if (!open) return; let cancelled = false; setLoading(true); - fetchTaskPurposeDetail(taskId) - .then((r) => !cancelled && setResult(r)) - .catch(() => !cancelled && setResult({ tree: [], hasData: false })) - .finally(() => !cancelled && setLoading(false)); + (async () => { + try { + // xdfx:行动id 换任务id 再查目的树(与登录时的解析一致);无行动id 时直接用任务id。 + let tid = taskId; + if (resolveFromActionId) { + tid = (await fetchTaskIdFromAction(resolveFromActionId)) || taskId; + } + if (cancelled) return; + setResolvedTaskId(tid); + const r = await fetchTaskPurposeDetail(tid); + if (!cancelled) setResult(r); + } catch { + if (!cancelled) setResult({ tree: [], hasData: false }); + } finally { + if (!cancelled) setLoading(false); + } + })(); return () => { cancelled = true; }; - }, [open, taskId]); + }, [open, taskId, resolveFromActionId]); return ( - 任务目的(任务 {taskId}) + 任务目的(任务 {resolvedTaskId}) {loading ? (