27 KiB
告警管理系统 API 接口文档(Django 版)
基础路径:
/api/v1服务器地址:http://192.168.28.32:8000认证方式:Bearer Token(24h 有效期) 统一响应信封:{ "err": { "ec": 0, "dm": "ok" }, "ret": <data> }
目录
1. 认证接口
1.1 登录
- 方法:
POST - 路径:
/auth/login - 描述:用户登录,获取 Token
- 鉴权:无(公开)
请求头:
Content-Type: application/json
Accept: application/json
请求体(Body JSON):
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
username |
string |
是 | 用户名 |
password |
string |
是 | 密码 |
cookieless |
string |
是 | "True" 或 "False" |
{
"username": "admin",
"password": "123456",
"cookieless": "False"
}
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {
"token": "eyJhbGciOiJIUzI1NiIs..."
}
}
| 返回字段 | 类型 | 说明 |
|---|---|---|
ret.token |
string |
JWT Token,有效期 24h |
失败响应:
{
"err": { "ec": 1001, "dm": "用户名或密码错误" }
}
1.2 登出
- 方法:
POST - 路径:
/auth/logout - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
请求体:无
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
1.3 添加用户
- 方法:
POST - 路径:
/auth/adduser - 鉴权:Bearer Token(需管理员权限)
请求头:
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
请求体(Body JSON):
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
username |
string |
是 | 用户名 |
password |
string |
是 | 密码 |
email |
string |
否 | 邮箱,默认为空 |
{
"username": "operator1",
"password": "pass123456",
"email": ""
}
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
1.4 删除用户
- 方法:
POST - 路径:
/auth/rmuser - 鉴权:Bearer Token(需管理员权限)
请求头:
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
请求体(Body JSON):
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
username |
string |
是 | 要删除的用户名 |
{
"username": "operator1"
}
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
1.5 获取所有用户
- 方法:
GET - 路径:
/auth/allusers - 鉴权:Bearer Token(需管理员权限)
请求头:
Authorization: Bearer <access_token>
Accept: application/json
请求参数:无
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {
"users": [
{
"username": "admin",
"email": ""
},
{
"username": "operator1",
"email": "op1@example.com"
}
]
}
}
| 返回字段 | 类型 | 说明 |
|---|---|---|
ret.users |
array |
用户列表 |
ret.users[].username |
string |
用户名 |
ret.users[].email |
string |
邮箱 |
1.6 重置用户信息
- 方法:
POST - 路径:
/auth/resetuser - 鉴权:Bearer Token(需管理员权限)
请求头:
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
请求体(Body JSON):
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
username |
string |
是 | 用户名 |
password |
string |
是 | 新密码 |
email |
string |
是 | 邮箱 |
{
"username": "operator1",
"password": "newpass123",
"email": "op1@example.com"
}
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
2. 事件(告警)接口
2.1 获取事件列表(分页)
- 方法:
GET - 路径:
/events - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Accept: application/json
查询参数(Query):
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
limit |
number |
否 | 20 |
每页条数 |
offset |
number |
否 | 0 |
偏移量 |
请求示例:
GET /api/v1/events?limit=20&offset=0
Authorization: Bearer <token>
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {
"count": 1617,
"next": "http://192.168.28.32:8000/api/v1/events?limit=20&offset=20",
"previous": null,
"results": [
{
"id": 90908,
"camera_id": 1,
"started_at": "2026-04-01T09:30:00Z",
"ended_at": "2026-04-01T09:30:10Z",
"mediums": [
{
"id": 109656,
"name": "snapshot",
"file": "http://192.168.28.32:8000/media/mediums/2026/04/02/camera1_xxx.jpg",
"event_id": 90908
}
],
"camera": {
"id": 1,
"name": "421枪机",
"uri": "rtsp://admin:1234qwer@192.168.28.102:554/Streaming/Channels/202",
"mode": "on",
"status": "online",
"detect_params": { "threshold": 0.5 },
"default_params": {},
"rules": [ /* RuleItem[] 见规则结构 */ ],
"should_push": false,
"config_params": {},
"sampling": false,
"note": {},
"snapshot": "http://192.168.28.32:8000/media/camera/camera1_snapshot.jpg",
"remote_id": -1,
"raw_address": "0b8342ec52e62d01dd3273f583d326ec",
"ip": "admin:1234qwer@192.168.28.102:554",
"port": 8082
},
"types": "wander",
"types_bits": 0,
"obj_types": {},
"uuid": "461aeb6e-10f3-4173-9b33-d540ce59511e",
"status": "pending",
"remark": null,
"should_push": false,
"metadata": {}
}
]
}
}
前端返回:
{
tableData: EventItem[], // ret.results
totalItems: number // ret.count
}
2.2 按参数筛选事件列表
- 方法:
GET - 路径:
/events - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Accept: application/json
查询参数(Query):
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
limit |
number |
否 | 20 |
每页条数 |
offset |
number |
否 | 0 |
偏移量 |
time_before |
string |
否 | — | 结束时间(ISO 8601) |
time_after |
string |
否 | — | 开始时间(ISO 8601) |
types |
string |
否 | — | 告警类型编码(如 wander) |
camera_id |
number |
否 | — | 摄像头 ID |
status |
string |
否 | — | 状态:pending / closed |
请求示例:
GET /api/v1/events?limit=20&offset=0&time_after=2026-04-01T00%3A00%3A00Z&time_before=2026-04-02T00%3A00%3A00Z&types=wander&camera_id=1&status=pending
Authorization: Bearer <token>
成功响应(200 OK):同 2.1 响应结构。
2.3 获取单个事件详情
- 方法:
GET - 路径:
/event/events/retrieves - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Accept: application/json
查询参数(Query):
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
id |
number |
是 | 事件 ID |
请求示例:
GET /api/v1/event/events/retrieves?id=90908
Authorization: Bearer <token>
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {
"objects": [
{
"id": 90908,
"camera_id": 1,
"started_at": "2026-04-01T09:30:00Z",
"ended_at": "2026-04-01T09:30:10Z",
"mediums": [
{
"id": 109656,
"name": "snapshot",
"file": "http://192.168.28.32:8000/media/mediums/2026/04/02/camera1_xxx.jpg",
"event_id": 90908
}
],
"camera": { /* CameraItem 见摄像头结构 */ },
"types": "wander",
"types_bits": 0,
"obj_types": {},
"uuid": "461aeb6e-10f3-4173-9b33-d540ce59511e",
"status": "pending",
"remark": null,
"should_push": false,
"metadata": {}
}
]
}
}
前端取值:res.data.ret.objects[0]
2.4 获取最新一条事件
- 方法:内部调用
getEvents(token, 1, 1) - 路径:
/events?limit=1&offset=0 - 鉴权:Bearer Token
成功响应:同 2.1,但 results 只有一条,count 为总条数。
2.5 修改事件状态
- 方法:
PATCH - 路径:
/events/{eventId} - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
路径参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
eventId |
number |
事件 ID |
请求体(Body JSON):
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
status |
string |
是 | 状态值:pending / closed |
remark |
string |
否 | 备注信息 |
{
"status": "closed",
"remark": "已处理完毕"
}
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
2.6 删除事件
- 方法:
DELETE - 路径:
/event/events/{eventId} - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Accept: application/json
路径参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
eventId |
number |
事件 ID |
请求体:无
成功响应:204 No Content(无 body)
失败响应(如事件不存在):
{
"err": {
"ec": 404,
"dm": "Not Found",
"em": "Not found."
}
}
2.7 事件对象完整结构(EventItem)
interface EventItem {
id: number; // 告警 ID
camera_id: number; // 摄像头 ID
started_at: string; // 开始时间(ISO 8601)
ended_at: string; // 结束时间(ISO 8601)
types: string; // 告警类型编码(如 "wander")
types_bits: number; // 类型位标记
obj_types: Record<string, any>; // 目标类型
uuid: string; // 唯一标识
status: 'pending' | 'closed'; // 处理状态
remark: string | null; // 备注
should_push: boolean; // 是否推送
metadata: Record<string, any>; // 元数据
// 多媒体
mediums: Array<{
id: number;
name: string; // 如 "snapshot"
file: string; // 图片 URL(已规范化)
event_id: number;
}>;
// 关联摄像头
camera: CameraItem;
}
3. 摄像头接口
3.1 获取摄像头列表
- 方法:
GET - 路径:
/camera/cameras/get_all - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Accept: application/json
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {
"count": 10,
"results": [
{
"id": 1,
"name": "421枪机",
"uri": "rtsp://{camerastream}",
"mode": "on",
"status": "online",
"detect_params": {
"threshold": 0.5
},
"default_params": {},
"rules": [
{
"id": 1,
"unique_id": "1268f3f2-e0c5-47ea-aa1f-5b97b6dfb95d",
"camera": 1,
"name": "规则名称",
"mode": "on",
"algo": "rule-name",
"params": {},
"params_base": "",
"schedule": {},
"event_types": {
"规则英文": "别名,中文映射"
}
}
],
"should_push": false,
"config_params": {},
"sampling": false,
"note": {},
"snapshot": "URL***.jpg",
"remote_id": -1,
"raw_address": "0b8342ec52e62d01dd3273f583d326ec",
"ip": "camera-url",
"port": 8082
}
]
}
}
3.2 获取单个摄像头详情
- 方法:
GET - 路径:
/camera/cameras/{cameraId} - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Accept: application/json
路径参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
cameraId |
number |
摄像头 ID |
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": { /* CameraItem */ }
}
3.3 更新摄像头信息
- 方法:
PATCH - 路径:
/camera/cameras/{cameraId} - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
路径参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
cameraId |
number |
摄像头 ID |
请求体(Body JSON):
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
name |
string |
否 | 摄像头名称 |
mode |
"on" / "off" |
是 | 检测模式 |
{
"name": "421枪机",
"mode": "on"
}
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": { /* CameraItem */ }
}
3.4 启动摄像头视频流
- 方法:
POST - 路径:
/camera/cameras/{cameraId}/start_stream - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Accept: application/json
路径参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
cameraId |
number |
摄像头 ID |
请求体:无
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {
"port": 8094
}
}
| 返回字段 | 类型 | 说明 |
|---|---|---|
ret.port |
number |
动态分配的 WebSocket 端口,用于 JSMpeg 视频播放 |
3.5 停止摄像头视频流
- 方法:
POST - 路径:
/camera/cameras/{cameraId}/stop_stream - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Accept: application/json
路径参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
cameraId |
number |
摄像头 ID |
请求体:无
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
3.8 摄像头对象完整结构(CameraItem)
interface CameraItem {
id: number;
name: string; // 点位名称(如 "421枪机")
uri: string; // RTSP 地址
mode: 'on' | 'off'; // 检测全局开关
status: 'online' | 'offline'; // 在线状态
detect_params: {
threshold: number; // 检测阈值(如 0.5)
};
default_params: Record<string, any>;
rules: RuleItem[]; // 关联规则列表
should_push: boolean;
config_params: Record<string, any>;
sampling: boolean;
note: Record<string, any>;
snapshot: string; // 快照图片 URL(已规范化)
remote_id: number;
raw_address: string;
ip: string;
port: number;
}
前端发送的 CameraData 类型(用于 updateCamera):
interface CameraData {
id?: number;
name?: string;
mode?: "on" | "off";
rules?: RuleData[] | {};
}
4. 规则接口
4.1 更新规则
- 方法:
PATCH - 路径:
/rules/{ruleId} - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
路径参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
ruleId |
number |
规则 ID |
请求体(Body JSON):
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
id |
number |
是 | 规则 ID |
name |
string |
否 | 规则名称 |
mode |
"on" / "off" / "schedule" |
否 | 规则模式 |
schedule |
object |
否 | 时间段配置 |
{
"id": 1,
"name": "徘徊",
"mode": "on",
"schedule": {}
}
带时间段的请求:
{
"id": 1,
"name": "未穿反光衣",
"mode": "schedule",
"schedule": {
"type": "daily",
"time_slots": [
[
960,
1020
]
]
}
}
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": { /* RuleItem */ }
}
4.2 规则对象完整结构(RuleItem)
interface RuleItem {
id: number;
unique_id: string; // UUID
camera: number; // 关联摄像头 ID
name: string; // 规则名称(如 "徘徊")
mode: 'on' | 'off' | 'schedule';
algo: string; // 算法编码(如 "wander")
params: Record<string, any>;
params_base: string;
schedule: {
type: string; // 如 "daily"
time_slots?: Array<[number, number]>;
} | {};
event_types: Record<string, string>; // 如 { "wander": "人员徘徊" }
}
5. 算法接口
5.1 获取算法列表
- 方法:
GET - 路径:
/algorithms - 鉴权:Bearer Token
请求头:
Authorization: Bearer <access_token>
Accept: application/json
请求参数:无
成功响应(200 OK):
{
"err": { "ec": 0, "dm": "ok" },
"ret": [
{ "code_name": "wander", "name": "人员徘徊" },
{ "code_name": "intrusion", "name": "入侵" },
{ "code_name": "no_reflective_clothing", "name": "未佩戴反光衣" }
]
}
| 返回字段 | 类型 | 说明 |
|---|---|---|
ret[] |
array |
算法列表(无分页包装) |
ret[].code_name |
string |
算法编码(如 wander) |
ret[].name |
string |
算法中文名称(如 人员徘徊) |
5.2 算法映射表
interface AlgorithmItem {
code_name: string; // 算法编码(如 "wander")
name: string; // 算法中文名称(如 "人员徘徊")
}
登录时自动拉取并构建 Map<code_name, name> 映射,供全局以编码查中文名。
6. WebSocket 接口
6.1 事件监听通道 WebSocket
- 地址:
ws://192.168.28.32:8080/ws/event - 代理地址(Vite 开发环境):
/ws/event
6.2 推送消息格式
{
"id": 90908,
"camera_id": 1,
"started_at": "2026-04-01T09:30:00Z",
"ended_at": "2026-04-01T09:30:10Z",
"types": "wander",
"status": "pending",
"camera": { "id": 1, "name": "421枪机" },
"mediums": [ { "id": 109656, "name": "snapshot", "file": "http://192.168.28.32:8000/media/mediums/xxx.jpg" } ]
}
6.3 视频流 WebSocket
- 地址:
ws://{host}:{dynamicPort}/ - 说明:由
startCameraStream返回动态端口,JSMpeg 直接连接播放
7. 通用响应格式
7.1 成功响应
{
"err": {
"ec": 0,
"dm": "ok"
},
"ret": { /* 响应数据 */ }
}
| 字段 | 类型 | 说明 |
|---|---|---|
err.ec |
number |
错误码,0 表示成功 |
err.dm |
string |
状态描述,成功时为 "ok" |
ret |
object / array |
返回的数据主体 |
7.2 错误响应
{
"err": {
"ec": 1001,
"dm": "错误描述信息"
}
}
7.3 常见错误码
| 错误码 | 说明 |
|---|---|
0 |
成功 |
1001 |
参数错误 |
1002 |
认证失败 |
1003 |
权限不足 |
1004 |
资源不存在 |
1005 |
操作失败 |
7.4 HTTP 状态码
| 状态码 | 说明 | 前端处理 |
|---|---|---|
200 OK |
请求成功 | 正常处理 |
201 Created |
POST 创建成功 | 正常处理 |
204 No Content |
DELETE / 无业务数据 PATCH | 视作成功 |
400 Bad Request |
参数错误 | 提示错误信息 |
401 Unauthorized |
未授权 / Token 过期 | 清除 Token,跳转登录页 |
403 Forbidden |
权限不足 | 提示无权限 |
404 Not Found |
资源不存在 | 提示未找到 |
500 Internal Server Error |
服务器内部错误 | 提示服务器错误 |
8. 认证与 Token 管理
8.1 Token 有效期
- Token 有效期:24 小时
- 前端每 30 分钟 检查一次 Token 是否过期
- 过期后自动清除 Token 并跳转到登录页
8.2 请求头格式
Authorization: Bearer <token>
Content-Type: application/json
Accept: application/json
8.3 拦截器行为
- 请求拦截:每次请求前检查 Token 是否过期(
checkTokenExpiry) - 响应拦截:收到
401状态码时自动清除 Token 并跳转登录
9. 前端数据转换说明
9.1 URL 规范化
后端返回的 JSON 中包含内部地址(如 http://127.0.0.1:8000/media/...),前端自动转换为:
http://127.0.0.1:8000/xxx→http://<实际服务器IP>:8000/xxxhttp://localhost:8000/xxx→http://<实际服务器IP>:8000/xxx
适用字段:
mediums[].file(事件图片)camera.snapshot(摄像头快照)- 顶层
snapshot/file next/previous分页链接
9.2 分页结构
所有列表接口统一分页格式:
{
count: number, // 总条数
next: string|null, // 下一页 URL
previous: string|null, // 上一页 URL
results: T[] // 当前页数据
}
10. 完整调用示例
10.1 登录并获取事件列表
import { BoxApi } from '@/utils/boxApi';
const api = new BoxApi();
// 登录
const token = await api.login('admin', 'password');
// 获取事件(第1页,每页20条)
const { tableData, totalItems } = await api.getEvents(token, 20, 1);
// 按条件筛选
const { results, count } = await api.getEventsByParams(
token, 20, 1,
'2026-04-01T00:00:00Z', '2026-04-02T00:00:00Z',
'wander', null, 'pending'
);
// 获取所有摄像头
const cameras = await api.getAllCameras(token);
// 更新事件状态
await api.setEventStatus(90908, 'closed', '已处理', token);
// 删除事件
await api.delEvents(token, [90908, 90909]);
10.2 摄像头管理
// 获取单个摄像头详情(含规则)
const camera = await api.getCameraById(token, 1);
// 更新摄像头基本设置
await api.updateCamera(token, 1, { name: '421枪机', mode: 'on' });
// 批量更新规则
await api.updateRule(token, [
{ id: 1, camera: 1, name: '徘徊', mode: 'on' },
{ id: 32, camera: 1, name: '入侵', mode: 'schedule', schedule: { type: 'daily', time_slots: [[480, 720]] } }
]);
// 启动视频流
const { port } = await api.startCameraStream(token, 1);
// 停止视频流
await api.stopCameraStream(token, 1);
11. 附录:前端 API 方法速查表
| 方法 | HTTP 方法 | 路径 | 请求体/参数 | 响应体 |
|---|---|---|---|---|
login() |
POST | /auth/login |
{username, password, cookieless} |
{token} |
logout() |
POST | /auth/logout |
无 | {} |
addUser() |
POST | /auth/adduser |
{username, password, email?} |
{} |
rmUser() |
POST | /auth/rmuser |
{username} |
{} |
getAllUsers() |
GET | /auth/allusers |
— | {users: [...]} |
resetUser() |
POST | /auth/resetuser |
{username, password, email} |
{} |
getEvents() |
GET | /events?limit=&offset= |
— | {count, next, prev, results} |
getEventsByParams() |
GET | /events?limit=&offset=&... |
— | {count, next, prev, results} |
getEventsByUrl() |
GET | 自定义 URL | — | {count, next, prev, results} |
getEventById() |
GET | /event/events/retrieves?id= |
— | {objects: [EventItem]} |
getOneEvent() |
GET | /events?limit=1&offset=0 |
— | {count, next, prev, results} |
setEventStatus() |
PATCH | /events/{id} |
{status, remark?} |
{} |
delEvents() |
DELETE | /event/events/{id} |
无 | [{id, success, message?}] |
getCameras() |
GET | /cameras?limit=&offset= |
— | {count, results: [...]} |
getCamerasByUrl() |
GET | 自定义 URL | — | {count, results: [...]} |
getAllCameras() |
GET | /camera/cameras/get_all |
— | CameraItem[] |
getCameraById() |
GET | /camera/cameras/{id} |
— | CameraItem |
updateCamera() |
PATCH | /camera/cameras/{id} |
{name, mode} |
CameraItem |
startCameraStream() |
POST | /camera/cameras/{id}/start_stream |
无 | {port} |
stopCameraStream() |
POST | /camera/cameras/{id}/stop_stream |
无 | {} |
updateRule() |
PATCH | /rules/{id} |
{id, camera, name?, mode?, schedule?} |
RuleItem |
getAlgorithms() |
GET | /algorithms |
— | AlgorithmItem[] |
getAlgorithmName() |
— | 本地映射 | code_name: string |
string(中文名) |