feat(alarm): add alarm snapshot viewing functionality
This commit is contained in:
@@ -24,6 +24,10 @@ const Dashboard: React.FC = () => {
|
|||||||
const [recentAlerts, setRecentAlerts] = useState<Alert[]>([]);
|
const [recentAlerts, setRecentAlerts] = useState<Alert[]>([]);
|
||||||
const [cameraStatus, setCameraStatus] = useState<any[]>([]);
|
const [cameraStatus, setCameraStatus] = useState<any[]>([]);
|
||||||
|
|
||||||
|
const handleViewSnapshot = (alert: Alert) => {
|
||||||
|
window.open(`/api/alarms/${alert.id}/snapshot`, '_blank');
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchStats();
|
fetchStats();
|
||||||
fetchAlerts();
|
fetchAlerts();
|
||||||
@@ -139,7 +143,7 @@ const Dashboard: React.FC = () => {
|
|||||||
description={formatTime(alert.created_at)}
|
description={formatTime(alert.created_at)}
|
||||||
/>
|
/>
|
||||||
{alert.snapshot_path && (
|
{alert.snapshot_path && (
|
||||||
<Button type="link" size="small">
|
<Button type="link" size="small" onClick={() => handleViewSnapshot(alert)}>
|
||||||
查看截图
|
查看截图
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|||||||
21
logs/app.log
21
logs/app.log
@@ -218,3 +218,24 @@
|
|||||||
2026-01-21 14:41:27,191 - security_monitor - INFO - 启动安保异常行为识别系统
|
2026-01-21 14:41:27,191 - security_monitor - INFO - 启动安保异常行为识别系统
|
||||||
2026-01-21 14:41:27,205 - security_monitor - INFO - 数据库初始化完成
|
2026-01-21 14:41:27,205 - security_monitor - INFO - 数据库初始化完成
|
||||||
2026-01-21 14:41:39,701 - security_monitor - INFO - 推理Pipeline启动,活跃摄像头数: 2
|
2026-01-21 14:41:39,701 - security_monitor - INFO - 推理Pipeline启动,活跃摄像头数: 2
|
||||||
|
2026-01-21 15:03:14,674 - security_monitor - INFO - 启动安保异常行为识别系统
|
||||||
|
2026-01-21 15:03:14,688 - security_monitor - INFO - 数据库初始化完成
|
||||||
|
2026-01-21 15:03:27,230 - security_monitor - INFO - 推理Pipeline启动,活跃摄像头数: 2
|
||||||
|
2026-01-21 15:06:28,976 - security_monitor - INFO - 启动安保异常行为识别系统
|
||||||
|
2026-01-21 15:06:28,990 - security_monitor - INFO - 数据库初始化完成
|
||||||
|
2026-01-21 15:06:41,537 - security_monitor - INFO - 推理Pipeline启动,活跃摄像头数: 2
|
||||||
|
2026-01-21 15:06:41,539 - security_monitor - INFO - 正在关闭系统...
|
||||||
|
2026-01-21 15:06:49,686 - security_monitor - INFO - 系统已关闭
|
||||||
|
2026-01-21 15:07:27,870 - security_monitor - INFO - 启动安保异常行为识别系统
|
||||||
|
2026-01-21 15:07:27,884 - security_monitor - INFO - 数据库初始化完成
|
||||||
|
2026-01-21 15:07:40,380 - security_monitor - INFO - 推理Pipeline启动,活跃摄像头数: 2
|
||||||
|
2026-01-21 15:07:58,160 - security_monitor - INFO - 正在关闭系统...
|
||||||
|
2026-01-21 15:07:58,299 - security_monitor - INFO - 系统已关闭
|
||||||
|
2026-01-21 15:08:28,521 - security_monitor - INFO - 启动安保异常行为识别系统
|
||||||
|
2026-01-21 15:08:28,533 - security_monitor - INFO - 数据库初始化完成
|
||||||
|
2026-01-21 15:08:41,019 - security_monitor - INFO - 推理Pipeline启动,活跃摄像头数: 2
|
||||||
|
2026-01-21 15:09:16,894 - security_monitor - INFO - 正在关闭系统...
|
||||||
|
2026-01-21 15:09:17,139 - security_monitor - INFO - 系统已关闭
|
||||||
|
2026-01-21 15:09:41,042 - security_monitor - INFO - 启动安保异常行为识别系统
|
||||||
|
2026-01-21 15:09:41,055 - security_monitor - INFO - 数据库初始化完成
|
||||||
|
2026-01-21 15:09:53,555 - security_monitor - INFO - 推理Pipeline启动,活跃摄像头数: 2
|
||||||
|
|||||||
22
main.py
22
main.py
@@ -11,11 +11,14 @@ os.environ["TENSORRT_DISABLE_MYELIN"] = "1"
|
|||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from fastapi import FastAPI, HTTPException
|
from fastapi import FastAPI, HTTPException, Depends
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.responses import FileResponse, StreamingResponse
|
from fastapi.responses import FileResponse, StreamingResponse
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
from prometheus_client import start_http_server
|
from prometheus_client import start_http_server
|
||||||
|
|
||||||
|
from db.models import get_db
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
from ultralytics.engine.results import Boxes as UltralyticsBoxes
|
from ultralytics.engine.results import Boxes as UltralyticsBoxes
|
||||||
@@ -144,6 +147,23 @@ async def get_snapshot_base64(camera_id: int):
|
|||||||
return {"image": base64.b64encode(buffer).decode("utf-8")}
|
return {"image": base64.b64encode(buffer).decode("utf-8")}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/alarms/{alarm_id}/snapshot")
|
||||||
|
async def get_alarm_snapshot(alarm_id: int, db: Session = Depends(get_db)):
|
||||||
|
from db.models import Alarm
|
||||||
|
|
||||||
|
alarm = db.query(Alarm).filter(Alarm.id == alarm_id).first()
|
||||||
|
if not alarm:
|
||||||
|
raise HTTPException(status_code=404, detail="告警不存在")
|
||||||
|
|
||||||
|
if not alarm.snapshot_path:
|
||||||
|
raise HTTPException(status_code=404, detail="该告警没有截图")
|
||||||
|
|
||||||
|
if not os.path.exists(alarm.snapshot_path):
|
||||||
|
raise HTTPException(status_code=404, detail="截图文件不存在")
|
||||||
|
|
||||||
|
return FileResponse(alarm.snapshot_path, media_type="image/jpeg")
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/camera/{camera_id}/detect")
|
@app.get("/api/camera/{camera_id}/detect")
|
||||||
async def get_detection_with_overlay(camera_id: int):
|
async def get_detection_with_overlay(camera_id: int):
|
||||||
pipeline = get_pipeline()
|
pipeline = get_pipeline()
|
||||||
|
|||||||
Reference in New Issue
Block a user