refactor(stage9): 后端业务域目录形状统一

- 每个域现在都是 src/server/routes/<domain>/ 目录:
  vehicles/routes.ts(原 routes/vehicles.ts)、vehicle-heatmap/{routes,model}.ts、
  hydrogen-heatmap/{routes,model}.ts、ele/routes.ts、feedback/routes.ts。
- 命名约定:index.ts 是聚合器(挂子路由),routes.ts 是叶子路由。mileage/energy/
  scheduling 保持 index.ts 聚合,其余统一为 routes.ts。
- 纯移动与改名,未改动任何 SQL、参数顺序、路由挂载前缀或处理器逻辑。
  import 改写由一次性 codemod 完成;vehicles/repository.test.ts 读取的源码路径同步更新。
- docs/ARCHITECTURE.md 补充"后端业务域形状"表,并如实标注 ele / feedback 尚未拆出
  repository(这两个域缺 SQL 指纹测试,建议先补测试再拆)。

lint / test(139) / build 全绿,可达性 0 未引用文件。
This commit is contained in:
dsh-agent
2026-09-11 10:30:54 +08:00
parent 954d626afc
commit 795fb207cb
14 changed files with 48 additions and 33 deletions
@@ -10,8 +10,8 @@ import {
rankHydrogenStations,
serializeHydrogenStation,
type HydrogenStationRecord,
} from './hydrogen-heatmap-model.js';
import { recentDayRange } from '../../shared/date-range.js';
} from './model.js';
import { recentDayRange } from '../../../shared/date-range.js';
// 默认区间是"近 30 天"滚动窗口,注入固定时钟让断言可复现。
const NOW = new Date('2026-07-13T12:00:00');
@@ -1,4 +1,4 @@
import { recentDayRange } from '../../shared/date-range.js';
import { recentDayRange } from '../../../shared/date-range.js';
export type HydrogenHeatmapMetric = 'kg' | 'refuels' | 'vehicles';
export type HydrogenPayer = 'all' | 'lingniu' | 'customer';
@@ -1,9 +1,9 @@
import { Hono } from 'hono';
import type { RowDataPacket } from 'mysql2';
import pool from '../db/mysql.js';
import type { AuthUser } from '../auth/types.js';
import { canAccessEnergy } from '../auth/types.js';
import { recentDayRange } from '../../shared/date-range.js';
import pool from '../../db/mysql.js';
import type { AuthUser } from '../../auth/types.js';
import { canAccessEnergy } from '../../auth/types.js';
import { recentDayRange } from '../../../shared/date-range.js';
import {
buildHydrogenPoints,
filterHydrogenStationsByRadius,
@@ -14,7 +14,7 @@ import {
serializeHydrogenStation,
type HydrogenPayer,
type HydrogenStationRecord,
} from './hydrogen-heatmap-model.js';
} from './model.js';
type StationRow = RowDataPacket & HydrogenStationRecord;
+1 -1
View File
@@ -2,7 +2,7 @@ import { Hono } from 'hono';
import pool from '../../db/mysql.js';
import { fetchVehicleInfoMap } from '../mileage/vehicle-info.js';
import { fetchOneOsMileageDates } from '../mileage/oneos-api.js';
import { mapRegion } from '../vehicles.js';
import { mapRegion } from '../vehicles/routes.js';
import { filterByPermission, maskCustomerNames } from '../../auth/permissions.js';
import { classifyVehicle, generateSuggestions } from './algorithm.js';
import { fetchActiveNotificationMap, fetchRecentInterventionCount } from './notify.js';
@@ -11,8 +11,8 @@ import {
summarizeVehicleRecords,
vehicleGridPrecision,
type VehicleHeatmapRecord,
} from './vehicle-heatmap-model.js';
import { recentDayRange } from '../../shared/date-range.js';
} from './model.js';
import { recentDayRange } from '../../../shared/date-range.js';
// 默认区间是"近 30 天"滚动窗口,注入固定时钟让断言可复现。
const NOW = new Date('2026-07-13T12:00:00');
@@ -1,4 +1,4 @@
import { recentDayRange } from '../../shared/date-range.js';
import { recentDayRange } from '../../../shared/date-range.js';
export type VehicleHeatmapMetric = 'locations' | 'vehicles';
export type VehicleHeatmapRecord = {
@@ -1,7 +1,7 @@
import { Hono } from 'hono';
import pool from '../db/mysql.js';
import heatmapPool from '../db/heatmap.js';
import { getCache } from './mileage/cache.js';
import pool from '../../db/mysql.js';
import heatmapPool from '../../db/heatmap.js';
import { getCache } from '../mileage/cache.js';
import {
buildVehicleGrid,
buildVehicleRanking,
@@ -11,7 +11,7 @@ import {
summarizeVehicleRecords,
vehicleGridPrecision,
type VehicleHeatmapRecord,
} from './vehicle-heatmap-model.js';
} from './model.js';
type MetaRow = {
start_date: string;
@@ -26,7 +26,7 @@ function vehicle(id: string): Vehicle {
}
test('keeps all vehicle GET endpoints in their established order', () => {
const source = readFileSync(new URL('../vehicles.ts', import.meta.url), 'utf8');
const source = readFileSync(new URL('./routes.ts', import.meta.url), 'utf8');
const paths = Array.from(source.matchAll(/app\.get\('([^']+)'/g), (match) => match[1]);
assert.deepEqual(paths, [
@@ -7,9 +7,9 @@ import type {
BatchSummary,
BatchGroup,
InventoryTypeSummary,
} from '../types.js';
import { filterByPermission, maskCustomerNames, maskCustomerName } from '../auth/permissions.js';
import type { AuthUser } from '../auth/types.js';
} from '../../types.js';
import { filterByPermission, maskCustomerNames, maskCustomerName } from '../../auth/permissions.js';
import type { AuthUser } from '../../auth/types.js';
import type { Context } from 'hono';
import {
INVENTORY_REGIONS,
@@ -21,7 +21,7 @@ import {
mapInventoryRegion,
mapMacroRegion,
resolveCity,
} from './vehicles/model.js';
} from './model.js';
import {
compareDepartmentNames,
countByType,
@@ -29,10 +29,10 @@ import {
getStats,
listDateRange,
normalizeDateRange,
} from './vehicles/utils.js';
import { vehicleRepository, type FlowDetailRow, type WeeklyDetailType } from './vehicles/repository.js';
} from './utils.js';
import { vehicleRepository, type FlowDetailRow, type WeeklyDetailType } from './repository.js';
export { mapRegion } from './vehicles/model.js';
export { mapRegion } from './model.js';
const app = new Hono();