import { Hono } from 'hono'; import mileagePool from '../../mileage-db.js'; const app = new Hono(); interface DayRow { date: string; daily_km: string | number | null; source: string | null; } 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 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 [rows] = await mileagePool.execute( `SELECT DATE_FORMAT(stat_date, '%Y-%m-%d') AS date, daily_km, source FROM v_vehicle_daily_stats WHERE plate = ? AND stat_date >= ? AND stat_date <= ? ORDER BY stat_date`, [plate, fmt(start), fmt(end)] ) as [DayRow[], unknown]; // 同一 plate 同一天可能有多个数据源,取最大 daily_km const map = new Map(); for (const r of rows) { const km = Number(r.daily_km) || 0; const src = r.source || 'NONE'; const existing = map.get(r.date); if (!existing || km > existing.dailyKm) { map.set(r.date, { dailyKm: km, source: src }); } } // 补全:从 start 到 end 每天一条 const result: { date: string; dailyKm: number; isDataSynced: boolean }[] = []; const cursor = new Date(start); while (cursor <= end) { const key = fmt(cursor); const hit = map.get(key); result.push({ date: key, dailyKm: hit?.dailyKm ?? 0, isDataSynced: !!hit && hit.source !== 'NONE', }); cursor.setDate(cursor.getDate() + 1); } return c.json({ plate, start: fmt(start), end: fmt(end), days: result }); } catch (e: unknown) { console.error('vehicle recent error:', e); return c.json({ plate, days: [] }, 500); } }); export default app;