feat: 分俱乐部推广海报背景与二维码生成

This commit is contained in:
XingQue
2026-06-26 15:52:17 +08:00
parent aaf14264d8
commit 992f4f4f18
4 changed files with 112 additions and 18 deletions

View File

@@ -3,8 +3,8 @@ from django.urls import path
from .views import ShangpinGonggaoView, AdminUpdateConfigView, AdminUploadImageView, AdminConfigQueryView, \
DashouPaihangView,GetAdminZhanghaoView, GetXiugaiJiluView,ShangjiaTianjiaMobanView, ShangjiaMobanListView, \
ShangjiaGengxinMobanView, ShangjiaShanchuMobanView, ShangjiaGenerateLinkView,KehuGetDingdanLianjieView, \
KehuTianxieDingdanView,GuanZhuAListView, ZuzhangHaibaoView,GuanshiQRCodeView,\
GetDynamicConfigView, PopupConfigView, GetWithdrawModeView,CheckPhoneAuthView,\
KehuTianxieDingdanView, GuanZhuAListView, ZuzhangHaibaoView,GuanshiQRCodeView,\
GetDynamicConfigView, HaibaoPeizhiView, PopupConfigView, GetWithdrawModeView,CheckPhoneAuthView,\
ShangjiaLianjieListView
@@ -32,6 +32,7 @@ urlpatterns = [
path('guanshiewm', GuanshiQRCodeView.as_view(), name='管事生成二维码'),
path('zuzhanghb', ZuzhangHaibaoView.as_view(), name='组长二维码'),
path('qdpzhq', GetDynamicConfigView.as_view(), name='小程序获取配置'),
path('haibaopz', HaibaoPeizhiView.as_view(), name='推广海报配置'),
path('tanchuang', PopupConfigView.as_view(), name='微信小程序获取弹窗数据'),
path('hqtxzsym', GetWithdrawModeView.as_view(), name='小程序获取提现方式'),

View File

@@ -115,6 +115,31 @@ class GetDynamicConfigView(APIView):
return Response({"code": 500, "msg": "服务器内部错误"}, status=500)
class HaibaoPeizhiView(APIView):
"""小程序推广海报背景配置(按俱乐部)。"""
permission_classes = [AllowAny]
parser_classes = [JSONParser]
def post(self, request):
try:
from jituan.services.display_config import _display_club_id
from jituan.services.miniapp_assets import get_poster_payload
club_id = _display_club_id(request)
poster = get_poster_payload(club_id)
return Response({
'code': 0,
'msg': 'success',
'data': {
'club_id': club_id,
'poster': poster,
},
})
except Exception as e:
logger.error('获取海报配置失败: %s', e, exc_info=True)
return Response({'code': 500, 'msg': '服务器内部错误'}, status=500)
class ShangpinGonggaoView(APIView):
@@ -2782,6 +2807,10 @@ class GuanshiQRCodeView(APIView):
logger.info(f"当前用户ID: {current_user.UserUID}")
try:
from jituan.services.club_context import resolve_effective_club_id
from utils.weixin_token import get_club_mini_access_token, is_weixin_token_invalid
club_id = resolve_effective_club_id(request, current_user)
try:
guanshi = current_user.GuanshiProfile
logger.info(f"管事扩展表查询成功,状态: {guanshi.zhuangtai}")
@@ -2815,15 +2844,15 @@ class GuanshiQRCodeView(APIView):
else:
logger.info(f"使用已有邀请码: {invite_code}")
# 直接获取新的 access_token,不缓存
access_token = self.get_fresh_access_token()
# 按俱乐部使用对应小程序 appid 的 access_token
access_token = get_club_mini_access_token(club_id)
if not access_token:
logger.error("获取 access_token 失败")
logger.error("获取 access_token 失败 club_id=%s", club_id)
return Response(
{'code': 500, 'message': '获取微信access_token失败', 'data': None},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
logger.info(f"获取到 access_token (前10位): {access_token[:10]}...")
logger.info(f"获取到 access_token (前10位): {access_token[:10]}... club={club_id}")
encoded_invite = urllib.parse.quote(invite_code, safe='')
page_path = f'pages/dashouduan/dashouduan?inviteCode={encoded_invite}'
@@ -2836,16 +2865,35 @@ class GuanshiQRCodeView(APIView):
}
logger.info(f"调用微信接口生成小程序码path: {page_path}")
try:
wx_resp = requests.post(wx_url, json=post_data, timeout=10)
logger.info(f"微信接口响应状态码: {wx_resp.status_code}")
except Exception as e:
logger.error(f"请求微信接口异常: {str(e)}", exc_info=True)
def _request_qr(token):
try:
return requests.post(
f'https://api.weixin.qq.com/wxa/getwxacode?access_token={token}',
json=post_data, timeout=10,
)
except Exception as e:
logger.error(f"请求微信接口异常: {str(e)}", exc_info=True)
return None
wx_resp = _request_qr(access_token)
if wx_resp is None:
return Response(
{'code': 500, 'message': '调用微信服务失败', 'data': None},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
if wx_resp.headers.get('content-type', '').startswith('application/json'):
try:
err = wx_resp.json()
if is_weixin_token_invalid(err.get('errcode'), err.get('errmsg', '')):
access_token = get_club_mini_access_token(club_id, force_refresh=True)
if access_token:
wx_resp = _request_qr(access_token)
except Exception:
pass
logger.info(f"微信接口响应状态码: {wx_resp.status_code}")
if wx_resp.status_code != 200:
error_info = {}
if wx_resp.headers.get('content-type') == 'application/json':
@@ -2881,7 +2929,7 @@ class GuanshiQRCodeView(APIView):
timestamp = int(time.time())
filename = f"{current_user.UserUID}_{timestamp}.png"
oss_path = f"erweima/guanshi/{filename}"
oss_path = f"erweima/guanshi/{club_id}/{filename}"
file_obj = io.BytesIO(wx_resp.content)
logger.info(f"开始上传图片到COS: {oss_path}")
@@ -2994,6 +3042,10 @@ class ZuzhangHaibaoView(APIView):
def post(self, request):
current_user = request.user
from jituan.services.club_context import resolve_effective_club_id
from utils.weixin_token import get_club_mini_access_token
club_id = resolve_effective_club_id(request, current_user)
# 1. 验证组长身份
try:
@@ -3027,8 +3079,8 @@ class ZuzhangHaibaoView(APIView):
zuzhang.yaoqingma = invite_code
zuzhang.save(update_fields=['yaoqingma'])
# 4. 获取微信 access_token优先 stable_tokentoken 失效时自动刷新重试
access_token = get_weixin_mini_access_token(force_refresh=False)
# 4. 获取微信 access_token按俱乐部对应小程序
access_token = get_club_mini_access_token(club_id, force_refresh=False)
if not access_token:
return Response({
'code': 500,
@@ -3042,8 +3094,8 @@ class ZuzhangHaibaoView(APIView):
wx_resp, wx_error = self._request_wx_qrcode(page_path, access_token)
if wx_error and is_weixin_token_invalid(wx_error.get('errcode'), wx_error.get('errmsg', '')):
logger.warning('组长海报二维码 token 失效,强制刷新后重试')
access_token = get_weixin_mini_access_token(force_refresh=True)
logger.warning('组长海报二维码 token 失效,强制刷新后重试 club=%s', club_id)
access_token = get_club_mini_access_token(club_id, force_refresh=True)
if not access_token:
return Response({
'code': 500,
@@ -3071,7 +3123,7 @@ class ZuzhangHaibaoView(APIView):
# 5. 上传到腾讯云 COS
timestamp = int(time.time())
filename = f"{current_user.UserUID}_{timestamp}.png"
oss_path = f"erweima/zuzhang/{filename}"
oss_path = f"erweima/zuzhang/{club_id}/{filename}"
file_obj = io.BytesIO(wx_resp.content)
try: