# 指挥中心接口文档(commandCenter) > 基于 `feat-dashboard-lianjd` 分支对比 `develop` 的新增接口整理,模块 `xp-robotaxi-admin-boot`。 > 给前端的接口分两部分:**REST**(4 个 GET 接口) + **Socket.IO**(实时推送)。 --- ## 一、基础信息 | 项 | 值 | | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | 后端模块 | `xp-robotaxi-admin-boot` | | 网关前缀 | 管理后台域名 + `/api/v1/commandCenter`(与 cockpit 同套 SSO 鉴权) | | 鉴权方式 | 管理后台 SSO Token(`userType=system`),由网关 `AuthFilter` 校验后注入 Header;REST 通过 `@RequiresPermissions("commandCenter:view")` 二次校验 | | 统一响应包装 | `R = { code: number, msg: string, data: T }`,`code=200` 表示成功 | --- ## 二、REST 接口 ### 2.1 查询单车详情 - **路径**:`GET /api/v1/commandCenter/vehicle/detail` - **权限**:`commandCenter:view` - **入参**(Query): | 字段 | 类型 | 必填 | 说明 | | ----------- | ------ | ---- | ------- | | `vehicleId` | `Long` | 是 | 车辆 ID | - **返回**:`R` — 见 [4.1](#41-commandcentervehicledetailvo) - **示例**: ```http GET /api/v1/commandCenter/vehicle/detail?vehicleId=10086 ``` ```json { "code": 200, "msg": "操作成功", "data": { "vehicleId": 10086, "vin": "LXP****", "plateNumber": "粤B-XXXXX", "monitorGroup": "HAS_ORDER", "monitorStatus": "接驾中", "stateCode": "PICK_UP", "currentElectricity": 76, "todayCompletedOrders": 12, "routeInfo": { "startLon": 113.93, "startLat": 22.53, "endLon": 113.95, "endLat": 22.55, "startAddress": "XX 大厦", "endAddress": "XX 公园", "eta": 480 }, "currentLon": 113.94, "currentLat": 22.54 } } ``` --- ### 2.2 查询城市电子围栏列表 - **路径**:`GET /api/v1/commandCenter/fences` - **权限**:`commandCenter:view` - **入参**(Query): | 字段 | 类型 | 必填 | 说明 | | ---------- | -------- | ---- | -------------------------------------------- | | `cityCode` | `String` | 是 | 城市编码(与 `xp_open_city.city_code` 对应) | - **返回**:`R>` — 见 [4.2](#42-commandcenterfencevo) ```http GET /api/v1/commandCenter/fences?cityCode=440300 ``` --- ### 2.3 查询城市场站列表 - **路径**:`GET /api/v1/commandCenter/stations` - **权限**:`commandCenter:view` - **入参**(Query): | 字段 | 类型 | 必填 | 说明 | | ---------- | -------- | ---- | -------- | | `cityCode` | `String` | 是 | 城市编码 | - **返回**:`R>` — 见 [4.3](#43-xpstation场站精简) --- ### 2.4 查询已开通城市列表 - **路径**:`GET /api/v1/commandCenter/regions` - **权限**:`commandCenter:view` - **入参**:无 - **返回**:`R>` — 见 [4.4](#44-xpopencity开通城市) ```http GET /api/v1/commandCenter/regions ``` --- ## 三、Socket.IO 接口 ### 3.1 连接信息 | 项 | 值 | | ------------ | ----------------------------------------------- | | URL | `wss://<管理后台域名>/ws`(或 `ws://` for dev) | | Namespace | `/commandCenter` | | 协议 | Socket.IO v4(netty-socketio 2.0.11 服务端) | | 默认命名空间 | **显式拒连**,必须使用 `/commandCenter` | | 心跳 | 服务端默认 `pingInterval=25s, pingTimeout=60s` | 前端示例(socket.io-client v4): ```js import { io } from "socket.io-client"; const socket = io("/commandCenter", { path: "/ws", transports: ["websocket"], }); socket.on("connect", () => { socket.emit("auth", { token: getSsoToken() }); }); ``` --- ### 3.2 客户端 → 服务端事件 #### `auth` — 鉴权(连接后**必须**第一时间发送) 入参:`CommandCenterAuthDto` | 字段 | 类型 | 必填 | 说明 | | ------- | -------- | ---- | -------------------------------- | | `token` | `String` | 是 | 管理后台 SSO Token(同 REST 用) | 服务端会用 token 解析出运维登录用户,要求权限里包含 `commandCenter:view`,否则下发 `auth_failed` 并断开。 --- #### `subscribe` — 订阅城市/围栏 入参:`CommandCenterSubscribeDto` | 字段 | 类型 | 必填 | 说明 | | -------------- | -------- | ---- | -------------------------------------------- | | `cityCode` | `String` | 是 | 城市编码,加入房间 `city_{cityCode}` | | `electronicId` | `Long` | 否 | 围栏 ID,传则同时加入 `fence_{electronicId}` | **前置条件**:必须先收到 `auth_success` 后再调用,否则服务端回 `auth_failed`。 --- #### `unsubscribe` — 取消订阅 入参同 `subscribe`。**注意**:切换城市时前端必须先 `unsubscribe` 旧城市,再 `subscribe` 新城市,否则会收到多城市数据。 --- ### 3.3 服务端 → 客户端事件 | 事件名 | 触发时机 | 推送频率 | 负载类型 | | ----------------- | ------------------------------------------ | ------------------------------- | ------------------------------------------------------- | | `auth_success` | `auth` 通过后立即推送一次 | 一次 | `{ userId: string }` | | `auth_failed` | token 为空 / 鉴权失败 / 未鉴权就 subscribe | 一次(随后断开) | `{ message: string }` | | `vehicles` | 已订阅城市的车辆位置/状态聚合 | **每 2 秒** | `VehicleMonitorVo[]` — 见 [4.5](#45-vehiclemonitorvo) | | `kpi` | 城市维度 KPI 指标 | **每 5 秒**(复用 2s 聚合结果) | `CommandCenterKpiVo` — 见 [4.6](#46-commandcenterkpivo) | | `passenger_calls` | 待接单乘客呼单列表 | **每 5 秒** | `PassengerCallVo[]` — 见 [4.7](#47-passengercallvo) | 推送范围:以 Socket.IO Room 维度广播,仅推到加入了 `city_{cityCode}` 房间的客户端;前端可同时订阅多个城市但要自行去重。 --- ## 四、数据结构 > 字段类型一栏使用 Java 类型,TS 对应:`Long`→`number`(如担心大数溢出可改为 `string`,由前端 JSON 解析时统一处理)、`Double/Float/BigDecimal`→`number`、`LocalDateTime`→ ISO 字符串 `yyyy-MM-dd HH:mm:ss`(+8)。 ### 4.1 `CommandCenterVehicleDetailVo` | 字段 | 类型 | 说明 | | ---------------------- | -------------------------- | ------------------------------------------------------------------------ | | `vehicleId` | `Long` | 车辆 ID | | `vin` | `String` | 车架号 | | `plateNumber` | `String` | 车牌号 | | `monitorGroup` | `String` | 监控分组,见 [MonitorGroupEnum](#48-monitorgroupenum) | | `monitorStatus` | `String` | 监控状态文案(如"接驾中") | | `stateCode` | `String` | 状态枚举 code,见 [VehicleMonitorStateEnum](#49-vehiclemonitorstateenum) | | `currentElectricity` | `Integer` | 当前电量 0-100 | | `todayCompletedOrders` | `Integer` | 今日已完成订单数 | | `routeInfo` | `CommandCenterRouteInfoVo` | 当前订单路线信息,无进行中订单时为 `null` | | `currentLon` | `Double` | 当前经度 | | `currentLat` | `Double` | 当前纬度 | ### 4.2 `CommandCenterFenceVo` | 字段 | 类型 | 说明 | | ---------------- | ----------------------------- | --------------------------------------------------- | | `electronicId` | `Long` | 围栏 ID | | `electronicName` | `String` | 围栏名称 | | `cityCode` | `String` | 城市编码 | | `status` | `Integer` | 围栏状态 | | `areas` | `List` | 围栏区域,含 `fencePoints`("经度*纬度,经度*纬度") | `XpElectronicFenceArea` 关键字段:`id` `electronicId` `areaName` `areaType`(1=运营区 2=禁行区)`areaStatus`(1=启用 2=禁用)`fencePoints`。 ### 4.3 `XpStation`(场站,精简) 前端用得到的字段:`id` `stationName` `stationNumber` `status`(0=草稿 1=待启用 2=启用中 3=已停用 4=失效)`cityCode` `cityName` `electronicId` `centerLon` `centerLat` `fencePoints` `stationArea` `sortNo`。完整字段见 [XpStation.java](file:///d:/projects/xp-robotaxi/xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpStation.java)。 ### 4.4 `XpOpenCity`(开通城市) | 字段 | 类型 | 说明 | | ------------------------------- | --------- | ------------------------------- | | `id` | `Long` | 主键 | | `provinceName` / `provinceCode` | `String` | 省 | | `cityName` / `cityCode` | `String` | 市(前端订阅时使用 `cityCode`) | | `districtName` / `districtCode` | `String` | 区县 | | `status` | `Integer` | 1=启用 0=禁用(接口只返回启用) | ### 4.5 `VehicleMonitorVo` | 字段 | 类型 | 说明 | | -------------------- | --------- | ------------------------------ | | `vehicleId` | `Long` | 车辆 ID | | `vin` | `String` | 车架号 | | `plateNumber` | `String` | 车牌号 | | `monitorGroup` | `String` | 监控分组 code,见 4.8 | | `monitorStatus` | `String` | 监控状态文案 | | `stateCode` | `String` | 状态 code,见 4.9 | | `lon` | `Double` | 经度 | | `lat` | `Double` | 纬度 | | `course` | `Double` | 航向角 | | `currentElectricity` | `Integer` | 当前电量 | | `speed` | `Float` | 当前速度 km/h | | `orderId` | `Long` | 进行中订单 ID(无单为 `null`) | | `charging` | `Boolean` | 是否充电中 | | `positionUpdateTime` | `Long` | 位置上报时间戳(毫秒) | ### 4.6 `CommandCenterKpiVo` | 字段 | 类型 | 说明 | | ---------------------- | ------------ | ------------------------ | | `cruisingCount` | `Integer` | 巡游中车辆数 | | `hasOrderCount` | `Integer` | 有单车辆数(接驾+送驾) | | `pickUpCount` | `Integer` | 接驾中 | | `dropOffCount` | `Integer` | 送驾中 | | `occupiedCount` | `Integer` | 占用中(充电+整备+回场) | | `chargingCount` | `Integer` | 充电中 | | `preparingCount` | `Integer` | 整备中 | | `returningCount` | `Integer` | 回场中 | | `abnormalCount` | `Integer` | 异常(含 ODD 越界) | | `todayCompletedOrders` | `Integer` | 今日完单数 | | `avgOrdersPerVehicle` | `BigDecimal` | 单车平均完单数 | ### 4.7 `PassengerCallVo` | 字段 | 类型 | 说明 | | ----------------------- | -------- | ------------------------------------- | | `orderId` | `Long` | 订单 ID | | `orderNumber` | `String` | 订单号 | | `startLon` / `startLat` | `Double` | 起点 | | `startAddress` | `String` | 起点地址 | | `endLon` / `endLat` | `Double` | 终点 | | `endAddress` | `String` | 终点地址 | | `createTime` | `String` | 下单时间,`yyyy-MM-dd HH:mm:ss`(+8) | | `waitingSeconds` | `Long` | 已等待秒数(用于呼单超时高亮) | ### 4.8 `MonitorGroupEnum` | code | desc | | ----------- | ------ | | `CRUISING` | 巡游中 | | `HAS_ORDER` | 有单 | | `OCCUPIED` | 占用中 | | `ABNORMAL` | 异常 | ### 4.9 `VehicleMonitorStateEnum` | code | desc | 所属分组 | | ----------- | -------- | ----------- | | `CRUISING` | 巡游中 | `CRUISING` | | `PICK_UP` | 接驾中 | `HAS_ORDER` | | `DROP_OFF` | 送驾中 | `HAS_ORDER` | | `CHARGING` | 充电中 | `OCCUPIED` | | `PREPARING` | 整备中 | `OCCUPIED` | | `RETURNING` | 回场中 | `OCCUPIED` | | `ABNORMAL` | 车辆异常 | `ABNORMAL` | | `ODD_OUT` | ODD 越界 | `ABNORMAL` | --- ## 五、前端接入要点(备忘) 1. **登录态**:复用现有管理后台 SSO,无需单独登录。 2. **路由前缀**:所有 REST 接口都在 `/api/v1/commandCenter` 下,与 cockpit 的 `/cockpit/*` 不冲突。 3. **Socket.IO 时序**:`connect` → `emit('auth', { token })` → `on('auth_success')` → `emit('subscribe', { cityCode })` → `on('vehicles' | 'kpi' | 'passenger_calls')`。 4. **切换城市**:先 `unsubscribe` 再 `subscribe`,避免多城市数据叠加。 5. **断线重连**:socket.io-client 自带重连;重连后需重新 `auth` 与 `subscribe`(服务端不保存订阅状态)。 6. **大屏刷新频率**:车辆 2s、KPI/呼单 5s;前端不要再做客户端拉取,纯被动接收推送。