diff --git a/src/App.tsx b/src/App.tsx
index c8ae409..08b23b9 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -16,7 +16,7 @@ const EleImportPage = lazy(() => import("./modules/ele/EleImportPage"));
const FeedbackAdminPage = lazy(() => import("./modules/admin/FeedbackAdminPage"));
const HydrogenPrototypeBoard = lazy(
() =>
- import("./vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/EnergyBiBoardApp").then(
+ import("./modules/energy/hydrogen/board/EnergyBiBoardApp").then(
({ EnergyBiBoardApp }) => ({ default: EnergyBiBoardApp }),
),
);
diff --git a/src/app/modules.ts b/src/app/modules.ts
index 875b804..cfa1ef9 100644
--- a/src/app/modules.ts
+++ b/src/app/modules.ts
@@ -15,7 +15,7 @@ import type { PathSet } from './routing';
const AssetsModule = lazy(() => import('../modules/assets/AssetsModule'));
const MileageModule = lazy(() => import('../modules/mileage/MileageModule'));
const SchedulingModule = lazy(() => import('../modules/scheduling/SchedulingModule'));
-const HydrogenModule = lazy(() => import('../modules/energy/HydrogenModule'));
+const HydrogenModule = lazy(() => import('../modules/energy/hydrogen/index'));
const ElectricModule = lazy(() => import('../modules/energy/ElectricModule'));
const EtcModule = lazy(() => import('../modules/energy/EtcModule'));
const VehicleHeatmapModule = lazy(() => import('../modules/vehicle-heatmap/VehicleHeatmapModule'));
diff --git a/src/modules/energy/hydrogen-bi-v2/independent-entry.test.ts b/src/modules/energy/hydrogen-bi-v2/independent-entry.test.ts
deleted file mode 100644
index 74bb1bc..0000000
--- a/src/modules/energy/hydrogen-bi-v2/independent-entry.test.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import assert from "node:assert/strict";
-import { readFileSync } from "node:fs";
-import test from "node:test";
-
-test("能源氢费 BI 入口与独立验收地址复用同一看板", () => {
- const entry = readFileSync(new URL("../HydrogenModule.tsx", import.meta.url), "utf8");
- const app = readFileSync(new URL("../../../App.tsx", import.meta.url), "utf8");
-
- assert.match(entry, /vendor\/lnbi-8113-exact\/prototypes\/energy-h2-bi-board\/EnergyBiBoardApp/);
- assert.match(entry, /return /);
- assert.match(app, /vendor\/lnbi-8113-exact\/prototypes\/energy-h2-bi-board\/EnergyBiBoardApp/);
-});
diff --git a/src/modules/energy/hydrogen-bi-v2/api.ts b/src/modules/energy/hydrogen/api.ts
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/api.ts
rename to src/modules/energy/hydrogen/api.ts
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/.spec/2026-08-29-mobile-overview-layout.md b/src/modules/energy/hydrogen/board/.spec/2026-08-29-mobile-overview-layout.md
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/.spec/2026-08-29-mobile-overview-layout.md
rename to src/modules/energy/hydrogen/board/.spec/2026-08-29-mobile-overview-layout.md
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/.spec/requirements-prd.md b/src/modules/energy/hydrogen/board/.spec/requirements-prd.md
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/.spec/requirements-prd.md
rename to src/modules/energy/hydrogen/board/.spec/requirements-prd.md
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/DEVELOPER-HANDOFF.md b/src/modules/energy/hydrogen/board/DEVELOPER-HANDOFF.md
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/DEVELOPER-HANDOFF.md
rename to src/modules/energy/hydrogen/board/DEVELOPER-HANDOFF.md
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/EnergyBiBoardApp.tsx b/src/modules/energy/hydrogen/board/EnergyBiBoardApp.tsx
similarity index 99%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/EnergyBiBoardApp.tsx
rename to src/modules/energy/hydrogen/board/EnergyBiBoardApp.tsx
index 7d69781..222b948 100644
--- a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/EnergyBiBoardApp.tsx
+++ b/src/modules/energy/hydrogen/board/EnergyBiBoardApp.tsx
@@ -20,8 +20,8 @@ import {
X,
Zap,
} from 'lucide-react';
-import { downloadExcelAoa } from '../../common/download-xls';
-import { MobileListFullscreenButton } from '../../common/MobileListFullscreenButton';
+import { downloadExcelAoa } from '../common/download-xls';
+import { MobileListFullscreenButton } from '../common/MobileListFullscreenButton';
import {
SOURCE_LABEL,
companyRowsForStats,
@@ -56,12 +56,12 @@ import {
type HostView,
type H2OrderRow,
} from './types';
-import { StationDailyApp } from '../energy-h2-station-daily/StationDailyApp';
-import '../energy-h2-station-daily/styles.css';
+import { StationDailyApp } from '../station-daily/StationDailyApp';
+import '../station-daily/styles.css';
import './styles/energy-bi-board.css';
-import { fetchH2BiDaily, fetchH2BiDailyTree, fetchH2BiMeta, fetchH2BiOverview } from '../../../../modules/energy/hydrogen-bi-v2/api';
-import { PrototypeRealDailyView } from '../../../../modules/energy/hydrogen-bi-v2/prototype-real-daily';
-import { PrototypeDrillModal, prototypeFleetScope } from '../../../../modules/energy/hydrogen-bi-v2/prototype-real-drills';
+import { fetchH2BiDaily, fetchH2BiDailyTree, fetchH2BiMeta, fetchH2BiOverview } from '../api';
+import { PrototypeRealDailyView } from '../drill/prototype-real-daily';
+import { PrototypeDrillModal, prototypeFleetScope } from '../drill/prototype-real-drills';
type BoardScope = 'global' | 'station';
type StatsTab = 'siteMonth' | 'customer';
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/data/aggregates.ts b/src/modules/energy/hydrogen/board/data/aggregates.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/data/aggregates.ts
rename to src/modules/energy/hydrogen/board/data/aggregates.ts
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/data/mockBoard.ts b/src/modules/energy/hydrogen/board/data/mockBoard.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/data/mockBoard.ts
rename to src/modules/energy/hydrogen/board/data/mockBoard.ts
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/data/mockDaily.ts b/src/modules/energy/hydrogen/board/data/mockDaily.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/data/mockDaily.ts
rename to src/modules/energy/hydrogen/board/data/mockDaily.ts
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/styles/energy-bi-board.css b/src/modules/energy/hydrogen/board/styles/energy-bi-board.css
similarity index 99%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/styles/energy-bi-board.css
rename to src/modules/energy/hydrogen/board/styles/energy-bi-board.css
index 858e19a..603e4bd 100644
--- a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/styles/energy-bi-board.css
+++ b/src/modules/energy/hydrogen/board/styles/energy-bi-board.css
@@ -3,7 +3,7 @@
* 本原型独立嵌入 bi-next,禁止引入 OneOS V2 组件;
* 字体例外:汉字/UI 与数字等宽对齐 V2 Token(DESIGN §2.2)。
*/
-@import '../../../resources/design-system/fonts/jetbrains-mono/jetbrains-mono.css';
+@import '../../fonts/jetbrains-mono/jetbrains-mono.css';
/* —— 访问口令门(轻门禁 · 对齐宿主蓝系,非 V2 组件) —— */
.ehb-gate {
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/types.ts b/src/modules/energy/hydrogen/board/types.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/types.ts
rename to src/modules/energy/hydrogen/board/types.ts
diff --git a/src/vendor/lnbi-8113-exact/common/MobileListFullscreenButton.tsx b/src/modules/energy/hydrogen/common/MobileListFullscreenButton.tsx
similarity index 100%
rename from src/vendor/lnbi-8113-exact/common/MobileListFullscreenButton.tsx
rename to src/modules/energy/hydrogen/common/MobileListFullscreenButton.tsx
diff --git a/src/vendor/lnbi-8113-exact/common/download-xls.js b/src/modules/energy/hydrogen/common/download-xls.js
similarity index 100%
rename from src/vendor/lnbi-8113-exact/common/download-xls.js
rename to src/modules/energy/hydrogen/common/download-xls.js
diff --git a/src/vendor/lnbi-8113-exact/common/energy-spot-cash-intake/index.ts b/src/modules/energy/hydrogen/common/energy-spot-cash-intake/index.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/common/energy-spot-cash-intake/index.ts
rename to src/modules/energy/hydrogen/common/energy-spot-cash-intake/index.ts
diff --git a/src/vendor/lnbi-8113-exact/common/energy-spot-cash-intake/store.ts b/src/modules/energy/hydrogen/common/energy-spot-cash-intake/store.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/common/energy-spot-cash-intake/store.ts
rename to src/modules/energy/hydrogen/common/energy-spot-cash-intake/store.ts
diff --git a/src/vendor/lnbi-8113-exact/common/energy-spot-cash-intake/types.ts b/src/modules/energy/hydrogen/common/energy-spot-cash-intake/types.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/common/energy-spot-cash-intake/types.ts
rename to src/modules/energy/hydrogen/common/energy-spot-cash-intake/types.ts
diff --git a/src/vendor/lnbi-8113-exact/common/mobile-list-fullscreen.css b/src/modules/energy/hydrogen/common/mobile-list-fullscreen.css
similarity index 100%
rename from src/vendor/lnbi-8113-exact/common/mobile-list-fullscreen.css
rename to src/modules/energy/hydrogen/common/mobile-list-fullscreen.css
diff --git a/src/vendor/lnbi-8113-exact/common/phone-viewport.test.ts b/src/modules/energy/hydrogen/common/phone-viewport.test.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/common/phone-viewport.test.ts
rename to src/modules/energy/hydrogen/common/phone-viewport.test.ts
diff --git a/src/vendor/lnbi-8113-exact/common/phone-viewport.ts b/src/modules/energy/hydrogen/common/phone-viewport.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/common/phone-viewport.ts
rename to src/modules/energy/hydrogen/common/phone-viewport.ts
diff --git a/src/modules/energy/hydrogen-bi-v2/prototype-download.ts b/src/modules/energy/hydrogen/common/prototype-download.ts
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/prototype-download.ts
rename to src/modules/energy/hydrogen/common/prototype-download.ts
diff --git a/src/modules/energy/hydrogen-bi-v2/dev-mock-api.test.ts b/src/modules/energy/hydrogen/dev-mock-api.test.ts
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/dev-mock-api.test.ts
rename to src/modules/energy/hydrogen/dev-mock-api.test.ts
diff --git a/src/modules/energy/hydrogen-bi-v2/dev-mock-api.ts b/src/modules/energy/hydrogen/dev-mock-api.ts
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/dev-mock-api.ts
rename to src/modules/energy/hydrogen/dev-mock-api.ts
diff --git a/src/modules/energy/hydrogen-bi-v2/drill-pagination.test.ts b/src/modules/energy/hydrogen/drill-pagination.test.ts
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/drill-pagination.test.ts
rename to src/modules/energy/hydrogen/drill-pagination.test.ts
diff --git a/src/modules/energy/hydrogen-bi-v2/daily-detail-controls.tsx b/src/modules/energy/hydrogen/drill/daily-detail-controls.tsx
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/daily-detail-controls.tsx
rename to src/modules/energy/hydrogen/drill/daily-detail-controls.tsx
diff --git a/src/modules/energy/hydrogen-bi-v2/daily-detail.test.ts b/src/modules/energy/hydrogen/drill/daily-detail.test.ts
similarity index 94%
rename from src/modules/energy/hydrogen-bi-v2/daily-detail.test.ts
rename to src/modules/energy/hydrogen/drill/daily-detail.test.ts
index 7e9cef9..a9c4c9b 100644
--- a/src/modules/energy/hydrogen-bi-v2/daily-detail.test.ts
+++ b/src/modules/energy/hydrogen/drill/daily-detail.test.ts
@@ -3,8 +3,8 @@ import test from "node:test";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { DailyBranchState, DailyTreeButton } from "./daily-detail-controls";
-import { dailySummaryRows, formatDailyChange } from "./daily-detail-format";
-import type { H2BiDailyResponse } from "./types";
+import { dailySummaryRows, formatDailyChange } from "../model/daily-detail-format";
+import type { H2BiDailyResponse } from "../types";
test("每日环比区分真实零值、缺失值和非数值", () => {
for (const value of [null, undefined, NaN, Infinity, "0"]) assert.equal(formatDailyChange(value), "环比 —");
diff --git a/src/modules/energy/hydrogen-bi-v2/drill-prototype-parity.css b/src/modules/energy/hydrogen/drill/drill-prototype-parity.css
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/drill-prototype-parity.css
rename to src/modules/energy/hydrogen/drill/drill-prototype-parity.css
diff --git a/src/modules/energy/hydrogen-bi-v2/drill-workspace.css b/src/modules/energy/hydrogen/drill/drill-workspace.css
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/drill-workspace.css
rename to src/modules/energy/hydrogen/drill/drill-workspace.css
diff --git a/src/modules/energy/hydrogen-bi-v2/prototype-real-daily.tsx b/src/modules/energy/hydrogen/drill/prototype-real-daily.tsx
similarity index 99%
rename from src/modules/energy/hydrogen-bi-v2/prototype-real-daily.tsx
rename to src/modules/energy/hydrogen/drill/prototype-real-daily.tsx
index f5f36cd..f2854a5 100644
--- a/src/modules/energy/hydrogen-bi-v2/prototype-real-daily.tsx
+++ b/src/modules/energy/hydrogen/drill/prototype-real-daily.tsx
@@ -1,9 +1,9 @@
import { Fragment, useEffect, useMemo, useRef, useState } from "react";
import { Download, RefreshCw, Truck } from "lucide-react";
import { DailyTreeButton, DailyBranchState } from "./daily-detail-controls";
-import { dailySummaryRows, formatDailyChange } from "./daily-detail-format";
-import { fetchH2BiDaily, fetchH2BiDailyTree, fetchH2BiDrill } from "./api";
-import { downloadExcelAoa } from "./prototype-download";
+import { dailySummaryRows, formatDailyChange } from "../model/daily-detail-format";
+import { fetchH2BiDaily, fetchH2BiDailyTree, fetchH2BiDrill } from "../api";
+import { downloadExcelAoa } from "../common/prototype-download";
import "./real-daily-mobile.css";
import type {
H2BiDailyResponse,
@@ -11,7 +11,7 @@ import type {
H2BiDrillResponse,
H2BiQuery,
H2BiVehicleScope,
-} from "./types";
+} from "../types";
const format = (value: number, digits = 2) =>
value.toLocaleString("zh-CN", {
diff --git a/src/modules/energy/hydrogen-bi-v2/prototype-real-drills.tsx b/src/modules/energy/hydrogen/drill/prototype-real-drills.tsx
similarity index 99%
rename from src/modules/energy/hydrogen-bi-v2/prototype-real-drills.tsx
rename to src/modules/energy/hydrogen/drill/prototype-real-drills.tsx
index 3dcde5d..7cfd91f 100644
--- a/src/modules/energy/hydrogen-bi-v2/prototype-real-drills.tsx
+++ b/src/modules/energy/hydrogen/drill/prototype-real-drills.tsx
@@ -2,10 +2,10 @@ import { Component, Fragment, useEffect, useMemo, useRef, useState } from "react
import type { ErrorInfo, ReactNode } from "react";
import { createPortal } from "react-dom";
import { ChevronDown, ChevronLeft, Download, Search, SlidersHorizontal, Truck, X } from "lucide-react";
-import { MobileListFullscreenButton } from "../../../vendor/lnbi-8113-exact/common/MobileListFullscreenButton";
-import { fetchAllH2BiDrill, fetchH2BiDrill, fetchH2BiMeta } from "./api";
-import { downloadExcelAoa } from "./prototype-download";
-import { bearingLabels } from "./bearing-labels";
+import { MobileListFullscreenButton } from "../common/MobileListFullscreenButton";
+import { fetchAllH2BiDrill, fetchH2BiDrill, fetchH2BiMeta } from "../api";
+import { downloadExcelAoa } from "../common/prototype-download";
+import { bearingLabels } from "../model/bearing-labels";
import type {
H2BiDrillGroupBy,
H2BiDrillGroupRow,
@@ -14,7 +14,7 @@ import type {
H2BiMetaResponse,
H2BiQuery,
H2BiVehicleScope,
-} from "./types";
+} from "../types";
import "./drill-prototype-parity.css";
type DrillKind = "kpi" | "customer" | "station" | "records";
diff --git a/src/modules/energy/hydrogen-bi-v2/real-daily-mobile.css b/src/modules/energy/hydrogen/drill/real-daily-mobile.css
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/real-daily-mobile.css
rename to src/modules/energy/hydrogen/drill/real-daily-mobile.css
diff --git a/src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/JetBrainsMono-Bold.woff2 b/src/modules/energy/hydrogen/fonts/jetbrains-mono/JetBrainsMono-Bold.woff2
similarity index 100%
rename from src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/JetBrainsMono-Bold.woff2
rename to src/modules/energy/hydrogen/fonts/jetbrains-mono/JetBrainsMono-Bold.woff2
diff --git a/src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/JetBrainsMono-ExtraBold.woff2 b/src/modules/energy/hydrogen/fonts/jetbrains-mono/JetBrainsMono-ExtraBold.woff2
similarity index 100%
rename from src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/JetBrainsMono-ExtraBold.woff2
rename to src/modules/energy/hydrogen/fonts/jetbrains-mono/JetBrainsMono-ExtraBold.woff2
diff --git a/src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/JetBrainsMono-Medium.woff2 b/src/modules/energy/hydrogen/fonts/jetbrains-mono/JetBrainsMono-Medium.woff2
similarity index 100%
rename from src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/JetBrainsMono-Medium.woff2
rename to src/modules/energy/hydrogen/fonts/jetbrains-mono/JetBrainsMono-Medium.woff2
diff --git a/src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/JetBrainsMono-Regular.woff2 b/src/modules/energy/hydrogen/fonts/jetbrains-mono/JetBrainsMono-Regular.woff2
similarity index 100%
rename from src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/JetBrainsMono-Regular.woff2
rename to src/modules/energy/hydrogen/fonts/jetbrains-mono/JetBrainsMono-Regular.woff2
diff --git a/src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/JetBrainsMono-SemiBold.woff2 b/src/modules/energy/hydrogen/fonts/jetbrains-mono/JetBrainsMono-SemiBold.woff2
similarity index 100%
rename from src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/JetBrainsMono-SemiBold.woff2
rename to src/modules/energy/hydrogen/fonts/jetbrains-mono/JetBrainsMono-SemiBold.woff2
diff --git a/src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/OFL.txt b/src/modules/energy/hydrogen/fonts/jetbrains-mono/OFL.txt
similarity index 100%
rename from src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/OFL.txt
rename to src/modules/energy/hydrogen/fonts/jetbrains-mono/OFL.txt
diff --git a/src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/README.md b/src/modules/energy/hydrogen/fonts/jetbrains-mono/README.md
similarity index 100%
rename from src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/README.md
rename to src/modules/energy/hydrogen/fonts/jetbrains-mono/README.md
diff --git a/src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/jetbrains-mono.css b/src/modules/energy/hydrogen/fonts/jetbrains-mono/jetbrains-mono.css
similarity index 100%
rename from src/vendor/lnbi-8113-exact/resources/design-system/fonts/jetbrains-mono/jetbrains-mono.css
rename to src/modules/energy/hydrogen/fonts/jetbrains-mono/jetbrains-mono.css
diff --git a/src/modules/energy/hydrogen/independent-entry.test.ts b/src/modules/energy/hydrogen/independent-entry.test.ts
new file mode 100644
index 0000000..1884769
--- /dev/null
+++ b/src/modules/energy/hydrogen/independent-entry.test.ts
@@ -0,0 +1,37 @@
+import assert from "node:assert/strict";
+import { readFileSync } from "node:fs";
+import { fileURLToPath } from "node:url";
+import path from "node:path";
+import test from "node:test";
+
+const here = path.dirname(fileURLToPath(import.meta.url));
+
+/** 抽出文件里指向某个模块的 import 说明符(支持静态 import 与动态 import())。 */
+function importedSpecifier(source: string, moduleName: string): string | null {
+ const patterns = [
+ new RegExp(`from\\s*["']([^"']*${moduleName})["']`),
+ new RegExp(`import\\(\\s*["']([^"']*${moduleName})["']\\s*\\)`),
+ ];
+ for (const re of patterns) {
+ const match = source.match(re);
+ if (match) return match[1];
+ }
+ return null;
+}
+
+test("能源氢费 BI 入口与独立验收地址复用同一看板", () => {
+ const entryPath = path.join(here, "index.tsx");
+ const appPath = path.join(here, "..", "..", "..", "App.tsx");
+ const entry = readFileSync(entryPath, "utf8");
+ const app = readFileSync(appPath, "utf8");
+
+ const entrySpec = importedSpecifier(entry, "EnergyBiBoardApp");
+ const appSpec = importedSpecifier(app, "EnergyBiBoardApp");
+ assert.ok(entrySpec, "氢费 BI 入口必须引用 EnergyBiBoardApp");
+ assert.ok(appSpec, "App.tsx 的独立验收路由必须引用 EnergyBiBoardApp");
+
+ // 不锁定具体路径,只锁定"两个入口解析到同一个文件",避免目录调整造成无意义漂移。
+ const resolve = (spec: string, from: string) => path.resolve(path.dirname(from), spec);
+ assert.equal(resolve(entrySpec!, entryPath), resolve(appSpec!, appPath));
+ assert.match(entry, /return /);
+});
diff --git a/src/modules/energy/HydrogenModule.tsx b/src/modules/energy/hydrogen/index.tsx
similarity index 68%
rename from src/modules/energy/HydrogenModule.tsx
rename to src/modules/energy/hydrogen/index.tsx
index 0be0293..b11c025 100644
--- a/src/modules/energy/HydrogenModule.tsx
+++ b/src/modules/energy/hydrogen/index.tsx
@@ -1,4 +1,4 @@
-import { EnergyBiBoardApp } from '../../vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/EnergyBiBoardApp';
+import { EnergyBiBoardApp } from './board/EnergyBiBoardApp';
/**
* The accepted hydrogen fee BI surface. It is shared with the independent
diff --git a/src/modules/energy/hydrogen-bi-v2/bearing-labels.test.ts b/src/modules/energy/hydrogen/model/bearing-labels.test.ts
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/bearing-labels.test.ts
rename to src/modules/energy/hydrogen/model/bearing-labels.test.ts
diff --git a/src/modules/energy/hydrogen-bi-v2/bearing-labels.ts b/src/modules/energy/hydrogen/model/bearing-labels.ts
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/bearing-labels.ts
rename to src/modules/energy/hydrogen/model/bearing-labels.ts
diff --git a/src/modules/energy/hydrogen-bi-v2/daily-detail-format.ts b/src/modules/energy/hydrogen/model/daily-detail-format.ts
similarity index 92%
rename from src/modules/energy/hydrogen-bi-v2/daily-detail-format.ts
rename to src/modules/energy/hydrogen/model/daily-detail-format.ts
index 1c7245c..a99ac50 100644
--- a/src/modules/energy/hydrogen-bi-v2/daily-detail-format.ts
+++ b/src/modules/energy/hydrogen/model/daily-detail-format.ts
@@ -1,4 +1,4 @@
-import type { H2BiDailyResponse } from "./types";
+import type { H2BiDailyResponse } from "../types";
export function formatDailyChange(value: unknown): string {
if (typeof value !== "number" || !Number.isFinite(value)) return "环比 —";
diff --git a/src/modules/energy/hydrogen-bi-v2/display-format.test.ts b/src/modules/energy/hydrogen/model/display-format.test.ts
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/display-format.test.ts
rename to src/modules/energy/hydrogen/model/display-format.test.ts
diff --git a/src/modules/energy/hydrogen-bi-v2/display-format.ts b/src/modules/energy/hydrogen/model/display-format.ts
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/display-format.ts
rename to src/modules/energy/hydrogen/model/display-format.ts
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/.spec/requirements-prd.md b/src/modules/energy/hydrogen/station-daily/.spec/requirements-prd.md
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/.spec/requirements-prd.md
rename to src/modules/energy/hydrogen/station-daily/.spec/requirements-prd.md
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/SdCustomerMultiSelect.tsx b/src/modules/energy/hydrogen/station-daily/SdCustomerMultiSelect.tsx
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/SdCustomerMultiSelect.tsx
rename to src/modules/energy/hydrogen/station-daily/SdCustomerMultiSelect.tsx
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/SdDateRangePicker.tsx b/src/modules/energy/hydrogen/station-daily/SdDateRangePicker.tsx
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/SdDateRangePicker.tsx
rename to src/modules/energy/hydrogen/station-daily/SdDateRangePicker.tsx
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/StationDailyApp.tsx b/src/modules/energy/hydrogen/station-daily/StationDailyApp.tsx
similarity index 98%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/StationDailyApp.tsx
rename to src/modules/energy/hydrogen/station-daily/StationDailyApp.tsx
index a0f1a11..316bea8 100644
--- a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/StationDailyApp.tsx
+++ b/src/modules/energy/hydrogen/station-daily/StationDailyApp.tsx
@@ -5,9 +5,9 @@
*/
import React, { useEffect, useMemo, useState } from 'react';
import { ArrowUpRight, Fuel, MapPin, RefreshCw, X } from 'lucide-react';
-import { MobileListFullscreenButton } from '../../common/MobileListFullscreenButton';
-import { fetchHydrogenStationBoard } from '../../../../modules/energy/api';
-import type { HydrogenStationBoardResponse } from '../../../../modules/energy/types';
+import { MobileListFullscreenButton } from '../common/MobileListFullscreenButton';
+import { fetchHydrogenStationBoard } from '../../api';
+import type { HydrogenStationBoardResponse } from '../../types';
import type { StationDailyVolumeRow } from './data/mockStationDaily';
import { SdDateRangePicker } from './SdDateRangePicker';
import { StationDailyDetailView } from './StationDailyDetailView';
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/StationDailyDetailView.tsx b/src/modules/energy/hydrogen/station-daily/StationDailyDetailView.tsx
similarity index 98%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/StationDailyDetailView.tsx
rename to src/modules/energy/hydrogen/station-daily/StationDailyDetailView.tsx
index 003d7cf..0354e75 100644
--- a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/StationDailyDetailView.tsx
+++ b/src/modules/energy/hydrogen/station-daily/StationDailyDetailView.tsx
@@ -5,17 +5,17 @@
*/
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { ArrowLeft, ChevronDown, ChevronUp, Download, RefreshCw } from 'lucide-react';
-import { downloadExcelAoa } from '../../common/download-xls';
-import { MobileListFullscreenButton } from '../../common/MobileListFullscreenButton';
+import { downloadExcelAoa } from '../common/download-xls';
+import { MobileListFullscreenButton } from '../common/MobileListFullscreenButton';
import {
SPOT_PAY_METHOD_LABEL,
type StationCashIntakeDay,
-} from '../../common/energy-spot-cash-intake';
-import { fetchHydrogenStationBoard } from '../../../../modules/energy/api';
-import { fetchAllH2BiDrillRecords } from '../../../../modules/energy/hydrogen-bi-v2/api';
-import { PrototypeDrillModal } from '../../../../modules/energy/hydrogen-bi-v2/prototype-real-drills';
+} from '../common/energy-spot-cash-intake';
+import { fetchHydrogenStationBoard } from '../../api';
+import { fetchAllH2BiDrillRecords } from '../api';
+import { PrototypeDrillModal } from '../drill/prototype-real-drills';
import { MobileDailyList, MobileCustomerMonthList } from './StationMobileLists';
-import type { HydrogenStationBoardResponse } from '../../../../modules/energy/types';
+import type { HydrogenStationBoardResponse } from '../../types';
import {
monthTotals,
stationTrendDateLabel,
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/StationMobileLists.tsx b/src/modules/energy/hydrogen/station-daily/StationMobileLists.tsx
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/StationMobileLists.tsx
rename to src/modules/energy/hydrogen/station-daily/StationMobileLists.tsx
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/data/mockStationDaily.ts b/src/modules/energy/hydrogen/station-daily/data/mockStationDaily.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/data/mockStationDaily.ts
rename to src/modules/energy/hydrogen/station-daily/data/mockStationDaily.ts
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/station-mobile-list-model.test.ts b/src/modules/energy/hydrogen/station-daily/station-mobile-list-model.test.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/station-mobile-list-model.test.ts
rename to src/modules/energy/hydrogen/station-daily/station-mobile-list-model.test.ts
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/station-mobile-list-model.ts b/src/modules/energy/hydrogen/station-daily/station-mobile-list-model.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/station-mobile-list-model.ts
rename to src/modules/energy/hydrogen/station-daily/station-mobile-list-model.ts
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/station-mobile-lists.css b/src/modules/energy/hydrogen/station-daily/station-mobile-lists.css
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/station-mobile-lists.css
rename to src/modules/energy/hydrogen/station-daily/station-mobile-lists.css
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/station-month-range.test.ts b/src/modules/energy/hydrogen/station-daily/station-month-range.test.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/station-month-range.test.ts
rename to src/modules/energy/hydrogen/station-daily/station-month-range.test.ts
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/station-month-range.ts b/src/modules/energy/hydrogen/station-daily/station-month-range.ts
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/station-month-range.ts
rename to src/modules/energy/hydrogen/station-daily/station-month-range.ts
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/styles.css b/src/modules/energy/hydrogen/station-daily/styles.css
similarity index 100%
rename from src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/styles.css
rename to src/modules/energy/hydrogen/station-daily/styles.css
diff --git a/src/modules/energy/hydrogen-bi-v2/types.ts b/src/modules/energy/hydrogen/types.ts
similarity index 100%
rename from src/modules/energy/hydrogen-bi-v2/types.ts
rename to src/modules/energy/hydrogen/types.ts
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/annotation-source.json b/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/annotation-source.json
deleted file mode 100644
index d38577a..0000000
--- a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-bi-board/annotation-source.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "directory": {
- "title": "能源氢费经营看板",
- "nodes": [
- {
- "id": "overview",
- "title": "产品需求说明(PRD)",
- "type": "markdown",
- "path": ".spec/requirements-prd.md",
- "description": "口令 lingniu · 顶栏全局/单站 · 无关联入口卡 · 默认全部车辆·KPI/图表/钻取跟随筛选 · 无车牌归外部车辆 · 外部主数据见 energy-h2-external-* · 分流 own→氢费明细 external→仅 BI"
- },
- {
- "id": "board-app",
- "title": "氢能经营看板",
- "type": "route",
- "path": "/prototypes/energy-h2-bi-board",
- "description": "顶栏全局/单站;责任主体统一为我司承担、客户承担、待核准三类,自行并入客户承担;PC 展示五项 KPI,移动端五项均可见可点;KPI 穿透支持按加氢站/按客户切换并追到车辆和订单;所有页面、全屏明细和钻取弹窗明确展示开始与结束时间,经营汇总到天、当日实时到分钟、订单和加氢流水到秒"
- },
- {
- "id": "energy-board-plan",
- "title": "能源 BI 看板方案",
- "type": "markdown",
- "path": "../../resources/prd/energy-board-plan-20260806.md"
- },
- {
- "id": "host-ref",
- "title": "宿主 overview 视觉参考",
- "type": "markdown",
- "path": "../../resources/prd/energy-bi-host-ref/content.md"
- }
- ]
- }
-}
diff --git a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/annotation-source.json b/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/annotation-source.json
deleted file mode 100644
index a991344..0000000
--- a/src/vendor/lnbi-8113-exact/prototypes/energy-h2-station-daily/annotation-source.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "directory": {
- "title": "加氢站日报",
- "nodes": [
- {
- "id": "overview",
- "title": "产品需求说明(PRD)",
- "type": "markdown",
- "path": ".spec/requirements-prd.md",
- "description": "口令 lingniu · 起止查询日期 · KPI钻取 · 各站行内加氢量占比 · 按量降序"
- },
- {
- "id": "app",
- "title": "加氢站日报",
- "type": "route",
- "path": "/prototypes/energy-h2-station-daily",
- "description": "起止日期+KPI钻取+占比+各站单卡;钻取页可导出xlsx"
- }
- ]
- }
-}
diff --git a/vite.config.ts b/vite.config.ts
index 21c0cc7..593a292 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,7 +1,7 @@
import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
-import { energyDevMockApi } from './src/modules/energy/hydrogen-bi-v2/dev-mock-api';
+import { energyDevMockApi } from './src/modules/energy/hydrogen/dev-mock-api';
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');