import { Activity, Camera, Circle, Copy, Database, Dot, Download, Keyboard, Layers3, MapPinned, Pentagon, Redo2, RefreshCw, Route, Ruler, Share2, Trash2, Undo2, Waypoints, type LucideIcon } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; import { MapAnnotationPanel, type MapAnnotationItem, type MapAnnotationShareAction } from "@/features/map/core/components/annotation-panel"; import type { BaseLayerOption } from "@/features/map/core/components/base-layers-control"; import { MapActionRow, MapControlPanel, MapMetricTile, MapPanelSection } from "@/features/map/core/components/control-panel"; import { MapDrawToolbar } from "@/features/map/core/components/draw-toolbar"; import { MapLayerPanel } from "@/features/map/core/components/layer-panel"; import type { MapLayerControlItem } from "@/features/map/core/components/layer-control"; import { MapLegendList, type MapLegendItem } from "@/features/map/core/components/legend"; import { MapMeasurePanel } from "@/features/map/core/components/measure-panel"; import { type WorkbenchDrawingAnnotation, type WorkbenchDrawMode } from "../hooks/use-workbench-drawing"; import { type WorkbenchMeasurementResult, type WorkbenchMeasureMode, type WorkbenchMeasureUnit } from "../hooks/use-workbench-measurement"; import { waterNetworkToolbarItems } from "../map/toolbar-config"; export type ToolbarToolId = "layers" | "measure" | "analysis" | "annotation" | "more"; export type ExportViewPreset = "current" | "4k"; type MeasureModeOption = { id: WorkbenchMeasureMode; label: string; icon: LucideIcon; }; const MEASURE_MODES: MeasureModeOption[] = [ { id: "distance", label: "距离", icon: Route }, { id: "area", label: "面积", icon: Pentagon }, { id: "segment", label: "管段", icon: Waypoints } ]; const MEASURE_UNITS: Array<{ id: WorkbenchMeasureUnit; label: string }> = [ { id: "m", label: "m" }, { id: "km", label: "km" } ]; const ANNOTATION_SHARE_ACTIONS: MapAnnotationShareAction[] = [ { id: "export", icon: Share2, label: "导出标注", description: "GeoJSON / 截图报告" } ]; const TOOL_PANEL_EXIT_MS = 160; const DRAW_TOOL_OPTIONS: Array<{ id: WorkbenchDrawMode | "undo" | "redo" | "delete" | "clear"; label: string; icon: LucideIcon; tone?: "danger"; }> = [ { id: "point", label: "点标注", icon: Dot }, { id: "line", label: "线标注", icon: Route }, { id: "polygon", label: "范围标注", icon: Pentagon }, { id: "circle", label: "圆形标注", icon: Circle }, { id: "undo", label: "撤销", icon: Undo2 }, { id: "redo", label: "重做", icon: Redo2 }, { id: "delete", label: "删除选中", icon: Trash2, tone: "danger" }, { id: "clear", label: "清空全部", icon: Trash2, tone: "danger" } ]; export type ToolbarPanelProps = { activeToolId: ToolbarToolId | null; activeMeasureModeId: WorkbenchMeasureMode; activeMeasureUnitId: WorkbenchMeasureUnit; measuring: boolean; measureResult: WorkbenchMeasurementResult; measureEnabled: boolean; hasMeasurePoints: boolean; activeDrawToolId: WorkbenchDrawMode | null; drawingEnabled: boolean; drawingAnnotations: WorkbenchDrawingAnnotation[]; canUndoDrawing: boolean; canRedoDrawing: boolean; canDeleteSelectedDrawing: boolean; hasDrawingFeatures: boolean; layerItems: MapLayerControlItem[]; legendItems: MapLegendItem[]; baseLayerOptions: BaseLayerOption[]; activeBaseLayerId: string; onSelectMeasureMode: (id: WorkbenchMeasureMode) => void; onSelectMeasureUnit: (id: WorkbenchMeasureUnit) => void; onStartMeasure: () => void; onStopMeasure: () => void; onClearMeasure: () => void; onCopyMeasure: () => void; onSelectDrawTool: (id: WorkbenchDrawMode | null) => void; onUndoDrawing: () => void; onRedoDrawing: () => void; onDeleteSelectedDrawing: () => void; onClearDrawing: () => void; onExportAnnotations: () => void; onSelectBaseLayer: (id: string) => void; onToggleLayer: (id: string, visible: boolean) => void; onExportView: (preset: ExportViewPreset) => void; onRefreshTiles: () => void; onShowDataStatus: () => void; onShowShortcuts: () => void; onExportConfig: () => void; panelWidthClassName?: string; }; export function ToolbarPanel({ activeToolId, activeMeasureModeId, activeMeasureUnitId, measuring, measureResult, measureEnabled, hasMeasurePoints, activeDrawToolId, drawingEnabled, drawingAnnotations, canUndoDrawing, canRedoDrawing, canDeleteSelectedDrawing, hasDrawingFeatures, layerItems, legendItems, baseLayerOptions, activeBaseLayerId, onSelectMeasureMode, onSelectMeasureUnit, onStartMeasure, onStopMeasure, onClearMeasure, onCopyMeasure, onSelectDrawTool, onUndoDrawing, onRedoDrawing, onDeleteSelectedDrawing, onClearDrawing, onExportAnnotations, onSelectBaseLayer, onToggleLayer, onExportView, onRefreshTiles, onShowDataStatus, onShowShortcuts, onExportConfig, panelWidthClassName }: ToolbarPanelProps) { const annotationItems = useMemo( () => drawingAnnotations.map((annotation) => ({ id: annotation.id, icon: getDrawingAnnotationIcon(annotation.kind), label: annotation.label, description: annotation.description, status: annotation.hidden ? "隐藏" : "显示", selected: annotation.selected, muted: annotation.hidden, onClick: annotation.onToggleVisibility })), [drawingAnnotations] ); const annotationShareActions = useMemo( () => ANNOTATION_SHARE_ACTIONS.map((action) => ({ ...action, onClick: action.id === "export" ? onExportAnnotations : action.onClick })), [onExportAnnotations] ); const [renderedToolId, setRenderedToolId] = useState(activeToolId); const panelVisible = Boolean(activeToolId); useEffect(() => { if (activeToolId) { setRenderedToolId(activeToolId); return; } if (!renderedToolId) { return; } const exitTimer = window.setTimeout(() => { setRenderedToolId(null); }, TOOL_PANEL_EXIT_MS); return () => window.clearTimeout(exitTimer); }, [activeToolId, renderedToolId]); if (!renderedToolId) { return null; } const activeTool = waterNetworkToolbarItems.find((item) => item.id === renderedToolId); const Icon = activeTool?.icon ?? Layers3; if (renderedToolId === "layers") { return ( item.visible).length}/${layerItems.length} 个业务图层可见`} icon={Icon} widthClassName={panelWidthClassName} visible={panelVisible} > ); } if (renderedToolId === "measure") { return ( onSelectMeasureMode(id as WorkbenchMeasureMode)} onSelectUnit={(id) => onSelectMeasureUnit(id as WorkbenchMeasureUnit)} /> ); } if (renderedToolId === "analysis") { return ( ); } if (renderedToolId === "annotation") { return ( ({ ...item, active: activeDrawToolId === item.id, disabled: !drawingEnabled || (item.id === "undo" && !canUndoDrawing) || (item.id === "redo" && !canRedoDrawing) || (item.id === "delete" && !canDeleteSelectedDrawing) || (item.id === "clear" && !canUndoDrawing && !hasDrawingFeatures), onClick: () => { if (item.id === "undo") { onUndoDrawing(); return; } if (item.id === "redo") { onRedoDrawing(); return; } if (item.id === "delete") { onDeleteSelectedDrawing(); return; } if (item.id === "clear") { onClearDrawing(); return; } onSelectDrawTool(activeDrawToolId === item.id ? null : item.id); } }))} /> ); } return ( ); } function AnalysisPanel({ legendItems }: { legendItems: MapLegendItem[] }) { return (
); } type MorePanelProps = { onExportView: (preset: ExportViewPreset) => void; onRefreshTiles: () => void; onShowDataStatus: () => void; onShowShortcuts: () => void; onExportConfig: () => void; }; function MorePanel({ onExportView, onRefreshTiles, onShowDataStatus, onShowShortcuts, onExportConfig }: MorePanelProps) { return (
onExportView("current")} /> onExportView("4k")} />
); } function getDrawingAnnotationIcon(kind: WorkbenchDrawMode) { if (kind === "line") { return Route; } if (kind === "polygon") { return Pentagon; } if (kind === "circle") { return Circle; } return MapPinned; }