""" 管理员仪表盘相关 API """ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func import os import glob from app.core.database import get_db from app.core.deps import get_current_user from app.core.config import settings from app.models.user import User from app.models.project import Project, ProjectMember from app.schemas.response import success_response router = APIRouter() @router.get("/stats", response_model=dict) async def get_dashboard_stats( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db) ): """获取仪表盘统计数据(仅管理员)""" # 检查是否为超级管理员 if current_user.is_superuser != 1: raise HTTPException(status_code=403, detail="仅管理员可访问") # 统计用户数 user_count_result = await db.execute(select(func.count(User.id))) user_count = user_count_result.scalar() # 统计项目数 project_count_result = await db.execute(select(func.count(Project.id))) project_count = project_count_result.scalar() # 统计文档数(所有项目中的 .md 文件) document_count = 0 if os.path.exists(settings.PROJECTS_PATH): for project_dir in os.listdir(settings.PROJECTS_PATH): project_path = os.path.join(settings.PROJECTS_PATH, project_dir) if os.path.isdir(project_path): md_files = glob.glob(os.path.join(project_path, "**/*.md"), recursive=True) document_count += len(md_files) # 获取最近创建的用户 recent_users_result = await db.execute( select(User) .order_by(User.created_at.desc()) .limit(5) ) recent_users = recent_users_result.scalars().all() recent_users_data = [ { "id": user.id, "username": user.username, "email": user.email, "created_at": user.created_at.isoformat() if user.created_at else None, } for user in recent_users ] # 获取最近创建的项目(包含所有者信息) recent_projects_result = await db.execute( select(Project, User) .join(User, Project.owner_id == User.id) .order_by(Project.created_at.desc()) .limit(5) ) recent_projects_rows = recent_projects_result.all() recent_projects_data = [ { "id": project.id, "name": project.name, "description": project.description, "owner_name": owner.username, "created_at": project.created_at.isoformat() if project.created_at else None, } for project, owner in recent_projects_rows ] return success_response( data={ "stats": { "user_count": user_count, "project_count": project_count, "document_count": document_count, }, "recent_users": recent_users_data, "recent_projects": recent_projects_data, } ) @router.get("/personal-stats", response_model=dict) async def get_personal_stats( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db) ): """获取个人桌面统计数据""" # 统计个人项目数 personal_projects_count_result = await db.execute( select(func.count(Project.id)).where(Project.owner_id == current_user.id) ) personal_projects_count = personal_projects_count_result.scalar() # 统计参加项目数(协作项目) shared_projects_count_result = await db.execute( select(func.count(Project.id)) .join(ProjectMember, Project.id == ProjectMember.project_id) .where(ProjectMember.user_id == current_user.id) .where(Project.owner_id != current_user.id) ) shared_projects_count = shared_projects_count_result.scalar() # 统计个人文档数(个人项目中的 .md 文件) document_count = 0 personal_projects_result = await db.execute( select(Project).where(Project.owner_id == current_user.id) ) personal_projects = personal_projects_result.scalars().all() for project in personal_projects: project_path = os.path.join(settings.PROJECTS_PATH, project.storage_key) if os.path.exists(project_path) and os.path.isdir(project_path): md_files = glob.glob(os.path.join(project_path, "**/*.md"), recursive=True) document_count += len(md_files) # 获取最近的个人项目 recent_personal_projects_result = await db.execute( select(Project) .where(Project.owner_id == current_user.id) .order_by(Project.created_at.desc()) .limit(5) ) recent_personal_projects = recent_personal_projects_result.scalars().all() recent_personal_projects_data = [ { "id": project.id, "name": project.name, "description": project.description, "created_at": project.created_at.isoformat() if project.created_at else None, } for project in recent_personal_projects ] # 获取最近的分享项目(从 project_members 表) recent_shared_projects_result = await db.execute( select(Project, ProjectMember) .join(ProjectMember, Project.id == ProjectMember.project_id) .where(ProjectMember.user_id == current_user.id) .where(Project.owner_id != current_user.id) .order_by(ProjectMember.joined_at.desc()) .limit(5) ) recent_shared_projects_rows = recent_shared_projects_result.all() recent_shared_projects_data = [ { "id": project.id, "name": project.name, "description": project.description, "role": member.role, "joined_at": member.joined_at.isoformat() if member.joined_at else None, } for project, member in recent_shared_projects_rows ] return success_response( data={ "user_info": { "id": current_user.id, "username": current_user.username, "email": current_user.email, "created_at": current_user.created_at.isoformat() if current_user.created_at else None, }, "stats": { "personal_projects_count": personal_projects_count, "shared_projects_count": shared_projects_count, "document_count": document_count, }, "recent_personal_projects": recent_personal_projects_data, "recent_shared_projects": recent_shared_projects_data, } )