feat(platform): show vehicles as service coverage
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
import { Button, Card, Form, Select, Space, Table, Toast } from '@douyinfe/semi-ui';
|
import { Button, Card, Form, Select, Space, Table, Tag, Toast } from '@douyinfe/semi-ui';
|
||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { api } from '../api/client';
|
import { api } from '../api/client';
|
||||||
import type { VehicleRow } from '../api/types';
|
import type { VehicleCoverageRow } from '../api/types';
|
||||||
import { DataEmpty } from '../components/DataEmpty';
|
import { DataEmpty } from '../components/DataEmpty';
|
||||||
import { PageHeader } from '../components/PageHeader';
|
import { PageHeader } from '../components/PageHeader';
|
||||||
import { StatusTag } from '../components/StatusTag';
|
import { StatusTag } from '../components/StatusTag';
|
||||||
|
|
||||||
export function Vehicles({ onOpenVehicle }: { onOpenVehicle: (vin: string) => void }) {
|
export function Vehicles({ onOpenVehicle }: { onOpenVehicle: (vin: string) => void }) {
|
||||||
const [rows, setRows] = useState<VehicleRow[]>([]);
|
const [rows, setRows] = useState<VehicleCoverageRow[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
const load = (values?: Record<string, string>) => {
|
const load = (values?: Record<string, string>) => {
|
||||||
@@ -15,7 +15,10 @@ export function Vehicles({ onOpenVehicle }: { onOpenVehicle: (vin: string) => vo
|
|||||||
const params = new URLSearchParams({ limit: '20' });
|
const params = new URLSearchParams({ limit: '20' });
|
||||||
if (values?.keyword) params.set('keyword', values.keyword);
|
if (values?.keyword) params.set('keyword', values.keyword);
|
||||||
if (values?.protocol) params.set('protocol', values.protocol);
|
if (values?.protocol) params.set('protocol', values.protocol);
|
||||||
api.vehicles(params)
|
if (values?.coverage) params.set('coverage', values.coverage);
|
||||||
|
if (values?.online) params.set('online', values.online);
|
||||||
|
if (values?.bindingStatus) params.set('bindingStatus', values.bindingStatus);
|
||||||
|
api.vehicleCoverage(params)
|
||||||
.then((page) => setRows(page.items))
|
.then((page) => setRows(page.items))
|
||||||
.catch((error: Error) => Toast.error(error.message))
|
.catch((error: Error) => Toast.error(error.message))
|
||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
@@ -29,27 +32,47 @@ export function Vehicles({ onOpenVehicle }: { onOpenVehicle: (vin: string) => vo
|
|||||||
{ title: '车牌', dataIndex: 'plate', width: 120 },
|
{ title: '车牌', dataIndex: 'plate', width: 120 },
|
||||||
{ title: '手机号', dataIndex: 'phone', width: 130 },
|
{ title: '手机号', dataIndex: 'phone', width: 130 },
|
||||||
{ title: 'OEM', dataIndex: 'oem', width: 120 },
|
{ title: 'OEM', dataIndex: 'oem', width: 120 },
|
||||||
{ title: '协议', dataIndex: 'protocol', width: 120 },
|
{
|
||||||
{ title: '在线', render: (_: unknown, row: VehicleRow) => <StatusTag status={row.online ? 'ok' : 'offline'} /> },
|
title: '来源',
|
||||||
|
width: 260,
|
||||||
|
render: (_: unknown, row: VehicleCoverageRow) => (
|
||||||
|
<Space spacing={4} wrap>
|
||||||
|
{row.protocols.map((protocol) => <Tag key={protocol} color="blue">{protocol}</Tag>)}
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ title: '覆盖', width: 90, render: (_: unknown, row: VehicleCoverageRow) => `${row.onlineSourceCount}/${row.sourceCount}` },
|
||||||
|
{ title: '在线', width: 90, render: (_: unknown, row: VehicleCoverageRow) => <StatusTag status={row.online ? 'ok' : 'offline'} /> },
|
||||||
{ title: '最后在线', dataIndex: 'lastSeen', width: 170 },
|
{ title: '最后在线', dataIndex: 'lastSeen', width: 170 },
|
||||||
{ title: '位置', dataIndex: 'locationText' },
|
{ title: '绑定', width: 90, render: (_: unknown, row: VehicleCoverageRow) => <Tag color={row.bindingStatus === 'bound' ? 'green' : 'orange'}>{row.bindingStatus === 'bound' ? '已绑定' : '未绑定'}</Tag> },
|
||||||
{ title: '绑定分', dataIndex: 'bindingScore', width: 90 },
|
{ title: '操作', width: 110, render: (_: unknown, row: VehicleCoverageRow) => <Button onClick={() => onOpenVehicle(row.vin)}>车辆服务</Button> }
|
||||||
{ title: '操作', render: (_: unknown, row: VehicleRow) => <Button onClick={() => onOpenVehicle(row.vin)}>车辆服务</Button> }
|
|
||||||
],
|
],
|
||||||
[onOpenVehicle]
|
[onOpenVehicle]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="vp-page">
|
<div className="vp-page">
|
||||||
<PageHeader title="车辆台账" description="车辆身份、协议绑定、车牌、手机号和 OEM 的运营台账" />
|
<PageHeader title="车辆台账" description="以 VIN 为主对象维护车辆身份、多源覆盖、在线状态和绑定状态" />
|
||||||
<Card bordered>
|
<Card bordered>
|
||||||
<Form layout="horizontal" onSubmit={(values) => load(values as Record<string, string>)}>
|
<Form layout="horizontal" onSubmit={(values) => load(values as Record<string, string>)}>
|
||||||
<Form.Input field="keyword" label="关键词" placeholder="VIN / 车牌 / 手机号" style={{ width: 260 }} />
|
<Form.Input field="keyword" label="关键词" placeholder="VIN / 车牌 / 手机号 / OEM" style={{ width: 260 }} />
|
||||||
<Form.Select field="protocol" label="协议" placeholder="全部协议" style={{ width: 180 }}>
|
<Form.Select field="protocol" label="协议" placeholder="全部协议" style={{ width: 180 }}>
|
||||||
<Select.Option value="GB32960">GB32960</Select.Option>
|
<Select.Option value="GB32960">GB32960</Select.Option>
|
||||||
<Select.Option value="JT808">JT808</Select.Option>
|
<Select.Option value="JT808">JT808</Select.Option>
|
||||||
<Select.Option value="YUTONG_MQTT">YUTONG_MQTT</Select.Option>
|
<Select.Option value="YUTONG_MQTT">YUTONG_MQTT</Select.Option>
|
||||||
</Form.Select>
|
</Form.Select>
|
||||||
|
<Form.Select field="coverage" label="来源覆盖" placeholder="全部" style={{ width: 130 }}>
|
||||||
|
<Select.Option value="single">单源</Select.Option>
|
||||||
|
<Select.Option value="multi">多源</Select.Option>
|
||||||
|
</Form.Select>
|
||||||
|
<Form.Select field="online" label="在线" placeholder="全部" style={{ width: 130 }}>
|
||||||
|
<Select.Option value="online">在线</Select.Option>
|
||||||
|
<Select.Option value="offline">离线</Select.Option>
|
||||||
|
</Form.Select>
|
||||||
|
<Form.Select field="bindingStatus" label="绑定" placeholder="全部" style={{ width: 130 }}>
|
||||||
|
<Select.Option value="bound">已绑定</Select.Option>
|
||||||
|
<Select.Option value="unbound">未绑定</Select.Option>
|
||||||
|
</Form.Select>
|
||||||
<Space>
|
<Space>
|
||||||
<Button htmlType="submit" theme="solid" type="primary">查询</Button>
|
<Button htmlType="submit" theme="solid" type="primary">查询</Button>
|
||||||
<Button onClick={() => load()}>重置</Button>
|
<Button onClick={() => load()}>重置</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user