diff --git a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.test.tsx b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.test.tsx
new file mode 100644
index 00000000..6a12d492
--- /dev/null
+++ b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.test.tsx
@@ -0,0 +1,43 @@
+import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react';
+import { afterEach, expect, test, vi } from 'vitest';
+import { MemoryRouter, Route, Routes } from 'react-router-dom';
+import { ROUTER_FUTURE } from '../routing/routerConfig';
+
+const routing = vi.hoisted(() => ({
+ preloadRoute: vi.fn(async () => undefined),
+ scheduleIdleRoutePreloads: vi.fn(() => vi.fn()),
+ shouldPreloadRouteOnIntent: vi.fn(() => true)
+}));
+
+vi.mock('../routing/routeModules', () => routing);
+vi.mock('../auth/AuthGate', () => ({
+ usePlatformSession: () => ({ session: { name: 'test-user', role: 'viewer' }, logout: vi.fn() })
+}));
+
+import { AppShell } from './AppShell';
+
+afterEach(() => {
+ cleanup();
+ vi.clearAllMocks();
+});
+
+test('reschedules likely route preloads when the active module changes', async () => {
+ const firstCleanup = vi.fn();
+ const secondCleanup = vi.fn();
+ routing.scheduleIdleRoutePreloads
+ .mockReturnValueOnce(firstCleanup)
+ .mockReturnValueOnce(secondCleanup);
+
+ render(
+ }>页面内容} />
+ );
+
+ expect(routing.scheduleIdleRoutePreloads).toHaveBeenCalledWith({ activePathname: '/monitor' });
+ fireEvent.click(screen.getByRole('link', { name: '历史数据' }));
+
+ await waitFor(() => expect(routing.scheduleIdleRoutePreloads).toHaveBeenLastCalledWith({ activePathname: '/history' }));
+ expect(firstCleanup).toHaveBeenCalledTimes(1);
+
+ cleanup();
+ expect(secondCleanup).toHaveBeenCalledTimes(1);
+});
diff --git a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx
index 90502f70..6e52a789 100644
--- a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx
+++ b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx
@@ -39,11 +39,11 @@ const pageNames: Record = {
export function AppShell() {
const location = useLocation();
- const [initialPathname] = useState(() => location.pathname);
const section = location.pathname.split('/')[1] || 'monitor';
+ const activeRoutePath = `/${section}`;
const { session, logout } = usePlatformSession();
const roleLabel = { viewer: '只读', operator: '处置员', admin: '管理员' }[session.role];
- useEffect(() => scheduleIdleRoutePreloads({ activePathname: initialPathname }), [initialPathname]);
+ useEffect(() => scheduleIdleRoutePreloads({ activePathname: activeRoutePath }), [activeRoutePath]);
return (