refactor: add electric order drilldown

This commit is contained in:
kkfluous
2026-08-07 14:55:55 +08:00
parent cf9782562b
commit cdf1fd27e7
8 changed files with 414 additions and 21 deletions
+76
View File
@@ -7,6 +7,7 @@ import {
parseHydrogenCustomerKind,
parseHydrogenCustomerName,
parseHydrogenStationId,
parseEnergyDate,
type HydrogenCustomerKind,
} from './query.js';
import type { AuthUser } from '../../auth/types.js';
@@ -592,6 +593,81 @@ app.get('/electric/overview', async (c) => {
return c.json(data);
});
// =========================================================
// 电能 订单下钻:指定自然日 + 车辆归属,最多返回 500 条明细
// =========================================================
app.get('/electric/orders', async (c) => {
const dateParam = c.req.query('date');
const date = parseEnergyDate(dateParam);
if (date === null) return c.json({ error: 'date 必须是有效的 YYYY-MM-DD 日期' }, 400);
const customerParam = c.req.query('customer');
if (customerParam !== undefined && customerParam !== 'lingniu' && customerParam !== 'external') {
return c.json({ error: 'customer 必须是 lingniu 或 external' }, 400);
}
const customer = customerParam === 'external' ? 'external' : 'lingniu';
const vehicleKind = customer === 'lingniu' ? 'internal' : 'external';
const data = await cached(`electric/orders?date=${date}&customer=${customer}`, async () => {
const params = [date, date, vehicleKind];
const [[summaryRows], [detailRows]] = await Promise.all([
pool.query<RowDataPacket[]>(
`SELECT COUNT(*) AS recordCount,
SUM(kwh) AS totalKwh,
SUM(fee) AS totalFee
FROM bi_ele_charge_record
WHERE start_time >= ? AND start_time < DATE_ADD(?, INTERVAL 1 DAY)
AND vehicle_kind = ?`,
params,
),
pool.query<RowDataPacket[]>(
`SELECT id,
order_no AS orderNo,
DATE_FORMAT(start_time, '%Y-%m-%d %H:%i:%s') AS startTime,
COALESCE(NULLIF(TRIM(station_name), ''), '未指定站点') AS stationName,
COALESCE(NULLIF(TRIM(matched_plate), ''), NULLIF(TRIM(judged_plate), ''), NULLIF(TRIM(plate), ''), '未识别车辆') AS plate,
vehicle_kind AS vehicleKind,
COALESCE(NULLIF(TRIM(order_status), ''), '未指定状态') AS orderStatus,
kwh,
e_fee AS electricityFee,
service_fee AS serviceFee,
fee AS totalFee
FROM bi_ele_charge_record
WHERE start_time >= ? AND start_time < DATE_ADD(?, INTERVAL 1 DAY)
AND vehicle_kind = ?
ORDER BY start_time DESC, id DESC
LIMIT 501`,
params,
),
]);
const summary = summaryRows[0] ?? {};
const truncated = detailRows.length > 500;
return {
date,
vehicleScope: customer,
recordCount: Number(summary.recordCount) || 0,
totalKwh: Math.round((Number(summary.totalKwh) || 0) * 100) / 100,
totalFee: Math.round((Number(summary.totalFee) || 0) * 100) / 100,
truncated,
items: detailRows.slice(0, 500).map(row => ({
id: Number(row.id),
orderNo: String(row.orderNo),
startTime: String(row.startTime),
stationName: String(row.stationName),
plate: String(row.plate),
vehicleKind: row.vehicleKind as 'internal' | 'external' | 'unknown',
orderStatus: String(row.orderStatus),
kwh: Math.round((Number(row.kwh) || 0) * 100) / 100,
electricityFee: Math.round((Number(row.electricityFee) || 0) * 100) / 100,
serviceFee: Math.round((Number(row.serviceFee) || 0) * 100) / 100,
totalFee: Math.round((Number(row.totalFee) || 0) * 100) / 100,
})),
};
});
return c.json(data);
});
// =========================================================
// 电能 每日:月份分组 + 日级行 —— 数据源:bi_ele_charge_record
// 支持 range 参数(thisWeek / thisMonth / last15