feat(workbench): integrate runtime data and map tooling
This commit is contained in:
@@ -33,6 +33,8 @@ import {
|
||||
import { env } from "@/shared/config/env";
|
||||
import type { AccessTokenProvider } from "@/shared/auth/keycloak-auth";
|
||||
import { AgentTaskTicker } from "./components/agent-task-ticker";
|
||||
import { AnalysisResultsPanel } from "./components/analysis-results-panel";
|
||||
import { PeripheralSamplePanel } from "./peripheral-sample/peripheral-sample-panel";
|
||||
import { MapDevPanel } from "./components/map-dev-panel";
|
||||
import { MobileWorkbenchSheet } from "./components/mobile-workbench-sheet";
|
||||
import { FeaturePopover } from "./components/feature-popover";
|
||||
@@ -62,13 +64,17 @@ import {
|
||||
createInitialWorkspaceContext,
|
||||
reduceWorkspaceContext
|
||||
} from "./workspace/workspace-context";
|
||||
import { WORKBENCH_SCENARIOS, WORKBENCH_USER } from "./data/workbench-session";
|
||||
import { WORKBENCH_USER } from "./data/workbench-session";
|
||||
import { useWorkbenchAgent } from "./hooks/use-workbench-agent";
|
||||
import { useWorkbenchDrawing, type WorkbenchDrawMode } from "./hooks/use-workbench-drawing";
|
||||
import { useWorkbenchMap } from "./hooks/use-workbench-map";
|
||||
import { useWorkbenchMapController } from "./hooks/use-workbench-map-controller";
|
||||
import { useWorkbenchProjectPresentation } from "./hooks/use-workbench-project-presentation";
|
||||
import { useWorkbenchResponsiveLayout } from "./hooks/use-workbench-responsive-layout";
|
||||
import { useWorkbenchRuntimeData } from "./hooks/use-workbench-runtime-data";
|
||||
import {
|
||||
formatHeaderDataTime,
|
||||
useWorkbenchRuntimeData
|
||||
} from "./hooks/use-workbench-runtime-data";
|
||||
import { toMapFeatureReference } from "./hooks/use-map-interactions";
|
||||
import {
|
||||
useWorkbenchMeasurement,
|
||||
@@ -87,9 +93,9 @@ import { parseScadaAnalysisItems } from "./map/scada-analysis";
|
||||
import {
|
||||
BASE_LAYER_OPTIONS,
|
||||
INITIAL_LAYER_VISIBILITY,
|
||||
MAP_LEGEND_ITEMS,
|
||||
applyBaseLayerVisibility,
|
||||
createLayerControlItems,
|
||||
createVisibleMapLegendItems,
|
||||
getWorkbenchLayerIds
|
||||
} from "./map/map-control-config";
|
||||
import { waterNetworkToolbarItems } from "./map/toolbar-config";
|
||||
@@ -100,10 +106,7 @@ import type {
|
||||
WorkbenchAlert,
|
||||
WorkbenchUser
|
||||
} from "./types";
|
||||
import {
|
||||
createScheduledConditionAlerts,
|
||||
getScheduledConditionIdFromAlertId
|
||||
} from "./utils/scheduled-condition-alerts";
|
||||
import { getScheduledConditionIdFromAlertId } from "./utils/scheduled-condition-alerts";
|
||||
import { createAlertQueueConversationPrompt } from "./utils/scheduled-condition-prompts";
|
||||
|
||||
const WORKBENCH_LAYOUT_CSS_VARIABLES = getWorkbenchLayoutCssVariables();
|
||||
@@ -119,6 +122,7 @@ export function MapWorkbenchPage({
|
||||
}) {
|
||||
const hasMapboxToken = Boolean(env.TJWATER_MAPBOX_ACCESS_TOKEN);
|
||||
const devPanelEnabled = env.TJWATER_ENABLE_DEV_PANEL;
|
||||
const projectPresentation = useWorkbenchProjectPresentation(user, getAccessToken);
|
||||
const mapContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [detailFeature, setDetailFeature] = useState<DetailFeature | null>(null);
|
||||
const [devPanelOpen, setDevPanelOpen] = useState(false);
|
||||
@@ -126,6 +130,8 @@ export function MapWorkbenchPage({
|
||||
const [activeToolId, setActiveToolId] = useState<ToolbarToolId | null>(null);
|
||||
const prefersReducedMotion = useReducedMotion();
|
||||
const [taskTickerVisible, setTaskTickerVisible] = useState(true);
|
||||
const [analysisResultsPanelOpen, setAnalysisResultsPanelOpen] = useState(false);
|
||||
const [peripheralSamplePanelOpen, setPeripheralSamplePanelOpen] = useState(false);
|
||||
const [selectedConditionId, setSelectedConditionId] = useState<string | null>(null);
|
||||
const [conditionFocusRequest, setConditionFocusRequest] = useState<{
|
||||
conditionId: string;
|
||||
@@ -135,15 +141,26 @@ export function MapWorkbenchPage({
|
||||
hasMapboxToken ? "mapbox-light" : "none"
|
||||
);
|
||||
const basemapTone = getWorkbenchBasemapTone(activeBaseLayerId);
|
||||
const [activeScenarioId, setActiveScenarioId] = useState(WORKBENCH_SCENARIOS[0]?.id ?? "");
|
||||
const [activeMeasureModeId, setActiveMeasureModeId] = useState<WorkbenchMeasureMode>("distance");
|
||||
const [activeMeasureUnitId, setActiveMeasureUnitId] = useState<WorkbenchMeasureUnit>("km");
|
||||
const [activeDrawToolId, setActiveDrawToolId] = useState<WorkbenchDrawMode | null>(null);
|
||||
const [layerVisibility, setLayerVisibility] =
|
||||
useState<Record<string, boolean>>(INITIAL_LAYER_VISIBILITY);
|
||||
const [agentUiResults, setAgentUiResults] = useState<AgentUiResult[]>([]);
|
||||
const { headerDataTime, scheduledConditions, scheduledConditionsLoading } =
|
||||
useWorkbenchRuntimeData();
|
||||
const {
|
||||
headerDataTime,
|
||||
scheduledConditions,
|
||||
scheduledConditionsLoading,
|
||||
workbenchAlerts,
|
||||
runtimeDataSource,
|
||||
alertDataSource,
|
||||
latestAnalysisArtifact,
|
||||
workOrderDataSource,
|
||||
realtimePipeFlows,
|
||||
flowDataSource,
|
||||
operationalDate,
|
||||
operationalCursorTime
|
||||
} = useWorkbenchRuntimeData(getAccessToken);
|
||||
const baseLayerOptions = useMemo(
|
||||
() =>
|
||||
BASE_LAYER_OPTIONS.map((option) => ({
|
||||
@@ -204,13 +221,29 @@ export function MapWorkbenchPage({
|
||||
const businessWorkspaceWidth = Math.max(0, viewportWidth - currentAgentWidth);
|
||||
const artifactWorkspace = useArtifactWorkspace(businessWorkspaceWidth);
|
||||
const artifactActive = artifactWorkspace.activeArtifact !== null;
|
||||
const activeSpatialOverlay = artifactWorkspace.activeArtifact?.spatialOverlay ?? null;
|
||||
const activeArtifactHasSpatialView = Boolean(activeSpatialOverlay?.features.length);
|
||||
const allowDemoSimulation = artifactWorkspace.activeArtifact === null
|
||||
|| artifactWorkspace.activeArtifact.origin === "demo";
|
||||
const latestAnalysisAvailable = Boolean(
|
||||
latestAnalysisArtifact?.blocks.some((block) =>
|
||||
block.kind === "chart" || block.kind === "data-table" || block.kind === "process-flow"
|
||||
)
|
||||
);
|
||||
const [timelineMode, setTimelineMode] = useState<OperationalTimelineMode>("compact");
|
||||
const [timelineVisible, setTimelineVisible] = useState(true);
|
||||
const [workspaceContext, dispatchWorkspaceContext] = useReducer(
|
||||
reduceWorkspaceContext,
|
||||
undefined,
|
||||
() => createInitialWorkspaceContext()
|
||||
() => createInitialWorkspaceContext(new Date(operationalCursorTime))
|
||||
);
|
||||
useEffect(() => {
|
||||
if (workspaceContext.operational.date === operationalDate) return;
|
||||
dispatchWorkspaceContext({
|
||||
type: "return-operational-now",
|
||||
now: operationalCursorTime
|
||||
});
|
||||
}, [operationalCursorTime, operationalDate, workspaceContext.operational.date]);
|
||||
const operationalEvents = useMemo(
|
||||
() => createOperationalEvents(scheduledConditions),
|
||||
[scheduledConditions]
|
||||
@@ -243,6 +276,13 @@ export function MapWorkbenchPage({
|
||||
});
|
||||
}, [artifactWorkspace.activeArtifact]);
|
||||
|
||||
useEffect(() => {
|
||||
setImpactVisible(activeArtifactHasSpatialView);
|
||||
setLayerVisibility((current) => current.simulation === activeArtifactHasSpatialView
|
||||
? current
|
||||
: { ...current, simulation: activeArtifactHasSpatialView });
|
||||
}, [activeArtifactHasSpatialView, artifactWorkspace.activeArtifact?.id]);
|
||||
|
||||
function openAgentWorkspaceForViewport() {
|
||||
openAgentPanelForViewport();
|
||||
}
|
||||
@@ -268,8 +308,10 @@ export function MapWorkbenchPage({
|
||||
mapError,
|
||||
sourceStatuses,
|
||||
availableSourceIds,
|
||||
sourceFeatureCounts,
|
||||
fitNetworkBounds,
|
||||
getScadaFeatures,
|
||||
scadaObservedAt,
|
||||
refreshGeoServerLayers
|
||||
} = useWorkbenchMap({
|
||||
containerRef: mapContainerRef,
|
||||
@@ -278,8 +320,15 @@ export function MapWorkbenchPage({
|
||||
onClearSelection: handleClearSelection,
|
||||
onSelectFeature: handleSelectFeature,
|
||||
selectedFeature: detailFeature,
|
||||
simulationOverlay: activeSpatialOverlay,
|
||||
allowDemoSimulation,
|
||||
networkView: projectPresentation.networkView,
|
||||
getAccessToken
|
||||
});
|
||||
const displayedDataTime = !["demo", "history"].includes(env.TJWATER_WORKBENCH_RUNTIME_MODE)
|
||||
&& scadaObservedAt
|
||||
? formatHeaderDataTime(new Date(scadaObservedAt), false)
|
||||
: headerDataTime;
|
||||
const { controller: mapController, state: mapControllerState } = useWorkbenchMapController({
|
||||
mapRef,
|
||||
mapReady,
|
||||
@@ -291,24 +340,29 @@ export function MapWorkbenchPage({
|
||||
availableSourceIds
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!mapReady) return;
|
||||
if (realtimePipeFlows) {
|
||||
void mapController.replacePipeFlowCalculations(realtimePipeFlows.records);
|
||||
return;
|
||||
}
|
||||
void mapController.clearPipeFlowCalculations();
|
||||
}, [mapController, mapReady, realtimePipeFlows]);
|
||||
|
||||
const activeAgentUiResults = useMemo(
|
||||
() => agentUiResults.filter((result) => result.sessionId === agent.sessionId),
|
||||
[agent.sessionId, agentUiResults]
|
||||
);
|
||||
const conditionAlerts = useMemo(
|
||||
() => createScheduledConditionAlerts(scheduledConditions),
|
||||
[scheduledConditions]
|
||||
);
|
||||
const runningTickerConditions = useMemo(
|
||||
const runningTickerConditions = useMemo<ScheduledConditionRecord[]>(
|
||||
() =>
|
||||
scheduledConditions.filter(
|
||||
(condition): condition is ScheduledConditionRecord =>
|
||||
condition.kind === "condition" && condition.status === "running"
|
||||
),
|
||||
scheduledConditions.reduce<ScheduledConditionRecord[]>((runningConditions, condition) => {
|
||||
if (condition.kind === "condition" && condition.status === "running") {
|
||||
runningConditions.push(condition);
|
||||
}
|
||||
return runningConditions;
|
||||
}, []),
|
||||
[scheduledConditions]
|
||||
);
|
||||
const workbenchAlerts = conditionAlerts;
|
||||
|
||||
const drawing = useWorkbenchDrawing({
|
||||
mapRef,
|
||||
mapReady,
|
||||
@@ -327,6 +381,7 @@ export function MapWorkbenchPage({
|
||||
!artifactActive
|
||||
&& mobileSheet === null
|
||||
&& !conditionFeedExpanded
|
||||
&& detailFeature === null
|
||||
&& taskTickerVisible
|
||||
&& taskTickerAvailable;
|
||||
const taskTickerEnterState = prefersReducedMotion
|
||||
@@ -424,10 +479,10 @@ export function MapWorkbenchPage({
|
||||
}, [mapController]);
|
||||
|
||||
const handleReturnOperationalNow = useCallback(() => {
|
||||
dispatchWorkspaceContext({ type: "return-operational-now", now: new Date().toISOString() });
|
||||
dispatchWorkspaceContext({ type: "return-operational-now", now: operationalCursorTime });
|
||||
dispatchWorkspaceContext({ type: "clear-spatial-feature" });
|
||||
mapController.clearHighlight();
|
||||
}, [mapController]);
|
||||
}, [mapController, operationalCursorTime]);
|
||||
|
||||
const toolbarItems = useMemo<MapToolbarItem[]>(
|
||||
() =>
|
||||
@@ -441,8 +496,12 @@ export function MapWorkbenchPage({
|
||||
);
|
||||
|
||||
const layerControlItems = useMemo(
|
||||
() => createLayerControlItems(layerVisibility, availableSourceIds),
|
||||
[availableSourceIds, layerVisibility]
|
||||
() => createLayerControlItems(layerVisibility, availableSourceIds, sourceFeatureCounts),
|
||||
[availableSourceIds, layerVisibility, sourceFeatureCounts]
|
||||
);
|
||||
const visibleLegendItems = useMemo(
|
||||
() => createVisibleMapLegendItems(layerControlItems),
|
||||
[layerControlItems]
|
||||
);
|
||||
function handleToggleLayer(layerControlId: string, visible: boolean) {
|
||||
const map = mapRef.current;
|
||||
@@ -545,48 +604,9 @@ export function MapWorkbenchPage({
|
||||
});
|
||||
}
|
||||
|
||||
function handleSelectScenario(scenarioId: string) {
|
||||
const scenario = WORKBENCH_SCENARIOS.find((item) => item.id === scenarioId);
|
||||
setActiveScenarioId(scenarioId);
|
||||
showMapNotice({
|
||||
tone: "success",
|
||||
title: "方案已切换",
|
||||
message: `当前方案:${scenario?.name ?? scenarioId}。地图模拟结果暂未自动切换。`
|
||||
});
|
||||
}
|
||||
|
||||
function handlePreviewScenario() {
|
||||
setImpactVisible(true);
|
||||
setLayerVisibility((current) => ({ ...current, simulation: true }));
|
||||
|
||||
const map = mapRef.current;
|
||||
if (map && mapReady) {
|
||||
getWorkbenchLayerIds(map, "simulation").forEach((layerId) => {
|
||||
map.setLayoutProperty(layerId, "visibility", "visible");
|
||||
});
|
||||
}
|
||||
|
||||
showMapNotice({
|
||||
tone: "info",
|
||||
title: "预览影响范围",
|
||||
message: "已打开模拟结果图层,可在右侧图层面板继续调整显示。"
|
||||
});
|
||||
}
|
||||
|
||||
function handleCompareScenario() {
|
||||
showMapNotice({
|
||||
tone: "info",
|
||||
title: "方案比较",
|
||||
message: "候选方案比较将汇总影响范围、阀门操作与保供风险。"
|
||||
});
|
||||
}
|
||||
|
||||
function handleExportScenarioReport() {
|
||||
showMapNotice({
|
||||
tone: "success",
|
||||
title: "场景报告",
|
||||
message: "已生成当前场景报告任务,可继续导出地图截图或配置。"
|
||||
});
|
||||
function handleOpenLatestAnalysis() {
|
||||
if (!latestAnalysisArtifact || !latestAnalysisAvailable) return;
|
||||
artifactWorkspace.openArtifact(latestAnalysisArtifact);
|
||||
}
|
||||
|
||||
async function handleAnalyzeAlertsWithAgent() {
|
||||
@@ -610,7 +630,8 @@ export function MapWorkbenchPage({
|
||||
await agent.submitPrompt(
|
||||
createAlertQueueConversationPrompt({
|
||||
alerts: workbenchAlerts,
|
||||
conditions: scheduledConditions
|
||||
conditions: scheduledConditions,
|
||||
dataSource: alertDataSource
|
||||
})
|
||||
);
|
||||
|
||||
@@ -629,7 +650,7 @@ export function MapWorkbenchPage({
|
||||
}
|
||||
|
||||
function handleSelectAlert(alert: WorkbenchAlert) {
|
||||
const conditionId = getScheduledConditionIdFromAlertId(alert.id);
|
||||
const conditionId = alert.conditionId ?? getScheduledConditionIdFromAlertId(alert.id);
|
||||
if (conditionId) {
|
||||
const condition = scheduledConditions.find((item) => item.id === conditionId);
|
||||
if (!condition) {
|
||||
@@ -858,7 +879,7 @@ export function MapWorkbenchPage({
|
||||
canDeleteSelectedDrawing: drawing.canDeleteSelected,
|
||||
hasDrawingFeatures: drawing.hasFeatures,
|
||||
layerItems: layerControlItems,
|
||||
legendItems: MAP_LEGEND_ITEMS,
|
||||
legendItems: visibleLegendItems,
|
||||
baseLayerOptions,
|
||||
activeBaseLayerId,
|
||||
onSelectMeasureMode: setActiveMeasureModeId,
|
||||
@@ -929,6 +950,7 @@ export function MapWorkbenchPage({
|
||||
approvalMode: agent.approvalMode,
|
||||
uiResults: activeAgentUiResults,
|
||||
workspaceContext: agentWorkspaceContext,
|
||||
prompt: agent.promptDraft,
|
||||
onRefreshHistory: agent.refreshSessionHistory,
|
||||
onStartNewSession: handleStartNewAgentSession,
|
||||
onLoadHistorySession: handleLoadAgentHistorySession,
|
||||
@@ -936,6 +958,7 @@ export function MapWorkbenchPage({
|
||||
onDeleteHistorySession: handleDeleteAgentHistorySession,
|
||||
onSelectModel: agent.setSelectedModel,
|
||||
onApprovalModeChange: agent.setApprovalMode,
|
||||
onPromptChange: agent.setPromptDraft,
|
||||
onSubmitPrompt: agent.submitPrompt,
|
||||
onStopPrompt: agent.stopPrompt,
|
||||
onReplyPermission: agent.replyPermission,
|
||||
@@ -956,29 +979,35 @@ export function MapWorkbenchPage({
|
||||
}
|
||||
>
|
||||
<WorkbenchTopBar
|
||||
dataTime={headerDataTime}
|
||||
modelName="AquaDispatch v1.0"
|
||||
scenarios={WORKBENCH_SCENARIOS}
|
||||
activeScenarioId={activeScenarioId}
|
||||
dataTime={displayedDataTime}
|
||||
modelName={agent.modelOptions.find((option) => option.id === agent.selectedModel)?.label
|
||||
|| agent.selectedModel
|
||||
|| "Agent 后端连接中"}
|
||||
activeAnalysisArtifact={artifactWorkspace.activeArtifact}
|
||||
alerts={workbenchAlerts}
|
||||
user={user}
|
||||
alertDataSource={alertDataSource}
|
||||
user={projectPresentation.user}
|
||||
conditionFeedVisible={isLargeScreen ? shouldShowConditionFeed : mobileSheet === "condition"}
|
||||
timelineVisible={timelineVisible}
|
||||
taskTickerAvailable={taskTickerAvailable}
|
||||
taskTickerVisible={taskTickerVisible}
|
||||
analysisResultsPanelOpen={analysisResultsPanelOpen}
|
||||
peripheralSamplePanelOpen={peripheralSamplePanelOpen}
|
||||
devPanelEnabled={devPanelEnabled}
|
||||
devPanelOpen={devPanelOpen}
|
||||
onSelectScenario={handleSelectScenario}
|
||||
onSelectAlert={handleSelectAlert}
|
||||
onToggleConditionFeed={toggleConditionWorkspaceForViewport}
|
||||
onToggleTimeline={toggleTimelineVisibility}
|
||||
onToggleTaskTicker={() => setTaskTickerVisible((current) => !current)}
|
||||
onToggleAnalysisResultsPanel={() => { setPeripheralSamplePanelOpen(false); setAnalysisResultsPanelOpen((current) => !current); }}
|
||||
onTogglePeripheralSamplePanel={() => { setAnalysisResultsPanelOpen(false); setPeripheralSamplePanelOpen((current) => !current); }}
|
||||
onToggleDevPanel={() => setDevPanelOpen((current) => !current)}
|
||||
onPreviewScenario={handlePreviewScenario}
|
||||
onCompareScenario={handleCompareScenario}
|
||||
onExportScenarioReport={handleExportScenarioReport}
|
||||
onAnalyzeAlertsWithAgent={handleAnalyzeAlertsWithAgent}
|
||||
onCreateTestAnalysis={artifactWorkspace.createTestArtifactPreview}
|
||||
latestAnalysisAvailable={latestAnalysisAvailable}
|
||||
analysisSplitAvailable={artifactWorkspace.mapSplitAvailable}
|
||||
onOpenLatestAnalysis={handleOpenLatestAnalysis}
|
||||
onSetAnalysisView={artifactWorkspace.setView}
|
||||
onCloseAnalysisView={artifactWorkspace.destroyArtifact}
|
||||
onShowDataStatus={handleShowDataStatus}
|
||||
onRefreshTiles={handleRefreshTiles}
|
||||
onShowShortcuts={handleShowShortcuts}
|
||||
@@ -986,6 +1015,22 @@ export function MapWorkbenchPage({
|
||||
onLogout={onLogout}
|
||||
/>
|
||||
|
||||
<AnalysisResultsPanel
|
||||
open={analysisResultsPanelOpen}
|
||||
onClose={() => setAnalysisResultsPanelOpen(false)}
|
||||
getAccessToken={getAccessToken}
|
||||
onOpenArtifact={(artifact) => {
|
||||
artifactWorkspace.openArtifact(artifact);
|
||||
setAnalysisResultsPanelOpen(false);
|
||||
}}
|
||||
/>
|
||||
|
||||
<PeripheralSamplePanel
|
||||
open={peripheralSamplePanelOpen}
|
||||
onClose={() => setPeripheralSamplePanelOpen(false)}
|
||||
getAccessToken={getAccessToken}
|
||||
/>
|
||||
|
||||
<WorkbenchMainFrame
|
||||
activeArtifact={artifactWorkspace.activeArtifact}
|
||||
pendingArtifact={artifactWorkspace.pendingArtifact}
|
||||
@@ -1049,12 +1094,16 @@ export function MapWorkbenchPage({
|
||||
)}
|
||||
mapOverlay={(
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<div className="pointer-events-auto absolute right-3 top-3 hidden lg:block">
|
||||
<MapToolbar items={toolbarItems} />
|
||||
</div>
|
||||
<div className="pointer-events-auto absolute right-16 top-3 hidden lg:block">
|
||||
<ToolbarPanel {...toolbarPanelProps} />
|
||||
</div>
|
||||
{!devPanelOpen ? (
|
||||
<>
|
||||
<div className="pointer-events-auto absolute right-3 top-10 hidden lg:block">
|
||||
<MapToolbar items={toolbarItems} />
|
||||
</div>
|
||||
<div className="pointer-events-auto absolute right-16 top-10 hidden lg:block">
|
||||
<ToolbarPanel {...toolbarPanelProps} />
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
<div
|
||||
className="absolute right-3 flex flex-col items-end gap-2 bottom-[var(--mobile-map-control-bottom)] transition-[bottom] duration-200 ease-out motion-reduce:transition-none lg:right-0 lg:bottom-[var(--desktop-map-scale-bottom)]"
|
||||
style={{
|
||||
@@ -1092,6 +1141,8 @@ export function MapWorkbenchPage({
|
||||
<ScheduledConditionFeed
|
||||
presentation="desktop-floating"
|
||||
conditions={scheduledConditions}
|
||||
dataSource={runtimeDataSource}
|
||||
workOrderDataSource={workOrderDataSource}
|
||||
expanded={conditionFeedExpanded}
|
||||
focusRequest={conditionFocusRequest}
|
||||
loading={scheduledConditionsLoading}
|
||||
@@ -1112,6 +1163,7 @@ export function MapWorkbenchPage({
|
||||
commands={mapController}
|
||||
controllerState={mapControllerState}
|
||||
detailFeature={detailFeature}
|
||||
flowDataSource={flowDataSource}
|
||||
onClose={() => setDevPanelOpen(false)}
|
||||
/>
|
||||
) : null}
|
||||
@@ -1146,7 +1198,11 @@ export function MapWorkbenchPage({
|
||||
animate={taskTickerEnterState}
|
||||
exit={taskTickerExitState}
|
||||
>
|
||||
<AgentTaskTicker className="w-full max-w-full" conditions={runningTickerConditions} />
|
||||
<AgentTaskTicker
|
||||
className="w-full max-w-full"
|
||||
conditions={runningTickerConditions}
|
||||
dataSource={runtimeDataSource}
|
||||
/>
|
||||
</motion.div>
|
||||
) : null}
|
||||
</AnimatePresence>
|
||||
@@ -1222,6 +1278,8 @@ export function MapWorkbenchPage({
|
||||
<ScheduledConditionFeed
|
||||
presentation="mobile-sheet"
|
||||
conditions={scheduledConditions}
|
||||
dataSource={runtimeDataSource}
|
||||
workOrderDataSource={workOrderDataSource}
|
||||
expanded={conditionFeedExpanded}
|
||||
focusRequest={conditionFocusRequest}
|
||||
loading={scheduledConditionsLoading}
|
||||
@@ -1239,7 +1297,12 @@ export function MapWorkbenchPage({
|
||||
</MobileWorkbenchSheet>
|
||||
) : null}
|
||||
|
||||
<FeaturePopover feature={detailFeature} onClose={() => setDetailFeature(null)} />
|
||||
<FeaturePopover
|
||||
feature={detailFeature}
|
||||
projectId={projectPresentation.projectId}
|
||||
getAccessToken={getAccessToken}
|
||||
onClose={() => setDetailFeature(null)}
|
||||
/>
|
||||
|
||||
{!mapReady && !mapError ? (
|
||||
<MapLoadingNotice message="正在加载底图样式、管网数据源和交互图层。" />
|
||||
|
||||
Reference in New Issue
Block a user