91 lines
2.6 KiB
Python
91 lines
2.6 KiB
Python
from datetime import datetime, timedelta
|
|
from pathlib import Path
|
|
import os
|
|
import shutil
|
|
from fastapi import APIRouter, Depends
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy import func
|
|
from redis import Redis
|
|
|
|
from app.core.db import get_db
|
|
from app.core.redis import get_redis
|
|
from app.schemas.dashboard import DashboardSummary, UserStats, StorageStats, ServerStats
|
|
from app.models import User
|
|
|
|
|
|
router = APIRouter(prefix="/dashboard", tags=["dashboard"])
|
|
|
|
|
|
AUDIO_EXTENSIONS = {".mp3", ".wav", ".m4a", ".flac", ".aac", ".ogg"}
|
|
|
|
|
|
def _get_base_dir() -> Path:
|
|
return Path(__file__).resolve().parents[5]
|
|
|
|
|
|
def _scan_storage(storage_dir: Path) -> tuple[int, int]:
|
|
total_bytes = 0
|
|
file_count = 0
|
|
if not storage_dir.exists():
|
|
return 0, 0
|
|
for root, _dirs, files in os.walk(storage_dir):
|
|
for name in files:
|
|
file_path = Path(root) / name
|
|
try:
|
|
total_bytes += file_path.stat().st_size
|
|
except OSError:
|
|
continue
|
|
file_count += 1
|
|
return total_bytes, file_count
|
|
|
|
|
|
def _get_cpu_memory() -> tuple[float, float]:
|
|
try:
|
|
import psutil # type: ignore
|
|
cpu = psutil.cpu_percent(interval=0.2)
|
|
mem = psutil.virtual_memory().percent
|
|
return float(cpu), float(mem)
|
|
except Exception:
|
|
return 0.0, 0.0
|
|
|
|
|
|
def _get_disk_usage(path: Path) -> float:
|
|
try:
|
|
total, used, _free = shutil.disk_usage(path)
|
|
if total == 0:
|
|
return 0.0
|
|
return round(used / total * 100, 2)
|
|
except Exception:
|
|
return 0.0
|
|
|
|
|
|
@router.get("/summary", response_model=DashboardSummary)
|
|
def get_dashboard_summary(db: Session = Depends(get_db), redis: Redis = Depends(get_redis)):
|
|
total_users = db.query(User).filter(User.is_deleted == 0).count()
|
|
|
|
# 2. 今日新增
|
|
today_start = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
|
new_today = db.query(User).filter(
|
|
User.created_at >= today_start,
|
|
User.is_deleted == 0
|
|
).count()
|
|
|
|
try:
|
|
online = len(redis.keys("auth:online:*"))
|
|
except Exception:
|
|
online = 0
|
|
|
|
base_dir = _get_base_dir()
|
|
storage_dir = base_dir / "storage"
|
|
total_bytes, audio_files = _scan_storage(storage_dir)
|
|
total_gb = round(total_bytes / (1024 ** 3), 2)
|
|
|
|
cpu, mem = _get_cpu_memory()
|
|
disk = _get_disk_usage(storage_dir if storage_dir.exists() else base_dir)
|
|
|
|
return DashboardSummary(
|
|
users=UserStats(total=total_users, new_today=new_today, online=online),
|
|
storage=StorageStats(total_gb=total_gb, audio_files=audio_files),
|
|
server=ServerStats(cpu=cpu, memory=mem, disk=disk),
|
|
)
|