164 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			164 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | 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) |