nex_docus/backend/app/api/v1/dashboard.py

178 lines
6.1 KiB
Python
Raw Normal View History

2025-12-20 11:18:59 +00:00
"""
管理员仪表盘相关 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()
# 统计个人文档数(个人项目中的 .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,
"document_count": document_count,
},
"recent_personal_projects": recent_personal_projects_data,
"recent_shared_projects": recent_shared_projects_data,
}
)