补充修改

This commit is contained in:
2026-06-18 02:30:42 +08:00
parent f9da920e6b
commit 7ce545fedb
12 changed files with 23 additions and 1168 deletions

View File

@@ -3025,7 +3025,7 @@ class GetGuanliDetailView(APIView):
# 获取多次分红配置(按次数和会员组织)
# 查询该管事的所有多次分红记录
duoci_records = DuociFenhong.query.filter(UserUID=yonghuid).order_by('cishu')
duoci_records = DuociFenhong.query.filter(yonghuid=yonghuid).order_by('cishu')
custom_first = {} # 首次分红定制cishu=1
extra_map = {} # 其他次数 { cishu: { huiyuan_id: { guanshi_fenhong, jieshao, jiage } } }
@@ -3206,7 +3206,7 @@ class UpdateGuanliView(APIView):
# 4.2 首次定制分红cishu=1
if custom_first is not None and isinstance(custom_first, dict):
# 获取当前所有首次定制记录
existing_first = DuociFenhong.query.filter(UserUID=yonghuid, cishu=1)
existing_first = DuociFenhong.query.filter(yonghuid=yonghuid, cishu=1)
# 前端传来的定制字典 {会员ID: 金额}
for huiyuan_id, amount in custom_first.items():
try:
@@ -3215,7 +3215,7 @@ class UpdateGuanliView(APIView):
continue
if amount <= 0:
# 金额为0或负数表示删除定制
DuociFenhong.query.filter(UserUID=yonghuid, huiyuan=huiyuan_id, cishu=1).delete()
DuociFenhong.query.filter(yonghuid=yonghuid, huiyuan=huiyuan_id, cishu=1).delete()
else:
DuociFenhong.query.update_or_create(
yonghuid=yonghuid,
@@ -3266,7 +3266,7 @@ class UpdateGuanliView(APIView):
}
)
# 删除不在 keep_set 中的额外次数记录
existing_extra = DuociFenhong.query.filter(UserUID=yonghuid, cishu__gte=2)
existing_extra = DuociFenhong.query.filter(yonghuid=yonghuid, cishu__gte=2)
for record in existing_extra:
if (record.cishu, record.huiyuan) not in keep_set:
record.delete()
@@ -3716,7 +3716,7 @@ class GetZuzhangDetailView(APIView):
m['zuzhangfc'] = str(m['zuzhangfc'])
# 获取多次分红配置(按次数和会员组织)
duoci_records = DuociFenhong.query.filter(UserUID=yonghuid).order_by('cishu')
duoci_records = DuociFenhong.query.filter(yonghuid=yonghuid).order_by('cishu')
custom_first = {} # 首次分红定制cishu=1
extra_map = {} # 其他次数 { cishu: { huiyuan_id: { zuzhang_fenhong, jieshao, jiage } } }
@@ -3889,7 +3889,7 @@ class UpdateZuzhangView(APIView):
# 4.2 首次定制分红cishu=1
if custom_first is not None and isinstance(custom_first, dict):
existing_first = DuociFenhong.query.filter(UserUID=yonghuid, cishu=1)
existing_first = DuociFenhong.query.filter(yonghuid=yonghuid, cishu=1)
for huiyuan_id, amount in custom_first.items():
try:
amount = Decimal(str(amount))
@@ -3897,7 +3897,7 @@ class UpdateZuzhangView(APIView):
continue
if amount <= 0:
# 删除定制(恢复默认)
DuociFenhong.query.filter(UserUID=yonghuid, huiyuan=huiyuan_id, cishu=1).delete()
DuociFenhong.query.filter(yonghuid=yonghuid, huiyuan=huiyuan_id, cishu=1).delete()
else:
DuociFenhong.query.update_or_create(
yonghuid=yonghuid,
@@ -3946,7 +3946,7 @@ class UpdateZuzhangView(APIView):
}
)
# 删除不在 keep_set 中的额外次数记录
existing_extra = DuociFenhong.query.filter(UserUID=yonghuid, cishu__gte=2)
existing_extra = DuociFenhong.query.filter(yonghuid=yonghuid, cishu__gte=2)
for record in existing_extra:
if (record.cishu, record.huiyuan) not in keep_set:
record.delete()

View File

@@ -1,69 +0,0 @@
#!/usr/bin/env python3
"""检查 user_dashou 中有 user_id 的记录"""
import re
with open('xaio_cheng_xu_backup.sql', 'r', encoding='utf-8') as f:
content = f.read()
pattern = re.compile(r"INSERT\s+INTO\s+`user_dashou`\s+VALUES\s*\((.+?)\)\s*;", re.IGNORECASE | re.DOTALL)
matches = list(pattern.finditer(content))
# 找有 user_id 的记录
has_uid = 0
no_uid = 0
uid_values = []
for m in matches:
v = m.group(1).rstrip()
if v.endswith('NULL'):
no_uid += 1
else:
has_uid += 1
# 提取最后一个值user_id
last_comma = v.rfind(',')
uid_val = v[last_comma+1:].strip()
uid_values.append(uid_val)
print(f"有 user_id: {has_uid}, 无 user_id: {no_uid}")
print(f"user_id 值样本: {uid_values[:10]}")
# 检查 user_main 中这些 user_id 是否存在
# user_main 的 id 字段是 vals[1]
main_pattern = re.compile(r"INSERT\s+INTO\s+`user_main`\s+VALUES\s*\((.+?)\)\s*;", re.IGNORECASE | re.DOTALL)
main_ids = set()
for m in main_pattern.finditer(content):
# 简单提取第二个字段 (id)
v = m.group(1)
# 找前几个逗号
in_q = False
commas = []
for i, ch in enumerate(v):
if ch == "'": in_q = not in_q
elif ch == ',' and not in_q:
commas.append(i)
if len(commas) >= 2: break
if len(commas) >= 2:
id_val = v[commas[0]+1:commas[1]].strip()
main_ids.add(id_val)
print(f"\nuser_main id 范围: {len(main_ids)}")
matched = sum(1 for uid in uid_values if uid in main_ids)
print(f"user_dashou user_id 匹配 user_main: {matched}/{len(uid_values)}")
# 也检查 user_type 分布
type_pattern = re.compile(r"INSERT\s+INTO\s+`user_main`\s+VALUES\s*\((.+?)\)\s*;", re.IGNORECASE | re.DOTALL)
type_counts = {}
for m in type_pattern.finditer(content):
v = m.group(1)
# 找第12个字段 (user_type, index 11)
in_q = False
commas = []
for i, ch in enumerate(v):
if ch == "'": in_q = not in_q
elif ch == ',' and not in_q:
commas.append(i)
if len(commas) >= 12: break
if len(commas) >= 12:
type_val = v[commas[10]+1:commas[11]].strip().strip("'")
type_counts[type_val] = type_counts.get(type_val, 0) + 1
print(f"\nuser_type 分布: {type_counts}")

