试点修复了 config 模型的拼音字段

This commit is contained in:
2026-06-19 11:41:18 +08:00
parent 6f6af7553a
commit 7df8a1a1d2
10 changed files with 930 additions and 815 deletions

View File

@@ -0,0 +1,64 @@
# Generated manually to rename pinyin fields to PascalCase
# db_column is preserved, so these are no-ops at the database level
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('config', '0001_initial'),
]
operations = [
# Lunbo
migrations.RenameField(model_name='lunbo', old_name='tupian_url', new_name='ImageURL'),
migrations.RenameField(model_name='lunbo', old_name='leixing', new_name='ImageType'),
# Gonggao
migrations.RenameField(model_name='gonggao', old_name='leixing', new_name='NoticeType'),
migrations.RenameField(model_name='gonggao', old_name='jieshao', new_name='Content'),
# Qunpeizhi
migrations.RenameField(model_name='qunpeizhi', old_name='peizhiid', new_name='GroupType'),
migrations.RenameField(model_name='qunpeizhi', old_name='neirong', new_name='GroupContent'),
migrations.RenameField(model_name='qunpeizhi', old_name='qunid', new_name='GroupID'),
migrations.RenameField(model_name='qunpeizhi', old_name='jieshao', new_name='Description'),
# Tupianpeizhi
migrations.RenameField(model_name='tupianpeizhi', old_name='tupian', new_name='ImageURL'),
migrations.RenameField(model_name='tupianpeizhi', old_name='leixing', new_name='ImageType'),
migrations.RenameField(model_name='tupianpeizhi', old_name='fangwen_cishu', new_name='AccessCount'),
# Szjilu
migrations.RenameField(model_name='szjilu', old_name='zongsy', new_name='TotalIncome'),
migrations.RenameField(model_name='szjilu', old_name='zongls', new_name='TotalFlow'),
migrations.RenameField(model_name='szjilu', old_name='zongzc', new_name='TotalExpense'),
migrations.RenameField(model_name='szjilu', old_name='jrzc', new_name='DailyExpense'),
migrations.RenameField(model_name='szjilu', old_name='jrls', new_name='DailyFlow'),
# ShangjiaMoban
migrations.RenameField(model_name='shangjiamoban', old_name='yonghu_id', new_name='UserID'),
migrations.RenameField(model_name='shangjiamoban', old_name='leixing_id', new_name='ProductTypeID'),
migrations.RenameField(model_name='shangjiamoban', old_name='moban_jieshao', new_name='TemplateDesc'),
migrations.RenameField(model_name='shangjiamoban', old_name='jiage', new_name='Price'),
migrations.RenameField(model_name='shangjiamoban', old_name='fabu_shuliang', new_name='PublishedCount'),
migrations.RenameField(model_name='shangjiamoban', old_name='yongjin_qiangdan', new_name='CommissionGrabEnabled'),
migrations.RenameField(model_name='shangjiamoban', old_name='yongjin_jiage', new_name='CommissionPrice'),
migrations.RenameField(model_name='shangjiamoban', old_name='chenghao_id', new_name='TitleID'),
# ShangjiaLianjie
migrations.RenameField(model_name='shangjialianjie', old_name='yonghu_id', new_name='UserID'),
migrations.RenameField(model_name='shangjialianjie', old_name='leixing_id', new_name='ProductTypeID'),
migrations.RenameField(model_name='shangjialianjie', old_name='moban_id', new_name='TemplateID'),
migrations.RenameField(model_name='shangjialianjie', old_name='lianjie', new_name='LinkURL'),
migrations.RenameField(model_name='shangjialianjie', old_name='dingdan_id', new_name='OrderID'),
migrations.RenameField(model_name='shangjialianjie', old_name='shiyongzhe_ip', new_name='UserIP'),
migrations.RenameField(model_name='shangjialianjie', old_name='youxiao_shijian', new_name='ExpireTime'),
migrations.RenameField(model_name='shangjialianjie', old_name='lianjie_token', new_name='LinkToken'),
migrations.RenameField(model_name='shangjialianjie', old_name='previous_lianjie_id', new_name='PreviousLinkID'),
migrations.RenameField(model_name='shangjialianjie', old_name='previous_dingdan_id', new_name='PreviousOrderID'),
# TixianQuotaDefault
migrations.RenameField(model_name='tixianquotadefault', old_name='leixing', new_name='UserType'),
]

View File

@@ -0,0 +1,76 @@
# Generated by Django 4.2.27 on 2026-06-19 11:36
# Modified to use SeparateDatabaseAndState for RemoveIndex to bypass
# MySQL backend's _create_missing_fk_index check that fails after RenameField
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0002_rename_pinyin_to_pascal'),
]
operations = [
# RemoveIndex operations wrapped in SeparateDatabaseAndState
# to bypass MySQL backend's FK index check that references old field names
migrations.SeparateDatabaseAndState(
state_operations=[
migrations.RemoveIndex(
model_name='shangjialianjie',
name='shangjia_li_yonghu__9f2b25_idx',
),
migrations.RemoveIndex(
model_name='shangjialianjie',
name='shangjia_li_lianjie_99014c_idx',
),
migrations.RemoveIndex(
model_name='shangjialianjie',
name='shangjia_li_dingdan_95b682_idx',
),
migrations.RemoveIndex(
model_name='shangjiamoban',
name='shangjia_mo_yonghu__bb287d_idx',
),
migrations.RemoveIndex(
model_name='shangjiamoban',
name='shangjia_mo_yonghu__4240d0_idx',
),
],
database_operations=[
migrations.RunSQL(
sql=[
'DROP INDEX `shangjia_li_yonghu__9f2b25_idx` ON `shangjia_lianjie`',
'DROP INDEX `shangjia_li_lianjie_99014c_idx` ON `shangjia_lianjie`',
'DROP INDEX `shangjia_li_dingdan_95b682_idx` ON `shangjia_lianjie`',
'DROP INDEX `shangjia_mo_yonghu__bb287d_idx` ON `shangjia_moban`',
'DROP INDEX `shangjia_mo_yonghu__4240d0_idx` ON `shangjia_moban`',
],
reverse_sql=[
# No reverse needed - indexes will be recreated by AddIndex
],
),
],
),
# AddIndex operations - these should work fine since fields exist with new names
migrations.AddIndex(
model_name='shangjialianjie',
index=models.Index(fields=['UserID', 'TemplateID', 'ProductTypeID'], name='shangjia_li_UserID_e59d94_idx'),
),
migrations.AddIndex(
model_name='shangjialianjie',
index=models.Index(fields=['LinkToken'], name='shangjia_li_LinkTok_6b32bb_idx'),
),
migrations.AddIndex(
model_name='shangjialianjie',
index=models.Index(fields=['OrderID'], name='shangjia_li_OrderID_e7ddf9_idx'),
),
migrations.AddIndex(
model_name='shangjiamoban',
index=models.Index(fields=['UserID', 'ProductTypeID'], name='shangjia_mo_UserID_abd699_idx'),
),
migrations.AddIndex(
model_name='shangjiamoban',
index=models.Index(fields=['UserID', 'ProductTypeID', 'id'], name='shangjia_mo_UserID_2dcb54_idx'),
),
]

View File

