feat(monitor): preserve investigation context

This commit is contained in:
lingniu
2026-07-16 17:08:54 +08:00
parent 38b056f5f1
commit 1cfc9c2bdd
17 changed files with 426 additions and 37 deletions

View File

@@ -0,0 +1,19 @@
import { render, screen } from '@testing-library/react';
import { expect, test } from 'vitest';
import { MemoryRouter } from 'react-router-dom';
import { ROUTER_FUTURE } from '../routing/routerConfig';
import { withMonitorReturn } from '../routing/monitorContext';
import { MonitorReturnBar } from './MonitorReturnBar';
test('shows a deterministic monitor return only for monitor-originated child routes', () => {
const child = withMonitorReturn('/history?vin=LTEST000000000001', '/monitor?selectedVin=LTEST000000000001&detail=collapsed&zoom=13&bounds=113.1%2C23%2C113.4%2C23.3');
const view = render(<MemoryRouter future={ROUTER_FUTURE} initialEntries={[child]}><MonitorReturnBar /></MemoryRouter>);
expect(screen.getByRole('link', { name: /返回全局监控/ })).toHaveAttribute('href', expect.stringContaining('/monitor?'));
expect(screen.getByText(/LTEST000000000001/)).toBeInTheDocument();
expect(screen.getByText(/Zoom 13 · 详情收起/)).toBeInTheDocument();
view.unmount();
render(<MemoryRouter future={ROUTER_FUTURE} initialEntries={['/history?vin=LTEST000000000001']}><MonitorReturnBar /></MemoryRouter>);
expect(screen.queryByRole('link', { name: /返回全局监控/ })).not.toBeInTheDocument();
});

View File

@@ -0,0 +1,21 @@
import { IconArrowLeft, IconMapPin } from '@douyinfe/semi-icons';
import { Link, useSearchParams } from 'react-router-dom';
import { monitorReturnFromParams, parseMonitorRouteContext } from '../routing/monitorContext';
export function MonitorReturnBar() {
const [searchParams] = useSearchParams();
const returnTo = monitorReturnFromParams(searchParams);
if (!returnTo) return null;
const context = parseMonitorRouteContext(new URL(returnTo, 'https://vehicle-platform.invalid').searchParams);
const scope = [
context.selectedVin || '',
context.keyword && context.keyword !== context.selectedVin ? context.keyword : '',
context.protocol,
context.status
].filter(Boolean).join(' · ');
return <section className="v2-monitor-return" aria-label="全局监控返回上下文">
<Link to={returnTo} replace><IconArrowLeft /></Link>
<span><IconMapPin />{scope || '恢复离开前的地图与筛选状态'}</span>
<em>Zoom {context.viewport.zoom} · {context.detailOpen ? '详情展开' : context.selectedVin ? '详情收起' : '未选车辆'}</em>
</section>;
}