修复了影响生产环境的问题,在生产环境中成功运行

This commit is contained in:
2026-06-15 00:01:46 +08:00
parent a155dc9f33
commit 8b9dbcba6f
18 changed files with 207 additions and 53 deletions

View File

@@ -29,14 +29,14 @@ INSTALLED_APPS = [
'corsheaders',
'django_celery_results',
'celery',
'yonghu',
'dingdan',
'shangpin',
'peizhi',
'houtai',
'users',
'orders',
'products',
'config',
'backend',
'utils',
'shangdian',
'dengji',
'shop',
'rank',
]
MIDDLEWARE = [
@@ -131,7 +131,7 @@ AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
]
AUTH_USER_MODEL = 'yonghu.UserMain'
AUTH_USER_MODEL = 'users.UserMain'
# ==================== DRF 配置 ====================
REST_FRAMEWORK = {

View File

@@ -10,20 +10,20 @@ urlpatterns = [
path('admin/', admin.site.urls),
# 用户相关路由
path('yonghu/', include('yonghu.urls')),
path('yonghu/', include('users.urls')),
# 订单相关路由
path('dingdan/', include('dingdan.urls')),
path('dingdan/', include('orders.urls')),
# 商品/陪玩服务相关路由
path('shangpin/', include('shangpin.urls')),
path('shangpin/', include('products.urls')),
# 配置相关路由(系统配置)
path('peizhi/', include('peizhi.urls')),
path('houtai/', include('houtai.urls')),
path('shangdian/', include('shangdian.urls')),
path('dengji/', include('dengji.urls')),
path('peizhi/', include('config.urls')),
path('houtai/', include('backend.urls')),
path('shangdian/', include('shop.urls')),
path('dengji/', include('rank.urls')),
]
# 重要说明:

View File

@@ -26,7 +26,7 @@ from rest_framework.throttling import AnonRateThrottle, SimpleRateThrottle
from utils.oss_utils import upload_to_oss, delete_from_oss, validate_image
from utils.weixin_broadcast import WeixinBroadcastSender
# from utils.ip_security import *
from Django.utils.invitationcode_utils import CreateInvitationCode, VerifyInvitationCode
from utils.invitationcode_utils import CreateInvitationCode, VerifyInvitationCode
from backend.utils import update_shangjia_daily
from orders.utils import sync_order_to_partners

163
find.py Normal file
View File

@@ -0,0 +1,163 @@
"""
REPL 模式文件内容搜索工具
支持正则或纯文本搜索,默认搜索当前目录
"""
import os
import re
import sys
# 硬编码排除目录
EXCLUDE_DIRS = {
'.git', '.vs', 'node_modules', '__pycache__', '.idea',
'miniprogram_npm', '_backup_pre_redesign',
}
# 排除的文件扩展名
EXCLUDE_EXTS = {
'.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.bmp',
'.mp3', '.mp4', '.wav', '.avi',
'.zip', '.rar', '.7z', '.tar', '.gz',
'.exe', '.dll', '.so', '.dylib',
'.pyc', '.pyo', '.class', '.o', '.obj',
'.db', '.sqlite', '.vsidx',
}
# 默认搜索根目录
DEFAULT_ROOT = os.path.dirname(os.path.abspath(__file__))
def should_skip(dirpath):
"""判断目录是否应跳过"""
parts = dirpath.replace('\\', '/').split('/')
return any(p in EXCLUDE_DIRS for p in parts)
def search(pattern, root=DEFAULT_ROOT, use_regex=True, max_results=50):
"""搜索文件内容"""
try:
if use_regex:
compiled = re.compile(pattern, re.IGNORECASE)
except re.error as e:
print(f' 正则语法错误: {e}')
return
count = 0
for dirpath, dirnames, filenames in os.walk(root):
# 就地修改 dirnames 以跳过排除目录
dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIRS]
for fname in filenames:
ext = os.path.splitext(fname)[1].lower()
if ext in EXCLUDE_EXTS:
continue
fpath = os.path.join(dirpath, fname)
relpath = os.path.relpath(fpath, root)
try:
with open(fpath, 'r', encoding='utf-8', errors='ignore') as f:
for lineno, line in enumerate(f, 1):
line_stripped = line.rstrip('\n\r')
if use_regex:
match = compiled.search(line_stripped)
if match:
highlight = line_stripped[:match.start()] + \
f'>>> {match.group()} <<<' + \
line_stripped[match.end():]
print(f' {relpath}:{lineno} {highlight}')
count += 1
else:
if pattern.lower() in line_stripped.lower():
print(f' {relpath}:{lineno} {line_stripped}')
count += 1
if count >= max_results:
print(f'\n ... 已达上限 {max_results} 条,停止')
return
except (PermissionError, OSError):
continue
if count == 0:
print(' 未找到匹配内容')
else:
print(f'\n{count} 条匹配')
def main():
print('=== 文件内容搜索工具 ===')
print(f'搜索根目录: {DEFAULT_ROOT}')
print(f'排除目录: {EXCLUDE_DIRS}')
print()
print('命令:')
print(' /regex <pattern> 正则搜索')
print(' /text <text> 纯文本搜索')
print(' /max <n> 设置结果上限(默认50)')
print(' /dir <path> 切换搜索目录')
print(' /help 显示帮助')
print(' /quit 退出')
print()
print('直接输入内容默认使用正则搜索')
print()
root = DEFAULT_ROOT
use_regex = True
max_results = 50
while True:
try:
raw = input('find> ').strip()
except (EOFError, KeyboardInterrupt):
print('\n再见')
break
if not raw:
continue
if raw == '/quit':
print('再见')
break
if raw == '/help':
print(' /regex <pattern> 正则搜索')
print(' /text <text> 纯文本搜索')
print(' /max <n> 设置结果上限')
print(' /dir <path> 切换搜索目录')
print(' /help 显示帮助')
print(' /quit 退出')
print(' 直接输入内容默认使用正则搜索')
continue
if raw.startswith('/regex '):
pattern = raw[7:].strip()
if pattern:
search(pattern, root, use_regex=True, max_results=max_results)
continue
if raw.startswith('/text '):
pattern = raw[6:].strip()
if pattern:
search(pattern, root, use_regex=False, max_results=max_results)
continue
if raw.startswith('/max '):
try:
max_results = int(raw[5:].strip())
print(f' 结果上限设为 {max_results}')
except ValueError:
print(' 请输入数字')
continue
if raw.startswith('/dir '):
new_dir = raw[5:].strip()
if os.path.isdir(new_dir):
root = os.path.abspath(new_dir)
print(f' 搜索目录切换为: {root}')
else:
print(f' 目录不存在: {new_dir}')
continue
# 默认正则搜索
search(raw, root, use_regex=use_regex, max_results=max_results)
if __name__ == '__main__':
main()

