feat(workbench): redesign investigation reports and diagrams

This commit is contained in:
2026-10-10 16:02:47 +08:00
parent 85a9a3ab45
commit ba78a24384
27 changed files with 2380 additions and 187 deletions
@@ -19,6 +19,8 @@ import type {
} from "../types";
import { createConditionConversationPrompt } from "../utils/scheduled-condition-prompts";
import type { OperationalTaskDecision } from "../api/operational-task-client";
import type { InvestigationDiscussion } from "../api/investigation-report";
import type { OperationalTaskReportPage } from "../api/operational-task-client";
import type { OperationalTaskDataSnapshot } from "../api/operational-task-client";
import { cn } from "@/shared/ui/cn";
import {
@@ -82,7 +84,7 @@ type ScheduledConditionFeedProps = {
onClose?: () => void;
onLoadHistorySession: (sessionId: string) => void | Promise<void>;
onSubmitPrompt: (prompt: string) => void | Promise<void>;
onOpenTaskCollaboration?: (taskId: string) => Promise<void>;
onOpenTaskCollaboration?: (taskId: string, discussion?: InvestigationDiscussion) => Promise<void>;
onTaskDecision?: (taskId: string, actionId: string, expectedVersion: number, decision: OperationalTaskDecision, comment?: string) => Promise<unknown>;
onTaskExecute?: (taskId: string, actionId: string, expectedVersion: number) => Promise<unknown>;
onTaskDraftUpdate?: (taskId: string, actionId: string, expectedVersion: number, payload: Record<string, unknown>) => Promise<unknown>;
@@ -91,12 +93,15 @@ type ScheduledConditionFeedProps = {
onTaskReconcile?: (taskId: string, actionId: string, expectedVersion: number) => Promise<unknown>;
onLoadTaskEvidenceSnapshot?: (taskId: string, evidenceId: string) => Promise<OperationalTaskDataSnapshot>;
onTaskRefresh?: () => void;
onLoadTaskReports?: (taskId: string, offset: number) => Promise<OperationalTaskReportPage>;
onReportViewed?: (taskId: string, generation: number, revision: number) => void;
onRefresh?: () => void | Promise<void>;
};
type ScheduledConditionFeedFocusRequest = {
conditionId: string;
requestId: number;
actionId?: string | null;
};
export function ScheduledConditionFeed({
@@ -127,6 +132,8 @@ export function ScheduledConditionFeed({
onTaskReconcile,
onLoadTaskEvidenceSnapshot,
onTaskRefresh,
onLoadTaskReports,
onReportViewed,
onRefresh
}: ScheduledConditionFeedProps) {
const [uncontrolledExpanded, setUncontrolledExpanded] = useState(false);
@@ -200,6 +207,7 @@ export function ScheduledConditionFeed({
null;
const focusConditionId = focusRequest?.conditionId;
const focusRequestId = focusRequest?.requestId;
const [focusedAction, setFocusedAction] = useState<{ conditionId: string; actionId: string } | null>(null);
const updateExpanded = useCallback(
(nextExpanded: boolean) => {
if (controlledExpanded === undefined) {
@@ -261,12 +269,14 @@ export function ScheduledConditionFeed({
setTaskFilter(CONDITION_FILTER_ALL);
setStatusFilter(CONDITION_FILTER_ALL);
updateSelectedConditionId(targetCondition.id);
setFocusedAction(focusRequest?.actionId ? { conditionId: targetCondition.id, actionId: focusRequest.actionId } : null);
updateExpanded(true);
onFocusRequestHandled?.(focusRequestId);
}, [
conditions,
focusConditionId,
focusRequestId,
focusRequest?.actionId,
onFocusRequestHandled,
updateExpanded,
updateSelectedConditionId
@@ -325,14 +335,14 @@ export function ScheduledConditionFeed({
}
}
function handleContinueConversation(condition: ScheduledConditionItem) {
function handleContinueConversation(condition: ScheduledConditionItem, discussion?: InvestigationDiscussion) {
if (condition.kind === "work_order") {
return;
}
if (condition.operationalTask) {
onExpandAgent();
void Promise.resolve(onOpenTaskCollaboration?.(condition.operationalTask.task_id))
void Promise.resolve(onOpenTaskCollaboration?.(condition.operationalTask.task_id, discussion))
.catch((error) => showMapNotice({
id: "operational-task-collaboration",
tone: "error",
@@ -385,6 +395,7 @@ export function ScheduledConditionFeed({
return (
<section
aria-label="工况任务"
data-task-category={taskCategory}
aria-hidden={!visible}
className={cn(
"scheduled-feed-panel-shell pointer-events-auto overflow-hidden p-3 motion-reduce:transition-none",
@@ -506,14 +517,14 @@ export function ScheduledConditionFeed({
)}
aria-hidden={!expanded}
>
{activeLoading && expanded ? (
{activeLoading && expanded && !selectedCondition ? (
<ConditionDetailSkeleton />
) : expanded && selectedCondition ? (
<ConditionDetailPanel
condition={selectedCondition}
dataSource={dataSource}
workOrderDataSource={workOrderDataSource}
onContinueConversation={() => handleContinueConversation(selectedCondition)}
onContinueConversation={(discussion) => handleContinueConversation(selectedCondition, discussion)}
onTaskDecision={onTaskDecision}
onTaskExecute={onTaskExecute}
onTaskDraftUpdate={onTaskDraftUpdate}
@@ -522,6 +533,9 @@ export function ScheduledConditionFeed({
onTaskReconcile={onTaskReconcile}
onLoadTaskEvidenceSnapshot={onLoadTaskEvidenceSnapshot}
onTaskRefresh={onTaskRefresh}
onLoadTaskReports={onLoadTaskReports}
onReportViewed={onReportViewed}
focusActionId={focusedAction?.conditionId === selectedConditionId ? focusedAction.actionId : undefined}
/>
) : null}
</div>
@@ -1098,14 +1112,15 @@ function ConditionTimelineRow({
>
<span className="flex min-w-0 items-center gap-2">
<span className="min-w-0 flex-1">
<span className="block truncate text-xs font-semibold leading-4">
<span className="scheduled-condition-title block truncate text-xs font-semibold leading-4">
{condition.title}
</span>
<span className="block truncate text-xs leading-4 text-[var(--ink-muted)]">
{condition.summary}
</span>
</span>
<StatusPill condition={condition} className="shrink-0 text-xs" />
<StatusPill condition={condition} className="scheduled-condition-status shrink-0 text-xs" />
{condition.kind === "condition" && condition.hasNewReport ? <span className="text-xs font-medium text-[var(--action-blue)]">新报告</span> : null}
</span>
</span>
</button>