@@ -1,434 +1,409 @@
from django.db import models
from gvsdsdk.model_base import QModel
class Lunbo(QModel):
tupian_url = models.CharField(max_length=500, null=True, blank=True, verbose_name='轮播图片URL')
leixing = models.IntegerField(null=True, blank=True, verbose_name='图片类型:1轮播2个人中心背景')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
class Meta:
db_table = 'lunbo'
verbose_name = '轮播'
verbose_name_plural = '轮播'
# 不要索引!数据量太小
class Gonggao(QModel):
leixing = models.IntegerField(null=True, blank=True, verbose_name='公告类型')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
jieshao = models.TextField(null=True, blank=True, verbose_name='公告介绍')
class Meta:
db_table = 'gonggao'
verbose_name = '公告'
verbose_name_plural = '公告'
# 不要索引!数据量太小
class Qunpeizhi(QModel):
peizhiid = models.IntegerField(null=True, blank=True, verbose_name='群类型:1.打手 2.管事')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
neirong = models.CharField(max_length=200, null=True, blank=True, verbose_name='群介绍')
qunid = models.CharField(max_length=100, null=True, blank=True, verbose_name='群id')
jieshao = models.CharField(max_length=200, null=True, blank=True, verbose_name='介绍')
class Meta:
db_table = 'qunpeizhi'
class Tupianpeizhi(QModel):
tupian = models.CharField(max_length=500, null=True, blank=True, verbose_name='配置图片URL')
leixing = models.PositiveIntegerField(null=True, blank=True, verbose_name='提现类型1:打手规则图片2默认头像图片')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
fangwen_cishu = models.PositiveIntegerField(default=0, verbose_name='访问次数') # 新增字段
class Meta:
db_table = 'tupianpeizhi'
verbose_name = '配置图片'
verbose_name_plural = '配置图片'
class Szjilu(QModel):
id = models.AutoField(primary_key=True, verbose_name='记录ID')
zongsy = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='总收益')
zongls = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='总流水')
zongzc = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='总支出')
jrzc = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='今日支出')
jrls = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='今日流水')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
class Meta:
db_table = 'szjilu'
verbose_name = '收支记录'
verbose_name_plural = '收支记录'
class ShangjiaMoban(QModel):
"""商家订单模板表 - 存储商家创建的订单模板"""
# 主键ID自动递增
id = models.AutoField(primary_key=True, verbose_name='模板ID')
# 关联字段
yonghu_id = models.CharField(max_length=7, db_index=True, verbose_name='用户ID')
leixing_id = models.PositiveIntegerField(db_index=True, verbose_name='商品类型ID')
# 模板内容
moban_jieshao = models.CharField(max_length=500, verbose_name='模板介绍')
jiage = models.DecimalField(
max_digits=10,
decimal_places=2,
verbose_name='模板价格',
help_text='单位:元'
)
# 统计字段
fabu_shuliang = models.PositiveIntegerField(default=0, verbose_name='发布数量')
yongjin_qiangdan = models.BooleanField(default=False, verbose_name='是否开启佣金抢单')
yongjin_jiage = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, verbose_name='佣金价格')
chenghao_id = models.IntegerField(null=True, blank=True, verbose_name='关联称号ID')
# 时间字段
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'shangjia_moban'
verbose_name = '商家订单模板'
verbose_name_plural = verbose_name
indexes = [
# 高频查询组合索引
models.Index(fields=['yonghu_id', 'leixing_id']),
models.Index(fields=['yonghu_id', 'leixing_id','id']),
]
# 同一个商家同一类型下模板介绍不能重复(允许修改)
unique_together = ['yonghu_id', 'leixing_id', 'moban_jieshao']
def __str__(self):
return f"模板{self.id}-{self.yonghu_id}"
class ShangjiaLianjie(QModel):
"""商家链接存储表 - 存储生成的派单链接"""
# 主键ID自动递增
id = models.AutoField(primary_key=True, verbose_name='链接ID')
# 关联字段
yonghu_id = models.CharField(max_length=7, db_index=True, verbose_name='用户ID')
leixing_id = models.PositiveIntegerField(db_index=True, verbose_name='商品类型ID')
moban_id = models.PositiveIntegerField(db_index=True, verbose_name='模板ID')
# 链接核心数据
lianjie = models.CharField(max_length=500, unique=True, verbose_name='链接地址')
#lianjie_token = models.CharField(max_length=32, unique=True, db_index=True, verbose_name='链接Token')
# 订单关联(生成订单后更新)
dingdan_id = models.CharField(max_length=32, null=True, blank=True, db_index=True, verbose_name='订单ID')
# 使用状态
is_used = models.BooleanField(default=False, verbose_name='是否已使用', db_index=True)
#shiyong_time = models.DateTimeField(null=True, blank=True, verbose_name='使用时间')
# 使用者信息
shiyongzhe_ip = models.CharField(max_length=50, null=True, blank=True, verbose_name='使用者IP')
#shiyongzhe_info = models.TextField(null=True, blank=True, verbose_name='使用者信息')
# 链接控制
#shiyong_cishu = models.PositiveIntegerField(default=1, verbose_name='可使用次数')
#yixiang_cishu = models.PositiveIntegerField(default=0, verbose_name='已使用次数')
youxiao_shijian = models.DateTimeField(null=True, blank=True, verbose_name='有效截止时间')
# 安全字段
#anquan_ma = models.CharField(max_length=100, null=True, blank=True, verbose_name='安全码')
# 新增 Token 字段
lianjie_token = models.CharField(
max_length=32,
unique=True,
db_index=True,
verbose_name='链接Token',
null=True,
blank=True # 先设置为可选,后面再设为必填
)
# 时间字段
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
# 在 ShangjiaLianjie 类中添加
# 上一个链接的ID可选记录订单被更换前的链接
previous_lianjie_id = models.PositiveIntegerField(
null=True,
blank=True,
db_index=True,
verbose_name='上一个链接ID'
)
# 上一个订单的ID可选记录被更换的旧订单ID
previous_dingdan_id = models.CharField(
max_length=32,
null=True,
blank=True,
db_index=True,
verbose_name='上一个订单ID'
)
class Meta:
db_table = 'shangjia_lianjie'
verbose_name = '商家链接'
verbose_name_plural = verbose_name
indexes = [
# 高频查询组合索引
models.Index(fields=['yonghu_id', 'moban_id','leixing_id']),
models.Index(fields=['lianjie_token']),
#models.Index(fields=['lianjie_token']),
models.Index(fields=['dingdan_id']),
#models.Index(fields=['moban_id']),
#models.Index(fields=['create_time']),
#models.Index(fields=['youxiao_shijian', 'is_used']),
]
#ordering = ['-create_time']
def __str__(self):
return f"链接{self.id}-{self.yonghu_id}"
class TixianQuotaDefault(QModel):
"""
默认每日提现限额表
"""
id = models.AutoField(primary_key=True)
leixing = models.IntegerField(
choices=[(1, '打手'), (2, '管事'), (3, '组长'),
(4, '考核官'), (5, '打手押金'), (6, '商家余额')],
unique=True,
verbose_name='用户类型'
)
default_quota = models.DecimalField(
max_digits=10,
decimal_places=2,
default=20.00,
verbose_name='默认每日提现限额(元)'
)
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'tixian_quota_default'
verbose_name = '默认提现限额'
verbose_name_plural = verbose_name
def __str__(self):
return f"{self.get_leixing_display()} 默认限额: {self.default_quota}"
class WithdrawConfig(QModel):
"""
提现模式配置
- mode = 1: 自动提现(前端展示收款码模式)
- mode = 2: 手动提现(前端展示微信零钱模式)
默认值为 2手动打款没有记录时前端也按默认 2 处理
"""
MODE_CHOICES = (
(1, '自动提现'), # 对应前端模式一
(2, '手动提现'), # 对应前端模式二
)
mode = models.IntegerField(
choices=MODE_CHOICES,
default=2,
verbose_name='提现模式'
)
created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'withdraw_config'
verbose_name = '提现模式配置'
verbose_name_plural = verbose_name
def __str__(self):
return f'提现模式: {"自动" if self.mode == 1 else "手动"}'
class AccountPermission(QModel):
"""账号权限表:记录每个账号拥有的权限及开关状态"""
account_id = models.CharField(max_length=11, db_index=True, verbose_name='账号ID')
permission_code = models.IntegerField(verbose_name='权限代码')
is_enabled = models.BooleanField(default=False, verbose_name='是否开启')
class Meta:
db_table = 'account_permission'
verbose_name = '账号权限'
verbose_name_plural = '账号权限'
unique_together = [['account_id', 'permission_code']] # 一个账号的同一权限只能有一条记录
def __str__(self):
return f"{self.account_id} 权限{self.permission_code}: {'开启' if self.is_enabled else '关闭'}"
# apps/dingdan/models.py (新增模型)
class DailyIncomeStat(QModel):
"""
每日收入统计表
记录平台每天通过微信支付获得的总收入和总笔数
"""
# 日期相关字段(便于快速筛选和分组)
date = models.DateField(verbose_name='统计日期', db_index=True, unique=True)
year = models.PositiveSmallIntegerField(verbose_name='年份')
month = models.PositiveSmallIntegerField(verbose_name='月份')
day = models.PositiveSmallIntegerField(verbose_name='日期')
# 收入统计
total_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='总收入金额')
total_count = models.PositiveIntegerField(default=0, verbose_name='总收入笔数')
# 时间戳
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'daily_income_stat'
verbose_name = '每日收入统计'
verbose_name_plural = verbose_name
indexes = [
models.Index(fields=['date']),
models.Index(fields=['year', 'month', 'day']),
]
def __str__(self):
return f"{self.date} - 收入{self.total_amount}元 - {self.total_count}"
# apps/dingdan/models.py
class DailyPayoutStat(QModel):
"""
每日出款统计表
记录平台每天通过提现/结算等方式的出款总额和总笔数
"""
date = models.DateField(verbose_name='统计日期', db_index=True, unique=True)
year = models.PositiveSmallIntegerField(verbose_name='年份')
month = models.PositiveSmallIntegerField(verbose_name='月份')
day = models.PositiveSmallIntegerField(verbose_name='日期')
total_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='出款总额')
total_count = models.PositiveIntegerField(default=0, verbose_name='出款总笔数')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'daily_payout_stat'
verbose_name = '每日出款统计'
verbose_name_plural = verbose_name
indexes = [
models.Index(fields=['date']),
models.Index(fields=['year', 'month', 'day']),
]
def __str__(self):
return f"{self.date} - 出款{self.total_amount}元 - {self.total_count}"
class PopupPage(QModel):
page_key = models.CharField(max_length=50, unique=True, db_index=True, verbose_name='页面标识')
name = models.CharField(max_length=100, verbose_name='页面名称')
description = models.TextField(blank=True, verbose_name='描述')
is_active = models.BooleanField(default=True, verbose_name='是否启用')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
ignore_user_mute = models.BooleanField(default=False, verbose_name='忽略用户今日屏蔽')
class Meta:
db_table = 'popup_page'
verbose_name = '弹窗页面'
verbose_name_plural = '弹窗页面'
def __str__(self):
return f'{self.name} ({self.page_key})'
class PopupConfig(QModel):
STRATEGY_CHOICES = (
('once', '仅一次'),
('daily', '每日'),
('weekly', '每周'),
('monthly', '每月'),
('yearly', '每年'),
('always', '始终'),
('count', '周期内次数限制'),
)
page = models.ForeignKey(PopupPage, on_delete=models.CASCADE, related_name='popups')
popup_id = models.CharField(max_length=50, verbose_name='弹窗唯一ID')
title = models.CharField(max_length=200, blank=True, verbose_name='标题(后台用)')
description = models.TextField(blank=True, verbose_name='描述(后台用)')
strategy_type = models.CharField(max_length=20, choices=STRATEGY_CHOICES, default='once')
max_count = models.PositiveIntegerField(default=1, verbose_name='周期内最大展示次数')
reset_interval = models.CharField(max_length=20, blank=True,
choices=(('day',''),('week',''),('month',''),('year','')),
verbose_name='重置周期count类型时使用')
duration = models.PositiveIntegerField(default=0, verbose_name='强制阅读秒数0=无强制)')
force_even_muted = models.BooleanField(default=False, verbose_name='强制弹出(忽略用户今日屏蔽)')
sort_order = models.PositiveIntegerField(default=0, verbose_name='展示顺序')
is_active = models.BooleanField(default=True, verbose_name='是否启用')
start_time = models.DateTimeField(null=True, blank=True, verbose_name='生效开始时间')
end_time = models.DateTimeField(null=True, blank=True, verbose_name='生效结束时间')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'popup_config'
verbose_name = '弹窗配置'
verbose_name_plural = '弹窗配置'
unique_together = ('page', 'popup_id')
ordering = ['sort_order', 'id']
def __str__(self):
return f'{self.page.name} - {self.popup_id}'
class PopupImage(QModel):
popup_config = models.ForeignKey(PopupConfig, on_delete=models.CASCADE, related_name='images')
image_url = models.CharField(max_length=500, verbose_name='图片相对路径')
text = models.TextField(blank=True, verbose_name='图片上方文字')
sort_order = models.PositiveIntegerField(default=0, verbose_name='展示顺序')
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'popup_image'
verbose_name = '弹窗图片'
verbose_name_plural = '弹窗图片'
ordering = ['sort_order', 'id']
def __str__(self):
return f'{self.popup_config.popup_id} - 图片{self.sort_order}'
from django.db import models
from gvsdsdk.model_base import QModel
class Lunbo(QModel):
ImageURL = models.CharField(max_length=500, null=True, blank=True, verbose_name='轮播图片URL')
ImageType = models.IntegerField(null=True, blank=True, verbose_name='图片类型:1轮播2个人中心背景')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
class Meta:
db_table = 'lunbo'
verbose_name = '轮播'
verbose_name_plural = '轮播'
# 不要索引!数据量太小
class Gonggao(QModel):
NoticeType = models.IntegerField(null=True, blank=True, verbose_name='公告类型')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
Content = models.TextField(null=True, blank=True, verbose_name='公告介绍')
class Meta:
db_table = 'gonggao'
verbose_name = '公告'
verbose_name_plural = '公告'
# 不要索引!数据量太小
class Qunpeizhi(QModel):
GroupType = models.IntegerField(null=True, blank=True, verbose_name='群类型:1.打手 2.管事')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
GroupContent = models.CharField(max_length=200, null=True, blank=True, verbose_name='群介绍')
GroupID = models.CharField(max_length=100, null=True, blank=True, verbose_name='群id')
Description = models.CharField(max_length=200, null=True, blank=True, verbose_name='介绍')
class Meta:
db_table = 'qunpeizhi'
class Tupianpeizhi(QModel):
ImageURL = models.CharField(max_length=500, null=True, blank=True, verbose_name='配置图片URL')
ImageType = models.PositiveIntegerField(null=True, blank=True, verbose_name='提现类型1:打手规则图片2默认头像图片')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
AccessCount = models.PositiveIntegerField(default=0, verbose_name='访问次数')
class Meta:
db_table = 'tupianpeizhi'
verbose_name = '配置图片'
verbose_name_plural = '配置图片'
class Szjilu(QModel):
id = models.AutoField(primary_key=True, verbose_name='记录ID')
TotalIncome = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='总收益')
TotalFlow = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='总流水')
TotalExpense = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='总支出')
DailyExpense = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='今日支出')
DailyFlow = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='今日流水')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
class Meta:
db_table = 'szjilu'
verbose_name = '收支记录'
verbose_name_plural = '收支记录'
class ShangjiaMoban(QModel):
"""商家订单模板表 - 存储商家创建的订单模板"""
# 主键ID自动递增
id = models.AutoField(primary_key=True, verbose_name='模板ID')
# 关联字段
UserID = models.CharField(max_length=7, db_index=True, verbose_name='用户ID')
ProductTypeID = models.PositiveIntegerField(db_index=True, verbose_name='商品类型ID')
# 模板内容
TemplateDesc = models.CharField(max_length=500, verbose_name='模板介绍')
Price = models.DecimalField(
max_digits=10,
decimal_places=2,
verbose_name='模板价格',
help_text='单位:元'
)
# 统计字段
PublishedCount = models.PositiveIntegerField(default=0, verbose_name='发布数量')
CommissionGrabEnabled = models.BooleanField(default=False, verbose_name='是否开启佣金抢单')
CommissionPrice = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, verbose_name='佣金价格')
TitleID = models.IntegerField(null=True, blank=True, verbose_name='关联称号ID')
# 时间字段
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'shangjia_moban'
verbose_name = '商家订单模板'
verbose_name_plural = verbose_name
indexes = [
# 高频查询组合索引
models.Index(fields=['UserID', 'ProductTypeID']),
models.Index(fields=['UserID', 'ProductTypeID','id']),
]
# 同一个商家同一类型下模板介绍不能重复(允许修改)
unique_together = ['UserID', 'ProductTypeID', 'TemplateDesc']
def __str__(self):
return f"模板{self.id}-{self.UserID}"
class ShangjiaLianjie(QModel):
"""商家链接存储表 - 存储生成的派单链接"""
# 主键ID自动递增
id = models.AutoField(primary_key=True, verbose_name='链接ID')
# 关联字段
UserID = models.CharField(max_length=7, db_index=True, verbose_name='用户ID')
ProductTypeID = models.PositiveIntegerField(db_index=True, verbose_name='商品类型ID')
TemplateID = models.PositiveIntegerField(db_index=True, verbose_name='模板ID')
# 链接核心数据
LinkURL = models.CharField(max_length=500, unique=True, verbose_name='链接地址')
# 订单关联(生成订单后更新)
OrderID = models.CharField(max_length=32, null=True, blank=True, db_index=True, verbose_name='订单ID')
# 使用状态
is_used = models.BooleanField(default=False, verbose_name='是否已使用', db_index=True)
# 使用者信息
UserIP = models.CharField(max_length=50, null=True, blank=True, verbose_name='使用者IP')
# 链接控制
ExpireTime = models.DateTimeField(null=True, blank=True, verbose_name='有效截止时间')
# 安全字段
LinkToken = models.CharField(
max_length=32,
unique=True,
db_index=True,
verbose_name='链接Token',
null=True,
blank=True
)
# 时间字段
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
# 上一个链接的ID可选记录订单被更换前的链接
PreviousLinkID = models.PositiveIntegerField(
null=True,
blank=True,
db_index=True,
verbose_name='上一个链接ID'
)
# 上一个订单的ID可选记录被更换的旧订单ID
PreviousOrderID = models.CharField(
max_length=32,
null=True,
blank=True,
db_index=True,
verbose_name='上一个订单ID'
)
class Meta:
db_table = 'shangjia_lianjie'
verbose_name = '商家链接'
verbose_name_plural = verbose_name
indexes = [
# 高频查询组合索引
models.Index(fields=['UserID', 'TemplateID','ProductTypeID']),
models.Index(fields=['LinkToken']),
models.Index(fields=['OrderID']),
]
def __str__(self):
return f"链接{self.id}-{self.UserID}"
class TixianQuotaDefault(QModel):
"""
默认每日提现限额表
"""
id = models.AutoField(primary_key=True)
UserType = models.IntegerField(
choices=[(1, '打手'), (2, '管事'), (3, '组长'),
(4, '考核官'), (5, '打手押金'), (6, '商家余额')],
unique=True,
verbose_name='用户类型'
)
default_quota = models.DecimalField(
max_digits=10,
decimal_places=2,
default=20.00,
verbose_name='默认每日提现限额(元)'
)
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'tixian_quota_default'
verbose_name = '默认提现限额'
verbose_name_plural = verbose_name
def __str__(self):
return f"{self.get_UserType_display()} 默认限额: {self.default_quota}"
class WithdrawConfig(QModel):
"""
提现模式配置表
- mode = 1: 自动提现(前端展示收款码模式)
- mode = 2: 手动提现(前端展示微信零钱模式)
默认值为 2手动打款没有记录时前端也按默认 2 处理
"""
MODE_CHOICES = (
(1, '自动提现'), # 对应前端模式一
(2, '手动提现'), # 对应前端模式二
)
mode = models.IntegerField(
choices=MODE_CHOICES,
default=2,
verbose_name='提现模式'
)
created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'withdraw_config'
verbose_name = '提现模式配置'
verbose_name_plural = verbose_name
def __str__(self):
return f'提现模式: {"自动" if self.mode == 1 else "手动"}'
class AccountPermission(QModel):
"""账号权限表:记录每个账号拥有的权限及开关状态"""
account_id = models.CharField(max_length=11, db_index=True, verbose_name='账号ID')
permission_code = models.IntegerField(verbose_name='权限代码')
is_enabled = models.BooleanField(default=False, verbose_name='是否开启')
class Meta:
db_table = 'account_permission'
verbose_name = '账号权限'
verbose_name_plural = '账号权限'
unique_together = [['account_id', 'permission_code']] # 一个账号的同一权限只能有一条记录
def __str__(self):
return f"{self.account_id} 权限{self.permission_code}: {'开启' if self.is_enabled else '关闭'}"
# apps/dingdan/models.py (新增模型)
class DailyIncomeStat(QModel):
"""
每日收入统计表
记录平台每天通过微信支付获得的总收入和总笔数
"""
# 日期相关字段(便于快速筛选和分组)
date = models.DateField(verbose_name='统计日期', db_index=True, unique=True)
year = models.PositiveSmallIntegerField(verbose_name='年份')
month = models.PositiveSmallIntegerField(verbose_name='月份')
day = models.PositiveSmallIntegerField(verbose_name='日期')
# 收入统计
total_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='总收入金额')
total_count = models.PositiveIntegerField(default=0, verbose_name='总收入笔数')
# 时间戳
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'daily_income_stat'
verbose_name = '每日收入统计'
verbose_name_plural = verbose_name
indexes = [
models.Index(fields=['date']),
models.Index(fields=['year', 'month', 'day']),
]
def __str__(self):
return f"{self.date} - 收入{self.total_amount}元 - {self.total_count}"
# apps/dingdan/models.py
class DailyPayoutStat(QModel):
"""
每日出款统计表
记录平台每天通过提现/结算等方式的出款总额和总笔数
"""
date = models.DateField(verbose_name='统计日期', db_index=True, unique=True)
year = models.PositiveSmallIntegerField(verbose_name='年份')
month = models.PositiveSmallIntegerField(verbose_name='月份')
day = models.PositiveSmallIntegerField(verbose_name='日期')
total_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='出款总额')
total_count = models.PositiveIntegerField(default=0, verbose_name='出款总笔数')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'daily_payout_stat'
verbose_name = '每日出款统计'
verbose_name_plural = verbose_name
indexes = [
models.Index(fields=['date']),
models.Index(fields=['year', 'month', 'day']),
]
def __str__(self):
return f"{self.date} - 出款{self.total_amount}元 - {self.total_count}"
class PopupPage(QModel):
page_key = models.CharField(max_length=50, unique=True, db_index=True, verbose_name='页面标识')
name = models.CharField(max_length=100, verbose_name='页面名称')
description = models.TextField(blank=True, verbose_name='描述')
is_active = models.BooleanField(default=True, verbose_name='是否启用')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
ignore_user_mute = models.BooleanField(default=False, verbose_name='忽略用户今日屏蔽')
class Meta:
db_table = 'popup_page'
verbose_name = '弹窗页面'
verbose_name_plural = '弹窗页面'
def __str__(self):
return f'{self.name} ({self.page_key})'
class PopupConfig(QModel):
STRATEGY_CHOICES = (
('once', '仅一次'),
('daily', '每日'),
('weekly', '每周'),
('monthly', '每月'),
('yearly', '每年'),
('always', '始终'),
('count', '周期内次数限制'),
)
page = models.ForeignKey(PopupPage, on_delete=models.CASCADE, related_name='popups')
popup_id = models.CharField(max_length=50, verbose_name='弹窗唯一ID')
title = models.CharField(max_length=200, blank=True, verbose_name='标题(后台用)')
description = models.TextField(blank=True, verbose_name='描述(后台用)')
strategy_type = models.CharField(max_length=20, choices=STRATEGY_CHOICES, default='once')
max_count = models.PositiveIntegerField(default=1, verbose_name='周期内最大展示次数')
reset_interval = models.CharField(max_length=20, blank=True,
choices=(('day',''),('week',''),('month',''),('year','')),
verbose_name='重置周期count类型时使用')
duration = models.PositiveIntegerField(default=0, verbose_name='强制阅读秒数0=无强制)')
force_even_muted = models.BooleanField(default=False, verbose_name='强制弹出(忽略用户今日屏蔽)')
sort_order = models.PositiveIntegerField(default=0, verbose_name='展示顺序')
is_active = models.BooleanField(default=True, verbose_name='是否启用')
start_time = models.DateTimeField(null=True, blank=True, verbose_name='生效开始时间')
end_time = models.DateTimeField(null=True, blank=True, verbose_name='生效结束时间')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'popup_config'
verbose_name = '弹窗配置'
verbose_name_plural = '弹窗配置'
unique_together = ('page', 'popup_id')
ordering = ['sort_order', 'id']
def __str__(self):
return f'{self.page.name} - {self.popup_id}'
class PopupImage(QModel):
popup_config = models.ForeignKey(PopupConfig, on_delete=models.CASCADE, related_name='images')
image_url = models.CharField(max_length=500, verbose_name='图片相对路径')
text = models.TextField(blank=True, verbose_name='图片上方文字')
sort_order = models.PositiveIntegerField(default=0, verbose_name='展示顺序')
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'popup_image'
verbose_name = '弹窗图片'
verbose_name_plural = '弹窗图片'
ordering = ['sort_order', 'id']
def __str__(self):
return f'{self.popup_config.popup_id} - 图片{self.sort_order}'

View File

@@ -1,85 +1,85 @@
"""
阿龙电竞 - 收支记录定时任务
处理收支记录表的每日清零
固定使用ID=1的记录
"""
from celery import shared_task
from django.db import transaction
from django.utils import timezone
from datetime import datetime
from decimal import Decimal
import logging
# 导入模型
from config.models import Szjilu
from utils.celery_utils import log_task_execution, rollback_on_failure
logger = logging.getLogger(__name__)
@shared_task
@rollback_on_failure("收支记录每日清零")
def daily_sz_reset_task():
"""
收支记录每日清零 - 每天凌晨0点5分执行
清零收支记录表的今日相关字段固定使用ID=1的记录
"""
try:
with transaction.atomic():
# 获取今天的日期
today = datetime.now().strftime('%Y-%m-%d')
logger.info(f"开始执行收支记录清零任务,日期: {today}")
# 查询ID=1的收支记录如果不存在则创建
try:
szjilu = Szjilu.objects.get(id=1)
logger.info(f"找到ID=1的收支记录")
except Szjilu.DoesNotExist:
# 创建ID=1的初始记录
szjilu = Szjilu.objects.create(
id=1,
zongsy=Decimal('0.00'),
zongls=Decimal('0.00'),
zongzc=Decimal('0.00'),
jrzc=Decimal('0.00'),
jrls=Decimal('0.00')
)
logger.info(f"创建ID=1的收支记录")
# 记录清零前的值(用于日志)
old_jrzc = szjilu.jrzc
old_jrls = szjilu.jrls
# 清零今日字段
szjilu.jrzc = Decimal('0.00')
szjilu.jrls = Decimal('0.00')
szjilu.save(update_fields=['jrzc', 'jrls', 'update_time'])
logger.info(f"收支记录清零完成,今日支出原值: {old_jrzc},今日流水原值: {old_jrls}")
result_msg = f"收支记录清零完成 - 日期: {today}, 记录ID: {szjilu.id}"
log_task_execution("收支记录每日清零", True, result_msg)
return {
"success": True,
"date": today,
"record_id": szjilu.id,
"jrzc_cleared": True,
"jrls_cleared": True,
"old_jrzc": str(old_jrzc),
"old_jrls": str(old_jrls),
"message": result_msg
}
except Exception as e:
error_msg = f"收支记录每日清零失败: {str(e)}"
logger.error(error_msg)
log_task_execution("收支记录每日清零", False, error_msg)
return {
"success": False,
"error": str(e),
"date": datetime.now().strftime('%Y-%m-%d'),
"message": error_msg
"""
阿龙电竞 - 收支记录定时任务
处理收支记录表的每日清零
固定使用ID=1的记录
"""
from celery import shared_task
from django.db import transaction
from django.utils import timezone
from datetime import datetime
from decimal import Decimal
import logging
# 导入模型
from config.models import Szjilu
from utils.celery_utils import log_task_execution, rollback_on_failure
logger = logging.getLogger(__name__)
@shared_task
@rollback_on_failure("收支记录每日清零")
def daily_sz_reset_task():
"""
收支记录每日清零 - 每天凌晨0点5分执行
清零收支记录表的今日相关字段固定使用ID=1的记录
"""
try:
with transaction.atomic():
# 获取今天的日期
today = datetime.now().strftime('%Y-%m-%d')
logger.info(f"开始执行收支记录清零任务,日期: {today}")
# 查询ID=1的收支记录如果不存在则创建
try:
szjilu = Szjilu.objects.get(id=1)
logger.info(f"找到ID=1的收支记录")
except Szjilu.DoesNotExist:
# 创建ID=1的初始记录
szjilu = Szjilu.objects.create(
id=1,
TotalIncome=Decimal('0.00'),
TotalFlow=Decimal('0.00'),
TotalExpense=Decimal('0.00'),
DailyExpense=Decimal('0.00'),
DailyFlow=Decimal('0.00')
)
logger.info(f"创建ID=1的收支记录")
# 记录清零前的值(用于日志)
old_jrzc = szjilu.DailyExpense
old_jrls = szjilu.DailyFlow
# 清零今日字段
szjilu.DailyExpense = Decimal('0.00')
szjilu.DailyFlow = Decimal('0.00')
szjilu.save(update_fields=['DailyExpense', 'DailyFlow', 'update_time'])
logger.info(f"收支记录清零完成,今日支出原值: {old_jrzc},今日流水原值: {old_jrls}")
result_msg = f"收支记录清零完成 - 日期: {today}, 记录ID: {szjilu.id}"
log_task_execution("收支记录每日清零", True, result_msg)
return {
"success": True,
"date": today,
"record_id": szjilu.id,
"jrzc_cleared": True,
"jrls_cleared": True,
"old_jrzc": str(old_jrzc),
"old_jrls": str(old_jrls),
"message": result_msg
}
except Exception as e:
error_msg = f"收支记录每日清零失败: {str(e)}"
logger.error(error_msg)
log_task_execution("收支记录每日清零", False, error_msg)
return {
"success": False,
"error": str(e),
"date": datetime.now().strftime('%Y-%m-%d'),
"message": error_msg
}

View File

@@ -132,13 +132,13 @@ class ShangpinGonggaoView(APIView):
try:
logger.info("收到商品公告和轮播图请求")
# 1. 查询公告类型为1
gonggao_obj = Gonggao.query.filter(leixing=1).first()
gonggao_obj = Gonggao.query.filter(NoticeType=1).first()
# 获取公告内容,如果没有则返回空字符串
gonggao_content = gonggao_obj.jieshao if gonggao_obj else ""
gonggao_content = gonggao_obj.Content if gonggao_obj else ""
# 2. 查询轮播图类型为1按显示顺序排序
lunbo_queryset = Lunbo.query.filter(leixing=1)
lunbo_queryset = Lunbo.query.filter(ImageType=1)
# 提取轮播图URL列表
lunbo_urls = [lunbo.tupian_url for lunbo in lunbo_queryset]
lunbo_urls = [lunbo.ImageURL for lunbo in lunbo_queryset]
# 3. 构建返回数据
response_data = {
"shangpingonggao": gonggao_content,
@@ -211,18 +211,18 @@ class AdminConfigQueryView(APIView):
}, status=status.HTTP_401_UNAUTHORIZED)
# 查询图片配置
rule_image = Tupianpeizhi.query.filter(leixing=1).first()
default_avatar = Tupianpeizhi.query.filter(leixing=2).first()
rule_image = Tupianpeizhi.query.filter(ImageType=1).first()
default_avatar = Tupianpeizhi.query.filter(ImageType=2).first()
# 查询群配置
qun_configs = Qunpeizhi.query.all()
qq_groups = []
for config in qun_configs:
qq_groups.append({
'peizhiid': config.peizhiid,
'neirong': config.neirong if config.neirong else '',
'qunid': config.qunid if config.qunid else '',
'jieshao': config.jieshao if config.jieshao else ''
'peizhiid': config.GroupType,
'neirong': config.GroupContent if config.GroupContent else '',
'qunid': config.GroupID if config.GroupID else '',
'jieshao': config.Description if config.Description else ''
})
# 查询利率配置
@@ -236,8 +236,8 @@ class AdminConfigQueryView(APIView):
# 构建返回数据
data = {
'images': {
'rule_image': rule_image.tupian if rule_image and rule_image.tupian else '',
'default_avatar': default_avatar.tupian if default_avatar and default_avatar.tupian else ''
'rule_image': rule_image.ImageURL if rule_image and rule_image.ImageURL else '',
'default_avatar': default_avatar.ImageURL if default_avatar and default_avatar.ImageURL else ''
},
'qq_groups': qq_groups,
'rates': {
@@ -374,8 +374,8 @@ class AdminUploadImageView(APIView):
# 更新数据库
with transaction.atomic():
# 获取或创建图片配置记录
tupian_peizhi, created = Tupianpeizhi.query.get_or_create(leixing=int(leixing))
tupian_peizhi.tupian = fixed_relative_url
tupian_peizhi, created = Tupianpeizhi.query.get_or_create(ImageType=int(leixing))
tupian_peizhi.ImageURL = fixed_relative_url
tupian_peizhi.save()
return Response({
@@ -454,7 +454,7 @@ class AdminUpdateConfigView(APIView):
continue
# 🔴 修复使用filter()确保查询到正确的记录
qun_configs = Qunpeizhi.query.filter(peizhiid=peizhiid)
qun_configs = Qunpeizhi.query.filter(GroupType=peizhiid)
if qun_configs.exists():
# 如果存在多个相同peizhiid的记录取第一个应该只有一个
@@ -466,27 +466,27 @@ class AdminUpdateConfigView(APIView):
jieshao = group_data.get('jieshao')
if neirong is not None:
qun_config.neirong = neirong or ''
qun_config.GroupContent = neirong or ''
if qunid is not None:
qun_config.qunid = qunid or ''
qun_config.GroupID = qunid or ''
if jieshao is not None:
qun_config.jieshao = jieshao or ''
qun_config.Description = jieshao or ''
qun_config.save()
else:
# 如果不存在创建新的使用提供的peizhiid
qun_config = Qunpeizhi.query.create(
peizhiid=peizhiid,
neirong=group_data.get('neirong', '') or '',
qunid=group_data.get('qunid', '') or '',
jieshao=group_data.get('jieshao', '') or ''
GroupType=peizhiid,
GroupContent=group_data.get('neirong', '') or '',
GroupID=group_data.get('qunid', '') or '',
Description=group_data.get('jieshao', '') or ''
)
updated_groups.append({
'peizhiid': qun_config.peizhiid,
'neirong': qun_config.neirong,
'qunid': qun_config.qunid,
'jieshao': qun_config.jieshao
'peizhiid': qun_config.GroupType,
'neirong': qun_config.GroupContent,
'qunid': qun_config.GroupID,
'jieshao': qun_config.Description
})
if updated_groups:
@@ -1349,45 +1349,45 @@ class ShangjiaMobanListView(APIView):
except (ValueError, TypeError):
label_id = None
query = Q(yonghu_id=yonghu_id, leixing_id=leixing_id)
query = Q(UserID=yonghu_id, ProductTypeID=leixing_id)
if get_type == 1: # 搜索模式
if keyword:
keyword = str(keyword).strip()
try:
mid = int(keyword)
query &= Q(id=mid) | Q(moban_jieshao__icontains=keyword)
query &= Q(id=mid) | Q(TemplateDesc__icontains=keyword)
except ValueError:
query &= Q(moban_jieshao__icontains=keyword)
query &= Q(TemplateDesc__icontains=keyword)
if min_price:
try:
query &= Q(jiage__gte=Decimal(str(min_price)))
query &= Q(Price__gte=Decimal(str(min_price)))
except:
pass
if label_id:
query &= Q(chenghao_id=label_id)
query &= Q(TitleID=label_id)
mobans = ShangjiaMoban.query.filter(query).order_by('-id')
formatted = []
for moban in mobans:
texiao_json = ''
label_name = ''
if moban.chenghao_id:
if moban.TitleID:
try:
ch = Chenghao.query.get(id=moban.chenghao_id)
ch = Chenghao.query.get(id=moban.TitleID)
label_name = ch.mingcheng
texiao_json = ch.texiao_miaoshu or ''
except Chenghao.DoesNotExist:
pass
formatted.append({
'mobanId': moban.id,
'shangpinTypeId': moban.leixing_id,
'jieshao': moban.moban_jieshao,
'jiage': str(moban.jiage),
'fabushuliang': moban.fabu_shuliang,
'commissionEnabled': moban.yongjin_qiangdan,
'commissionValue': str(moban.yongjin_jiage) if moban.yongjin_jiage is not None else None,
'labelId': moban.chenghao_id,
'shangpinTypeId': moban.ProductTypeID,
'jieshao': moban.TemplateDesc,
'jiage': str(moban.Price),
'fabushuliang': moban.PublishedCount,
'commissionEnabled': moban.CommissionGrabEnabled,
'commissionValue': str(moban.CommissionPrice) if moban.CommissionPrice is not None else None,
'labelId': moban.TitleID,
'labelName': label_name,
'texiaoJson': texiao_json,
'createTime': moban.create_time.strftime('%Y-%m-%d %H:%M:%S') if moban.create_time else ''
@@ -1405,22 +1405,22 @@ class ShangjiaMobanListView(APIView):
for moban in current_page.object_list:
texiao_json = ''
label_name = ''
if moban.chenghao_id:
if moban.TitleID:
try:
ch = Chenghao.query.get(id=moban.chenghao_id)
ch = Chenghao.query.get(id=moban.TitleID)
label_name = ch.mingcheng
texiao_json = ch.texiao_miaoshu or ''
except Chenghao.DoesNotExist:
pass
formatted.append({
'mobanId': moban.id,
'shangpinTypeId': moban.leixing_id,
'jieshao': moban.moban_jieshao,
'jiage': str(moban.jiage),
'fabushuliang': moban.fabu_shuliang,
'commissionEnabled': moban.yongjin_qiangdan,
'commissionValue': str(moban.yongjin_jiage) if moban.yongjin_jiage is not None else None,
'labelId': moban.chenghao_id,
'shangpinTypeId': moban.ProductTypeID,
'jieshao': moban.TemplateDesc,
'jiage': str(moban.Price),
'fabushuliang': moban.PublishedCount,
'commissionEnabled': moban.CommissionGrabEnabled,
'commissionValue': str(moban.CommissionPrice) if moban.CommissionPrice is not None else None,
'labelId': moban.TitleID,
'labelName': label_name,
'texiaoJson': texiao_json,
'createTime': moban.create_time.strftime('%Y-%m-%d %H:%M:%S') if moban.create_time else ''
@@ -1499,17 +1499,17 @@ class ShangjiaTianjiaMobanView(APIView):
return Response({'code': 400, 'msg': '订单介绍不能超过100字', 'data': {}}, status=400)
# 6. 佣金验证(若启用)
yongjin_qiangdan = False
yongjin_jiage = None
CommissionGrabEnabled = False
CommissionPrice = None
if commission_enabled:
yongjin_qiangdan = True
CommissionGrabEnabled = True
if not commission_value:
return Response({'code': 400, 'msg': '开启佣金时,佣金金额不能为空', 'data': {}}, status=400)
try:
comm_decimal = Decimal(str(commission_value))
if comm_decimal <= 0:
return Response({'code': 400, 'msg': '佣金必须大于0', 'data': {}}, status=400)
yongjin_jiage = comm_decimal
CommissionPrice = comm_decimal
except (InvalidOperation, ValueError, TypeError):
return Response({'code': 400, 'msg': '佣金格式错误', 'data': {}}, status=400)
@@ -1532,23 +1532,23 @@ class ShangjiaTianjiaMobanView(APIView):
# 9. 检查同一用户、同一类型下是否已存在相同介绍的模板
if ShangjiaMoban.query.filter(
yonghu_id=yonghu_id,
leixing_id=leixing_id,
moban_jieshao=jieshao
UserID=yonghu_id,
ProductTypeID=leixing_id,
TemplateDesc=jieshao
).exists():
return Response({'code': 400, 'msg': '已存在相同介绍的模板', 'data': {}}, status=400)
# 10. 执行数据库创建(事务)
with transaction.atomic():
moban = ShangjiaMoban.query.create(
yonghu_id=yonghu_id,
leixing_id=leixing_id,
moban_jieshao=jieshao,
jiage=jiage_decimal,
fabu_shuliang=0,
yongjin_qiangdan=yongjin_qiangdan,
yongjin_jiage=yongjin_jiage,
chenghao_id=cleaned_label_id
UserID=yonghu_id,
ProductTypeID=leixing_id,
TemplateDesc=jieshao,
Price=jiage_decimal,
PublishedCount=0,
CommissionGrabEnabled=yongjin_qiangdan,
CommissionPrice=yongjin_jiage,
TitleID=cleaned_label_id
)
# 11. 返回成功数据(字段与前端对齐)
@@ -1558,13 +1558,13 @@ class ShangjiaTianjiaMobanView(APIView):
'data': {
'mobanId': moban.id,
'shangpinTypeId': leixing_id,
'jieshao': moban.moban_jieshao,
'jiage': str(moban.jiage),
'fabushuliang': moban.fabu_shuliang,
'jieshao': moban.TemplateDesc,
'jiage': str(moban.Price),
'fabushuliang': moban.PublishedCount,
'createTime': moban.create_time.strftime('%Y-%m-%d %H:%M:%S'),
'commissionEnabled': moban.yongjin_qiangdan,
'commissionValue': str(moban.yongjin_jiage) if moban.yongjin_jiage is not None else None,
'labelId': moban.chenghao_id
'commissionEnabled': moban.CommissionGrabEnabled,
'commissionValue': str(moban.CommissionPrice) if moban.CommissionPrice is not None else None,
'labelId': moban.TitleID
}
})
@@ -1599,7 +1599,7 @@ class ShangjiaShanchuMobanView(APIView):
return Response({'code': 400, 'msg': '参数缺失', 'data': {}}, status=400)
try:
moban = ShangjiaMoban.query.get(id=moban_id, yonghu_id=yonghu_id, leixing_id=leixing_id)
moban = ShangjiaMoban.query.get(id=moban_id, UserID=yonghu_id, ProductTypeID=leixing_id)
except ShangjiaMoban.DoesNotExist:
return Response({'code': 404, 'msg': '模板不存在', 'data': {}}, status=404)
@@ -1645,8 +1645,8 @@ class ShangjiaGengxinMobanView(APIView):
try:
moban = ShangjiaMoban.query.get(
id=moban_id,
yonghu_id=yonghu_id,
leixing_id=leixing_id
UserID=yonghu_id,
ProductTypeID=leixing_id
)
except ShangjiaMoban.DoesNotExist:
return Response({'code': 404, 'msg': '模板不存在或无权修改', 'data': {}}, status=404)
@@ -1657,9 +1657,9 @@ class ShangjiaGengxinMobanView(APIView):
if new_jieshao:
if len(new_jieshao) > 100:
return Response({'code': 400, 'msg': '订单介绍不能超过100字', 'data': {}}, status=400)
if new_jieshao != moban.moban_jieshao:
moban.moban_jieshao = new_jieshao
update_fields.append('moban_jieshao')
if new_jieshao != moban.TemplateDesc:
moban.TemplateDesc = new_jieshao
update_fields.append('TemplateDesc')
# 修改价格
if new_jiage:
@@ -1667,18 +1667,18 @@ class ShangjiaGengxinMobanView(APIView):
jiage_decimal = Decimal(new_jiage)
if jiage_decimal <= 0 or jiage_decimal > 10000:
return Response({'code': 400, 'msg': '价格必须在0.1-10000元之间', 'data': {}}, status=400)
if jiage_decimal != moban.jiage:
moban.jiage = jiage_decimal
update_fields.append('jiage')
if jiage_decimal != moban.Price:
moban.Price = jiage_decimal
update_fields.append('Price')
except (InvalidOperation, ValueError, TypeError):
return Response({'code': 400, 'msg': '价格格式错误', 'data': {}}, status=400)
# 修改标签
if label_id is not None: # 允许传空字符串或不传传0表示清空
new_label = int(label_id) if label_id else None
if new_label != moban.chenghao_id:
moban.chenghao_id = new_label
update_fields.append('chenghao_id')
if new_label != moban.TitleID:
moban.TitleID = new_label
update_fields.append('TitleID')
# 修改佣金设置
if commission_enabled is not None:
@@ -1690,27 +1690,27 @@ class ShangjiaGengxinMobanView(APIView):
comm_decimal = Decimal(commission_value)
if comm_decimal < 0.1 or comm_decimal > 50:
return Response({'code': 400, 'msg': '佣金需在0.1-50元之间', 'data': {}}, status=400)
if moban.yongjin_qiangdan != True or moban.yongjin_jiage != comm_decimal:
moban.yongjin_qiangdan = True
moban.yongjin_jiage = comm_decimal
update_fields.extend(['yongjin_qiangdan', 'yongjin_jiage'])
if moban.CommissionGrabEnabled != True or moban.CommissionPrice != comm_decimal:
moban.CommissionGrabEnabled = True
moban.CommissionPrice = comm_decimal
update_fields.extend(['CommissionGrabEnabled', 'CommissionPrice'])
except (InvalidOperation, ValueError, TypeError):
return Response({'code': 400, 'msg': '佣金格式错误', 'data': {}}, status=400)
else:
if moban.yongjin_qiangdan != False or moban.yongjin_jiage is not None:
moban.yongjin_qiangdan = False
moban.yongjin_jiage = None
update_fields.extend(['yongjin_qiangdan', 'yongjin_jiage'])
if moban.CommissionGrabEnabled != False or moban.CommissionPrice is not None:
moban.CommissionGrabEnabled = False
moban.CommissionPrice = None
update_fields.extend(['CommissionGrabEnabled', 'CommissionPrice'])
if not update_fields:
return Response({'code': 400, 'msg': '没有修改内容', 'data': {}}, status=400)
# 检查介绍唯一性
if 'moban_jieshao' in update_fields:
if 'TemplateDesc' in update_fields:
if ShangjiaMoban.query.filter(
yonghu_id=yonghu_id,
leixing_id=leixing_id,
moban_jieshao=moban.moban_jieshao
UserID=yonghu_id,
ProductTypeID=leixing_id,
TemplateDesc=moban.TemplateDesc
).exclude(id=moban_id).exists():
return Response({'code': 400, 'msg': '已存在相同介绍的模板', 'data': {}}, status=400)
@@ -1723,13 +1723,13 @@ class ShangjiaGengxinMobanView(APIView):
'msg': '模板修改成功',
'data': {
'mobanId': moban.id,
'shangpinTypeId': moban.leixing_id,
'jieshao': moban.moban_jieshao,
'jiage': str(moban.jiage),
'fabushuliang': moban.fabu_shuliang,
'commissionEnabled': moban.yongjin_qiangdan,
'commissionValue': str(moban.yongjin_jiage) if moban.yongjin_jiage else None,
'labelId': moban.chenghao_id,
'shangpinTypeId': moban.ProductTypeID,
'jieshao': moban.TemplateDesc,
'jiage': str(moban.Price),
'fabushuliang': moban.PublishedCount,
'commissionEnabled': moban.CommissionGrabEnabled,
'commissionValue': str(moban.CommissionPrice) if moban.CommissionPrice else None,
'labelId': moban.TitleID,
'updateTime': moban.update_time.strftime('%Y-%m-%d %H:%M:%S')
}
})
@@ -1778,11 +1778,11 @@ class ShangjiaGenerateLinkView(APIView):
# 查询模板
try:
moban = ShangjiaMoban.query.get(id=moban_id, yonghu_id=user.UserUID, leixing_id=shangpin_type_id)
moban = ShangjiaMoban.query.get(id=moban_id, UserID=user.UserUID, ProductTypeID=shangpin_type_id)
except ShangjiaMoban.DoesNotExist:
return Response({'code': 400, 'msg': '模板不存在', 'data': {}}, status=400)
jiage = moban.jiage
jiage = moban.Price
if jiage > shangjia.yue:
return Response({'code': 400, 'msg': f'余额不足,当前余额{shangjia.yue}', 'data': {}}, status=400)
@@ -1794,10 +1794,10 @@ class ShangjiaGenerateLinkView(APIView):
dashou_fencheng = Decimal(str(round(float(jiage) * lilu, 2)))
# 抢单要求:根据模板是否启用佣金
chenghao_id = moban.chenghao_id
if moban.yongjin_qiangdan and moban.yongjin_jiage is not None:
chenghao_id = moban.TitleID
if moban.CommissionGrabEnabled and moban.CommissionPrice is not None:
final_yaoqiuleixing = 2 # 佣金模式
final_yongjin = moban.yongjin_jiage
final_yongjin = moban.CommissionPrice
final_huiyuan_id = ''
else:
final_yaoqiuleixing = shangpin_leixing.yaoqiuleixing or 1
@@ -1825,7 +1825,7 @@ class ShangjiaGenerateLinkView(APIView):
raw = f"{timestamp}:{dd_id}:{uid}:{salt}"
token = hashlib.sha256(raw.encode()).hexdigest()[:24]
# 确保唯一性(极小概率重复再试一次)
if ShangjiaLianjie.query.filter(lianjie_token=token).exists():
if ShangjiaLianjie.query.filter(LinkToken=token).exists():
return generate_secure_token(dd_id, uid)
return token
@@ -1848,7 +1848,7 @@ class ShangjiaGenerateLinkView(APIView):
yaoqiuleixing=final_yaoqiuleixing,
huiyuan_id=final_huiyuan_id,
yongjin=final_yongjin,
Description=moban.moban_jieshao[:2000],
Description=moban.TemplateDesc[:2000],
user1_id=f"Sj{user.UserUID}",
ImageURL=user.Avatar or '',
)
@@ -1881,18 +1881,18 @@ class ShangjiaGenerateLinkView(APIView):
# 生成链接并保存
link_url = generate_link_url(secure_token)
lianjie_obj = ShangjiaLianjie.query.create(
yonghu_id=user.UserUID,
leixing_id=shangpin_type_id,
moban_id=moban_id,
lianjie=link_url,
lianjie_token=secure_token,
dingdan_id=dingdan_id,
UserID=user.UserUID,
ProductTypeID=shangpin_type_id,
TemplateID=moban_id,
LinkURL=link_url,
LinkToken=secure_token,
OrderID=dingdan_id,
is_used=False,
youxiao_shijian=timezone.now() + timezone.timedelta(days=1)
ExpireTime=timezone.now() + timezone.timedelta(days=1)
)
# 更新模板发布数量
ShangjiaMoban.query.filter(id=moban_id).update(fabu_shuliang=F('fabu_shuliang') + 1)
ShangjiaMoban.query.filter(id=moban_id).update(PublishedCount=F('PublishedCount') + 1)
shangjia.refresh_from_db()
logger.info(f"链接生成成功 - 订单ID: {dingdan_id}, 标签: {label_name}")
@@ -1904,11 +1904,11 @@ class ShangjiaGenerateLinkView(APIView):
'linkUrl': link_url,
'newBalance': str(shangjia.yue),
'dingdanId': dingdan_id,
'dingdanJieshao': moban.moban_jieshao,
'dingdanJieshao': moban.TemplateDesc,
'jiage': str(jiage),
'labelId': chenghao_id,
'labelName': label_name,
'youxiaoShijian': lianjie_obj.youxiao_shijian.strftime('%Y-%m-%d %H:%M:%S'),
'youxiaoShijian': lianjie_obj.ExpireTime.strftime('%Y-%m-%d %H:%M:%S'),
}
})
@@ -1939,13 +1939,13 @@ class ShangjiaLianjieListView(APIView):
# 校验模板归属
try:
moban = ShangjiaMoban.query.get(id=moban_id, yonghu_id=yonghu_id)
moban = ShangjiaMoban.query.get(id=moban_id, UserID=yonghu_id)
except ShangjiaMoban.DoesNotExist:
return Response({'code': 404, 'msg': '模板不存在或无权查看', 'data': {}}, status=404)
links = ShangjiaLianjie.query.filter(
yonghu_id=yonghu_id,
moban_id=moban_id,
UserID=yonghu_id,
TemplateID=moban_id,
is_used=(used == 1)
).order_by('-create_time')
@@ -1958,11 +1958,11 @@ class ShangjiaLianjieListView(APIView):
for link in current_page.object_list:
data_list.append({
'id': link.id,
'lianjie': link.lianjie,
'lianjie_token': link.lianjie_token,
'lianjie': link.LinkURL,
'LinkToken': link.LinkToken,
'is_used': link.is_used,
'dingdan_id': link.dingdan_id,
'youxiao_shijian': link.youxiao_shijian.strftime('%Y-%m-%d %H:%M:%S') if link.youxiao_shijian else '',
'dingdan_id': link.OrderID,
'ExpireTime': link.ExpireTime.strftime('%Y-%m-%d %H:%M:%S') if link.ExpireTime else '',
'create_time': link.create_time.strftime('%Y-%m-%d %H:%M:%S')
})
@@ -2138,8 +2138,8 @@ class KehuGetDingdanLianjieView(APIView):
# 5. 查询链接记录
try:
lianjie_obj = ShangjiaLianjie.query.select_related().get(lianjie_token=token)
logger.info(f"找到链接记录 - 链接ID: {lianjie_obj.id}, 商家ID: {lianjie_obj.yonghu_id}")
lianjie_obj = ShangjiaLianjie.query.select_related().get(LinkToken=token)
logger.info(f"找到链接记录 - 链接ID: {lianjie_obj.id}, 商家ID: {lianjie_obj.UserID}")
except ShangjiaLianjie.DoesNotExist:
logger.warning(f"链接不存在 - Token: {token[:8]}..., IP: {client_ip}")
return Response({
@@ -2157,8 +2157,8 @@ class KehuGetDingdanLianjieView(APIView):
# 6. 更新访问者IP无论是否已使用都记录最新访问IP
try:
lianjie_obj.shiyongzhe_ip = client_ip
lianjie_obj.save(update_fields=['shiyongzhe_ip'])
lianjie_obj.UserIP = client_ip
lianjie_obj.save(update_fields=['UserIP'])
logger.info(f"更新访问者IP成功: {client_ip}")
except Exception as e:
logger.warning(f"更新IP失败: {str(e)}")
@@ -2166,8 +2166,8 @@ class KehuGetDingdanLianjieView(APIView):
# 7. 检查链接有效期
'''now = timezone.now()
if lianjie_obj.youxiao_shijian and lianjie_obj.youxiao_shijian < now:
logger.warning(f"链接已过期 - 过期时间: {lianjie_obj.youxiao_shijian}, 当前: {now}")
if lianjie_obj.ExpireTime and lianjie_obj.ExpireTime < now:
logger.warning(f"链接已过期 - 过期时间: {lianjie_obj.ExpireTime}, 当前: {now}")
return Response({
'code': 400,
'msg': '链接已过期',
@@ -2177,25 +2177,25 @@ class KehuGetDingdanLianjieView(APIView):
# 8. 准备返回数据
response_data = {
'is_used': lianjie_obj.is_used,
'dingdan_id': lianjie_obj.dingdan_id or '',
'youxiao_shijian': lianjie_obj.youxiao_shijian.strftime(
'%Y-%m-%d %H:%M:%S') if lianjie_obj.youxiao_shijian else '',
'dingdan_id': lianjie_obj.OrderID or '',
'youxiao_shijian': lianjie_obj.ExpireTime.strftime(
'%Y-%m-%d %H:%M:%S') if lianjie_obj.ExpireTime else '',
}
# 9. 获取订单信息
if lianjie_obj.dingdan_id:
if lianjie_obj.OrderID:
try:
# 查询订单主表
dingdan_obj = Order.query.get(OrderID=lianjie_obj.dingdan_id)
dingdan_obj = Order.query.get(OrderID=lianjie_obj.OrderID)
# 获取商家昵称
shangjia_nicheng = ''
try:
user_main = User.query.get(UserUID=lianjie_obj.yonghu_id)
user_main = User.query.get(UserUID=lianjie_obj.UserID)
shangjia_obj = user_main.ShopProfile
shangjia_nicheng = shangjia_obj.nicheng
except (User.DoesNotExist, UserShangjia.DoesNotExist):
logger.warning(f"商家信息不存在 - 用户ID: {lianjie_obj.yonghu_id}")
logger.warning(f"商家信息不存在 - 用户ID: {lianjie_obj.UserID}")
# ========== 新增:确定俱乐部配置 ==========
# 默认头像(相对路径)
@@ -2217,7 +2217,7 @@ class KehuGetDingdanLianjieView(APIView):
'default_avatar': default_avatar,
'goeasy_appkey': goeasy_appkey,
# 前端用于连接GoEasy的自身用户ID固定B前缀+商家ID
'self_user_id': f"B{lianjie_obj.yonghu_id}" if lianjie_obj.yonghu_id else '',
'self_user_id': f"B{lianjie_obj.UserID}" if lianjie_obj.UserID else '',
}
# 如果已使用,返回已填写的信息
@@ -2237,14 +2237,14 @@ class KehuGetDingdanLianjieView(APIView):
shangjia_biaoshi = ''
try:
shangjia_kuozhan = MerchantOrderExt.query.select_related('Order').filter(
Order__OrderID=lianjie_obj.dingdan_id
Order__OrderID=lianjie_obj.OrderID
).first()
if shangjia_kuozhan and shangjia_kuozhan.MerchantID:
shangjia_biaoshi = f'Sj{shangjia_kuozhan.MerchantID}'
logger.info(f"生成商家标识: {shangjia_biaoshi}")
else:
logger.info(f"订单 {lianjie_obj.dingdan_id} 没有商家订单扩展信息")
logger.info(f"订单 {lianjie_obj.OrderID} 没有商家订单扩展信息")
except Exception as e:
logger.error(f"查询商家订单扩展异常: {str(e)}", exc_info=True)
@@ -2258,7 +2258,7 @@ class KehuGetDingdanLianjieView(APIView):
response_data.update(dingdan_info)
except Order.DoesNotExist:
logger.error(f"订单不存在 - 订单ID: {lianjie_obj.dingdan_id}")
logger.error(f"订单不存在 - 订单ID: {lianjie_obj.OrderID}")
response_data.update({
'jieshao': '',
'jiage': '0.00',
@@ -2437,9 +2437,9 @@ class KehuTianxieDingdanView(APIView):
# 9. 查询链接记录
try:
lianjie_obj = ShangjiaLianjie.query.get(lianjie_token=token)
lianjie_obj = ShangjiaLianjie.query.get(LinkToken=token)
logger.info(
f"找到链接记录 - 链接ID: {lianjie_obj.id}, 商家ID: {lianjie_obj.yonghu_id}, 是否已使用: {lianjie_obj.is_used}")
f"找到链接记录 - 链接ID: {lianjie_obj.id}, 商家ID: {lianjie_obj.UserID}, 是否已使用: {lianjie_obj.is_used}")
except ShangjiaLianjie.DoesNotExist:
logger.warning(f"链接不存在 - Token: {token[:8]}..., IP: {client_ip}")
return Response({
@@ -2450,8 +2450,8 @@ class KehuTianxieDingdanView(APIView):
# 10. 检查链接有效期
now = timezone.now()
if lianjie_obj.youxiao_shijian and lianjie_obj.youxiao_shijian < now:
logger.warning(f"链接已过期 - 过期时间: {lianjie_obj.youxiao_shijian}")
if lianjie_obj.ExpireTime and lianjie_obj.ExpireTime < now:
logger.warning(f"链接已过期 - 过期时间: {lianjie_obj.ExpireTime}")
return Response({
'code': 400,
'msg': '链接已过期',
@@ -2523,17 +2523,17 @@ class KehuTianxieDingdanView(APIView):
try:
with transaction.atomic():
# 更新链接记录
lianjie_obj.shiyongzhe_ip = client_ip
lianjie_obj.UserIP = client_ip
lianjie_obj.is_used = True
lianjie_obj.save(update_fields=['shiyongzhe_ip', 'is_used'])
lianjie_obj.save(update_fields=['UserIP', 'is_used'])
logger.info(f"更新链接记录成功 - 链接ID: {lianjie_obj.id}, 设置为已使用")
# 查询订单
if not lianjie_obj.dingdan_id:
if not lianjie_obj.OrderID:
logger.error(f"链接记录中订单ID为空 - 链接ID: {lianjie_obj.id}")
raise ValueError("订单ID为空")
dingdan_obj = Order.query.get(OrderID=lianjie_obj.dingdan_id)
dingdan_obj = Order.query.get(OrderID=lianjie_obj.OrderID)
# 检查订单状态是否为13灰色状态
if dingdan_obj.Status != 13:
@@ -2571,12 +2571,12 @@ class KehuTianxieDingdanView(APIView):
# 获取商家信息用于返回
try:
user_main = User.query.get(UserUID=lianjie_obj.yonghu_id)
user_main = User.query.get(UserUID=lianjie_obj.UserID)
shangjia_obj = user_main.ShopProfile
shangjia_mingcheng = shangjia_obj.nicheng
except:
shangjia_mingcheng = f"商家{lianjie_obj.yonghu_id}"
logger.warning(f"获取商家昵称失败,使用默认 - 用户ID: {lianjie_obj.yonghu_id}")
shangjia_mingcheng = f"商家{lianjie_obj.UserID}"
logger.warning(f"获取商家昵称失败,使用默认 - 用户ID: {lianjie_obj.UserID}")
# 14. 返回成功响应
response_data = {
@@ -2594,7 +2594,7 @@ class KehuTianxieDingdanView(APIView):
# 新方法(行为驱动,更安全)
update_shangjia_daily(
yonghuid=lianjie_obj.yonghu_id,
yonghuid=lianjie_obj.UserID,
amount=Decimal(str(dingdan_obj.Amount)),
action=1 # 1 = 派发
)
@@ -2606,7 +2606,7 @@ class KehuTianxieDingdanView(APIView):
}, status=status.HTTP_200_OK)
except Order.DoesNotExist:
logger.error(f"订单不存在 - 订单ID: {lianjie_obj.dingdan_id}")
logger.error(f"订单不存在 - 订单ID: {lianjie_obj.OrderID}")
return Response({
'code': 500,
'msg': '订单数据异常',
@@ -2699,7 +2699,7 @@ class GuanZhuAListView(APIView):
def post(self, request):
try:
# 查询类型为3的所有记录
qs = Tupianpeizhi.query.filter(leixing=3)
qs = Tupianpeizhi.query.filter(ImageType=3)
if not qs.exists():
return Response({
'code': 0,
@@ -2712,7 +2712,7 @@ class GuanZhuAListView(APIView):
}, status=status.HTTP_200_OK)
# 获取所有图片的相对URL
images = list(qs.values_list('tupian', flat=True))
images = list(qs.values_list('ImageURL', flat=True))
# 获取最新更新时间取所有记录的update_time最大值
last_update = qs.aggregate(Max('update_time'))['update_time__max']
@@ -2720,8 +2720,8 @@ class GuanZhuAListView(APIView):
# 原子性增加访问次数
# 先更新所有记录,再获取更新后的最大次数
qs.update(fangwen_cishu=F('fangwen_cishu') + 1)
visit_count = qs.aggregate(Max('fangwen_cishu'))['fangwen_cishu__max'] or 0
qs.update(AccessCount=F('AccessCount') + 1)
visit_count = qs.aggregate(Max('AccessCount'))['AccessCount__max'] or 0
return Response({
'code': 0,