fix: Tab切换延迟渲染重内容,解决区域页切换卡顿
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- 切换Tab时先卸载旧内容显示loading,下一帧再渲染新内容 - 图表等重组件不再阻塞Tab切换动画 - 所有Tab统一处理,切换体验一致 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
30
src/App.tsx
30
src/App.tsx
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect, useCallback, useMemo, useRef, useTransition } from 'react';
|
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
||||||
import {
|
import {
|
||||||
Truck,
|
Truck,
|
||||||
Warehouse,
|
Warehouse,
|
||||||
@@ -114,9 +114,17 @@ const TABS = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [activeTab, setActiveTabRaw] = useState<'overview' | 'department' | 'region' | 'customer'>('overview');
|
const [activeTab, setActiveTab] = useState<'overview' | 'department' | 'region' | 'customer'>('overview');
|
||||||
const [, startTransition] = useTransition();
|
const [tabReady, setTabReady] = useState(true);
|
||||||
const setActiveTab = useCallback((tab: typeof activeTab) => { startTransition(() => setActiveTabRaw(tab)); }, []);
|
const prevTabRef = useRef(activeTab);
|
||||||
|
useEffect(() => {
|
||||||
|
if (prevTabRef.current !== activeTab) {
|
||||||
|
setTabReady(false);
|
||||||
|
prevTabRef.current = activeTab;
|
||||||
|
const id = requestAnimationFrame(() => { setTabReady(true); });
|
||||||
|
return () => cancelAnimationFrame(id);
|
||||||
|
}
|
||||||
|
}, [activeTab]);
|
||||||
const [theme, setTheme] = useState<'soft' | 'minimal' | 'vibrant'>('soft');
|
const [theme, setTheme] = useState<'soft' | 'minimal' | 'vibrant'>('soft');
|
||||||
const [expandedModels, setExpandedModels] = useState<Set<string>>(new Set());
|
const [expandedModels, setExpandedModels] = useState<Set<string>>(new Set());
|
||||||
const [expandedAssetTypes, setExpandedAssetTypes] = useState<Set<string>>(new Set());
|
const [expandedAssetTypes, setExpandedAssetTypes] = useState<Set<string>>(new Set());
|
||||||
@@ -613,7 +621,13 @@ export default function App() {
|
|||||||
{/* Main Content Area */}
|
{/* Main Content Area */}
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-col gap-6">
|
||||||
|
|
||||||
{activeTab === 'overview' && (
|
{!tabReady && (
|
||||||
|
<div className="flex items-center justify-center py-20">
|
||||||
|
<Loader2 className="animate-spin text-blue-500" size={28} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{tabReady && activeTab === 'overview' && (
|
||||||
<>
|
<>
|
||||||
{/* Header Summary - Ultra Compact */}
|
{/* Header Summary - Ultra Compact */}
|
||||||
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-2 mb-2">
|
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-2 mb-2">
|
||||||
@@ -1384,7 +1398,7 @@ export default function App() {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 'department' && (
|
{tabReady && activeTab === 'department' && (
|
||||||
<section className="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden mb-6">
|
<section className="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden mb-6">
|
||||||
<div className="p-0 sm:p-2 bg-gray-50/30">
|
<div className="p-0 sm:p-2 bg-gray-50/30">
|
||||||
{/* Overall Total Summary (Compact) - Moved to Top */}
|
{/* Overall Total Summary (Compact) - Moved to Top */}
|
||||||
@@ -1901,7 +1915,7 @@ export default function App() {
|
|||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 'region' && (
|
{tabReady && activeTab === 'region' && (
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-col gap-6">
|
||||||
{/* Region Distribution Chart */}
|
{/* Region Distribution Chart */}
|
||||||
<section className="bg-white rounded-2xl shadow-sm border border-gray-100 p-4 sm:p-6">
|
<section className="bg-white rounded-2xl shadow-sm border border-gray-100 p-4 sm:p-6">
|
||||||
@@ -2175,7 +2189,7 @@ export default function App() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 'customer' && (
|
{tabReady && activeTab === 'customer' && (
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-col gap-6">
|
||||||
{/* Customer Region Distribution Chart */}
|
{/* Customer Region Distribution Chart */}
|
||||||
<section className="bg-white rounded-2xl shadow-sm border border-gray-100 p-4 sm:p-6">
|
<section className="bg-white rounded-2xl shadow-sm border border-gray-100 p-4 sm:p-6">
|
||||||
|
|||||||
Reference in New Issue
Block a user