南钢智慧管控平台 FastAPI 接口设计与数据结构说明

本文对应平台后端 v3.0.0,用于说明前后端分离后的 API 设计、数据结构和联调方式。示例地址统一写作 <server>。出于生产安全考虑,现场设备 IP、账号、口令、厂商写入报文、道闸控制确认值等内容不在公开文档中展示。

一、设计目标

南钢智慧管控平台需要同时服务智慧大屏、车辆管控、人员预约、门岗设备和后续新增子系统。后端采用 FastAPI,将页面展示与设备协议解耦,并通过 PostgreSQL 保存业务数据、Redis 承担缓存和实时事件分发。

核心目标包括:

  1. 前端只依赖统一 REST API,不直接访问摄像机、门禁或停车软件。
  2. 不同厂家设备由适配器转换为统一的通道、车辆事件和控制能力模型。
  3. 大屏通过 SSE 接收实时变化,断线时可以回退到普通查询接口。
  4. 车辆进出、预约、白名单同步和人工控制都保留可追溯记录。
  5. PostgreSQL 与 Redis 只运行在后端内部网络,浏览器和现场设备只访问 FastAPI。

二、总体架构

Vue 3 大屏 / 管理页面
          │  HTTPS / 同源 /api
          ▼
      Nginx 网关
          │
          ▼
FastAPI 平台服务(REST + SSE)
    │          │          │
    ▼          ▼          ▼
PostgreSQL    Redis      设备适配器
业务数据      缓存/事件   停车软件、门禁、摄像机、DI/Modbus

生产环境推荐由 Nginx 将同源 /api/ 转发到 FastAPI。这样前端无须写死内网地址,同一套页面可在不同授权网络中使用。

三、接口约定

3.1 基础地址

http(s)://<server>/api

