""" 验证模板层级结构是否正确 """ import os import pymysql from pathlib import Path from typing import Dict, List, Optional from dotenv import load_dotenv # 加载环境变量 load_dotenv() # 数据库配置 DB_CONFIG = { 'host': os.getenv('DB_HOST', '152.136.177.240'), 'port': int(os.getenv('DB_PORT', 5012)), 'user': os.getenv('DB_USER', 'finyx'), 'password': os.getenv('DB_PASSWORD', '6QsGK6MpePZDE57Z'), 'database': os.getenv('DB_NAME', 'finyx'), 'charset': 'utf8mb4' } def print_section(title): """打印章节标题""" print("\n" + "="*70) print(f" {title}") print("="*70) def get_actual_tenant_id(conn) -> int: """获取数据库中的实际tenant_id""" cursor = conn.cursor(pymysql.cursors.DictCursor) try: cursor.execute("SELECT DISTINCT tenant_id FROM f_polic_file_config LIMIT 1") result = cursor.fetchone() if result: return result['tenant_id'] return 1 finally: cursor.close() def print_hierarchy(conn, tenant_id: int, parent_id: Optional[int] = None, level: int = 0, prefix: str = ""): """递归打印层级结构""" cursor = conn.cursor(pymysql.cursors.DictCursor) try: if parent_id is None: sql = """ SELECT id, name, file_path, parent_id FROM f_polic_file_config WHERE tenant_id = %s AND parent_id IS NULL ORDER BY name """ cursor.execute(sql, (tenant_id,)) else: sql = """ SELECT id, name, file_path, parent_id FROM f_polic_file_config WHERE tenant_id = %s AND parent_id = %s ORDER BY name """ cursor.execute(sql, (tenant_id, parent_id)) items = cursor.fetchall() for i, item in enumerate(items): is_last = (i == len(items) - 1) current_prefix = "└── " if is_last else "├── " next_prefix = prefix + (" " if is_last else "│ ") if item['file_path']: # 文件节点 print(f"{prefix}{current_prefix}{item['name']} (文件, ID: {item['id']})") else: # 目录节点 print(f"{prefix}{current_prefix}{item['name']} (目录, ID: {item['id']})") # 递归打印子节点 print_hierarchy(conn, tenant_id, item['id'], level + 1, next_prefix) finally: cursor.close() def verify_hierarchy(conn, tenant_id: int): """验证层级结构""" print_section("验证模板层级结构") cursor = conn.cursor(pymysql.cursors.DictCursor) try: # 1. 统计信息 print("1. 统计信息:") # 根节点(parent_id为NULL) cursor.execute(""" SELECT COUNT(*) as count FROM f_polic_file_config WHERE tenant_id = %s AND parent_id IS NULL """, (tenant_id,)) root_count = cursor.fetchone()['count'] print(f" 根节点: {root_count} 个") # 目录节点(file_path为NULL) cursor.execute(""" SELECT COUNT(*) as count FROM f_polic_file_config WHERE tenant_id = %s AND file_path IS NULL """, (tenant_id,)) dir_count = cursor.fetchone()['count'] print(f" 目录节点: {dir_count} 个") # 文件节点(file_path不为NULL) cursor.execute(""" SELECT COUNT(*) as count FROM f_polic_file_config WHERE tenant_id = %s AND file_path IS NOT NULL """, (tenant_id,)) file_count = cursor.fetchone()['count'] print(f" 文件节点: {file_count} 个") # 有父级的文件 cursor.execute(""" SELECT COUNT(*) as count FROM f_polic_file_config WHERE tenant_id = %s AND file_path IS NOT NULL AND parent_id IS NOT NULL """, (tenant_id,)) file_with_parent = cursor.fetchone()['count'] print(f" 有父级的文件: {file_with_parent} 个") # 没有父级的文件 cursor.execute(""" SELECT COUNT(*) as count FROM f_polic_file_config WHERE tenant_id = %s AND file_path IS NOT NULL AND parent_id IS NULL """, (tenant_id,)) file_without_parent = cursor.fetchone()['count'] print(f" 没有父级的文件: {file_without_parent} 个") # 2. 显示层级结构 print("\n2. 层级结构:") print_hierarchy(conn, tenant_id) # 3. 检查问题 print("\n3. 检查潜在问题:") # 检查是否有孤立的文件(没有父级,但应该在某个目录下) cursor.execute(""" SELECT id, name, file_path FROM f_polic_file_config WHERE tenant_id = %s AND file_path IS NOT NULL AND parent_id IS NULL AND file_path LIKE 'template_finish/%%/%%' """, (tenant_id,)) isolated_files = cursor.fetchall() if isolated_files: print(f" [警告] 发现 {len(isolated_files)} 个可能孤立的文件(有路径但无父级):") for file in isolated_files[:5]: print(f" - {file['name']} (ID: {file['id']})") print(f" 路径: {file['file_path']}") else: print(" [OK] 没有发现孤立的文件") # 检查是否有循环引用 cursor.execute(""" SELECT t1.id, t1.name, t1.parent_id, t2.id as parent_exists FROM f_polic_file_config t1 LEFT JOIN f_polic_file_config t2 ON t1.parent_id = t2.id AND t1.tenant_id = t2.tenant_id WHERE t1.tenant_id = %s AND t1.parent_id IS NOT NULL AND t2.id IS NULL """, (tenant_id,)) broken_links = cursor.fetchall() if broken_links: print(f" [警告] 发现 {len(broken_links)} 个断开的父级链接:") for link in broken_links[:5]: print(f" - {link['name']} (ID: {link['id']}, parent_id: {link['parent_id']})") else: print(" [OK] 没有发现断开的父级链接") finally: cursor.close() def main(): """主函数""" print_section("验证模板层级结构") try: conn = pymysql.connect(**DB_CONFIG) print("[OK] 数据库连接成功") except Exception as e: print(f"[FAIL] 数据库连接失败: {str(e)}") return try: tenant_id = get_actual_tenant_id(conn) print(f"实际tenant_id: {tenant_id}") verify_hierarchy(conn, tenant_id) finally: conn.close() print("\n[OK] 数据库连接已关闭") if __name__ == "__main__": main()