feat(workbench): integrate runtime data and map tooling
This commit is contained in:
@@ -11,7 +11,11 @@ import { AnimatePresence, motion } from "motion/react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { MAP_TOOL_PANEL_SURFACE_CLASS_NAME, showMapNotice } from "@/features/map/core";
|
||||
import { isGeneratedScheduledConditionSessionId } from "../data/scheduled-conditions";
|
||||
import type { ScheduledConditionItem } from "../types";
|
||||
import type {
|
||||
ScheduledConditionItem,
|
||||
WorkbenchRuntimeDataSource,
|
||||
WorkbenchWorkOrderDataSource
|
||||
} from "../types";
|
||||
import { createConditionConversationPrompt } from "../utils/scheduled-condition-prompts";
|
||||
import { cn } from "@/shared/ui/cn";
|
||||
import {
|
||||
@@ -58,6 +62,8 @@ type ScheduledConditionFeedProps = {
|
||||
expanded?: boolean;
|
||||
focusRequest?: ScheduledConditionFeedFocusRequest | null;
|
||||
loading?: boolean;
|
||||
dataSource?: WorkbenchRuntimeDataSource;
|
||||
workOrderDataSource?: WorkbenchWorkOrderDataSource;
|
||||
visible?: boolean;
|
||||
selectedConditionId?: string | null;
|
||||
onExpandedChange?: (expanded: boolean) => void;
|
||||
@@ -80,6 +86,8 @@ export function ScheduledConditionFeed({
|
||||
expanded: controlledExpanded,
|
||||
focusRequest,
|
||||
loading = false,
|
||||
dataSource = "mock",
|
||||
workOrderDataSource = "mock",
|
||||
visible = true,
|
||||
selectedConditionId: controlledSelectedConditionId,
|
||||
onExpandedChange,
|
||||
@@ -142,13 +150,24 @@ export function ScheduledConditionFeed({
|
||||
const filterActive = taskFilter !== CONDITION_FILTER_ALL || statusFilter !== CONDITION_FILTER_ALL;
|
||||
const totalConditionCount = allRecentConditions.length + allFutureWorkOrders.length;
|
||||
const filteredConditionCount = recentConditions.length + futureWorkOrders.length;
|
||||
const conditionSourceLabel = {
|
||||
mock: "工况演示数据",
|
||||
backend: "后端当天数据",
|
||||
scheduled_tasks: "后端定时任务"
|
||||
}[dataSource];
|
||||
const workOrderSourceLabel = {
|
||||
mock: "工单演示回退",
|
||||
backend: "后端工单",
|
||||
none: "未接入工单"
|
||||
}[workOrderDataSource];
|
||||
const sourceLabel = `${conditionSourceLabel} · ${workOrderSourceLabel}`;
|
||||
const headerSummary = loading
|
||||
? "正在加载工况任务"
|
||||
: expanded && filterActive
|
||||
? `筛选 ${filteredConditionCount}/${totalConditionCount} 条 · 预约 ${futureWorkOrders.length}/${allFutureWorkOrders.length} 条`
|
||||
? `筛选 ${filteredConditionCount}/${totalConditionCount} 条 · 预约 ${futureWorkOrders.length}/${allFutureWorkOrders.length} 条 · ${sourceLabel}`
|
||||
: expanded
|
||||
? `最近 ${recentConditions.length} 条 · 预约 ${futureWorkOrders.length} 条`
|
||||
: `最近 ${recentConditions.length} 条 · 预约 ${futureWorkOrders.length} 条`;
|
||||
? `最近 ${recentConditions.length} 条 · 预约 ${futureWorkOrders.length} 条 · ${sourceLabel}`
|
||||
: `最近 ${recentConditions.length} 条 · 预约 ${futureWorkOrders.length} 条 · ${sourceLabel}`;
|
||||
const selectedCondition =
|
||||
timelineConditions.find((condition) => condition.id === selectedConditionId) ??
|
||||
recentConditions[0] ??
|
||||
@@ -256,7 +275,10 @@ export function ScheduledConditionFeed({
|
||||
}
|
||||
|
||||
if (isGeneratedScheduledConditionSessionId(condition.sessionId)) {
|
||||
void Promise.resolve(onSubmitPrompt(createConditionConversationPrompt(condition)))
|
||||
void Promise.resolve(onSubmitPrompt(createConditionConversationPrompt(
|
||||
condition,
|
||||
condition.dataSource ?? dataSource
|
||||
)))
|
||||
.then(() => {
|
||||
showMapNotice({
|
||||
id: "scheduled-condition-generated-session",
|
||||
@@ -381,6 +403,8 @@ export function ScheduledConditionFeed({
|
||||
) : expanded && selectedCondition ? (
|
||||
<ConditionDetailPanel
|
||||
condition={selectedCondition}
|
||||
dataSource={dataSource}
|
||||
workOrderDataSource={workOrderDataSource}
|
||||
onContinueConversation={() => handleContinueConversation(selectedCondition)}
|
||||
/>
|
||||
) : null}
|
||||
@@ -849,12 +873,16 @@ function ConditionTimelineRow({
|
||||
}: ConditionTimelineRowProps) {
|
||||
const Icon = getStatusIcon(condition.status);
|
||||
const isWorkOrder = condition.kind === "work_order";
|
||||
const workOrderStage = isWorkOrder ? getWorkOrderCurrentStage(condition)?.id : undefined;
|
||||
const workOrderStage = isWorkOrder ? getWorkOrderCurrentStage(condition)?.status : undefined;
|
||||
const tone = isWorkOrder
|
||||
? getWorkOrderStageTone(workOrderStage)
|
||||
? condition.status === "running"
|
||||
? getWorkOrderStageTone(workOrderStage)
|
||||
: getStatusTone(condition.status)
|
||||
: getStatusTone(condition.status);
|
||||
const activity = isWorkOrder
|
||||
? getWorkOrderStageActivity(workOrderStage)
|
||||
? condition.status === "running"
|
||||
? getWorkOrderStageActivity(workOrderStage)
|
||||
: getStatusActivity(condition.status)
|
||||
: getStatusActivity(condition.status);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user