健康检查位于根路径 /health/*。FastAPI 自带的交互式文档位于 /docs,生产部署可按网络边界限制访问。

3.2 数据格式

  • 请求和响应默认使用 application/json; charset=utf-8
  • 日期时间统一使用 yyyy-MM-dd HH:mm:ss
  • 查询接口采用 items + total 返回列表和总数。
  • 方向字段统一为 in(进场)和 out(出场)。
  • 车牌在入库前自动去除空白并转换为大写。
  • 图片接口直接返回 image/jpeg,不存在时返回 404

列表响应示例:

{
  "items": [
    {
      "id": 1001,
      "gate_no": "示例通道",
      "direction": "in",
      "captured_at": "2026-08-02 10:30:00"
    }
  ],
  "total": 1
}

错误响应沿用 FastAPI 的 detail 字段:

{
  "detail": "请求内容不符合业务规则"
}

常用状态码:

状态码 含义
200 查询或操作成功
201 预约、车辆档案创建成功
204 删除成功,无响应正文
400 业务参数错误或缺少二次确认
401 兼容登录接口认证失败
404 通道、车辆、事件或图片不存在
409 数据冲突、设备状态不支持当前操作
422 字段类型、长度或枚举校验失败
502 下游停车软件、门禁或设备调用失败
503 服务依赖未就绪,或天气数据暂不可用

四、健康检查

GET /health/live

只判断 FastAPI 进程是否存活,适合容器存活探针。

{
  "success": true,
  "service": "nangang-platform-api"
}

GET /health/ready

检查 PostgreSQL、Redis、采集 Worker 和通道统计,适合 Nginx、大屏右上角服务器状态以及容器就绪探针。

{
  "success": true,
  "service": "nangang-platform-api",
  "dependencies": {
    "postgres": true,
    "redis": true,
    "worker": true
  },
  "online_gates": 8,
  "total_gates": 10
}

任一关键依赖不可用时,接口返回 503,同时保留各依赖的布尔状态,前端可以显示明确的故障来源。

五、大屏公开查询接口

方法 路径 作用 主要参数
GET /api/public/weather 查询南京实时天气
GET /api/public/stats 查询指定时间段进出统计 startend
GET /api/public/summary 查询当前在场和容量概况
GET /api/public/events 查询大屏安全字段事件 limit=1..100
GET /api/public/records 查询完整车辆进出记录 分页、车牌、通道、方向、时间
GET /api/public/sessions 查询车辆在场会话 session_statuslimit
GET /api/public/gates 查询全部通道及能力
GET /api/public/gates/{gate_id}/barrier 查询指定道闸状态 通道标识
GET /api/public/events/{event_id}/image 获取事件抓拍图片 事件 ID
GET /api/public/appointments 查询最近预约 limit=1..50
GET /api/public/appointments/options 查询人员预约部门和设备选项

5.1 统计查询

curl "https://<server>/api/public/stats?start=2026-08-02%2000:00:00&end=2026-08-02%2023:59:59"

未传时间时,服务默认统计当天 00:00:0023:59:59。概况接口则返回当前在场数量、剩余容量及相关汇总字段,适合大屏定时兜底刷新。

5.2 进出记录查询

curl "https://<server>/api/public/records?limit=50&offset=0&plate=%E8%8B%8FA12345&direction=in"

参数说明:

参数 类型 说明
limit integer 每页数量,1..100,默认 50
offset integer 偏移量,从 0 开始
plate string 车牌模糊或精确筛选,由服务统一转为大写
gate_id string 通道标识
direction enum 空、inout
start datetime 开始时间
end datetime 结束时间

5.3 在场会话

车辆一次进场到对应出场形成一个停车会话。session_status 支持:

  • open:仍在场,默认值;
  • closed:已出场;
  • all:全部会话。

会话模型将进场事件、出场事件和停留时长关联起来,避免前端自行配对进出记录。

六、南京天气接口

GET /api/public/weather

服务固定使用南京坐标和 Asia/Shanghai 时区,从 Open-Meteo 获取天气。Redis 新鲜缓存为 10 分钟,最近一次成功结果可作为 24 小时降级缓存。

{
  "city": "南京",
  "condition": "多云",
  "temperature_c": 30.2,
  "weather_code": 3,
  "observed_at": "2026-08-02 10:30:00",
  "updated_at": "2026-08-02 10:31:12",
  "source": "Open-Meteo",
  "stale": false
}

stale=true 表示外部天气源暂时不可用,当前返回的是最近一次成功缓存。若没有可用缓存,则返回 503,前端应保留上一次显示结果并提示数据更新时间。

七、SSE 实时事件流

GET /api/public/realtime/stream

接口使用 Server-Sent Events(SSE)向浏览器推送实时变化,服务每 15 秒发送一次保活信息。事件类型包括设备状态、车辆进出、在场数量和天气更新。

浏览器示例:

const stream = new EventSource("/api/public/realtime/stream");

stream.addEventListener("vehicle_event", (event) => {
  const data = JSON.parse(event.data);
  console.log("车辆事件", data);
});

stream.addEventListener("presence_updated", (event) => {
  const data = JSON.parse(event.data);
  console.log("在场数量", data);
});

stream.onerror = () => {
  // EventSource 会自动重连;页面同时保留定时查询作为降级方案。
};

SSE 只负责通知“数据已变化”,重要页面仍应在首次打开时调用 REST API 获取完整快照,重连后再次校准,避免网络中断期间漏掉变化。

八、预约接口

8.1 人员预约

POST /api/public/appointments/person

{
  "name": "张三",
  "phone": "13800000000",
  "reason": "项目沟通",
  "department_no": "DEPT001",
  "device_nos": ["DEVICE001"],
  "id_card": "",
  "sex": 1,
  "photo": "data:image/jpeg;base64,<base64-data>",
  "valid_from": "2026-08-02 09:00:00",
  "valid_until": "2026-08-02 18:00:00"
}

字段约束:姓名 1..50 字符,手机号 6..30 字符,事由 1..100 字符,设备最多 30 个;sex0/1/2;照片为 Base64,服务限制有效长度;许可结束时间必须晚于开始时间。

8.2 车辆预约

POST /api/public/appointments/vehicle

{
  "name": "李四",
  "phone": "13800000000",
  "plate": "苏A12345",
  "plate_color": "blue",
  "reason": "临时来访",
  "valid_from": "2026-08-02 09:00:00",
  "valid_until": "2026-08-02 18:00:00"
}

车牌颜色支持 autoblueyellowgreen。预约成功后,平台先保存预约记录,再建立临时车辆档案并同步到停车系统;任一外部同步失败都会写入失败状态和审计记录,不会把“仅保存成功”误报为“设备已生效”。

九、车辆档案与白名单

车辆档案接口供车辆管控页面使用:

方法 路径 作用
GET /api/vehicles?query= 查询车辆档案
POST /api/vehicles 新增车辆并按启用状态同步
PUT /api/vehicles/{vehicle_id} 修改车辆并更新停车系统
POST /api/vehicles/{vehicle_id}/sync 重试单车同步
DELETE /api/vehicles/{vehicle_id} 停用下游权限后删除车辆
POST /api/vehicles/import 批量导入,单次最多 500 条

车辆输入模型:

{
  "plate": "苏A12345",
  "owner": "张三",
  "department": "生产部",
  "phone": "13800000000",
  "vehicle_type": "内部车辆",
  "plate_color": "blue",
  "valid_from": "2026-08-02 00:00:00",
  "valid_until": "2027-08-02 23:59:59",
  "enabled": true,
  "note": "长期车辆"
}

主要约束:车牌 3..16 字符;车主最多 40 字符;部门最多 80 字符;备注最多 200 字符;失效时间必须晚于生效时间。日期只传 yyyy-MM-dd 时,开始日期自动补 00:00:00,结束日期自动补 23:59:59

9.1 批量导入

{
  "duplicate_mode": "update",
  "items": [
    {
      "plate": "苏A12345",
      "owner": "张三",
      "department": "生产部",
      "enabled": true
    },
    {
      "plate": "苏A67890",
      "owner": "李四",
      "department": "物流部",
      "enabled": true
    }
  ]
}

duplicate_mode 支持 skipupdate。返回结果会分别统计 createdupdatedskippedfailed,并为每一行返回状态和失败原因,便于前端生成导入报告。

{
  "success": true,
  "total": 2,
  "created": 1,
  "updated": 1,
  "skipped": 0,
  "failed": 0,
  "items": [
    {
      "row": 1,
      "plate": "苏A12345",
      "status": "updated",
      "message": "同步成功",
      "vehicle_id": 10
    }
  ]
}

十、核心数据结构

10.1 通道 Gate

字段 说明
id 平台内部通道标识
gate_no 展示名称或门号
direction in / out
online 最近一次采集是否在线
last_seen_at 最近在线时间
capabilities 设备支持的状态读取、事件采集、图片或控制能力

10.2 车辆事件 VehicleEvent

字段 说明
id 平台事件 ID
source_key 来源侧唯一键,用于去重
gate_id / gate_no 通道标识与显示名称
direction 进场或出场
plate 标准化车牌
plate_color 车牌颜色
captured_at 设备抓拍时间
received_at 平台接收时间
image_path 平台内部图片引用,不直接暴露文件系统路径

10.3 停车会话 ParkingSession

字段 说明
plate 车牌
status open / closed
entry_event_id 进场事件
exit_event_id 出场事件
entered_at / exited_at 进出时间
duration_seconds 停留时长

10.4 车辆档案 Vehicle

除车牌、车主、部门和有效期外,模型还保存 enabled、下游同步状态、同步结果编号、最近同步消息与更新时间。这样可以区分“平台已保存”“停车软件已接收”和“现场设备已具备放行条件”。

10.5 预约 Appointment

预约记录包含类型、预约人、手机号、事由、车牌或人员目标、许可时间、外部系统编号、处理状态和结果消息。平台先落库再调用外部系统,因此失败记录也能被追踪和重试。

10.6 审计 AuditLog

人工控制、车辆新增修改、批量导入、预约和同步重试都会记录操作类型、目标对象、来源地址、成功状态、时间及必要的错误摘要。审计记录不保存明文密码和设备口令。

十一、设备同步与控制边界

设备适配器统一输出四类能力:在线状态、车辆事件、抓拍图片和控制能力。查询端只读取统一模型,不关心设备来自 HTTP、XML、停车软件接口还是其他现场协议。

人工开闸属于生产控制操作,接口必须经过明确二次确认、网络访问控制和审计。本文不公开该接口路径、确认值、设备标识和底层报文;相关内容只应出现在受控的交付运维手册中。业务上也不应把“新增车牌”简单等同于“立即抬杆”:是否自动放行还取决于有效期、启用状态、下游同步结果以及停车系统当前策略。

十二、Nginx 同源转发

推荐配置思路如下,实际上游地址由部署环境提供:

location /api/ {
    proxy_pass http://platform_api:19080/api/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

location /api/public/realtime/stream {
    proxy_pass http://platform_api:19080/api/public/realtime/stream;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
    proxy_cache off;
    proxy_read_timeout 1h;
}

SSE 路径需要关闭代理缓冲并延长读取超时,否则浏览器可能长时间收不到事件,或被网关误判为超时。

十三、联调建议

  1. 先调用 /health/ready,确认数据库、Redis 和采集 Worker 全部就绪。
  2. 再调用 /api/public/gates,检查通道总数、在线状态和能力集合。
  3. 使用 /api/public/records/api/public/sessions 核对进出记录和在场车辆。
  4. 打开 SSE 后制造一条测试事件,确认事件通知和 REST 快照一致。
  5. 新增或导入车辆后,以接口返回的同步状态为准,不以页面“保存成功”代替设备侧生效确认。
  6. 对外部系统失败、重复车牌、无效时间范围和网络超时分别做一次异常测试。

十四、安全说明

  • 浏览器和现场终端只访问 FastAPI,不直接连接 PostgreSQL 或 Redis。
  • 公开查询与业务写入应在网关层按部署网络进行访问控制。
  • 控制类操作必须保留二次确认、来源地址和审计记录。
  • 生产日志应脱敏,不记录明文口令、完整身份信息和设备认证参数。
  • 抓拍图片使用事件 ID 访问,并校验文件路径,防止越权读取服务器文件。
  • API 文档与实际服务版本保持一致,升级时同步维护字段、迁移和兼容说明。

十五、前后端代码仓库

前端仓库提供 Vue 3 大屏和 Nginx 同源转发配置。后端链接指向可公开交付的脱敏版本,用于展示 FastAPI 分层、数据结构和部署方式;其中不包含生产环境配置、账号密码、现场设备 IP、真实业务数据、图片备份和厂商控制参数。实际部署时应通过环境变量或受控配置文件补充现场参数,不要将生产密钥提交到 GitHub。

结语

这套 API 的重点不是把各厂家接口原样暴露给前端,而是建立稳定的平台契约:页面只面向统一业务模型,设备差异由后端适配器消化,实时性由 Redis 与 SSE 提供,业务一致性由 PostgreSQL 和审计记录保障。后续接入新的门禁、道闸或监控子系统时,只需新增适配器并复用现有事件和通道模型,无须重写大屏。


南钢智慧管控平台 FastAPI 接口设计与数据结构说明
https://us.wpengu.top/archives/nangang-platform-fastapi-api-design
作者
Administrator
发布于
2026年08月02日
许可协议