diff --git a/package-lock.json b/package-lock.json index 1652476..3d465ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ln-bi", - "version": "1.1.23", + "version": "1.1.24", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ln-bi", - "version": "1.1.23", + "version": "1.1.24", "dependencies": { "@amap/amap-jsapi-loader": "^1.0.1", "@hono/node-server": "^1.13.0", diff --git a/package.json b/package.json index 269359b..db540c6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ln-bi", "private": true, - "version": "1.1.23", + "version": "1.1.24", "type": "module", "scripts": { "dev": "concurrently -n server,client -c blue,green \"npm run dev:server\" \"npm run dev:client\"", diff --git a/src/server/routes/mileage/query-cache.ts b/src/server/routes/mileage/query-cache.ts index f963ae8..980dd97 100644 --- a/src/server/routes/mileage/query-cache.ts +++ b/src/server/routes/mileage/query-cache.ts @@ -21,12 +21,24 @@ async function loadSource(start: string, end: string, protocols: OneOsProtocol[] plates ? Promise.resolve([]) : fetchOneOsDailyMileage(previousMileageDate(start), undefined, protocols, refresh), ]); // Plate-scoped summary requests are used only for filtered trends. - if (plates || start === end) return { summary, yesterdayRows }; - const missing = summary.vehicles.filter(v => v.endDateTotalMileageKm === null && v.validDays + v.anomalyDays > 0); + if (plates) return { summary, yesterdayRows }; + const missing = summary.vehicles.filter(v => v.endDateTotalMileageKm === null); if (!missing.length) return { summary, yesterdayRows }; - const dates = mileageDatesBetween(start, previousMileageDate(end)); - const history = await fetchOneOsMileageDates(dates, missing.map(v => v.plateNumber), protocols); const priorOdometers = new Map(); + const endRows = await fetchOneOsDailyMileage(end, missing.map(v => v.plateNumber), protocols, refresh); + const observationDate = new Intl.DateTimeFormat('en-CA', { timeZone: 'Asia/Shanghai' }); + for (const row of endRows) { + if (row.status !== 'NORMAL' || row.dataQuality !== 'CARRIED_FORWARD' || row.totalMileageKm == null || !row.dataTime) continue; + // OneOS observation timestamps include the Shanghai offset, even for older carried readings. + const time = Date.parse(row.dataTime); + if (!Number.isFinite(time)) continue; + const date = observationDate.format(time); + if (date <= end) priorOdometers.set(row.plateNumber.toUpperCase(), { date, km: row.totalMileageKm }); + } + const unresolved = missing.filter(v => !priorOdometers.has(v.plateNumber) && v.validDays + v.anomalyDays > 0); + if (start === end || !unresolved.length) return { summary, yesterdayRows, priorOdometers }; + const dates = mileageDatesBetween(start, previousMileageDate(end)); + const history = await fetchOneOsMileageDates(dates, unresolved.map(v => v.plateNumber), protocols); for (const date of dates.reverse()) { for (const row of history.get(date) || []) { const plate = row.plateNumber.toUpperCase();