feat(platform): support vehicle keyword detail lookup

This commit is contained in:
lingniu
2026-07-03 23:57:11 +08:00
parent d4fdd7527b
commit 8af622e7f6
3 changed files with 50 additions and 20 deletions

View File

@@ -1,13 +1,13 @@
import { Button, Card, Descriptions, Form, Select, Space, Table, Tabs, Tag, Toast, Typography } from '@douyinfe/semi-ui';
import { IconRefresh, IconSearch } from '@douyinfe/semi-icons';
import { useEffect, useMemo, useState } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react';
import { api } from '../api/client';
import type { QualityIssueRow, VehicleDetail as VehicleDetailData, VehicleSourceStatus } from '../api/types';
import { PageHeader } from '../components/PageHeader';
import { StatusTag } from '../components/StatusTag';
type VehicleQuery = {
vin: string;
keyword: string;
protocol?: string;
};
@@ -27,29 +27,44 @@ export function VehicleDetail({
onOpenHistory: (vin: string) => void;
onOpenMileage: (vin: string) => void;
}) {
const [query, setQuery] = useState<VehicleQuery>({ vin });
const [query, setQuery] = useState<VehicleQuery>({ keyword: vin });
const [detail, setDetail] = useState<VehicleDetailData | null>(null);
const [loading, setLoading] = useState(false);
const requestSeq = useRef(0);
const load = (nextQuery = query) => {
const vin = nextQuery.vin.trim();
if (!vin) {
Toast.warning('请输入 VIN');
const keyword = nextQuery.keyword.trim();
if (!keyword) {
Toast.warning('请输入 VIN / 车牌 / 手机号');
return;
}
setLoading(true);
const params = new URLSearchParams({ vin });
const params = new URLSearchParams({ keyword });
if (nextQuery.protocol?.trim()) {
params.set('protocol', nextQuery.protocol.trim());
}
const seq = requestSeq.current + 1;
requestSeq.current = seq;
api.vehicleDetail(params)
.then(setDetail)
.catch((error: Error) => Toast.error(error.message))
.finally(() => setLoading(false));
.then((nextDetail) => {
if (requestSeq.current === seq) {
setDetail(nextDetail);
}
})
.catch((error: Error) => {
if (requestSeq.current === seq) {
Toast.error(error.message);
}
})
.finally(() => {
if (requestSeq.current === seq) {
setLoading(false);
}
});
};
useEffect(() => {
const nextQuery = { vin };
const nextQuery = { keyword: vin };
setQuery(nextQuery);
load(nextQuery);
}, [vin]);
@@ -57,6 +72,7 @@ export function VehicleDetail({
const identity = detail?.identity;
const summary = detail?.realtimeSummary;
const latest = detail?.realtime[0];
const resolvedVIN = detail?.vin || summary?.vin || identity?.vin || latest?.vin || query.keyword;
const protocols = useMemo(() => detail?.sources ?? [], [detail?.sources]);
const latestRaw = detail?.raw.items[0];
const qualityCount = detail?.quality.total ?? 0;
@@ -68,11 +84,11 @@ export function VehicleDetail({
<PageHeader title="车辆服务" description="以 VIN 为主对象聚合身份、实时、历史、RAW 和里程,协议仅作为数据来源" />
<Card bordered>
<Form initValues={query} layout="horizontal" onSubmit={(values) => {
const nextQuery = { vin: String(values.vin ?? ''), protocol: String(values.protocol ?? '') };
const nextQuery = { keyword: String(values.keyword ?? ''), protocol: String(values.protocol ?? '') };
setQuery(nextQuery);
load(nextQuery);
}}>
<Form.Input field="vin" label="VIN" placeholder="输入 VIN" style={{ width: 280 }} />
<Form.Input field="keyword" label="车辆关键词" placeholder="VIN / 车牌 / 手机号" style={{ width: 280 }} />
<Form.Select field="protocol" label="数据来源" placeholder="全部来源" style={{ width: 180 }}>
<Select.Option value="GB32960">GB32960</Select.Option>
<Select.Option value="JT808">JT808</Select.Option>
@@ -81,8 +97,8 @@ export function VehicleDetail({
<Space>
<Button icon={<IconSearch />} htmlType="submit" theme="solid" type="primary"></Button>
<Button icon={<IconRefresh />} onClick={() => load(query)} loading={loading}></Button>
<Button onClick={() => onOpenHistory(query.vin)}></Button>
<Button onClick={() => onOpenMileage(query.vin)}></Button>
<Button onClick={() => onOpenHistory(resolvedVIN)}></Button>
<Button onClick={() => onOpenMileage(resolvedVIN)}></Button>
</Space>
</Form>
</Card>
@@ -92,7 +108,7 @@ export function VehicleDetail({
<Descriptions
row
data={[
{ key: 'VIN', value: summary?.vin ?? identity?.vin ?? latest?.vin ?? query.vin },
{ key: 'VIN', value: resolvedVIN },
{ key: '车牌', value: summary?.plate || identity?.plate || latest?.plate || '-' },
{ key: '手机号', value: summary?.phone || identity?.phone || '-' },
{ key: 'OEM', value: summary?.oem || identity?.oem || '-' },