View File

@@ -53,7 +53,6 @@ class Dingdan(models.Model):
db_index=True,
verbose_name='微信支付订单号'
)
class Meta:
db_table = 'dingdan'
@@ -90,7 +89,6 @@ class DingdanPingtai(models.Model):
verbose_name='上级分红金额')
# =============================
class Meta:
db_table = 'dingdan_pingtai'
@@ -99,13 +97,12 @@ class DingdanPingtai(models.Model):
indexes = [
models.Index(fields=['laoban_id']),
models.Index(fields=['dianpu_id']), # 为新字段加索引
]
def __str__(self):
return f"平台扩展-{self.dingdan.dingdan_id}"
class DingdanShangjia(models.Model):
"""商家发单扩展表 (当 fadan_pingtai=2 时使用)"""
dingdan = models.OneToOneField(Dingdan, on_delete=models.CASCADE, related_name='shangjia_kuozhan', verbose_name='订单')
@@ -553,10 +550,6 @@ class Ptliushui(models.Model):
db_table = 'ptliushui'
# models.py - ChatRelation 模型
class Liaotian(models.Model):
"""聊天关系表 - 极简设计,不设置唯一约束"""
# 主键

View File

@@ -18,6 +18,8 @@ from orders.models import Dingdan
from users.models import UserMain, UserDashou, UserShangjia
from utils.celery_utils import safe_decimal_operation, log_task_execution, rollback_on_failure
# from users.utils import update_platform_profit # 导入函数
logger = logging.getLogger(__name__)
@@ -109,7 +111,6 @@ def process_expired_order(self, dingdan_id):
if fadan_pingtai == 1:
try:
from orders.utils import update_platform_profit # 导入函数
update_platform_profit(dingdan_id)
except Exception as e:
# 平台收益更新失败不影响主流程,但记录日志

View File

@@ -39,9 +39,10 @@ from tencentcloud.sts.v20180813 import sts_client, models
from utils.weixin_broadcast import WeixinBroadcastSender
from utils.chat_utils import _send_group_message, _subscribe_users_to_group, establish_order_chat
from utils.fadan_utils import check_fadan_qiangdan_eligible
# from utils.admin import update_platform_profit
from orders.utils import (
update_platform_profit, calc_shangjia_order_fencheng, sync_order_to_partners,
calc_shangjia_order_fencheng, sync_order_to_partners,
update_daily_dispatch_stat, update_daily_income, update_daily_payout,
settle_shangjia_order_guanshi_fenhong
)

