试点修复了 config 模型的拼音字段
This commit is contained in:
64
config/migrations/0002_rename_pinyin_to_pascal.py
Normal file
64
config/migrations/0002_rename_pinyin_to_pascal.py
Normal 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'),
|
||||
]
|
||||
@@ -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'),
|
||||
),
|
||||
]
|
||||
843
config/models.py
843
config/models.py
@@ -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}'
|
||||
|
||||
168
config/tasks.py
168
config/tasks.py
@@ -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
|
||||
}
|
||||
318
config/views.py
318
config/views.py
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user