from datetime import date from fastapi import APIRouter, Query, HTTPException, Path from mysql.connector import Error as MySQLError from ds.db import db from encryption.encrypt_decorator import encrypt_response from schema.device_danger_schema import ( DeviceDangerResponse, DeviceDangerListResponse ) from schema.response_schema import APIResponse router = APIRouter( prefix="/api/devices/dangers", tags=["设备管理-危险记录"] ) # 获取危险记录列表 @router.get("/", response_model=APIResponse, summary="获取设备危险记录列表(多条件筛选)") @encrypt_response() async def get_danger_list( page: int = Query(1, ge=1, description="页码、默认第1页"), page_size: int = Query(10, ge=1, le=100, description="每页条数、1-100之间"), client_ip: str = Query(None, max_length=100, description="按设备IP筛选"), danger_type: str = Query(None, max_length=255, alias="type", description="按危险类型筛选"), start_date: date = Query(None, description="按创建时间筛选(开始日期、格式YYYY-MM-DD)"), end_date: date = Query(None, description="按创建时间筛选(结束日期、格式YYYY-MM-DD)") ): conn = None cursor = None try: conn = db.get_connection() cursor = conn.cursor(dictionary=True) # 构建筛选条件 where_clause = [] params = [] if client_ip: where_clause.append("client_ip = %s") params.append(client_ip) if danger_type: where_clause.append("type = %s") params.append(danger_type) if start_date: where_clause.append("DATE(created_at) >= %s") params.append(start_date.strftime("%Y-%m-%d")) if end_date: where_clause.append("DATE(created_at) <= %s") params.append(end_date.strftime("%Y-%m-%d")) # 1. 统计符合条件的总记录数 count_query = "SELECT COUNT(*) AS total FROM device_danger" if where_clause: count_query += " WHERE " + " AND ".join(where_clause) cursor.execute(count_query, params) total = cursor.fetchone()["total"] # 2. 分页查询记录(按创建时间倒序、最新的在前) offset = (page - 1) * page_size list_query = "SELECT * FROM device_danger" if where_clause: list_query += " WHERE " + " AND ".join(where_clause) list_query += " ORDER BY created_at DESC LIMIT %s OFFSET %s" params.extend([page_size, offset]) # 追加分页参数 cursor.execute(list_query, params) danger_list = cursor.fetchall() # 转换为响应模型 return APIResponse( code=200, message="获取危险记录列表成功", data=DeviceDangerListResponse( total=total, dangers=[DeviceDangerResponse(**item) for item in danger_list] ) ) except MySQLError as e: raise HTTPException(status_code=500, detail=f"查询危险记录失败: {str(e)}") from e finally: db.close_connection(conn, cursor) # 获取单个设备的所有危险记录 @router.get("/device/{client_ip}", response_model=APIResponse, summary="获取单个设备的所有危险记录") # @encrypt_response() async def get_device_dangers( client_ip: str = Path(..., max_length=100, description="设备IP地址"), page: int = Query(1, ge=1, description="页码、默认第1页"), page_size: int = Query(10, ge=1, le=100, description="每页条数、1-100之间") ): # 先检查设备是否存在 from service.device_danger_service import check_device_exist if not check_device_exist(client_ip): raise HTTPException(status_code=404, detail=f"IP为 {client_ip} 的设备不存在") conn = None cursor = None try: conn = db.get_connection() cursor = conn.cursor(dictionary=True) # 1. 统计该设备的危险记录总数 count_query = "SELECT COUNT(*) AS total FROM device_danger WHERE client_ip = %s" cursor.execute(count_query, (client_ip,)) total = cursor.fetchone()["total"] # 2. 分页查询该设备的危险记录 offset = (page - 1) * page_size list_query = """ SELECT * FROM device_danger WHERE client_ip = %s ORDER BY created_at DESC LIMIT %s OFFSET %s """ cursor.execute(list_query, (client_ip, page_size, offset)) danger_list = cursor.fetchall() return APIResponse( code=200, message=f"获取设备[{client_ip}]危险记录成功(共{total}条)", data=DeviceDangerListResponse( total=total, dangers=[DeviceDangerResponse(**item) for item in danger_list] ) ) except MySQLError as e: raise HTTPException(status_code=500, detail=f"查询设备[{client_ip}]危险记录失败: {str(e)}") from e finally: db.close_connection(conn, cursor) # ------------------------------ # 根据ID获取单个危险记录详情 # ------------------------------ @router.get("/{danger_id}", response_model=APIResponse, summary="根据ID获取单个危险记录详情") @encrypt_response() async def get_danger_detail( danger_id: int = Path(..., ge=1, description="危险记录ID") ): conn = None cursor = None try: conn = db.get_connection() cursor = conn.cursor(dictionary=True) # 查询单个危险记录 query = "SELECT * FROM device_danger WHERE id = %s" cursor.execute(query, (danger_id,)) danger = cursor.fetchone() if not danger: raise HTTPException(status_code=404, detail=f"ID为 {danger_id} 的危险记录不存在") return APIResponse( code=200, message="获取危险记录详情成功", data=DeviceDangerResponse(**danger) ) except MySQLError as e: raise HTTPException(status_code=500, detail=f"查询危险记录详情失败: {str(e)}") from e finally: db.close_connection(conn, cursor)