xiangqinxiaochengxu/backend/app/services/dashboard_service.py
2026-04-17 10:49:14 +08:00

63 lines
2.3 KiB
Python

from datetime import datetime, timedelta
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.activity import Activity
from app.models.match import Match
from app.models.user import User
async def get_dashboard_data(session: AsyncSession) -> dict:
total_users = int((await session.execute(select(func.count(User.id)))).scalar() or 0)
total_matches = int((await session.execute(select(func.count(Match.id)))).scalar() or 0)
total_activities = int((await session.execute(select(func.count(Activity.id)))).scalar() or 0)
pending_audit = int(
(await session.execute(select(func.count(User.id)).where(User.audit_status == 1))).scalar() or 0
)
ongoing_activities = int(
(await session.execute(select(func.count(Activity.id)).where(Activity.status.in_([1, 3])))).scalar() or 0
)
seven_days_ago = datetime.now() - timedelta(days=7)
active_users_7d = int(
(await session.execute(select(func.count(User.id)).where(User.updated_at >= seven_days_ago))).scalar() or 0
)
match_rate = round(total_matches / total_users, 3) if total_users else 0
user_trend = []
match_trend = []
for offset in range(6, -1, -1):
day_start = (datetime.now() - timedelta(days=offset)).replace(hour=0, minute=0, second=0, microsecond=0)
day_end = day_start + timedelta(days=1)
user_count = int(
(await session.execute(
select(func.count(User.id)).where(User.created_at >= day_start, User.created_at < day_end)
)).scalar()
or 0
)
match_count = int(
(await session.execute(
select(func.count(Match.id)).where(Match.matched_at >= day_start, Match.matched_at < day_end)
)).scalar()
or 0
)
day_label = day_start.strftime('%Y-%m-%d')
user_trend.append({"date": day_label, "count": user_count})
match_trend.append({"date": day_label, "count": match_count})
return {
"total_users": total_users,
"active_users_7d": active_users_7d,
"pending_audit": pending_audit,
"total_activities": total_activities,
"ongoing_activities": ongoing_activities,
"total_matches": total_matches,
"match_rate": match_rate,
"user_trend": user_trend,
"match_trend": match_trend,
}