from django.db import models class Lunbo(models.Model): 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(models.Model): 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(models.Model): 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(models.Model): 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(models.Model): 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 = '收支记录' # models/shangjia_moban.py from django.db import models class ShangjiaMoban(models.Model): """商家订单模板表 - 存储商家创建的订单模板""" # 主键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='发布数量') # 时间字段 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') update_time = models.DateTimeField(auto_now=True, 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') 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}" # models/shangjia_lianjie.py from django.db import models class ShangjiaLianjie(models.Model): """商家链接存储表 - 存储生成的派单链接""" # 主键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='更新时间') # 上一个链接的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' ) # 上一个链接的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(models.Model): """ 默认每日提现限额表 """ id = models.AutoField(primary_key=True) leixing = models.IntegerField( choices=[(1, '打手'), (2, '管事'), (3, '组长'), (4, '打手总额'), (5, '管事总额'), (6, '组长总额'), (7, '考核官总额'), (8, '打手押金总额'), (9, '商家余额总额')], 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(models.Model): """ 提现模式配置表 - mode = 1: 自动提现(前端展示收款码模式) - mode = 2: 手动提现(前端展示微信零钱模式) 默认值为 2(手动打款),没有记录时前端也按默认 2 处理 """ MODE_CHOICES = ( (1, '自动提现'), # 对应前端模式一 (2, '手动提现'), # 对应前端模式二 ) mode = models.IntegerField( choices=MODE_CHOICES, default=2, verbose_name='提现模式' ) dongjie_quanju_enabled = models.BooleanField(default=False, 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 "手动"}' # apps/club/models.py from django.db import models class Club(models.Model): """合作俱乐部/平台信息表""" # 自己的俱乐部ID(6位字符) club_id = models.CharField(max_length=6, db_index=True, verbose_name='本俱乐部ID') # 对方的俱乐部ID(6位字符) partner_club_id = models.CharField(max_length=6, unique= True,verbose_name='对方俱乐部ID') # 是否开启平台互通(双方互相同意才可传递订单) is_interop_enabled = models.BooleanField(default=False, verbose_name='是否开启平台互通') # 是否同意接收对方订单(对方同意我方发单,但接收订单需我方同意) is_receive_enabled = models.BooleanField(default=False, verbose_name='是否同意接收对方订单') # 打手分红费率(默认100%,即原金额,对方平台打手分成 = 我方打手分成 × 费率) dashou_rate = models.DecimalField(max_digits=5, decimal_places=4, default=1.0000, verbose_name='打手分红费率') # 新增字段:接收对方订单时打手分红费率(默认100%) receive_rate = models.DecimalField(max_digits=5, decimal_places=4, default=1.0000, verbose_name='接收打手分红费率') # 对方服务器域名(完整 URL,如 https://api.partner.com) partner_domain = models.URLField(max_length=200, blank=True, 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 = 'club' verbose_name = '俱乐部' verbose_name_plural = '俱乐部' indexes = [ models.Index(fields=['club_id']), models.Index(fields=['partner_club_id']), ] class OrderTypeMapping(models.Model): """对方订单类型 → 我方订单类型 映射表""" partner_club_id = models.CharField(max_length=6, db_index=True, verbose_name='对方俱乐部ID') partner_type_id = models.PositiveIntegerField(verbose_name='对方订单类型ID') partner_type_name = models.CharField(max_length=100, verbose_name='对方订单类型名称') our_type_id = models.PositiveIntegerField(verbose_name='我方订单类型ID') our_type_name = models.CharField(max_length=100, 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 = 'order_type_mapping' verbose_name = '订单类型映射' verbose_name_plural = '订单类型映射' unique_together = (('partner_club_id', 'partner_type_id'),) class ClubConfig(models.Model): """ 俱乐部配置信息表 存储俱乐部(我方或对方)的详细配置,如昵称、头像、API密钥等 """ # 俱乐部ID(6位字符,与 Club 表中的 club_id 或 partner_club_id 对应) club_id = models.CharField(max_length=6, db_index=True, verbose_name='俱乐部ID') # 俱乐部昵称 club_nickname = models.CharField(max_length=50, blank=True, default='', verbose_name='俱乐部昵称') # 俱乐部头像地址(URL) club_avatar = models.CharField(max_length=500, blank=True, default='', verbose_name='俱乐部头像地址') # 俱乐部后台域名(用于API请求) backend_domain = models.CharField(max_length=200, blank=True, default='', verbose_name='后台域名') # 聊天API密钥 chat_api_key = models.CharField(max_length=200, blank=True, default='', verbose_name='聊天API密钥') # 聊天API ID chat_api_id = models.CharField(max_length=200, blank=True, default='', verbose_name='聊天API ID') # 客服路径 customer_service_api_url = models.CharField(max_length=200, blank=True, default='', verbose_name='客服API URL') customer_service_corp_id = models.CharField(max_length=100, blank=True, default='', verbose_name='客服企业ID') # 存储桶域名(如腾讯云COS、阿里云OSS的访问域名) storage_bucket_domain = models.CharField(max_length=500, blank=True, default='', verbose_name='存储桶域名') storage_bucket_name = models.CharField(max_length=100, blank=True, default='', verbose_name='存储桶名称') # 标识是我方还是对方俱乐部:1=我方,0=对方(默认0) is_self = models.SmallIntegerField( choices=((0, '对方'), (1, '我方')), default=0, db_index=True, 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 = 'club_config' verbose_name = '俱乐部配置' verbose_name_plural = '俱乐部配置' # 联合唯一约束:同一个俱乐部ID只能有一条记录(无论我方对方),若需要分开则可不加 # 但通常一个俱乐部只会存在一种身份,所以加联合唯一约束更安全 unique_together = [['club_id']] # 确保每个club_id只有一条配置记录 def __str__(self): return f"{self.club_nickname or self.club_id} ({'我方' if self.is_self else '对方'})" from django.db import models class AccountPermission(models.Model): """账号权限表:记录每个账号拥有的权限及开关状态""" 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 DailyDispatchStat(models.Model): """ 每日派单统计表 记录每天向各合作俱乐部派单的数据,用于替代俱乐部表中的累计字段。 """ # 日期相关字段(便于快速筛选) date = models.DateField(verbose_name='统计日期', db_index=True) year = models.PositiveSmallIntegerField(verbose_name='年份') month = models.PositiveSmallIntegerField(verbose_name='月份') day = models.PositiveSmallIntegerField(verbose_name='日期') # 派单方向:1=我方派单(我方订单被对方抢单),2=对方派单(对方订单被我方抢单) direction = models.PositiveSmallIntegerField(choices=[(1, '我方派单'), (2, '对方派单')], verbose_name='派单方向') # 对方俱乐部ID partner_club_id = models.CharField(max_length=6, db_index=True, verbose_name='对方俱乐部ID') # 派单数 dispatch_count = models.PositiveIntegerField(default=0, verbose_name='派单数') # 派单总额(打手分成 * 费率) dispatch_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='派单总额') # 抢单统计(我方实际抢到的对方派单数/金额) claimed_count = models.PositiveIntegerField(default=0, verbose_name='抢单数') claimed_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='抢单总额') # 成交订单数(预留,当前暂不更新) success_count = models.PositiveIntegerField(default=0, verbose_name='成交订单数') # 成交总额(预留) success_amount = models.DecimalField(max_digits=12, 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 = 'daily_dispatch_stat' verbose_name = '每日派单统计' verbose_name_plural = verbose_name indexes = [ models.Index(fields=['year', 'month', 'day', 'direction', 'partner_club_id']), models.Index(fields=['date']), ] def __str__(self): return f"{self.date} - 方向{self.direction} - 俱乐部{self.partner_club_id} - 派单{self.dispatch_count}次" # apps/dingdan/models.py (新增模型) class DailyIncomeStat(models.Model): """ 每日收入统计表 记录平台每天通过微信支付获得的总收入和总笔数 """ # 日期相关字段(便于快速筛选和分组) 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(models.Model): """ 每日出款统计表 记录平台每天通过提现/结算等方式的出款总额和总笔数 """ 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}笔" from django.db import models class PopupPage(models.Model): 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(models.Model): 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(models.Model): 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}' class HuashuConfig(models.Model): """小程序话术/确认弹窗配置(聊天发图、客服欢迎/自动回复、商家派单等)""" SCENE_CHAT_IMAGE_CONFIRM = 'chat_image_confirm' SCENE_CS_WELCOME = 'cs_welcome' SCENE_CS_AUTO_REPLY = 'cs_auto_reply' SCENE_MERCHANT_DISPATCH = 'merchant_dispatch_confirm' SCENE_CHOICES = ( (SCENE_CHAT_IMAGE_CONFIRM, '聊天发图确认'), (SCENE_CS_WELCOME, '客服欢迎语'), (SCENE_CS_AUTO_REPLY, '客服自动回复'), (SCENE_MERCHANT_DISPATCH, '商家派单确认'), ) ITEM_CONFIRM = 'confirm_modal' ITEM_TEXT = 'text_display' ITEM_AUTO_REPLY = 'auto_reply' ITEM_TYPE_CHOICES = ( (ITEM_CONFIRM, '确认弹窗'), (ITEM_TEXT, '纯文本展示'), (ITEM_AUTO_REPLY, '自动回复'), ) MATCH_CONTAINS = 'contains' MATCH_EXACT = 'exact' MATCH_MODE_CHOICES = ( (MATCH_CONTAINS, '包含匹配'), (MATCH_EXACT, '精确匹配'), ) scene_key = models.CharField(max_length=50, choices=SCENE_CHOICES, db_index=True, verbose_name='场景标识') item_type = models.CharField(max_length=20, choices=ITEM_TYPE_CHOICES, verbose_name='条目类型') title = models.CharField(max_length=200, blank=True, default='', verbose_name='标题') content = models.TextField(verbose_name='正文内容') confirm_text = models.CharField(max_length=50, blank=True, default='我知道了', verbose_name='确认按钮文案') cancel_text = models.CharField(max_length=50, blank=True, default='取消', verbose_name='取消按钮文案') keywords = models.JSONField(default=list, blank=True, verbose_name='触发关键词(JSON数组)') match_mode = models.CharField( max_length=20, choices=MATCH_MODE_CHOICES, default=MATCH_CONTAINS, verbose_name='匹配模式' ) priority = models.IntegerField(default=0, verbose_name='优先级(越大越先匹配)') is_active = models.BooleanField(default=True, verbose_name='是否启用') sort_order = models.IntegerField(default=0, verbose_name='排序') created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'huashu_config' verbose_name = '话术配置' verbose_name_plural = '话术配置' ordering = ['scene_key', '-priority', 'sort_order', 'id'] def __str__(self): return f'{self.get_scene_key_display()} - {self.get_item_type_display()}' class XcxSysPeizhi(models.Model): """小程序/微信系统配置(单例表,后台可改,优先于 settings.py)""" weixin_appid = models.CharField(max_length=64, blank=True, default='', verbose_name='小程序AppID') weixin_secret = models.CharField(max_length=128, blank=True, default='', verbose_name='小程序Secret') weixin_official_appid = models.CharField(max_length=64, blank=True, default='', verbose_name='服务号AppID') weixin_official_secret = models.CharField(max_length=128, blank=True, default='', verbose_name='服务号Secret') weixin_official_token = models.CharField(max_length=128, blank=True, default='', verbose_name='服务号Token') weixin_official_encoding_aes_key = models.CharField( max_length=128, blank=True, default='', verbose_name='服务号EncodingAESKey' ) weixin_template_id = models.CharField(max_length=128, blank=True, default='', verbose_name='模板消息ID') weixin_template_max_per_minute = models.PositiveIntegerField(default=950, verbose_name='模板消息每分钟上限') weixin_template_batch_size = models.PositiveIntegerField(default=100, verbose_name='模板消息批大小') weixin_broadcast_enabled = models.BooleanField(default=True, verbose_name='服务号广播开关') weixin_broadcast_workers = models.PositiveIntegerField(default=30, verbose_name='广播并发线程数') weixin_mchid = models.CharField(max_length=32, blank=True, default='', verbose_name='微信支付商户号') weixin_shanghu_miyao = models.CharField(max_length=128, blank=True, default='', verbose_name='商户密钥') weixin_notify_url = models.CharField(max_length=300, blank=True, default='', verbose_name='支付回调URL') weixin_cert_path = models.CharField(max_length=500, blank=True, default='', verbose_name='退款证书路径') weixin_key_path = models.CharField(max_length=500, blank=True, default='', verbose_name='退款密钥路径') notify_base_url = models.CharField( max_length=300, blank=True, default='https://wenhe.nmslb.com/hqhd', verbose_name='业务回调根URL' ) # 点单页 /shangpin/shangpinhuoqu 按此值筛选类型/专区/商品的 shenhezhuangtai shangpin_shenhe_mode = models.PositiveSmallIntegerField( default=2, verbose_name='点单商品展示模式', help_text='1=正常运营(shenhezhuangtai=1),2=审核专用(shenhezhuangtai=2)', ) shangjia_paifa_jiage_min = models.DecimalField( max_digits=10, decimal_places=2, default=10.00, verbose_name='商家派单最低金额(元)', ) shangjia_paifa_jiage_max = models.DecimalField( max_digits=10, decimal_places=2, default=10000.00, verbose_name='商家派单最高金额(元)', ) update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'xcx_sys_peizhi' verbose_name = '小程序系统配置' verbose_name_plural = verbose_name class XcxPageZiyuan(models.Model): """小程序页面背景图/图标(按组+键唯一)""" ziyuan_zu = models.CharField(max_length=32, db_index=True, verbose_name='资源组') ziyuan_key = models.CharField(max_length=64, verbose_name='资源键') ziyuan_path = models.CharField(max_length=500, verbose_name='OSS相对路径') miaoshu = models.CharField(max_length=200, blank=True, default='', verbose_name='说明') update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'xcx_page_ziyuan' verbose_name = '小程序页面资源' verbose_name_plural = verbose_name unique_together = [['ziyuan_zu', 'ziyuan_key']] indexes = [models.Index(fields=['ziyuan_zu'])] def __str__(self): return f'{self.ziyuan_zu}.{self.ziyuan_key}' class XcxXieyi(models.Model): """小程序用户协议配置""" MODE_IMAGE = 1 MODE_TEXT = 2 MODE_CHOICES = ( (MODE_IMAGE, '纯图片'), (MODE_TEXT, '文字'), ) SHENFEN_CHOICES = ( ('dashou', '打手'), ('guanshi', '管事'), ('zuzhang', '组长'), ('shangjia', '商家'), ('normal', '点单老板'), ) title = models.CharField(max_length=200, verbose_name='后台标题') shenfen = models.CharField(max_length=20, choices=SHENFEN_CHOICES, db_index=True, verbose_name='适用身份') mode = models.PositiveSmallIntegerField(choices=MODE_CHOICES, default=MODE_TEXT, verbose_name='展示模式') content_title = models.CharField(max_length=200, blank=True, default='', verbose_name='前端展示标题') content_text = models.TextField(blank=True, default='', verbose_name='文字内容') version = models.PositiveIntegerField(default=1, verbose_name='版本号') is_active = models.BooleanField(default=True, verbose_name='是否启用') must_sign = models.BooleanField(default=True, verbose_name='是否强制签署') sort_order = models.IntegerField(default=0, verbose_name='排序') created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'xcx_xieyi' verbose_name = '小程序协议' verbose_name_plural = verbose_name ordering = ['sort_order', 'id'] def __str__(self): return f'{self.title}({self.get_shenfen_display()})' class XcxXieyiImage(models.Model): """协议图片(纯图片模式,支持多张)""" xieyi = models.ForeignKey(XcxXieyi, on_delete=models.CASCADE, related_name='images', verbose_name='协议') image_path = models.CharField(max_length=500, verbose_name='OSS相对路径') sort_order = models.IntegerField(default=0, verbose_name='排序') class Meta: db_table = 'xcx_xieyi_image' verbose_name = '协议图片' verbose_name_plural = verbose_name ordering = ['sort_order', 'id'] class XcxXieyiQianshu(models.Model): """用户协议签署记录""" yonghuid = models.CharField(max_length=7, db_index=True, verbose_name='用户ID') xieyi = models.ForeignKey(XcxXieyi, on_delete=models.CASCADE, related_name='sign_records', verbose_name='协议') xieyi_version = models.PositiveIntegerField(verbose_name='签署时协议版本') shenfen = models.CharField(max_length=20, verbose_name='签署时身份') signature_path = models.CharField(max_length=500, verbose_name='签名图OSS路径') signed_at = models.DateTimeField(auto_now_add=True, verbose_name='签署时间') client_ip = models.CharField(max_length=64, blank=True, default='', verbose_name='客户端IP') class Meta: db_table = 'xcx_xieyi_qianshu' verbose_name = '协议签署记录' verbose_name_plural = verbose_name indexes = [ models.Index(fields=['yonghuid', 'xieyi']), ]