Files
lingniu-vehicle-ingest/docs/vehicle-data-platform-analysis.md

232 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 车辆数据中台一期现状分析与总体方案
> 结论日期2026-07-14
> 范围:只完成现状分析和方案设计,不进入 V2 功能开发或 ECS 部署。
> 代码依据:`/Users/lingniu/project/ai-coding/ln-bi`、`vehicle-data-platform`、`go/vehicle-gateway`,以及 `docs/architecture`、`docs/ops` 中的生产说明。
## 1. 结论摘要
当前数据接入链路已经具备可用的生产底座GB32960、JT808、YUTONG_MQTT 经 NATS/Kafka 分流后,分别形成 Redis 当前态、TDengine RAW/位置历史、MySQL 身份/实时/日里程投影;现有平台 BFF 也已提供车辆、实时位置、轨迹点、RAW、里程、质量和运维健康等只读接口。
但现有前端不是可直接扩展的一期产品:生产入口加载的是约 6000 行的 `PrototypeApp.tsx`,仍混有 mock 数据和“接口缺失时展示能力边界”的原型逻辑;另一个模块化 `App.tsx` 并非当前入口。现有地图每次最多创建 500 个普通 Marker没有聚合、MassMarks/Canvas 图层和视口查询,无法满足 1 万辆级监控。所谓告警接口实际上是质量问题接口的别名,没有规则、事件、处理记录和通知持久化。
建议丢弃现有原型页面的产品实现,但保留经验证的数据适配、领域工具、测试、运行时配置和部署脚手架,建立独立 V2。前端沿用 React + TypeScript + Vite吸收 `ln-bi` 的视觉语言、壳层、鉴权思想和基础组件,但采用正式路由、查询缓存、虚拟表格和独立地图 SDK 层。后端保留现有接入链路,通过平台 BFF 和新增的告警/导出 worker 补齐业务能力,不让浏览器直接访问 Redis、TDengine 或 MySQL。
## 2. 当前前端技术栈与目录
### 2.1 `ln-bi` 参考项目
| 项目 | 当前实现 | 评价 |
| --- | --- | --- |
| 框架 | React 19、React DOM 19、TypeScript 5.8、Vite 6.2 | 可作为 V2 目标栈参考;不建议仅为对齐版本立刻升级已有平台依赖 |
| 样式 | Tailwind CSS 4、少量 CSS 变量 | 视觉语言清晰,但业务组件 class 较分散,需要提炼 token 和组件配方 |
| 图标/动效 | lucide-react、Motion | 可复用设计语言;监控页面动效应克制并支持 reduced motion |
| 图表 | Recharts 3.8 | 适合常规 BI百万点、多 Y 轴时序更推荐现平台已有 ECharts 5 |
| 地图 | `@amap/amap-jsapi-loader` + AMap JS API 2.0 | 加载和实例生命周期可借鉴;目前只是热力图业务组件,不是通用地图 SDK |
| API | 原生 `fetch` + JWT 注入 | 可借鉴鉴权流程;错误类型、超时、重试、取消、缓存仍不足 |
| 服务端 | Hono、MySQL/Postgres、JWT、XLSX | 属于 `ln-bi` 自身 BFF不应直接搬入车辆接入 Go 数据面 |
| 路由 | pathname + hash + `replaceState` 手写 | 适合少量模块,不适合可分享查询、详情层级和权限路由 |
| 状态 | React 本地状态/Context | 未使用全局状态库或服务端查询缓存 |
主要目录:
```text
ln-bi/src/
├── App.tsx # 模块注册、权限门禁、懒加载
├── auth/ # jumpToken -> JWT、fetch token 注入
├── components/
│ ├── Shell.tsx # 桌面侧栏、移动底栏、模块切换、水印
│ ├── SearchSelect.tsx
│ ├── MultiSearchSelect.tsx
│ └── ui/surface.tsx # PageFrame、SurfaceCard、MetricTile、状态组件
├── modules/
│ ├── vehicle-heatmap/ # AMap 热力图和筛选/详情面板
│ ├── hydrogen-heatmap/
│ ├── mileage/ # 表格、详情弹窗、XLSX 导出
│ └── ...
├── server/ # Hono BFF、认证、DB 查询
├── shared/auth/roles.ts # 角色判断
└── index.css # Tailwind、主题变量、地图控件样式
```
### 2.2 当前车辆平台前端
目录为 `vehicle-data-platform/apps/web`,使用 React 18.3、TypeScript 5.7、Vite 6、Semi UI 2.71、ECharts 5.6。当前入口 `src/main.tsx` 加载 `PrototypeApp`,不是 `src/App.tsx`
```text
vehicle-data-platform/apps/web/src/
├── main.tsx # 当前生产入口 -> PrototypeApp
├── PrototypeApp.tsx # 大型原型单体,真实接口与 mock 逻辑混合
├── App.tsx # 未作为入口的模块化旧实现
├── api/ # 统一响应信封、类型和调用方法
├── components/ # VehicleMap、状态标签、空状态等
├── config/ # API/高德运行时配置
├── domain/ # 路由、导出、车辆查询等纯函数
├── integrations/amap.ts # AMap loader、坐标校验、逆地理编码
├── layout/AppShell.tsx
├── pages/ # 旧模块化页面
├── prototype/ # mock、真实数据适配、view model、字段映射
└── styles/ # token、全局样式、原型样式
```
V2 的原则是“页面重建、能力甄别复用”:不复制 `PrototypeApp.tsx``prototype.css`;保留可独立测试的 `api``domain``integrations`、真实数据归一化逻辑及其测试,再按新接口契约重构。
## 3. 可复用能力清单
| 能力 | 来源 | 复用决策 | 说明 |
| --- | --- | --- | --- |
| 80px 深色侧栏、顶部面包屑、水印、移动底栏 | `ln-bi/components/Shell.tsx` | 设计复用、代码重构 | V2 桌面优先,应改为正式路由和可折叠侧栏 |
| PageFrame、SurfaceCard、MetricTile、SegmentedNav | `ln-bi/components/ui/surface.tsx` | 可迁移后组件化 | 统一 token、尺寸和可访问性后复用 |
| SearchSelect、MultiSearchSelect | `ln-bi/components` | 交互参考 | 当前仅接收字符串数组缺少远程搜索、虚拟列表、label/value 和键盘完整性 |
| 加载、空、错误状态 | 两项目 | 合并重构 | 建立统一 `AsyncState`,禁止页面各自拼接 |
| JWT/jumpToken 门禁、角色判断 | `ln-bi/auth``shared/auth` | 复用认证协议思想 | token 仍应保存在 session权限改为路由/操作级声明,后端必须二次校验 |
| AMap loader、实例销毁、运行时密钥 | 两项目 | 合并为通用 SDK | 统一 loader promise、插件注册、安全代理和错误状态 |
| 热力图数据归一化 | `ln-bi/vehicle-heatmap` | 可复用算法 | `log1p/sqrt` 强度变换适合密度层,不等于车辆状态点图层 |
| 表格/详情弹窗/XLSX | `ln-bi/mileage` | 交互与导出格式参考 | 一期大数据导出必须后端异步,不能沿用浏览器全量 XLSX |
| ECharts | 当前车辆平台 | 保留 | 更适合多 Y 轴、dataZoom、断点、阶梯线和大数据采样 |
| `api/client.ts` 响应信封和 traceId | 当前车辆平台 | 扩展复用 | 增加鉴权、AbortSignal、超时、错误码、幂等键和查询缓存 |
| 车辆 lookup、字段归一化、CSV 纯函数及测试 | 当前车辆平台 | 审核后复用 | 去掉 mock fallback统一到 V2 DTO/领域模型 |
| Semi UI 页面组件 | 当前车辆平台 | 暂不作为 V2 默认 | 与 `ln-bi` Tailwind 视觉体系并存会形成双设计系统V2 启动前只选一套基础组件策略 |
不存在可直接复用的“通用图表组件”或“通用高性能表格组件”。`ln-bi` 的 Recharts 与页面耦合,当前平台的 ECharts 也需要建立 `TimeSeriesChart`、轴/单位/空值策略和采样契约;表格需新增服务端分页、列配置、固定列和虚拟滚动封装。
## 4. 高德地图当前封装方式
### 4.1 `ln-bi`
`AmapHeatmapCanvas.tsx` 动态导入 `@amap/amap-jsapi-loader`,写入 `_AMapSecurityConfig.securityJsCode`,加载 AMap 2.0 的 HeatMap、ToolBar、Scale 插件;创建白色地图和 HeatMap点击地图回传经纬度数据变化时调用 `setDataSet`,焦点变化时计算 bounds卸载时销毁实例。
优点是 loader 官方、生命周期完整、地图与侧面板分屏清楚。限制是车辆和加氢模块各有近似实现,密钥直接下发前端,未封装 Marker/聚合/信息窗/轨迹/播放,也没有实例共享和视口事件节流。
### 4.2 当前车辆平台
`integrations/amap.ts` 自行加载 `https://webapi.amap.com/loader.js`,按插件集合缓存 Promise支持 Scale、Geocoder、坐标合法性检查、URI Marker 链接和浏览器逆地理编码;`appConfig.ts``window.__LINGNIU_APP_CONFIG__` 或 Vite 环境变量读取 Web JS key、安全代码/代理和 API base URL。
`VehicleMap.tsx` 在组件内创建 Map、Marker、Polyline重绘时清除 overlay最多截取 500 个点,并在未配置地图时提供坐标预览。它适合验证和小规模页面,不适合一期:每点 HTML button、没有聚合、状态图层、InfoWindow 管理、车辆朝向、轨迹抽稀/播放或视口查询。
### 4.3 V2 建议封装
建立 `features/map-sdk`,分为:
- `AMapProvider/useAMap`:唯一 loader、插件按需加载、实例注册、resize/destroy。
- `BaseMap`:纯地图容器,只接收中心、缩放、样式和事件。
- `VehiclePointLayer`:小规模用 Marker规模化优先 MarkerCluster/LabelsLayer/MassMarks 或 Canvas/WebGL 能力;详情卡只保留一个 InfoWindow。
- `TrackLayer`Polyline、起终点、停车/告警节点和移动标记;播放状态在业务 hook不绑入地图实例。
- `HeatmapLayer``GeocoderService``MapControls`:独立能力。
- 视口查询使用 `bounds + zoom + filterHash`;移动结束后防抖请求服务器聚合结果,前端不一次拉取全量 1 万点 DOM。
高德 Web JS key 可由运行时配置下发,但安全密钥优先使用服务端安全代理;逆地理编码优先走现有 `/api/map/reverse-geocode`,避免泄露 REST key并便于限流/缓存。
## 5. 当前车辆相关接口
现有平台 BFF 的有效能力如下;详细缺口见 `vehicle-data-platform-api-gap.md`
| 领域 | 接口 | 当前用途 |
| --- | --- | --- |
| 总览 | `GET /api/dashboard/summary` | 在线、今日活跃、帧数、问题数、协议/服务/链路统计 |
| 车辆 | `GET /api/vehicles``/api/vehicles/resolve``/api/vehicles/coverage``/summary` | 车辆列表、VIN/车牌/手机号解析、来源覆盖 |
| 单车 | `GET /api/vehicle-service``/summary``/overview``POST /overviews` | 聚合身份、实时、历史、RAW、里程、质量证据 |
| 实时 | `GET /api/realtime/vehicles``/api/realtime/locations` | VIN 聚合实时状态和每协议最新位置 |
| 历史 | `GET /api/history/locations``GET/POST /api/history/raw-frames` | TDengine 位置点和 RAW 证据分页 |
| 里程 | `GET /api/mileage/summary``/api/mileage/daily` | MySQL 日里程统计 |
| 在线 | `GET /api/statistics/online-summary``/online-vehicles` | 当前固定口径的在线统计和车辆状态 |
| 数据质量 | `GET /api/quality/summary``/issues``/notification-plan` | 由当前数据推导的质量信号和静态通知方案 |
| 告警兼容 | `GET /api/alert-events/summary``/alert-events``/notification-plan` | 实际是上述质量接口别名,不是业务告警事件 |
| 地图 | `GET /api/map/reverse-geocode` | 服务端高德逆地理编码 |
| 运维 | `GET /api/ops/health``/source-readiness` | 数据源可写性、Kafka lag、连接/Redis key、发布版本和接入准备度 |
同时Go `realtime-api` 还提供面向底层表的查询接口和 OpenAPI但 V2 浏览器应统一访问平台 BFF避免前端绑定多个端口与底层存储模型。
## 6. 数据职责概览
- TDengine `lingniu_vehicle_ts``raw_frames` 是原始接收与扁平解析证据,`raw_frame_payload_chunks` 保存超长 payload`vehicle_locations` 保存 VIN 级位置、速度、方向、告警标志和总里程历史。它不是车辆档案或告警业务库。
- Redis DB 50`vehicle:latest:*``vehicle:realtime-raw:*``vehicle:rt-kv:*``vehicle:online:*``vehicle:protocols:*``vehicle:last_seen` 提供可过期、可重建的当前态。它不能作为历史、告警或导出任务事实源。
- MySQL `lingniu_vehicle_data`:保存 `vehicle`、多标识映射、JT808 注册鉴权、每协议实时快照/位置、来源配置和日里程事实/结果。现有 `vehicle` 档案很轻,只含 VIN、车牌、OEM、启用状态尚不足以支撑车型、公司、车辆类型等产品字段。
统一模型及新增模型详见 `vehicle-data-platform-data-model.md`
## 7. 一期缺口结论
必须新增或升级的核心能力:
1. 完整车辆档案、组织/车型/协议/接入厂家字典与首次接入事实。
2. 地图聚合查询、组合筛选、状态统计和可配置在线口径。
3. 包含方向、SOC、告警标志、停车点、异常点过滤和抽稀元数据的轨迹接口。
4. 动态指标目录,以及多车、多指标、聚合/抽稀、分页的通用时序查询。
5. MySQL 持久化告警规则、告警事件、处理记录、站内通知和告警计算 worker。
6. MySQL 异步导出任务、对象/本地文件存储、worker、进度与下载授权。
7. 接入状态字段:首次/最近上报、事件时间与接收时间延迟、最近消息类型、最近错误、动态在线阈值。
8. 真正的认证、菜单/操作权限审计;现车辆平台 BFF 尚未呈现完整权限体系。
## 8. 推荐一期路由与菜单
```text
/
├── /monitor 全局监控(默认首页)
├── /vehicles 车辆查询
│ └── /vehicles/:vin 单车数字档案
├── /tracks 轨迹查询与回放
├── /history 历史数据分析
│ └── /history/exports 导出任务
├── /alerts
│ ├── /alerts/events 告警事件
│ ├── /alerts/rules 告警规则
│ └── /alerts/inbox 站内通知
├── /access 车辆接入状态
└── /operations 运维质量(管理员)
```
侧栏一级菜单保持 6 个业务入口:全局监控、车辆中心、轨迹回放、历史分析、告警中心、接入管理;导出任务挂在历史分析二级菜单,运维质量按权限置底。详情、告警、轨迹之间用带 `returnTo` 的上下文跳转,查询条件同步 URL浏览器返回可恢复筛选、时间和选中车辆。
## 9. 推荐前后端整体架构
```mermaid
flowchart LR
UI["V2 React Web"] --> BFF["Platform API / BFF"]
BFF --> RT["Redis 当前态"]
BFF --> TS["TDengine 时序与 RAW"]
BFF --> DB["MySQL 业务事实"]
BFF --> MAP["高德 REST / 安全代理"]
ING["Gateway + NATS + Kafka Writers"] --> RT
ING --> TS
ING --> DB
K["Kafka fields/raw"] --> AW["Alert evaluator"]
AW --> DB
BFF --> EQ["Export queue"]
EQ --> EW["Export worker"]
EW --> TS
EW --> DB
EW --> FS["文件/对象存储"]
```
前端按 `app/router``shared``entities/vehicle``features``pages` 分层。服务端状态使用查询缓存库统一取消、去重、失效和后台刷新;少量 UI 状态用 React Context/局部 store。地图、图表、表格均只接收领域 DTO不直接处理协议字段名。
平台 BFF 负责统一鉴权、参数校验、分页、在线状态计算、跨源聚合、字段目录、限流、traceId 和 DTO禁止让前端分别拼 Redis/MySQL/TDengine。已有接入 writer 保持不变,新告警 worker 消费可重放 fields/raw 流,异步导出 worker 读取 TDengine/MySQL 并把任务状态写 MySQL。
## 10. 运维与最终 ECS 部署边界
已查阅 `docs/ops/vehicle-ingest-runbook.md``docs/ops/go-vehicle-ingest-memory.md``docs/architecture/production-data-plane-inventory.md``vehicle-data-platform/docs/deployment.md`。当前接入数据面采用 systemd 裸机 release 目录与 `current` 软链,平台使用 `/opt/lingniu-vehicle-platform/{releases,current,env}`HTTP 端口 20300部署后应验证 `/api/ops/health`、车辆查询和运行时配置。
V2 最终仍部署到当前 ECS但不应在分析阶段执行。实施完成后的发布顺序应是数据库向前兼容迁移 -> 新 worker默认禁用规则-> BFF -> 静态 Web -> 小流量健康验证 -> 启用告警/导出 worker。每一步保留旧 release 和可回滚软链;密钥只进 ECS 环境文件,不进仓库或构建产物。完整发布验收纳入路线图最后阶段。
## 11. 风险与待确认事项
| 优先级 | 风险/待确认 | 影响与建议 |
| --- | --- | --- |
| P0 | `vehicle` 档案缺车型、类型、公司、接入厂家等 | 先确定主数据来源和维护责任,不要从实时 JSON 猜档案 |
| P0 | 现有告警接口名与真实语义不符 | V2 使用 `/api/v2/alerts/*` 新契约,旧别名标记 deprecated避免误把质量信号当已处理事件 |
| P0 | 动态指标没有目录、单位、类型和协议映射 | 先落指标元数据;否则图表、规则和导出会各自硬编码 |
| P0 | 用户/角色来源尚未确认 | 明确复用 `ln-bi` jumpToken/JWT还是接入统一 SSO后端权限不可只靠菜单隐藏 |
| P1 | 在线阈值是全局、协议级还是车辆级 | 建议全局默认 + 协议覆盖;一期暂不做单车覆盖 |
| P1 | 轨迹异常过滤可能隐藏原始证据 | API 同时返回 raw/filtered 计数和算法版本,允许关闭过滤 |
| P1 | TDengine `raw_frames.parsed_json` 是动态字段唯一历史来源 | 通用指标查询先从 JSON 提取会有成本;高频稳定指标应按使用量逐步物化,而非一期全列化 |
| P1 | 单 ECS 同时承担接入、查询、告警和导出 | 导出/重查询必须有并发、时间范围、行数和资源配额;压测后再定 worker 并发 |
| P1 | 地图 1 万辆的插件/授权与浏览器性能 | 先完成 1k/10k 基准,确定 MarkerCluster、MassMarks 或 Canvas 方案和高德配额 |
| P1 | 站内通知实时方式 | 一期可 SSE + 轮询降级;若 ECS 反代不适合长连接,先使用增量轮询 |
| P2 | Semi UI 与 Tailwind 双设计系统 | V2 启动前确认唯一基础组件策略;建议 Tailwind token + 无样式/轻量基础组件ECharts 保留 |
| P2 | 导出文件存储位置与保留期 | 确认 OSS 或 ECS 本地盘;推荐 OSS/兼容对象存储,任务和文件设过期清理策略 |
## 12. 本阶段完成定义
本阶段仅交付本分析、路线图、API 缺口和数据模型四份文档。V2 代码、数据库迁移、告警/导出 worker、ECS 发布均须在确认 P0 项后按路线图进入下一阶段。