# 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 健康检查 ```http GET /health ``` **响应**: ```json { "status": "healthy", "database": "healthy" } ``` #### 2.2.2 创建告警(边缘端调用) ```http POST /api/v1/alerts Content-Type: multipart/form-data ``` **请求参数**: - `data` (FormField): JSON 字符串 ```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, 可选): 告警抓拍图片 **响应**: ```json { "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 查询告警列表 ```http GET /api/v1/alerts ``` **查询参数**: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | cameraId | string | 否 | 摄像头ID | | alertType | string | 否 | 告警类型 | | status | string | 否 | 处理状态 | | startTime | datetime | 否 | 开始时间 | | endTime | datetime | 否 | 结束时间 | | page | int | 否 | 页码,默认1 | | pageSize | int | 否 | 每页条数,默认20 | **响应**: ```json { "alerts": [...], "total": 100, "page": 1, "pageSize": 20 } ``` #### 2.2.4 获取告警详情 ```http GET /api/v1/alerts/{alertId} ``` #### 2.2.5 处理告警 ```http PUT /api/v1/alerts/{alertId}/handle ``` **请求体**: ```json { "status": "confirmed", "remark": "确认为真实告警" } ``` **状态枚举**: `pending` | `confirmed` | `ignored` | `resolved` #### 2.2.6 获取告警统计 ```http GET /api/v1/alerts/statistics ``` **响应**: ```json { "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`: ```typescript 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; 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; } export interface HandleAlertRequest { status: 'confirmed' | 'ignored' | 'resolved'; remark?: string; } } export function getAlertList(params: AlertApi.AlertListParams) { return requestClient.get('/api/v1/alerts', { params, }); } export function getAlertDetail(alertId: number) { return requestClient.get(`/api/v1/alerts/${alertId}`); } export function handleAlert(alertId: number, data: AlertApi.HandleAlertRequest) { return requestClient.put(`/api/v1/alerts/${alertId}/handle`, data, { params: { handledBy: 'currentUser' }, }); } export function getAlertStatistics() { return requestClient.get('/api/v1/alerts/statistics'); } ``` ### 3.2 创建路由配置 在 `apps/web-antd/src/router/routes/modules/` 下创建 `alert.ts`: ```typescript 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**: ```typescript 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` 中添加告警上报功能: ```python 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` 方法中调用: ```python 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` 文件中配置: ```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 配置项 ```env AI_MODEL_ENDPOINT=http://localhost:8001 AI_MODEL_API_KEY=your_api_key ``` ### 6.2 大模型 API 格式 告警平台期望大模型服务提供以下接口: ```http 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 } } ``` **响应格式**: ```json { "risk_level": "HIGH", "description": "检测到人员在非工作区域长时间停留,建议现场核实", "suggestion": "可能是误报,建议确认监控区域工作安排", "confidence_score": 0.92 } ``` --- ## 七、部署说明 ### 7.1 后端部署 ```bash # 1. 安装依赖 pip install -r requirements.txt # 2. 配置环境变量 cp .env.example .env # 编辑 .env 文件 # 3. 启动服务 python -m app.main ``` ### 7.2 使用 Gunicorn 生产部署 ```bash gunicorn app.main:app -k uvicorn.workers.UvicornWorker -w 4 -b 0.0.0.0:8000 ``` ### 7.3 Docker 部署 创建 `Dockerfile`: ```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"] ``` --- ## 八、注意事项 1. **芋道项目权限**: 告警相关接口需要芋道后端配合实现用户认证 2. **跨域配置**: 告警平台需要配置 CORS 以允许芋道前端访问 3. **图片存储**: 阿里云 OSS 需要配置 CORS 允许前端直接访问图片 4. **时区处理**: 建议统一使用 UTC 时间,前端展示时转换为本地时间 5. **大模型服务**: 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 # 列表页面 ```