fix: 修复bigint精度丢失导致交还替换数据膨胀
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

truck ID 为 MySQL bigint,JavaScript Number 精度不够导致
不同 ID 被截断为相同值造成误匹配。改用 CAST AS CHAR +
字符串 Set 比较。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
kkfluous
2026-03-26 14:50:22 +08:00
parent 23fa3e1531
commit 0b2e2f23b5
2 changed files with 17 additions and 17 deletions

View File

@@ -14,7 +14,7 @@ import type {
const app = new Hono(); const app = new Hono();
const MAIN_SQL = `SELECT const MAIN_SQL = `SELECT
truck.id AS id, CAST(truck.id AS CHAR) AS id,
truck.plate_number AS 车牌号, truck.plate_number AS 车牌号,
truck.vin AS vin, truck.vin AS vin,
truck.brand AS 车辆品牌, truck.brand AS 车辆品牌,
@@ -269,10 +269,10 @@ function getRegionCounts(vehicles: Vehicle[], regions: readonly string[]): Recor
// Weekly truck ID sets, cached // Weekly truck ID sets, cached
interface WeeklyTruckIds { interface WeeklyTruckIds {
pending: Set<number>; pending: Set<string>;
delivered: Set<number>; delivered: Set<string>;
returned: Set<number>; returned: Set<string>;
replaced: Set<number>; replaced: Set<string>;
} }
let cachedWeeklyTruckIds: WeeklyTruckIds | null = null; let cachedWeeklyTruckIds: WeeklyTruckIds | null = null;
let weeklyTruckIdsLastFetch = 0; let weeklyTruckIdsLastFetch = 0;
@@ -284,19 +284,19 @@ async function getWeeklyTruckIds(): Promise<WeeklyTruckIds> {
} }
const [[pendingRows], [deliveredRows], [returnedRows], [replacedRows]] = await Promise.all([ const [[pendingRows], [deliveredRows], [returnedRows], [replacedRows]] = await Promise.all([
pool.query<any[]>(`SELECT id AS truck_id FROM tab_truck WHERE is_deleted=0 AND is_operation=1 AND truck_rent_status=7`), pool.query<any[]>(`SELECT CAST(id AS CHAR) AS truck_id FROM tab_truck WHERE is_deleted=0 AND is_operation=1 AND truck_rent_status=7`),
pool.query<any[]>(`SELECT rent_truck.truck_id FROM tab_truck_rent_take take pool.query<any[]>(`SELECT CAST(rent_truck.truck_id AS CHAR) AS truck_id FROM tab_truck_rent_take take
LEFT JOIN tab_truck_rent_task task ON task.id = take.truck_rent_task_id LEFT JOIN tab_truck_rent_task task ON task.id = take.truck_rent_task_id
LEFT JOIN tab_contract_rent_truck rent_truck ON rent_truck.id = task.contract_rent_truck_id LEFT JOIN tab_contract_rent_truck rent_truck ON rent_truck.id = task.contract_rent_truck_id
WHERE take.is_deleted=0 AND take.take_name IS NOT NULL WHERE take.is_deleted=0 AND take.take_name IS NOT NULL
AND task.task_type=1 AND task.task_status=1 AND take.update_time IS NOT NULL AND task.task_type=1 AND task.task_status=1 AND take.update_time IS NOT NULL
AND take.handover_date >= ${WEEK_START_SQL} AND take.handover_date < ${WEEK_END_SQL}`), AND take.handover_date >= ${WEEK_START_SQL} AND take.handover_date < ${WEEK_END_SQL}`),
pool.query<any[]>(`SELECT rent_truck.truck_id FROM tab_truck_rent_return r pool.query<any[]>(`SELECT CAST(rent_truck.truck_id AS CHAR) AS truck_id FROM tab_truck_rent_return r
LEFT JOIN tab_truck_rent_task task ON task.id = r.truck_rent_task_id LEFT JOIN tab_truck_rent_task task ON task.id = r.truck_rent_task_id
LEFT JOIN tab_contract_rent_truck rent_truck ON rent_truck.id = task.contract_rent_truck_id LEFT JOIN tab_contract_rent_truck rent_truck ON rent_truck.id = task.contract_rent_truck_id
WHERE r.is_deleted=0 AND r.return_date IS NOT NULL WHERE r.is_deleted=0 AND r.return_date IS NOT NULL
AND r.return_date >= ${WEEK_START_SQL} AND r.return_date < ${WEEK_END_SQL}`), AND r.return_date >= ${WEEK_START_SQL} AND r.return_date < ${WEEK_END_SQL}`),
pool.query<any[]>(`SELECT rent_truck.truck_id FROM tab_truck_rent_take take pool.query<any[]>(`SELECT CAST(rent_truck.truck_id AS CHAR) AS truck_id FROM tab_truck_rent_take take
LEFT JOIN tab_truck_rent_task task ON task.id = take.truck_rent_task_id LEFT JOIN tab_truck_rent_task task ON task.id = take.truck_rent_task_id
LEFT JOIN tab_contract_rent_truck rent_truck ON rent_truck.id = task.contract_rent_truck_id LEFT JOIN tab_contract_rent_truck rent_truck ON rent_truck.id = task.contract_rent_truck_id
WHERE take.is_deleted=0 AND take.take_name IS NOT NULL WHERE take.is_deleted=0 AND take.take_name IS NOT NULL
@@ -304,7 +304,7 @@ async function getWeeklyTruckIds(): Promise<WeeklyTruckIds> {
AND take.handover_date >= ${WEEK_START_SQL} AND take.handover_date < ${WEEK_END_SQL}`), AND take.handover_date >= ${WEEK_START_SQL} AND take.handover_date < ${WEEK_END_SQL}`),
]); ]);
const toSet = (rows: any[]) => new Set((rows as any[]).map((r) => Number(r.truck_id)).filter(Boolean)); const toSet = (rows: any[]) => new Set((rows as any[]).map((r) => String(r.truck_id)).filter((s) => s && s !== 'null'));
cachedWeeklyTruckIds = { cachedWeeklyTruckIds = {
pending: toSet(pendingRows as any[]), pending: toSet(pendingRows as any[]),
delivered: toSet(deliveredRows as any[]), delivered: toSet(deliveredRows as any[]),
@@ -316,7 +316,7 @@ async function getWeeklyTruckIds(): Promise<WeeklyTruckIds> {
} }
function getStats(list: Vehicle[], weeklyIds?: WeeklyTruckIds) { function getStats(list: Vehicle[], weeklyIds?: WeeklyTruckIds) {
const ids = list.map((v) => v.id); const strIds = list.map((v) => String(v.id));
return { return {
total: list.length, total: list.length,
inventory: list.filter((v) => v.status === 'Inventory').length, inventory: list.filter((v) => v.status === 'Inventory').length,
@@ -324,11 +324,11 @@ function getStats(list: Vehicle[], weeklyIds?: WeeklyTruckIds) {
list.filter((v) => v.status === 'Inventory'), list.filter((v) => v.status === 'Inventory'),
REGIONS, REGIONS,
), ),
pending: weeklyIds ? ids.filter((id) => weeklyIds.pending.has(id)).length : 0, pending: weeklyIds ? strIds.filter((id) => weeklyIds.pending.has(id)).length : 0,
operating: list.filter((v) => v.status === 'Operating').length, operating: list.filter((v) => v.status === 'Operating').length,
weeklyDelivered: weeklyIds ? ids.filter((id) => weeklyIds.delivered.has(id)).length : 0, weeklyDelivered: weeklyIds ? strIds.filter((id) => weeklyIds.delivered.has(id)).length : 0,
weeklyReturned: weeklyIds ? ids.filter((id) => weeklyIds.returned.has(id)).length : 0, weeklyReturned: weeklyIds ? strIds.filter((id) => weeklyIds.returned.has(id)).length : 0,
weeklyReplaced: weeklyIds ? ids.filter((id) => weeklyIds.replaced.has(id)).length : 0, weeklyReplaced: weeklyIds ? strIds.filter((id) => weeklyIds.replaced.has(id)).length : 0,
}; };
} }

View File

@@ -1,5 +1,5 @@
export interface VehicleRow { export interface VehicleRow {
id: number; id: string;
车牌号: string; 车牌号: string;
vin: string; vin: string;
车辆品牌: string; 车辆品牌: string;
@@ -28,7 +28,7 @@ export interface VehicleRow {
} }
export interface Vehicle { export interface Vehicle {
id: number; id: string;
plateNumber: string; plateNumber: string;
vin: string; vin: string;
type: string; type: string;