新增日统计排行榜接口 phbhqsj,配置接口返回排行榜素材路径

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-06-27 00:38:03 +08:00
parent 770d198bf8
commit ceaca8bf4d
3 changed files with 299 additions and 1 deletions

View File

@@ -88,7 +88,14 @@ class GetDynamicConfigView(APIView):
},
"otherConfig": {
"morentouxiang": morentouxiang,
"dashouguize": dashouguize
"dashouguize": dashouguize,
"paihangAssets": {
"basePath": "beijing/paihangbang/",
"pageBg": "page-bg.jpg",
"cardBg": "list-card-bg.png",
"emptyIcon": "empty.png",
"refreshIcon": "icon-refresh.png",
},
},
"kefu": {
"link": kefu_link,

289
yonghu/paihang_views.py Normal file
View File

@@ -0,0 +1,289 @@
"""
排行榜接口 — 基于 houtai 日统计表聚合(文赫电竞)
POST /yonghu/phbhqsj
"""
import logging
from datetime import date, timedelta
from decimal import Decimal
from django.db.models import Sum
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from houtai.models import (
DashouRiTongji,
GuanshiRiTongji,
ZuzhangRiTongji,
ShangjiaRiTongji,
)
from yonghu.models import UserMain, UserDashou, UserShangjia, UserBoss
logger = logging.getLogger(__name__)
MAX_RANK = 50
RIQI_OPTIONS = frozenset({'今日', '本周', '本月', '总榜', '昨日', '上周', '上月'})
SHENFEN_OPTIONS = frozenset({'dashou', 'guanshi', 'zuzhang', 'shangjia'})
ROLE_CONFIG = {
'dashou': {
'model': DashouRiTongji,
'id_field': 'yonghuid',
'sort_field': 'chengjiao_zonge',
'fields': ('jiedan_zongliang', 'chengjiao_zongliang', 'jiedan_zonge', 'chengjiao_zonge'),
'int_fields': frozenset({'jiedan_zongliang', 'chengjiao_zongliang'}),
},
'guanshi': {
'model': GuanshiRiTongji,
'id_field': 'yonghuid',
'sort_field': 'shouru_zonge',
'fields': ('yaoqing_dashou_shu', 'chongzhi_dashou_shu', 'shouru_zonge'),
'int_fields': frozenset({'yaoqing_dashou_shu', 'chongzhi_dashou_shu'}),
},
'zuzhang': {
'model': ZuzhangRiTongji,
'id_field': 'yonghuid',
'sort_field': 'shouru_zonge',
'fields': ('yaoqing_guanshi_shu', 'fenyong_jine', 'shouru_zonge'),
'int_fields': frozenset({'yaoqing_guanshi_shu'}),
},
'shangjia': {
'model': ShangjiaRiTongji,
'id_field': 'yonghuid',
'sort_field': 'jiesuan_jine',
'fields': ('paifa_dingdan_shu', 'paifa_jine', 'jiesuan_dingdan_shu', 'jiesuan_jine'),
'int_fields': frozenset({'paifa_dingdan_shu', 'jiesuan_dingdan_shu'}),
},
}
TODAY_PROFILE_CONFIG = {
'dashou': {
'profile_model': UserDashou,
'profile_sort_field': 'jinrishouyi',
'field_map': {
'jiedan_zongliang': 'jinrijiedan',
'chengjiao_zongliang': 'jinrijiedan',
'jiedan_zonge': 'jinrishouyi',
'chengjiao_zonge': 'jinrishouyi',
},
},
'guanshi': {
'profile_model': UserGuanshi,
'profile_sort_field': 'jinrichongzhi',
'field_map': {
'yaoqing_dashou_shu': None,
'chongzhi_dashou_shu': 'jinrichongzhi',
'shouru_zonge': None,
},
},
'zuzhang': {
'profile_model': UserZuzhang,
'profile_sort_field': 'jinri_fenyong',
'field_map': {
'yaoqing_guanshi_shu': None,
'fenyong_jine': 'jinri_fenyong',
'shouru_zonge': 'jinri_fenyong',
},
},
'shangjia': {
'profile_model': UserShangjia,
'profile_sort_field': 'jinriliushui',
'field_map': {
'paifa_dingdan_shu': 'jinridingdan',
'paifa_jine': 'jinriliushui',
'jiesuan_dingdan_shu': None,
'jiesuan_jine': None,
},
},
}
from yonghu.models import UserGuanshi, UserZuzhang # noqa: E402 — after ROLE_CONFIG
def _resolve_date_range(riqi: str):
today = date.today()
if riqi == '今日':
return today, today
if riqi == '昨日':
d = today - timedelta(days=1)
return d, d
if riqi == '本周':
monday = today - timedelta(days=today.weekday())
return monday, today
if riqi == '上周':
this_monday = today - timedelta(days=today.weekday())
last_sunday = this_monday - timedelta(days=1)
last_monday = last_sunday - timedelta(days=6)
return last_monday, last_sunday
if riqi == '本月':
return today.replace(day=1), today
if riqi == '上月':
first_this_month = today.replace(day=1)
last_day_prev = first_this_month - timedelta(days=1)
return last_day_prev.replace(day=1), last_day_prev
return None
def _fmt_value(val, is_int: bool):
if val is None:
return 0 if is_int else 0.0
if is_int:
return int(val)
if isinstance(val, Decimal):
return float(val.quantize(Decimal('0.01')))
return float(val)
class PhbHqsjView(APIView):
"""POST /yonghu/phbhqsj — 新排行榜(日统计表聚合)"""
permission_classes = [IsAuthenticated]
def post(self, request):
shenfen = (request.data.get('shenfen') or '').strip()
riqi = (request.data.get('riqi') or '').strip()
if shenfen not in SHENFEN_OPTIONS:
return Response({
'code': 400,
'msg': '参数错误shenfen 必须为 dashou/guanshi/zuzhang/shangjia',
'data': {'list': []},
})
if riqi not in RIQI_OPTIONS:
return Response({
'code': 400,
'msg': '参数错误riqi 必须为 今日/本周/本月/总榜/昨日/上周/上月',
'data': {'list': []},
})
try:
if riqi == '总榜':
rows = self._query_rank_rows(shenfen, all_time=True)
else:
date_range = _resolve_date_range(riqi)
if date_range is None:
return Response({
'code': 400,
'msg': '参数错误:无效的日期范围',
'data': {'list': []},
})
rows = self._query_rank_rows(shenfen, date_range[0], date_range[1])
nick_map, avatar_map = self._load_user_display(rows, shenfen)
cfg = ROLE_CONFIG[shenfen]
int_fields = cfg['int_fields']
id_field = cfg['id_field']
result_list = []
for idx, row in enumerate(rows):
yonghuid = row[id_field]
item = {
'mingci': idx + 1,
'yonghuid': yonghuid,
'nicheng': nick_map.get(yonghuid, '用户'),
'touxiang': avatar_map.get(yonghuid, '') or '',
}
for field in cfg['fields']:
item[field] = _fmt_value(row.get(field), field in int_fields)
result_list.append(item)
return Response({
'code': 0,
'msg': '获取成功',
'data': {'list': result_list},
})
except Exception as e:
logger.error('排行榜查询失败 shenfen=%s riqi=%s: %s', shenfen, riqi, e, exc_info=True)
return Response({
'code': 500,
'msg': '服务器内部错误',
'data': {'list': []},
})
def _query_rank_rows(self, shenfen, start_date=None, end_date=None, all_time=False):
cfg = ROLE_CONFIG[shenfen]
model = cfg['model']
sort_field = cfg['sort_field']
fields = cfg['fields']
id_field = cfg['id_field']
annotate_kwargs = {f: Sum(f) for f in fields}
if all_time:
rows = (
model.objects
.values(id_field)
.annotate(**annotate_kwargs)
.order_by(f'-{sort_field}')[:MAX_RANK]
)
return list(rows)
if start_date == end_date:
qs = model.objects.filter(riqi=start_date).order_by(f'-{sort_field}')[:MAX_RANK]
rows = [
{id_field: getattr(r, id_field), **{f: getattr(r, f) for f in fields}}
for r in qs
]
if rows:
return rows
today = date.today()
if start_date == today:
return self._query_today_from_profiles(shenfen)
return rows
rows = (
model.objects
.filter(riqi__gte=start_date, riqi__lte=end_date)
.values(id_field)
.annotate(**annotate_kwargs)
.order_by(f'-{sort_field}')[:MAX_RANK]
)
return list(rows)
def _query_today_from_profiles(self, shenfen):
cfg = ROLE_CONFIG[shenfen]
today_cfg = TODAY_PROFILE_CONFIG[shenfen]
profile_model = today_cfg['profile_model']
profile_sort = today_cfg['profile_sort_field']
field_map = today_cfg['field_map']
id_field = cfg['id_field']
fields = cfg['fields']
qs = profile_model.objects.filter(
**{f'{profile_sort}__gt': 0}
).select_related('user').order_by(f'-{profile_sort}')[:MAX_RANK]
rows = []
for p in qs:
uid = p.user.yonghuid
row = {id_field: uid}
for f in fields:
profile_field = field_map.get(f)
if profile_field:
row[f] = getattr(p, profile_field)
else:
row[f] = 0
rows.append(row)
return rows
def _load_user_display(self, rows, shenfen):
id_field = ROLE_CONFIG[shenfen]['id_field']
yonghuids = [r[id_field] for r in rows if r.get(id_field)]
if not yonghuids:
return {}, {}
users = UserMain.objects.filter(yonghuid__in=yonghuids)
avatar_map = {u.yonghuid: u.avatar or '' for u in users}
nick_map = {}
if shenfen == 'dashou':
for p in UserDashou.objects.filter(user__yonghuid__in=yonghuids).select_related('user'):
nick_map[p.user.yonghuid] = p.nicheng or '用户'
elif shenfen == 'shangjia':
for p in UserShangjia.objects.filter(user__yonghuid__in=yonghuids).select_related('user'):
nick_map[p.user.yonghuid] = p.nicheng or '用户'
else:
for b in UserBoss.objects.filter(user__yonghuid__in=yonghuids).select_related('user'):
nick_map[b.user.yonghuid] = b.nickname or '用户'
return nick_map, avatar_map

View File

@@ -21,6 +21,7 @@ from .views import WechatMiniProgramLoginView, UserInfoUpdateView, DashouXinxiAP
KaohePayView,KaohePayCallbackView, KaohePayPollView, KaohePayFailView, TixianAssetView
from .tixian_shenhe_views import TixianZddkshApplyView
from .paihang_views import PhbHqsjView
urlpatterns = [
@@ -69,6 +70,7 @@ urlpatterns = [
path('shangjiahuce', ShangjiaZhuceView.as_view(), name='商家注册'),
path('paihangbang', PaihangbangGuanliQueryView.as_view(), name='管理查询排行榜'),
path('adhqphrq', PaihangbangRiqiliebiaoView.as_view(), name='管理原获取排行榜日期'),
path('phbhqsj', PhbHqsjView.as_view(), name='排行榜数据-日统计'),