feat: expand intelligent investigation workspace
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState, type ReactNode } from "react";
|
||||
import { useEffect, useRef, useState, type ReactNode } from "react";
|
||||
import { InvestigationQuestions } from "./investigation-questions";
|
||||
import { History, LoaderCircle, MessageSquare } from "lucide-react";
|
||||
import { Button } from "@/shared/ui/button";
|
||||
import { Disclosure } from "@/shared/ui/disclosure";
|
||||
@@ -34,6 +35,7 @@ type Props = {
|
||||
onViewExecutionHistory?: (target: TaskExecutionHistoryTarget, knownRunId?: string) => Promise<void> | void;
|
||||
renderAction: (action: OperationalTaskAction) => ReactNode;
|
||||
renderEvidence: (evidence: OperationalTaskEvidence) => ReactNode;
|
||||
onAnswerQuestion?: import("../api/operational-task-client").AnswerTaskQuestion;
|
||||
onLoadReports?: (offset: number) => Promise<OperationalTaskReportPage>;
|
||||
onReportViewed?: (generation: number, revision: number) => void;
|
||||
focusActionId?: string | null;
|
||||
@@ -82,6 +84,12 @@ function investigationTimeline(
|
||||
detail: snapshot.report.current_conclusion
|
||||
});
|
||||
}
|
||||
task.questions?.forEach((question) => {
|
||||
items.push({ id: `question:${question.question_request_id}`, occurredAt: question.created_at,
|
||||
title: "调查提出补充问题", detail: question.questions.map((item) => item.title).join(";") });
|
||||
if (question.answered_at) items.push({ id: `answer:${question.question_request_id}`, occurredAt: question.answered_at,
|
||||
title: "已收到调查回答", detail: "回答已保存为用户补充信息,调查接续处理。" });
|
||||
});
|
||||
task.actions.forEach((action) => {
|
||||
const title = actionTitle(action);
|
||||
items.push({
|
||||
@@ -133,10 +141,14 @@ export function InvestigationTaskReport({
|
||||
renderAction,
|
||||
renderEvidence,
|
||||
onLoadReports,
|
||||
onAnswerQuestion,
|
||||
onReportViewed,
|
||||
focusActionId,
|
||||
onLocate
|
||||
}: Props) {
|
||||
const questionsRef = useRef<HTMLElement>(null);
|
||||
const hasPendingQuestions = task.questions?.some((request) => request.status === "pending"
|
||||
&& request.execution_generation === task.execution_generation) ?? false;
|
||||
// Null follows live task content. Only a deliberate history selection freezes a report.
|
||||
const [selection, setSelection] = useState<ReportSelection | null>(null);
|
||||
const [history, setHistory] = useState<OperationalTaskReport[]>([]);
|
||||
@@ -313,6 +325,8 @@ export function InvestigationTaskReport({
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<InvestigationQuestions task={task} onAnswer={onAnswerQuestion} sectionRef={questionsRef} />
|
||||
|
||||
<InvestigationReportNavigation reportRef={reportRef} sections={sections} />
|
||||
|
||||
{latestAvailable ? (
|
||||
@@ -489,14 +503,19 @@ export function InvestigationTaskReport({
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
discuss(
|
||||
`我要补充“${formatInvestigationText(gap.missing_data)}”相关的现场事实。请说明需要的记录范围和时间信息。`,
|
||||
{ gap_id: gap.gap_id }
|
||||
)
|
||||
}
|
||||
onClick={() => {
|
||||
if (hasPendingQuestions) {
|
||||
questionsRef.current?.scrollIntoView({ block: "start" });
|
||||
questionsRef.current?.focus({ preventScroll: true });
|
||||
} else {
|
||||
discuss(
|
||||
`请帮我讨论“${formatInvestigationText(gap.missing_data)}”这个缺口的查询范围和补齐途径。`,
|
||||
{ gap_id: gap.gap_id }
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
补充事实
|
||||
{hasPendingQuestions ? "回答当前调查问题" : "讨论此缺口"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -548,12 +567,6 @@ export function InvestigationTaskReport({
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
onAsk={(node) =>
|
||||
discuss(
|
||||
`请解释调查脉络中的“${node.label}”及其关联依据。`,
|
||||
node.evidence_refs[0] ? { evidence_id: node.evidence_refs[0] } : undefined
|
||||
)
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user