feat: expand vehicle data platform capabilities

This commit is contained in:
lingniu
2026-07-27 16:46:15 +08:00
parent e3a1f80f86
commit 3c4bece72c
650 changed files with 62155 additions and 2552 deletions

View File

@@ -0,0 +1,186 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>车辆数据开放平台</title>
<style>
:root{color-scheme:light;--ink:#13213c;--muted:#60708c;--line:#dce3ed;--blue:#1768e5;--soft:#f4f7fb}
*{box-sizing:border-box}body{margin:0;font:15px/1.65 system-ui,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;color:var(--ink);background:#fff}
main{max-width:980px;margin:auto;padding:48px 24px 80px}header{padding:34px;border:1px solid var(--line);border-radius:18px;background:linear-gradient(135deg,#f5f9ff,#eef4ff)}
h1{margin:0 0 10px;font-size:34px}h2{margin:42px 0 14px;font-size:22px}h3{margin:24px 0 10px;font-size:17px}
p{margin:8px 0;color:var(--muted)}a{color:var(--blue)}nav{display:flex;gap:12px;flex-wrap:wrap;margin-top:20px}
nav a{padding:8px 13px;border:1px solid #b9cef0;border-radius:9px;text-decoration:none;background:#fff}
code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}pre{overflow:auto;padding:18px;border-radius:12px;background:#101827;color:#e9f1ff;font-size:13px}
table{width:100%;border-collapse:collapse}th,td{text-align:left;padding:11px;border-bottom:1px solid var(--line);vertical-align:top}th{background:var(--soft)}
.method{display:inline-block;margin-right:8px;padding:2px 8px;border-radius:6px;background:#dff3e5;color:#136b35;font-weight:700}
.note{padding:14px 16px;border-left:4px solid var(--blue);background:var(--soft);color:var(--muted)}
</style>
</head>
<body>
<main>
<header>
<h1>车辆数据开放平台</h1>
<p>面向合作方开放车辆单日用氢量、单日里程、区间日里程和指定时刻总里程。接口使用独立的 32 位 appKey 认证。</p>
<nav>
<a href="/open-api/swagger/">Swagger 在线调试</a>
<a href="/open-api/openapi.yaml">下载 OpenAPI 3.0</a>
</nav>
</header>
<h2>认证</h2>
<pre>Authorization: Bearer &lt;32位appKey&gt;
Content-Type: application/json</pre>
<p class="note">appKey 由平台管理员创建并授权车辆。Key 和逐车授权都必须完整覆盖所查询的自然日。</p>
<h2>开放接口</h2>
<h3><span class="method">POST</span>/api/v1/vehicles/hydrogen-consumption/query</h3>
<p>查询指定车辆的单日用氢量,单位 kg。</p>
<h3><span class="method">POST</span>/api/v1/vehicles/mileage/query</h3>
<p>查询指定车辆的单日行驶里程、累计总里程、实际来源协议、车辆源数据时间和投影更新时间,单位 km。</p>
<p class="note">以上两个按日接口的 plateNumbers 可选;省略或传空数组时,返回该应用在查询自然日有效授权的全部车辆。</p>
<h3><span class="method">POST</span>/api/v1/vehicles/mileage/range/query</h3>
<p>按最长 366 天区间分页查询逐车逐日里程。首次请求固化授权车辆清单,后续使用 nextCursor 翻页。</p>
<p class="note">两个里程接口均可传 protocolPriority唯一外部值为 GB32960、MQTT、JT808。逐车逐日按数组顺序选择第一个有效协议未列出的协议完全禁用。省略字段时保持现有默认选源行为。</p>
<p class="note">查询日没有有效里程但此前存在有效累计里程时,日里程补 0累计总里程、来源协议和数据时间沿用最近有效统计updatedAt 显示上一个统计周期的计算时间。</p>
<h3><span class="method">POST</span>/api/v1/vehicles/total-mileage/query</h3>
<p>按 VIN 和北京时间查询不晚于指定时刻的最近一条总里程,返回实际采集协议、记录时间和时间差秒数。</p>
<h2>总里程协议口径</h2>
<table>
<thead><tr><th>protocol 唯一规范值</th><th>总里程含义</th></tr></thead>
<tbody>
<tr><td>GB32960</td><td>车辆仪表盘累计总里程,对应 GB/T 32960 整车数据累计里程</td></tr>
<tr><td>YUTONG_MQTT</td><td>车辆仪表盘或车端控制器累计总里程,由 MQTT 平台上报</td></tr>
<tr><td>JT808</td><td>定位终端累计里程,由 GPS/终端侧计算,不等同于车辆仪表盘里程</td></tr>
</tbody>
</table>
<p class="note">protocol 不传时严格按 GB32960 &gt; YUTONG_MQTT &gt; JT808 选择首个有数据的协议。接口取不晚于请求时间的最近记录,不跨协议拼接里程。</p>
<h2>请求示例</h2>
<pre>curl -X POST 'https://your-host/api/v1/vehicles/hydrogen-consumption/query' \
-H 'Authorization: Bearer YOUR_32_CHARACTER_APP_KEY' \
-H 'Content-Type: application/json' \
-d '{
"plateNumbers": ["粤A12345", "粤B67890"],
"date": "2026-07-01"
}'</pre>
<h3>查询全部授权车辆的单日数据</h3>
<pre>{
"date": "2026-07-01"
}</pre>
<h3>按自定义协议优先级查询单日里程</h3>
<pre>{
"plateNumbers": ["粤A12345"],
"date": "2026-07-01",
"protocolPriority": ["JT808", "GB32960", "MQTT"]
}</pre>
<h3>指定时刻总里程</h3>
<pre>curl -X POST 'https://your-host/api/v1/vehicles/total-mileage/query' \
-H 'Authorization: Bearer YOUR_32_CHARACTER_APP_KEY' \
-H 'Content-Type: application/json' \
-d '{
"vin": "LA9GG68L2PBAF4790",
"time": "2026-07-21 09:30:00",
"protocol": "GB32960"
}'</pre>
<h3>车辆区间日里程</h3>
<pre>curl -X POST 'https://your-host/api/v1/vehicles/mileage/range/query' \
-H 'Authorization: Bearer YOUR_32_CHARACTER_APP_KEY' \
-H 'Content-Type: application/json' \
-d '{
"startDate": "2026-07-01",
"endDate": "2026-07-23",
"protocolPriority": ["GB32960", "MQTT"],
"pageSize": 5000
}'</pre>
<p class="note">下一页保持原请求参数不变,并传入上一页 nextCursor同一次分页查询的 snapshotId 保持不变。</p>
<h2>响应示例</h2>
<h3>车辆单日里程</h3>
<pre>{
"code": "SUCCESS",
"message": "success",
"data": [{
"vin": "LNB00000000000001",
"plateNumber": "粤A12345",
"date": "2026-07-01",
"dailyMileageKm": 182.437,
"totalMileageKm": 12345.679,
"dataTime": "2026-07-01T23:58:45+08:00",
"updatedAt": "2026-07-02T05:10:00+08:00",
"sourceProtocol": "GB32960",
"status": "NORMAL"
}],
"traceId": "b7ff5582ab1a4e13bfb4f10943685599"
}</pre>
<p class="note">里程状态为 NORMAL 时dailyMileageKm、totalMileageKm、dataTime 与 updatedAt 均有值NO_DATA 时相关数据字段为 null真实零里程仍为 NORMAL。</p>
<h3>车辆区间日里程响应</h3>
<pre>{
"code": "SUCCESS",
"message": "success",
"data": [{
"vin": "LNB00000000000001",
"plateNumber": "粤A12345",
"date": "2026-07-01",
"dailyMileageKm": 182.437,
"dataTime": "2026-07-01T23:58:45+08:00",
"updatedAt": "2026-07-02T05:10:00+08:00",
"status": "NORMAL"
}],
"snapshotId": "9f8a74efbf9846349ae5676f3a5c0de8",
"nextCursor": null,
"traceId": "4ccf63c4e51d4d4ab9107d931783a53e"
}</pre>
<h3>车辆单日用氢量</h3>
<pre>{
"code": "SUCCESS",
"message": "success",
"data": [{
"plateNumber": "粤A12345",
"date": "2026-07-01",
"hydrogenConsumptionKg": 12.315,
"status": "NORMAL"
}],
"traceId": "4ccf63c4e51d4d4ab9107d931783a53e"
}</pre>
<h3>指定时刻总里程响应</h3>
<pre>{
"code": "SUCCESS",
"message": "success",
"data": {
"vin": "LA9GG68L2PBAF4790",
"queryTime": "2026-07-21 09:30:00",
"totalMileageKm": 12345.678,
"protocol": "GB32960",
"protocolInput": "GB32960",
"mileageMeaning": "车辆仪表盘累计总里程GB/T 32960整车数据累计里程",
"recordTime": "2026-07-21 09:29:45",
"timeDifferenceSeconds": 15,
"selectionPolicy": "GB32960 &gt; YUTONG_MQTT &gt; JT808",
"status": "NORMAL"
},
"traceId": "95bddca78133474fa2bf56ecdf758e22"
}</pre>
<h2>状态与错误码</h2>
<table>
<thead><tr><th>HTTP</th><th>code</th><th>说明</th></tr></thead>
<tbody>
<tr><td>200</td><td>SUCCESS</td><td>查询成功;无统计数据的车辆以 NO_DATA 返回</td></tr>
<tr><td>400</td><td>INVALID_REQUEST</td><td>请求格式、车牌或数量不正确</td></tr>
<tr><td>400</td><td>INVALID_DATE_FORMAT</td><td>日期不是 yyyy-MM-dd</td></tr>
<tr><td>400</td><td>INVALID_DATETIME_FORMAT</td><td>时间不是 yyyy-MM-dd HH:mm:ss</td></tr>
<tr><td>401</td><td>UNAUTHORIZED</td><td>appKey 不存在、停用或过期</td></tr>
<tr><td>403</td><td>FORBIDDEN</td><td>Key 或车辆授权未覆盖查询自然日</td></tr>
<tr><td>500</td><td>INTERNAL_ERROR</td><td>服务内部异常</td></tr>
</tbody>
</table>
</main>
</body>
</html>

View File

@@ -0,0 +1,743 @@
openapi: 3.0.3
info:
title: 车辆数据开放平台 API
version: 1.5.0
license:
name: Proprietary
description: |
向授权合作方开放车辆单日用氢量、单日里程、区间日里程和指定时刻总里程。
appKey 和逐车授权必须完整覆盖查询自然日。
servers:
- url: /
description: 当前服务
tags:
- name: 合作方数据接口
description: 使用 appKey 查询已授权车辆的日统计数据
- name: 开放平台管理
description: 仅车辆数据平台管理员可调用的应用和车辆授权管理接口
paths:
/api/v1/vehicles/hydrogen-consumption/query:
post:
tags: [合作方数据接口]
summary: 查询车辆单日用氢量
description: plateNumbers 省略或传空数组时,返回该应用在查询自然日有效授权的全部车辆。
operationId: queryDailyHydrogenConsumption
security:
- AppKeyAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/VehicleDailyQuery'
example:
date: '2026-07-01'
responses:
'200':
description: 查询成功;无数据车辆仍保留在结果中
content:
application/json:
schema:
$ref: '#/components/schemas/HydrogenQueryResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalError'
/api/v1/vehicles/mileage/query:
post:
tags: [合作方数据接口]
summary: 查询车辆单日里程
description: |
plateNumbers 省略或传空数组时,返回该应用在查询自然日有效授权的全部车辆。
protocolPriority 传入时,逐车按数组顺序选择第一个有效协议,未列出的协议完全禁用且不会兜底;省略时保持平台默认选源行为。
NORMAL 结果同时包含日里程、累计总里程、实际来源协议、源数据时间和投影更新时间。
当日无有效里程时,日里程补 0累计总里程、来源协议、dataTime 和 updatedAt 沿用此前最近的有效统计updatedAt 仍为上一统计周期的计算时间。
operationId: queryDailyMileage
security:
- AppKeyAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/MileageDailyQuery'
example:
date: '2026-07-01'
protocolPriority: [GB32960, MQTT, JT808]
responses:
'200':
description: 查询成功;无数据车辆仍保留在结果中
content:
application/json:
schema:
$ref: '#/components/schemas/MileageQueryResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalError'
/api/v1/vehicles/mileage/range/query:
post:
tags: [合作方数据接口]
summary: 分页查询车辆区间日里程
description: |
最长支持 366 天。plateNumbers 省略或传空数组时固化应用在整个查询区间有效授权的全部车辆。
首次请求返回 snapshotId 和 nextCursor后续请求保持原参数并传回 nextCursor。
快照仅固化授权车辆清单,逐页读取已建立索引的日统计投影,不扫描原始时序明细。
protocolPriority 对区间内每辆车、每个自然日独立生效;未列出的协议完全禁用。
某日无有效里程时dailyMileageKm 补 0其余里程证据沿用此前最近的有效统计。
operationId: queryDailyMileageRange
security:
- AppKeyAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/MileageRangeQuery'
example:
startDate: '2026-07-01'
endDate: '2026-07-23'
plateNumbers: [沪A00001, 沪A00002]
protocolPriority: [JT808, GB32960, MQTT]
cursor: null
pageSize: 5000
responses:
'200':
description: 查询成功;每辆授权车辆每天均有一条 NORMAL 或 NO_DATA 记录
content:
application/json:
schema:
$ref: '#/components/schemas/MileageRangeQueryResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalError'
/api/v1/vehicles/total-mileage/query:
post:
tags: [合作方数据接口]
summary: 查询指定时刻的车辆总里程
description: |
返回不晚于请求时间的最近一条有效总里程记录、实际记录时间和时间差秒数。
protocol 不传时严格按 GB32960 > YUTONG_MQTT > JT808 选择首个有数据的协议。
GB32960 和 YUTONG_MQTT 为车辆仪表盘或车端累计里程JT808 为定位终端/GPS侧累计里程。
operationId: queryTotalMileageAtTime
security:
- AppKeyAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TotalMileageQuery'
example:
vin: LA9GG68L2PBAF4790
time: '2026-07-21 09:30:00'
protocol: GB32960
responses:
'200':
description: 查询成功;没有可用记录时返回 NO_DATA
content:
application/json:
schema:
$ref: '#/components/schemas/TotalMileageQueryResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalError'
/api/v2/open-platform/apps:
get:
tags: [开放平台管理]
summary: 查询开放平台应用
operationId: listOpenPlatformApps
security:
- AdminBearer: []
responses:
'200':
description: 应用列表
content:
application/json:
schema:
$ref: '#/components/schemas/AdminAppListResponse'
'401':
description: 未登录
'403':
description: 非管理员
post:
tags: [开放平台管理]
summary: 创建应用和 appKey
description: appKey 明文仅在本次响应中返回。
operationId: createOpenPlatformApp
security:
- AdminBearer: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AppInput'
responses:
'200':
description: 创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/AdminAppCreatedResponse'
'400':
description: 参数错误
'401':
description: 未登录
'403':
description: 非管理员
/api/v2/open-platform/apps/{id}:
put:
tags: [开放平台管理]
summary: 更新应用状态和有效期
operationId: updateOpenPlatformApp
security:
- AdminBearer: []
parameters:
- $ref: '#/components/parameters/AppId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AppInput'
responses:
'200':
description: 更新成功
'400':
description: 参数错误
'404':
description: 应用不存在
/api/v2/open-platform/apps/{id}/rotate-key:
post:
tags: [开放平台管理]
summary: 轮换 appKey
description: 旧 Key 立即失效,新 Key 明文仅在本次响应中返回。
operationId: rotateOpenPlatformAppKey
security:
- AdminBearer: []
parameters:
- $ref: '#/components/parameters/AppId'
responses:
'200':
description: 轮换成功
content:
application/json:
schema:
$ref: '#/components/schemas/AdminAppCreatedResponse'
'404':
description: 应用不存在
/api/v2/open-platform/apps/{id}/vehicles:
get:
tags: [开放平台管理]
summary: 查询应用的车辆授权
operationId: listOpenPlatformVehicleGrants
security:
- AdminBearer: []
parameters:
- $ref: '#/components/parameters/AppId'
responses:
'200':
description: 授权列表
'404':
description: 应用不存在
put:
tags: [开放平台管理]
summary: 完整替换车辆授权
operationId: replaceOpenPlatformVehicleGrants
security:
- AdminBearer: []
parameters:
- $ref: '#/components/parameters/AppId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/VehicleGrantRequest'
responses:
'200':
description: 替换成功
'400':
description: VIN 或有效期不正确
'404':
description: 应用不存在
components:
securitySchemes:
AppKeyAuth:
type: http
scheme: bearer
bearerFormat: 32-character appKey
description: 32 位无连字符 UUID appKey
AdminBearer:
type: http
scheme: bearer
bearerFormat: Platform session token
description: 车辆数据平台管理员令牌
parameters:
AppId:
name: id
in: path
required: true
schema:
type: integer
format: int64
minimum: 1
responses:
BadRequest:
description: 请求参数不正确
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
examples:
invalidDate:
value:
code: INVALID_DATE_FORMAT
message: date格式必须为yyyy-MM-dd
traceId: 4ccf63c4e51d4d4ab9107d931783a53e
Unauthorized:
description: appKey 不存在、停用或过期
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Forbidden:
description: Key 或车辆授权未完整覆盖查询自然日
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
InternalError:
description: 服务内部异常
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
schemas:
VehicleDailyQuery:
type: object
additionalProperties: false
required: [date]
properties:
plateNumbers:
type: array
maxItems: 200
uniqueItems: true
items:
type: string
minLength: 1
maxLength: 32
description: 可选;指定时查询这些已授权车牌,省略或传空数组时查询该自然日有效授权的全部车辆
date:
type: string
format: date
description: 查询自然日yyyy-MM-dd
MileageDailyQuery:
type: object
additionalProperties: false
required: [date]
properties:
plateNumbers:
type: array
maxItems: 200
uniqueItems: true
items:
type: string
minLength: 1
maxLength: 32
description: 可选;指定时查询这些已授权车牌,省略或传空数组时查询该自然日有效授权的全部车辆
date:
type: string
format: date
description: 查询自然日yyyy-MM-dd
protocolPriority:
$ref: '#/components/schemas/ProtocolPriority'
MileageRangeQuery:
type: object
additionalProperties: false
required: [startDate, endDate]
properties:
startDate:
type: string
format: date
description: 区间开始自然日Asia/Shanghai
endDate:
type: string
format: date
description: 区间结束自然日,含当日;与 startDate 最多相隔 365 天
plateNumbers:
type: array
maxItems: 5000
uniqueItems: true
items:
type: string
minLength: 1
maxLength: 32
description: 可选;省略或传空数组时查询整个区间均有效授权的全部车辆
protocolPriority:
$ref: '#/components/schemas/ProtocolPriority'
cursor:
type: string
nullable: true
description: 首次查询传 null 或省略;翻页时原样传入上一页 nextCursor
pageSize:
type: integer
minimum: 1
maximum: 5000
default: 5000
ProtocolPriority:
type: array
minItems: 1
maxItems: 3
uniqueItems: true
items:
type: string
enum: [GB32960, MQTT, JT808]
description: 可选;按数组顺序逐车逐日选择第一个有效协议。未列出的协议被禁用且不会作为兜底;省略字段时保持平台默认选源行为
TotalMileageQuery:
type: object
additionalProperties: false
required: [vin, time]
properties:
vin:
type: string
pattern: '^[A-HJ-NPR-Z0-9]{17}$'
description: 已授权车辆 VIN
time:
type: string
pattern: '^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$'
description: 请求时刻,北京时间,固定格式 yyyy-MM-dd HH:mm:ss
protocol:
type: string
enum: [GB32960, YUTONG_MQTT, JT808]
description: 可选;只接受平台统一协议标识;不传时按 GB32960 > YUTONG_MQTT > JT808
HydrogenResult:
type: object
required: [plateNumber, date, hydrogenConsumptionKg, status]
properties:
plateNumber:
type: string
date:
type: string
format: date
hydrogenConsumptionKg:
type: number
format: double
nullable: true
description: 单日用氢量kg无数据时为 null
status:
$ref: '#/components/schemas/DataStatus'
MileageResult:
type: object
required: [vin, plateNumber, date, dailyMileageKm, totalMileageKm, dataTime, updatedAt, sourceProtocol, status]
properties:
vin:
type: string
plateNumber:
type: string
date:
type: string
format: date
dailyMileageKm:
type: number
format: double
nullable: true
description: 单日里程km当日无记录但存在历史累计里程时为 0
totalMileageKm:
type: number
format: double
nullable: true
description: 当日所选协议最后有效累计总里程kmstatus=NORMAL 时必定有值NO_DATA 时为 null
dataTime:
type: string
format: date-time
nullable: true
description: 本次统计实际采用的最后一条车辆源数据时间status=NO_DATA 时为 null
updatedAt:
type: string
format: date-time
nullable: true
description: 本行所依据统计周期的计算时间前向填充时为上一统计周期计算时间status=NO_DATA 时为 null
sourceProtocol:
type: string
enum: [GB32960, MQTT, JT808]
nullable: true
description: 本行实际选中的来源协议status=NO_DATA 时为 null
status:
$ref: '#/components/schemas/DataStatus'
MileageRangeResult:
type: object
required: [vin, plateNumber, date, dailyMileageKm, totalMileageKm, dataTime, updatedAt, sourceProtocol, status]
properties:
vin:
type: string
plateNumber:
type: string
date:
type: string
format: date
dailyMileageKm:
type: number
format: double
nullable: true
minimum: 0
description: 当日无记录但存在历史累计里程时为 0
totalMileageKm:
type: number
format: double
nullable: true
minimum: 0
description: 当日所选协议累计总里程;缺日时沿用此前最近有效值
dataTime:
type: string
format: date-time
nullable: true
updatedAt:
type: string
format: date-time
nullable: true
description: 本行所依据统计周期的计算时间;缺日补齐时为上一统计周期计算时间
sourceProtocol:
type: string
enum: [GB32960, MQTT, JT808]
nullable: true
description: 本行实际选中的来源协议status=NO_DATA 时为 null
status:
$ref: '#/components/schemas/DataStatus'
DataStatus:
type: string
enum: [NORMAL, NO_DATA]
HydrogenQueryResponse:
allOf:
- $ref: '#/components/schemas/SuccessEnvelope'
- type: object
required: [data]
properties:
data:
type: array
items:
$ref: '#/components/schemas/HydrogenResult'
MileageQueryResponse:
allOf:
- $ref: '#/components/schemas/SuccessEnvelope'
- type: object
required: [data]
properties:
data:
type: array
items:
$ref: '#/components/schemas/MileageResult'
MileageRangeQueryResponse:
type: object
required: [code, message, data, snapshotId, nextCursor, traceId]
properties:
code:
type: string
enum: [SUCCESS]
message:
type: string
example: success
data:
type: array
items:
$ref: '#/components/schemas/MileageRangeResult'
snapshotId:
type: string
description: 同一次分页查询保持不变的授权车辆快照标识
nextCursor:
type: string
nullable: true
description: 下一页游标;最后一页为 null
traceId:
type: string
TotalMileageResult:
type: object
required: [vin, queryTime, totalMileageKm, selectionPolicy, status]
properties:
vin:
type: string
queryTime:
type: string
description: 请求时刻,北京时间
totalMileageKm:
type: number
format: double
nullable: true
description: 总里程km无数据时为 null
protocol:
type: string
enum: [GB32960, YUTONG_MQTT, JT808]
description: 实际采用的采集协议
protocolInput:
type: string
description: 请求中指定的协议原值;未指定时省略
mileageMeaning:
type: string
description: 当前协议总里程的业务含义
recordTime:
type: string
description: 命中的实际采集记录时间,北京时间
timeDifferenceSeconds:
type: integer
format: int64
minimum: 0
description: 请求时间减实际记录时间,单位秒
selectionPolicy:
type: string
example: GB32960 > YUTONG_MQTT > JT808
status:
$ref: '#/components/schemas/DataStatus'
TotalMileageQueryResponse:
allOf:
- $ref: '#/components/schemas/SuccessEnvelope'
- type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/TotalMileageResult'
SuccessEnvelope:
type: object
required: [code, message, traceId]
properties:
code:
type: string
enum: [SUCCESS]
message:
type: string
example: success
traceId:
type: string
example: 4ccf63c4e51d4d4ab9107d931783a53e
ErrorResponse:
type: object
required: [code, message, traceId]
properties:
code:
type: string
enum:
- INVALID_REQUEST
- INVALID_DATE_FORMAT
- UNAUTHORIZED
- FORBIDDEN
- INTERNAL_ERROR
message:
type: string
traceId:
type: string
AppInput:
type: object
additionalProperties: false
required: [name, status, validFrom]
properties:
name:
type: string
maxLength: 96
example: 示例合作方
status:
type: string
enum: [enabled, disabled]
validFrom:
type: string
format: date-time
example: '2026-07-01T00:00:00+08:00'
validTo:
type: string
format: date-time
nullable: true
example: '2027-07-01T00:00:00+08:00'
App:
type: object
required: [id, name, appKeyPrefix, status, validFrom]
properties:
id:
type: integer
format: int64
name:
type: string
appKeyPrefix:
type: string
minLength: 8
maxLength: 8
status:
type: string
enum: [enabled, disabled]
validFrom:
type: string
format: date-time
validTo:
type: string
format: date-time
nullable: true
AppCreated:
allOf:
- $ref: '#/components/schemas/App'
- type: object
required: [appKey]
properties:
appKey:
type: string
minLength: 32
maxLength: 32
pattern: '^[0-9a-f]{32}$'
description: 仅本次响应返回
VehicleGrantRequest:
type: object
additionalProperties: false
required: [vehicles]
properties:
vehicles:
type: array
maxItems: 500
items:
$ref: '#/components/schemas/VehicleGrantInput'
VehicleGrantInput:
type: object
additionalProperties: false
required: [vin, validFrom]
properties:
vin:
type: string
minLength: 17
maxLength: 17
validFrom:
type: string
format: date-time
validTo:
type: string
format: date-time
nullable: true
AdminAppListResponse:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/App'
traceId:
type: string
AdminAppCreatedResponse:
type: object
properties:
data:
$ref: '#/components/schemas/AppCreated'
traceId:
type: string

View File

@@ -0,0 +1,17 @@
window.addEventListener("load", function () {
window.ui = SwaggerUIBundle({
url: "/open-api/openapi.yaml",
dom_id: "#swagger-ui",
deepLinking: true,
displayRequestDuration: true,
filter: true,
persistAuthorization: false,
tryItOutEnabled: false,
validatorUrl: null,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
layout: "StandaloneLayout"
});
});

View File

@@ -0,0 +1,15 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>车辆数据开放平台 Swagger</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.17.14/swagger-ui.css">
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.17.14/swagger-ui-bundle.js"></script>
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.17.14/swagger-ui-standalone-preset.js"></script>
<script src="/open-api/swagger-init.js"></script>
</body>
</html>