feat(platform): add filtered vehicle coverage summary

This commit is contained in:
lingniu
2026-07-04 03:42:19 +08:00
parent 6683ce4df7
commit b7e8aae317
12 changed files with 228 additions and 14 deletions

View File

@@ -1,7 +1,7 @@
import { Button, Card, Form, Select, Space, Table, Tag, Toast } from '@douyinfe/semi-ui';
import { useEffect, useMemo, useState } from 'react';
import { api } from '../api/client';
import type { VehicleCoverageRow } from '../api/types';
import type { VehicleCoverageRow, VehicleCoverageSummary } from '../api/types';
import { DataEmpty } from '../components/DataEmpty';
import { PageHeader } from '../components/PageHeader';
import { StatusTag } from '../components/StatusTag';
@@ -30,20 +30,18 @@ function vehicleServiceStatus(row: VehicleCoverageRow) {
export function Vehicles({ onOpenVehicle, initialFilters = {} }: { onOpenVehicle: (vin: string) => void; initialFilters?: Record<string, string> }) {
const [rows, setRows] = useState<VehicleCoverageRow[]>([]);
const [summary, setSummary] = useState<VehicleCoverageSummary | null>(null);
const [loading, setLoading] = useState(true);
const [filters, setFilters] = useState<Record<string, string>>(initialFilters);
const [pagination, setPagination] = useState({ currentPage: 1, pageSize: 20, total: 0 });
const resultSummary = useMemo(() => {
const onlineRows = rows.filter((row) => row.online).length;
const multiSourceRows = rows.filter((row) => row.sourceCount > 1).length;
const unboundRows = rows.filter((row) => row.bindingStatus !== 'bound').length;
return [
{ label: '过滤车辆', value: pagination.total.toLocaleString() },
{ label: '本页在线', value: onlineRows.toLocaleString() },
{ label: '本页多源', value: multiSourceRows.toLocaleString() },
{ label: '本页待绑定', value: unboundRows.toLocaleString() }
{ label: '过滤车辆', value: (summary?.totalVehicles ?? pagination.total).toLocaleString() },
{ label: '在线车辆', value: (summary?.onlineVehicles ?? 0).toLocaleString() },
{ label: '多源车辆', value: (summary?.multiSourceVehicles ?? 0).toLocaleString() },
{ label: '待绑定', value: (summary?.unboundVehicles ?? 0).toLocaleString() }
];
}, [pagination.total, rows]);
}, [pagination.total, summary]);
const load = (values: Record<string, string> = filters, page = pagination.currentPage, pageSize = pagination.pageSize) => {
setLoading(true);
@@ -54,9 +52,13 @@ export function Vehicles({ onOpenVehicle, initialFilters = {} }: { onOpenVehicle
if (values?.online) params.set('online', values.online);
if (values?.bindingStatus) params.set('bindingStatus', values.bindingStatus);
if (values?.serviceStatus) params.set('serviceStatus', values.serviceStatus);
api.vehicleCoverage(params)
.then((nextPage) => {
const summaryParams = new URLSearchParams(params);
summaryParams.delete('limit');
summaryParams.delete('offset');
Promise.all([api.vehicleCoverage(params), api.vehicleCoverageSummary(summaryParams)])
.then(([nextPage, nextSummary]) => {
setRows(nextPage.items);
setSummary(nextSummary);
setPagination({ currentPage: page, pageSize, total: nextPage.total });
})
.catch((error: Error) => Toast.error(error.message))