diff --git a/src/App.tsx b/src/App.tsx index 0ebfdaa..cc35a32 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -44,6 +44,8 @@ const metricOptions = [ { key: 'dataCount', label: '数据量' }, ] as const; +const gridMetricOptions = metricOptions.filter((option) => option.key !== 'dataCount'); + const metricShortLabels: Record = { cost: '价', buildingArea: '建', @@ -729,6 +731,7 @@ function App() { const [rightPanelCollapsed, setRightPanelCollapsed] = useState(false); const [statisticMenuOpen, setStatisticMenuOpen] = useState(false); const [metricMenuOpen, setMetricMenuOpen] = useState(false); + const [gridContextMenuPosition, setGridContextMenuPosition] = useState<{ left: number; top: number } | null>(null); const [activeContentKey, setActiveContentKey] = useState('geoLocation'); const [treeByContent, setTreeByContent] = useState>({ geoLocation: [], @@ -979,7 +982,7 @@ function App() { ], }, { - headerName: '样本统计值', + headerName: `样本统计值(${pivotGridRowData.length})`, children: [ { field: 'maxValue', @@ -1036,7 +1039,7 @@ function App() { }, ]; }, - [requestMetricKey], + [pivotGridRowData.length, requestMetricKey], ); const fitPivotGridColumns = useCallback(() => { window.requestAnimationFrame(() => { @@ -1049,6 +1052,29 @@ function App() { }); }); }, []); + const exportPivotGrid = useCallback(() => { + pivotGridApiRef.current?.exportDataAsCsv({ fileName: '组团统计表.csv' }); + setGridContextMenuPosition(null); + }, []); + + useEffect(() => { + if (!gridContextMenuPosition) return; + + const closeMenu = () => setGridContextMenuPosition(null); + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') closeMenu(); + }; + document.addEventListener('mousedown', closeMenu); + document.addEventListener('keydown', handleKeyDown); + window.addEventListener('blur', closeMenu); + window.addEventListener('resize', closeMenu); + return () => { + document.removeEventListener('mousedown', closeMenu); + document.removeEventListener('keydown', handleKeyDown); + window.removeEventListener('blur', closeMenu); + window.removeEventListener('resize', closeMenu); + }; + }, [gridContextMenuPosition]); const selectedNodeKeys = useMemo( () => new Set(selectedContentNodes.map((node) => getSelectionKey(node.contentKey, node.id))), [selectedContentNodes], @@ -1616,9 +1642,16 @@ function App() { }; const togglePivotView = useCallback(() => { - setChartViewKey((current) => (current === 'trend' ? 'pivot' : 'trend')); + setChartViewKey((current) => { + if (current === 'trend') { + setMetricKey((selectedKey) => selectedKey === 'dataCount' ? metricOptions[0].key : selectedKey); + return 'pivot'; + } + return 'trend'; + }); setMetricMenuOpen(false); setStatisticMenuOpen(false); + setGridContextMenuPosition(null); }, []); const toggleWorkspaceFullscreen = useCallback(() => { @@ -1889,10 +1922,6 @@ function App() { handleToolbarAction(button); }; - const suppressBrowserContextMenu = (event: MouseEvent) => { - event.preventDefault(); - }; - const observer = new MutationObserver(syncToolbarButtons); const initialSyncTimers = [ window.setTimeout(syncToolbarButtons, 0), @@ -1902,8 +1931,6 @@ function App() { ]; document.addEventListener('keydown', handleKeyDown, true); document.addEventListener('fullscreenchange', handleFullscreenChange); - document.addEventListener('contextmenu', suppressBrowserContextMenu); - frame.addEventListener('contextmenu', suppressBrowserContextMenu); frame.addEventListener('click', handleToolbarClick, true); frame.addEventListener('keydown', handleToolbarKeyDown, true); observer.observe(frame, { childList: true, subtree: true }); @@ -1913,8 +1940,6 @@ function App() { initialSyncTimers.forEach((timer) => window.clearTimeout(timer)); document.removeEventListener('keydown', handleKeyDown, true); document.removeEventListener('fullscreenchange', handleFullscreenChange); - document.removeEventListener('contextmenu', suppressBrowserContextMenu); - frame.removeEventListener('contextmenu', suppressBrowserContextMenu); frame.removeEventListener('click', handleToolbarClick, true); frame.removeEventListener('keydown', handleToolbarKeyDown, true); observer.disconnect(); @@ -2180,7 +2205,7 @@ function App() { {metricMenuOpen ? (
- {metricOptions.map((option) => ( + {(variant === 'grid' ? gridMetricOptions : metricOptions).map((option) => (
: null} {chartViewKey === 'pivot' ? ( -
+
{ + event.preventDefault(); + setMetricMenuOpen(false); + setStatisticMenuOpen(false); + setGridContextMenuPosition({ + left: Math.max(8, Math.min(event.clientX, window.innerWidth - 132)), + top: Math.max(8, Math.min(event.clientY, window.innerHeight - 44)), + }); + }} + > + {gridContextMenuPosition ? ( +
event.stopPropagation()} + > + +
+ ) : null}