docs: 添加里程管理模块设计文档
覆盖架构、API 端点、前端组件、数据映射, 1:1 复刻原型的实时监控和统计报表。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
242
docs/superpowers/specs/2026-04-01-mileage-module-design.md
Normal file
242
docs/superpowers/specs/2026-04-01-mileage-module-design.md
Normal file
@@ -0,0 +1,242 @@
|
||||
# 里程管理模块设计
|
||||
|
||||
## 背景
|
||||
|
||||
在模块化重构的基础上,实现里程管理 BI 模块,1:1 复刻原型 `/Users/kkfluous/Projects/ai-coding/ln-yuanxing/lnoneos-1` 中的里程管理部分。包含 3 个子 Tab:实时监控、统计报表、每日汇报(占位)。
|
||||
|
||||
## 目标
|
||||
|
||||
- 1:1 复刻原型 UI(样式、动画、交互细节完全一致)
|
||||
- 接入真实数据源(两个数据库)
|
||||
- 每日汇报 Tab 暂做占位
|
||||
|
||||
## 数据源
|
||||
|
||||
### 数据库 1:lingniu_prod(已有连接)
|
||||
|
||||
- `tab_mileage_assessment_target` — 5 个考核项目定义(目标名称、车辆数、年考核里程、考核年限等)
|
||||
- `tab_mileage_assessment_vehicle` — 492 辆考核车辆(今日里程、累计里程、完成率、达标状态等)
|
||||
- `tab_truck` → `tab_truck_status_info` → `tab_contract` → `tab_customer` / `tab_user` → `tab_department` — 车辆关联客户名、部门、经理
|
||||
|
||||
### 数据库 2:hydrogen_energy(新增连接)
|
||||
|
||||
- 连接信息:`101.133.130.65:3306`,用户 `bi_reader_02`,密码 `bi_reader_02_Pass`,库名 `hydrogen_energy`
|
||||
- `v_vehicle_daily_stats` — 1004 辆车的每日里程明细(plate, vin, stat_date, daily_km, total_km, day_hydrogen, daily_run_secs, source)
|
||||
|
||||
## 架构
|
||||
|
||||
### 后端
|
||||
|
||||
新增 `src/server/mileage-db.ts` — hydrogen_energy 数据库连接池。
|
||||
新增 `src/server/routes/mileage.ts` — 里程管理 API 路由。
|
||||
修改 `src/server/index.ts` — 注册新路由 `/api/mileage`。
|
||||
|
||||
### 前端
|
||||
|
||||
```
|
||||
src/modules/mileage/
|
||||
├── MileageModule.tsx # 主组件:3个子Tab切换(实时监控/统计报表/每日汇报)
|
||||
├── MonitoringView.tsx # 实时监控视图
|
||||
├── StatisticsView.tsx # 统计报表视图
|
||||
├── DailyReportView.tsx # 每日汇报(占位)
|
||||
├── api.ts # API 客户端
|
||||
└── types.ts # 类型定义
|
||||
```
|
||||
|
||||
### 数据流
|
||||
|
||||
```
|
||||
前端 MileageModule → fetch /api/mileage/*
|
||||
↓
|
||||
后端 mileage.ts 路由
|
||||
├── lingniu_prod 池:考核目标/车辆、车辆关联信息(客户/部门/经理)
|
||||
└── hydrogen_energy 池:v_vehicle_daily_stats(日里程/趋势)
|
||||
↓ 内存合并
|
||||
前端渲染(Recharts 图表 + 列表)
|
||||
```
|
||||
|
||||
## API 端点
|
||||
|
||||
### `GET /api/mileage/monitoring`
|
||||
|
||||
实时监控数据:全部 1004 辆车的今日里程 + 关联信息。
|
||||
|
||||
**查询逻辑:**
|
||||
1. 从 `v_vehicle_daily_stats` 取最新日期的所有车辆数据(plate, daily_km, total_km, source)
|
||||
2. 从 `lingniu_prod` 取车辆关联信息(客户名、部门、经理),使用现有的 `MAIN_SQL` 关联链
|
||||
3. 内存按 plate 合并
|
||||
|
||||
**返回:**
|
||||
```ts
|
||||
{
|
||||
vehicles: Array<{
|
||||
plate: string;
|
||||
vin: string;
|
||||
dailyKm: number;
|
||||
totalKm: number | null;
|
||||
source: string; // TBOX / G7S / NONE
|
||||
isOnline: boolean; // source !== 'NONE' && dailyKm > 0
|
||||
isDataSynced: boolean; // source !== 'NONE'
|
||||
customer: string | null;
|
||||
department: string | null;
|
||||
manager: string | null;
|
||||
}>;
|
||||
updatedAt: string;
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /api/mileage/targets`
|
||||
|
||||
考核项目列表 + 每个项目的汇总统计。
|
||||
|
||||
**查询逻辑:**
|
||||
1. 从 `tab_mileage_assessment_target` 取全部未删除项目
|
||||
2. 从 `tab_mileage_assessment_vehicle` 按 target_id 聚合统计
|
||||
|
||||
**返回:**
|
||||
```ts
|
||||
Array<{
|
||||
id: number;
|
||||
targetName: string;
|
||||
vehicleCount: number;
|
||||
totalMileagePerVehicle: number;
|
||||
annualMileagePerVehicle: number;
|
||||
assessmentYears: number;
|
||||
period: string; // "YYYY-MM-DD ~ YYYY-MM-DD"
|
||||
todayTotal: number; // SUM(today_mileage)
|
||||
cumulativeTotal: number; // SUM(current_mileage)
|
||||
avgCompletion: number; // AVG(completion_rate) * 100
|
||||
qualifiedCount: number; // SUM(is_qualified)
|
||||
yearQualifiedCount: number; // SUM(current_year_is_qualified)
|
||||
halfQualifiedCount: number; // completion_rate >= 0.5 的车辆数
|
||||
currentYearTarget: number; // SUM(current_year_mileage_task)
|
||||
currentYearCompleted: number; // SUM(current_year_mileage)
|
||||
remaining: number; // currentYearTarget - currentYearCompleted
|
||||
daysLeft: number; // current_year_assessment_end_date - today
|
||||
dailyTarget: number; // remaining / daysLeft
|
||||
}>
|
||||
```
|
||||
|
||||
### `GET /api/mileage/target/:id/vehicles`
|
||||
|
||||
某考核项目的车辆明细列表。
|
||||
|
||||
**查询逻辑:**
|
||||
从 `tab_mileage_assessment_vehicle` WHERE target_id = :id AND is_deleted = 0
|
||||
|
||||
**返回:**
|
||||
```ts
|
||||
Array<{
|
||||
plateNumber: string;
|
||||
todayMileage: number;
|
||||
totalMileage: number;
|
||||
completionRate: number;
|
||||
isQualified: boolean;
|
||||
currentYearIsQualified: boolean;
|
||||
dailyRequiredMileage: number;
|
||||
}>
|
||||
```
|
||||
|
||||
### `GET /api/mileage/trend?targetId=...&days=7`
|
||||
|
||||
7天里程趋势,按考核项目筛选。
|
||||
|
||||
**查询逻辑:**
|
||||
1. 若有 targetId:从 `tab_mileage_assessment_vehicle` 取该项目的所有 plate_number
|
||||
2. 从 `v_vehicle_daily_stats` WHERE plate IN (...) AND stat_date >= (today - days) GROUP BY stat_date
|
||||
|
||||
**返回:**
|
||||
```ts
|
||||
Array<{
|
||||
date: string; // "MM-DD"
|
||||
mileage: number; // SUM(daily_km)
|
||||
}>
|
||||
```
|
||||
|
||||
## 前端组件设计
|
||||
|
||||
### MileageModule.tsx
|
||||
|
||||
主组件,管理子 Tab 切换(monitoring / statistics / report),包含:
|
||||
- 子导航栏(实时监控/统计报表/每日汇报),带 motion layoutId 动画下划线
|
||||
- 条件渲染对应 View 组件
|
||||
|
||||
### MonitoringView.tsx
|
||||
|
||||
1:1 复刻原型实时监控视图。
|
||||
|
||||
**状态:**
|
||||
- activeSubTab 由父组件管理
|
||||
- searchTerm, filterDept, filterPlate, filterProject, filterEntity, filterRegionCode, filterYear, filterDate, filterDateRange, filterMileageRange
|
||||
- sortBy ('today' | 'total'), sortOrder ('asc' | 'desc')
|
||||
- isFilterOpen, isFullscreen
|
||||
|
||||
**UI 结构:**
|
||||
1. 看板头部(标题 + 全屏按钮 + 排序切换)
|
||||
2. 快捷筛选栏(3 个 SearchableSelect + 高级筛选图标)
|
||||
3. 可展开高级筛选面板
|
||||
4. KPI 卡片网格(4列:总里程深色卡、平均单车、监控台数)
|
||||
5. 车辆详情清单(motion.div 列表)
|
||||
6. 全屏叠加层(AnimatePresence)
|
||||
|
||||
**SearchableSelect 组件:** 在 MonitoringView 内部定义(原型中的实现与公共 SearchSelect 不同,它使用 motion 动画、"无限制"默认选项、不同样式)。
|
||||
|
||||
### StatisticsView.tsx
|
||||
|
||||
1:1 复刻原型统计报表视图。
|
||||
|
||||
**状态:**
|
||||
- selectedProject, chartType ('bar' | 'line' | 'area')
|
||||
- isTableFullscreen, expandedModel, viewAllModel, viewAllSearch, viewAllSort
|
||||
|
||||
**UI 结构:**
|
||||
1. 项目选择器(横向滚动按钮组)
|
||||
2. 左侧:7天趋势图(Recharts BarChart/LineChart/AreaChart 切换)+ landscape KPI 卡片
|
||||
3. 右侧:车型考核里程汇总卡片列表(可展开详情 + 车辆明细前5台)
|
||||
4. 全屏表格叠加层(15列明细表)
|
||||
5. 查看全部侧滑面板(搜索 + 排序 + 车辆列表)
|
||||
|
||||
### DailyReportView.tsx
|
||||
|
||||
占位组件,显示"每日汇报 - 开发中"。
|
||||
|
||||
## 数据映射
|
||||
|
||||
### 实时监控
|
||||
|
||||
| UI 字段 | 数据来源 |
|
||||
|---------|---------|
|
||||
| 车牌号 | `v_vehicle_daily_stats.plate` |
|
||||
| 今日里程 | `daily_km`(最新日期) |
|
||||
| 累计里程 | `total_km`(最近非空值,用用户提供的变量填充 SQL) |
|
||||
| 在线状态 | `source !== 'NONE' && daily_km > 0` |
|
||||
| 数据同步 | `source !== 'NONE'` |
|
||||
| 客户名 | `lingniu_prod`: tab_truck → tab_truck_status_info → tab_contract → tab_customer.customer_name |
|
||||
| 部门 | `lingniu_prod`: → tab_user → tab_department.dep_name |
|
||||
|
||||
### 统计报表
|
||||
|
||||
| UI 字段 | 数据来源 |
|
||||
|---------|---------|
|
||||
| 项目列表 | `tab_mileage_assessment_target`(target_name, vehicle_count 等) |
|
||||
| 今日总里程 | `SUM(tab_mileage_assessment_vehicle.today_mileage)` by target_id |
|
||||
| 累计总里程 | `SUM(current_mileage)` by target_id |
|
||||
| 平均完成率 | `AVG(completion_rate) * 100` by target_id |
|
||||
| 达标车辆数 | `SUM(current_year_is_qualified)` by target_id |
|
||||
| 50%达标数 | `COUNT(completion_rate >= 0.5)` by target_id |
|
||||
| 考核区间 | `default_start_date ~ default_end_date` |
|
||||
| 年考核任务/辆 | `annual_mileage_per_vehicle` |
|
||||
| 本年需完成 | `SUM(current_year_mileage_task)` |
|
||||
| 已完成 | `SUM(current_year_mileage)` |
|
||||
| 未完成总数 | 本年需完成 - 已完成 |
|
||||
| 剩余天数 | `current_year_assessment_end_date - today`(取 vehicle 中的值) |
|
||||
| 日均需完成 | 未完成 / 剩余天数 |
|
||||
| 7天趋势 | `v_vehicle_daily_stats` 按项目车牌过滤聚合 |
|
||||
| 车辆明细 | `tab_mileage_assessment_vehicle` 的 plate_number, today_mileage, total_mileage 等 |
|
||||
|
||||
## 不在范围内
|
||||
|
||||
- 每日汇报 Tab 具体实现(占位)
|
||||
- landscape 适配(原型中有 landscape: 前缀样式,照搬即可但不做额外适配工作)
|
||||
- 后端缓存
|
||||
- 新增依赖
|
||||
Reference in New Issue
Block a user