重构模板保存和下载逻辑,将文件保存到本地template_finish文件夹,并更新文档服务以从本地读取模板文件。增强了错误处理,确保文件路径的有效性和安全性。
This commit is contained in:
parent
fb7fb985ad
commit
eec66cbe05
68
README_模板字段导出说明.md
Normal file
68
README_模板字段导出说明.md
Normal file
@ -0,0 +1,68 @@
|
||||
# 模板字段导出说明
|
||||
|
||||
## 功能说明
|
||||
|
||||
`export_template_fields_to_excel.py` 脚本用于导出所有模板及其关联的输入字段和输出字段到Excel表格,方便汇总整理模板和字段关系。
|
||||
|
||||
## 使用方法
|
||||
|
||||
```bash
|
||||
python export_template_fields_to_excel.py
|
||||
```
|
||||
|
||||
## 输出文件
|
||||
|
||||
脚本会在当前目录生成Excel文件,文件名格式:`template_fields_export_YYYYMMDD_HHMMSS.xlsx`
|
||||
|
||||
## Excel表格结构
|
||||
|
||||
生成的Excel表格包含以下列:
|
||||
|
||||
1. **模板ID** - 模板在数据库中的唯一标识
|
||||
2. **模板名称** - 模板的中文名称
|
||||
3. **模板上级** - 模板的分类路径(从文件路径或模板名称推断,可能不完整,需要手动补充)
|
||||
4. **输入字段** - 该模板关联的输入字段列表,格式:`字段名称(字段编码); 字段名称(字段编码)`
|
||||
5. **输出字段** - 该模板关联的输出字段列表,格式:`字段名称(字段编码); 字段名称(字段编码)`
|
||||
6. **输入字段数量** - 输入字段的个数
|
||||
7. **输出字段数量** - 输出字段的个数
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **模板上级字段**:脚本会尝试从文件路径或模板名称推断模板的分类,但可能不完整或不准确。您可以在Excel中手动补充或修正。
|
||||
|
||||
2. **字段格式**:输入字段和输出字段以分号分隔,每个字段的格式为 `字段名称(字段编码)`。
|
||||
|
||||
3. **数据来源**:所有数据来自数据库,只导出状态为启用(state=1)的模板和字段。
|
||||
|
||||
4. **后续使用**:您可以基于这个Excel表格:
|
||||
- 手动补充或修正模板上级分类
|
||||
- 新增模板和字段关系
|
||||
- 创建导入脚本将修改后的数据导入数据库
|
||||
|
||||
## 示例数据
|
||||
|
||||
```
|
||||
模板ID: 1765432134276990
|
||||
模板名称: 1.请示报告卡(初核谈话)
|
||||
模板上级: 2-初核模版/2.谈话审批
|
||||
输入字段: 线索信息(clue_info); 被核查人员工作基本情况线索(target_basic_info_clue)
|
||||
输出字段: 被核查人姓名(target_name); 被核查人员单位及职务(target_organization_and_position); ...
|
||||
输入字段数量: 2
|
||||
输出字段数量: 3
|
||||
```
|
||||
|
||||
## 导入脚本开发建议
|
||||
|
||||
后续开发导入脚本时,可以参考以下步骤:
|
||||
|
||||
1. 读取Excel文件
|
||||
2. 解析模板名称、模板上级、输入字段、输出字段
|
||||
3. 根据模板名称查找或创建模板记录
|
||||
4. 根据字段编码查找字段ID
|
||||
5. 创建或更新模板和字段的关联关系
|
||||
|
||||
## 相关文件
|
||||
|
||||
- `export_template_fields_to_excel.py` - 导出脚本
|
||||
- `template_fields_export_*.xlsx` - 生成的Excel文件
|
||||
|
||||
39
app.py
39
app.py
@ -11,6 +11,7 @@ import tempfile
|
||||
import zipfile
|
||||
import re
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from dotenv import load_dotenv
|
||||
from flask import send_file
|
||||
from docx import Document
|
||||
@ -1921,26 +1922,30 @@ def save_template():
|
||||
|
||||
new_field_map[placeholder] = field_id
|
||||
|
||||
# 2. 上传文件到 MinIO
|
||||
minio_client = get_minio_client()
|
||||
bucket_name = os.getenv('MINIO_BUCKET', 'finyx')
|
||||
# 2. 保存文件到本地 template_finish 文件夹
|
||||
# 获取项目根目录
|
||||
project_root = Path(__file__).parent
|
||||
templates_dir = project_root / "template_finish"
|
||||
|
||||
# 确保存储桶存在
|
||||
if not minio_client.bucket_exists(bucket_name):
|
||||
minio_client.make_bucket(bucket_name)
|
||||
# 创建 uploaded 子目录用于存放新上传的模板
|
||||
uploaded_dir = templates_dir / "uploaded"
|
||||
uploaded_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# 生成 MinIO 路径
|
||||
# 生成本地文件路径(使用时间戳确保文件名唯一)
|
||||
now = datetime.now()
|
||||
object_name = f'{tenant_id}/TEMPLATE/{now.year}/{now.month:02d}/{filename}'
|
||||
timestamp = now.strftime('%Y%m%d_%H%M%S')
|
||||
# 处理文件名,确保安全
|
||||
safe_filename = secure_filename(filename)
|
||||
# 如果文件名已存在,添加时间戳前缀
|
||||
local_file_path = uploaded_dir / f"{timestamp}_{safe_filename}"
|
||||
|
||||
minio_client.fput_object(
|
||||
bucket_name,
|
||||
object_name,
|
||||
temp_file_path,
|
||||
content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
||||
)
|
||||
# 复制文件到本地
|
||||
import shutil
|
||||
shutil.copy2(temp_file_path, local_file_path)
|
||||
|
||||
minio_path = f"/{object_name}"
|
||||
# 生成相对路径(相对于项目根目录,使用正斜杠)
|
||||
local_path = local_file_path.relative_to(project_root)
|
||||
local_path_str = str(local_path).replace('\\', '/')
|
||||
|
||||
# 3. 保存模板到数据库
|
||||
template_id = generate_id()
|
||||
@ -1956,7 +1961,7 @@ def save_template():
|
||||
None, # parent_id
|
||||
template_name_final,
|
||||
json.dumps({'template_name': template_name_final}, ensure_ascii=False),
|
||||
minio_path,
|
||||
local_path_str,
|
||||
created_by,
|
||||
updated_by
|
||||
))
|
||||
@ -2005,7 +2010,7 @@ def save_template():
|
||||
return success_response({
|
||||
'template_id': template_id,
|
||||
'template_name': template_name_final,
|
||||
'file_path': minio_path,
|
||||
'file_path': local_path_str,
|
||||
'field_count': len(all_field_ids)
|
||||
}, "模板保存成功")
|
||||
|
||||
|
||||
328
export_template_fields_to_excel.py
Normal file
328
export_template_fields_to_excel.py
Normal file
@ -0,0 +1,328 @@
|
||||
"""
|
||||
导出模板和字段关系到Excel表格
|
||||
用于汇总整理模板和字段关系,后续可以基于这个Excel表格新增数据并增加导入脚本
|
||||
"""
|
||||
import pymysql
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
|
||||
from openpyxl.utils import get_column_letter
|
||||
from datetime import datetime
|
||||
import re
|
||||
|
||||
# 加载环境变量
|
||||
load_dotenv()
|
||||
|
||||
# 数据库配置
|
||||
DB_CONFIG = {
|
||||
'host': os.getenv('DB_HOST'),
|
||||
'port': int(os.getenv('DB_PORT', 3306)),
|
||||
'user': os.getenv('DB_USER'),
|
||||
'password': os.getenv('DB_PASSWORD'),
|
||||
'database': os.getenv('DB_NAME'),
|
||||
'charset': 'utf8mb4'
|
||||
}
|
||||
|
||||
TENANT_ID = 615873064429507639
|
||||
|
||||
|
||||
def clean_query_result(data):
|
||||
"""清理查询结果,将 bytes 类型转换为字符串"""
|
||||
if isinstance(data, bytes):
|
||||
if len(data) == 1:
|
||||
return int.from_bytes(data, byteorder='big')
|
||||
try:
|
||||
return data.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
return data.decode('utf-8', errors='ignore')
|
||||
elif isinstance(data, dict):
|
||||
return {key: clean_query_result(value) for key, value in data.items()}
|
||||
elif isinstance(data, list):
|
||||
return [clean_query_result(item) for item in data]
|
||||
elif isinstance(data, (int, float, str, bool, type(None))):
|
||||
return data
|
||||
else:
|
||||
return str(data)
|
||||
|
||||
|
||||
def extract_template_category(file_path, template_name):
|
||||
"""
|
||||
从文件路径或模板名称提取模板的上级分类
|
||||
例如:/615873064429507639/TEMPLATE/2025/12/2-初核模版/2.谈话审批/走读式谈话审批/2谈话审批表.docx
|
||||
提取为:2-初核模版/2.谈话审批/走读式谈话审批
|
||||
"""
|
||||
category = ""
|
||||
|
||||
# 首先尝试从文件路径提取
|
||||
if file_path:
|
||||
# 移除开头的斜杠和租户ID部分
|
||||
path = file_path.lstrip('/')
|
||||
# 移除租户ID/TEMPLATE/年份/月份/部分
|
||||
pattern = r'^\d+/TEMPLATE/\d+/\d+/(.+)'
|
||||
match = re.match(pattern, path)
|
||||
if match:
|
||||
full_path = match.group(1)
|
||||
# 移除文件名,只保留目录路径
|
||||
if '/' in full_path:
|
||||
category = '/'.join(full_path.split('/')[:-1])
|
||||
|
||||
# 如果路径格式不匹配,尝试其他方式
|
||||
if not category and ('template_finish' in path.lower() or '初核' in path or '谈话' in path or '函询' in path):
|
||||
# 尝试提取目录结构
|
||||
parts = path.split('/')
|
||||
result_parts = []
|
||||
for part in parts:
|
||||
if any(keyword in part for keyword in ['初核', '谈话', '函询', '模版', '模板']):
|
||||
result_parts.append(part)
|
||||
if result_parts:
|
||||
category = '/'.join(result_parts[:-1]) if len(result_parts) > 1 else result_parts[0]
|
||||
|
||||
# 如果从路径无法提取,尝试从模板名称推断
|
||||
if not category and template_name:
|
||||
# 根据模板名称中的关键词推断分类
|
||||
if '初核' in template_name:
|
||||
if '谈话' in template_name:
|
||||
category = '2-初核模版/2.谈话审批'
|
||||
elif '请示' in template_name or '审批' in template_name:
|
||||
category = '2-初核模版/1.初核请示'
|
||||
elif '结论' in template_name or '报告' in template_name:
|
||||
category = '2-初核模版/3.初核结论'
|
||||
else:
|
||||
category = '2-初核模版'
|
||||
elif '谈话' in template_name:
|
||||
if '函询' in template_name:
|
||||
category = '1-谈话函询模板/函询模板'
|
||||
else:
|
||||
category = '1-谈话函询模板/谈话模版'
|
||||
elif '函询' in template_name:
|
||||
category = '1-谈话函询模板/函询模板'
|
||||
|
||||
return category
|
||||
|
||||
|
||||
def get_all_templates_with_fields():
|
||||
"""
|
||||
获取所有模板及其关联的输入和输出字段
|
||||
|
||||
Returns:
|
||||
list: 模板列表,每个模板包含字段信息
|
||||
"""
|
||||
conn = pymysql.connect(**DB_CONFIG)
|
||||
cursor = conn.cursor(pymysql.cursors.DictCursor)
|
||||
|
||||
try:
|
||||
# 查询所有启用的模板
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
fc.id AS template_id,
|
||||
fc.name AS template_name,
|
||||
fc.file_path
|
||||
FROM f_polic_file_config fc
|
||||
WHERE fc.tenant_id = %s
|
||||
AND fc.state = 1
|
||||
ORDER BY fc.name
|
||||
""", (TENANT_ID,))
|
||||
|
||||
templates = cursor.fetchall()
|
||||
templates = [clean_query_result(t) for t in templates]
|
||||
|
||||
result = []
|
||||
|
||||
for template in templates:
|
||||
template_id = template['template_id']
|
||||
template_name = template['template_name']
|
||||
file_path = template.get('file_path', '')
|
||||
|
||||
# 提取模板上级分类
|
||||
template_category = extract_template_category(file_path, template_name)
|
||||
|
||||
# 查询该模板关联的输入字段
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
f.id AS field_id,
|
||||
f.name AS field_name,
|
||||
f.filed_code AS field_code
|
||||
FROM f_polic_file_field fff
|
||||
INNER JOIN f_polic_field f ON fff.filed_id = f.id
|
||||
WHERE fff.file_id = %s
|
||||
AND fff.tenant_id = %s
|
||||
AND fff.state = 1
|
||||
AND f.state = 1
|
||||
AND f.field_type = 1
|
||||
ORDER BY f.name
|
||||
""", (template_id, TENANT_ID))
|
||||
|
||||
input_fields = cursor.fetchall()
|
||||
input_fields = [clean_query_result(f) for f in input_fields]
|
||||
|
||||
# 查询该模板关联的输出字段
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
f.id AS field_id,
|
||||
f.name AS field_name,
|
||||
f.filed_code AS field_code
|
||||
FROM f_polic_file_field fff
|
||||
INNER JOIN f_polic_field f ON fff.filed_id = f.id
|
||||
WHERE fff.file_id = %s
|
||||
AND fff.tenant_id = %s
|
||||
AND fff.state = 1
|
||||
AND f.state = 1
|
||||
AND f.field_type = 2
|
||||
ORDER BY f.name
|
||||
""", (template_id, TENANT_ID))
|
||||
|
||||
output_fields = cursor.fetchall()
|
||||
output_fields = [clean_query_result(f) for f in output_fields]
|
||||
|
||||
# 格式化字段信息
|
||||
input_fields_str = '; '.join([f"{f['field_name']}({f['field_code']})" for f in input_fields])
|
||||
output_fields_str = '; '.join([f"{f['field_name']}({f['field_code']})" for f in output_fields])
|
||||
|
||||
result.append({
|
||||
'template_id': template_id,
|
||||
'template_name': template_name,
|
||||
'template_category': template_category,
|
||||
'input_fields': input_fields,
|
||||
'output_fields': output_fields,
|
||||
'input_fields_str': input_fields_str,
|
||||
'output_fields_str': output_fields_str,
|
||||
'input_field_count': len(input_fields),
|
||||
'output_field_count': len(output_fields)
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
|
||||
def create_excel_file(templates_data, output_file='template_fields_export.xlsx'):
|
||||
"""
|
||||
创建Excel文件
|
||||
|
||||
Args:
|
||||
templates_data: 模板数据列表
|
||||
output_file: 输出文件名
|
||||
"""
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
ws.title = "模板字段关系"
|
||||
|
||||
# 设置表头
|
||||
headers = ['模板ID', '模板名称', '模板上级', '输入字段', '输出字段', '输入字段数量', '输出字段数量']
|
||||
ws.append(headers)
|
||||
|
||||
# 设置表头样式
|
||||
header_fill = PatternFill(start_color="366092", end_color="366092", fill_type="solid")
|
||||
header_font = Font(bold=True, color="FFFFFF", size=11)
|
||||
header_alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
|
||||
border = Border(
|
||||
left=Side(style='thin'),
|
||||
right=Side(style='thin'),
|
||||
top=Side(style='thin'),
|
||||
bottom=Side(style='thin')
|
||||
)
|
||||
|
||||
for col_num, header in enumerate(headers, 1):
|
||||
cell = ws.cell(row=1, column=col_num)
|
||||
cell.fill = header_fill
|
||||
cell.font = header_font
|
||||
cell.alignment = header_alignment
|
||||
cell.border = border
|
||||
|
||||
# 填充数据
|
||||
data_font = Font(size=10)
|
||||
data_alignment = Alignment(horizontal="left", vertical="top", wrap_text=True)
|
||||
|
||||
for template in templates_data:
|
||||
row = [
|
||||
template['template_id'],
|
||||
template['template_name'],
|
||||
template['template_category'],
|
||||
template['input_fields_str'],
|
||||
template['output_fields_str'],
|
||||
template['input_field_count'],
|
||||
template['output_field_count']
|
||||
]
|
||||
ws.append(row)
|
||||
|
||||
# 设置数据行样式
|
||||
for col_num in range(1, len(headers) + 1):
|
||||
cell = ws.cell(row=ws.max_row, column=col_num)
|
||||
cell.font = data_font
|
||||
cell.alignment = data_alignment
|
||||
cell.border = border
|
||||
|
||||
# 设置列宽
|
||||
ws.column_dimensions['A'].width = 18 # 模板ID
|
||||
ws.column_dimensions['B'].width = 40 # 模板名称
|
||||
ws.column_dimensions['C'].width = 50 # 模板上级
|
||||
ws.column_dimensions['D'].width = 60 # 输入字段
|
||||
ws.column_dimensions['E'].width = 80 # 输出字段
|
||||
ws.column_dimensions['F'].width = 15 # 输入字段数量
|
||||
ws.column_dimensions['G'].width = 15 # 输出字段数量
|
||||
|
||||
# 设置行高
|
||||
ws.row_dimensions[1].height = 30 # 表头行高
|
||||
for row_num in range(2, ws.max_row + 1):
|
||||
ws.row_dimensions[row_num].height = 60 # 数据行高
|
||||
|
||||
# 冻结首行
|
||||
ws.freeze_panes = 'A2'
|
||||
|
||||
# 保存文件
|
||||
wb.save(output_file)
|
||||
print(f"Excel文件已生成: {output_file}")
|
||||
print(f"共导出 {len(templates_data)} 个模板")
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print("开始导出模板和字段关系...")
|
||||
print("=" * 80)
|
||||
|
||||
try:
|
||||
# 获取所有模板及其字段
|
||||
templates_data = get_all_templates_with_fields()
|
||||
|
||||
if not templates_data:
|
||||
print("未找到任何模板数据")
|
||||
return
|
||||
|
||||
print(f"共找到 {len(templates_data)} 个模板")
|
||||
|
||||
# 生成Excel文件
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
output_file = f"template_fields_export_{timestamp}.xlsx"
|
||||
create_excel_file(templates_data, output_file)
|
||||
|
||||
# 打印统计信息
|
||||
print("\n统计信息:")
|
||||
print(f" 模板总数: {len(templates_data)}")
|
||||
total_input_fields = sum(t['input_field_count'] for t in templates_data)
|
||||
total_output_fields = sum(t['output_field_count'] for t in templates_data)
|
||||
print(f" 输入字段总数: {total_input_fields}")
|
||||
print(f" 输出字段总数: {total_output_fields}")
|
||||
|
||||
# 打印前几个模板的信息
|
||||
print("\n前5个模板预览:")
|
||||
for i, template in enumerate(templates_data[:5], 1):
|
||||
print(f"\n{i}. {template['template_name']}")
|
||||
print(f" 上级: {template['template_category']}")
|
||||
print(f" 输入字段: {template['input_field_count']} 个")
|
||||
print(f" 输出字段: {template['output_field_count']} 个")
|
||||
|
||||
if len(templates_data) > 5:
|
||||
print(f"\n... 还有 {len(templates_data) - 5} 个模板")
|
||||
|
||||
except Exception as e:
|
||||
print(f"导出失败: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@ -117,10 +117,10 @@ class DocumentService:
|
||||
|
||||
def download_template_from_minio(self, file_path: str) -> str:
|
||||
"""
|
||||
从MinIO下载模板文件到临时目录
|
||||
从本地template_finish文件夹读取模板文件到临时目录
|
||||
|
||||
Args:
|
||||
file_path: MinIO中的相对路径,如 '/615873064429507639/TEMPLATE/2024/11/初步核实审批表模板.docx'
|
||||
file_path: 本地相对路径(相对于项目根目录),如 'template_finish/2-初核模版/1.初核请示/1.请示报告卡(XXX).docx'
|
||||
|
||||
Returns:
|
||||
本地临时文件路径
|
||||
@ -129,23 +129,34 @@ class DocumentService:
|
||||
if not file_path:
|
||||
raise Exception("模板文件路径不能为空,请检查数据库中模板配置的file_path字段")
|
||||
|
||||
client = self.get_minio_client()
|
||||
# 获取项目根目录(document_service.py在services/目录下,需要向上一级)
|
||||
project_root = Path(__file__).parent.parent
|
||||
local_template_path = project_root / file_path
|
||||
|
||||
# 检查文件是否存在
|
||||
if not local_template_path.exists():
|
||||
raise Exception(f"模板文件不存在: {local_template_path}。请检查数据库中的file_path配置是否正确。")
|
||||
|
||||
if not local_template_path.is_file():
|
||||
raise Exception(f"路径不是文件: {local_template_path}")
|
||||
|
||||
# 创建临时文件
|
||||
temp_dir = tempfile.gettempdir()
|
||||
temp_file = os.path.join(temp_dir, f"template_{datetime.now().strftime('%Y%m%d%H%M%S')}.docx")
|
||||
# 使用原文件名和扩展名,但添加时间戳确保唯一性
|
||||
original_name = local_template_path.name
|
||||
name_without_ext = local_template_path.stem
|
||||
ext = local_template_path.suffix
|
||||
temp_file = os.path.join(temp_dir, f"template_{name_without_ext}_{datetime.now().strftime('%Y%m%d%H%M%S')}{ext}")
|
||||
|
||||
try:
|
||||
# 从相对路径中提取对象名称(去掉开头的/)
|
||||
object_name = file_path.lstrip('/')
|
||||
|
||||
# 下载文件
|
||||
client.fget_object(self.bucket_name, object_name, temp_file)
|
||||
# 复制文件到临时目录
|
||||
import shutil
|
||||
shutil.copy2(local_template_path, temp_file)
|
||||
|
||||
return temp_file
|
||||
|
||||
except S3Error as e:
|
||||
raise Exception(f"从MinIO下载模板文件失败: {str(e)}")
|
||||
except Exception as e:
|
||||
raise Exception(f"从本地读取模板文件失败: {str(e)}")
|
||||
|
||||
def replace_placeholders_via_xml(self, docx_path: str, field_data: Dict[str, str]) -> bool:
|
||||
"""
|
||||
|
||||
BIN
template_fields_export_20251216_101749.xlsx
Normal file
BIN
template_fields_export_20251216_101749.xlsx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/函询模板/1.纪委请示报告卡.docx
Normal file
BIN
template_finish/1-谈话函询模板/函询模板/1.纪委请示报告卡.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/函询模板/2谈话函询呈批表.docx
Normal file
BIN
template_finish/1-谈话函询模板/函询模板/2谈话函询呈批表.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/函询模板/3函询通知书.docx
Normal file
BIN
template_finish/1-谈话函询模板/函询模板/3函询通知书.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/函询模板/4. 函询情况报告.docx
Normal file
BIN
template_finish/1-谈话函询模板/函询模板/4. 函询情况报告.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/函询模板/5.纪委请示报告卡.docx
Normal file
BIN
template_finish/1-谈话函询模板/函询模板/5.纪委请示报告卡.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/函询模板/6.谈话函询结果呈批表.doc
Normal file
BIN
template_finish/1-谈话函询模板/函询模板/6.谈话函询结果呈批表.doc
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/函询模板/7.反馈通知书.docx
Normal file
BIN
template_finish/1-谈话函询模板/函询模板/7.反馈通知书.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/谈话模版/1.请示报告卡.docx
Normal file
BIN
template_finish/1-谈话函询模板/谈话模版/1.请示报告卡.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/谈话模版/2.谈话函询呈批表.docx
Normal file
BIN
template_finish/1-谈话函询模板/谈话模版/2.谈话函询呈批表.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/谈话模版/3.谈话方案、安全预案.docx
Normal file
BIN
template_finish/1-谈话函询模板/谈话模版/3.谈话方案、安全预案.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/谈话模版/4.谈话通知书.docx
Normal file
BIN
template_finish/1-谈话函询模板/谈话模版/4.谈话通知书.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/谈话模版/5.谈话笔录.docx
Normal file
BIN
template_finish/1-谈话函询模板/谈话模版/5.谈话笔录.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/谈话模版/6.请示报告卡(了结).docx
Normal file
BIN
template_finish/1-谈话函询模板/谈话模版/6.请示报告卡(了结).docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/谈话模版/7.谈话函询结果呈批表.docx
Normal file
BIN
template_finish/1-谈话函询模板/谈话模版/7.谈话函询结果呈批表.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/谈话模版/8.谈话情况报告.docx
Normal file
BIN
template_finish/1-谈话函询模板/谈话模版/8.谈话情况报告.docx
Normal file
Binary file not shown.
BIN
template_finish/1-谈话函询模板/谈话模版/9.谈话了结通知书.docx
Normal file
BIN
template_finish/1-谈话函询模板/谈话模版/9.谈话了结通知书.docx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
template_finish/3-立案模版/党员/移送审理/1.请示报告卡(移送审理).doc
Normal file
BIN
template_finish/3-立案模版/党员/移送审理/1.请示报告卡(移送审理).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/移送审理/2.移送审理审批表.doc
Normal file
BIN
template_finish/3-立案模版/党员/移送审理/2.移送审理审批表.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/移送审理/3.案件材料移送审理交接单.doc
Normal file
BIN
template_finish/3-立案模版/党员/移送审理/3.案件材料移送审理交接单.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/1.立案审查请示报批/1.请示报告卡(立案审查).docx
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/1.立案审查请示报批/1.请示报告卡(立案审查).docx
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/1.立案审查请示报批/2.立案审批表.docx
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/1.立案审查请示报批/2.立案审批表.docx
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/1.立案审查请示报批/3.会议纪要(立案审查).doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/1.立案审查请示报批/3.会议纪要(立案审查).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/1.立案审查请示报批/4.立案审查方案.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/1.立案审查请示报批/4.立案审查方案.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/2.立案决定书/立案决定书-第一联.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/2.立案决定书/立案决定书-第一联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/2.立案决定书/立案决定书-第三联.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/2.立案决定书/立案决定书-第三联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/2.立案决定书/立案决定书-第二联.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/2.立案决定书/立案决定书-第二联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/3.立案通知书/立案通知书-第一联.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/3.立案通知书/立案通知书-第一联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/3.立案通知书/立案通知书-第三联(送达单位).doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/3.立案通知书/立案通知书-第三联(送达单位).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/3.立案通知书/立案通知书-第二联(单位签字后附卷).doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/3.立案通知书/立案通知书-第二联(单位签字后附卷).doc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/1.请示报告卡(谈话-直接立案).doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/1.请示报告卡(谈话-直接立案).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/2谈话审批表.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/2谈话审批表.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/3.谈话前安全风险评估表.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/3.谈话前安全风险评估表.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/4.谈话方案.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/4.谈话方案.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/5谈话询问对象情况摸底调查30问.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/5谈话询问对象情况摸底调查30问.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/6.被谈话人权利义务告知书.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/6.被谈话人权利义务告知书.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/7谈话笔录.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/7谈话笔录.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/8.点对点交接单.wps
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/8.点对点交接单.wps
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/9.陪送交接单(新).doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/4.谈话请示报批/9.陪送交接单(新).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/5.谈话通知书/谈话通知书第一联.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/5.谈话通知书/谈话通知书第一联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/5.谈话通知书/谈话通知书第三联.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/5.谈话通知书/谈话通知书第三联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/5.谈话通知书/谈话通知书第二联.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/5.谈话通知书/谈话通知书第二联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/6.立案审查报告请示报批/1.会议纪要(审查处分意见).doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/6.立案审查报告请示报批/1.会议纪要(审查处分意见).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/6.立案审查报告请示报批/2.请示报告卡(审查报告).doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/6.立案审查报告请示报批/2.请示报告卡(审查报告).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/6.立案审查报告请示报批/3.审查报告.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/6.立案审查报告请示报批/3.审查报告.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/6.立案审查报告请示报批/4.个人简历.docx
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/6.立案审查报告请示报批/4.个人简历.docx
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/立案审查/6.立案审查报告请示报批/5.违纪事实材料.doc
Normal file
BIN
template_finish/3-立案模版/党员/立案审查/6.立案审查报告请示报批/5.违纪事实材料.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/装卷/1.程序卷(目录).doc
Normal file
BIN
template_finish/3-立案模版/党员/装卷/1.程序卷(目录).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/装卷/1.程序卷(封皮).doc
Normal file
BIN
template_finish/3-立案模版/党员/装卷/1.程序卷(封皮).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/装卷/2.主体身份卷(封皮).doc
Normal file
BIN
template_finish/3-立案模版/党员/装卷/2.主体身份卷(封皮).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/党员/装卷/2.主体身份卷(目录).doc
Normal file
BIN
template_finish/3-立案模版/党员/装卷/2.主体身份卷(目录).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/移送审理/1.请示报告卡(移送审理).doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/移送审理/1.请示报告卡(移送审理).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/移送审理/2.移送审理审批表(调查).doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/移送审理/2.移送审理审批表(调查).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/移送审理/3.案件材料移送审理交接单.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/移送审理/3.案件材料移送审理交接单.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/1.立案调查请示报批/1.会议纪要(调查方案).doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/1.立案调查请示报批/1.会议纪要(调查方案).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/1.立案调查请示报批/2.立案调查方案.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/1.立案调查请示报批/2.立案调查方案.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/1.立案调查请示报批/3.请示报告卡(立案调查).doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/1.立案调查请示报批/3.请示报告卡(立案调查).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/1.立案调查请示报批/4.立案审批表.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/1.立案调查请示报批/4.立案审批表.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/2.立案决定书/立案决定书-第一联.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/2.立案决定书/立案决定书-第一联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/2.立案决定书/立案决定书-第三联.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/2.立案决定书/立案决定书-第三联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/2.立案决定书/立案决定书-第二联.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/2.立案决定书/立案决定书-第二联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/3.立案通知书/立案通知书-第一联.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/3.立案通知书/立案通知书-第一联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/3.立案通知书/立案通知书-第三联(送达单位).doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/3.立案通知书/立案通知书-第三联(送达单位).doc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/2谈话审批表.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/2谈话审批表.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/3.谈话前安全风险评估表.docx
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/3.谈话前安全风险评估表.docx
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/4.谈话方案.docx
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/4.谈话方案.docx
Normal file
Binary file not shown.
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/6.被谈话人权利义务告知书.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/6.被谈话人权利义务告知书.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/7谈话笔录.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/7谈话笔录.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/8.点对点交接单.docx
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/8.点对点交接单.docx
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/9.陪送交接单(新).doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/4.谈话请示报批/9.陪送交接单(新).doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/5.谈话通知书/谈话通知书第一联.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/5.谈话通知书/谈话通知书第一联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/5.谈话通知书/谈话通知书第三联.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/5.谈话通知书/谈话通知书第三联.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/5.谈话通知书/谈话通知书第二联.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/5.谈话通知书/谈话通知书第二联.doc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/6.立案调查报告请示报批/3.调查报告.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/6.立案调查报告请示报批/3.调查报告.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/6.立案调查报告请示报批/4.个人简历.docx
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/6.立案调查报告请示报批/4.个人简历.docx
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/6.立案调查报告请示报批/5.违法事实材料.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/立案调查/6.立案调查报告请示报批/5.违法事实材料.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/装卷(目录)/1.封皮.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/装卷(目录)/1.封皮.doc
Normal file
Binary file not shown.
BIN
template_finish/3-立案模版/非党员监察对象/装卷(目录)/2.目录.doc
Normal file
BIN
template_finish/3-立案模版/非党员监察对象/装卷(目录)/2.目录.doc
Normal file
Binary file not shown.
255
update_template_paths_to_local.py
Normal file
255
update_template_paths_to_local.py
Normal file
@ -0,0 +1,255 @@
|
||||
"""
|
||||
更新数据库中的模板路径,将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()
|
||||
Loading…
x
Reference in New Issue
Block a user