""" 管理员用户管理API路由 提供用户列表、详情、状态变更等API端点 """ from typing import Optional from datetime import date from fastapi import APIRouter, Depends, HTTPException, status, Query, Request from sqlalchemy.orm import Session from app.database import get_db from app.schemas.admin_schema import ( UserListItem, UserDetailResponse, UserUsageStats, UserStatusRequest, ResetPasswordResponse ) from app.schemas.model_schema import PaginatedResponse from app.services.admin_user_service import AdminUserService from app.services.operation_log_service import OperationLogService from app.dependencies.admin_auth import get_current_admin from app.models.admin import AdminUser router = APIRouter(prefix="/api/admin/users", tags=["用户管理"]) ERROR_MESSAGES = { "USER_NOT_FOUND": "用户不存在", "STATUS_UNCHANGED": "状态无需变更" } @router.get("", response_model=PaginatedResponse) def list_users( keyword: Optional[str] = Query(None, description="搜索关键词"), user_status: Optional[str] = Query(None, alias="status", description="账户状态"), register_start: Optional[date] = Query(None, description="注册开始日期"), register_end: Optional[date] = Query(None, description="注册结束日期"), sort_by: str = Query("created_at", description="排序字段"), sort_order: str = Query("desc", description="排序方向"), page: int = Query(1, ge=1, description="页码"), size: int = Query(20, ge=1, le=100, description="每页数量"), current_admin: AdminUser = Depends(get_current_admin), db: Session = Depends(get_db) ): """获取用户列表""" from app.schemas.admin_schema import UserListParams params = UserListParams( keyword=keyword, status=user_status, register_start=register_start, register_end=register_end, sort_by=sort_by, sort_order=sort_order, page=page, size=size ) service = AdminUserService(db) users, total = service.list_users(params) return PaginatedResponse( items=[u.model_dump() for u in users], total=total, page=page, page_size=size ) @router.get("/{user_id}", response_model=UserDetailResponse) def get_user_detail( user_id: str, current_admin: AdminUser = Depends(get_current_admin), db: Session = Depends(get_db) ): """获取用户详情""" service = AdminUserService(db) user = service.get_user_detail(user_id) if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail={"code": "USER_NOT_FOUND", "message": "用户不存在"} ) return user @router.get("/{user_id}/usage-stats", response_model=UserUsageStats) def get_user_usage_stats( user_id: str, current_admin: AdminUser = Depends(get_current_admin), db: Session = Depends(get_db) ): """获取用户使用统计""" service = AdminUserService(db) return service.get_user_usage_stats(user_id) @router.post("/{user_id}/status") def update_user_status( user_id: str, data: UserStatusRequest, request: Request, current_admin: AdminUser = Depends(get_current_admin), db: Session = Depends(get_db) ): """更新用户状态""" service = AdminUserService(db) try: service.update_user_status(user_id, data.status) # 记录操作日志 log_service = OperationLogService(db) log_service.create_log( admin_id=current_admin.id, operation_type="update", module="user", target_id=user_id, detail={"action": "update_status", "new_status": data.status}, ip_address=request.client.host if request.client else None ) return {"message": "状态更新成功", "user_id": user_id, "status": data.status} except ValueError as e: error_code = str(e) raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST if error_code == "STATUS_UNCHANGED" else status.HTTP_404_NOT_FOUND, detail={"code": error_code, "message": ERROR_MESSAGES.get(error_code, "操作失败")} ) @router.post("/{user_id}/reset-password", response_model=ResetPasswordResponse) def reset_user_password( user_id: str, request: Request, current_admin: AdminUser = Depends(get_current_admin), db: Session = Depends(get_db) ): """重置用户密码""" service = AdminUserService(db) try: new_password = service.reset_password(user_id) # 记录操作日志 log_service = OperationLogService(db) log_service.create_log( admin_id=current_admin.id, operation_type="update", module="user", target_id=user_id, detail={"action": "reset_password"}, ip_address=request.client.host if request.client else None ) return ResetPasswordResponse(user_id=user_id, new_password=new_password) except ValueError as e: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail={"code": "USER_NOT_FOUND", "message": "用户不存在"} )