From 644fd47f0a905a5c7f2823a5dd9bb72b9882a222 Mon Sep 17 00:00:00 2001 From: XingQue Date: Wed, 12 Aug 2026 17:43:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=81=E5=BE=AE=E5=AE=A2=E6=9C=8D?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=82=B9=E5=8D=95=E7=AB=AF=E7=8B=AC=E7=AB=8B?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 点单端(boss)与打手端(dashou)分字段存储,接口下发 kefu.boss,顶层 link 仍兼容打手端。 Co-authored-by: Cursor --- .../migrations/0031_club_wecom_kefu_boss.py | 27 +++++++++ jituan/models.py | 4 +- jituan/services/wecom_kefu.py | 55 ++++++++++++++----- jituan/views_wecom_kefu.py | 4 +- 4 files changed, 73 insertions(+), 17 deletions(-) create mode 100644 jituan/migrations/0031_club_wecom_kefu_boss.py diff --git a/jituan/migrations/0031_club_wecom_kefu_boss.py b/jituan/migrations/0031_club_wecom_kefu_boss.py new file mode 100644 index 0000000..c3817cd --- /dev/null +++ b/jituan/migrations/0031_club_wecom_kefu_boss.py @@ -0,0 +1,27 @@ +# Generated manually for 点单端企微客服 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('jituan', '0030_fund_freeze_dashou_yajin_role'), + ] + + operations = [ + migrations.AddField( + model_name='clubwecomkefuconfig', + name='boss_link', + field=models.CharField(blank=True, default='', max_length=512, verbose_name='点单端客服链接'), + ), + migrations.AddField( + model_name='clubwecomkefuconfig', + name='boss_corp_id', + field=models.CharField(blank=True, default='', max_length=64, verbose_name='点单端企业ID'), + ), + migrations.AlterModelOptions( + name='clubwecomkefuconfig', + options={'verbose_name': '企业微信客服配置'}, + ), + ] diff --git a/jituan/models.py b/jituan/models.py index 30d9ca3..dc74d15 100644 --- a/jituan/models.py +++ b/jituan/models.py @@ -692,9 +692,11 @@ class ClubRoleAgreementSign(QModel): class ClubWecomKefuConfig(QModel): """ 俱乐部企业微信客服链接(小程序 wx.openCustomerServiceChat)。 - 打手端 / 商家端各一套,互不影响;未配置时小程序可读 settings 兜底。 + 点单端 / 打手端 / 商家端各一套,互不影响;未配置时小程序可读 settings 兜底。 """ club_id = models.CharField(max_length=16, unique=True, db_index=True, verbose_name='俱乐部') + boss_link = models.CharField(max_length=512, blank=True, default='', verbose_name='点单端客服链接') + boss_corp_id = models.CharField(max_length=64, blank=True, default='', verbose_name='点单端企业ID') dashou_link = models.CharField(max_length=512, blank=True, default='', verbose_name='打手端客服链接') dashou_corp_id = models.CharField(max_length=64, blank=True, default='', verbose_name='打手端企业ID') merchant_link = models.CharField(max_length=512, blank=True, default='', verbose_name='商家端客服链接') diff --git a/jituan/services/wecom_kefu.py b/jituan/services/wecom_kefu.py index 13461a0..8a257c5 100644 --- a/jituan/services/wecom_kefu.py +++ b/jituan/services/wecom_kefu.py @@ -1,4 +1,4 @@ -"""俱乐部企业微信客服链接:打手端 / 商家端分端配置。""" +"""俱乐部企业微信客服链接:点单端 / 打手端 / 商家端分端配置。""" from django.conf import settings from jituan.models import ClubWecomKefuConfig @@ -25,24 +25,28 @@ def get_or_create_wecom_kefu(club_id: str): return row +def _side_dict(link: str, corp: str) -> dict: + return { + 'link': (link or '').strip(), + 'enterpriseId': (corp or '').strip(), + } + + def config_to_dict(row) -> dict: if not row: + empty = {'link': '', 'enterpriseId': ''} return { 'club_id': '', - 'dashou': {'link': '', 'enterpriseId': ''}, - 'merchant': {'link': '', 'enterpriseId': ''}, + 'boss': dict(empty), + 'dashou': dict(empty), + 'merchant': dict(empty), 'updated_by': '', } return { 'club_id': row.club_id, - 'dashou': { - 'link': (row.dashou_link or '').strip(), - 'enterpriseId': (row.dashou_corp_id or '').strip(), - }, - 'merchant': { - 'link': (row.merchant_link or '').strip(), - 'enterpriseId': (row.merchant_corp_id or '').strip(), - }, + 'boss': _side_dict(getattr(row, 'boss_link', ''), getattr(row, 'boss_corp_id', '')), + 'dashou': _side_dict(row.dashou_link, row.dashou_corp_id), + 'merchant': _side_dict(row.merchant_link, row.merchant_corp_id), 'updated_by': (row.updated_by or '').strip(), } @@ -59,10 +63,15 @@ def save_wecom_kefu(club_id: str, data: dict, updated_by: str = '') -> dict: if not row: raise ValueError('缺少俱乐部') + boss = _pick_side(data, 'boss') or _pick_side(data, 'diandan') or _pick_side(data, 'normal') dashou = _pick_side(data, 'dashou') merchant = _pick_side(data, 'merchant') - # 兼容扁平字段 + boss_link = boss.get('link', data.get('boss_link', data.get('diandan_link'))) + boss_corp = boss.get( + 'enterpriseId', + data.get('boss_corp_id', data.get('boss_enterpriseId', data.get('diandan_corp_id'))), + ) dashou_link = dashou.get('link', data.get('dashou_link')) dashou_corp = dashou.get('enterpriseId', data.get('dashou_corp_id', data.get('dashou_enterpriseId'))) merchant_link = merchant.get('link', data.get('merchant_link')) @@ -71,6 +80,10 @@ def save_wecom_kefu(club_id: str, data: dict, updated_by: str = '') -> dict: data.get('merchant_corp_id', data.get('merchant_enterpriseId')), ) + if boss_link is not None: + row.boss_link = str(boss_link or '').strip()[:LINK_MAX] + if boss_corp is not None: + row.boss_corp_id = str(boss_corp or '').strip()[:CORP_MAX] if dashou_link is not None: row.dashou_link = str(dashou_link or '').strip()[:LINK_MAX] if dashou_corp is not None: @@ -89,7 +102,10 @@ def miniapp_kefu_payload(club_id: str) -> dict: """ 小程序动态配置用。 分端优先读库;空则回落 settings(兼容旧单链接)。 - 顶层 link / enterpriseId 对齐打手端,兼容旧前端。 + - boss:点单端平台客服 / 我的联系客服 + - dashou:打手端 + - merchant:商家端 + 顶层 link / enterpriseId 仍对齐打手端,兼容旧前端浮窗。 """ fb = _settings_fallback() row = None @@ -97,6 +113,8 @@ def miniapp_kefu_payload(club_id: str) -> dict: if cid: row = ClubWecomKefuConfig.query.filter(club_id=cid).first() + boss_link = ((getattr(row, 'boss_link', '') if row else '') or '').strip() or fb['link'] + boss_corp = ((getattr(row, 'boss_corp_id', '') if row else '') or '').strip() or fb['enterpriseId'] dashou_link = ((row.dashou_link if row else '') or '').strip() or fb['link'] dashou_corp = ((row.dashou_corp_id if row else '') or '').strip() or fb['enterpriseId'] merchant_link = ((row.merchant_link if row else '') or '').strip() or fb['link'] @@ -105,6 +123,10 @@ def miniapp_kefu_payload(club_id: str) -> dict: return { 'link': dashou_link, 'enterpriseId': dashou_corp, + 'boss': { + 'link': boss_link, + 'enterpriseId': boss_corp, + }, 'dashou': { 'link': dashou_link, 'enterpriseId': dashou_corp, @@ -119,5 +141,10 @@ def miniapp_kefu_payload(club_id: str) -> dict: def resolve_side_link(club_id: str, side: str = 'merchant') -> str: """商家链接页等只需 link 字符串时用。""" payload = miniapp_kefu_payload(club_id) - key = 'merchant' if side in ('merchant', 'shangjia') else 'dashou' + if side in ('boss', 'diandan', 'normal', 'laoban'): + key = 'boss' + elif side in ('merchant', 'shangjia'): + key = 'merchant' + else: + key = 'dashou' return (payload.get(key) or {}).get('link') or payload.get('link') or '' diff --git a/jituan/views_wecom_kefu.py b/jituan/views_wecom_kefu.py index 4dce574..3dd6249 100644 --- a/jituan/views_wecom_kefu.py +++ b/jituan/views_wecom_kefu.py @@ -1,4 +1,4 @@ -"""客服后台:企业微信客服链接(打手端 / 商家端)。""" +"""客服后台:企业微信客服链接(点单端 / 打手端 / 商家端)。""" import logging from django.db import OperationalError, ProgrammingError @@ -35,7 +35,7 @@ class WecomKefuConfigView(APIView): """ POST /jituan/houtai/wecom-kefu-config action: get | save - body.save: dashou: {link, enterpriseId}, merchant: {link, enterpriseId} + body.save: boss / dashou / merchant: {link, enterpriseId} """ permission_classes = [IsAuthenticated] parser_classes = [JSONParser]