fix(energy): 氢能单价不再加权,混合价组显示「—」并修复 hydrogen_time 歧义
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- pricePerKg 改为 CASE WHEN MIN=MAX THEN MIN ELSE NULL,
同价组返回原价(无小数误读),混合价组返回 null
- 类型 HydrogenStationRow.pricePerKg: number | null
- 前端 mobile/desktop 两处展示在 null 时显示「—」
- 修复 ER_NON_UNIQ_ERROR:tab_import_hydrogen_order 也有 hydrogen_time 字段,
把 SELECT/ORDER BY 中 ${HYDROGEN_LOCAL} 替换为显式 b.hydrogen_time 限定
- 实测:712 个站点-日组中 682 个同价直接显示原价,30 个混合显示「—」
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -197,9 +197,9 @@ export default function HydrogenDaily() {
|
|||||||
>
|
>
|
||||||
<span className="text-[12px] text-slate-600 truncate">
|
<span className="text-[12px] text-slate-600 truncate">
|
||||||
{s.name}
|
{s.name}
|
||||||
<span className="md:hidden text-slate-400 text-[10px]"> · {s.pricePerKg}</span>
|
<span className="md:hidden text-slate-400 text-[10px]"> · {s.pricePerKg == null ? '—' : s.pricePerKg}</span>
|
||||||
</span>
|
</span>
|
||||||
<span className="hidden md:block text-right text-[12px] text-slate-500 font-bold tabular-nums">{s.pricePerKg}</span>
|
<span className="hidden md:block text-right text-[12px] text-slate-500 font-bold tabular-nums">{s.pricePerKg == null ? '—' : s.pricePerKg}</span>
|
||||||
<span className="text-right text-[12px] text-slate-700 font-bold tabular-nums">
|
<span className="text-right text-[12px] text-slate-700 font-bold tabular-nums">
|
||||||
{s.kg.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}
|
{s.kg.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export interface HydrogenRegionShare {
|
|||||||
|
|
||||||
export interface HydrogenStationRow {
|
export interface HydrogenStationRow {
|
||||||
name: string;
|
name: string;
|
||||||
pricePerKg: number;
|
pricePerKg: number | null;
|
||||||
kg: number;
|
kg: number;
|
||||||
chainPct: number;
|
chainPct: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ app.get('/hydrogen/overview', async (c) => {
|
|||||||
LEFT JOIN tab_import_hydrogen_order i ON i.bill_code = b.bill_code
|
LEFT JOIN tab_import_hydrogen_order i ON i.bill_code = b.bill_code
|
||||||
WHERE b.is_deleted = 0
|
WHERE b.is_deleted = 0
|
||||||
AND b.hydrogen_time >= ?
|
AND b.hydrogen_time >= ?
|
||||||
AND YEAR(${HYDROGEN_LOCAL}) = YEAR(CURDATE())
|
AND YEAR(DATE_ADD(b.hydrogen_time, INTERVAL 8 HOUR)) = YEAR(CURDATE())
|
||||||
GROUP BY b.hydrogen_station_id
|
GROUP BY b.hydrogen_station_id
|
||||||
ORDER BY kg DESC
|
ORDER BY kg DESC
|
||||||
LIMIT 5`,
|
LIMIT 5`,
|
||||||
@@ -164,10 +164,10 @@ app.get('/hydrogen/daily', async (c) => {
|
|||||||
].join(' AND ');
|
].join(' AND ');
|
||||||
|
|
||||||
// 站点级聚合(每日 × 每站)。前端组装成 day → stations
|
// 站点级聚合(每日 × 每站)。前端组装成 day → stations
|
||||||
// 站点名 fallback 顺序:内部站表 → 外部站表 → 导入订单表(tab_import_hydrogen_order.hydrogen_station_name,按 bill_code 关联)
|
// 站点名 fallback:内部站表 → 外部站表 → 导入订单表(tab_import_hydrogen_order,按 bill_code 关联)
|
||||||
// 单价用「按量加权」的实际效率价:SUM(费用)/SUM(量),同价组自动等于原价(不再产生意外小数)
|
// 单价不重算:同价组显示原价,混合价组返回 NULL,前端显示「—」
|
||||||
const [stationRows] = await pool.query<RowDataPacket[]>(
|
const [stationRows] = await pool.query<RowDataPacket[]>(
|
||||||
`SELECT DATE_FORMAT(${HYDROGEN_LOCAL}, '%Y-%m-%d') AS d,
|
`SELECT DATE_FORMAT(DATE_ADD(b.hydrogen_time, INTERVAL 8 HOUR), '%Y-%m-%d') AS d,
|
||||||
b.hydrogen_station_id AS stationId,
|
b.hydrogen_station_id AS stationId,
|
||||||
COALESCE(MAX(s.short_name), MAX(s.name),
|
COALESCE(MAX(s.short_name), MAX(s.name),
|
||||||
MAX(os.fixed_station_name), MAX(os.station_name),
|
MAX(os.fixed_station_name), MAX(os.station_name),
|
||||||
@@ -175,7 +175,8 @@ app.get('/hydrogen/daily', async (c) => {
|
|||||||
CASE WHEN b.hydrogen_station_id IS NULL THEN '未关联站点'
|
CASE WHEN b.hydrogen_station_id IS NULL THEN '未关联站点'
|
||||||
ELSE CONCAT('未知站点 #', b.hydrogen_station_id) END) AS stationName,
|
ELSE CONCAT('未知站点 #', b.hydrogen_station_id) END) AS stationName,
|
||||||
ROUND(SUM(b.hydrogen_quantity), 2) AS kg,
|
ROUND(SUM(b.hydrogen_quantity), 2) AS kg,
|
||||||
ROUND(SUM(b.cost_expense) / NULLIF(SUM(b.hydrogen_quantity), 0), 2) AS pricePerKg
|
CASE WHEN MIN(b.cost_price) = MAX(b.cost_price) THEN MIN(b.cost_price)
|
||||||
|
ELSE NULL END AS pricePerKg
|
||||||
FROM tab_energy_hydrogen_bill b
|
FROM tab_energy_hydrogen_bill b
|
||||||
LEFT JOIN tab_hydrogen_site s ON s.id = b.hydrogen_station_id
|
LEFT JOIN tab_hydrogen_site s ON s.id = b.hydrogen_station_id
|
||||||
LEFT JOIN tab_outside_hydrogen_site os ON os.inner_site_id = b.hydrogen_station_id
|
LEFT JOIN tab_outside_hydrogen_site os ON os.inner_site_id = b.hydrogen_station_id
|
||||||
@@ -187,13 +188,13 @@ app.get('/hydrogen/daily', async (c) => {
|
|||||||
|
|
||||||
// 站点环比:同站点上一条记录的 kg
|
// 站点环比:同站点上一条记录的 kg
|
||||||
// 按 stationId 分组、按日期升序计算
|
// 按 stationId 分组、按日期升序计算
|
||||||
type StationRow = { date: string; stationId: number; name: string; kg: number; pricePerKg: number };
|
type StationRow = { date: string; stationId: number; name: string; kg: number; pricePerKg: number | null };
|
||||||
const flat: StationRow[] = stationRows.map(r => ({
|
const flat: StationRow[] = stationRows.map(r => ({
|
||||||
date: r.d as string,
|
date: r.d as string,
|
||||||
stationId: Number(r.stationId),
|
stationId: Number(r.stationId),
|
||||||
name: r.stationName as string,
|
name: r.stationName as string,
|
||||||
kg: Number(r.kg) || 0,
|
kg: Number(r.kg) || 0,
|
||||||
pricePerKg: Number(r.pricePerKg) || 0,
|
pricePerKg: r.pricePerKg == null ? null : Number(r.pricePerKg),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// 计算日级总量 + 日级环比
|
// 计算日级总量 + 日级环比
|
||||||
@@ -243,7 +244,7 @@ app.get('/hydrogen/daily', async (c) => {
|
|||||||
.sort((a, b) => b.kg - a.kg)
|
.sort((a, b) => b.kg - a.kg)
|
||||||
.map(s => ({
|
.map(s => ({
|
||||||
name: s.name,
|
name: s.name,
|
||||||
pricePerKg: Math.round(s.pricePerKg * 100) / 100,
|
pricePerKg: s.pricePerKg == null ? null : Math.round(s.pricePerKg * 100) / 100,
|
||||||
kg: Math.round(s.kg * 100) / 100,
|
kg: Math.round(s.kg * 100) / 100,
|
||||||
chainPct: stationChain.get(`${s.date}|${s.stationId}`) ?? 0,
|
chainPct: stationChain.get(`${s.date}|${s.stationId}`) ?? 0,
|
||||||
})),
|
})),
|
||||||
|
|||||||
Reference in New Issue
Block a user