View File

@@ -1,19 +0,0 @@
#!/usr/bin/env python3
"""检查数据库表行数"""
import MySQLdb
from app_secrets import DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME
conn = MySQLdb.connect(
host=DATABASE_HOST, port=int(DATABASE_PORT),
user=DATABASE_USER, password=DATABASE_PASSWORD,
database=DATABASE_NAME
)
cursor = conn.cursor()
cursor.execute(
"SELECT TABLE_NAME, TABLE_ROWS FROM information_schema.TABLES "
"WHERE TABLE_SCHEMA = %s ORDER BY TABLE_NAME",
[DATABASE_NAME]
)
for row in cursor.fetchall():
print(f"{row[0]:40s} {row[1]}")
conn.close()

View File

@@ -1,31 +0,0 @@
import MySQLdb
conn = MySQLdb.connect(
host='gvsds.com', port=50030, user='root',
password='sajksh.sdfGH3YUge.wjkd+',
database='xaio_cheng_xu', charset='utf8mb4'
)
cur = conn.cursor()
# 获取所有表
cur.execute("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA='xaio_cheng_xu'")
tables = [row[0] for row in cur.fetchall()]
print(f'{len(tables)} 张表')
# 禁用外键检查,删除所有表
cur.execute('SET FOREIGN_KEY_CHECKS = 0')
for t in tables:
cur.execute(f'DROP TABLE IF EXISTS `{t}`')
print(f' 已删除: {t}')
cur.execute('SET FOREIGN_KEY_CHECKS = 1')
conn.commit()
print(f'\n已删除全部 {len(tables)} 张表')
# 验证
cur.execute("SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='xaio_cheng_xu'")
count = cur.fetchone()[0]
print(f'剩余表数: {count}')
cur.close()
conn.close()

163
find.py
View File

