fix: 模板创建变量名; 客服模板/角色/权限 API

This commit is contained in:
XingQue
2026-06-20 03:17:01 +08:00
parent 89632228cc
commit 6fa0e1638d
5 changed files with 177 additions and 3 deletions

View File

@@ -1546,8 +1546,8 @@ class ShangjiaTianjiaMobanView(APIView):
TemplateDesc=jieshao, TemplateDesc=jieshao,
Price=jiage_decimal, Price=jiage_decimal,
PublishedCount=0, PublishedCount=0,
CommissionGrabEnabled=yongjin_qiangdan, CommissionGrabEnabled=CommissionGrabEnabled,
CommissionPrice=yongjin_jiage, CommissionPrice=CommissionPrice,
TitleID=cleaned_label_id TitleID=cleaned_label_id
) )

View File

@@ -32,6 +32,11 @@ def staff_can_access_order(member, order_id, perm_all='order_view_all', perm_sel
def proxy_merchant_order_view(request, member, view_class, perm_code): def proxy_merchant_order_view(request, member, view_class, perm_code):
"""子客服通过商家 User 代理调用现有 View.post。""" """子客服通过商家 User 代理调用现有 View.post。"""
return proxy_as_merchant_user(request, member, view_class, perm_code)
def proxy_as_merchant_user(request, member, view_class, perm_code):
"""子客服以商家身份代理调用任意商家 View订单/配置等)。"""
if not member_has_perm(member, perm_code): if not member_has_perm(member, perm_code):
raise StaffAuthError(403, f'无权限: {perm_code}') raise StaffAuthError(403, f'无权限: {perm_code}')

View File

@@ -3,7 +3,8 @@ from django.urls import path
from merchant_ops.views_manage import ( from merchant_ops.views_manage import (
StaffInviteCreateView, StaffInviteListView, StaffInviteRevokeView, StaffInviteCreateView, StaffInviteListView, StaffInviteRevokeView,
StaffMemberListView, StaffMemberUpdateRoleView, StaffMemberRemoveView, StaffMemberListView, StaffMemberUpdateRoleView, StaffMemberRemoveView,
StaffMemberDisableView, StaffRoleListView, StaffRoleSetPermsView, StaffMemberDisableView, StaffMemberUpdatePermsView,
StaffRoleListView, StaffRoleCreateView, StaffRoleSetPermsView,
StaffWalletAllocateView, StaffWalletLedgerView, StaffAuditListView, StaffWalletAllocateView, StaffWalletLedgerView, StaffAuditListView,
StaffRankView, StaffRankView,
) )
@@ -13,6 +14,10 @@ from merchant_ops.views_orders import (
StaffProductTypesView, StaffSettleView, StaffCancelView, StaffRefundView, StaffProductTypesView, StaffSettleView, StaffCancelView, StaffRefundView,
StaffPenaltyApplyView, StaffPenaltyManageView, StaffChangePlayerView, StaffPenaltyApplyView, StaffPenaltyManageView, StaffChangePlayerView,
) )
from merchant_ops.views_templates import (
StaffTemplateListView, StaffTemplateCreateView, StaffTemplateUpdateView,
StaffTemplateDeleteView, StaffLinkGenerateView, StaffLinkListView,
)
urlpatterns = [ urlpatterns = [
# 子客服 # 子客服
@@ -24,9 +29,11 @@ urlpatterns = [
path('invite/revoke', StaffInviteRevokeView.as_view()), path('invite/revoke', StaffInviteRevokeView.as_view()),
path('member/list', StaffMemberListView.as_view()), path('member/list', StaffMemberListView.as_view()),
path('member/update-role', StaffMemberUpdateRoleView.as_view()), path('member/update-role', StaffMemberUpdateRoleView.as_view()),
path('member/update-perms', StaffMemberUpdatePermsView.as_view()),
path('member/remove', StaffMemberRemoveView.as_view()), path('member/remove', StaffMemberRemoveView.as_view()),
path('member/disable', StaffMemberDisableView.as_view()), path('member/disable', StaffMemberDisableView.as_view()),
path('role/list', StaffRoleListView.as_view()), path('role/list', StaffRoleListView.as_view()),
path('role/create', StaffRoleCreateView.as_view()),
path('role/set-perms', StaffRoleSetPermsView.as_view()), path('role/set-perms', StaffRoleSetPermsView.as_view()),
path('wallet/allocate', StaffWalletAllocateView.as_view()), path('wallet/allocate', StaffWalletAllocateView.as_view()),
path('wallet/ledger', StaffWalletLedgerView.as_view()), path('wallet/ledger', StaffWalletLedgerView.as_view()),
@@ -43,4 +50,11 @@ urlpatterns = [
path('order/penalty-apply', StaffPenaltyApplyView.as_view()), path('order/penalty-apply', StaffPenaltyApplyView.as_view()),
path('order/penalty-manage', StaffPenaltyManageView.as_view()), path('order/penalty-manage', StaffPenaltyManageView.as_view()),
path('order/change-player', StaffChangePlayerView.as_view()), path('order/change-player', StaffChangePlayerView.as_view()),
# 子客服模板 / 链接(独立路径,内部代理商家逻辑 + 权限校验)
path('template/list', StaffTemplateListView.as_view()),
path('template/create', StaffTemplateCreateView.as_view()),
path('template/update', StaffTemplateUpdateView.as_view()),
path('template/delete', StaffTemplateDeleteView.as_view()),
path('link/generate', StaffLinkGenerateView.as_view()),
path('link/list', StaffLinkListView.as_view()),
] ]

View File

@@ -252,6 +252,72 @@ class StaffRoleSetPermsView(APIView):
return _err(e) return _err(e)
class StaffRoleCreateView(APIView):
"""商家自定义角色(自由勾选权限)。"""
permission_classes = [IsAuthenticated]
def post(self, request):
try:
mid = request.user.UserUID
ensure_owner_merchant(mid, request.user)
ensure_merchant_roles(mid)
role_name = (request.data.get('role_name') or '').strip()
if not role_name:
return Response({'code': 400, 'msg': '角色名称不能为空', 'data': None})
role_code = (request.data.get('role_code') or '').strip()
if not role_code:
role_code = 'CUSTOM_' + secrets.token_hex(3).upper()
if MerchantStaffRole.query.filter(merchant_id=mid, role_code=role_code).exists():
return Response({'code': 400, 'msg': '角色码已存在', 'data': None})
permissions = request.data.get('permissions', [])
role = MerchantStaffRole.objects.create(
club_id='xq',
merchant_id=mid,
role_code=role_code,
role_name=role_name,
is_system=False,
sort_order=50,
status=1,
)
valid = set(MerchantStaffPermission.query.filter(status=1).values_list('perm_code', flat=True))
for p in permissions:
if p in valid:
MerchantStaffRolePermission.objects.create(role=role, perm_code=p)
audit_owner(mid, mid, 'ROLE_CREATE', request, resource_id=role.id)
return Response({'code': 0, 'msg': '创建成功', 'data': {'id': role.id, 'role_code': role.role_code}})
except Exception as e:
return _err(e)
class StaffMemberUpdatePermsView(APIView):
"""成员级权限加减(覆盖角色默认权限)。"""
permission_classes = [IsAuthenticated]
def post(self, request):
try:
mid = request.user.UserUID
ensure_owner_merchant(mid, request.user)
member_id = request.data.get('member_id')
overrides = request.data.get('overrides', [])
m = MerchantStaffMember.query.get(id=member_id, merchant_id=mid, status=MEMBER_STATUS_ACTIVE)
MerchantStaffMemberPermission.query.filter(member=m).delete()
valid = set(MerchantStaffPermission.query.filter(status=1).values_list('perm_code', flat=True))
for item in overrides:
if isinstance(item, dict):
code = item.get('perm_code')
granted = bool(item.get('granted', True))
else:
code = item
granted = True
if code not in valid:
continue
MerchantStaffMemberPermission.objects.create(member=m, perm_code=code, granted=granted)
audit_owner(mid, mid, 'MEMBER_SET_PERMS', request, resource_id=member_id)
return Response({'code': 0, 'msg': '成员权限已更新', 'data': {'permissions': list(get_member_permissions(m))}})
except Exception as e:
return _err(e)
class StaffWalletAllocateView(APIView): class StaffWalletAllocateView(APIView):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]

View File

@@ -0,0 +1,89 @@
"""子客服专用:派单模板 / 链接(代理商家 config 接口,校验权限,不修改原 /peizhi/*)。"""
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from config.views import (
ShangjiaMobanListView,
ShangjiaTianjiaMobanView,
ShangjiaGengxinMobanView,
ShangjiaShanchuMobanView,
ShangjiaGenerateLinkView,
ShangjiaLianjieListView,
)
from merchant_ops.helpers import proxy_as_merchant_user
from merchant_ops.services.authz import StaffAuthError, get_active_staff_member, member_has_perm
from merchant_ops.views_manage import _err
def _require_staff(request):
member = get_active_staff_member(request.user)
if not member:
raise StaffAuthError(403, '非有效子客服')
return member
class StaffTemplateListView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
try:
member = _require_staff(request)
return proxy_as_merchant_user(request, member, ShangjiaMobanListView, 'template_manage')
except Exception as e:
return _err(e)
class StaffTemplateCreateView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
try:
member = _require_staff(request)
return proxy_as_merchant_user(request, member, ShangjiaTianjiaMobanView, 'template_manage')
except Exception as e:
return _err(e)
class StaffTemplateUpdateView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
try:
member = _require_staff(request)
return proxy_as_merchant_user(request, member, ShangjiaGengxinMobanView, 'template_manage')
except Exception as e:
return _err(e)
class StaffTemplateDeleteView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
try:
member = _require_staff(request)
return proxy_as_merchant_user(request, member, ShangjiaShanchuMobanView, 'template_manage')
except Exception as e:
return _err(e)
class StaffLinkGenerateView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
try:
member = _require_staff(request)
return proxy_as_merchant_user(request, member, ShangjiaGenerateLinkView, 'order_dispatch')
except Exception as e:
return _err(e)
class StaffLinkListView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
try:
member = _require_staff(request)
return proxy_as_merchant_user(request, member, ShangjiaLianjieListView, 'order_dispatch')
except Exception as e:
return _err(e)