feat: 假单种子脚本、商家名称字段、返回随机顺序与时间

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-06-28 17:41:32 +08:00
parent b050a6895b
commit 7c9db3f360
6 changed files with 201 additions and 8 deletions

View File

View File

View File

@@ -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)}'
))

View File

@@ -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='商家名称(假单展示)',
),
),
]

View File

@@ -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='是否优质商家',

View File

@@ -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({