# pump **Repository Path**: jerry_ouyang/pump ## Basic Information - **Project Name**: pump - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-16 - **Last Updated**: 2026-09-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 设备定位平台(VP · Vehicle Positioning Platform) 设备定位系统管理平台后端(Spring Boot)与前端(Vue3 + TS)实现。本期完成**认证/RBAC、系统管理 CRUD、监控报警、OpenAPI、前端监控台**,以及**实时网关(JT808/809/1078)、报警引擎、AI 检测、媒体服务、对象存储**的真实可用代码实现(非桩)。各模块按 JT/T 808-2019、JT/T 809-2019、JT/T 1078 标准规范编写。 ## 工程契约(VP / BP 双端必须遵守) 以下三条是双端后端长期稳定运行的硬约束,改动任何一端都必须保持另一端同步,禁止只改一端。 1. **国密报文**:应用层采用「SM2 信封 + SM4 报文」加解密(`CryptoService`,过密评)。前端每次非文件请求随机生成 16 字节 SM4 会话密钥,用服务端 SM2 公钥加密后经请求头 `X-SM2-Key` 传输,请求/响应体以 SM4-CBC-PKCS7 加解密(随机 IV + SM3 完整性标签 `mac`)。查询参数不再明文走 URL:**GET/DELETE 由前端转 POST + `X-HTTP-Method-Override`**,后端 `RequestDecryptFilter` 还原原始方法并把信封内 JSON 参数回填 `getParameter*`,使 `@GetMapping`/`@DeleteMapping` 仍可命中。 2. **分页强制走 `PageSupport`**:所有分页查询必须经 `PageSupport.paged(...)`(或 `BaseServiceImpl.scopedPage(...)`),**禁止直接 `mapper.selectPage(...)` / `this.page(...)`**。本项目 MyBatis-Plus 发行版不含 `PaginationInnerInterceptor`,原生 `selectPage` 会静默退化为全表查询且 total 恒为 0。`PageSupport` 统一单页硬上限 500、非法 page/size 回退默认值、先 count 再追加 LIMIT。 3. **Sa-Token `active-timeout` 7200 兜底**:`application.yml` 中 `sa-token.active-timeout: 7200`,空闲 2 小时强制下线,杜绝令牌在持续操作下永不过期(此前为 -1,属静默永不下线)。生产 profile 同样收紧为 7200,不得改回 -1。 ## 技术栈 - **后端**:Spring Boot 4.1 · JDK 21 · MyBatis Plus · Sa-Token(双 Token + 权限注解)· 统一 `Result` / `PageResult` - **前端**:Vue 3.5 · TypeScript 5.7 · Vite 6 · Element Plus 2.9 · Pinia · Axios(响应拦截自动解包 `Result`) - **包名 / 坐标**:`com.newpump.vp` · `com.newpump:newpump-vp-backend` ## 目录结构 ``` vp-backend/ Spring Boot 后端(VP 设备定位平台) controller/ 认证、系统管理、监控、报警、巡检、交换、视频、统计、底图、审计、OpenAPI service/ 业务接口与实现(Service → Manager → DAO) model/ DO / DTO / VO / Query 分层 common/ 统一响应、异常、常量(PermissionConstants / MenuConstants)、工具 config/ Sa-Token、OpenApi 拦截器、CORS 等 vp-frontend/ Vue3 + TS 前端(VP 设备定位平台) # bp-backend/ + bp-frontend/ 业务管理平台(BP):后续新建,同仓按平台代号前缀平铺 src/api 请求封装(utils/request.ts,解包 Result) src/stores Pinia:user / app src/router 路由(Layout + 懒加载业务页) src/config crudConfig.ts 数据驱动系统管理页 src/views/dashboard|monitor|track|video|alarm|inspection|exchange|stats|map|audit src/views/system/GenericCrud.vue 数据驱动 CRUD 组件 src/types/model.ts 业务类型定义 docs/ 需求 / 设计 / UI 设计文档(详见 .workbuddy 记忆) ``` ## 运行 ### 后端 ```bash # 需要 JDK 21 + Maven 3.9+ cd backend mvn spring-boot:run # 默认端口 8080;Sa-Token access-token 超时 1800s(application.yml vp.token.access-timeout) ``` ### 前端 ```bash cd frontend npm install npm run dev # 开发:http://localhost:5173,/api 代理到 :8080 npm run build # 生产构建(vue-tsc 类型检查 + vite build) ``` ## 权限模型(双层 RBAC) - 系统级权限码 `system:xxx`(系统管理)与业务权限码 `xxx:view/edit/...`(监控/报警/...);`PermissionConstants.ALL` 为全集。 - `SYS_ADMIN` 角色拥有 `PermissionConstants.ALL` 全部权限,菜单/权限码静态目录构建(见 `MenuConstants.buildTree`)。 - 数据范围:组织 / 基地 / 授权车辆(角色 `dataScope` 字段)。 - 操作审计:通过 `@OperationLog` AOP 写入 `t_audit_log`(`OperationTypeEnum`)。 ## OpenAPI(对外) - 公开 `POST /v1/openapi/token`(`appKey + appSecret` → `client_token`,Redis 存 `openapi:token:{token}`=appId,TTL 7200s)。 - `OpenApiInterceptor` 校验 + 限流(`openapi:ratelimit:{appId}:{minute}`)+ 落 `t_openapi_log`。 - 业务 OpenAPI 控制器按订阅范围 `OpenApiScopeUtil.matches` 隔离(scope 空或 `*`=全部,否则车牌逗号分隔)。 - 事件订阅(Webhook,真实推送):`POST /v1/alarms/subscribe` 注册回调、`GET /v1/alarms/subscribe` 列表、`DELETE /v1/alarms/subscribe/{id}` 退订;配置落 `t_openapi_subscription`。报警(`AlarmEvent`)与摄像头巡检(`InspectionEvent`)产生时由 `OpenApiSubscribeServiceImpl` 异步推送 HTTP POST JSON(可选 HMAC-SHA256 签名:`X-NewPump-Timestamp` / `X-NewPump-Signature` 头),开关与超时见 `vp.webhook.*`。 ## 对象存储(可配置:本地 / S3) 存储为**可插拔抽象**,运行期可在「系统管理 → 对象存储」切换,即时生效(无需重启): - `StorageTemplate`(业务统一注入):按 `t_param`(category=`storage`)覆盖 `application.yml` 默认值;保存即重建策略。 - 策略实现: - `LocalStorageStrategy`:服务器本地文件系统,零依赖,适合内网/单机。 - `S3StorageStrategy`:S3 兼容(MinIO / 阿里云 OSS / 腾讯云 COS / AWS S3),走 MinIO Java SDK(`pom.xml` 已引入 `io.minio:minio:8.5.17`)。 - 配置接口:`GET/PUT /v1/storage/config`(权限 `system:storage:query` / `system:storage:edit`),SecretKey 脱敏不回显、留空表示不修改。 - 通用上传:`POST /v1/storage/upload`(权限 `system:storage:upload`)→ 返回 `key` + 可访问 `url`;本地文件经 `StorageFileController`(`/v1/storage/files/**`,登录态保护)代理,S3 返回预签名/公开地址。 - 前端:`vp-frontend/src/views/system/storage/index.vue` 提供类型切换、凭证录入与上传测试。 > 各业务模块(摄像头巡检证据、报警截图、录像索引)后续统一调用 `StorageTemplate` / `/v1/storage/upload`,不再各自硬编码存储。 ## 实时网关与媒体服务(已实现) > 各模块均按 JT/T 808-2019、JT/T 809-2019、JT/T 1078 标准规范编写,非桩实现。 ### JT/T 808 终端接入网关 - Netty TCP 服务(端口 8808,可配 `vp.jt808.*`);完整帧编解码:0x7E 分隔、0x7D 转义、XOR 校验、2011/2019 双协议版本。 - 上行全量处理:注册 0x0100 / 鉴权 0x0102 / 心跳 0x0002 / 位置上报 0x0200 / 参数应答 0x0104;平台下行 0x8100 / 0x8201 / 0x8103 / 0x8300 / 0x8500。 - 注册时自动建档 `t_terminal` 并生成鉴权码;位置上报写入 `t_location`、刷新终端在线态、写 Redis 实时位与在线集,并发布 `LocationEvent`。 ### 报警引擎(事件驱动,可平滑切换 Kafka) - `LocationEvent` → `@Async @EventListener` → 规则链(`OverspeedRule` 超速带迟滞、`FatigueRule` 连续驾驶 4h)→ 命中写 `t_alarm` 并发布 `AlarmEvent`。 - 阈值可配:`vp.alarm.overspeed-limit`(默认 80)、`vp.alarm.fatigue-hours`(默认 4)。 ### AI 视觉检测 - `AiDetectService` 可插拔:`MockAiDetectService`(本地确定性)/ `HttpAiDetectClient`(推理网关 `ai.endpoint`);`ai.provider` 切换、HTTP 不可达时自动回退 Mock。 - 巡检 `InspectionService.runAiDetect`:置信度阈值 `ai.confidence-threshold`(默认 0.6)过滤 + 24h 同类未关闭去重,写入 `t_inspection`(`detectSource=0` AI)。 ### JT/T 1078 媒体服务(ZLMediaKit) - `MediaGatewayService` 编排:经 `Jt808Downlink` 下发 1078 控制(0x9101 实时视频 / 0x9105 云台 / 0x9206 抓拍)→ 终端推流至媒体服务器 → `ZlmClient` 拉流代理 `addStreamProxy` / 截图 `getSnap` → 证据经 `StorageTemplate` 落对象存储。 - 控制器 `/v1/videos/{vehicleId}/{channels|play|ptz|snapshot|records}`;前端「视频监控」页可真实取流 / 云台 / 抓拍 / 调阅录像。 ### JT/T 809 平台交换网关(双向完整) - **作为下级平台(客户端)主动 TCP 连接上级**:`Jt809LinkManager` 完成 0x1001 登录握手、0x1003 周期心跳、0x1005/0x1007 断链处理、断线按 `reconnect-delay-seconds` 自动重连(已停用 / 手动断开不重连)。 - **作为上级平台(服务端)监听下级**:`Jt809Server` 在 `vp.jt809.server.port`(默认 8909)监听;收到下级 0x1001 登录回 0x1002 应答、0x1003 心跳回 0x1004、0x1005 断链回 0x1006;心跳超时(`heartbeat-timeout-seconds`)自动断开;按对端 GNSS 中心编号自动建档/更新下级链路(`t_exchange_link`,`role=2`)。 - 下行(向上转发):帧编解码完备(0x5B 标志、0x5A 转义、XOR 校验、22 字节报文头);`Jt809Forwarder` 监听 `LocationEvent`/`AlarmEvent` 封装 0x1202 位置交换 / 0x9204 报警交换并下发。 - 上行(接收下级):`Jt809ServerHandler` 接收 0x1202/0x1203 位置、0x9204 报警,按车牌解析车辆后写入 `t_location`(经 `LocationService.handlePeerReport`,不向上回环)与 `t_alarm`。 - 管理接口:`POST /v1/exchanges/{id}/connect`、`/disconnect`;`GET /v1/exchanges/server/status` 查询服务端监听端口、启用状态与下级在线数。 ### 运行期依赖(生产须配置) - **MySQL**:业务库(`t_*` 表)。 - **Redis**:实时位置 / 在线态 / `client_token` 缓存。 - **ZLMediaKit**:JT1078 媒体服务(`media.zlm.host` / `secret`,`media.jt1078.rtsp-base` 指向终端推流汇聚地址)。 - **AI 推理网关(可选)**:`ai.endpoint`(不配则走 Mock 检测)。 - **809 上级平台(可选)**:在「平台交换」新建链路并 `connect` 建链。 ## 桩化 / TODO(接口先行,待基础设施) | 模块 | 状态 | 说明 | |------|------|------| | 终端接入 | ✅ 已实现 | JT/T 808(Netty)注册/鉴权/心跳/位置上报/下行指令,写入 `t_location`、在线态、发布 `LocationEvent` | | 平台交换 | ✅ 已实现 | JT/T 809 主链路登录/心跳/断链 + 自动重连 + 位置/报警转发;`ExchangeLinkService.connect` 已接入真实建链 | | 视频 | ✅ 已实现 | JT/T 1078 媒体网关编排:拉流代理、云台、抓拍落存;`VideoController` 全量接真实服务 | | AI 检测 | ✅ 已实现 | `AiDetectService` 可插拔(Mock/HTTP),置信度阈值 + 24h 去重写入 `t_inspection` | | 对象存储 | ✅ 已实现 | `StorageTemplate` 本地/S3 可配、即时生效;证据截图经通用上传端点落地 | | 底图 | ✅ 已实现 | `MapConfigController` 读取天地图/高德/百度启用与默认;前端 `MapPanel` 基于 Leaflet 渲染真实底图,内置 WGS-84↔GCJ-02↔BD-09 坐标系转换(按服务商自动转换) | > 前端地图已实现为真实底图(基于 Leaflet,本地内置 `public/vendor/leaflet`,免 npm 依赖)。 > 默认天地图(WGS-84,与内部坐标一致,无需转换);未配置 key 时自动回退 OpenStreetMap,开箱即真实可用。 > 选用高德/百度需在 `.env` 配置对应 key(见下)。后端 `/v1/map/config` 仅下发服务商偏好,key 由前端环境变量提供(不暴露于接口)。 ### 底图 key 配置(`.env`) ```bash # 默认底图服务商:tianditu | amap | baidu(缺省 tianditu) VITE_MAP_PROVIDER=tianditu # 天地图 tk(WGS-84,推荐;不填则回退 OSM) VITE_TIANDITU_TK= # 高德 key(GCJ-02) VITE_AMAP_KEY= # 百度 key(BD-09,需 leaflet 百度 CRS 插件,当前回退 OSM) VITE_BAIDU_KEY= ``` > 说明:Leaflet 运行时通过 `public/vendor/leaflet/leaflet.js` 注入全局 `L`,`MapPanel.vue` 经 `utils/map.ts` 构建各服务商瓦片层与坐标转换。 > 若改用 npm 管理 Leaflet,可 `npm i leaflet @types/leaflet` 并改为 `import 'leaflet'` / `import L from 'leaflet'`(本仓库因 npm 安全删除拦截,采用 vendoring 方案)。 ## 测试 - 协议编解码往返测试:`vp-backend/src/test/java/com/newpump/vp/gateway/{jt808,jt809}/codec/*CodecTest.java`(JT808 转义/BCD/整帧编解码含 2019 与分片;JT809 转义/校验和/整帧编解码含边界字节)。 - 运行双端单测:`cd vp-backend && mvn test`、`cd bp-backend && mvn test`(需 JDK 21 + Maven 3.9+)。 - 双端一致性门禁(CI 硬门禁):`node test/tools/check-dual-consistency.mjs --gate`,已知共享(byte-identical)类若漂移即非零退出; 基线文件 `test/tools/dual-consistency-baseline.txt` 由 `--write-baseline` 生成,两端改动共享类后需同步。 ## 前端规范(.workbuddy/rules/vue-ts-spec.md) - `