from fastapi import APIRouter, Depends from sqlalchemy.orm import Session from typing import List, Optional from db.models import get_db from services.sync_service import get_sync_service router = APIRouter(prefix="/api/sync", tags=["同步"]) @router.get("/status") def get_sync_status(db: Session = Depends(get_db)): """获取同步服务状态""" from sqlalchemy import text service = get_sync_service() status = service.get_status() pending_cameras = db.execute( text("SELECT COUNT(*) FROM cameras WHERE pending_sync = 1") ).scalar() or 0 pending_rois = db.execute( text("SELECT COUNT(*) FROM rois WHERE pending_sync = 1") ).scalar() or 0 pending_alarms = db.execute( text("SELECT COUNT(*) FROM alarms WHERE upload_status = 'pending' OR upload_status = 'retry'") ).scalar() or 0 return { "running": status["running"], "cloud_enabled": status["cloud_enabled"], "network_status": status["network_status"], "device_id": status["device_id"], "pending_sync": pending_cameras + pending_rois, "pending_alarms": pending_alarms, "details": { "pending_cameras": pending_cameras, "pending_rois": pending_rois, "pending_alarms": pending_alarms } } @router.get("/pending") def get_pending_syncs(db: Session = Depends(get_db)): """获取待同步项列表""" from sqlalchemy import text from db.models import Camera, ROI, Alarm pending_cameras = db.query(Camera).filter(Camera.pending_sync == True).all() pending_rois = db.query(ROI).filter(ROI.pending_sync == True).all() from db.session import SessionLocal temp_db = SessionLocal() try: pending_alarms = temp_db.query(Alarm).filter( Alarm.upload_status.in_(['pending', 'retry']) ).limit(100).all() finally: temp_db.close() return { "cameras": [{"id": c.id, "name": c.name} for c in pending_cameras], "rois": [{"id": r.id, "name": r.name, "camera_id": r.camera_id} for r in pending_rois], "alarms": [{"id": a.id, "camera_id": a.camera_id, "type": a.event_type} for a in pending_alarms] } @router.post("/trigger") def trigger_sync(): """手动触发同步""" service = get_sync_service() from db.session import SessionLocal from db.crud import get_all_cameras, get_all_rois from db.models import Camera, ROI db = SessionLocal() try: cameras = get_all_cameras(db) for camera in cameras: service.queue_camera_sync(camera.id, 'update', { 'name': camera.name, 'rtsp_url': camera.rtsp_url, 'enabled': camera.enabled }) db.query(Camera).filter(Camera.id == camera.id).update({'pending_sync': False}) db.commit() rois = get_all_rois(db) for roi in rois: service.queue_roi_sync(roi.id, 'update', { 'name': roi.name, 'roi_type': roi.roi_type, 'points': roi.points, 'enabled': roi.enabled }) db.query(ROI).filter(ROI.id == roi.id).update({'pending_sync': False}) db.commit() return {"message": "同步任务已加入队列", "count": len(cameras) + len(rois)} finally: db.close() @router.post("/clear-failed") def clear_failed_syncs(db: Session = Depends(get_db)): """清除失败的同步标记""" from sqlalchemy import text db.execute(text("UPDATE cameras SET pending_sync = 0, sync_failed_at = NULL, sync_retry_count = 0")) db.execute(text("UPDATE rois SET pending_sync = 0, sync_failed_at = NULL, sync_retry_count = 0")) db.commit() return {"message": "已清除所有失败的同步标记"}