This commit is contained in:
wintsa 2026-06-01 14:53:26 +08:00
parent c413072afc
commit 01ee0ce1f4
3 changed files with 165 additions and 250 deletions

View File

@ -6,11 +6,13 @@ import {
ModuleRegistry as AgGridModuleRegistry,
type ColDef,
type ColGroupDef,
type GridApi,
type GridReadyEvent,
type ValueFormatterParams,
} from 'ag-grid-community';
import type { AgCartesianChartOptions } from 'ag-charts-community';
import { ModuleRegistry } from 'ag-charts-community';
import { Building2, Construction, LayoutGrid, Library, LocateFixed, MapPinned, Waypoints } from 'lucide-react';
import { Building2, Construction, LayoutGrid, Library, LocateFixed, MapPinned, PanelRightClose, PanelRightOpen, Waypoints } from 'lucide-react';
import {
AnnotationsModule,
ContextMenuModule,
@ -704,6 +706,7 @@ function renderFilterTreeNodes(
function App() {
const workspaceRef = useRef<HTMLElement>(null);
const chartFrameRef = useRef<HTMLDivElement>(null);
const pivotGridApiRef = useRef<GridApi<PivotGridRow> | null>(null);
const treeInitialLoadStartedRef = useRef<Record<ContentKey, boolean>>({
geoLocation: false,
facilityType: false,
@ -723,6 +726,7 @@ function App() {
const [metricKey, setMetricKey] = useState<MetricKey>('cost');
const [chartViewKey, setChartViewKey] = useState<ChartViewKey>('trend');
const [workspaceFullscreen, setWorkspaceFullscreen] = useState(false);
const [rightPanelCollapsed, setRightPanelCollapsed] = useState(false);
const [statisticMenuOpen, setStatisticMenuOpen] = useState(false);
const [metricMenuOpen, setMetricMenuOpen] = useState(false);
const [activeContentKey, setActiveContentKey] = useState<ContentKey>('geoLocation');
@ -837,6 +841,7 @@ function App() {
const pivotToggleActionLabel = chartViewKey === 'pivot' ? '切换到趋势图' : '切换到表格';
const pivotToggleTitle = `${chartViewKey === 'pivot' ? '当前表格' : '当前趋势图'}${pivotToggleActionLabel}`;
const fullscreenToggleLabel = workspaceFullscreen ? '退出全屏' : '全屏';
const rightPanelToggleLabel = rightPanelCollapsed ? '展开选择区' : '收起选择区';
const activeContent = contentOptions.find((option) => option.key === activeContentKey) ?? contentOptions[0];
const activeTree = treeByContent[activeContentKey];
const activeFilter = filterOptions.find((option) => option.key === filterModalKey);
@ -937,14 +942,15 @@ function App() {
{
field: 'year',
headerName: '年度',
minWidth: 68,
width: 74,
minWidth: 58,
width: 64,
},
{
field: 'name',
headerName: '名称',
flex: 1,
minWidth: 108,
minWidth: 86,
tooltipField: 'name',
},
{
headerName: '基准阀值',
@ -953,21 +959,21 @@ function App() {
field: 'lowValue',
headerName: '低值',
type: 'numericColumn',
minWidth: 78,
minWidth: 64,
valueFormatter,
},
{
field: 'centerValue',
headerName: '中心值',
type: 'numericColumn',
minWidth: 78,
minWidth: 68,
valueFormatter,
},
{
field: 'highValue',
headerName: '高值',
type: 'numericColumn',
minWidth: 78,
minWidth: 64,
valueFormatter,
},
],
@ -979,49 +985,49 @@ function App() {
field: 'maxValue',
headerName: '最大值',
type: 'numericColumn',
minWidth: 78,
minWidth: 68,
valueFormatter,
},
{
field: 'minValue',
headerName: '最小值',
type: 'numericColumn',
minWidth: 78,
minWidth: 68,
valueFormatter,
},
{
field: 'avgValue',
headerName: '平均值',
type: 'numericColumn',
minWidth: 78,
minWidth: 68,
valueFormatter,
},
{
field: 'medianValue',
headerName: '中位数',
type: 'numericColumn',
minWidth: 78,
minWidth: 68,
valueFormatter,
},
{
field: 'standardDeviation',
headerName: '标准差',
type: 'numericColumn',
minWidth: 78,
minWidth: 68,
valueFormatter,
},
{
field: 'interquartileRange',
headerName: '四分位距',
type: 'numericColumn',
minWidth: 88,
minWidth: 76,
valueFormatter,
},
{
field: 'coefficientOfVariation',
headerName: '变异系数',
type: 'numericColumn',
minWidth: 88,
minWidth: 76,
valueFormatter: ({ value }: ValueFormatterParams<PivotGridRow, number | null>) => (
value == null ? '' : formatNumber(Number(value), 4)
),
@ -1032,6 +1038,17 @@ function App() {
},
[requestMetricKey],
);
const fitPivotGridColumns = useCallback(() => {
window.requestAnimationFrame(() => {
pivotGridApiRef.current?.sizeColumnsToFit({
defaultMinWidth: 58,
columnLimits: [
{ key: 'year', minWidth: 58, maxWidth: 72 },
{ key: 'name', minWidth: 86, maxWidth: 220 },
],
});
});
}, []);
const selectedNodeKeys = useMemo(
() => new Set(selectedContentNodes.map((node) => getSelectionKey(node.contentKey, node.id))),
[selectedContentNodes],
@ -1916,6 +1933,13 @@ function App() {
toggleWorkspaceFullscreen,
]);
useEffect(() => {
if (chartViewKey !== 'pivot') return;
const timer = window.setTimeout(fitPivotGridColumns, 180);
return () => window.clearTimeout(timer);
}, [chartViewKey, fitPivotGridColumns, metricKey, pivotGridRowData.length, rightPanelCollapsed]);
const chartOptions = useMemo<AgCartesianChartOptions>(() => {
const trendData = groupNames.map((groupName) => {
const row: Record<string, string | number | null> = { groupName };
@ -2184,7 +2208,11 @@ function App() {
))}
</div>
<section className="workspace" aria-label="年度费用模板" ref={workspaceRef}>
<section
className={`workspace${rightPanelCollapsed ? ' is-right-panel-collapsed' : ''}`}
aria-label="年度费用模板"
ref={workspaceRef}
>
{indicatorSelectionLabel ? <div className="chart-indicator-selection-label" title={indicatorSelectionLabel}>{indicatorSelectionLabel}</div> : null}
<div className="chart-filter-bar chart-filter-bar--workspace" aria-label="筛选条件">
{chartFilterOptions.map((option) => {
@ -2315,7 +2343,17 @@ function App() {
sortable: true,
resizable: true,
filter: true,
minWidth: 58,
}}
rowHeight={30}
headerHeight={32}
groupHeaderHeight={32}
onGridReady={(event: GridReadyEvent<PivotGridRow>) => {
pivotGridApiRef.current = event.api;
fitPivotGridColumns();
}}
onGridSizeChanged={fitPivotGridColumns}
onFirstDataRendered={fitPivotGridColumns}
suppressCellFocus
overlayNoRowsTemplate={selectedContentNodes.length === 0 ? '请选择右侧分类项' : '暂无透视数据'}
/>
@ -2329,7 +2367,21 @@ function App() {
</div>
</section>
<aside className="right-panel" aria-label="选择内容">
<button
className="right-panel-toggle"
type="button"
title={rightPanelToggleLabel}
aria-label={rightPanelToggleLabel}
aria-expanded={!rightPanelCollapsed}
onClick={() => setRightPanelCollapsed((collapsed) => !collapsed)}
>
{rightPanelCollapsed ? (
<PanelRightOpen className="right-panel-toggle-icon" aria-hidden="true" strokeWidth={2} />
) : (
<PanelRightClose className="right-panel-toggle-icon" aria-hidden="true" strokeWidth={2} />
)}
</button>
<aside className="right-panel" aria-label="选择内容" aria-hidden={rightPanelCollapsed}>
<div className="content-tabs" role="tablist" aria-label="选择内容切换项">
{contentOptions.map((option) => (
<button

View File

@ -69,10 +69,18 @@ button {
gap: 12px 28px;
height: 100vh;
padding: 30px 28px 18px 64px;
transition: grid-template-columns 160ms ease, gap 160ms ease;
}
.workspace.is-right-panel-collapsed {
grid-template-columns: minmax(0, 1fr) 34px;
gap: 12px 12px;
}
.chart-area {
display: grid;
grid-column: 1;
grid-row: 2;
grid-template-rows: minmax(0, 1fr);
min-width: 0;
}
@ -251,6 +259,11 @@ button {
background: #f5e8d8;
}
.workspace:fullscreen.is-right-panel-collapsed {
grid-template-columns: minmax(0, 1fr) 34px;
gap: 12px 12px;
}
.workspace:fullscreen .chart-area {
min-height: 0;
}
@ -486,13 +499,31 @@ button {
--ag-active-color: #0078a8;
--ag-background-color: #fffaf4;
--ag-border-color: rgba(90, 82, 72, 0.18);
--ag-cell-horizontal-padding: 6px;
--ag-font-family: "Microsoft YaHei", "PingFang SC", "Segoe UI", Arial, sans-serif;
--ag-font-size: 12px;
--ag-foreground-color: #262a33;
--ag-header-cell-horizontal-padding: 6px;
--ag-header-background-color: #f6eadc;
--ag-row-hover-color: rgba(0, 120, 168, 0.08);
}
.chart-pivot-grid-panel .ag-header-cell,
.chart-pivot-grid-panel .ag-header-group-cell {
padding-left: 6px;
padding-right: 6px;
}
.chart-pivot-grid-panel .ag-cell {
padding-left: 6px;
padding-right: 6px;
}
.chart-pivot-grid-panel .ag-header-cell-label,
.chart-pivot-grid-panel .ag-header-group-cell-label {
justify-content: center;
}
.metric-switcher {
position: absolute;
z-index: 12;
@ -734,6 +765,8 @@ button {
.right-panel {
display: grid;
grid-column: 2;
grid-row: 2;
grid-template-rows: auto minmax(0, 1fr);
min-width: 0;
height: 100%;
@ -742,6 +775,52 @@ button {
overflow: hidden;
}
.right-panel-toggle {
display: inline-grid;
grid-column: 2;
grid-row: 2;
justify-self: end;
align-self: start;
width: 28px;
height: 28px;
place-items: center;
padding: 0;
border: 1px solid rgba(90, 82, 72, 0.18);
border-radius: 3px;
color: #46413b;
background: rgba(255, 249, 241, 0.82);
cursor: pointer;
z-index: 4;
}
.right-panel-toggle:hover,
.right-panel-toggle:focus-visible {
color: #0078a8;
border-color: rgba(0, 120, 168, 0.36);
background: rgba(255, 252, 248, 0.96);
box-shadow: 0 1px 5px rgba(69, 54, 36, 0.12);
}
.right-panel-toggle:focus-visible {
outline: 2px solid rgba(0, 120, 168, 0.28);
outline-offset: 2px;
}
.right-panel-toggle-icon {
display: block;
width: 16px;
height: 16px;
}
.workspace.is-right-panel-collapsed .right-panel {
display: none;
}
.workspace.is-right-panel-collapsed .right-panel-toggle {
position: sticky;
top: 24px;
}
.content-tabs {
display: flex;
align-items: center;
@ -1112,14 +1191,27 @@ button {
padding: 8px 18px 18px 56px;
}
.workspace.is-right-panel-collapsed {
grid-template-columns: 1fr;
}
.chart-area {
grid-row: 2;
min-height: 520px;
}
.right-panel {
grid-column: 1;
grid-row: 3;
min-height: 280px;
}
.right-panel-toggle {
grid-column: 1;
grid-row: 3;
justify-self: end;
}
.content-tabs {
flex-wrap: wrap;
}

View File

@ -1,237 +1,8 @@
Port 5173 is in use, trying another one...
VITE v7.3.2 ready in 271 ms
VITE v7.3.2 ready in 303 ms
➜ Local: http://localhost:5174/
➜ Network: http://198.18.0.1:5174/
➜ Network: http://100.106.162.120:5174/
➜ Network: http://192.168.1.155:5174/
➜ Local: http://localhost:5173/
➜ Network: http://100.106.162.120:5173/
➜ Network: http://192.168.1.155:5173/
➜ Network: http://172.31.112.1:5173/
 ➜ press h + enter to show help
15:45:13 [vite] (client) hmr update /src/App.tsx
15:45:39 [vite] (client) hmr update /src/styles.css
15:59:24 [vite] (client) hmr update /src/App.tsx
15:59:52 [vite] (client) hmr update /src/styles.css
16:00:28 [vite] (client) hmr update /src/styles.css
16:00:58 [vite] (client) hmr update /src/styles.css
16:06:48 [vite] (client) hmr update /src/App.tsx
16:07:28 [vite] (client) hmr update /src/App.tsx
16:07:28 [vite] (client) ✨ new dependencies optimized: ag-charts-enterprise, ag-charts-locale
16:07:28 [vite] (client) ✨ optimized dependencies changed. reloading
16:07:47 [vite] (client) hmr update /src/styles.css
16:08:26 [vite] (client) hmr update /src/styles.css
16:09:28 [vite] (client) hmr update /src/App.tsx
16:11:07 [vite] (client) hmr update /src/App.tsx
16:11:48 [vite] (client) hmr update /src/styles.css
16:13:15 [vite] (client) hmr update /src/styles.css
16:17:34 [vite] (client) hmr update /src/App.tsx
16:18:10 [vite] (client) hmr update /src/styles.css
16:22:30 [vite] (client) hmr update /src/App.tsx
16:23:11 [vite] (client) hmr update /src/styles.css
16:24:37 [vite] (client) hmr update /src/App.tsx
16:25:42 [vite] (client) page reload demo.html
16:25:42 [vite] (client) page reload demo.html
16:27:28 [vite] (client) hmr update /src/App.tsx
16:28:39 [vite] (client) hmr update /src/styles.css
16:32:10 [vite] (client) hmr update /src/App.tsx
16:33:55 [vite] (client) hmr update /src/App.tsx
16:38:49 [vite] (client) hmr update /src/App.tsx
16:39:34 [vite] (client) hmr update /src/styles.css
16:46:57 [vite] (client) hmr update /src/App.tsx
16:47:20 [vite] (client) hmr update /src/App.tsx
16:53:41 [vite] (client) hmr update /src/App.tsx
16:54:18 [vite] (client) hmr update /src/styles.css
16:59:35 [vite] (client) hmr update /src/styles.css
17:01:23 [vite] (client) hmr update /src/styles.css
17:03:24 [vite] (client) hmr update /src/styles.css
17:06:50 [vite] (client) hmr update /src/styles.css
17:29:44 [vite] (client) hmr update /src/App.tsx
17:29:52 [vite] (client) hmr update /src/styles.css
17:32:17 [vite] (client) hmr update /src/App.tsx
17:32:43 [vite] (client) hmr update /src/styles.css
17:34:33 [vite] (client) hmr update /src/App.tsx
17:40:09 [vite] (client) hmr update /src/styles.css
17:40:37 [vite] (client) hmr update /src/App.tsx
17:41:32 [vite] (client) hmr update /src/styles.css
17:42:39 [vite] (client) hmr update /src/styles.css
17:44:42 [vite] (client) hmr update /src/App.tsx
09:11:33 [vite] (client) hmr update /src/App.tsx
09:11:59 [vite] (client) hmr update /src/styles.css
09:14:42 [vite] (client) hmr update /src/styles.css
09:15:32 [vite] (client) hmr update /src/styles.css
09:18:16 [vite] (client) hmr update /src/App.tsx
09:18:28 [vite] (client) hmr update /src/styles.css
09:35:28 [vite] (client) hmr update /src/App.tsx
09:35:53 [vite] (client) hmr update /src/App.tsx
09:35:53 [vite] (client) hmr update /src/styles.css
09:36:43 [vite] (client) hmr update /src/App.tsx
09:40:50 [vite] (client) hmr update /src/App.tsx
09:41:06 [vite] (client) hmr update /src/styles.css
09:42:18 [vite] (client) hmr update /src/styles.css
09:55:02 [vite] (client) hmr update /src/App.tsx
09:55:36 [vite] (client) hmr update /src/App.tsx
09:55:49 [vite] (client) hmr update /src/styles.css
10:07:23 [vite] (client) hmr update /src/App.tsx
10:26:33 [vite] (client) hmr update /src/App.tsx
10:27:25 [vite] (client) hmr update /src/App.tsx
10:27:56 [vite] (client) hmr update /src/styles.css
11:14:09 [vite] (client) hmr update /src/App.tsx
11:16:09 [vite] (client) page reload zbChart/index.html
11:17:29 [vite] (client) page reload index.html
11:17:43 [vite] (client) page reload src/main.tsx
11:32:17 [vite] (client) page reload src/main.tsx
11:35:33 [vite] (client) hmr update /src/App.tsx
11:35:45 [vite] (client) hmr update /src/styles.css
11:49:29 [vite] (client) hmr update /src/App.tsx
11:52:03 [vite] (client) hmr update /src/styles.css
11:53:37 [vite] (client) hmr update /src/App.tsx
11:57:22 [vite] (client) hmr update /src/App.tsx
11:59:02 [vite] (client) hmr update /src/App.tsx
15:00:25 [vite] (client) hmr update /src/App.tsx
15:14:46 [vite] (client) hmr update /src/App.tsx
15:14:56 [vite] (client) hmr update /src/App.tsx
15:15:05 [vite] (client) hmr update /src/App.tsx
15:15:18 [vite] (client) hmr update /src/App.tsx
15:15:29 [vite] (client) hmr update /src/App.tsx
15:15:39 [vite] (client) hmr update /src/App.tsx
15:15:49 [vite] (client) hmr update /src/styles.css
15:54:06 [vite] (client) hmr update /src/App.tsx
15:54:29 [vite] (client) hmr update /src/styles.css
16:29:28 [vite] (client) hmr update /src/App.tsx
16:29:37 [vite] (client) hmr update /src/App.tsx
17:53:09 [vite] (client) hmr update /src/App.tsx
17:53:24 [vite] (client) hmr update /src/styles.css
17:54:53 [vite] (client) hmr update /src/App.tsx
17:55:03 [vite] (client) hmr update /src/styles.css
18:10:22 [vite] (client) hmr update /src/App.tsx
09:43:29 [vite] (client) page reload zbChart/index.html
09:43:43 [vite] (client) page reload demo.html
09:44:24 [vite] (client) hmr update /src/App.tsx
09:47:32 [vite] (client) hmr update /src/App.tsx
09:56:50 [vite] (client) hmr update /src/App.tsx
10:03:05 [vite] (client) hmr update /src/App.tsx
10:04:28 [vite] (client) hmr update /src/App.tsx
10:04:35 [vite] (client) hmr update /src/styles.css
10:06:06 [vite] (client) hmr update /src/App.tsx
10:06:25 [vite] (client) hmr update /src/styles.css
14:21:06 [vite] (client) hmr update /src/App.tsx
14:26:18 [vite] (client) hmr update /src/App.tsx
14:26:51 [vite] (client) hmr update /src/styles.css
14:28:15 [vite] (client) hmr update /src/App.tsx
14:28:24 [vite] (client) hmr update /src/App.tsx
15:07:03 [vite] (client) hmr update /src/App.tsx
15:07:31 [vite] (client) hmr update /src/App.tsx
15:08:11 [vite] (client) hmr update /src/App.tsx
15:13:59 [vite] (client) hmr update /src/App.tsx
16:47:31 [vite] (client) hmr update /src/App.tsx
16:48:22 [vite] (client) hmr update /src/App.tsx
16:48:32 [vite] (client) hmr update /src/App.tsx
17:00:07 [vite] (client) hmr update /src/App.tsx
17:15:44 [vite] (client) hmr update /src/App.tsx
18:06:45 [vite] (client) hmr update /src/App.tsx
18:07:01 [vite] (client) hmr update /src/App.tsx
18:07:22 [vite] (client) hmr update /src/App.tsx
18:07:43 [vite] (client) hmr update /src/App.tsx
18:08:03 [vite] (client) hmr update /src/App.tsx
18:08:20 [vite] (client) hmr update /src/App.tsx
18:08:55 [vite] (client) hmr update /src/App.tsx
18:09:09 [vite] (client) hmr update /src/App.tsx
18:09:41 [vite] (client) hmr update /src/App.tsx
18:10:20 [vite] (client) hmr update /src/styles.css
18:11:00 [vite] (client) hmr update /src/styles.css
09:08:22 [vite] (client) hmr update /src/App.tsx
09:09:58 [vite] (client) hmr update /src/App.tsx
09:10:10 [vite] (client) hmr update /src/styles.css
09:12:48 [vite] (client) hmr update /src/styles.css
09:24:09 [vite] (client) hmr update /src/styles.css
09:24:54 [vite] (client) hmr update /src/styles.css
09:25:33 [vite] (client) hmr update /src/App.tsx
09:25:55 [vite] (client) hmr update /src/styles.css
09:31:55 [vite] (client) hmr update /src/App.tsx
09:32:05 [vite] (client) hmr update /src/App.tsx
09:32:12 [vite] (client) hmr update /src/App.tsx
09:32:32 [vite] (client) hmr update /src/styles.css
09:45:56 [vite] (client) hmr update /src/App.tsx
10:00:51 [vite] (client) hmr update /src/App.tsx
10:01:08 [vite] (client) hmr update /src/App.tsx
10:01:23 [vite] (client) hmr update /src/App.tsx
10:01:36 [vite] (client) hmr update /src/App.tsx
10:01:46 [vite] (client) hmr update /src/App.tsx
10:01:56 [vite] (client) hmr update /src/App.tsx
10:02:58 [vite] (client) hmr update /src/App.tsx
10:08:33 [vite] (client) hmr update /src/App.tsx
10:08:56 [vite] (client) hmr update /src/App.tsx
10:09:20 [vite] (client) hmr update /src/styles.css
10:09:29 [vite] (client) hmr update /src/styles.css
10:12:15 [vite] (client) hmr update /src/styles.css
10:17:02 [vite] (client) hmr update /src/App.tsx
10:54:20 [vite] (client) hmr update /src/App.tsx
10:54:44 [vite] (client) hmr update /src/App.tsx
10:59:54 [vite] (client) hmr update /src/App.tsx
11:00:16 [vite] (client) hmr update /src/App.tsx
11:00:32 [vite] (client) hmr update /src/App.tsx
11:00:55 [vite] (client) hmr update /src/App.tsx
11:12:15 [vite] (client) hmr update /src/App.tsx
11:16:52 [vite] (client) hmr update /src/App.tsx
11:20:34 [vite] (client) hmr update /src/App.tsx
11:22:39 [vite] (client) hmr update /src/App.tsx
11:30:32 [vite] (client) hmr update /src/App.tsx
11:42:14 [vite] (client) hmr update /src/App.tsx
11:48:40 [vite] (client) hmr update /src/App.tsx
12:07:11 [vite] (client) hmr update /src/App.tsx
12:07:25 [vite] (client) hmr update /src/App.tsx
12:07:50 [vite] (client) hmr update /src/App.tsx
14:44:40 [vite] (client) hmr update /src/App.tsx
14:47:46 [vite] (client) hmr update /src/App.tsx
14:48:15 [vite] (client) hmr update /src/App.tsx
14:51:05 [vite] (client) hmr update /src/App.tsx
15:13:54 [vite] (client) hmr update /src/App.tsx
15:14:22 [vite] (client) hmr update /src/App.tsx
15:17:54 [vite] (client) hmr update /src/App.tsx
15:18:05 [vite] (client) hmr update /src/App.tsx
15:18:58 [vite] (client) hmr update /src/App.tsx
15:37:07 [vite] (client) hmr update /src/App.tsx
15:37:17 [vite] (client) hmr update /src/App.tsx
15:44:06 [vite] (client) hmr update /src/App.tsx
16:32:19 [vite] (client) hmr update /src/App.tsx
17:15:32 [vite] (client) hmr update /src/App.tsx
15:34:28 [vite] (client) hmr update /src/App.tsx
11:18:46 [vite] (client) hmr update /src/App.tsx
11:18:59 [vite] (client) hmr update /src/App.tsx
11:19:51 [vite] (client) hmr update /src/App.tsx
11:20:06 [vite] (client) hmr update /src/App.tsx
11:20:27 [vite] (client) hmr update /src/App.tsx
11:20:45 [vite] (client) hmr update /src/App.tsx
11:21:04 [vite] (client) hmr update /src/App.tsx
11:21:48 [vite] (client) hmr update /src/App.tsx
11:25:16 [vite] (client) hmr update /src/App.tsx
11:25:34 [vite] (client) hmr update /src/App.tsx
11:33:37 [vite] (client) hmr update /src/styles.css
11:38:01 [vite] (client) hmr update /src/App.tsx
11:38:14 [vite] (client) hmr update /src/App.tsx
11:38:28 [vite] (client) hmr update /src/App.tsx
11:38:42 [vite] (client) hmr update /src/styles.css
11:39:18 [vite] (client) hmr update /src/App.tsx
11:41:08 [vite] (client) hmr update /src/App.tsx
11:48:17 [vite] (client) hmr update /src/App.tsx
11:50:43 [vite] (client) hmr update /src/styles.css
12:07:07 [vite] (client) hmr update /src/App.tsx
12:07:24 [vite] (client) hmr update /src/App.tsx
12:07:45 [vite] (client) hmr update /src/App.tsx
12:08:39 [vite] (client) hmr update /src/App.tsx
12:08:54 [vite] (client) hmr update /src/App.tsx
12:09:23 [vite] (client) hmr update /src/App.tsx
12:09:54 [vite] (client) hmr update /src/App.tsx
12:10:36 [vite] (client) hmr update /src/App.tsx
12:11:14 [vite] (client) hmr update /src/App.tsx
12:12:29 [vite] (client) hmr update /src/App.tsx
12:13:01 [vite] (client) hmr update /src/App.tsx
12:14:05 [vite] (client) hmr update /src/styles.css
12:18:36 [vite] (client) hmr update /src/App.tsx
12:19:03 [vite] (client) hmr update /src/App.tsx
12:22:51 [vite] (client) hmr update /src/App.tsx
12:44:18 [vite] (client) hmr update /src/App.tsx
12:45:27 [vite] (client) hmr update /src/App.tsx
14:35:53 [vite] (client) hmr update /src/App.tsx
15:23:18 [vite] (client) hmr update /src/App.tsx
15:23:36 [vite] (client) hmr update /src/App.tsx
15:41:18 [vite] (client) hmr update /src/App.tsx