修复了影响生产环境的问题,在生产环境中成功运行
This commit is contained in:
@@ -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 = {
|
||||
|
||||
@@ -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')),
|
||||
]
|
||||
|
||||
# 重要说明:
|
||||
|
||||
@@ -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
163
find.py
Normal 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()
|
||||
@@ -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):
|
||||
"""聊天关系表 - 极简设计,不设置唯一约束"""
|
||||
# 主键
|
||||
|
||||
@@ -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:
|
||||
# 平台收益更新失败不影响主流程,但记录日志
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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__)
|
||||
|
||||
|
||||
@@ -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='映射的公共商品类型'
|
||||
|
||||
@@ -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='商店获取商品类型专区'),
|
||||
|
||||
@@ -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': '服务器内部错误'})
|
||||
@@ -2,6 +2,7 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import AbstractBaseUser
|
||||
|
||||
|
||||
# ==================== 用户主表 ====================
|
||||
class UserMain(AbstractBaseUser):
|
||||
# ID字段
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
|
||||
Reference in New Issue
Block a user