feat(platform): link records to vehicle service
This commit is contained in:
@@ -50,8 +50,8 @@ export default function App() {
|
|||||||
vehicles: <Vehicles onOpenVehicle={openVehicle} />,
|
vehicles: <Vehicles onOpenVehicle={openVehicle} />,
|
||||||
realtime: <Realtime />,
|
realtime: <Realtime />,
|
||||||
detail: <VehicleDetail vin={activeVin} />,
|
detail: <VehicleDetail vin={activeVin} />,
|
||||||
history: <History />,
|
history: <History onOpenVehicle={openVehicle} />,
|
||||||
mileage: <Mileage />,
|
mileage: <Mileage onOpenVehicle={openVehicle} />,
|
||||||
quality: <Quality onHealthLoaded={(health) => setLinkIssueCount(health.linkHealth.filter((item) => item.status !== 'ok').length)} />
|
quality: <Quality onHealthLoaded={(health) => setLinkIssueCount(health.linkHealth.filter((item) => item.status !== 'ok').length)} />
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,12 @@ const defaultFilters: HistoryFilters = {
|
|||||||
|
|
||||||
const defaultPage = { items: [], total: 0, limit: 10, offset: 0 };
|
const defaultPage = { items: [], total: 0, limit: 10, offset: 0 };
|
||||||
|
|
||||||
export function History() {
|
function canOpenVehicle(vin?: string) {
|
||||||
|
const value = vin?.trim();
|
||||||
|
return Boolean(value && value !== 'unknown');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function History({ onOpenVehicle }: { onOpenVehicle: (vin: string) => void }) {
|
||||||
const [filters, setFilters] = useState<HistoryFilters>(defaultFilters);
|
const [filters, setFilters] = useState<HistoryFilters>(defaultFilters);
|
||||||
const [locations, setLocations] = useState<Page<HistoryLocationRow>>(defaultPage);
|
const [locations, setLocations] = useState<Page<HistoryLocationRow>>(defaultPage);
|
||||||
const [rawFrames, setRawFrames] = useState<Page<RawFrameRow>>(defaultPage);
|
const [rawFrames, setRawFrames] = useState<Page<RawFrameRow>>(defaultPage);
|
||||||
@@ -143,7 +148,14 @@ export function History() {
|
|||||||
{ title: '速度 km/h', dataIndex: 'speedKmh', width: 120 },
|
{ title: '速度 km/h', dataIndex: 'speedKmh', width: 120 },
|
||||||
{ title: '总里程 km', dataIndex: 'totalMileageKm', width: 130 },
|
{ title: '总里程 km', dataIndex: 'totalMileageKm', width: 130 },
|
||||||
{ title: '设备时间', dataIndex: 'deviceTime', width: 190 },
|
{ title: '设备时间', dataIndex: 'deviceTime', width: 190 },
|
||||||
{ title: '入库时间', dataIndex: 'serverTime', width: 190 }
|
{ title: '入库时间', dataIndex: 'serverTime', width: 190 },
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
width: 110,
|
||||||
|
render: (_: unknown, row: HistoryLocationRow) => (
|
||||||
|
<Button disabled={!canOpenVehicle(row.vin)} onClick={() => onOpenVehicle(row.vin)}>车辆服务</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
@@ -169,7 +181,16 @@ export function History() {
|
|||||||
{ title: '大小 B', dataIndex: 'rawSizeBytes', width: 100 },
|
{ title: '大小 B', dataIndex: 'rawSizeBytes', width: 100 },
|
||||||
{ title: '设备时间', dataIndex: 'deviceTime', width: 190 },
|
{ title: '设备时间', dataIndex: 'deviceTime', width: 190 },
|
||||||
{ title: '入库时间', dataIndex: 'serverTime', width: 190 },
|
{ title: '入库时间', dataIndex: 'serverTime', width: 190 },
|
||||||
{ title: '操作', width: 100, render: (_: unknown, row: RawFrameRow) => <Button onClick={() => setSelectedRaw(row)}>字段</Button> }
|
{
|
||||||
|
title: '操作',
|
||||||
|
width: 200,
|
||||||
|
render: (_: unknown, row: RawFrameRow) => (
|
||||||
|
<Space>
|
||||||
|
<Button onClick={() => setSelectedRaw(row)}>字段</Button>
|
||||||
|
<Button disabled={!canOpenVehicle(row.vin)} onClick={() => onOpenVehicle(row.vin)}>车辆服务</Button>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
|
|||||||
@@ -27,7 +27,12 @@ function formatKm(value: number) {
|
|||||||
return Number.isFinite(value) ? value.toLocaleString(undefined, { maximumFractionDigits: 1 }) : '0';
|
return Number.isFinite(value) ? value.toLocaleString(undefined, { maximumFractionDigits: 1 }) : '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Mileage() {
|
function canOpenVehicle(vin?: string) {
|
||||||
|
const value = vin?.trim();
|
||||||
|
return Boolean(value && value !== 'unknown');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Mileage({ onOpenVehicle }: { onOpenVehicle: (vin: string) => void }) {
|
||||||
const [rows, setRows] = useState<DailyMileageRow[]>([]);
|
const [rows, setRows] = useState<DailyMileageRow[]>([]);
|
||||||
const [summary, setSummary] = useState<MileageSummary>(emptySummary);
|
const [summary, setSummary] = useState<MileageSummary>(emptySummary);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
@@ -121,7 +126,14 @@ export function Mileage() {
|
|||||||
{ title: '结束里程', dataIndex: 'endMileageKm' },
|
{ title: '结束里程', dataIndex: 'endMileageKm' },
|
||||||
{ title: '日里程', dataIndex: 'dailyMileageKm' },
|
{ title: '日里程', dataIndex: 'dailyMileageKm' },
|
||||||
{ title: '来源', dataIndex: 'source' },
|
{ title: '来源', dataIndex: 'source' },
|
||||||
{ title: '异常', render: (_: unknown, row: DailyMileageRow) => row.anomalySeverity ? <Tag color="orange">{row.anomalySeverity}</Tag> : <Tag color="green">正常</Tag> }
|
{ title: '异常', render: (_: unknown, row: DailyMileageRow) => row.anomalySeverity ? <Tag color="orange">{row.anomalySeverity}</Tag> : <Tag color="green">正常</Tag> },
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
width: 110,
|
||||||
|
render: (_: unknown, row: DailyMileageRow) => (
|
||||||
|
<Button disabled={!canOpenVehicle(row.vin)} onClick={() => onOpenVehicle(row.vin)}>车辆服务</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
Reference in New Issue
Block a user