13 KiB
13 KiB
AI 告警平台与芋道前端对接文档
本文档指导如何在芋道前端项目(yudao-ui-admin-vben)中集成告警平台功能。
一、项目概述
1.1 告警平台后端
- 技术栈: FastAPI + SQLite + 阿里云 OSS
- 职责: 接收边缘端告警、存储告警证据、提供 REST API
- 端口: 8000
1.2 芋道前端
- 技术栈: Vue 3 + Vben Admin + Ant Design Vue
- 职责: 告警列表展示、详情查看、人工处理
- 复用: 用户体系、权限管理、页面布局
二、后端 API 接口
2.1 基础信息
- Base URL:
http://localhost:8000 - 文档地址:
http://localhost:8000/docs
2.2 接口列表
2.2.1 健康检查
GET /health
响应:
{
"status": "healthy",
"database": "healthy"
}
2.2.2 创建告警(边缘端调用)
POST /api/v1/alerts
Content-Type: multipart/form-data
请求参数:
data(FormField): JSON 字符串{ "camera_id": "cam-001", "roi_id": "roi-01", "alert_type": "leave_post", "algorithm": "LeavePostAlgorithm", "confidence": 85, "duration_minutes": 5, "trigger_time": "2024-01-20T10:30:00Z", "message": "离岗告警" }snapshot(File, 可选): 告警抓拍图片
响应:
{
"id": 1,
"alert_no": "ALT20240120103000ABC12345",
"camera_id": "cam-001",
"roi_id": "roi-01",
"alert_type": "leave_post",
"algorithm": "LeavePostAlgorithm",
"confidence": 85,
"duration_minutes": 5,
"trigger_time": "2024-01-20T10:30:00Z",
"message": "离岗告警",
"snapshot_url": "https://your-bucket.oss-cn-hangzhou.aliyuncs.com/alerts/xxx.jpg",
"status": "pending",
"created_at": "2024-01-20T10:30:00Z"
}
2.2.3 查询告警列表
GET /api/v1/alerts
查询参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| cameraId | string | 否 | 摄像头ID |
| alertType | string | 否 | 告警类型 |
| status | string | 否 | 处理状态 |
| startTime | datetime | 否 | 开始时间 |
| endTime | datetime | 否 | 结束时间 |
| page | int | 否 | 页码,默认1 |
| pageSize | int | 否 | 每页条数,默认20 |
响应:
{
"alerts": [...],
"total": 100,
"page": 1,
"pageSize": 20
}
2.2.4 获取告警详情
GET /api/v1/alerts/{alertId}
2.2.5 处理告警
PUT /api/v1/alerts/{alertId}/handle
请求体:
{
"status": "confirmed",
"remark": "确认为真实告警"
}
状态枚举: pending | confirmed | ignored | resolved
2.2.6 获取告警统计
GET /api/v1/alerts/statistics
响应:
{
"total": 100,
"pending": 10,
"confirmed": 50,
"ignored": 20,
"resolved": 20,
"by_type": {
"leave_post": 80,
"intrusion": 20
}
}
三、芋道前端集成步骤
3.1 创建 API 文件
在 apps/web-antd/src/api/ 目录下创建 alert 目录,并添加 alert.ts:
import { requestClient } from '#/api/request';
export namespace AlertApi {
export interface Alert {
id: number;
alertNo: string;
cameraId: string;
roiId?: string;
alertType: string;
algorithm?: string;
confidence?: number;
durationMinutes?: number;
triggerTime: string;
message?: string;
snapshotUrl?: string;
status: 'pending' | 'confirmed' | 'ignored' | 'resolved';
handleRemark?: string;
handledBy?: string;
handledAt?: string;
aiAnalysis?: Record<string, any>;
createdAt: string;
updatedAt: string;
}
export interface AlertListParams {
pageNo: number;
pageSize: number;
cameraId?: string;
alertType?: string;
status?: string;
startTime?: string;
endTime?: string;
}
export interface AlertListResponse {
alerts: Alert[];
total: number;
page: number;
pageSize: number;
}
export interface AlertStatistics {
total: number;
pending: number;
confirmed: number;
ignored: number;
resolved: number;
by_type: Record<string, number>;
}
export interface HandleAlertRequest {
status: 'confirmed' | 'ignored' | 'resolved';
remark?: string;
}
}
export function getAlertList(params: AlertApi.AlertListParams) {
return requestClient.get<AlertApi.AlertListResponse>('/api/v1/alerts', {
params,
});
}
export function getAlertDetail(alertId: number) {
return requestClient.get<AlertApi.Alert>(`/api/v1/alerts/${alertId}`);
}
export function handleAlert(alertId: number, data: AlertApi.HandleAlertRequest) {
return requestClient.put<AlertApi.Alert>(`/api/v1/alerts/${alertId}/handle`, data, {
params: { handledBy: 'currentUser' },
});
}
export function getAlertStatistics() {
return requestClient.get<AlertApi.AlertStatistics>('/api/v1/alerts/statistics');
}
3.2 创建路由配置
在 apps/web-antd/src/router/routes/modules/ 下创建 alert.ts:
import type { RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [
{
path: '/alert',
name: 'AlertCenter',
meta: {
title: '告警中心',
icon: 'lucide:bell',
keepAlive: true,
},
children: [
{
path: 'list',
name: 'AlertList',
meta: {
title: '告警列表',
noCache: true,
},
component: () => import('#/views/alert/list/index.vue'),
},
],
},
];
export default routes;
将此路由添加到主路由配置中(编辑 apps/web-antd/src/router/routes/modules/ 下的 dashboard.ts 或其他菜单配置)。
3.3 创建页面组件
在 apps/web-antd/src/views/ 下创建 alert/list/ 目录:
data.ts:
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { getRangePickerDefaultProps } from '#/utils';
export function useAlertFormSchema(): VbenFormSchema[] {
return [
{ fieldName: 'cameraId', label: '摄像头ID', component: 'Input', componentProps: { placeholder: '请输入摄像头ID', allowClear: true } },
{ fieldName: 'alertType', label: '告警类型', component: 'Input', componentProps: { placeholder: '请输入告警类型', allowClear: true } },
{
fieldName: 'status',
label: '处理状态',
component: 'Select',
componentProps: {
options: [
{ label: '待处理', value: 'pending' },
{ label: '已确认', value: 'confirmed' },
{ label: '已忽略', value: 'ignored' },
{ label: '已解决', value: 'resolved' },
],
placeholder: '请选择处理状态',
allowClear: true,
},
},
{ fieldName: 'createTime', label: '创建时间', component: 'RangePicker', componentProps: { ...getRangePickerDefaultProps(), allowClear: true } },
];
}
export function useAlertColumns(): VxeTableGridOptions['columns'] {
return [
{ type: 'checkbox', width: 40 },
{ field: 'id', title: '编号', minWidth: 80 },
{ field: 'alertNo', title: '告警编号', minWidth: 150 },
{ field: 'cameraId', title: '摄像头', minWidth: 100 },
{ field: 'alertType', title: '告警类型', minWidth: 100 },
{ field: 'algorithm', title: '算法', minWidth: 120 },
{ field: 'confidence', title: '置信度', minWidth: 80, slots: { default: 'confidence' } },
{ field: 'durationMinutes', title: '离岗时长', minWidth: 100, slots: { default: 'duration' } },
{ field: 'status', title: '状态', minWidth: 100, slots: { default: 'status' } },
{ field: 'createdAt', title: '创建时间', minWidth: 180, formatter: 'formatDateTime' },
{ title: '操作', width: 150, fixed: 'right', slots: { default: 'actions' } },
];
}
index.vue:
参考芋道现有的 IoT 告警页面 apps/web-antd/src/views/iot/alert/record/index.vue 进行修改。
四、边缘端对接示例
4.1 Python (ai_edge 项目)
在 ai_edge 项目的 main.py 中添加告警上报功能:
import requests
from datetime import datetime
class AlertReporter:
ALERT_PLATFORM_URL = "http://localhost:8000/api/v1/alerts"
def report_alert(
self,
camera_id: str,
roi_id: str,
alert_type: str,
algorithm: str,
confidence: float,
duration_minutes: int,
message: str,
screenshot: bytes,
):
alert_data = {
"camera_id": camera_id,
"roi_id": roi_id,
"alert_type": alert_type,
"algorithm": algorithm,
"confidence": int(confidence * 100),
"duration_minutes": duration_minutes,
"trigger_time": datetime.utcnow().isoformat() + "Z",
"message": message,
}
files = {
"snapshot": ("alert.jpg", screenshot, "image/jpeg"),
"data": (None, json.dumps(alert_data), "application/json"),
}
response = requests.post(self.ALERT_PLATFORM_URL, files=files)
response.raise_for_status()
return response.json()
4.2 在推理服务中调用
在 EdgeInferenceService._handle_detections 方法中调用:
def _handle_detections(self, camera_id: str, roi, frame: VideoFrame, alerts: list):
for alert in alerts:
# 上报到云端告警平台
self._reporter.report_to_platform(
camera_id=camera_id,
roi_id=roi.roi_id,
alert_type=alert.get("alert_type"),
algorithm="LeavePostAlgorithm",
confidence=alert.get("confidence", 1.0),
duration_minutes=alert.get("duration_minutes", 0),
message=alert.get("message", ""),
screenshot=frame.image,
)
五、阿里云 OSS 配置
5.1 配置项
在告警平台的 .env 文件中配置:
OSS_ACCESS_KEY_ID=your_access_key_id
OSS_ACCESS_KEY_SECRET=your_access_key_secret
OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com
OSS_BUCKET_NAME=your_bucket_name
OSS_URL_PREFIX=https://your-bucket-name.oss-cn-hangzhou.aliyuncs.com
5.2 权限要求
OSS Bucket 需要配置以下权限:
- CORS: 允许前端跨域访问
- 公共读: 告警图片需要可以公开访问
六、大模型分析配置(可选)
6.1 配置项
AI_MODEL_ENDPOINT=http://localhost:8001
AI_MODEL_API_KEY=your_api_key
6.2 大模型 API 格式
告警平台期望大模型服务提供以下接口:
POST /analyze
Content-Type: application/json
{
"alert_id": 1,
"snapshot_url": "https://xxx/alert.jpg",
"alert_info": {
"camera_id": "cam-001",
"roi_id": "roi-01",
"alert_type": "leave_post",
"confidence": 85,
"duration_minutes": 5
}
}
响应格式:
{
"risk_level": "HIGH",
"description": "检测到人员在非工作区域长时间停留,建议现场核实",
"suggestion": "可能是误报,建议确认监控区域工作安排",
"confidence_score": 0.92
}
七、部署说明
7.1 后端部署
# 1. 安装依赖
pip install -r requirements.txt
# 2. 配置环境变量
cp .env.example .env
# 编辑 .env 文件
# 3. 启动服务
python -m app.main
7.2 使用 Gunicorn 生产部署
gunicorn app.main:app -k uvicorn.workers.UvicornWorker -w 4 -b 0.0.0.0:8000
7.3 Docker 部署
创建 Dockerfile:
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "-m", "app.main"]
八、注意事项
- 芋道项目权限: 告警相关接口需要芋道后端配合实现用户认证
- 跨域配置: 告警平台需要配置 CORS 以允许芋道前端访问
- 图片存储: 阿里云 OSS 需要配置 CORS 允许前端直接访问图片
- 时区处理: 建议统一使用 UTC 时间,前端展示时转换为本地时间
- 大模型服务: AI 分析功能可选,需要部署大模型服务支持
九、目录结构总结
# 告警平台后端
alert_platform/
├── app/
│ ├── main.py # FastAPI 入口
│ ├── config.py # 配置
│ ├── models.py # SQLAlchemy 模型
│ ├── schemas.py # Pydantic 模型
│ ├── services/
│ │ ├── alert_service.py # 告警业务逻辑
│ │ ├── oss_storage.py # OSS 存储
│ │ └── ai_analyzer.py # AI 分析
│ └── utils/
│ └── logger.py # 日志
├── data/ # SQLite 数据库
├── uploads/ # 本地临时存储
├── requirements.txt
├── .env.example
└── README.md
# 芋道前端需要创建的文件
yudao-ui-admin-vben/
└── apps/web-antd/src/
├── api/
│ └── alert/
│ └── alert.ts # 告警 API
├── router/routes/modules/
│ └── alert.ts # 告警路由
└── views/alert/
└── list/
├── data.ts # 列表配置
└── index.vue # 列表页面