This commit is contained in:
fengxiangdebaozi committed 2026-06-19 10:03:10 +08:00
commit 81ca13280b
6 files changed
+321 -49

No files matched your search

@@ -3,7 +3,8 @@
* - rwfx(任务FX,完整版):左对话列表 + 任务操作(编辑/下一步/清除记录)+ 跳转三情分析按钮;
* 右侧问答带「目的树闸门」(AgentChatPage taskGate)。
* - 3qfx(三情分析)/ xdfx(行动分析)(``lite`` 精简版):只有左对话列表(按 taskId + agentId 隔离),
* 无任务操作、无闸门;新建对话直接带任务开场信息自动发出(AgentChatPage taskBind)。
* 无任务操作、无闸门;新建对话进问答页后,右上角「开始回答」按钮手动发出任务开场信息(AgentChatPage taskBind)。
* xdfx 额外在左上「当前任务」卡片下展示「行动详情」(行动名称/叙事,来自行动详情接口)。
*
* 左侧顶部 = 当前任务卡片(任务名称 + 简介,来自登录深链暂存的 copTaskDetail)+「新建对话」;
* 右侧 = <Outlet/> 渲染选中的对话。
@@ -29,7 +30,7 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { deleteTaskPurpose, readTaskContext } from "@/core/auth/task-purpose";
import { readCopTaskDetail } from "@/core/auth/task-deeplink";
import { fetchActionDetail, readCopTaskDetail, type ActionDetail } from "@/core/auth/task-deeplink";
import { TASK_BUSINESSES, type TaskBusiness } from "@/core/auth/task-buttons";
import { useTaskThreads } from "@/core/threads/use-task-threads";
import { titleOfThread } from "@/core/threads/utils";
@@ -78,6 +79,49 @@ function TaskDetailHeader() {
);
}
/**
* xdfx 专用「行动详情」卡片:放在「当前任务」卡片下面。用任务上下文里的「行动id」
* (xdfx 深链原始 ?taskId=)调行动详情接口,展示行动名称 + 叙事。无数据时不渲染。
*/
function ActionDetailHeader() {
const actionId = useMemo(() => readTaskContext()?.actionId ?? "", []);
const [detail, setDetail] = useState<ActionDetail | null>(null);
useEffect(() => {
if (!actionId) return;
let alive = true;
void fetchActionDetail(actionId).then((d) => {
if (alive) setDetail(d);
});
return () => {
alive = false;
};
}, [actionId]);
const name = desensitize((detail?.actionName ?? "").trim());
const narration = desensitize((detail?.narration ?? "").trim());
// 行动名称为空时用「行动 #id」兜底,至少把卡片标出来(mock 行动名/叙事常为空)。
const title = name || (detail?.id ? `行动 #${detail.id}` : "");
if (!title && !narration) return null;
return (
<div className="mb-3 rounded-md border border-[var(--card-border)] bg-background/70 p-2.5 shadow-sm dark:border-[#2b8ffe]/40 dark:bg-[#0b2546]/70">
<div className="text-muted-foreground mb-1 text-[11px] font-medium">行动详情</div>
{title && (
<div className="text-foreground line-clamp-2 text-sm font-semibold leading-snug" title={title}>
{title}
</div>
)}
{narration && (
<div
className="text-muted-foreground mt-1 line-clamp-3 text-xs leading-relaxed"
title={narration}
>
{narration}
</div>
)}
</div>
);
}
/** 从路由路径里解析当前打开的会话 id(布局组件读不到子路由的 :thread_id,故从 path 取)。 */
function parseThreadId(pathname: string, chatsBase: string): string | null {
if (!pathname.startsWith(chatsBase)) return null;
@@ -117,6 +161,8 @@ function TaskConversationsList({
<span className="text-foreground text-sm font-semibold tracking-wide">{businessName}</span>
</div>
<TaskDetailHeader />
{/* xdfx:任务详情下面再展示行动详情 */}
{business === "xdfx" && <ActionDetailHeader />}
<div className="mb-2 flex items-center justify-between gap-2">
<div className="min-w-0">
<div className="text-foreground text-sm font-semibold">任务对话</div>
@@ -274,7 +320,9 @@ export function TaskFxIndexResolver({ taskBase }: { taskBase: string }) {
if (hasThreads && latestThreadId) {
navigate(`${chatsBase}/${latestThreadId}`, { replace: true });
} else {
navigate(`${chatsBase}/new`, { replace: true });
// 首次进入、该任务尚无聊天对话 → /new 并打 taskAutoStart 标记:3qfx/xdfx 直接自动发开场词,
// rwfx 目的树为空时自动开始(用户主动「新建对话」走 TaskConversationsList 的 navigate,不带此标记)。
navigate(`${chatsBase}/new`, { replace: true, state: { taskAutoStart: true } });
}
}, [isLoading, hasThreads, latestThreadId, chatsBase, navigate]);
@@ -308,7 +356,7 @@ export function TaskFxChat({
);
}
/** 右侧对话宿主(3qfx/xdfx):AgentChatPage taskBind → 仅 1:N 绑定,新建对话直接带开场信息自动发出。 */
/** 右侧对话宿主(3qfx/xdfx):AgentChatPage taskBind → 仅 1:N 绑定,新建对话进问答页,右上角「开始回答」按钮手动发出开场信息。 */
export function TaskBindChat({ taskBase }: { taskBase: string }) {
const { agent_id } = useParams<{ agent_id: string }>();
return (