Files
turing_alert_web/接口文档.md
2026-06-10 11:46:45 +08:00

1187 lines
27 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 告警管理系统 API 接口文档Django 版)
> 基础路径:`/api/v1`
> 服务器地址:`http://192.168.28.32:8000`
> 认证方式Bearer Token24h 有效期)
> 统一响应信封:`{ "err": { "ec": 0, "dm": "ok" }, "ret": <data> }`
---
## 目录
1. [认证接口](#1-认证接口)
2. [事件(告警)接口](#2-事件告警接口)
3. [摄像头接口](#3-摄像头接口)
4. [规则接口](#4-规则接口)
5. [算法接口](#5-算法接口)
6. [WebSocket 接口](#6-websocket-接口)
7. [通用响应格式](#7-通用响应格式)
8. [认证与 Token 管理](#8-认证与-token-管理)
9. [前端数据转换说明](#9-前端数据转换说明)
10. [完整调用示例](#10-完整调用示例)
11. [附录:前端 API 方法速查表](#11-附录前端-api-方法速查表)
---
## 1. 认证接口
---
### 1.1 登录
- **方法**`POST`
- **路径**`/auth/login`
- **描述**:用户登录,获取 Token
- **鉴权**:无(公开)
**请求头**
```http
Content-Type: application/json
Accept: application/json
```
**请求体Body JSON**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `username` | `string` | 是 | 用户名 |
| `password` | `string` | 是 | 密码 |
| `cookieless` | `string` | 是 | `"True"``"False"` |
```json
{
"username": "admin",
"password": "123456",
"cookieless": "False"
}
```
**成功响应200 OK**
```json
{
"err": { "ec": 0, "dm": "ok" },
"ret": {
"token": "eyJhbGciOiJIUzI1NiIs..."
}
}
```
| 返回字段 | 类型 | 说明 |
|---------|------|------|
| `ret.token` | `string` | JWT Token有效期 24h |
**失败响应**
```json
{
"err": { "ec": 1001, "dm": "用户名或密码错误" }
}
```
---
### 1.2 登出
- **方法**`POST`
- **路径**`/auth/logout`
- **鉴权**Bearer Token
**请求头**
```http
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
```
**请求体**:无
**成功响应200 OK**
```json
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
```
---
### 1.3 添加用户
- **方法**`POST`
- **路径**`/auth/adduser`
- **鉴权**Bearer Token需管理员权限
**请求头**
```http
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
```
**请求体Body JSON**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `username` | `string` | 是 | 用户名 |
| `password` | `string` | 是 | 密码 |
| `email` | `string` | 否 | 邮箱,默认为空 |
```json
{
"username": "operator1",
"password": "pass123456",
"email": ""
}
```
**成功响应200 OK**
```json
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
```
---
### 1.4 删除用户
- **方法**`POST`
- **路径**`/auth/rmuser`
- **鉴权**Bearer Token需管理员权限
**请求头**
```http
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
```
**请求体Body JSON**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `username` | `string` | 是 | 要删除的用户名 |
```json
{
"username": "operator1"
}
```
**成功响应200 OK**
```json
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
```
---
### 1.5 获取所有用户
- **方法**`GET`
- **路径**`/auth/allusers`
- **鉴权**Bearer Token需管理员权限
**请求头**
```http
Authorization: Bearer <access_token>
Accept: application/json
```
**请求参数**:无
**成功响应200 OK**
```json
{
"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需管理员权限
**请求头**
```http
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
```
**请求体Body JSON**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `username` | `string` | 是 | 用户名 |
| `password` | `string` | 是 | 新密码 |
| `email` | `string` | 是 | 邮箱 |
```json
{
"username": "operator1",
"password": "newpass123",
"email": "op1@example.com"
}
```
**成功响应200 OK**
```json
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
```
---
## 2. 事件(告警)接口
---
### 2.1 获取事件列表(分页)
- **方法**`GET`
- **路径**`/events`
- **鉴权**Bearer Token
**请求头**
```http
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**
```json
{
"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": {}
}
]
}
}
```
**前端返回**
```typescript
{
tableData: EventItem[], // ret.results
totalItems: number // ret.count
}
```
---
### 2.2 按参数筛选事件列表
- **方法**`GET`
- **路径**`/events`
- **鉴权**Bearer Token
**请求头**
```http
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
**请求头**
```http
Authorization: Bearer <access_token>
Accept: application/json
```
**查询参数Query**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `id` | `number` | 是 | 事件 ID |
**请求示例**
```
GET /api/v1/event/events/retrieves?id=90908
Authorization: Bearer <token>
```
**成功响应200 OK**
```json
{
"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
**请求头**
```http
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
```
**路径参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| `eventId` | `number` | 事件 ID |
**请求体Body JSON**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `status` | `string` | 是 | 状态值:`pending` / `closed` |
| `remark` | `string` | 否 | 备注信息 |
```json
{
"status": "closed",
"remark": "已处理完毕"
}
```
**成功响应200 OK**
```json
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
```
---
### 2.6 删除事件
- **方法**`DELETE`
- **路径**`/event/events/{eventId}`
- **鉴权**Bearer Token
**请求头**
```http
Authorization: Bearer <access_token>
Accept: application/json
```
**路径参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| `eventId` | `number` | 事件 ID |
**请求体**:无
**成功响应**`204 No Content`(无 body
**失败响应**(如事件不存在):
```json
{
"err": {
"ec": 404,
"dm": "Not Found",
"em": "Not found."
}
}
```
---
### 2.7 事件对象完整结构EventItem
```typescript
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
**请求头**
```http
Authorization: Bearer <access_token>
Accept: application/json
```
**成功响应200 OK**
```json
{
"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
**请求头**
```http
Authorization: Bearer <access_token>
Accept: application/json
```
**路径参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| `cameraId` | `number` | 摄像头 ID |
**成功响应200 OK**
```json
{
"err": { "ec": 0, "dm": "ok" },
"ret": { /* CameraItem */ }
}
```
---
### 3.3 更新摄像头信息
- **方法**`PATCH`
- **路径**`/camera/cameras/{cameraId}`
- **鉴权**Bearer Token
**请求头**
```http
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
```
**路径参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| `cameraId` | `number` | 摄像头 ID |
**请求体Body JSON**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `name` | `string` | 否 | 摄像头名称 |
| `mode` | `"on"` / `"off"` | 是 | 检测模式 |
```json
{
"name": "421枪机",
"mode": "on"
}
```
**成功响应200 OK**
```json
{
"err": { "ec": 0, "dm": "ok" },
"ret": { /* CameraItem */ }
}
```
---
### 3.4 启动摄像头视频流
- **方法**`POST`
- **路径**`/camera/cameras/{cameraId}/start_stream`
- **鉴权**Bearer Token
**请求头**
```http
Authorization: Bearer <access_token>
Accept: application/json
```
**路径参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| `cameraId` | `number` | 摄像头 ID |
**请求体**:无
**成功响应200 OK**
```json
{
"err": { "ec": 0, "dm": "ok" },
"ret": {
"port": 8094
}
}
```
| 返回字段 | 类型 | 说明 |
|---------|------|------|
| `ret.port` | `number` | 动态分配的 WebSocket 端口,用于 JSMpeg 视频播放 |
---
### 3.5 停止摄像头视频流
- **方法**`POST`
- **路径**`/camera/cameras/{cameraId}/stop_stream`
- **鉴权**Bearer Token
**请求头**
```http
Authorization: Bearer <access_token>
Accept: application/json
```
**路径参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| `cameraId` | `number` | 摄像头 ID |
**请求体**:无
**成功响应200 OK**
```json
{
"err": { "ec": 0, "dm": "ok" },
"ret": {}
}
```
---
### 3.8 摄像头对象完整结构CameraItem
```typescript
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
```typescript
interface CameraData {
id?: number;
name?: string;
mode?: "on" | "off";
rules?: RuleData[] | {};
}
```
---
## 4. 规则接口
---
### 4.1 更新规则
- **方法**`PATCH`
- **路径**`/rules/{ruleId}`
- **鉴权**Bearer Token
**请求头**
```http
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` | 否 | 时间段配置 |
```json
{
"id": 1,
"name": "徘徊",
"mode": "on",
"schedule": {}
}
```
**带时间段的请求**
```json
{
"id": 1,
"name": "未穿反光衣",
"mode": "schedule",
"schedule": {
"type": "daily",
"time_slots": [
[
960,
1020
]
]
}
}
```
**成功响应200 OK**
```json
{
"err": { "ec": 0, "dm": "ok" },
"ret": { /* RuleItem */ }
}
```
---
### 4.2 规则对象完整结构RuleItem
```typescript
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
**请求头**
```http
Authorization: Bearer <access_token>
Accept: application/json
```
**请求参数**:无
**成功响应200 OK**
```json
{
"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 算法映射表
```typescript
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 推送消息格式
```json
{
"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 成功响应
```json
{
"err": {
"ec": 0,
"dm": "ok"
},
"ret": { /* */ }
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `err.ec` | `number` | 错误码,`0` 表示成功 |
| `err.dm` | `string` | 状态描述,成功时为 `"ok"` |
| `ret` | `object` / `array` | 返回的数据主体 |
### 7.2 错误响应
```json
{
"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 请求头格式
```http
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/xxx`
- `http://localhost:8000/xxx``http://<实际服务器IP>:8000/xxx`
适用字段:
- `mediums[].file`(事件图片)
- `camera.snapshot`(摄像头快照)
- 顶层 `snapshot` / `file`
- `next` / `previous` 分页链接
### 9.2 分页结构
所有列表接口统一分页格式:
```typescript
{
count: number, // 总条数
next: string|null, // 下一页 URL
previous: string|null, // 上一页 URL
results: T[] // 当前页数据
}
```
---
## 10. 完整调用示例
### 10.1 登录并获取事件列表
```typescript
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 摄像头管理
```typescript
// 获取单个摄像头详情(含规则)
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`(中文名) |