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

188 lines
6.5 KiB
Python

"""
管理员仪表盘相关 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,
}
)