Files
lingniu-vehicle-ingest/vehicle-data-platform/apps/web/src/v2/domain/access.ts
2026-07-16 18:07:45 +08:00

55 lines
2.9 KiB
TypeScript

import type { AccessProtocolThreshold, AccessThresholdConfig, AccessVehicleRow } from '../../api/types';
const accessTimeFormatter = new Intl.DateTimeFormat('zh-CN', {
year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false
});
export const accessStateLabels: Record<AccessVehicleRow['onlineState'], string> = {
online: '在线',
offline: '离线',
never_reported: '从未上报',
unknown: '未知'
};
export function formatSeconds(value: number | null | undefined) {
if (value === null || value === undefined || !Number.isFinite(value)) return '—';
const sign = value < 0 ? '-' : '';
const seconds = Math.abs(Math.round(value));
if (seconds < 60) return `${sign}${seconds}`;
if (seconds < 3600) return `${sign}${Math.floor(seconds / 60)}${seconds % 60}`;
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
return `${sign}${hours} 小时${minutes ? ` ${minutes}` : ''}`;
}
export function formatAccessTime(value: string) {
if (!value) return '—';
const parsed = new Date(value);
if (Number.isNaN(parsed.getTime())) return '—';
return accessTimeFormatter.format(parsed).replace(/\//g, '-');
}
export function thresholdForProtocol(config: AccessThresholdConfig, protocol: string) {
return config.protocols.find((item) => item.protocol === protocol)?.thresholdSec ?? config.defaultThresholdSec;
}
export function updateProtocolThreshold(items: AccessProtocolThreshold[], protocol: string, thresholdSec: number) {
const next = items.filter((item) => item.protocol !== protocol);
next.push({ protocol, thresholdSec });
return next.sort((a, b) => a.protocol.localeCompare(b.protocol));
}
export function accessRowsToCSV(rows: AccessVehicleRow[]) {
const protocolColumns = ['GB32960', 'JT808', 'YUTONG_MQTT'].flatMap((protocol) => [`${protocol}接入状态`, `${protocol}接入厂家`, `${protocol}首次接入`, `${protocol}最新上报`, `${protocol}离线秒数`]);
const columns = ['综合状态', '车牌', 'VIN', '品牌', '车型', '企业', '真实接入协议', '资料待维护', ...protocolColumns];
const quote = (value: unknown) => `"${String(value ?? '').replace(/"/g, '""')}"`;
const lines = rows.map((row) => {
const protocolValues = ['GB32960', 'JT808', 'YUTONG_MQTT'].flatMap((protocol) => {
const status = row.protocolStatuses.find((item) => item.protocol === protocol);
return [status?.connected ? accessStateLabels[status.onlineState] : '无来源', status?.provider, status?.firstSeenAt, status?.latestReceivedAt, status?.freshnessSec];
});
return [row.connectionState, row.plate, row.vin, row.oem, row.model, row.company, row.actualProtocols.join('/'), row.masterDataIssues.join('/'), ...protocolValues].map(quote).join(',');
});
return `\uFEFF${columns.map(quote).join(',')}\n${lines.join('\n')}`;
}