Files
boss_dp/server/api/stats.py
ddrwode 6cb86ec7fb haha
2026-03-06 16:09:18 +08:00

125 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""
统计分析 API需要登录
- GET /api/stats -> 总览统计
- GET /api/stats/daily -> 按日统计
"""
from datetime import timedelta
from django.db.models import Count, Q
from django.utils import timezone
from rest_framework.decorators import api_view
from server.core.response import api_success
from server.models import ContactRecord, BossAccount, TaskLog
from server.core.worker_manager import worker_manager
GREETED_STATUS = "新打招呼"
@api_view(["GET"])
def stats_overview(request):
"""总览统计数据。"""
period = request.query_params.get("period", "all")
now = timezone.now()
# 根据时间段过滤
date_filter = Q()
if period == "today":
date_filter = Q(contacted_at__date=now.date())
elif period == "week":
date_filter = Q(contacted_at__gte=now - timedelta(days=7))
elif period == "month":
date_filter = Q(contacted_at__gte=now - timedelta(days=30))
contacts_qs = ContactRecord.objects.filter(date_filter)
total_contacts = contacts_qs.count()
total_greeted = contacts_qs.filter(reply_status=GREETED_STATUS).count()
total_replied = contacts_qs.filter(reply_status="已回复").count()
total_wechat = contacts_qs.filter(wechat_exchanged=True).count()
# 今日数据
today_filter = Q(contacted_at__date=now.date())
today_contacts = ContactRecord.objects.filter(today_filter).count()
today_greeted = ContactRecord.objects.filter(today_filter, reply_status=GREETED_STATUS).count()
today_replied = ContactRecord.objects.filter(today_filter, reply_status="已回复").count()
today_wechat = ContactRecord.objects.filter(today_filter, wechat_exchanged=True).count()
# 账号统计
total_accounts = BossAccount.objects.count()
logged_in_accounts = BossAccount.objects.filter(is_logged_in=True).count()
# Worker 统计
all_workers = worker_manager.get_all_workers()
online_workers = [w for w in all_workers if w.online]
# 任务统计
total_task_logs = TaskLog.objects.count()
reply_rate = round(total_replied / max(total_contacts, 1) * 100, 1)
wechat_rate = round(total_wechat / max(total_replied, 1) * 100, 1)
return api_success({
"period": period,
"contacts": {
"total": total_contacts,
"today": today_contacts,
"greeted": total_greeted,
"today_greeted": today_greeted,
"replied": total_replied,
"today_replied": today_replied,
"reply_rate": reply_rate,
},
"greetings": {
"total": total_greeted,
"today": today_greeted,
},
"wechat": {
"total": total_wechat,
"today": today_wechat,
"success_rate": wechat_rate,
},
"accounts": {
"total": total_accounts,
"logged_in": logged_in_accounts,
},
"workers": {
"total": len(all_workers),
"online": len(online_workers),
},
"tasks": {
"total_logs": total_task_logs,
},
})
@api_view(["GET"])
def stats_daily(request):
"""按日统计最近 N 天数据。"""
try:
days = int(request.query_params.get("days", 7))
except (TypeError, ValueError):
days = 7
days = max(1, min(days, 180))
now = timezone.now()
daily_data = []
for i in range(days - 1, -1, -1):
day = (now - timedelta(days=i)).date()
day_filter = Q(contacted_at__date=day)
qs = ContactRecord.objects.filter(day_filter)
total = qs.count()
greeted = qs.filter(reply_status=GREETED_STATUS).count()
replied = qs.filter(reply_status="已回复").count()
wechat = qs.filter(wechat_exchanged=True).count()
daily_data.append({
"date": f"{day.isoformat()}T00:00:00",
"contacts": total,
"greeted": greeted,
"replied": replied,
"wechat": wechat,
"reply_rate": round(replied / max(total, 1) * 100, 1),
})
return api_success(daily_data)