Files
ln-bi/src/modules/energy/hydrogen/station-daily/station-month-range.ts
T
dsh-agent 7556dbcebc refactor(stage2): 生产代码移出 src/vendor,氢能收敛为分层 feature
src/vendor 语义是'第三方/参考',却装着线上氢能看板并反向 import
src/modules,依赖方向倒挂。本次把生产代码归位并建立氢能分层:

  src/modules/energy/hydrogen/
    index.tsx        导航入口(原 HydrogenModule.tsx)
    api.ts types.ts  HTTP 与 DTO
    dev-mock-api.ts  仅 dev 的 vite 插件(仍由 vite.config.ts 引用)
    model/           纯逻辑(format / bearing-labels / daily-detail-format)
    board/           经营看板 UI(原 vendor energy-h2-bi-board)
    station-daily/   单站日报 UI(原 vendor energy-h2-station-daily)
    drill/           下钻弹层 UI(原 hydrogen-bi-v2 的 UI 部分)
    common/          工具与共享组件(原 vendor common + prototype-download)
    fonts/           JetBrains Mono(原 vendor resources/design-system)

- UI 与 CSS 逐字节保留,仅移动位置与改写相对 import。
- 删除自挂载原型入口后遗留的 2 个 annotation-source.json。
- vite.config.ts 与 tsconfig 的路径/exclude 同步清理。
- independent-entry.test.ts 不再硬编码路径,改为断言'两个入口解析到同一文件'。

导入改写用一次性 codemod 完成(按旧位置解析、按新位置重写),
lint / test(131) / build 全绿,可达性分析仍为 0 未引用文件。
2026-09-11 10:14:37 +08:00

38 lines
1.5 KiB
TypeScript

/**
* 客户月度接口固定返回“截至查询结束日的近 12 个月”。
* 键保留完整 YYYY-MM,避免跨年时把不同年份的同月合并。
*/
export function customerMonthRange(asOfYmd: string, count = 12): string[] {
const matched = /^(\d{4})-(\d{2})-\d{2}$/.exec(asOfYmd);
if (!matched || count < 1) return [];
const endYear = Number(matched[1]);
const endMonth = Number(matched[2]);
if (endMonth < 1 || endMonth > 12) return [];
const months: string[] = [];
for (let offset = count - 1; offset >= 0; offset -= 1) {
const date = new Date(Date.UTC(endYear, endMonth - 1 - offset, 1));
months.push(`${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}`);
}
return months;
}
export function customerMonthLabel(monthKey: string): string {
const matched = /^(\d{4})-(\d{2})$/.exec(monthKey);
return matched ? `${matched[1]}年${Number(matched[2])}月` : monthKey;
}
/** 闭区间日数;用于让卡片副标题与实际查询口径保持一致。 */
export function inclusiveDayCount(start: string, end: string): number {
const startTime = Date.parse(`${start}T00:00:00Z`);
const endTime = Date.parse(`${end}T00:00:00Z`);
if (!Number.isFinite(startTime) || !Number.isFinite(endTime) || endTime < startTime) return 0;
return Math.floor((endTime - startTime) / 86_400_000) + 1;
}
export function dateRangeLabel(start: string, end: string): string {
const days = inclusiveDayCount(start, end);
return days > 0 ? `${start} 至 ${end}(共 ${days} 天)` : `${start} 至 ${end}`;
}