""" 更新数据库中的模板路径,将MinIO路径改为本地相对路径 """ import os import pymysql from pathlib import Path from typing import Dict, List, Optional from dotenv import load_dotenv import difflib # 加载环境变量 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' } TENANT_ID = 615873064429507639 # 本地模板目录(相对于项目根目录) PROJECT_ROOT = Path(__file__).parent TEMPLATES_DIR = PROJECT_ROOT / "template_finish" def print_section(title): """打印章节标题""" print("\n" + "="*70) print(f" {title}") print("="*70) def print_result(success, message): """打印结果""" status = "[OK]" if success else "[FAIL]" print(f"{status} {message}") def scan_local_templates(base_dir: Path) -> Dict[str, Path]: """ 扫描本地模板文件 Returns: 字典,key为文件名(不含路径),value为相对路径(相对于项目根目录) """ templates = {} if not base_dir.exists(): print_result(False, f"模板目录不存在: {base_dir}") return templates # 遍历所有文件 for file_path in base_dir.rglob('*'): if file_path.is_file(): # 只处理文档文件 if file_path.suffix.lower() in ['.doc', '.docx', '.wps']: # 获取相对路径(相对于项目根目录) relative_path = file_path.relative_to(PROJECT_ROOT) # 使用正斜杠作为路径分隔符(跨平台兼容) relative_path_str = str(relative_path).replace('\\', '/') # 使用文件名作为key(不含路径) file_name = file_path.name templates[file_name] = relative_path_str return templates def get_db_templates(conn) -> Dict[str, List[Dict]]: """ 从数据库获取所有模板配置 Returns: 字典,key为文件名(从file_path中提取),value为模板信息列表(可能有多个同名文件) """ cursor = conn.cursor(pymysql.cursors.DictCursor) try: sql = """ SELECT id, name, file_path FROM f_polic_file_config WHERE tenant_id = %s AND state = 1 AND file_path IS NOT NULL AND file_path != '' """ cursor.execute(sql, (TENANT_ID,)) templates = cursor.fetchall() # 构建字典:文件名 -> 模板信息列表 result = {} for template in templates: file_path = template['file_path'] if file_path: # 从file_path中提取文件名(可能是MinIO路径或本地路径) # 处理各种路径格式 file_name = Path(file_path).name if file_name not in result: result[file_name] = [] result[file_name].append({ 'id': template['id'], 'name': template['name'], 'file_path': file_path }) return result finally: cursor.close() def find_best_match(local_file_name: str, db_file_names: List[str], threshold: float = 0.8) -> Optional[str]: """ 使用模糊匹配找到最佳匹配的文件名 Args: local_file_name: 本地文件名 db_file_names: 数据库中的文件名列表 threshold: 相似度阈值(0-1之间) Returns: 最佳匹配的文件名,如果没有找到则返回None """ if not db_file_names: return None # 先尝试精确匹配 if local_file_name in db_file_names: return local_file_name # 使用模糊匹配 matches = difflib.get_close_matches(local_file_name, db_file_names, n=1, cutoff=threshold) if matches: return matches[0] return None def update_template_path(conn, template_id: int, new_path: str, old_path: str): """更新数据库中的模板路径""" cursor = conn.cursor() try: sql = """ UPDATE f_polic_file_config SET file_path = %s WHERE id = %s """ cursor.execute(sql, (new_path, template_id)) conn.commit() return cursor.rowcount > 0 except Exception as e: conn.rollback() raise e finally: cursor.close() def main(): """主函数""" print_section("更新模板路径:从MinIO路径改为本地相对路径") # 1. 扫描本地模板文件 print_section("1. 扫描本地模板文件") local_templates = scan_local_templates(TEMPLATES_DIR) print_result(True, f"找到 {len(local_templates)} 个本地模板文件") if not local_templates: print_result(False, "未找到本地模板文件,请检查 template_finish 目录") return # 2. 连接数据库 print_section("2. 连接数据库") try: conn = pymysql.connect(**DB_CONFIG) print_result(True, "数据库连接成功") except Exception as e: print_result(False, f"数据库连接失败: {str(e)}") return try: # 3. 获取数据库中的模板 print_section("3. 获取数据库中的模板配置") db_templates = get_db_templates(conn) print_result(True, f"找到 {sum(len(v) for v in db_templates.values())} 条数据库模板记录") # 4. 匹配并更新路径 print_section("4. 匹配并更新路径") updated_count = 0 skipped_count = 0 not_found_count = 0 # 遍历数据库中的模板 for db_file_name, template_list in db_templates.items(): # 查找本地匹配的文件 local_path = local_templates.get(db_file_name) if not local_path: # 尝试模糊匹配 local_file_names = list(local_templates.keys()) matched_name = find_best_match(db_file_name, local_file_names) if matched_name: local_path = local_templates[matched_name] print(f" [模糊匹配] {db_file_name} -> {matched_name}") if local_path: # 更新所有匹配的模板记录 for template in template_list: old_path = template['file_path'] # 检查是否已经是本地路径(避免重复更新) if old_path.startswith('template_finish/'): print(f" [跳过] ID={template['id']}, 名称={template['name']}, 已经是本地路径: {old_path}") skipped_count += 1 continue # 更新路径 try: update_template_path(conn, template['id'], local_path, old_path) print(f" [更新] ID={template['id']}, 名称={template['name']}") print(f" 旧路径: {old_path}") print(f" 新路径: {local_path}") updated_count += 1 except Exception as e: print(f" [错误] ID={template['id']}, 更新失败: {str(e)}") else: # 未找到匹配的本地文件 for template in template_list: print(f" [未找到] ID={template['id']}, 名称={template['name']}, 文件名={db_file_name}") not_found_count += 1 # 5. 输出统计信息 print_section("5. 更新结果统计") print_result(True, f"成功更新: {updated_count} 条记录") if skipped_count > 0: print_result(True, f"跳过(已是本地路径): {skipped_count} 条记录") if not_found_count > 0: print_result(False, f"未找到匹配文件: {not_found_count} 条记录") print_section("更新完成") finally: conn.close() print_result(True, "数据库连接已关闭") if __name__ == "__main__": main()