P1 性能优化(避免循环内 N+1 / N 次 DB 查询): - shop_order_views._batch_images: 移除 ThreadPoolExecutor 掩盖的 N 次查询,改单次批量 + Python 侧分组 - product_query.DashouHuiyuanList: 5N 查询 -> 3 次批量预取 + 本地闭包判断 - roles.GetRolePermissionView / 用户列表: 循环内 RolePermission/Permission/UserRole/Role -> 批量 __in 预取 - guanli / zuzhang 杜次分红 4.2/4.3: 循环内 update_or_create + 单条 delete -> bulk_create + bulk_update + 批量 delete - admin_config QQ 群配置: 循环内 exists/first/save/create -> 批量预取 + bulk_create + bulk_update - jituan 服务层多处合并统计查询、批量预取 map - rank 多处循环 N+1 改批量预取 - backend 多处循环内 count/create 改批量 - config/orders/merchant_ops 多处循环 N+1 改批量预取 其他改动: - users/views/kefu.py 拆分为 kefu_base/kefu_dashou/kefu_orders/kefu_punishment/kefu_withdraw 5 个文件 - 删除遗留脚本 check_prod_uid.py / create_rbac_tables.sql
128 lines
4.9 KiB
Python
128 lines
4.9 KiB
Python
"""考核官后台管理(按俱乐部隔离)。"""
|
|
import logging
|
|
|
|
from django.db import transaction
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from backend.view import verify_kefu_permission
|
|
from jituan.services.club_user import get_user_club_id
|
|
from jituan.services.shenhe_club import user_belongs_to_request_club
|
|
from rank.models import Bankuai, KaoheguanBankuai
|
|
from users.business_models import User
|
|
from users.models import UserShenheguan
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _normalize_bankuai_ids(data):
|
|
ids = data.get('bankuai_ids')
|
|
if ids is None and data.get('bankuai_id'):
|
|
ids = [data.get('bankuai_id')]
|
|
if not isinstance(ids, list):
|
|
return []
|
|
out = []
|
|
for item in ids:
|
|
s = str(item or '').strip()
|
|
if s and s not in out:
|
|
out.append(s)
|
|
return out
|
|
|
|
|
|
class ClubKhgglAddView(APIView):
|
|
"""
|
|
后台添加考核官(升级为考核官并关联板块)。
|
|
POST /jituan/houtai/khggl-add
|
|
Body: {
|
|
"phone": "管理员手机号",
|
|
"yonghuid": "用户ID",
|
|
"bankuai_ids": ["bk001", "bk002"], // 或 bankuai_id 单个
|
|
"is_renzheng": true // 可选,默认 true
|
|
}
|
|
"""
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
try:
|
|
username_from_frontend = request.data.get('phone', None)
|
|
kefu_obj, permissions = verify_kefu_permission(request, username_from_frontend)
|
|
if kefu_obj is None:
|
|
return permissions
|
|
if 'kaohepeizhi' not in permissions:
|
|
return Response({'code': 403, 'msg': '无考核管理权限'}, status=403)
|
|
|
|
yonghuid = str(request.data.get('yonghuid', '')).strip()
|
|
bankuai_ids = _normalize_bankuai_ids(request.data)
|
|
is_renzheng = request.data.get('is_renzheng', True)
|
|
if isinstance(is_renzheng, str):
|
|
is_renzheng = is_renzheng.lower() in ('1', 'true', 'yes')
|
|
|
|
if not yonghuid:
|
|
return Response({'code': 1, 'msg': '请输入用户ID'}, status=400)
|
|
if not bankuai_ids:
|
|
return Response({'code': 1, 'msg': '请选择至少一个板块'}, status=400)
|
|
|
|
try:
|
|
user = User.query.get(UserUID=yonghuid)
|
|
except User.DoesNotExist:
|
|
return Response({'code': 1, 'msg': '用户ID不存在'}, status=404)
|
|
|
|
if not user_belongs_to_request_club(user, request):
|
|
return Response({'code': 403, 'msg': '该用户不属于当前俱乐部,无法添加为考核官'}, status=403)
|
|
|
|
# 一次性查询所有板块是否存在,避免循环内 N+1 exists
|
|
_existing_bids = set(
|
|
Bankuai.query.filter(bankuai_id__in=bankuai_ids)
|
|
.values_list('bankuai_id', flat=True)
|
|
)
|
|
for bid in bankuai_ids:
|
|
if bid not in _existing_bids:
|
|
return Response({'code': 1, 'msg': f'板块不存在: {bid}'}, status=400)
|
|
|
|
created_new = False
|
|
with transaction.atomic():
|
|
kg, created_new = UserShenheguan.query.get_or_create(
|
|
user=user,
|
|
defaults={
|
|
'zhuangtai': 1,
|
|
'shenhe_zhuangtai': 0,
|
|
'is_renzheng': bool(is_renzheng),
|
|
'shenhe_zongshu': 0,
|
|
'tongguo_zongshu': 0,
|
|
'yue': 0,
|
|
'zonge': 0,
|
|
},
|
|
)
|
|
if not created_new:
|
|
if kg.zhuangtai != 1:
|
|
kg.zhuangtai = 1
|
|
if is_renzheng:
|
|
kg.is_renzheng = True
|
|
kg.save()
|
|
|
|
added_bankuai = []
|
|
for bid in bankuai_ids:
|
|
rel, rel_created = KaoheguanBankuai.query.get_or_create(
|
|
kaoheguan_id=yonghuid,
|
|
bankuai_id=bid,
|
|
)
|
|
if rel_created:
|
|
added_bankuai.append(bid)
|
|
|
|
msg = '考核官添加成功' if created_new else '已关联板块(该用户已是考核官)'
|
|
return Response({
|
|
'code': 0,
|
|
'msg': msg,
|
|
'data': {
|
|
'yonghuid': yonghuid,
|
|
'created': created_new,
|
|
'added_bankuai_ids': added_bankuai,
|
|
'club_id': get_user_club_id(user),
|
|
'is_renzheng': bool(kg.is_renzheng),
|
|
},
|
|
})
|
|
except Exception as e:
|
|
logger.exception('ClubKhgglAddView 接口错误')
|
|
return Response({'code': 1, 'msg': f'服务器内部错误: {str(e)}'}, status=500)
|