run_main.py 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. import settings
  2. from .detail_func import *
  3. import json
  4. from .base import *
  5. from .match_and_cutout_mode_control.base_deal_image_v2 import BaseDealImage
  6. # from module.view_control.MineQWidget import DialogShow, WorkerOneThread
  7. import threading
  8. from concurrent.futures import ThreadPoolExecutor
  9. import concurrent.futures
  10. from .data import DataModeGenerateDetail
  11. import time
  12. from PIL import Image
  13. from io import BytesIO
  14. import os, re
  15. from functools import partial
  16. # from multiprocessing import Process, Queue
  17. import pickle
  18. from .base_deal import BaseDealImage
  19. class RunMain():
  20. # run_end_sign = Signal(dict)
  21. # show_dialog_sign = Signal(dict)
  22. # show_progress_detail_sign = Signal(str)
  23. # # 定义一个信号用于请求显示对话框
  24. # show_dialog_signal = Signal()
  25. # # 定义一个信号用于返回对话框的结果
  26. # dialog_result_signal = Signal(str)
  27. # dialog_result_signal = Signal(str)
  28. def __init__(self):
  29. super().__init__()
  30. # self.windows = windows
  31. self.dialog_result = ""
  32. self.data_mode_generate_detail = DataModeGenerateDetail()
  33. # self.dialog_result_signal.connect(self.on_dialog_result)
  34. self.event = threading.Event()
  35. def set_state(self, state_value: int):
  36. # 0禁用 1进行中 2已结束
  37. if state_value not in [0, 1, 2, 99]:
  38. return
  39. # self.windows.change_state_sign.emit(state_value)
  40. # self.windows.set_state(state_value)
  41. # 抠图前先做数据规整处理;类似详情图生成逻辑
  42. def check_before_cutout(self, config_data):
  43. return_data = {
  44. "code": 99,
  45. "message": "",
  46. "data": {
  47. "all_goods_art_no_folder_data": [],
  48. "config_data": config_data,
  49. },
  50. }
  51. image_dir = config_data["image_dir"]
  52. image_order = config_data["image_order"]
  53. is_check_number = config_data["is_check_number"]
  54. is_filter = config_data["cutout_is_pass"]
  55. resize_image_view = config_data["resize_image_view"]
  56. logo_path = config_data["logo_path"]
  57. cutout_mode = config_data["cutout_mode"] # 是否精细化抠图,默认为普通抠图
  58. special_goods_art_no_folder_line = config_data["special_goods_art_no_folder_line"]
  59. # 自动处理红蜻蜓货号,进行重命名
  60. # if settings.PROJECT == "红蜻蜓":
  61. # # 规整红蜻蜓货号图
  62. # all_goods_art_no_folder_data = get_all_goods_art_no_folder(path=image_dir)
  63. # BaseDealImage().rename_folder_for_hqt(all_goods_art_no_folder_data=all_goods_art_no_folder_data)
  64. # 重新获取文件夹信息
  65. all_goods_art_no_folder_data = get_all_goods_art_no_folder(path=image_dir)
  66. f = True
  67. is_do_other = False
  68. if is_do_other:
  69. for i in all_goods_art_no_folder_data:
  70. i["label"] = "不处理"
  71. is_filter = False
  72. specified_goods_art_no_folder = special_goods_art_no_folder_line
  73. specified_goods_art_no_folder = specified_goods_art_no_folder.strip()
  74. specified_goods_art_no_folder = specified_goods_art_no_folder.replace(",", ",")
  75. specified_goods_art_no_folder_list = specified_goods_art_no_folder.split(",")
  76. specified_goods_art_no_folder_list = [x for x in specified_goods_art_no_folder_list if x]
  77. if not specified_goods_art_no_folder_list:
  78. return_data["message"] += '请手动输入文件夹名称(多选),或关闭指定文件夹模式\n'
  79. else:
  80. for i in all_goods_art_no_folder_data:
  81. if i["folder_path"] in specified_goods_art_no_folder_list:
  82. i["label"] = "待处理"
  83. # 哪些数据不合规
  84. all_folder_name_list = [x["folder_name"] for x in all_goods_art_no_folder_data]
  85. for goods_art_no_folder_name in specified_goods_art_no_folder_list:
  86. if goods_art_no_folder_name not in all_folder_name_list:
  87. return_data["message"] += '文件夹:{},在您选的目录下不存在\n'.format(goods_art_no_folder_name)
  88. f = False
  89. if not f:
  90. self.set_state(state_value=2)
  91. return
  92. # 清空指定文件夹的已抠图文件
  93. if is_do_other:
  94. for folder_data in all_goods_art_no_folder_data:
  95. goods_art_no_folder_path = "{}/原始图_已抠图".format(folder_data["folder_path"])
  96. if os.path.exists(goods_art_no_folder_path):
  97. remove_all_file(goods_art_no_folder_path)
  98. return_data["data"]["succeed_folder_list"] = 1
  99. # ==================检查填写的图片视角是否符合要求
  100. res = BaseDealImage().getImageOrder(image_order=image_order, resize_image_view=resize_image_view)
  101. if res['code'] != 0:
  102. return_data["message"] += "{}\n".format(res['msg'])
  103. return return_data
  104. else:
  105. # 图片命名顺序
  106. image_order_list = res['imageOrderList']
  107. for goods_art_no_folder_data in all_goods_art_no_folder_data:
  108. if goods_art_no_folder_data["label"] != "待处理":
  109. continue
  110. goods_art_no_folder_data["image_order_list"] = image_order_list
  111. # ================是否过滤已有生成的文件夹
  112. if is_filter:
  113. for goods_art_no_folder_data in all_goods_art_no_folder_data:
  114. if goods_art_no_folder_data["label"] != "待处理":
  115. continue
  116. folder_path = goods_art_no_folder_data["folder_path"]
  117. _p = "{}/800x800".format(folder_path)
  118. if os.path.exists(_p):
  119. if len(os.listdir(_p)):
  120. goods_art_no_folder_data["label"] = "不处理"
  121. # ================检查每个货号文件夹图片数量是否符合要求
  122. all_goods_art_no_folder_data, message = BaseDealImage().check_folders_image_amount(all_goods_art_no_folder_data,
  123. image_order_list)
  124. if message:
  125. return_data["message"] += "{}\n".format(message)
  126. return_data["code"] = 0
  127. return_data["data"]["all_goods_art_no_folder_data"] = all_goods_art_no_folder_data
  128. return_data["data"]["image_dir"] = image_dir
  129. return_data["data"]["resize_image_view"] = resize_image_view
  130. return_data["data"]["cutout_mode"] = cutout_mode
  131. return_data["data"]["image_order_list"] = image_order_list
  132. return_data["data"]["logo_path"] = logo_path
  133. return return_data
  134. # 抠图校验后的回调函数处理
  135. def check_for_cutout_image_first_call_back(self, return_data):
  136. # return_data = {
  137. # "code": 99,
  138. # "message": "",
  139. # "data": {
  140. # "all_goods_art_no_folder_data": [],
  141. # },
  142. # }
  143. code = return_data["code"]
  144. config_data = return_data["data"]["config_data"]
  145. config_data["sign_text"] = ""
  146. # if code != 0:
  147. # # self.windows.show_message(return_data["message"])
  148. # # self.show_progress_detail(return_data["message"])
  149. # _dialog_dict = {"text": return_data["message"],
  150. # "windows": self,
  151. # }
  152. # self.show_dialog_sign.emit(_dialog_dict)
  153. # self.event.wait()
  154. # return
  155. do_next = False
  156. text = ""
  157. all_goods_art_no_folder_data = return_data["data"]["all_goods_art_no_folder_data"]
  158. button_1, button_2, button_3 = None, None, None
  159. text += return_data["message"]
  160. # 存在错误文件夹
  161. error_folder = [x for x in all_goods_art_no_folder_data if x["label"] == "错误"]
  162. todo_folder = [x for x in all_goods_art_no_folder_data if x["label"] == "待处理"]
  163. if error_folder:
  164. button_2 = "移除错误文件"
  165. if error_folder and todo_folder:
  166. button_1 = "移除并继续"
  167. button_3 = "继续(忽略其他)"
  168. if not error_folder and todo_folder:
  169. button_1 = "继续"
  170. # do_next = True
  171. text += "\n==================\n错误数据:{}个,校验无误数据:{}个".format(len(error_folder), len(todo_folder))
  172. self.show_progress_detail(text)
  173. if button_1 is None and button_2 is None and button_3 is None:
  174. pass
  175. elif button_1 == "继续" and button_2 is None and button_3 is None:
  176. do_next = True
  177. else:
  178. # print("runmain 179----------------")
  179. # # print(self)
  180. # # print(self.windows)
  181. # _dialog_dict = {"text": text,
  182. # "button_1": button_1,
  183. # "button_2": button_2,
  184. # "button_3": button_3,
  185. # "windows": self,
  186. # }
  187. # self.show_dialog_sign.emit(_dialog_dict)
  188. # # self.exec_()
  189. # # 等待事件被设置
  190. # self.event.wait()
  191. # print("self.dialog_result", self.dialog_result)
  192. # #
  193. # # my_dialog = DialogShow(self.windows, text=text, button_1=button_1, button_2=button_2,
  194. # # button_3=button_3)
  195. # # ret = my_dialog.exec()
  196. # print("460 ===============my_dialog.flag_name===============")
  197. # print(my_dialog.flag_name)
  198. if "移除" in self.dialog_result:
  199. for error_folder_data in [x for x in all_goods_art_no_folder_data if x["label"] == "错误"]:
  200. self.move_error_folders(
  201. one_path=error_folder_data["folder_path"],
  202. target_folder="{}/软件-处理失败".format(config_data["image_dir"]),
  203. )
  204. if "继续" in self.dialog_result:
  205. do_next = True
  206. if do_next:
  207. all_goods_art_no_folder_data = [x for x in all_goods_art_no_folder_data if x["label"] == "待处理"]
  208. print("===============all_goods_art_no_folder_data===============")
  209. print(all_goods_art_no_folder_data)
  210. new_func = partial(self.do_run_cutout_image,
  211. all_goods_art_no_folder_data=all_goods_art_no_folder_data,
  212. callback_func=self.show_progress_detail,
  213. image_order_list=return_data["data"]["image_order_list"],
  214. cutout_mode=return_data["data"]["cutout_mode"],
  215. resize_image_view=return_data["data"]["resize_image_view"],
  216. windows=self.windows,
  217. logo_path=return_data["data"]["logo_path"],
  218. config_data=config_data)
  219. self._w_3 = WorkerOneThread(func=new_func, name="_w_3")
  220. self._w_3.start()
  221. # self.t = threading.Thread(target=self.do_run_cutout_image,
  222. # kwargs={"all_goods_art_no_folder_data": all_goods_art_no_folder_data,
  223. # "callback_func": self.show_progress_detail,
  224. # "image_order_list": return_data["data"]["image_order_list"],
  225. # "cutout_mode": return_data["data"]["cutout_mode"],
  226. # "resize_image_view": return_data["data"]["resize_image_view"],
  227. # "windows": self.windows,
  228. # "logo_path": return_data["data"]["logo_path"],
  229. # "config_data": config_data,
  230. # })
  231. # self.t.start()
  232. else:
  233. config_data["sign_text"] = "已结束抠图处理"
  234. self.run_end_sign.emit(config_data)
  235. def do_run_cutout_image(self,
  236. all_goods_art_no_folder_data,
  237. callback_func,
  238. image_order_list,
  239. cutout_mode,
  240. resize_image_view,
  241. windows,
  242. logo_path,
  243. config_data):
  244. BaseDealImage().run_main(all_goods_art_no_folder_data=all_goods_art_no_folder_data,
  245. callback_func=callback_func,
  246. image_order_list=image_order_list,
  247. cutout_mode=cutout_mode,
  248. resize_image_view=resize_image_view,
  249. windows=windows,
  250. logo_path=logo_path,
  251. )
  252. # ==============完成处理==============
  253. # self.set_state(state_value=2)
  254. callback_func("已结束抠图处理")
  255. config_data["sign_text"] = "已结束抠图处理"
  256. self.run_end_sign.emit(config_data)
  257. def do_run_cutout_image1111(self, all_goods_art_no_folder_data,
  258. callback_func,
  259. image_order_list,
  260. cutout_mode,
  261. resize_image_view,
  262. windows,
  263. logo_path,
  264. config_data):
  265. max_workers = 1
  266. with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
  267. futures = []
  268. futures.append(executor.submit(
  269. BaseDealImage().run_main,
  270. all_goods_art_no_folder_data=all_goods_art_no_folder_data,
  271. callback_func=callback_func,
  272. image_order_list=image_order_list,
  273. cutout_mode=cutout_mode,
  274. resize_image_view=resize_image_view,
  275. windows=windows,
  276. logo_path=logo_path,
  277. ))
  278. # 使用 wait 方法等待所有任务完成
  279. done, not_done = concurrent.futures.wait(futures, timeout=60)
  280. # 处理完成的任务
  281. for future in done:
  282. if settings.IS_TEST:
  283. result = future.result()
  284. else:
  285. try:
  286. result = future.result()
  287. except BaseException as e:
  288. print("2039 图片处理失败.{}".format(e))
  289. callback_func("2039 处理失败.{}".format(e))
  290. # ==============完成处理==============
  291. # self.set_state(state_value=2)
  292. callback_func("已结束抠图处理")
  293. config_data["sign_text"] = "已结束抠图处理"
  294. self.run_end_sign.emit(config_data)
  295. def check_before_detail(self, config_data):
  296. # =============
  297. # 整体数据校验,返回错误内容,以及
  298. # temp_name:模板名称
  299. """
  300. 步骤:
  301. 1、 整体文件夹检查,并输出数据结构
  302. 2、数据进行对应规整(可能有excel,红蜻蜓等)
  303. 3、执行单个款数据处理
  304. """
  305. return_data = {
  306. "code": 99,
  307. "message": "",
  308. "data": {
  309. "error_folder_list": [],
  310. "goods_no_dict": {},
  311. "succeed_folder_list": [],
  312. "temp_name": config_data["temp_name"],
  313. "temp_name_list": config_data["temp_name_list"],
  314. "assigned_page_dict": config_data["assigned_page_dict"],
  315. "excel_temp_goods_no_data": {}, # 表格数据可能存在多模板,数据结构为一个款号下的多个模板的数据列表
  316. "finally_goods_no_need_temps": {}, # 每个款号需要生成的模板数据
  317. "config_data": config_data,
  318. },
  319. }
  320. temp_name = config_data["temp_name"]
  321. temp_name_list = config_data["temp_name_list"]
  322. assigned_page_dict = config_data["assigned_page_dict"]
  323. image_dir = config_data["image_dir"]
  324. is_use_excel = config_data["is_use_excel"]
  325. excel_path = config_data["excel_path"]
  326. temp_class = config_data["temp_class"]
  327. is_check_color_is_all = config_data["is_check_color_is_all"]
  328. detail_is_pass = config_data["detail_is_pass"]
  329. error_folder_list = []
  330. # 遍历货号获取所有货号--可能为编号
  331. folder_name_list = detail_func.get_all_dir_info(image_dir=image_dir)
  332. if not folder_name_list:
  333. return_data["message"] += "不存在任何货号/编号文件夹\n"
  334. print("不存在任何货号/编号文件夹")
  335. return return_data
  336. # =========================组装数据---数据来源多种途径=========================
  337. _result = {"code": 99, "message": "无法解析到数据,请检查登录企业"}
  338. if not is_use_excel:
  339. if settings.PROJECT == "红蜻蜓":
  340. # goods_no_dict输出为文件夹下涉及到的所有款为key的字典,后续通过解析字典,进行提取对应文件夹
  341. _result = self.data_mode_generate_detail.get_basic_goods_art_data_by_hqt_and_hlm(
  342. folder_name_list
  343. )
  344. elif settings.PROJECT == "惠利玛":
  345. if settings.Company:
  346. if "惠利玛" in settings.Company:
  347. _result = self.data_mode_generate_detail.get_basic_goods_art_data_by_hqt_and_hlm(
  348. folder_name_list
  349. )
  350. else:
  351. keys = settings.keys
  352. _result = (
  353. self.data_mode_generate_detail.get_basic_goods_art_data_form_excel(
  354. folder_name_list,
  355. excel_path,
  356. keys,
  357. )
  358. )
  359. if _result["code"] == 0:
  360. remote_data = _result["data"]
  361. else:
  362. return_data["message"] += _result["message"] + "\n"
  363. return return_data
  364. # print(json.dumps(remote_data))
  365. # =========================拼接数据组合为款数据=========================
  366. """
  367. 1、获取所有文件夹基础数据内容
  368. 2、结合上述返回结果进行数据组合拼接
  369. 3、输出结果为按款为主键信息
  370. 4、注意模板ID
  371. """
  372. # 获取所有文件夹基础数据内容 检查不满足要求的文件不满足要求移动到错误文件夹
  373. need_view_list = temp_class[temp_name].need_view
  374. _all_dir_info_data = detail_func.get_all_dir_info_and_pic_info(
  375. image_dir, folder_name_list, need_view_list
  376. )
  377. all_dir_info_data = {}
  378. for one_folder, value in _all_dir_info_data.items():
  379. if "message" in value:
  380. if value["message"]:
  381. error_folder_list.append(
  382. {
  383. "folder_name": one_folder,
  384. "folder_path": "{}/{}".format(image_dir, one_folder),
  385. }
  386. )
  387. return_data["message"] += "文件夹:{} 结构错误:{}\n".format(
  388. one_folder, value["message"]
  389. )
  390. continue
  391. # 符合要求的数据处理
  392. all_dir_info_data[one_folder] = value
  393. # 结合上述返回结果进行数据组合拼接
  394. # 返回可能存在的情况:1、存在文件夹不匹配数据,2、存在货号数据缺失
  395. goods_no_dict, error_folder_name_list = detail_func.merge_local_and_remote_data(
  396. all_dir_info_data=all_dir_info_data, remote_data=remote_data
  397. )
  398. # 文件在系统中没有匹配的结果
  399. if error_folder_name_list:
  400. for one_folder in error_folder_name_list:
  401. error_folder_list.append(
  402. {
  403. "folder_name": one_folder,
  404. "folder_path": "{}/{}".format(image_dir, one_folder),
  405. }
  406. )
  407. return_data["message"] += "文件夹:{} 找不到对应数据\n".format(
  408. one_folder
  409. )
  410. print("===============goods_no_dict==================")
  411. if settings.IS_TEST:
  412. _text = json.dumps(goods_no_dict)
  413. print(goods_no_dict)
  414. create_folder("qt_test")
  415. with open("qt_test/goods_no_dict.txt", 'w', encoding='utf-8') as file:
  416. file.write(_text)
  417. print("===============goods_no_dict==================")
  418. # ===================================是否齐色检查=============================================
  419. # 如为红蜻蜓企业则还需要检查同款下是否齐全;数据返回结果为款号列表
  420. error_data_dict = {}
  421. if is_check_color_is_all:
  422. if not is_use_excel:
  423. if settings.PROJECT == "红蜻蜓":
  424. error_data_dict = (
  425. self.data_mode_generate_detail.check_goods_is_not_deficiency(
  426. goods_no_dict
  427. )
  428. )
  429. else:
  430. error_data_dict = self.data_mode_generate_detail.check_goods_is_not_deficiency_form_excel(
  431. goods_no_dict, excel_path
  432. )
  433. if error_data_dict:
  434. print("----error_data_dict----")
  435. print(json.dumps(error_data_dict))
  436. # 款号反向映射;因为部分key键格式为KUM9999999
  437. _x = {}
  438. for i, v in goods_no_dict.items():
  439. _x[v["款号"]] = i
  440. for goods_no, value in error_data_dict.items():
  441. if goods_no in _x:
  442. goods_no = _x[goods_no]
  443. if goods_no in goods_no_dict:
  444. # =====移动到错误文件夹======
  445. for _folder_name in [
  446. x["文件夹名称"] for x in goods_no_dict[goods_no]["货号资料"]
  447. ]:
  448. error_folder_list.append(
  449. {
  450. "folder_name": _folder_name,
  451. "folder_path": "{}\{}".format(
  452. image_dir, _folder_name
  453. ),
  454. }
  455. )
  456. return_data["message"] += "文件夹:{};{}\n".format(
  457. _folder_name, value["message"]
  458. )
  459. # 从 正确 款下面进行数据剔除
  460. goods_no_dict.pop(goods_no)
  461. print("-----------------1goods_no_dict---------------")
  462. print(json.dumps(goods_no_dict, ensure_ascii=False))
  463. print("-----------------1goods_no_dict---------------")
  464. # 如果没有有效数据则进行退出
  465. if not goods_no_dict:
  466. return_data["message"] += "没有任何有效数据\n"
  467. return return_data
  468. # 校验无误的文件夹数据 goods_no_dict为最终有效数据
  469. for goods_no, value in goods_no_dict.items():
  470. return_data["data"]["succeed_folder_list"].extend(
  471. [x["文件夹名称"] for x in goods_no_dict[goods_no]["货号资料"]]
  472. )
  473. # 如果是表格数据,则获取表格数据中需要生成的货号
  474. # 数据结构
  475. # {“款号1”:
  476. # {“模板名称1”:data_dict1,
  477. # “模板名称2”:data_dict2,
  478. # }}
  479. if is_use_excel:
  480. excel_temp_goods_no_data = self.data_mode_generate_detail.get_basic_template_information(
  481. _goods_no_dict=goods_no_dict, excel_path=excel_path)
  482. else:
  483. excel_temp_goods_no_data = {}
  484. print("731===================excel_temp_goods_no_data,is_use_excel:{}".format(is_use_excel))
  485. print(json.dumps(excel_temp_goods_no_data))
  486. # ===========数据组装,统计每个款需要生成哪些模板==============
  487. # 不适用表格指定模板
  488. goods_no_need_temps = {}
  489. # isUseTemplate 为false 表示使用excel表格数据
  490. if not is_use_excel:
  491. for i in goods_no_dict:
  492. goods_no_need_temps[i] = [temp_name]
  493. else:
  494. for i in goods_no_dict:
  495. # i 为款号
  496. if i in excel_temp_goods_no_data:
  497. # 获取 某个款号的所有允许生成的模板列表
  498. goods_no_need_temps[i] = list(excel_temp_goods_no_data[i].keys())
  499. # ========开始执行详情图生成===================
  500. # _goods_no_dict = goods_no_dict
  501. _goods_no_dict = {}
  502. # assigned_page_dict 如存在对应模板的,则不管是否有过滤都需要生成
  503. # 检查是否已存在模板,已存在的需要进行跳过;可能部分模板已存在,部分不存在。
  504. finally_goods_no_need_temps = {}
  505. for goods_no, value in goods_no_dict.items():
  506. if goods_no not in goods_no_need_temps:
  507. continue
  508. for __temp_name in goods_no_need_temps[goods_no]:
  509. _path = "{}/{}/{}/{}".format(image_dir, "软件-详情图生成", __temp_name, goods_no)
  510. if not os.path.exists(_path):
  511. print("款号详情图不存在", _path)
  512. if goods_no not in finally_goods_no_need_temps:
  513. finally_goods_no_need_temps[goods_no] = []
  514. _goods_no_dict[goods_no] = value # 需要生成的数据
  515. finally_goods_no_need_temps[goods_no].append(__temp_name)
  516. else:
  517. print("款号详情图存在", _path)
  518. # 如果在指定模板中存在,则也需要生成
  519. if __temp_name in assigned_page_dict:
  520. print("指定模板需要更新", _path)
  521. if goods_no not in finally_goods_no_need_temps:
  522. finally_goods_no_need_temps[goods_no] = []
  523. _goods_no_dict[goods_no] = value # 需要生成的数据
  524. finally_goods_no_need_temps[goods_no].append(__temp_name)
  525. else:
  526. if detail_is_pass:
  527. return_data["message"] += "\n款号:{},模板:{} 已存在".format(goods_no, __temp_name)
  528. else:
  529. if goods_no not in finally_goods_no_need_temps:
  530. finally_goods_no_need_temps[goods_no] = []
  531. _goods_no_dict[goods_no] = value # 需要生成的数据
  532. finally_goods_no_need_temps[goods_no].append(__temp_name)
  533. pass
  534. # _path = "{}/{}".format(self.image_dir, "软件-详情图生成")
  535. # if os.path.exists(_path):
  536. # _goods_no_dict = {}
  537. # # 数据返回为 已有的款数据,为款号列表
  538. # is_pass_goods_no = detail_func.get_all_detail_info(_path)
  539. # for goods_no, value in goods_no_dict.items():
  540. # if "软件" in goods_no:
  541. # continue
  542. #
  543. # if value["模板名称"] in assigned_page_dict:
  544. # need_todo = True
  545. # else:
  546. # if goods_no in is_pass_goods_no:
  547. # need_todo = False
  548. # else:
  549. # need_todo = True
  550. # if need_todo:
  551. # _goods_no_dict[goods_no] = value
  552. print("-----------------2goods_no_dict---------------")
  553. print(json.dumps(_goods_no_dict, ensure_ascii=False))
  554. print("-----------------2goods_no_dict---------------")
  555. return_data["data"]["error_folder_list"] = error_folder_list
  556. if len(_goods_no_dict) == 0:
  557. return_data["message"] += "\n没有任何文件夹需要执行"
  558. return_data["data"]["goods_no_dict"] = _goods_no_dict
  559. return_data["data"]["excel_temp_goods_no_data"] = excel_temp_goods_no_data
  560. return_data["data"]["finally_goods_no_need_temps"] = finally_goods_no_need_temps
  561. return_data["code"] = 0
  562. return return_data
  563. def move_error_folders(self, one_path, target_folder, message=""):
  564. if os.path.exists(one_path):
  565. check_path(target_folder)
  566. move_folders(path_list=[one_path], target_folder=target_folder)
  567. def check_for_detail_first_call_back(self, data):
  568. # 首次数据校验的信息返回
  569. # self.show_message(text="22222222222222222222222")
  570. # QMessageBox.critical(self, "警告", "1111111", QMessageBox.Ok)
  571. code = data["code"]
  572. config_data = data["data"]["config_data"]
  573. target_error_folder = config_data["target_error_folder"]
  574. print("635 check_for_detail_first_call_back")
  575. print(data)
  576. if code != 0:
  577. # self.windows.show_message(data["message"])
  578. # my_dialog = DialogShow(self.windows.windows, text=data["message"])
  579. # ret = my_dialog.exec()
  580. self.show_progress_detail(text=data["message"])
  581. _dialog_dict = {"text": data["message"],
  582. "windows": self,
  583. }
  584. self.show_dialog_sign.emit(_dialog_dict)
  585. self.event.wait()
  586. # self.windows.set_state(2)
  587. config_data["sign_text"] = "已结束详情处理"
  588. self.run_end_sign.emit(config_data)
  589. return
  590. do_next = False
  591. if data["message"]:
  592. button_1, button_2, button_3 = None, None, None
  593. text = data["message"]
  594. if code == 0:
  595. if data["data"]:
  596. if data["data"]["error_folder_list"]:
  597. print("22----------error_folder_list------------")
  598. print(json.dumps(data["data"]["error_folder_list"]))
  599. button_2 = "移除错误文件"
  600. if data["data"]["goods_no_dict"]:
  601. if button_2:
  602. button_1 = "移除并继续"
  603. button_3 = "继续(忽略其他)"
  604. else:
  605. button_1 = "继续"
  606. if data["data"]["succeed_folder_list"]:
  607. text += "\n==================\n校验无误数据:{}个文件夹".format(
  608. len(data["data"]["succeed_folder_list"])
  609. )
  610. self.show_progress_detail(text=data["message"])
  611. if button_1 is None and button_2 is None and button_3 is None:
  612. pass
  613. elif button_1 == "继续" and button_2 is None and button_3 is None:
  614. do_next = True
  615. else:
  616. print("runmain 642----------------")
  617. # todo 弹框修改处理等
  618. _dialog_dict = {"text": text,
  619. "button_1": button_1,
  620. "button_2": button_2,
  621. "button_3": button_3,
  622. "windows": self,
  623. }
  624. self.show_dialog_sign.emit(_dialog_dict)
  625. # 等待事件被设置
  626. self.event.wait()
  627. print("self.dialog_result", self.dialog_result)
  628. # my_dialog = DialogShow(
  629. # self.windows, text=text, button_1=button_1, button_2=button_2, button_3=button_3
  630. # )
  631. print("my_dialog.flag_name", self.dialog_result)
  632. if "移除" in self.dialog_result:
  633. for error_folder_data in data["data"]["error_folder_list"]:
  634. self.move_error_folders(
  635. one_path=error_folder_data["folder_path"],
  636. target_folder=target_error_folder,
  637. )
  638. if "继续" in self.dialog_result:
  639. do_next = True
  640. if data["data"]["goods_no_dict"] and not data["data"]["error_folder_list"]:
  641. do_next = True
  642. if do_next:
  643. # self.set_state(state_value=1)
  644. getAllData = data["data"]
  645. base_temp_name = getAllData["temp_name"]
  646. set_temp_name = getAllData.get("template_name", "")
  647. kwargs = {
  648. "config_data": config_data,
  649. "_goods_no_dict": data["data"]["goods_no_dict"],
  650. "temp_name": base_temp_name,
  651. "temp_name_list": data["data"]["temp_name_list"],
  652. "assigned_page_dict": data["data"]["assigned_page_dict"],
  653. "excel_temp_goods_no_data": data["data"]["excel_temp_goods_no_data"],
  654. # 表格数据可能存在多模板,数据结构为一个款号下的多个模板的数据列表
  655. "finally_goods_no_need_temps": data["data"]["finally_goods_no_need_temps"], # 每个款号需要生成的模板数据
  656. }
  657. # todo work
  658. new_func = partial(self.detail_run_by_thread,
  659. config_data=kwargs["config_data"],
  660. _goods_no_dict=kwargs["_goods_no_dict"],
  661. temp_name=kwargs["temp_name"],
  662. temp_name_list=kwargs["temp_name_list"],
  663. assigned_page_dict=kwargs["assigned_page_dict"],
  664. excel_temp_goods_no_data=kwargs["excel_temp_goods_no_data"],
  665. finally_goods_no_need_temps=kwargs["finally_goods_no_need_temps"])
  666. self._w_3 = WorkerOneThread(func=new_func, name="_w_3")
  667. self._w_3.start()
  668. # threading.Thread(target=self.detail_run_by_thread, kwargs=kwargs).start()
  669. else:
  670. config_data["sign_text"] = "已结束详情处理"
  671. self.run_end_sign.emit(config_data)
  672. def detail_run_by_thread(self, config_data, _goods_no_dict, temp_name, temp_name_list, assigned_page_dict,
  673. excel_temp_goods_no_data,
  674. finally_goods_no_need_temps):
  675. """
  676. excel_temp_goods_no_data: {}, # 表格数据可能存在多模板,数据结构为一个款号下的多个模板的数据列表
  677. finally_goods_no_need_temps: {}, # 每个款号需要生成的模板数据
  678. """
  679. # 开始处理
  680. self.n = 0
  681. self.total_num = len(_goods_no_dict)
  682. self.fail_num = 0
  683. is_use_excel = config_data["is_use_excel"]
  684. image_dir = config_data["image_dir"]
  685. # 详情图生成结果文件夹
  686. out_put_dir = "{}\软件-详情图生成".format(image_dir)
  687. if settings.IS_TEST:
  688. print("==============_goods_no_dict 打印=================")
  689. print(json.dumps(_goods_no_dict))
  690. print("==============_goods_no_dict 打印-end=================")
  691. all_detail_path_list = []
  692. for goods_no, temp_name_list in finally_goods_no_need_temps.items():
  693. try:
  694. for _temp_name in temp_name_list:
  695. # if _temp_name != "xiaosushuoxie-4":
  696. # continue
  697. assigned_page_list = []
  698. if _temp_name in assigned_page_dict:
  699. assigned_page_list = assigned_page_dict[_temp_name]
  700. # 如果为使用表格,则获取表格中的数据作为款号的基础数据
  701. temp_info_data = copy.copy(_goods_no_dict[goods_no])
  702. if is_use_excel:
  703. # 将表格中的数据进行替换
  704. if goods_no in excel_temp_goods_no_data:
  705. if _temp_name in excel_temp_goods_no_data[goods_no]:
  706. # 将表格中的特定的模板的行,替换到goods_no的data中,因为不同的模板有数据特殊性
  707. for _key, _key_value in excel_temp_goods_no_data[goods_no][_temp_name].items():
  708. if _key in temp_info_data:
  709. temp_info_data[_key] = _key_value
  710. print("temp_info_data")
  711. print("goods_no:{},_temp_name:{}".format(goods_no, _temp_name))
  712. all_detail_path_list.append("{}/{}/".format(out_put_dir, _temp_name, goods_no))
  713. # continue
  714. self.detail_deal_one_data(goods_no=goods_no,
  715. value=temp_info_data,
  716. out_put_dir=out_put_dir,
  717. temp_name=_temp_name,
  718. assigned_page_list=assigned_page_list)
  719. except BaseException as e:
  720. self.show_progress_detail(
  721. "款:{}生成详情异常:{}".format(goods_no, e))
  722. print(e)
  723. # ==============完成处理==============
  724. self.set_state(state_value=2)
  725. if self.total_num:
  726. if self.fail_num:
  727. self.show_progress_detail("处理完成,-----处理失败数据:{}个款".format(self.fail_num))
  728. else:
  729. self.show_progress_detail("处理完成")
  730. else:
  731. self.show_progress_detail("没有任何数据")
  732. config_data["sign_text"] = "已结束详情处理"
  733. config_data["all_detail_path_list"] = all_detail_path_list
  734. # 打开文件夹
  735. os.startfile(out_put_dir)
  736. self.run_end_sign.emit(config_data)
  737. def detail_run_by_thread11111(self, config_data, _goods_no_dict, temp_name, temp_name_list, assigned_page_dict,
  738. excel_temp_goods_no_data,
  739. finally_goods_no_need_temps):
  740. """
  741. excel_temp_goods_no_data: {}, # 表格数据可能存在多模板,数据结构为一个款号下的多个模板的数据列表
  742. finally_goods_no_need_temps: {}, # 每个款号需要生成的模板数据
  743. """
  744. # 开始处理
  745. self.n = 0
  746. self.total_num = len(_goods_no_dict)
  747. self.fail_num = 0
  748. is_use_excel = config_data["is_use_excel"]
  749. image_dir = config_data["image_dir"]
  750. # 详情图生成结果文件夹
  751. out_put_dir = "{}\软件-详情图生成".format(image_dir)
  752. if settings.IS_TEST:
  753. print("==============_goods_no_dict 打印=================")
  754. print(json.dumps(_goods_no_dict))
  755. print("==============_goods_no_dict 打印-end=================")
  756. if settings.IS_TEST:
  757. max_workers = 1
  758. else:
  759. max_workers = 1
  760. all_detail_path_list = []
  761. with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
  762. futures = []
  763. for goods_no, temp_name_list in finally_goods_no_need_temps.items():
  764. for _temp_name in temp_name_list:
  765. # if _temp_name != "xiaosushuoxie-4":
  766. # continue
  767. assigned_page_list = []
  768. if _temp_name in assigned_page_dict:
  769. assigned_page_list = assigned_page_dict[_temp_name]
  770. # 如果为使用表格,则获取表格中的数据作为款号的基础数据
  771. temp_info_data = copy.copy(_goods_no_dict[goods_no])
  772. if is_use_excel:
  773. # 将表格中的数据进行替换
  774. if goods_no in excel_temp_goods_no_data:
  775. if _temp_name in excel_temp_goods_no_data[goods_no]:
  776. # 将表格中的特定的模板的行,替换到goods_no的data中,因为不同的模板有数据特殊性
  777. for _key, _key_value in excel_temp_goods_no_data[goods_no][_temp_name].items():
  778. if _key in temp_info_data:
  779. temp_info_data[_key] = _key_value
  780. print("temp_info_data")
  781. print("goods_no:{},_temp_name:{}".format(goods_no, _temp_name))
  782. all_detail_path_list.append("{}/{}/".format(out_put_dir, _temp_name, goods_no))
  783. # continue
  784. futures.append(executor.submit(
  785. self.detail_deal_one_data,
  786. goods_no=goods_no,
  787. value=temp_info_data,
  788. out_put_dir=out_put_dir,
  789. temp_name=_temp_name,
  790. assigned_page_list=assigned_page_list,
  791. ))
  792. # for goods_no, value in _goods_no_dict.items():
  793. # _temp_name = temp_name
  794. # # 使用自定义的表格数据
  795. # if self.isUseTemplate is False:
  796. # if "模板名称" in value:
  797. # if value["模板名称"] in temp_name_list:
  798. # _temp_name = value["模板名称"]
  799. # assigned_page_list = []
  800. # if _temp_name in assigned_page_dict:
  801. # assigned_page_list = assigned_page_dict[_temp_name]
  802. #
  803. # futures.append(executor.submit(
  804. # self.deal_one_data,
  805. # goods_no=goods_no,
  806. # value=value,
  807. # out_put_dir=out_put_dir,
  808. # temp_name=_temp_name,
  809. # assigned_page_list=assigned_page_list,
  810. # ))
  811. # 使用 wait 方法等待所有任务完成
  812. done, not_done = concurrent.futures.wait(futures)
  813. # 处理完成的任务
  814. for future in done:
  815. if settings.IS_TEST:
  816. result = future.result()
  817. # ==============完成处理==============
  818. self.set_state(state_value=2)
  819. if self.total_num:
  820. if self.fail_num:
  821. self.show_progress_detail(
  822. "处理完成,-----------处理失败数据:{}个款".format(self.fail_num)
  823. )
  824. else:
  825. self.show_progress_detail("处理完成")
  826. else:
  827. self.show_progress_detail("没有任何数据")
  828. config_data["sign_text"] = "已结束详情处理"
  829. config_data["all_detail_path_list"] = all_detail_path_list
  830. self.run_end_sign.emit(config_data)
  831. def show_progress_detail(self, text):
  832. # self.show_progress_detail_sign.emit(text)
  833. # self.windows.show_progress_detail(text)
  834. pass
  835. def detail_deal_one_data(self, goods_no, value, out_put_dir, temp_name, assigned_page_list):
  836. if self.windows.state == 99:
  837. self.show_progress_detail("用户主动取消:{}".format(goods_no))
  838. return
  839. self.show_progress_detail("正在生成:{},模板:{}".format(goods_no, temp_name))
  840. is_deal_success = False
  841. print("=================deal_one_data=====================")
  842. print("goods_no", goods_no)
  843. print("模板:", temp_name)
  844. print("value:", value)
  845. if settings.IS_TEST:
  846. d = self.windows.temp_class[temp_name](goods_no, value,
  847. out_put_dir=out_put_dir,
  848. windows=self.windows,
  849. assigned_page_list=assigned_page_list)
  850. is_deal_success = True
  851. else:
  852. try:
  853. # # 处理图片详情图生成
  854. d = self.windows.temp_class[temp_name](goods_no, value,
  855. out_put_dir=out_put_dir,
  856. windows=self.windows,
  857. assigned_page_list=assigned_page_list)
  858. is_deal_success = True
  859. except BaseException as e:
  860. self.show_progress_detail("{}处理失败".format(goods_no))
  861. error_text = "{}".format(e)
  862. if "Unable to allocate" in error_text:
  863. error_text = "电脑内存不足,生成失败"
  864. self.show_progress_detail("失败原因:{}".format(error_text))
  865. self.fail_num += 1
  866. self.n += 1
  867. if not is_deal_success:
  868. goods_art_no_list = value["货号资料"]
  869. self.show_progress_detail("处理失败")
  870. self.show_progress_detail(
  871. "相关货号:{}".format([x["货号"] for x in goods_art_no_list])
  872. )
  873. # 将相关的文件夹统一移动至错误文件夹
  874. detail_func.move_folders(
  875. path_list=[
  876. "{}/{}".format(self.windows.image_dir, x)
  877. for x in [x["文件夹名称"] for x in goods_art_no_list]
  878. ],
  879. target_folder=self.windows.target_error_folder,
  880. )
  881. pass
  882. # 更新进度
  883. print(self.n, self.total_num)
  884. self.windows.progress_sign.emit(
  885. {
  886. "type": "详情图生成",
  887. "progress_bar_value": int(self.n / self.total_num * 100),
  888. }
  889. )
  890. def check_serializable(self, obj): # 检查某个对象其中的属性哪些不能被序列化
  891. for attr_name in dir(obj):
  892. if not attr_name.startswith('__'):
  893. try:
  894. attr_value = getattr(obj, attr_name)
  895. serialized = pickle.dumps(attr_value)
  896. print(f"属性 {attr_name} 是可序列化的。")
  897. except (TypeError, pickle.PicklingError):
  898. print(f"属性 {attr_name} 不可序列化。")
  899. def on_dialog_result(self, result):
  900. """处理对话框结果"""
  901. self.dialog_result = result
  902. print("972 处理对话框结果:{}".format(result))
  903. # self.quit() # 结束事件循
  904. self.event.set()