Files
ln-bi/src/server/routes/mileage/vehicle-recent.ts

106 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Hono } from 'hono';
import { fetchOneOsMileageDates } from './oneos-api.js';
import {
parseMileageSourcePriority,
protocolsForSourcePriority,
sourceCategoryFromProtocol,
} from './source-policy.js';
const app = new Hono();
function fmt(d: Date): string {
const y = d.getFullYear();
const m = String(d.getMonth() + 1).padStart(2, '0');
const dd = String(d.getDate()).padStart(2, '0');
return `${y}-${m}-${dd}`;
}
function parseYmd(s: string): Date | null {
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(s);
if (!m) return null;
const d = new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
d.setHours(0, 0, 0, 0);
return Number.isFinite(d.getTime()) ? d : null;
}
const MAX_DAYS = 366;
app.get('/:plate/recent', async (c) => {
const plate = c.req.param('plate');
if (!plate) return c.json({ plate: '', days: [] }, 400);
const sourcePriority = parseMileageSourcePriority(c.req.query('sourcePriority'));
const protocolPriority = protocolsForSourcePriority(sourcePriority);
const today = new Date();
today.setHours(0, 0, 0, 0);
// 区间参数:优先 start/end否则回退 days兼容旧调用
const startQ = c.req.query('start');
const endQ = c.req.query('end');
let start: Date;
let end: Date;
if (startQ) {
const ps = parseYmd(startQ);
if (!ps) return c.json({ plate, days: [] }, 400);
start = ps;
end = endQ ? (parseYmd(endQ) ?? today) : today;
} else {
const days = Math.min(Math.max(Number(c.req.query('days')) || 15, 1), MAX_DAYS);
end = today;
start = new Date(today);
start.setDate(today.getDate() - (days - 1));
}
if (start > end) [start, end] = [end, start];
// 限制区间长度
const span = Math.round((end.getTime() - start.getTime()) / 86400000) + 1;
if (span > MAX_DAYS) {
start = new Date(end);
start.setDate(end.getDate() - (MAX_DAYS - 1));
}
try {
const dates: string[] = [];
const dateCursor = new Date(start);
while (dateCursor <= end) {
dates.push(fmt(dateCursor));
dateCursor.setDate(dateCursor.getDate() + 1);
}
const rowsByDate = await fetchOneOsMileageDates(dates, [plate], protocolPriority);
// 补全:从 start 到 end 每天一条
const result: {
date: string;
dailyKm: number;
isDataSynced: boolean;
sourceProtocol: 'GB32960' | 'MQTT' | 'JT808' | null;
sourceCategory: 'INSTRUMENT' | 'GPS' | null;
}[] = [];
const cursor = new Date(start);
while (cursor <= end) {
const key = fmt(cursor);
const hit = (rowsByDate.get(key) || []).find(row => row.plateNumber === plate);
result.push({
date: key,
dailyKm: hit?.status === 'NORMAL' ? (hit.dailyMileageKm || 0) : 0,
isDataSynced: hit?.status === 'NORMAL',
sourceProtocol: hit?.sourceProtocol || null,
sourceCategory: sourceCategoryFromProtocol(hit?.sourceProtocol || null),
});
cursor.setDate(cursor.getDate() + 1);
}
return c.json({
plate,
start: fmt(start),
end: fmt(end),
sourcePriority,
days: result,
});
} catch (e: unknown) {
console.error('vehicle recent error:', e);
return c.json({ plate, days: [] }, 500);
}
});
export default app;