xiangqinxiaochengxu/backend/app/services/dashboard_service.py

63 lines
2.3 KiB
Python
Raw Normal View History

2026-04-17 10:49:14 +08:00
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,
}