View File

@@ -36,7 +36,7 @@ class Shangpin(models.Model):
shenhezhuangtai = models.IntegerField(default=1, verbose_name='审核状态', help_text='1=正常, 2=审核专用')
dianpu = models.ForeignKey(
'shangdian.Dianpu', # 🔥 跨应用完整路径
'shop.Dianpu', # 🔥 跨应用完整路径
on_delete=models.CASCADE,
null=True,
blank=True,
@@ -44,7 +44,7 @@ class Shangpin(models.Model):
verbose_name='所属店铺'
)
dianpu_leixing = models.ForeignKey(
'shangdian.ShangpinLeixingDianpu',
'shop.ShangpinLeixingDianpu',
on_delete=models.SET_NULL,
null=True,
blank=True,
@@ -79,7 +79,7 @@ class ShangpinLeixing(models.Model):
paixu = models.IntegerField(default=0, verbose_name='排序权重')
shenhezhuangtai = models.IntegerField(default=1, verbose_name='审核状态', help_text='1=正常, 2=审核专用')
bankuai = models.ForeignKey(
'dengji.Bankuai',
'rank.Bankuai',
on_delete=models.SET_NULL,
null=True,
blank=True,
@@ -104,7 +104,7 @@ class ShangpinZhuanqu(models.Model):
shenhezhuangtai = models.IntegerField(default=1, verbose_name='审核状态', help_text='1=正常, 2=审核专用')
dianpu = models.ForeignKey(
'shangdian.Dianpu', # 🔥 跨应用完整路径
'shop.Dianpu', # 🔥 跨应用完整路径
on_delete=models.CASCADE,
null=True,
blank=True,
@@ -112,7 +112,7 @@ class ShangpinZhuanqu(models.Model):
verbose_name='所属店铺'
)
dianpu_leixing = models.ForeignKey(
'shangdian.ShangpinLeixingDianpu',
'shop.ShangpinLeixingDianpu',
on_delete=models.SET_NULL,
null=True,
blank=True,
@@ -144,7 +144,7 @@ class Huiyuan(models.Model):
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
bankuai = models.ForeignKey(
'dengji.Bankuai',
'rank.Bankuai',
on_delete=models.SET_NULL,
null=True,
blank=True,
@@ -308,7 +308,7 @@ class ShangpinMeiriTongji(models.Model):
日期精确到天,冗余年月日字段便于分组查询
"""
shangpin = models.ForeignKey(
'shangpin.Shangpin',
'products.Shangpin',
on_delete=models.CASCADE,
db_index=True,
verbose_name='商品ID'

View File

@@ -19,7 +19,7 @@ class Bankuai(models.Model):
# ==================== 打手订单表现记录 ====================
class DashouBiaoxian(models.Model):
dingdan = models.ForeignKey('dingdan.Dingdan', to_field='dingdan_id', on_delete=models.CASCADE, related_name='biaoxian', verbose_name='关联订单', db_index=True)
dingdan = models.ForeignKey('orders.Dingdan', to_field='dingdan_id', on_delete=models.CASCADE, related_name='biaoxian', verbose_name='关联订单', db_index=True)
dashou_id = models.CharField(max_length=32, db_index=True, verbose_name='打手ID')
bankuai = models.ForeignKey(Bankuai, on_delete=models.PROTECT, to_field='bankuai_id', verbose_name='所属板块', db_index=True,null=True)
@@ -94,7 +94,6 @@ class YonghuChenghao(models.Model):
class DingdanBiaoqian(models.Model):
"""订单需求标签关联表"""
dingdan = models.ForeignKey(
@@ -104,7 +103,7 @@ class DingdanBiaoqian(models.Model):
verbose_name='订单',
db_index=True
)
chenghao = models.ForeignKey('dengji.Chenghao', on_delete=models.CASCADE, verbose_name='标签')
chenghao = models.ForeignKey('rank.Chenghao', on_delete=models.CASCADE, verbose_name='标签')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
class Meta:

View File

@@ -14,7 +14,7 @@ from .models import (
## users应用
from users.models import UserMain, UserShenheguan, UserDashou
## orders应用
from orders.models import YonghuChenghao
from .models import YonghuChenghao
# 日志对象
logger = logging.getLogger(__name__)

View File

@@ -1,7 +1,5 @@
from django.db import models
# Create your models here.
class YonghuPingzheng(models.Model):
id = models.AutoField(primary_key=True, verbose_name='自增主键ID')
@@ -26,7 +24,7 @@ class YonghuPingzheng(models.Model):
class Dianpu(models.Model):
id = models.AutoField(primary_key=True, verbose_name='店铺自增ID')
pingzheng = models.OneToOneField(
'shangdian.YonghuPingzheng', # 同应用内可简写,但完整路径更清晰
'shop.YonghuPingzheng', # 同应用内可简写,但完整路径更清晰
on_delete=models.CASCADE,
db_index=True,
verbose_name='关联用户凭证'
@@ -149,7 +147,7 @@ class DianpuShouzhiMeiriTongji(models.Model):
class YonghuDianpuBangding(models.Model):
id = models.AutoField(primary_key=True, verbose_name='绑定自增ID')
yonghu = models.ForeignKey(
'yonghu.UserMain', # 🔥 完整路径
'users.UserMain', # 🔥 完整路径
to_field='yonghuid',
on_delete=models.CASCADE,
db_index=True,
@@ -166,8 +164,6 @@ class YonghuDianpuBangding(models.Model):
unique_together = [['yonghu', 'dianpu']]
# shangdian/models.py
class ShangpinLeixingDianpu(models.Model):
"""
店铺级商品类型映射表
@@ -175,14 +171,14 @@ class ShangpinLeixingDianpu(models.Model):
"""
id = models.AutoField(primary_key=True, verbose_name='类型自增ID')
dianpu = models.ForeignKey(
'shangdian.Dianpu',
'shop.Dianpu',
on_delete=models.CASCADE,
db_index=True,
verbose_name='所属店铺'
)
# 🔥 强制映射到公共商品类型,不可为空
gonggong_leixing = models.ForeignKey(
'shangpin.ShangpinLeixing',
'shop.ShangpinLeixing',
on_delete=models.CASCADE,
db_index=True,
verbose_name='映射的公共商品类型'

View File

@@ -10,8 +10,8 @@ urlpatterns = [
path('bdsd', BindDianpuView.as_view(), name='绑定或更新商家店铺'),
path('hqsp', ShopGoodsView.as_view(), name='获取商品数据'),
path('login', ShangdianLoginView.as_view(), name='商家登录'),
path('sjdpgl', ShopOverviewView.as_view(), name='商家获取店铺信息'),
path('login', ShangdianLoginView.as_view(), name='商家登录'),
path('sjdpgl', ShopOverviewView.as_view(), name='商家获取店铺信息'),
path('sdscdpm', ShopQrcodeView.as_view(), name='生成或更新店铺二维码'),
path('dphqspxx', ShopProductConfigView.as_view(), name='商店获取商品类型专区'),

View File

@@ -3370,4 +3370,4 @@ class ShopFineApplyView(APIView):
except Exception as e:
logger.error(f"店铺罚款申请异常: {traceback.format_exc()}")
return Response({'code': 500, 'msg': '服务器内部错误'})
return Response({'code': 500, 'msg': '服务器内部错误'})

View File

@@ -2,6 +2,7 @@
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
# ==================== 用户主表 ====================
class UserMain(AbstractBaseUser):
# ID字段

View File

@@ -43,7 +43,7 @@ from utils.oss_utils import validate_image, upload_to_oss, delete_from_oss
from utils.fadan_utils import check_fadan_qiangdan_eligible
from utils.wechat_v3 import verify_wechat_sign, decrypt_callback_ciphertext
from Django.utils.invitationcode_utils import CreateInvitationCode, VerifyInvitationCode
from utils.invitationcode_utils import CreateInvitationCode, VerifyInvitationCode
from users.fadan_fenhong_utils import process_fadan_fenhong
from orders.utils import (
@@ -86,7 +86,7 @@ from rank.models import (
from users.models import UserShenheguan
from products.utils import update_shangpin_daily_stat
from shop.utils import update_dianpu_daily_stat
from orders.utils import create_shenhe_jilu_from_temp
from rank.utils import create_shenhe_jilu_from_temp
import logging
logger = logging.getLogger(__name__)

View File

@@ -67,6 +67,8 @@ def custom_exception_handler(exc, context):
f"错误类型: {type(exc).__name__}, 错误: {str(exc)}"
)
if not settings.DEBUG:
import traceback
print(traceback.format_exc())
return Response(
{'code': 500, 'message': '服务器内部错误,请稍后重试'},
status=status.HTTP_500_INTERNAL_SERVER_ERROR

View File

@@ -57,7 +57,7 @@ def check_fadan_qiangdan_eligible(yonghuid: str, action_type: int) -> tuple:
import logging
from django.db import transaction
from decimal import Decimal
from dingdan.models import Fadan, FadanFenhong, FadanFenhongLilv
from orders.models import Fadan, FadanFenhong, FadanFenhongLilv
logger = logging.getLogger('xiaochengxu')

View File

@@ -1,3 +1 @@
from django.db import models
# Create your models here.