""" 告警管理 API 路由 """ from typing import Annotated, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from app.schemas import ( AlertCreate, AlertResponse, AlertUpdate, ResponseData ) from app.services.alert_service import AlertService from app.api.v1.auth import get_current_user from app.models import User from app.db.init_db import get_sqlite_db router = APIRouter() @router.post("", response_model=ResponseData) async def create_alert( request: AlertCreate, current_user: Annotated[User, Depends(get_current_user)], db: Session = Depends(get_sqlite_db) ): """ 创建价格告警 - **symbol**: 品种代码 - **condition_type**: 条件类型 (greater_than, less_than, equals) - **condition_value**: 条件值 - **alert_type**: 告警类型 (price, percent_change) """ alert = AlertService.create_alert( user_id=current_user.id, symbol=request.symbol, condition_type=request.condition_type, condition_value=request.condition_value, alert_type=request.alert_type ) return ResponseData( code=0, message="success", data={ "id": alert.id, "symbol": alert.symbol, "condition_type": alert.condition_type, "condition_value": float(alert.condition_value), "alert_type": alert.alert_type, "status": alert.status, "created_at": alert.created_at.isoformat() } ) @router.get("", response_model=ResponseData) async def list_alerts( status: Annotated[Optional[str], Query(description="告警状态")] = None, current_user: Annotated[User, Depends(get_current_user)] = None, db: Session = Depends(get_sqlite_db) ): """获取用户告警列表""" alerts = AlertService.get_user_alerts(current_user.id, status) return ResponseData( code=0, message="success", data=[ { "id": a.id, "symbol": a.symbol, "condition_type": a.condition_type, "condition_value": float(a.condition_value), "alert_type": a.alert_type, "status": a.status, "triggered_at": a.triggered_at.isoformat() if a.triggered_at else None, "created_at": a.created_at.isoformat(), "updated_at": a.updated_at.isoformat() } for a in alerts ] ) @router.get("/{alert_id}", response_model=ResponseData) async def get_alert( alert_id: int, current_user: Annotated[User, Depends(get_current_user)] ): """获取告警详情""" alert = AlertService.get_alert_by_id(alert_id, current_user.id) if not alert: raise HTTPException( status_code=404, detail="Alert not found" ) return ResponseData( code=0, message="success", data={ "id": alert.id, "symbol": alert.symbol, "condition_type": alert.condition_type, "condition_value": float(alert.condition_value), "alert_type": alert.alert_type, "status": alert.status, "triggered_at": alert.triggered_at.isoformat() if alert.triggered_at else None, "created_at": alert.created_at.isoformat(), "updated_at": alert.updated_at.isoformat() } ) @router.put("/{alert_id}", response_model=ResponseData) async def update_alert( alert_id: int, request: AlertUpdate, current_user: Annotated[User, Depends(get_current_user)] ): """更新告警""" alert = AlertService.update_alert( alert_id=alert_id, user_id=current_user.id, condition_value=request.condition_value, status=request.status ) if not alert: raise HTTPException( status_code=404, detail="Alert not found" ) return ResponseData( code=0, message="success", data={ "id": alert.id, "symbol": alert.symbol, "condition_type": alert.condition_type, "condition_value": float(alert.condition_value), "alert_type": alert.alert_type, "status": alert.status, "updated_at": alert.updated_at.isoformat() } ) @router.delete("/{alert_id}", response_model=ResponseData) async def delete_alert( alert_id: int, current_user: Annotated[User, Depends(get_current_user)] ): """删除告警""" success = AlertService.delete_alert(alert_id, current_user.id) if not success: raise HTTPException( status_code=404, detail="Alert not found" ) return ResponseData( code=0, message="success", data={"id": alert_id, "status": "deleted"} ) @router.post("/{alert_id}/trigger", response_model=ResponseData) async def trigger_alert( alert_id: int, current_user: Annotated[User, Depends(get_current_user)] ): """手动触发告警 (测试用)""" alert = AlertService.trigger_alert(alert_id) if not alert: raise HTTPException( status_code=404, detail="Alert not found" ) return ResponseData( code=0, message="success", data={ "id": alert.id, "status": alert.status, "triggered_at": alert.triggered_at.isoformat() } )