| 12345678910111213141516171819202122232425262728293031 |
- import { ArrowRight, BookOpenCheck, ChevronDown, ChevronUp, FileText, GitBranch } from "lucide-react";
- import { Handle, Position, type NodeProps } from "@xyflow/react";
- import type { CanvasNodeData } from "@/lib/layout";
- import { SourceNoticeBadge, StatusBadge } from "@/components/ui/Badges";
- import { SourceComparisonButton } from "@/components/flow/SourceComparisonButton";
- export function CandidateCard({ data }: NodeProps) {
- const { item, onOpen, onToggleBranch } = data as unknown as CanvasNodeData;
- if (!item || item.itemType !== "branch-summary") return null;
- const summary = item.branch.summary;
- return <article className="flowCard candidateCard" data-focus-return={`${item.id}:card`} aria-label={`候选方案:${item.branch.title}`} tabIndex={0} onKeyDown={(event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); onOpen(item, "business"); } }}>
- <Handle type="target" position={Position.Left} className="flowHandle" /><Handle type="source" position={Position.Right} className="flowHandle" />
- <header className="cardHeader"><span className="candidateLabel">{item.branch.pathType === "领域信息" ? <BookOpenCheck size={14} /> : <GitBranch size={14} />}实现 Agent · 方案 {item.branchId} · {item.branch.pathType === "unknown" ? "类型未记录" : item.branch.pathType}</span><StatusBadge status={item.branch.status} /></header>
- {item.branch.title !== `方案 ${item.branchId}` ? <h3>{item.branch.title}</h3> : null}
- <div className="candidateSummary">
- <SummaryRow label="任务" value={summary.task} />
- <SummaryRow label={item.branch.pathType === "领域信息" ? "领域事实" : "候选产出"} value={summary.output} />
- </div>
- <footer className="cardFooter">
- <button type="button" className="nodeAction nodrag nopan" onClick={(event) => { event.stopPropagation(); onToggleBranch(item.roundIndex, item.branchId); }}>{data.expanded ? <ChevronUp size={14} /> : <ChevronDown size={14} />}{data.expanded ? "收起方案过程" : "展开方案过程"}</button>
- {item.detailRef ? <button type="button" className="nodeAction nodrag nopan" data-focus-return={`${item.id}:business`} onClick={(event) => { event.stopPropagation(); onOpen(item, "business"); }}>查看方案汇总<ArrowRight size={14} /></button> : null}
- <SourceComparisonButton item={item} onOpen={onOpen} />
- {item.branch.output.type === "script-artifact" && item.branch.output.snapshotRef ? <button type="button" className="nodeAction nodrag nopan artifactAction" data-focus-return={`${item.id}:artifact`} onClick={(event) => { event.stopPropagation(); onOpen(item, "artifact"); }}><FileText size={14} />查看完整候选脚本</button> : null}
- </footer>
- <SourceNoticeBadge notice={item.branch.outcome.sourceNotice || item.branch.task.sourceNotice || item.branch.output.node.sourceNotice} />
- </article>;
- }
- function SummaryRow({ label, value }: { label: string; value?: string | null }) {
- return <div><b>{label}</b><p>{value || "未记录"}</p></div>;
- }
|