feat(platform): persist history filters in route

This commit is contained in:
lingniu
2026-07-04 06:54:29 +08:00
parent b9534af233
commit 266b20b97a
4 changed files with 153 additions and 12 deletions

View File

@@ -11,7 +11,7 @@ type HistoryFilters = {
dateFrom?: string;
dateTo?: string;
fields?: string;
includeFields?: boolean;
includeFields?: boolean | string;
};
const defaultFilters: HistoryFilters = {
@@ -39,19 +39,37 @@ function normalizeHistoryTab(value?: string): HistoryTabKey {
return value === 'raw' ? 'raw' : 'location';
}
function isIncludeFieldsEnabled(value?: boolean | string) {
return value === true || value === 'true';
}
function mergeInitialFilters(initialVin: string, initialProtocol?: string, initialFilters: Record<string, string> = {}): HistoryFilters {
return {
...defaultFilters,
keyword: initialVin || defaultFilters.keyword,
protocol: initialProtocol,
...initialFilters,
includeFields: isIncludeFieldsEnabled(initialFilters.includeFields)
};
}
export function History({
initialVin,
initialProtocol,
initialTab,
initialFilters = {},
onFiltersChange,
onOpenVehicle
}: {
initialVin: string;
initialProtocol?: string;
initialTab?: string;
initialFilters?: Record<string, string>;
onFiltersChange?: (filters: HistoryFilters, tab?: HistoryTabKey) => void;
onOpenVehicle: (vin: string, protocol?: string) => void;
}) {
const initialFilters = { ...defaultFilters, keyword: initialVin || defaultFilters.keyword, protocol: initialProtocol };
const [filters, setFilters] = useState<HistoryFilters>(initialFilters);
const initialHistoryFilters = mergeInitialFilters(initialVin, initialProtocol, initialFilters);
const [filters, setFilters] = useState<HistoryFilters>(initialHistoryFilters);
const [activeTab, setActiveTab] = useState<HistoryTabKey>(normalizeHistoryTab(initialTab));
const [locations, setLocations] = useState<Page<HistoryLocationRow>>(defaultPage);
const [rawFrames, setRawFrames] = useState<Page<RawFrameRow>>(defaultPage);
@@ -67,7 +85,7 @@ export function History({
if (nextFilters.protocol?.trim()) params.set('protocol', nextFilters.protocol.trim());
if (nextFilters.dateFrom?.trim()) params.set('dateFrom', nextFilters.dateFrom.trim());
if (nextFilters.dateTo?.trim()) params.set('dateTo', nextFilters.dateTo.trim());
if (raw && nextFilters.includeFields) params.set('includeFields', 'true');
if (raw && isIncludeFieldsEnabled(nextFilters.includeFields)) params.set('includeFields', 'true');
if (raw && nextFilters.fields?.trim()) params.set('fields', nextFilters.fields.trim());
return params;
};
@@ -78,7 +96,7 @@ export function History({
if (nextFilters.protocol?.trim()) query.protocol = nextFilters.protocol.trim();
if (nextFilters.dateFrom?.trim()) query.dateFrom = nextFilters.dateFrom.trim();
if (nextFilters.dateTo?.trim()) query.dateTo = nextFilters.dateTo.trim();
if (nextFilters.includeFields) query.includeFields = true;
if (isIncludeFieldsEnabled(nextFilters.includeFields)) query.includeFields = true;
const fields = splitFields(nextFilters.fields);
if (fields.length > 0) query.fields = fields;
return query;
@@ -116,24 +134,32 @@ export function History({
includeFields: Boolean(values.includeFields)
};
setFilters(nextFilters);
onFiltersChange?.(nextFilters, activeTab);
loadLocations(nextFilters, 1, locationPagination.pageSize);
loadRawFrames(nextFilters, 1, rawPagination.pageSize);
};
const reset = () => {
const nextFilters = { ...defaultFilters, keyword: initialVin || defaultFilters.keyword, protocol: initialProtocol };
const nextFilters = mergeInitialFilters(initialVin, initialProtocol, {});
setFilters(nextFilters);
onFiltersChange?.(nextFilters, activeTab);
loadLocations(nextFilters, 1, locationPagination.pageSize);
loadRawFrames(nextFilters, 1, rawPagination.pageSize);
};
useEffect(() => {
const nextFilters = { ...defaultFilters, keyword: initialVin || defaultFilters.keyword, protocol: initialProtocol };
const nextFilters = mergeInitialFilters(initialVin, initialProtocol, initialFilters);
setFilters(nextFilters);
setActiveTab(normalizeHistoryTab(initialTab));
loadLocations(nextFilters, 1, locationPagination.pageSize);
loadRawFrames(nextFilters, 1, rawPagination.pageSize);
}, [initialVin, initialProtocol, initialTab]);
}, [initialVin, initialProtocol, initialTab, JSON.stringify(initialFilters)]);
const changeTab = (key: string) => {
const nextTab = normalizeHistoryTab(String(key));
setActiveTab(nextTab);
onFiltersChange?.(filters, nextTab);
};
const rawFieldCount = useMemo(() => Object.keys(selectedRaw?.parsedFields ?? {}).length, [selectedRaw]);
const currentVehicleKeyword = filters.keyword?.trim() ?? '';
@@ -156,7 +182,7 @@ export function History({
<Typography.Text type="tertiary"> RAW </Typography.Text>
</div>
<Card bordered>
<Form key={`${filters.keyword ?? ''}-${filters.protocol ?? ''}-${filters.includeFields ? 'fields' : 'light'}`} initValues={filters} layout="horizontal" onSubmit={(values) => submit(values)}>
<Form key={JSON.stringify(filters)} initValues={filters} layout="horizontal" onSubmit={(values) => submit(values)}>
<Form.Input field="keyword" label="车辆关键词" placeholder="VIN / 车牌 / 手机号" style={{ width: 260 }} />
<Form.Select field="protocol" label="数据来源" placeholder="全部来源" style={{ width: 190 }}>
<Select.Option value="GB32960">GB32960</Select.Option>
@@ -182,7 +208,7 @@ export function History({
</Form>
</Card>
<Card bordered style={{ marginTop: 16 }}>
<Tabs activeKey={activeTab} onChange={(key) => setActiveTab(normalizeHistoryTab(String(key)))}>
<Tabs activeKey={activeTab} onChange={(key) => changeTab(String(key))}>
<Tabs.TabPane tab="位置历史" itemKey="location">
<Table
rowKey="deviceTime"