fix: Tab切换延迟渲染重内容,解决区域页切换卡顿
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:
kkfluous
2026-03-29 00:35:07 +08:00
parent 799d00b3da
commit 189098cd54

View File

@@ -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">