@@ -1,163 +0,0 @@
"""
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

@@ -1,67 +0,0 @@
#!/usr/bin/env python3
"""修复 yonghu_dianpu_bangding 表的 FK 约束"""
import MySQLdb
from app_secrets import DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME
conn = MySQLdb.connect(
host=DATABASE_HOST, port=int(DATABASE_PORT),
user=DATABASE_USER, password=DATABASE_PASSWORD,
database=DATABASE_NAME, charset='utf8mb4'
)
cursor = conn.cursor()
# 1. 查看所有引用 User 表的 FK 约束
cursor.execute("""
SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = %s AND REFERENCED_TABLE_NAME = 'User'
""", [DATABASE_NAME])
fks = cursor.fetchall()
print("引用 User 表的 FK 约束:")
for fk in fks:
print(f" {fk[0]}: {fk[1]}.{fk[2]} -> {fk[3]}.{fk[4]}")
# 2. 删除所有引用 User.UserUID 的 FK 约束(类型不兼容的)
for fk in fks:
if fk[4] == 'UserUID': # 引用了 UserUID (varchar) 而不是 UserUUID (binary)
constraint_name = fk[0]
table_name = fk[1]
print(f"\n删除不兼容 FK: {constraint_name} on {table_name}")
try:
cursor.execute(f"ALTER TABLE `{table_name}` DROP FOREIGN KEY `{constraint_name}`")
conn.commit()
print(f" 已删除 {constraint_name}")
except Exception as e:
print(f" 删除失败: {e}")
# 3. 修改 yonghu_dianpu_bangding.UserUUID 列类型
print("\n修改 yonghu_dianpu_bangding.UserUUID 列类型...")
try:
cursor.execute("ALTER TABLE yonghu_dianpu_bangding MODIFY COLUMN UserUUID binary(16) NOT NULL")
conn.commit()
print(" 修改成功")
except Exception as e:
print(f" 修改失败: {e}")
# 4. 重新添加 FK 约束
print("\n重新添加 FK 约束...")
try:
cursor.execute("""
ALTER TABLE yonghu_dianpu_bangding
ADD CONSTRAINT yonghu_dianpu_bangding_UserUUID_fk
FOREIGN KEY (UserUUID) REFERENCES User(UserUUID)
""")
conn.commit()
print(" FK 约束添加成功")
except Exception as e:
print(f" FK 约束添加失败: {e}")
# 5. 验证
print("\n验证表结构:")
cursor.execute("DESCRIBE yonghu_dianpu_bangding")
for row in cursor.fetchall():
print(f" {row}")
conn.close()
print("\n完成!")

View File

@@ -1,122 +0,0 @@
#!/usr/bin/env python3
"""修复 tixianjilu 导入 — 使用指定列名的 INSERT"""
import re, sys, time, MySQLdb
sys.path.insert(0, '.')
import os; os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'a_long_dianjing.settings')
import django; django.setup()
from app_secrets import DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME
SQL_FILE = os.path.join(os.path.dirname(__file__), 'xaio_cheng_xu_backup.sql')
with open(SQL_FILE, 'r', encoding='utf-8') as f:
sql_content = f.read()
# 旧表字段顺序SQL INSERT VALUES 的顺序)
OLD_COLUMNS = [
'id', 'yonghuid', 'avatar', 'phone', 'nicheng', 'leixing', 'zhifu',
'skzhanghao', 'jine', 'zhuangtai', 'fangshi', 'shenheid', 'bhliyou',
'create_time', 'update_time', 'shenhe_danhao', 'shenhe_jilu_id'
]
# 新表字段顺序
NEW_COLUMNS = [
'id', 'yonghuid', 'avatar', 'phone', 'nicheng', 'leixing', 'zhifu',
'skzhanghao', 'jine', 'zhuangtai', 'fangshi', 'shenheid', 'bhliyou',
'shenhe_jilu_id', 'shenhe_danhao', 'create_time', 'update_time'
]
def parse_sql_value(val_str):
val_str = val_str.strip()
if val_str.upper() == 'NULL': return None
if val_str.startswith("'") and val_str.endswith("'"):
return val_str[1:-1].replace("\\'", "'").replace("\\\\", "\\")
try: return int(val_str)
except ValueError:
try: return float(val_str)
except ValueError: return val_str
def split_sql_values(values_str):
values, current, in_quote, escape = [], [], False, False
for ch in values_str:
if escape: current.append(ch); escape = False; continue
if ch == '\\': current.append(ch); escape = True; continue
if ch == "'": in_quote = not in_quote; current.append(ch); continue
if ch == ',' and not in_quote: values.append(''.join(current).strip()); current = []; continue
current.append(ch)
if current: values.append(''.join(current).strip())
return [parse_sql_value(v) for v in values]
pattern = re.compile(r"INSERT\s+INTO\s+`tixianjilu`\s+VALUES\s*\((.+?)\)\s*;", re.IGNORECASE | re.DOTALL)
matches = list(pattern.finditer(sql_content))
print(f"找到 {len(matches)} 条 tixianjilu 记录")
conn = MySQLdb.connect(
host=DATABASE_HOST, port=int(DATABASE_PORT),
user=DATABASE_USER, password=DATABASE_PASSWORD,
database=DATABASE_NAME, charset='utf8mb4',
connect_timeout=10, read_timeout=60, write_timeout=60
)
cursor = conn.cursor()
cursor.execute('SET FOREIGN_KEY_CHECKS = 0')
success = 0
fail = 0
start = time.time()
for i, m in enumerate(matches):
vals = split_sql_values(m.group(1))
if len(vals) != len(OLD_COLUMNS):
fail += 1
continue
# 旧字段 → 值映射
old_dict = dict(zip(OLD_COLUMNS, vals))
# 按新字段顺序构建值列表
new_vals = []
for col in NEW_COLUMNS:
new_vals.append(old_dict.get(col))
# 构建 INSERT 语句(指定列名)
col_names = ', '.join(f'`{c}`' for c in NEW_COLUMNS)
val_parts = []
for v in new_vals:
if v is None:
val_parts.append('NULL')
elif isinstance(v, str):
escaped = conn.escape_string(v)
if isinstance(escaped, bytes): escaped = escaped.decode()
val_parts.append(f"'{escaped}'")
elif isinstance(v, bool):
val_parts.append('1' if v else '0')
elif isinstance(v, (int, float)):
val_parts.append(str(v))
else:
val_parts.append('NULL')
sql = f"INSERT INTO `tixianjilu` ({col_names}) VALUES ({', '.join(val_parts)})"
try:
cursor.execute(sql)
success += 1
except Exception as e:
fail += 1
if fail <= 3:
print(f" ERR: {str(e)[:100]}")
if success % 100 == 0 and success > 0:
conn.commit()
if (i + 1) % 200 == 0:
elapsed = time.time() - start
pct = (i + 1) / len(matches)
sys.stdout.write(f'\r [{pct:5.1%}] {i+1}/{len(matches)} {elapsed:.0f}s OK:{success} FAIL:{fail}')
sys.stdout.flush()
conn.commit()
cursor.execute('SET FOREIGN_KEY_CHECKS = 1')
conn.commit()
conn.close()
elapsed = time.time() - start
print(f'\n完成: 成功 {success}, 失败 {fail}, 耗时 {elapsed:.0f}s')

View File

@@ -1,145 +0,0 @@
#!/usr/bin/env python3
"""只导入用户迁移所需的表到临时数据库 xaio_old"""
import MySQLdb
import re
from app_secrets import DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD
# 需要导入的表(用户相关)
NEEDED_TABLES = {
'user_main', 'user_dashou', 'user_guanshi', 'user_kefu',
'user_shangjia', 'user_boss', 'admin_profile', 'user_zuzhang',
'user_shenheguan', 'user_role', 'role', 'permission',
'role_permission', 'account_permission',
}
def get_conn(db=None):
kwargs = dict(
host=DATABASE_HOST, port=int(DATABASE_PORT),
user=DATABASE_USER, password=DATABASE_PASSWORD,
charset='utf8mb4', connect_timeout=60,
read_timeout=300, write_timeout=300,
)
if db:
kwargs['database'] = db
return MySQLdb.connect(**kwargs)
# Drop and recreate
conn = get_conn()
cursor = conn.cursor()
cursor.execute('DROP DATABASE IF EXISTS xaio_old')
cursor.execute('CREATE DATABASE xaio_old CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci')
conn.commit()
conn.close()
print('临时数据库 xaio_old 已重建')
# Read the SQL file
with open('xaio_cheng_xu_backup.sql', 'r', encoding='utf-8') as f:
sql_content = f.read()
# Parse and filter statements
# We need CREATE TABLE and INSERT statements for NEEDED_TABLES only
# Also need DROP TABLE IF EXISTS for those tables
statements = []
current = []
current_table = None
in_create = False
for line in sql_content.split('\n'):
stripped = line.strip()
if not stripped or stripped.startswith('--') or stripped.startswith('/*'):
continue
# Detect table name from CREATE TABLE or DROP TABLE or INSERT INTO
create_match = re.match(r'CREATE\s+TABLE\s+`(\w+)`', stripped, re.IGNORECASE)
drop_match = re.match(r'DROP\s+TABLE\s+IF\s+EXISTS\s+`(\w+)`', stripped, re.IGNORECASE)
insert_match = re.match(r'INSERT\s+INTO\s+`(\w+)`', stripped, re.IGNORECASE)
if create_match:
current_table = create_match.group(1)
in_create = True
elif drop_match:
current_table = drop_match.group(1)
elif insert_match:
current_table = insert_match.group(1)
in_create = False
# Only include statements for needed tables
if current_table and current_table in NEEDED_TABLES:
current.append(line)
if stripped.endswith(';'):
stmt = '\n'.join(current).strip()
current = []
current_table = None
in_create = False
upper = stmt.upper()
if not upper.startswith('SET ') and not upper.startswith('USE '):
statements.append(stmt)
elif stripped.endswith(';'):
# Not a needed table, skip
current = []
current_table = None
in_create = False
elif current_table and current_table in NEEDED_TABLES:
current.append(line)
else:
# Not needed, skip but track state
if stripped.endswith(';'):
current = []
current_table = None
print(f'筛选出 {len(statements)} 条用户相关SQL语句')
# Execute
conn = get_conn(db='xaio_old')
cursor = conn.cursor()
cursor.execute('SET FOREIGN_KEY_CHECKS = 0')
executed = 0
errors = 0
for stmt in statements:
try:
cursor.execute(stmt)
executed += 1
if executed % 20 == 0:
conn.commit()
except MySQLdb.OperationalError as e:
if e.args[0] in (2006, 2013):
try:
conn.close()
except:
pass
conn = get_conn(db='xaio_old')
cursor = conn.cursor()
try:
cursor.execute(stmt)
executed += 1
except Exception as e2:
errors += 1
if errors <= 5:
print(f' ERR(retry): {str(e2)[:100]}')
else:
errors += 1
if errors <= 5:
print(f' ERR: {str(e)[:100]}')
except Exception as e:
errors += 1
if errors <= 5:
print(f' ERR: {str(e)[:100]}')
conn.commit()
cursor.execute('SET FOREIGN_KEY_CHECKS = 1')
conn.commit()
print(f'\n导入完成: 成功 {executed}, 错误 {errors}')
# Check row counts
print('\n关键表行数:')
for table in sorted(NEEDED_TABLES):
try:
cursor.execute('SELECT COUNT(*) FROM `%s`' % table)
count = cursor.fetchone()[0]
print(f' {table}: {count} rows')
except Exception:
print(f' {table}: NOT FOUND')
conn.close()

View File

@@ -1,463 +0,0 @@
#!/usr/bin/env python3
"""
migrate_data.py — 从 SQL 备份文件直接迁移数据到新的 gvsdsdk User + RBAC 体系
v3: 正确的字段映射 + 基于扩展表存在性分配角色 + bulk_create + 实时进度
"""
import os, sys, re, uuid, time, datetime, MySQLdb
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'a_long_dianjing.settings')
import django; django.setup()
from app_secrets import DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME
TENANT_UUID = uuid.UUID('a0000000-0000-0000-0000-000000000001').bytes
COMPANY_UUID = uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes
BATCH_SIZE = 500
ROLE_MAP = {
'normal': '消费者', 'dashou': '打手', 'shop': '商家',
'guanshi': '负责人', 'admin': '管理员', 'kefu': '客服',
'zuzhang': '组长', 'shenheguan': '审核官',
}
# 角色优先级(高→低): 管理员 > 客服 > 负责人 > 组长 > 审核官 > 商家 > 打手 > 消费者
ROLE_PRIORITY = ['admin', 'kefu', 'guanshi', 'zuzhang', 'shenheguan', 'shop', 'dashou', 'normal']
# 扩展表 → 角色类型 映射
EXT_ROLE_MAP = {
'admin_profile': 'admin',
'user_kefu': 'kefu',
'user_guanshi': 'guanshi',
'user_zuzhang': 'zuzhang',
'user_shenheguan': 'shenheguan',
'user_shangjia': 'shop',
'user_dashou': 'dashou',
}
SQL_FILE = os.path.join(os.path.dirname(__file__), 'xaio_cheng_xu_backup.sql')
class Progress:
def __init__(self, total, width=35):
self.total = total; self.width = width; self.start = time.time(); self.done = 0
def update(self, n=1):
self.done += n; pct = self.done / self.total if self.total else 0
filled = int(self.width * pct); bar = '' * filled + '' * (self.width - filled)
elapsed = time.time() - self.start
eta = (elapsed / self.done * (self.total - self.done)) if self.done else 0
sys.stdout.write(f'\r [{bar}] {pct:5.1%} {self.done}/{self.total} {elapsed:.0f}s ETA{eta:.0f}s')
sys.stdout.flush()
def finish(self):
elapsed = time.time() - self.start
sys.stdout.write(f'\r [{""*self.width}] 100% {self.done}/{self.total} {elapsed:.0f}s\n')
sys.stdout.flush()
def parse_insert_values(table_name, sql_content):
pattern = re.compile(r"INSERT\s+INTO\s+`" + re.escape(table_name) + r"`\s+VALUES\s*\((.+?)\)\s*;", re.IGNORECASE | re.DOTALL)
return [m.group(1) for m in pattern.finditer(sql_content)]
def parse_sql_value(val_str):
val_str = val_str.strip()
if val_str.upper() == 'NULL': return None
if val_str.startswith("'") and val_str.endswith("'"):
return val_str[1:-1].replace("\\'", "'").replace("\\\\", "\\")
try: return int(val_str)
except ValueError:
try: return float(val_str)
except ValueError: return val_str
def split_sql_values(values_str):
values, current, in_quote, escape = [], [], False, False
for ch in values_str:
if escape: current.append(ch); escape = False; continue
if ch == '\\': current.append(ch); escape = True; continue
if ch == "'": in_quote = not in_quote; current.append(ch); continue
if ch == ',' and not in_quote: values.append(''.join(current).strip()); current = []; continue
current.append(ch)
if current: values.append(''.join(current).strip())
return [parse_sql_value(v) for v in values]
def parse_dt(v):
if isinstance(v, str) and v:
try: return datetime.datetime.fromisoformat(v.replace(' ', 'T'))
except: pass
return datetime.datetime.utcnow()
def get_raw_conn(db=None):
kwargs = dict(host=DATABASE_HOST, port=int(DATABASE_PORT), user=DATABASE_USER,
password=DATABASE_PASSWORD, charset='utf8mb4', connect_timeout=10,
read_timeout=60, write_timeout=60)
if db: kwargs['database'] = db
return MySQLdb.connect(**kwargs)
def run_migration():
from gvsdsdk.models import User, Role, UserRole
from users.models import (
UserBoss, UserDashou, UserShangjia, UserGuanshi,
UserZuzhang, UserShenheguan, AdminProfile, UserKefu,
UserSensitiveData
)
print("=" * 60)
print("开始从 SQL 备份迁移数据到 gvsdsdk.User + RBAC")
print("=" * 60)
# [0] 读取 SQL
print("\n[0/7] 读取 SQL 备份文件...", end=' ')
with open(SQL_FILE, 'r', encoding='utf-8') as f:
sql_content = f.read()
print(f"{len(sql_content)/1024/1024:.1f} MB")
# [1] 解析所有扩展表的 user_id → 建立角色映射
print("\n[1/7] 解析扩展表建立角色映射...")
# 正确的 user_id 索引位置
ext_user_id_idx = {
'user_dashou': 22,
'user_guanshi': 11,
'user_kefu': 9,
'user_shangjia': 14,
'user_boss': 6,
'admin_profile': 4,
'user_zuzhang': 17,
'user_shenheguan': 9,
}
# user_main.id → 角色集合
user_roles = {} # old_user_id -> set of role_types
for table_name, role_type in EXT_ROLE_MAP.items():
inserts = parse_insert_values(table_name, sql_content)
uid_idx = ext_user_id_idx[table_name]
count = 0
for values_str in inserts:
vals = split_sql_values(values_str)
if uid_idx < len(vals) and vals[uid_idx] is not None:
old_uid = vals[uid_idx]
if old_uid not in user_roles:
user_roles[old_uid] = set()
user_roles[old_uid].add(role_type)
count += 1
print(f" {table_name}: {count} 条有 user_id")
# [2] 解析 user_main
print("\n[2/7] 解析 user_main...")
user_main_inserts = parse_insert_values('user_main', sql_content)
total = len(user_main_inserts)
print(f"{total} 条记录")
uid_map = {} # yonghuid -> UserUUID (bytes)
user_id_map = {} # old id -> yonghuid
phone_to_yonghuid = {}
# 先解析所有 user_main 记录
user_data = [] # (old_id, yonghuid, fields_dict, role_type)
prog = Progress(total)
for i, values_str in enumerate(user_main_inserts):
vals = split_sql_values(values_str)
if len(vals) < 16:
prog.update(); continue
old_id = vals[1]
yonghuid = str(vals[2]) if vals[2] else None
if not yonghuid:
prog.update(); continue
# 确定角色:基于扩展表存在性 + user_type
roles = user_roles.get(old_id, set())
user_type = str(vals[11]) if vals[11] else 'normal'
# user_type 也可能指定角色
if user_type == 'admin':
roles.add('admin')
elif user_type == 'kefu':
roles.add('kefu')
# 如果没有任何角色,默认为 normal
if not roles:
roles.add('normal')
# 选择优先级最高的角色
primary_role = 'normal'
for r in ROLE_PRIORITY:
if r in roles:
primary_role = r
break
user_data.append((old_id, yonghuid, vals, primary_role, roles))
user_id_map[old_id] = yonghuid
phone = str(vals[5]) if vals[5] else ''
if phone: phone_to_yonghuid[phone] = yonghuid
prog.update()
prog.finish()
print(f" 解析完成: {len(user_data)} 条有效记录")
# [3] 创建角色
print("\n[3/7] 创建角色...")
created_roles = {}
for user_type, role_name in ROLE_MAP.items():
role, created = Role.objects.get_or_create(
RoleName=role_name, TenantUUID=TENANT_UUID,
defaults={'RoleUUID': uuid.uuid4().bytes, 'RoleDesc': f'{role_name}角色', 'RoleStatus': 1, 'AssignScope': 0})
created_roles[user_type] = role
print(f" {role_name}: {'NEW' if created else 'EXISTS'}")
# [4] 批量创建 User + UserRole + UserSensitiveData
print("\n[4/7] 批量创建 User + UserRole + UserSensitiveData...")
user_batch, ur_batch, usd_batch = [], [], []
errors = 0
prog = Progress(len(user_data))
for old_id, yonghuid, vals, primary_role, all_roles in user_data:
openid = str(vals[3]) if vals[3] else ''
avatar = str(vals[4]) if vals[4] else 'a_long/morentouxiang.jpg'
phone = str(vals[5]) if vals[5] else ''
password = str(vals[6]) if vals[6] else ''
zhifu = str(vals[7]) if vals[7] else ''
skzhanghao = str(vals[8]) if vals[8] else ''
ip = str(vals[9]) if vals[9] else ''
last_login_time = vals[10]
create_time = vals[12]
unionid = str(vals[14]) if vals[14] else ''
shoujihao_renzheng = bool(vals[15]) if vals[15] is not None else False
user_uuid = uuid.uuid4().bytes
ct, lt = parse_dt(create_time), parse_dt(last_login_time)
user_batch.append(User(
UserUUID=user_uuid, UserName=yonghuid, UserUID=yonghuid,
OpenID=openid, UnionID=unionid, Avatar=avatar, Phone=phone,
PhoneVerified=shoujihao_renzheng, IP=ip, UserAccountLicense=1,
UserPositionStatus=0, UserCreateTime=ct, UserLastLoginDate=lt,
IsStaff=('admin' in all_roles), IsSuperuser=('admin' in all_roles)))
# 为每个角色创建 UserRole多对多
for role_type in all_roles:
role = created_roles.get(role_type)
if role:
ur_batch.append(UserRole(
UserRoleUUID=uuid.uuid4().bytes, UserUUID=user_uuid,
RoleUUID=role.RoleUUID, CompanyUUID=COMPANY_UUID))
usd_batch.append(UserSensitiveData(
user_uuid_id=user_uuid, password=password, zhifu=zhifu,
skzhanghao=skzhanghao, shoujihao_renzheng=shoujihao_renzheng))
uid_map[yonghuid] = user_uuid
if len(user_batch) >= BATCH_SIZE:
try:
User.objects.bulk_create(user_batch, ignore_conflicts=True)
UserRole.objects.bulk_create(ur_batch, ignore_conflicts=True)
UserSensitiveData.objects.bulk_create(usd_batch, ignore_conflicts=True)
except Exception: errors += len(user_batch)
user_batch, ur_batch, usd_batch = [], [], []
prog.update()
if user_batch:
try:
User.objects.bulk_create(user_batch, ignore_conflicts=True)
UserRole.objects.bulk_create(ur_batch, ignore_conflicts=True)
UserSensitiveData.objects.bulk_create(usd_batch, ignore_conflicts=True)
except Exception: errors += len(user_batch)
prog.finish()
print(f" 成功: {len(uid_map)}, 错误: {errors}")
# [5] 迁移扩展表 — 用 ORM bulk_create正确字段映射
print("\n[5/7] 迁移扩展表...")
# 正确的字段映射: (sql_index, model_field_name)
# None = 跳过, '_user_id' = FK 到新 User
ext_configs = [
('user_dashou', UserDashou, [
(0, None), (1, 'nicheng'), (2, 'chenghao'), (3, 'zhuangtai'), (4, 'zaixianzhuangtai'),
(5, 'zhanghaozhuangtai'), (6, 'jieshao'), (7, 'jiedanzongliang'), (8, 'chengjiaozongliang'),
(9, 'tuikuanliang'), (10, 'yue'), (11, 'zonge'), (12, 'dianhua'), (13, 'wechat'),
(14, 'yaoqingren'), (15, 'jinrijiedan'), (16, 'jinrishouyi'), (17, 'jinyuejiedan'),
(18, 'jinyueshouyi'), (19, 'jifen'), (20, 'yajin'), (21, None), # create_time
(22, '_user_id'), # user_id FK
(23, 'ewai_xiane'), (24, 'jinritixian_jine'), (25, 'kaioi_ewai_xiane'),
(26, 'last_tixian_date'),
]),
('user_guanshi', UserGuanshi, [
(0, None), (1, 'yaoqingma'), (2, 'dianhua'), (3, 'wechat'),
(4, 'yaogingshuliang'), (5, 'zhuangtai'), (6, 'jinrichongzhi'),
(7, 'jinyuechongzhi'), (8, 'chongzhifenrun'), (9, 'yue'), (10, None), # create_time
(11, '_user_id'),
(12, 'fenghong_erci'), (13, 'fenghong_erci_enabled'), (14, 'fenhong_yici'),
(15, 'ewai_xiane'), (16, 'jinritixian_jine'), (17, 'kaioi_ewai_xiane'),
(18, 'last_tixian_date'), (19, 'yaoqingren'), (20, 'invite_qrcode_url'),
]),
('user_kefu', UserKefu, [
(0, None), (1, 'nicheng'), (2, 'erjimima'), (3, 'zhuangtai'),
(4, 'jinrichuli'), (5, 'jinyuechuli'), (6, 'zongchuli'),
(7, None), (8, None), (9, '_user_id'),
]),
('user_shangjia', UserShangjia, [
(0, None), (1, 'nicheng'), (2, 'zhuangtai'), (3, 'dianhua'), (4, 'wechat'),
(5, 'fabu'), (6, 'tuikuan'), (7, 'yue'), (8, 'chengjiao'),
(9, 'jinridingdan'), (10, 'jinriliushui'), (11, 'jinyuedingdan'),
(12, 'jinyueliushui'), (13, None), (14, '_user_id'),
]),
('user_boss', UserBoss, [
(0, None), (1, 'nickname'), (2, 'zonge'), (3, 'alldingdan'),
(4, 'alltui'), (5, None), (6, '_user_id'),
]),
('admin_profile', AdminProfile, [
(0, None), (1, 'password'), (2, 'wechat'), (3, None),
(4, '_user_id'), (5, 'yaoqingma'),
]),
('user_zuzhang', UserZuzhang, [
(0, None), (1, 'yaoqingma'), (2, 'fenyong_zonge'), (3, 'ketixian_jine'),
(4, 'yaoqing_zongshu'), (5, 'jinri_fenyong'), (6, 'jinyue_fenyong'),
(7, 'zhuangtai'), (8, 'haibao_url'), (9, 'jinri_tixian'), (10, 'last_tixian_time'),
(11, 'ewai_tixian_xiane'), (12, 'kaioi_ewai_tixian'), (13, 'kaioi_ewai_fenhong'),
(14, 'ewai_fenhong_jine'), (15, None), (16, None), (17, '_user_id'),
]),
('user_shenheguan', UserShenheguan, [
(0, None), (1, 'zhuangtai'), (2, 'shenhe_zhuangtai'),
(3, 'shenhe_zongshu'), (4, 'tongguo_zongshu'), (5, 'yue'), (6, 'zonge'),
(7, None), (8, None), (9, '_user_id'), (10, 'is_renzheng'),
]),
]
for table_name, model, field_map in ext_configs:
inserts = parse_insert_values(table_name, sql_content)
if not inserts:
print(f" {table_name}: 0 条"); continue
user_id_sql_idx = next((idx for idx, fn in field_map if fn == '_user_id'), None)
if user_id_sql_idx is None:
print(f" {table_name}: 无法定位 user_id"); continue
batch = []
success = 0
fail = 0
prog = Progress(len(inserts))
for values_str in inserts:
vals = split_sql_values(values_str)
if not vals or user_id_sql_idx >= len(vals) or vals[user_id_sql_idx] is None:
fail += 1; prog.update(); continue
old_user_id = vals[user_id_sql_idx]
yonghuid = user_id_map.get(old_user_id)
if not yonghuid:
fail += 1; prog.update(); continue
new_uuid = uid_map.get(yonghuid)
if not new_uuid:
fail += 1; prog.update(); continue
try:
obj = model(user_id=new_uuid)
for sql_idx, field_name in field_map:
if field_name is None or field_name == '_user_id':
continue
if sql_idx < len(vals) and vals[sql_idx] is not None:
try: setattr(obj, field_name, vals[sql_idx])
except: pass
batch.append(obj)
success += 1
except Exception:
fail += 1
if len(batch) >= BATCH_SIZE:
try: model.objects.bulk_create(batch, ignore_conflicts=True)
except: pass
batch = []
prog.update()
if batch:
try: model.objects.bulk_create(batch, ignore_conflicts=True)
except: pass
prog.finish()
print(f" 成功: {success}, 失败(无user_id): {fail}")
# [6] 迁移其他引用表
print("\n[6/7] 迁移其他引用 yonghuid 的表...")
other_tables = [
'tixianjilu', 'tixian_shenhe_jilu', 'tixian_auto_record',
'xiugaijilu', 'ranking_record',
]
conn = get_raw_conn(db=DATABASE_NAME)
cursor = conn.cursor()
cursor.execute('SET FOREIGN_KEY_CHECKS = 0')
for table_name in other_tables:
inserts = parse_insert_values(table_name, sql_content)
if not inserts:
print(f" {table_name}: 0 条"); continue
success = 0
prog = Progress(len(inserts))
for values_str in inserts:
sql = f"INSERT INTO `{table_name}` VALUES ({values_str})"
try:
cursor.execute(sql)
success += 1
except Exception:
pass
if success % 100 == 0 and success > 0:
try: conn.commit()
except: pass
prog.update()
try: conn.commit()
except MySQLdb.OperationalError:
conn = get_raw_conn(db=DATABASE_NAME)
cursor = conn.cursor()
cursor.execute('SET FOREIGN_KEY_CHECKS = 0')
prog.finish()
print(f" 成功: {success}")
try:
cursor.execute('SET FOREIGN_KEY_CHECKS = 1')
conn.commit(); conn.close()
except: pass
# [7] 验证
print("\n[7/7] 验证迁移结果...")
new_user_count = User.objects.count()
new_ur_count = UserRole.objects.count()
usd_count = UserSensitiveData.objects.count()
print(f" gvsdsdk.User: {new_user_count}")
print(f" UserRole: {new_ur_count}")
print(f" UserSensitiveData: {usd_count}")
print("\n 角色分布:")
for user_type, role in created_roles.items():
ur_count = UserRole.objects.filter(RoleUUID=role.RoleUUID).count()
print(f" {ROLE_MAP[user_type]}: {ur_count}")
print("\n 扩展表:")
for name, model in [('user_dashou', UserDashou), ('user_guanshi', UserGuanshi),
('user_kefu', UserKefu), ('user_shangjia', UserShangjia),
('user_boss', UserBoss), ('admin_profile', AdminProfile),
('user_zuzhang', UserZuzhang), ('user_shenheguan', UserShenheguan)]:
print(f" {name}: {model.objects.count()}")
print("\n" + "=" * 60)
print("迁移完成!")
print(f"TENANT_UUID = {uuid.UUID(bytes=TENANT_UUID)}")
print(f"COMPANY_UUID = {uuid.UUID(bytes=COMPANY_UUID)}")
print("=" * 60)
if __name__ == '__main__':
run_migration()

View File

@@ -1,13 +0,0 @@
import MySQLdb
conn = MySQLdb.connect(
host='gvsds.com', port=50030, user='root',
password='sajksh.sdfGH3YUge.wjkd+',
database='xaio_cheng_xu', charset='utf8mb4'
)
cur = conn.cursor()
cur.execute("SHOW TABLES")
for row in cur.fetchall():
print(row[0])
cur.close()
conn.close()

View File

@@ -1090,7 +1090,7 @@ class ShangJiaXinXiView(APIView):
# ------------------- 3. 从 ShangjiaRiTongji 获取今日统计 -------------------
try:
today_stat = ShangjiaRiTongji.query.get(UserUID=yonghuid, riqi=today)
today_stat = ShangjiaRiTongji.query.get(yonghuid=yonghuid, riqi=today)
jinri_paifa_dingdan = today_stat.paifa_dingdan_shu
jinri_paifa_jine = float(today_stat.paifa_jine)
jinri_tuikuan_dingdan = today_stat.tuikuan_dingdan_shu
@@ -1105,7 +1105,7 @@ class ShangJiaXinXiView(APIView):
# ------------------- 4. 从 ShangjiaRiTongji 获取本月统计 -------------------
month_stats = ShangjiaRiTongji.query.filter(
UserUID=yonghuid,
yonghuid=yonghuid,
riqi__gte=this_month_start,
riqi__lte=today
).aggregate(
@@ -2170,7 +2170,7 @@ class TixianJiluHuoquViewV2(APIView):
limit = 100
offset = (page - 1) * limit
qs = Tixianjilu.query.filter(UserUID=yonghuid)
qs = Tixianjilu.query.filter(yonghuid=yonghuid)
if mode == 2:
# 自动提现含新审核关联记录zhuangtai>0 时按状态筛选
if zhuangtai_filter > 0:
@@ -5739,7 +5739,7 @@ class YonghuTixianShenheXiugaiView(APIView):
try:
tixian_record = Tixianjilu.objects.select_for_update().get(
id=tixian_id,
UserUID=current_yonghuid # 确保只能修改自己的记录
yonghuid=current_yonghuid # 确保只能修改自己的记录
)
except Tixianjilu.DoesNotExist:
return Response({
@@ -6167,7 +6167,7 @@ class ChufaJiluHuoquView(APIView):
zhengju_mapping = {}
if dingdan_ids and shangjia_ids:
# 构建Q对象dingdan_id在列表中 AND yonghuid在商家ID列表中
zhengju_q = Q(dingdan_id__in=dingdan_ids, UserUID__in=shangjia_ids)
zhengju_q = Q(dingdan_id__in=dingdan_ids, yonghuid__in=shangjia_ids)
zhengju_queryset = Chufatupian.query.filter(zhengju_q).values('dingdan_id', 'yonghuid', 'tupian')
for item in zhengju_queryset:
@@ -6362,7 +6362,7 @@ class DashouShensuView(APIView):
# 检查是否已经有申诉图片
existing_shensu_tupian = Chufatupian.query.filter(
dingdan_id=chufa_record.dingdan_id,
UserUID=yonghuid
yonghuid=yonghuid
).exists()
if existing_shensu_tupian:
@@ -6609,7 +6609,7 @@ class ShangjiaChufaJiluHuoquView(APIView):
shensu_mapping = {}
if dingdan_ids and dashou_ids:
# 构建Q对象dingdan_id在列表中 AND yonghuid在打手ID列表中
shensu_q = Q(dingdan_id__in=dingdan_ids, UserUID__in=dashou_ids)
shensu_q = Q(dingdan_id__in=dingdan_ids, yonghuid__in=dashou_ids)
shensu_queryset = Chufatupian.query.filter(shensu_q).values('dingdan_id', 'yonghuid', 'tupian')
for item in shensu_queryset:
@@ -9198,11 +9198,11 @@ class KefuPunishmentDetailView(APIView):
shensu_images = []
try:
# 商家证据图片:上传者为请求人 (qingqiuid)
zhengju_qs = Chufatupian.query.filter(dingdan_id=dingdan_id, UserUID=record.qingqiuid)
zhengju_qs = Chufatupian.query.filter(dingdan_id=dingdan_id, yonghuid=record.qingqiuid)
zhengju_images = [item.tupian for item in zhengju_qs if item.tupian]
# 打手申诉图片:上传者为打手 (dashouid)
shensu_qs = Chufatupian.query.filter(dingdan_id=dingdan_id, UserUID=record.dashouid)
shensu_qs = Chufatupian.query.filter(dingdan_id=dingdan_id, yonghuid=record.dashouid)
shensu_images = [item.tupian for item in shensu_qs if item.tupian]
except Exception as e:
logger.error(f"查询图片失败: {e}")
@@ -11940,7 +11940,7 @@ class FaKuanPayPollView(APIView):
if not dingdanid:
return Response({'code': 400, 'message': '订单ID不能为空'})
order = Czjilu.query.get(dingdan_id=dingdanid, UserUID=request.user.yonghuid)
order = Czjilu.query.get(dingdan_id=dingdanid, yonghuid=request.user.yonghuid)
if order.zhuangtai == 3:
return Response({'code': 200, 'message': '支付成功'})
else:
@@ -11963,7 +11963,7 @@ class FaKuanPayFailView(APIView):
if not dingdanid:
return Response({'code': 400, 'message': '订单ID不能为空'})
order = Czjilu.query.get(dingdan_id=dingdanid, UserUID=request.user.yonghuid)
order = Czjilu.query.get(dingdan_id=dingdanid, yonghuid=request.user.yonghuid)
if order.zhuangtai == 9: # 未支付
order.delete()
logger.info(f"用户{request.user.yonghuid}删除未支付订单: {dingdanid}")
@@ -12375,7 +12375,7 @@ class KaohePayCallbackView(View):
# 从临时表获取业务参数并创建审核记录
try:
temp = KaohePayTemp.query.get(dingdan_id=out_trade_no, UserUID=order.yonghuid)
temp = KaohePayTemp.query.get(dingdan_id=out_trade_no, yonghuid=order.yonghuid)
logger.info(f"找到临时表记录: {out_trade_no}, 用户ID: {order.yonghuid}")
user = User.query.get(UserUID=order.yonghuid)
@@ -12495,7 +12495,7 @@ class KaohePayPollView(APIView):
if not dingdanid:
return Response({'code': 400, 'message': '订单ID不能为空'})
try:
order = Czjilu.query.get(dingdan_id=dingdanid, UserUID=request.user.yonghuid, leixing=5)
order = Czjilu.query.get(dingdan_id=dingdanid, yonghuid=request.user.yonghuid, leixing=5)
if order.zhuangtai == 3:
return Response({'code': 200, 'message': '支付成功'})
return Response({'code': 400, 'message': '订单尚未支付'})
@@ -12512,7 +12512,7 @@ class KaohePayFailView(APIView):
if not dingdanid:
return Response({'code': 400, 'message': '订单ID不能为空'})
try:
order = Czjilu.query.get(dingdan_id=dingdanid, UserUID=request.user.yonghuid, leixing=5)
order = Czjilu.query.get(dingdan_id=dingdanid, yonghuid=request.user.yonghuid, leixing=5)
if order.zhuangtai == 9:
order.delete()
return Response({'code': 200, 'message': '订单已删除'})
@@ -12864,7 +12864,7 @@ class TixianQueRenAutoView(APIView):
try:
auto_record = TixianAutoRecord.objects.select_for_update().get(
tixian_id=tixian_id,
UserUID=user_main.yonghuid,
yonghuid=user_main.yonghuid,
)
except TixianAutoRecord.DoesNotExist:
return Response({'code': 4, 'msg': '提现记录不存在'}, status=status.HTTP_404_NOT_FOUND)

View File

@@ -1,53 +0,0 @@
#!/usr/bin/env python3
"""验证所有兼容性修复"""
import os; os.environ['DJANGO_SETTINGS_MODULE']='a_long_dianjing.settings'
import django; django.setup()
from gvsdsdk.models import User
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.authentication import JWTAuthentication
from unittest.mock import Mock
u = User.objects.filter(UserName__isnull=False).first()
print(f'用户: {u.UserName}, UserUID: {u.UserUID}')
# 1. JWT 认证
refresh = RefreshToken.for_user(u)
access = refresh.access_token
auth = JWTAuthentication()
request = Mock()
request.META = {'HTTP_AUTHORIZATION': f'Bearer {access}'}
request._request = request
validated_user, _ = auth.authenticate(request)
print(f'1. JWT: {validated_user.UserName}')
# 2. 兼容属性
print(f'2. yonghuid: {u.yonghuid}')
print(f' phone: {u.phone}')
print(f' avatar: {u.avatar}')
print(f' ip: {u.ip}')
print(f' last_login_time: {u.last_login_time}')
print(f' shoujihao_renzheng: {u.shoujihao_renzheng}')
print(f' zhifu: {u.zhifu}')
print(f' skzhanghao: {u.skzhanghao}')
# 3. ORM 查询
u2 = User.query.get(UserUID=u.UserUID)
print(f'3. User.query.get(UserUID=): {u2.UserName}')
u3 = User.query.filter(OpenID=u.OpenID).first()
print(f' User.query.filter(OpenID=): {u3.UserName}')
u4 = User.query.filter(Phone=u.Phone).first() if u.Phone else None
print(f' User.query.filter(Phone=): {u4.UserName if u4 else "N/A"}')
# 4. user_type
print(f'4. user_type: {u.user_type}')
# 5. has_role
print(f'5. has_role(dashou): {u.has_role("dashou")}')
# 6. dashou_profile
dp = u.dashou_profile
print(f'6. dashou_profile: {dp}')
print('\n所有测试通过!')