From 7c9db3f3604ef8d1979d1f758459b80bfb7df589 Mon Sep 17 00:00:00 2001 From: XingQue Date: Sun, 28 Jun 2026 17:41:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=81=87=E5=8D=95=E7=A7=8D=E5=AD=90?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E3=80=81=E5=95=86=E5=AE=B6=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E3=80=81=E8=BF=94=E5=9B=9E=E9=9A=8F=E6=9C=BA?= =?UTF-8?q?=E9=A1=BA=E5=BA=8F=E4=B8=8E=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- orders/management/__init__.py | 0 orders/management/commands/__init__.py | 0 .../commands/seed_fake_grab_orders.py | 154 ++++++++++++++++++ .../0011_fakegraborder_merchantnickname.py | 22 +++ orders/models.py | 4 + orders/services/fake_order_pool.py | 29 +++- 6 files changed, 201 insertions(+), 8 deletions(-) create mode 100644 orders/management/__init__.py create mode 100644 orders/management/commands/__init__.py create mode 100644 orders/management/commands/seed_fake_grab_orders.py create mode 100644 orders/migrations/0011_fakegraborder_merchantnickname.py diff --git a/orders/management/__init__.py b/orders/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/orders/management/commands/__init__.py b/orders/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/orders/management/commands/seed_fake_grab_orders.py b/orders/management/commands/seed_fake_grab_orders.py new file mode 100644 index 0000000..231b334 --- /dev/null +++ b/orders/management/commands/seed_fake_grab_orders.py @@ -0,0 +1,154 @@ +"""写入抢单大厅假单种子数据。用法: python manage.py seed_fake_grab_orders --club-id xq --leixing-id 1""" +import random +import time + +from django.core.management.base import BaseCommand +from django.utils import timezone + +from orders.models import FakeGrabOrder + +DEFAULT_AVATAR = 'a_long/morentouxiang.jpg' + +COMMON_TAIL = ( + '下单凑七套,不卡保底,不要私藏变卖,私藏变卖老板必退款,' + '陪护也不能私藏,不能藏一丁点装备和变卖,不然必退款和罚款。' +) + +# 7 个模板(各生成 2 条 = 14 条) +TEMPLATE_ROWS = [ + { + 'title': '2100W', + 'description': f'打手选图保底2100W,{COMMON_TAIL}', + 'amount': '35.00', + }, + { + 'title': '4光子鸡', + 'description': ( + '单据4个光子鸡,不出,一直打,下单凑七套,装备和收益都归老板,' + '不卡保底,不要私藏变卖,私藏变卖老板必退款,陪护也不能私藏,' + '不能藏一丁点装备和变卖,不然必退款和罚款。' + ), + 'amount': '30.00', + }, + { + 'title': '3金光', + 'description': ( + '单局出3个金光,下单凑七套,装备和收益都归老板,' + '不卡保底,不要私藏变卖,私藏变卖老板必退款,陪护也不能私藏,' + '不能藏一丁点装备和变卖,不然必退款和罚款。' + ), + 'amount': '20.00', + }, + { + 'title': '1500W', + 'description': f'打手选图保底1500W,{COMMON_TAIL}', + 'amount': '25.00', + }, + { + 'title': '300W', + 'description': f'保底,300w以上,{COMMON_TAIL}', + 'amount': '6.00', + }, + { + 'title': '4金条', + 'description': ( + '单据4根,金条不出,一直打,下单凑七套,装备和收益都归老板,' + '不卡保底,不要私藏变卖,私藏变卖老板必退款,陪护也不能私藏,' + '不能藏一丁点装备和变卖,不然必退款和罚款。' + ), + 'amount': '18.00', + }, + { + 'title': '1000W', + 'description': f'打手选图保底1000W,{COMMON_TAIL}', + 'amount': '15.00', + }, +] + +MERCHANT_NAMES = [ + '官方直营店', + '接单秒结', + '没实力的别接', + '骂老板4千家', +] + +# 14 条:平台 5 + 商家 9;优质商家 6(仅商家单) +# 索引 0-13 对应 7 模板各 2 条 +PLATFORM_INDEXES = {0, 1, 2, 3, 4} +PREMIUM_MERCHANT_INDEXES = {5, 6, 7, 8, 9, 10} +REMARK_INDEXES = {2, 5, 8, 11} +REMARK_TEXT = '打的好奖励鸡腿' + +POOL_USER_IDS = ['3829104', '5829104', '1928374', '6649201', '7731045', '8812345'] + + +def _gen_order_id(used): + while True: + oid = f'JD{int(time.time() * 1000)}{random.randint(1000, 9999)}' + if oid not in used: + used.add(oid) + return oid + + +class Command(BaseCommand): + help = '写入抢单大厅假单(7 模板 ×2 = 14 条,可重复执行会先清理同俱乐部+类型旧 JD 假单)' + + def add_arguments(self, parser): + parser.add_argument('--club-id', default='xq', help='俱乐部 ID,默认 xq') + parser.add_argument('--leixing-id', type=int, default=1, help='商品类型 ID(与抢单大厅 Tab 一致)') + parser.add_argument('--no-clear', action='store_true', help='不清理旧 JD 假单,直接追加(可能 ID 冲突)') + + def handle(self, *args, **options): + club_id = (options['club_id'] or 'xq').strip() + leixing_id = int(options['leixing_id']) + now = timezone.now() + + if not options['no_clear']: + deleted, _ = FakeGrabOrder.query.filter( + ClubID=club_id, + ProductTypeID=leixing_id, + OrderID__startswith='JD', + ).delete() + self.stdout.write(f'已清理旧假单 {deleted} 条(club={club_id}, leixing={leixing_id})') + + used_ids = set() + expanded = [] + for tpl in TEMPLATE_ROWS: + expanded.append(tpl) + expanded.append(tpl) + + created = 0 + for idx, tpl in enumerate(expanded): + is_platform = idx in PLATFORM_INDEXES + is_premium = idx in PREMIUM_MERCHANT_INDEXES and not is_platform + remark = REMARK_TEXT if idx in REMARK_INDEXES else '' + + merchant_name = '' + if not is_platform: + merchant_name = MERCHANT_NAMES[idx % len(MERCHANT_NAMES)] + + dispatcher_id = random.choice(POOL_USER_IDS) + + FakeGrabOrder.query.create( + OrderID=_gen_order_id(used_ids), + Amount=tpl['amount'], + ProductTypeID=leixing_id, + Description=tpl['description'], + Remark=remark, + DispatcherUserID=dispatcher_id, + DispatcherAvatar=DEFAULT_AVATAR, + MerchantNickname=merchant_name, + IsPremiumMerchant=is_premium, + Platform=1 if is_platform else 2, + ClubID=club_id, + SortOrder=100 - idx, + CreateTime=now, + UpdateTime=now, + ) + created += 1 + + self.stdout.write(self.style.SUCCESS( + f'假单种子完成:新增 {created} 条 | club={club_id} leixing_id={leixing_id} ' + f'(平台单 {len(PLATFORM_INDEXES)} 商家单 {created - len(PLATFORM_INDEXES)} ' + f'优质商家 {len(PREMIUM_MERCHANT_INDEXES)})' + )) diff --git a/orders/migrations/0011_fakegraborder_merchantnickname.py b/orders/migrations/0011_fakegraborder_merchantnickname.py new file mode 100644 index 0000000..26897da --- /dev/null +++ b/orders/migrations/0011_fakegraborder_merchantnickname.py @@ -0,0 +1,22 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('orders', '0010_fakegraborder'), + ] + + operations = [ + migrations.AddField( + model_name='fakegraborder', + name='MerchantNickname', + field=models.CharField( + blank=True, + db_column='shangjia_nicheng', + max_length=50, + null=True, + verbose_name='商家名称(假单展示)', + ), + ), + ] diff --git a/orders/models.py b/orders/models.py index 19c880b..632e426 100644 --- a/orders/models.py +++ b/orders/models.py @@ -1067,6 +1067,10 @@ class FakeGrabOrder(QModel): max_length=500, null=True, blank=True, db_column='paidan_touxiang', verbose_name='派单者头像(展示用默认头像)', ) + MerchantNickname = models.CharField( + max_length=50, null=True, blank=True, + db_column='shangjia_nicheng', verbose_name='商家名称(假单展示)', + ) IsPremiumMerchant = models.BooleanField( default=False, db_column='is_youzhi_shangjia', verbose_name='是否优质商家', diff --git a/orders/services/fake_order_pool.py b/orders/services/fake_order_pool.py index ba15063..ba59ae1 100644 --- a/orders/services/fake_order_pool.py +++ b/orders/services/fake_order_pool.py @@ -1,7 +1,10 @@ """抢单大厅假单:无资格/封禁打手仅展示假数据。""" +import random +from datetime import timedelta from decimal import Decimal from django.core.exceptions import ObjectDoesNotExist +from django.utils import timezone from rest_framework.response import Response from backend.utils import fmt_datetime, pick_leixing_id @@ -36,14 +39,22 @@ def dashou_should_use_fake_pool(user): return True -def _format_fake_row(row): +def _random_display_time_str(): + """返回给前端的创建时间:当前请求时刻 2~5 分钟前的随机时间。""" + seconds_ago = random.randint(120, 300) + dt = timezone.now() - timedelta(seconds=seconds_ago) + return fmt_datetime(dt) + + +def _format_fake_row(row, display_time=None): """字段与 DashouDingdanHuoquView 真实单列表保持一致。""" avatar = DEFAULT_DISPATCHER_AVATAR platform = int(row.Platform or 1) oid = row.OrderID price = float(row.Amount or 0) - ct = fmt_datetime(row.CreateTime) + ct = display_time or _random_display_time_str() zid = (row.DispatcherUserID or '').strip() + sj_name = (getattr(row, 'MerchantNickname', None) or '').strip() return { 'dingdan_id': oid, @@ -59,7 +70,7 @@ def _format_fake_row(row): 'beizhu': row.Remark or '', 'creat_time': ct, 'create_time': ct, - 'sjnicheng': '', + 'sjnicheng': sj_name if platform == 2 else '', 'sj_avatar': avatar if platform == 2 else '', 'zhiding_uid': zid, 'zhiding_avatar': avatar, @@ -85,12 +96,14 @@ def build_fake_order_pool_response(request): if leixing_id is not None: qs = qs.filter(ProductTypeID=leixing_id) - qs = qs.order_by('-SortOrder', '-CreateTime') - total = qs.count() - offset = (page - 1) * page_size - rows = list(qs[offset:offset + page_size]) + rows = list(qs) + random.shuffle(rows) - formatted_list = [_format_fake_row(r) for r in rows] + total = len(rows) + offset = (page - 1) * page_size + page_rows = rows[offset:offset + page_size] + + formatted_list = [_format_fake_row(r) for r in page_rows] has_more = (page * page_size) < total return Response({