# 文档处理工具 from tools.document_tools import ( create_document, add_documents,add_table_and_replace, add_table_to_document,add_dynamic_table,add_section, process_server_images_table,add_header,add_landscape_section, merge_documents,add_table,add_defect_info_table,add_table_title, add_title,change_heading,add_auto_toc_at_end,add_jf_picture_table ) # 内容处理工具 from tools.content_tools import ( search_and_replace,add_heading ) from tools.get_pictures import ( process_picture_data,get_records_with_pic ) from tools.Get_Json import ( get_project_info,get_jizu_info, get_jizu_shigong_info,get_defect_detail, get_part_picture,get_yepian_xiangqing, check_pic_url,get_full_picture_url, get_defect_record_list ) from tools.dataproccess import ( caculate_work_days,get_year_month, merge_info,get_defect_str,get_defect_json, safe_get,get_resource_path,get_defedct_info, tree_dict_to_table_data,merge_dicts, defect_list_addtitle ) from tools.json_to_docx import json_to_docx, list_to_json_with_merges from core.tables import fill_tables from tools.defines import * import os, re, datetime async def generate_jf_report(base_info, baogao_info): #获取模板编号、模板名称 num_to_chinese = {1 : '一', 2 : '二', 3 : '三', 4 : '四', 5 : '五', 6 : '六', 7 : '七', 8 : '八', 9 : '九', 10 : '十', 11 : '十一', 12 : '十二'} cover_encode = "encode" cover_project = "project" baogao_name1 = "baogaoname1" baogao_name2 = "baogaoname2" company_name_yi = "company_name_yi" cover_date = "time" TITLE_OF_REPORT = "companyencode" jiegou_xuhao = 'num' print(f"获取到参数:基本信息:{base_info}\n\n报告信息:{baogao_info}") try: base_info = merge_info(base_info, DEFAULT_BASE_INFO) turbine_id = base_info['turbine_id'] jizu_data = get_jizu_info(turbine_id) project_data = get_project_info(jizu_data['projectId']) shigong_data = get_jizu_shigong_info(turbine_id) fengchang_name = project_data['farmName'] Yi_company = project_data['inspectionUnit'] yi_fuzeren = project_data['inspectionContact'] yi_phone = project_data['inspectionPhone'] fengchang_location = project_data['farmAddress'] Jia_company = project_data['client'] jia_fuzeren = project_data['clientContact'] jia_phone = project_data['clientPhone'] jizu_num = project_data['scale'] jizu_xinghao = project_data['turbineModel'] jizu_manufacture = project_data.get('turbineManufacturer', "") project_name = project_data['projectName'] jizu_bianhao = jizu_data["turbineName"] start_date = project_data['startDate'] end_date = project_data['endDate'] cover_url = project_data['coverUrl'] gongqi = caculate_work_days(start_date, end_date) except Exception as e: print(f"数据库的项目-机组基本信息获取失败:{e}") return try: baogao_date = datetime.datetime.now().strftime("%Y年%m月%d日 %H:%M") #现在的时间 date_year_month = get_year_month(baogao_date) #前端信息 baogao_info = merge_info(baogao_info, DEFAULT_BAOGAO_INFO) key_words= re.compile('|'.join(map(re.escape, baogao_info['key_words'].split(',')))) #关键字 shengcheng_dir = baogao_info['shengcheng_dir'] #路径 if shengcheng_dir == "": print("未配置生成路径,请检查配置") return if_waibu = baogao_info["if_waibu"] if_neibu = baogao_info["if_neibu"] if_fanglei = baogao_info["if_fanglei"] quexian_type = baogao_info['quexian_enum'] dianxing_type = baogao_info['dianxing_enum'] other_type = baogao_info["other_enum"] jiancha_renyuan = baogao_info['jiancha_renyuan'] #检查人员,目前是从命令行参数获取,需要完善 check_date = baogao_info['check_date'] if check_date == None: check_date = "未获取" baogao_bianzhi = baogao_info["userName"] baogao_shenghe = baogao_info["baogaoCheck"] Jiancha_date = baogao_info["check_date"] data_processor = baogao_info["data_processor"] coverurl = baogao_info["coverurl"] #数据库拉取信息 # Jiancha_date = shigong_data["startTime"].replace("T", " ") #检查日期 # image_count = shigong_data['imageCount'] #从施工方案获取的图片数量,待定!!! # temperature = shigong_data['temperature'] #温度 # wind_speed = shigong_data['windSpeed'] #风速 # weather = get_weather(shigong_data["weatherCode"]) #天气 不从此接口获取,待定!!! #拉取部件、图片数据 part_data, picture_data1, picture_data2, Yepians = get_part_picture(turbine_id) picture_data = merge_dicts(picture_data1, picture_data2) print(Yepians) Y1_info = get_yepian_xiangqing(Yepians[0]["partId"]) Y_Code = [yepian["partCode"] for yepian in Yepians] partType = Y1_info["partType"] partManufacturer = Y1_info["partManufacturer"] print(f"找到叶片号{Y_Code},厂商{partManufacturer}") image_source_to_find = [] baogao_label = [] renyuan_peizhi = [] gongzuo_neirong = [] shigong_fangan = [] shebei_peizhi = [] beizhu = [] jiancha = [] neirong = [] neirong2 = [] use_tool_table = [] table_index = 1 typical_picture_description = [] #获取对应枚举字段 if if_waibu: baogao_label.append("外观") image_source_to_find.append(baogao_info['waibu_enum']) use_tool_table.extend( [ [str(idx)] + item for idx, item in enumerate(USE_TOOL_ENUM.OUT.LIST, start=table_index) ] ) table_index += len(USE_TOOL_ENUM.OUT.LIST) if baogao_info["shigong_fangan"] == None: print("未传入施工方案,使用已有枚举") renyuan_peizhi.append(SHIGONG_FANGAN_ENUM.WAIBU.RENYUAN_PEIZHI) gongzuo_neirong.append(SHIGONG_FANGAN_ENUM.WAIBU.GONGZUO_NEIRONG) shebei_peizhi.append(SHIGONG_FANGAN_ENUM.WAIBU.SHEBEI_PEIZHI) shigong_fangan.append(SHIGONG_FANGAN_ENUM.WAIBU.SHIGONG_FANGAN) else: pass #待添加如果从平台传入枚举,但目前没必要,如果这种枚举标准信息库有更好的优化则可以实现 jiancha.append("无人机外观检查") neirong.append(f"、".join(Y_Code) + f"共{len(Y_Code)}支叶片的前缘、后缘、迎风面、背风面。") neirong2.append("前缘、后缘、迎风面、背风面。") typical_picture_description.extend(TEMPLATE_HEADER.JINFENG_HEADER.WAIBU.TYPICAL_LIST) if if_neibu: baogao_label.append("内部") image_source_to_find.append(baogao_info['neibu_enum']) use_tool_table.extend( [ [str(idx)] + item for idx, item in enumerate(USE_TOOL_ENUM.IN.LIST, start=table_index) ] ) table_index += len(USE_TOOL_ENUM.IN.LIST) if baogao_info["shigong_fangan"] == None: renyuan_peizhi.append(SHIGONG_FANGAN_ENUM.NEIBU.RENYUAN_PEIZHI) gongzuo_neirong.append(SHIGONG_FANGAN_ENUM.NEIBU.GONGZUO_NEIRONG) shebei_peizhi.append(SHIGONG_FANGAN_ENUM.NEIBU.SHEBEI_PEIZHI) shigong_fangan.append(SHIGONG_FANGAN_ENUM.NEIBU.SHIGONG_FANGAN) else: pass jiancha.append("叶片内部检查") neirong.append(f"、".join(Y_Code) + f"共{len(Y_Code)}支叶片的内部导雷卡、腹板、透光、人孔盖版、叶根盖板...") neirong2.append("内部导雷卡、腹板、透光、人孔盖版、叶根盖板...") typical_picture_description.extend(TEMPLATE_HEADER.JINFENG_HEADER.NEIBU.TYPICAL_LIST) if if_fanglei: baogao_label.append("防雷") image_source_to_find.append(baogao_info['fanglei_enum']) use_tool_table.extend( [ [str(idx)] + item for idx, item in enumerate(USE_TOOL_ENUM.LIGHT.LIST, start=table_index) ] ) table_index += len(USE_TOOL_ENUM.LIGHT.LIST) if baogao_info["shigong_fangan"] == None: renyuan_peizhi.append(SHIGONG_FANGAN_ENUM.FANGLEI.YEPIAN.RENYUAN_PEIZHI) gongzuo_neirong.append(SHIGONG_FANGAN_ENUM.FANGLEI.YEPIAN.GONGZUO_NEIRONG) shebei_peizhi.append(SHIGONG_FANGAN_ENUM.FANGLEI.YEPIAN.SHEBEI_PEIZHI) shigong_fangan.append(SHIGONG_FANGAN_ENUM.FANGLEI.YEPIAN.SHIGONG_FANGAN) else: pass jiancha.append("叶片导通测试") neirong.append(f"轮毂至塔基导通、内部导线线阻、外部导线线阻...") neirong2.append("轮毂至塔基导通、内部导线线阻、外部导线线阻...") typical_picture_description.extend(TEMPLATE_HEADER.JINFENG_HEADER.FANGLEI.TYPICAL_LIST) #获取缺陷图列表和典型图列表 filtered_picture_data, total_picture_num = process_picture_data(picture_data, image_source_to_find) #获取所有缺陷记录 defect_records = get_defect_record_list() #获取缺陷记录中对应图片的记录 defect_records_with_pic, error_pic_with_no_record = get_records_with_pic(defect_records, filtered_picture_data, quexian_type) if len(error_pic_with_no_record) > 0: print(f"!!!有部分缺陷图片没有对应的缺陷记录,将不会生成这些图片的缺陷表:{error_pic_with_no_record} ") print(f"对应缺陷图的缺陷记录列表:{defect_records_with_pic}") except Exception as e: print(f"报告基本信息获取失败:{e}") return #检查参数合法性 if not if_fanglei or not if_neibu or not if_waibu: print("请至少选择一种检查项目") return if not os.path.exists(shengcheng_dir): print(f"生成路径{shengcheng_dir}不存在") return baogao_name = "叶片" + "、".join(baogao_label) + "检查报告" output_dir = os.path.normpath(f"{shengcheng_dir}/{project_name}项目{baogao_name}{jizu_bianhao}{baogao_date.split(' ')[0]}版.docx") version = 1 while os.path.exists(output_dir): if version != 1: output_dir = output_dir.replace(f"版{version - 1}",f"版{version}") else: output_dir = output_dir.replace("版",f"版{version}") version += 1 add_list = [ get_resource_path(MUBAN_DIR + '/jf_fengmian.png'), get_resource_path(MUBAN_DIR + '/jf_fengmian1.png'), get_resource_path(MUBAN_DIR + '/jinfeng_fengmian_name.docx'), get_resource_path(MUBAN_DIR + '/jf_fengmian2.png'), get_resource_path(MUBAN_DIR + '/jinfeng_fengmian_renyuan.docx'), get_resource_path(MUBAN_DIR + '/jf_fengmian2.png'), get_resource_path(MUBAN_DIR + '/jinfeng_fengmian_riqi.docx'), get_resource_path(MUBAN_DIR + '/jf_fengmian1.png'), get_resource_path(MUBAN_DIR + '/jinfeng_fengmian_luokuan.docx'), get_resource_path(MUBAN_DIR + '/jf_fengmian3.png'), ] print(await create_document(output_dir, section_args={ "page_height" : JF_HEIGHT, "page_width" : JF_WIDTH, "left_margin" : JF_L_MARGIN, "right_margin" : JF_R_MARGIN, "top_margin" : JF_T_MARGIN, "bottom_margin" : JF_B_MARGIN, })) #标题样式 change_heading(output_dir, "Heading 1") change_heading(output_dir, "Heading 2", HEADING_2_CONFIG) change_heading(output_dir, "Heading 3", HEADING_3_CONFIG) #加封面 merge_documents(output_dir, add_list) #页眉 add_header(output_dir, TEMPLATE_HEADER.JINFENG_HEADER.ENUM) #项目机组信息表格 print(add_documents(output_dir, get_resource_path(MUBAN_DIR + '/jf_table_title.docx'))) total_table_num = 0 print(add_table(output_dir, get_resource_path(MUBAN_DIR + '/jinfeng_table.docx'), REPORT_ENUM=TEMPLATE_HEADER.JINFENG_HEADER.ENUM)) total_picture_num += 1 list_to_replace = { 'jia_company_name' : Jia_company, 'fengchang_name' : fengchang_name, 'jizu_hao' : jizu_bianhao, 'bianzhi_renyuan': baogao_bianzhi, 'bianzhi_riqi': baogao_date, 'fengchang_name' : fengchang_name, 'jizu_hao' : jizu_bianhao, 'fengchang_location' : fengchang_location, 'kehu_company' : Yi_company, 'xiangmuguige' : jizu_num, 'kehu_fuzeren' : yi_fuzeren, 'yezhu_phone' : yi_phone, 'shigong_company' : JINFENG_COMPANY, 'shigong_date' : "未填写",#shigong_date, 'shigong_fuzeren' : "未填写", 'shigong_phone' : "未填写", 'zhengji_changjia' : jizu_manufacture, 'yepian_changjia' : partManufacturer, 'jizu_type' : jizu_xinghao, 'yepian_type' : partType, 'jiancha_fangshi' : '、'.join(jiancha), 'jiancha_renyuan' : jiancha_renyuan } for find_text, replace_text in list_to_replace.items(): print(search_and_replace(output_dir, find_text, replace_text)) print(f"静态内容生成完毕,开始生成动态内容") #缺陷信息表格1 defect_info, defect_part_type_list = get_defedct_info(defect_records_with_pic) total_picture_num = add_defect_info_table(output_dir, defect_info, get_resource_path(MUBAN_DIR + '/quexian_liebiao.docx'), total_table_num,TEMPLATE_HEADER.JINFENG_HEADER.ENUM) #缺陷信息表格2 table_list = tree_dict_to_table_data(defect_part_type_list) # 服务器获取的树形结构转化为表格数据 table_list = defect_list_addtitle(table_list, jizu_bianhao) # 增加每列标题,机组 add_table_title(output_dir, DEFECT_TABLE_TITLE) # 增加表格标题 total_table_num += 1 table_json = list_to_json_with_merges(table_list, style_config=STYLE_CONFIG, merge_columns=2) #将list转换为json形式,前两列检查相同合并 json_to_docx(table_json, output_dir).save(output_dir) #jsontodocx total_table_num += 1 #使用器具记录表 add_table_title(output_dir, USE_TOOL_TABLE_TITLE) total_table_num += 1 json_to_docx(list_to_json_with_merges(use_tool_table, style_config=STYLE_CONFIG, detect_merges=False),output_dir).save(output_dir) total_table_num += 1 #添加目录节 add_section(output_dir).save(output_dir) #添加目录 #add_auto_toc_at_end(output_dir) #添加横向节(展示图片) add_landscape_section(output_dir).save(output_dir) print(add_heading(output_dir, f"1. 机组号:{jizu_bianhao}", 1)) print(add_heading(output_dir, f"1.1 叶片编号:{Y_Code[0]}", 2)) #add_header(output_dir, TEMPLATE_HEADER.JINFENG_HEADER.ENUM, if_section=False, text = " " + TEMPLATE_HEADER.JINFENG_HEADER.PARA) """ typical_picture_list: #每列有两种情况 [ [str(图片描述), int(n), ...], [str(图片地址), str(缺陷类型), ...] ] defect_picture_list: #只有一种情况 [ [str(图片描述), str(图片描述), ...], [str(图片地址), str(图片地址), ...] ] """ typical_picture_list = [] defect_picture_list = [] typical_picture_list = [ [ "外观检查(迎、背风面是否有漆面脱落、裂纹等)1", "外观检查(前、后缘;如前缘漆面脱落、合模缝开裂等)2", "外观检查(迎、背风面是否有漆面脱落、裂纹等)3", "外观检查(前、后缘;如前缘漆面脱落、合模缝开裂等)4", "外观检查(迎、背风面是否有漆面脱落、裂纹等)5", "外观检查(前、后缘;如前缘漆面脱落、合模缝开裂等)6", "外观检查(迎、背风面是否有漆面脱落、裂纹等)7", "外观检查(前、后缘;如前缘漆面脱落、合模缝开裂等)8", "外观检查(迎、背风面是否有漆面脱落、裂纹等)9", "外观检查(前、后缘;如前缘漆面脱落、合模缝开裂等)10", ], [ "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", 2, "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", 2, "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", 2, 2, ], [ "", "图层脱落", "", "", "图层脱落", "", "", "", "图层脱落", "图层脱落", ] ] defect_picture_list = [ [ "1", "2", "3456", "456", "56", "6", "12", "123", ], [ "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", "/home/dtyx/桌面/yhh/Report_Generate_Server/muban/wechat_2025-07-29_123404_038.png", ] ] total_table_num = add_jf_picture_table( typical_picture_list, defect_picture_list, get_resource_path(MUBAN_DIR + '/typical_picture_table.docx'), get_resource_path(MUBAN_DIR + '/defect_picture_table.docx'), output_dir, total_table_num )