api.py 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702
  1. from re import search
  2. from natsort.natsort import order_by_index
  3. from sqlalchemy import func
  4. from models import *
  5. import requests
  6. import json
  7. from logger import logger
  8. from serial.tools import list_ports
  9. from model import PhotoRecord
  10. import settings, datetime
  11. import pandas as pd
  12. from utils.hlm_http_request import forward_request
  13. from utils.utils_func import check_path
  14. from sockets.socket_client import socket_manager
  15. from mcu.DeviceControl import DeviceControl
  16. import time, shutil, os
  17. from sqlalchemy import and_, asc, desc
  18. from functools import partial
  19. from service.deal_image import DealImage
  20. from databases import DeviceConfig, SysConfigs, SqlQuery, CRUD, select, DeviceConfigTabs
  21. from service.run_main import RunMain
  22. import importlib
  23. from service.auto_deal_pics.upload_pic import UploadPic
  24. from service.OnePicTest import OnePicTest
  25. from service.base import check_move_goods_art_no_folder
  26. import win32api, win32gui, win32con
  27. from win32gui import EnumWindows, GetWindowText
  28. from service.online_request.module_online_data import OnlineDataRequest
  29. from concurrent.futures import ThreadPoolExecutor
  30. from functools import partial
  31. from service.online_request.module_online_data import AIGCDataRequest
  32. import asyncio
  33. from fastapi import BackgroundTasks
  34. import functools
  35. import traceback
  36. def log_exception_with_context(context_message=""):
  37. """装饰器:为函数添加异常日志上下文"""
  38. def decorator(func):
  39. @functools.wraps(func)
  40. def wrapper(*args, **kwargs):
  41. try:
  42. return func(*args, **kwargs)
  43. except Exception as e:
  44. logger.error(f"=== 异常发生在函数: {func.__name__} ===")
  45. if context_message:
  46. logger.error(f"上下文信息: {context_message}")
  47. logger.error(f"函数参数: args={args}, kwargs={kwargs}")
  48. logger.error(f"异常类型: {type(e).__name__}")
  49. logger.error(f"异常信息: {str(e)}")
  50. logger.error("完整堆栈跟踪:")
  51. logger.error(traceback.format_exc())
  52. raise # 重新抛出异常
  53. return wrapper
  54. return decorator
  55. def parserGoodsDict2Aigc(return_data_check_before_detail):
  56. """获取商品组装数据"""
  57. goods_no_dict = return_data_check_before_detail.get("data", {}).get(
  58. "goods_no_dict", {}
  59. )
  60. return goods_no_dict
  61. async def sendAsyncMessage(msg="", goods_arts=[], status="", msg_type="", data=None,progress=None):
  62. """异步发送消息"""
  63. if progress is not None:
  64. progress["msg_type"] = msg_type
  65. data = {
  66. "code": 0,
  67. "msg": msg,
  68. "status": 2,
  69. "data": (
  70. data
  71. if data is not None
  72. else {
  73. "status": status,
  74. "goods_art_nos": goods_arts,
  75. }
  76. ),
  77. "progress": None if progress is None else progress,
  78. "msg_type": msg_type,
  79. }
  80. await message_queue.put(data)
  81. @app.get("/")
  82. async def index():
  83. # await socket_manager.send_message(msg="测试")
  84. return {"message": "Hello World"}
  85. @app.get("/scan_serials", description="扫描可用的设备端口")
  86. async def scanSerials():
  87. """扫描串口"""
  88. ports = list_ports.comports()
  89. print("Scanning", ports)
  90. return {"message": "Hello World"}
  91. @app.api_route(
  92. "/forward_request", methods=["GET", "POST"], description="代理转发hlm项目得请求"
  93. )
  94. async def forwardRequest(request: HlmForwardRequest):
  95. """
  96. 转发HTTP请求到目标URL
  97. :param request: FastAPI Request对象
  98. :return: 目标接口的响应
  99. """
  100. try:
  101. if request.method == "GET":
  102. params = request.query_params
  103. elif request.method == "POST":
  104. params = json.dump(request.query_params)
  105. else:
  106. raise UnicornException("仅支持GET和POST方法")
  107. target_url = request.target_url
  108. method = request.method.upper()
  109. headers = request.headers
  110. if not target_url:
  111. raise UnicornException("目标url地址不能为空")
  112. # 调用 hlm_http_request 中的 forward_request 函数
  113. response = forward_request(
  114. target_url, params=params, method=method, headers=headers
  115. )
  116. return response
  117. except requests.RequestException as e:
  118. raise UnicornException(e)
  119. except Exception as e:
  120. raise UnicornException(e)
  121. async def fromExcelHandler(params: HandlerDetail):
  122. obj = None
  123. excel_path = params.excel_path
  124. token = "Bearer " + params.token
  125. uuid = params.uuid
  126. aigc_clazz = AIGCDataRequest(token)
  127. run_main = RunMain(obj, token, uuid)
  128. onlineData = OnlineDataRequest(token)
  129. excel_df = pd.read_excel(excel_path, sheet_name=0, header=0)
  130. online_stores = params.online_stores # 上传第三方的店铺名称数组
  131. is_product_scene = params.is_product_scene # 上传第三方的店铺名称数组
  132. is_upper_footer = params.is_upper_footer # 上传第三方的店铺名称数组
  133. upper_footer_params = params.upper_footer_params # 上传第三方的店铺名称数组
  134. product_scene_prompt = params.product_scene_prompt # 上传第三方的店铺名称数组
  135. handler_result = []
  136. handler_result_folder = ""
  137. if "文件夹名称" not in excel_df.columns:
  138. raise UnicornException("缺失 [文件夹名称] 列")
  139. if "商品货号" not in excel_df.columns:
  140. raise UnicornException("缺失 [商品货号] 列")
  141. if "款号" not in excel_df.columns:
  142. raise UnicornException("缺失 [款号] 列")
  143. goods_art_dirs = excel_df.groupby(excel_df["款号"])
  144. # 抠图时用到的货号列表,与生成详情图有所区别
  145. goods_art_no_arrays = []
  146. # # 详情图生成需要对同款商品进行分组,保证详情图可以生成多个色
  147. goods_art_no_group_arrays = []
  148. for _, goods_row in excel_df.iterrows():
  149. goods_art_no = str(goods_row["商品货号"])
  150. goods_art_no_arrays.append(goods_art_no)
  151. goods_no = str(goods_row["款号"])
  152. a001_df = goods_art_dirs.get_group(goods_no)
  153. goods_art_groups = a001_df["商品货号"].tolist()
  154. if goods_art_groups in goods_art_no_group_arrays:
  155. continue
  156. goods_art_no_group_arrays.append(goods_art_groups)
  157. limit_path = "output/{}".format(
  158. time.strftime("%Y-%m-%d", time.localtime(time.time()))
  159. )
  160. # 该数组表示是否需要后面的移动文件夹操作,减少重复抠图,提升抠图时间和速度
  161. move_folder_array = check_move_goods_art_no_folder(
  162. "output", goods_art_no_arrays, limit_path
  163. )
  164. try:
  165. for index, row in excel_df.iterrows():
  166. goods_art_no_image_dir = str(row["文件夹名称"])
  167. goods_art_no = str(row["商品货号"])
  168. print("货号数据", goods_art_no)
  169. if not goods_art_no:
  170. raise UnicornException("货号不能为空")
  171. session = SqlQuery()
  172. pr = CRUD(PhotoRecord)
  173. images = pr.read_all(session, conditions={"goods_art_no": goods_art_no})
  174. if not images:
  175. raise UnicornException(
  176. f"商品货号【{goods_art_no}】在商品档案资料中不存在,请检查货号是否正确"
  177. )
  178. # 货号目录不存在再去进行移动和创建操作
  179. if move_folder_array.get(goods_art_no) == None:
  180. image_dir = "{}/data/".format(os.getcwd()).replace("\\", "/")
  181. check_path(image_dir)
  182. for idx, itemImg in enumerate(images):
  183. if itemImg.image_path == "" or itemImg.image_path == None:
  184. raise UnicornException(
  185. f"货号【{goods_art_no}】存在没有拍摄完成的图片,请重拍或删除后重试"
  186. )
  187. new_file_name = str(itemImg.goods_art_no) + "_" + str(idx) + ".jpg"
  188. if not os.path.exists(
  189. image_dir + "/" + os.path.basename(new_file_name)
  190. ):
  191. shutil.copy(itemImg.image_path, image_dir + new_file_name)
  192. dealImage = DealImage(image_dir)
  193. resFlag, path = dealImage.dealMoveImage(
  194. image_dir=image_dir,
  195. callback_func=None,
  196. goods_art_no=goods_art_no_image_dir,
  197. )
  198. if not resFlag:
  199. raise UnicornException(path)
  200. shutil.rmtree(image_dir)
  201. # path = os.path.dirname(path)
  202. except UnicornException as e:
  203. handler_result_folder = ""
  204. handler_result.append(
  205. {"goods_art_no": "", "success": False, "info": str(e.msg)}
  206. )
  207. print(f"UnicornException 生成错误信息:{e}")
  208. await sendAsyncMessage(
  209. msg="处理结束",
  210. data={"output_folder": handler_result_folder, "list": handler_result},
  211. status="处理结束",
  212. msg_type="detail_result_progress",
  213. )
  214. return True
  215. except Exception as e:
  216. print(f"详情图生成错误信息:{e}")
  217. handler_result_folder = ""
  218. handler_result.append({"goods_art_no": "", "success": False, "info": str(e)})
  219. await sendAsyncMessage(
  220. msg="处理结束",
  221. data={"output_folder": handler_result_folder, "list": handler_result},
  222. status="处理结束",
  223. msg_type="detail_result_progress",
  224. )
  225. return True
  226. temp_class = {}
  227. # 可用模板列表-需要导包
  228. temp_name_list = []
  229. for tempItem in params.temp_list:
  230. temp_class[tempItem.template_id] = tempItem.template_local_classes
  231. temp_name_list.append(tempItem.template_id)
  232. cutOutMode = (
  233. "0"
  234. if settings.getSysConfigs("other_configs", "cutout_mode", "普通抠图")
  235. == "普通抠图"
  236. else "1"
  237. )
  238. config_data = {
  239. "image_dir": limit_path, # 这个目录作为本次生成的图片目录非常重要 例:./output/当前日期
  240. "image_order": (
  241. "俯视,侧视,后跟,鞋底,内里,组合,组合2,组合3,组合4,组合5"
  242. if params.template_image_order == None or params.template_image_order == ""
  243. else params.template_image_order
  244. ),
  245. "goods_art_no": goods_art_no,
  246. "goods_art_nos": goods_art_no_arrays,
  247. "is_check_number": False,
  248. "resize_image_view": "后跟",
  249. "cutout_mode": cutOutMode,
  250. "logo_path": params.logo_path,
  251. "special_goods_art_no_folder_line": "",
  252. "is_use_excel": (False if params.excel_path == "" else True), # 是否使用excel
  253. "excel_path": params.excel_path, # excel路径
  254. "is_check_color_is_all": False,
  255. "cutout_is_pass": True,
  256. "assigned_page_dict": {},
  257. "detail_is_pass": True,
  258. "upload_is_pass": False,
  259. "upload_is_enable": False,
  260. "is_filter": False,
  261. "temp_class": temp_class,
  262. "temp_name": params.temp_name,
  263. "temp_name_list": temp_name_list,
  264. "target_error_folder": f"{limit_path}/软件-生成详情错误",
  265. "success_handler": [],
  266. }
  267. # 动态导入类
  268. temp_class_dict = {}
  269. for key, class_path in config_data["temp_class"].items():
  270. module_path, class_name = class_path.rsplit(".", 1)
  271. module = importlib.import_module(module_path)
  272. cls = getattr(module, class_name)
  273. temp_class_dict[key] = cls
  274. config_data["temp_class"] = temp_class_dict
  275. # executor = ThreadPoolExecutor(max_workers=4)
  276. # 此处对抠图进行批量处理,保证所有的图片在生成详情图之前已经完成抠图,以保证详情图生成的效率
  277. return_data = run_main.check_before_cutout(config_data)
  278. cutout_res = run_main.check_for_cutout_image_first_call_back(return_data)
  279. check_for_detail_first_res = None
  280. if cutout_res == True:
  281. sys_path = format(os.getcwd()).replace("\\", "/")
  282. handler_result_folder = f"{sys_path}/{limit_path}"
  283. for goods_art_item in goods_art_no_arrays:
  284. handler_result.append(
  285. {
  286. "goods_art_no": goods_art_item,
  287. "success": True,
  288. "info": "处理成功",
  289. }
  290. )
  291. try:
  292. if is_product_scene == 1:
  293. if product_scene_prompt == "" or product_scene_prompt == None:
  294. raise UnicornException("请填写场景描述")
  295. if is_upper_footer == 1:
  296. if upper_footer_params == {} or upper_footer_params == None:
  297. raise UnicornException("请选择模特")
  298. man_id = upper_footer_params.get("man_id")
  299. if not man_id:
  300. raise UnicornException("请选择男模特")
  301. women_id = upper_footer_params.get("women_id")
  302. if not women_id:
  303. raise UnicornException("请选择女模特")
  304. return_data_check_before_detail = run_main.check_before_detail(config_data)
  305. print("报错前返回的结果数据", return_data_check_before_detail)
  306. if is_product_scene == 1:
  307. goods_dict = parserGoodsDict2Aigc(return_data_check_before_detail)
  308. new_goods_dict = {}
  309. await sendAsyncMessage(
  310. msg="开始处理场景图",
  311. goods_arts=[goods_art_no for goods_art_no in goods_dict.keys()],
  312. status="开始处理",
  313. msg_type="scene_progress",
  314. )
  315. for goods_art_no in goods_dict.keys():
  316. print("处理场景图", goods_art_no)
  317. goods_art_dict_info = goods_dict[goods_art_no]
  318. first_goods_art_no_info = goods_art_dict_info.get("货号资料", [])[0]
  319. first_pics = first_goods_art_no_info.get("pics")
  320. ceshi_image_path = first_pics.get("侧视-抠图")
  321. save_root_path = ceshi_image_path.split("阴影图处理")[0]
  322. save_image_path = f"{save_root_path}场景图.jpg"
  323. if os.path.isfile(save_image_path):
  324. goods_art_dict_info["场景图"] = save_image_path
  325. new_goods_dict[goods_art_no] = goods_art_dict_info
  326. continue
  327. aigc_clazz.center_paste_image(ceshi_image_path, save_image_path)
  328. try:
  329. image_path = aigc_clazz.generateProductScene(
  330. save_image_path, product_scene_prompt, save_image_path
  331. )
  332. # image_path = aigc_clazz.generateProductSceneQW(
  333. # save_image_path, product_scene_prompt, save_image_path
  334. # )
  335. goods_art_dict_info["场景图"] = image_path
  336. new_goods_dict[goods_art_no] = goods_art_dict_info
  337. handler_result.append(
  338. {
  339. "goods_art_no": goods_art_no,
  340. "success": True,
  341. "info": "场景图处理成功",
  342. }
  343. )
  344. await sendAsyncMessage(
  345. msg="场景图处理完成",
  346. goods_arts=[goods_art_no],
  347. status="场景图处理完成",
  348. msg_type="scene_progress",
  349. )
  350. except Exception as e:
  351. os.remove(save_image_path)
  352. handler_result.append(
  353. {
  354. "goods_art_no": goods_art_no,
  355. "success": False,
  356. "info": f"场景图处理失败:{e}",
  357. }
  358. )
  359. await sendAsyncMessage(
  360. msg="场景图处理失败",
  361. goods_arts=[goods_art_no],
  362. status="场景图处理失败",
  363. msg_type="scene_progress",
  364. )
  365. if new_goods_dict is not None or new_goods_dict != {}:
  366. return_data_check_before_detail["data"][
  367. "goods_no_dict"
  368. ] = new_goods_dict
  369. if is_upper_footer == 1:
  370. goods_dict = parserGoodsDict2Aigc(return_data_check_before_detail)
  371. new_goods_dict = {}
  372. await sendAsyncMessage(
  373. msg="开始处理模特图",
  374. goods_arts=list(goods_dict.keys()),
  375. status="开始处理模特图",
  376. msg_type="upper_footer_progress",
  377. )
  378. for goods_art_no in goods_dict.keys():
  379. goods_art_dict_info = goods_dict[goods_art_no]
  380. first_goods_art_no_info = goods_art_dict_info.get("货号资料", [])[0]
  381. first_pics = first_goods_art_no_info.get("pics")
  382. gender = goods_art_dict_info.get("性别")
  383. model_id = man_id if "男" in gender else women_id
  384. ceshi_image_path = first_pics.get("侧视-抠图")
  385. save_root_path = ceshi_image_path.split("阴影图处理")[0]
  386. save_image_path = f"{save_root_path}模特图.jpg"
  387. if os.path.isfile(save_image_path):
  388. goods_art_dict_info["模特图"] = save_image_path
  389. new_goods_dict[goods_art_no] = goods_art_dict_info
  390. continue
  391. shutil.copy(ceshi_image_path, save_image_path)
  392. try:
  393. image_path = aigc_clazz.generateUpperShoes(
  394. save_image_path, model_id, save_image_path
  395. )
  396. # image_path = aigc_clazz.generateModelShoesQW(
  397. # save_image_path, model_id, save_image_path
  398. # )
  399. goods_art_dict_info["模特图"] = image_path
  400. new_goods_dict[goods_art_no] = goods_art_dict_info
  401. handler_result.append(
  402. {
  403. "goods_art_no": goods_art_no,
  404. "success": True,
  405. "info": "模特图处理成功",
  406. }
  407. )
  408. await sendAsyncMessage(
  409. msg="模特图处理成功",
  410. goods_arts=[goods_art_no],
  411. status="模特图处理成功",
  412. msg_type="upper_footer_progress",
  413. )
  414. except Exception as e:
  415. os.remove(save_image_path)
  416. handler_result.append(
  417. {
  418. "goods_art_no": goods_art_no,
  419. "success": False,
  420. "info": f"模特图处理失败:{e}",
  421. }
  422. )
  423. await sendAsyncMessage(
  424. msg="模特图处理失败",
  425. goods_arts=[goods_art_no],
  426. status="模特图处理失败",
  427. msg_type="upper_footer_progress",
  428. )
  429. if new_goods_dict is not None or new_goods_dict != {}:
  430. return_data_check_before_detail["data"][
  431. "goods_no_dict"
  432. ] = new_goods_dict
  433. await sendAsyncMessage(
  434. msg="开始处理详情页",
  435. goods_arts=[],
  436. status="开始处理详情页",
  437. msg_type="detail_progress",
  438. )
  439. check_for_detail_first_res = run_main.check_for_detail_first_call_back(
  440. return_data_check_before_detail
  441. )
  442. if isinstance(check_for_detail_first_res, partial):
  443. result = check_for_detail_first_res()
  444. try:
  445. config_data = result["config_data"]
  446. except:
  447. config_data = result
  448. if config_data["sign_text"] == "已结束详情处理":
  449. await sendAsyncMessage(
  450. msg="详情页处理结束",
  451. goods_arts=[],
  452. status="详情页处理结束",
  453. msg_type="detail_progress",
  454. )
  455. print("config_data", config_data)
  456. # if config_data["upload_is_enable"]:
  457. # to_deal_dir = "{}/软件-详情图生成".format(config_data["image_dir"])
  458. # check_path(to_deal_dir)
  459. # print("to_deal_dir", to_deal_dir)
  460. # if os.path.exists(to_deal_dir):
  461. # upload_pic = UploadPic(
  462. # windows=None,
  463. # to_deal_dir=to_deal_dir,
  464. # config_data=config_data,
  465. # token=token,
  466. # )
  467. # upload_pic.run()
  468. out_put_dir = config_data.get("out_put_dir")
  469. if out_put_dir == None:
  470. handler_result_folder = ""
  471. if len(config_data["success_handler"]) > 0:
  472. for good_art in config_data["success_handler"]:
  473. handler_result.append(good_art)
  474. else:
  475. for good_art in goods_art_no_arrays:
  476. handler_result.append(
  477. {
  478. "goods_art_no": good_art,
  479. "success": False,
  480. "info": "处理失败",
  481. }
  482. )
  483. else:
  484. out_put_dir_path = "{}/{}".format(os.getcwd(), out_put_dir).replace(
  485. "\\", "/"
  486. )
  487. handler_result_folder = os.path.dirname(out_put_dir_path)
  488. if len(config_data["success_handler"]) == 0:
  489. for good_art in goods_art_no_arrays:
  490. handler_result.append(
  491. {
  492. "goods_art_no": good_art,
  493. "success": False,
  494. "info": "处理失败",
  495. }
  496. )
  497. else:
  498. if len(online_stores) > 0:
  499. result_goods_no_dict = return_data_check_before_detail["data"][
  500. "goods_no_dict"
  501. ]
  502. for goods_idx, goods_no_dict in enumerate(
  503. result_goods_no_dict.keys()
  504. ):
  505. all_detail_path_list = config_data["all_detail_path_list"]
  506. for detail_path in all_detail_path_list:
  507. if goods_no_dict in detail_path:
  508. detail_path_replace = detail_path.replace("\\", "/")
  509. result_goods_no_dict[goods_no_dict][
  510. "detail_path"
  511. ] = f"{detail_path_replace}/详情页.jpg"
  512. await sendAsyncMessage(
  513. msg="开始上传商品数据",
  514. goods_arts=[],
  515. status="开始上传商品数据",
  516. msg_type="upload_goods_progress",
  517. )
  518. try:
  519. onlineData.uploadGoods2ThirdParty(
  520. result_goods_no_dict, online_stores=online_stores
  521. )
  522. except Exception as e:
  523. print(f"上传任务出现错误:{e}")
  524. await sendAsyncMessage(
  525. msg="商品上传第三方成功",
  526. goods_arts=[],
  527. status="商品上传第三方成功",
  528. msg_type="upload_goods_progress",
  529. )
  530. handler_result = config_data["success_handler"]
  531. else:
  532. for good_art in goods_art_no_arrays:
  533. handler_result.append(
  534. {"goods_art_no": good_art, "success": False, "info": "处理失败"}
  535. )
  536. except UnicornException as e:
  537. handler_result_folder = ""
  538. handler_result.append(
  539. {"goods_art_no": "", "success": False, "info": str(e.msg)}
  540. )
  541. print(f"UnicornException 生成错误信息:{e}")
  542. except Exception as e:
  543. for good_art in goods_art_no_arrays:
  544. handler_result.append(
  545. {"goods_art_no": good_art, "success": False, "info": str(e)}
  546. )
  547. handler_result_folder = "/".join(handler_result_folder.split("/")[:-1])
  548. await sendAsyncMessage(
  549. msg="处理结束",
  550. data={"output_folder": handler_result_folder, "list": handler_result},
  551. status="处理结束",
  552. msg_type="detail_result_progress",
  553. )
  554. return True
  555. def group_by_style_number(data):
  556. result = {}
  557. for goods_id, info in data.items():
  558. style_number = info["款号"]
  559. if style_number not in result:
  560. result[style_number] = []
  561. result[style_number].append(goods_id)
  562. return result
  563. @app.post("/handle_detail")
  564. async def handle_detail_background(
  565. request: Request, params: HandlerDetail, background_tasks: BackgroundTasks
  566. ):
  567. goods_art_no_arrays = params.goods_art_no
  568. is_check = params.is_check
  569. is_only_cutout = params.is_only_cutout # 是否仅抠图
  570. online_stores = params.online_stores # 上传第三方的店铺名称数组
  571. is_detail = params.is_detail # 上传第三方的店铺名称数组
  572. is_product_scene = params.is_product_scene # 上传第三方的店铺名称数组
  573. is_upper_footer = params.is_upper_footer # 上传第三方的店铺名称数组
  574. if is_only_cutout == 1:
  575. # 如果是仅抠图模式,避免进入到excel模式
  576. params.excel_path = ""
  577. # if params.excel_path != "" and params.excel_path != None:
  578. # return await fromExcelHandler(params)
  579. path = ""
  580. limit_path = "output/{}".format(
  581. time.strftime("%Y-%m-%d", time.localtime(time.time()))
  582. )
  583. check_path(limit_path)
  584. # 该数组表示是否需要后面的移动文件夹操作,减少重复抠图,提升抠图时间和速度
  585. move_folder_array = check_move_goods_art_no_folder(
  586. "output", goods_art_no_arrays, limit_path
  587. )
  588. try:
  589. for goods_art_no in goods_art_no_arrays:
  590. if not goods_art_no:
  591. raise UnicornException("货号不能为空")
  592. session = SqlQuery()
  593. pr = CRUD(PhotoRecord)
  594. images = pr.read_all(session, conditions={"goods_art_no": goods_art_no})
  595. if not images:
  596. raise UnicornException(
  597. f"商品货号【{goods_art_no}】在商品档案资料中不存在,请检查货号是否正确"
  598. )
  599. if is_only_cutout != 1:
  600. detail_counts = len(params.template_image_order.split(","))
  601. image_counts = len(images)
  602. if image_counts < detail_counts:
  603. raise UnicornException(
  604. f"货号:[{goods_art_no}],实际照片数量:{image_counts}张,小于详情图要求数量:{detail_counts}张"
  605. )
  606. if move_folder_array.get(goods_art_no) == None:
  607. image_dir = "{}/data/".format(os.getcwd()).replace("\\", "/")
  608. check_path(image_dir)
  609. for idx, itemImg in enumerate(images):
  610. if itemImg.image_path == "" or itemImg.image_path == None:
  611. raise UnicornException(
  612. f"货号【{goods_art_no}】存在没有拍摄完成的图片,请重拍或删除后重试"
  613. )
  614. new_file_name = str(itemImg.goods_art_no) + "_" + str(idx) + ".jpg"
  615. if not os.path.exists(
  616. image_dir + "/" + os.path.basename(new_file_name)
  617. ):
  618. shutil.copy(itemImg.image_path, image_dir + new_file_name)
  619. dealImage = DealImage(image_dir)
  620. resFlag, path = dealImage.dealMoveImage(
  621. image_dir=image_dir, callback_func=None, goods_art_no=goods_art_no
  622. )
  623. if not resFlag:
  624. raise UnicornException(path)
  625. except Exception as e:
  626. raise UnicornException(str(e))
  627. progress = [{"msg_type":"segment_progress","name":"抠图","status":"等待处理","current":0,"total":0,"error":0}]
  628. if is_product_scene == 1:
  629. progress.append({"msg_type":"scene_progress","name":"场景图","status":"等待处理","current":0,"total":0,"error":0})
  630. if is_upper_footer == 1:
  631. progress.append({"msg_type":"upper_footer_progress","name":"模特图","status":"等待处理","current":0,"total":0,"error":0})
  632. if is_detail==1 or (params.excel_path != "" and params.excel_path != None):
  633. progress.append({"msg_type":"detail_progress","name":"详情页(详情页切片、详情页拼接、详情页生成完成)","status":"等待处理","current":0,"total":0,"error":0})
  634. if len(online_stores) > 0:
  635. progress.append({"msg_type":"upload_goods_progress","name":"上传第三方商品","status":"等待处理","current":0,"total":0,"error":0})
  636. if is_check == 1:
  637. return {
  638. "code": 0,
  639. "msg": "检测通过",
  640. "data": {"progress":progress},
  641. }
  642. asyncio.create_task(process_handle_detail(request, params))
  643. return {"code": 0, "msg": "任务已提交后台处理", "data": {"status": "processing"}}
  644. async def process_handle_detail(request: Request, params: HandlerDetail):
  645. obj = None
  646. token = "Bearer " + params.token
  647. uuid = params.uuid
  648. aigc_clazz = AIGCDataRequest(token)
  649. run_main = RunMain(obj, token, uuid)
  650. onlineData = OnlineDataRequest(token)
  651. goods_art_no_arrays = params.goods_art_no
  652. is_only_cutout = params.is_only_cutout # 是否仅抠图
  653. online_stores = params.online_stores # 上传第三方的店铺名称数组
  654. is_detail = params.is_detail # 上传第三方的店铺名称数组
  655. is_product_scene = params.is_product_scene # 上传第三方的店铺名称数组
  656. is_upper_footer = params.is_upper_footer # 上传第三方的店铺名称数组
  657. upper_footer_params = params.upper_footer_params # 上传第三方的店铺名称数组
  658. product_scene_prompt = params.product_scene_prompt # 上传第三方的店铺名称数组
  659. handler_result = []
  660. handler_result_folder = ""
  661. if is_only_cutout == 1:
  662. # 如果是仅抠图模式,避免进入到excel模式
  663. params.excel_path = ""
  664. if params.excel_path != "" and params.excel_path != None:
  665. return await fromExcelHandler(params)
  666. else:
  667. path = ""
  668. limit_path = "output/{}".format(
  669. time.strftime("%Y-%m-%d", time.localtime(time.time()))
  670. )
  671. check_path(limit_path)
  672. # 该数组表示是否需要后面的移动文件夹操作,减少重复抠图,提升抠图时间和速度
  673. move_folder_array = check_move_goods_art_no_folder(
  674. "output", goods_art_no_arrays, limit_path
  675. )
  676. try:
  677. for goods_art_no in goods_art_no_arrays:
  678. if not goods_art_no:
  679. raise UnicornException("货号不能为空")
  680. session = SqlQuery()
  681. pr = CRUD(PhotoRecord)
  682. images = pr.read_all(session, conditions={"goods_art_no": goods_art_no})
  683. if not images:
  684. raise UnicornException(
  685. f"商品货号【{goods_art_no}】在商品档案资料中不存在,请检查货号是否正确"
  686. )
  687. if is_only_cutout != 1:
  688. detail_counts = len(params.template_image_order.split(","))
  689. image_counts = len(images)
  690. if image_counts < detail_counts:
  691. raise UnicornException(
  692. f"货号:[{goods_art_no}],实际照片数量:{image_counts}张,小于详情图要求数量:{detail_counts}张"
  693. )
  694. if move_folder_array.get(goods_art_no) == None:
  695. image_dir = "{}/data/".format(os.getcwd()).replace("\\", "/")
  696. check_path(image_dir)
  697. for idx, itemImg in enumerate(images):
  698. if itemImg.image_path == "" or itemImg.image_path == None:
  699. raise UnicornException(
  700. f"货号【{goods_art_no}】存在没有拍摄完成的图片,请重拍或删除后重试"
  701. )
  702. new_file_name = str(itemImg.goods_art_no) + "_" + str(idx) + ".jpg"
  703. if not os.path.exists(
  704. image_dir + "/" + os.path.basename(new_file_name)
  705. ):
  706. shutil.copy(itemImg.image_path, image_dir + new_file_name)
  707. dealImage = DealImage(image_dir)
  708. resFlag, path = dealImage.dealMoveImage(
  709. image_dir=image_dir, callback_func=None, goods_art_no=goods_art_no
  710. )
  711. if not resFlag:
  712. raise UnicornException(path)
  713. except UnicornException as e:
  714. handler_result_folder = ""
  715. handler_result.append(
  716. {"goods_art_no": "", "success": False, "info": str(e.msg)}
  717. )
  718. print(f"UnicornException 生成错误信息:{e}")
  719. await sendAsyncMessage(
  720. msg="处理结束",
  721. data={"output_folder": handler_result_folder, "list": handler_result},
  722. status="处理结束",
  723. msg_type="detail_result_progress",
  724. )
  725. return True
  726. except Exception as e:
  727. print(f"详情图生成错误信息:{e}")
  728. handler_result_folder = ""
  729. handler_result.append({"goods_art_no": "", "success": False, "info": str(e)})
  730. await sendAsyncMessage(
  731. msg="处理结束",
  732. data={"output_folder": handler_result_folder, "list": handler_result},
  733. status="处理结束",
  734. msg_type="detail_result_progress",
  735. )
  736. return True
  737. # try:
  738. temp_class = {}
  739. temp_name_list = []
  740. for tempItem in params.temp_list:
  741. temp_class[tempItem.template_id] = tempItem.template_local_classes
  742. temp_name_list.append(tempItem.template_id)
  743. cutOutMode = (
  744. "1"
  745. if settings.getSysConfigs("other_configs", "cutout_mode", "普通抠图")
  746. == "普通抠图"
  747. else "2"
  748. )
  749. config_data = {
  750. "image_dir": limit_path,
  751. "image_order": (
  752. "俯视,侧视,后跟,鞋底,内里,组合,组合2,组合3,组合4,组合5"
  753. if params.template_image_order == None or params.template_image_order == ""
  754. else params.template_image_order
  755. ),
  756. "goods_art_no": "",
  757. "goods_art_nos": goods_art_no_arrays,
  758. "is_check_number": False,
  759. "resize_image_view": "后跟",
  760. "cutout_mode": cutOutMode,
  761. "logo_path": params.logo_path,
  762. "special_goods_art_no_folder_line": "",
  763. "is_use_excel": False, # 是否使用excel
  764. "excel_path": "", # excel路径
  765. "is_check_color_is_all": False,
  766. "cutout_is_pass": True,
  767. "assigned_page_dict": {},
  768. "detail_is_pass": True,
  769. "upload_is_pass": False,
  770. "upload_is_enable": settings.IS_UPLOAD_HLM, # 是否上传到惠利玛商品库,通过config.ini得is_upload开启
  771. "is_filter": False,
  772. "temp_class": temp_class,
  773. "temp_name": params.temp_name,
  774. "temp_name_list": temp_name_list,
  775. "target_error_folder": f"{limit_path}/软件-生成详情错误",
  776. "success_handler": [],
  777. }
  778. print("image_dir=====>>>>>", config_data["image_dir"])
  779. # 动态导入类
  780. temp_class_dict = {}
  781. for key, class_path in config_data["temp_class"].items():
  782. module_path, class_name = class_path.rsplit(".", 1)
  783. module = importlib.import_module(module_path)
  784. cls = getattr(module, class_name)
  785. temp_class_dict[key] = cls
  786. config_data["temp_class"] = temp_class_dict
  787. return_data = run_main.check_before_cutout(config_data)
  788. cutout_res = run_main.check_for_cutout_image_first_call_back(return_data)
  789. check_for_detail_first_res = None
  790. if cutout_res == True:
  791. sys_path = format(os.getcwd()).replace("\\", "/")
  792. handler_result_folder = f"{sys_path}/{limit_path}"
  793. for goods_art_item in goods_art_no_arrays:
  794. handler_result.append(
  795. {
  796. "goods_art_no": goods_art_item,
  797. "success": True,
  798. "info": "处理成功",
  799. }
  800. )
  801. if len(move_folder_array.keys()) == len(goods_art_no_arrays):
  802. progress = {"status":"抠图完成",
  803. "current":len(goods_art_no_arrays),
  804. "total":len(goods_art_no_arrays),
  805. "error":0}
  806. await sendAsyncMessage(
  807. msg="抠图完成",
  808. data={"output_folder": handler_result_folder, "list": handler_result},
  809. status="抠图完成",
  810. msg_type="segment_progress",
  811. progress=progress
  812. )
  813. if is_only_cutout == 1:
  814. await sendAsyncMessage(
  815. msg="处理结束",
  816. data={"output_folder": handler_result_folder, "list": handler_result},
  817. status="处理结束",
  818. msg_type="detail_result_progress",
  819. )
  820. return True
  821. try:
  822. if is_product_scene == 1:
  823. if product_scene_prompt == "" or product_scene_prompt == None:
  824. raise UnicornException("请填写场景描述")
  825. if is_upper_footer == 1:
  826. if upper_footer_params == {} or upper_footer_params == None:
  827. raise UnicornException("请选择模特")
  828. man_id = upper_footer_params.get("man_id")
  829. if not man_id:
  830. raise UnicornException("请选择男模特")
  831. women_id = upper_footer_params.get("women_id")
  832. if not women_id:
  833. raise UnicornException("请选择女模特")
  834. return_data_check_before_detail = run_main.check_before_detail(config_data)
  835. success_handler = return_data_check_before_detail.get("data").get("config_data").get("success_handler",[])
  836. failed_items = [item for item in success_handler if item.get('success') == False]
  837. print("failed_items",failed_items)
  838. if len(failed_items) > 0:
  839. await sendAsyncMessage(
  840. msg="处理结束",
  841. data={"output_folder": handler_result_folder, "list": failed_items},
  842. status="处理结束",
  843. msg_type="detail_result_progress",
  844. )
  845. if len(failed_items)!=0 and len(failed_items) == len(success_handler):
  846. # 如果全部错误 直接终止
  847. return True
  848. else:
  849. if is_product_scene == 1:
  850. goods_dict = parserGoodsDict2Aigc(return_data_check_before_detail)
  851. new_goods_dict = {}
  852. product_scene_total_progress = len(goods_dict.keys())
  853. product_scene_finish_progress = 0
  854. product_scene_error_progress = 0
  855. product_scene_progress = {"status":"开始处理场景图", "current":product_scene_finish_progress, "total":product_scene_total_progress, "error":product_scene_error_progress}
  856. print("product_scene_progress",goods_dict,product_scene_progress)
  857. await sendAsyncMessage(
  858. msg="开始处理场景图",
  859. goods_arts=[goods_art_no for goods_art_no in goods_dict.keys()],
  860. status="开始处理",
  861. msg_type="scene_progress",
  862. progress=product_scene_progress
  863. )
  864. for goods_art_no in goods_dict.keys():
  865. print("处理场景图", goods_art_no)
  866. goods_art_dict_info = goods_dict[goods_art_no]
  867. first_goods_art_no_info = goods_art_dict_info.get("货号资料", [])[0]
  868. first_pics = first_goods_art_no_info.get("pics")
  869. ceshi_image_path = first_pics.get("侧视-抠图")
  870. save_root_path = ceshi_image_path.split("阴影图处理")[0]
  871. save_image_path = f"{save_root_path}场景图.jpg"
  872. if os.path.isfile(save_image_path):
  873. goods_art_dict_info["场景图"] = save_image_path
  874. new_goods_dict[goods_art_no] = goods_art_dict_info
  875. continue
  876. aigc_clazz.center_paste_image(ceshi_image_path, save_image_path)
  877. try:
  878. image_path = aigc_clazz.generateProductScene(
  879. save_image_path, product_scene_prompt, save_image_path
  880. )
  881. # image_path = aigc_clazz.generateProductSceneQW(
  882. # save_image_path, product_scene_prompt, save_image_path
  883. # )
  884. goods_art_dict_info["场景图"] = image_path
  885. new_goods_dict[goods_art_no] = goods_art_dict_info
  886. handler_result.append(
  887. {
  888. "goods_art_no": goods_art_no,
  889. "success": True,
  890. "info": "场景图处理成功",
  891. }
  892. )
  893. product_scene_finish_progress+=1
  894. product_scene_progress = {"status":"正在处理场景图", "current":product_scene_finish_progress, "total":product_scene_total_progress, "error":product_scene_error_progress}
  895. await sendAsyncMessage(
  896. msg="场景图处理完成",
  897. goods_arts=[goods_art_no],
  898. status="场景图处理完成",
  899. msg_type="scene_progress",
  900. progress=product_scene_progress
  901. )
  902. except Exception as e:
  903. os.remove(save_image_path)
  904. handler_result.append(
  905. {
  906. "goods_art_no": goods_art_no,
  907. "success": False,
  908. "info": f"场景图处理失败:{e}",
  909. }
  910. )
  911. product_scene_error_progress +=1
  912. product_scene_progress = {"status":"正在处理场景图", "current":product_scene_finish_progress, "total":product_scene_total_progress, "error":product_scene_error_progress}
  913. await sendAsyncMessage(
  914. msg="场景图处理失败",
  915. goods_arts=[goods_art_no],
  916. status="场景图处理失败",
  917. msg_type="scene_progress",
  918. progress=product_scene_progress
  919. )
  920. product_scene_progress = {"status":"正在处理场景图", "current":product_scene_finish_progress, "total":product_scene_total_progress, "error":product_scene_error_progress}
  921. await sendAsyncMessage(
  922. msg="场景图处理结束",
  923. goods_arts=[],
  924. status="场景图处理结束",
  925. msg_type="scene_progress",
  926. progress=product_scene_progress
  927. )
  928. if new_goods_dict is not None or new_goods_dict != {}:
  929. return_data_check_before_detail["data"][
  930. "goods_no_dict"
  931. ] = new_goods_dict
  932. if is_upper_footer == 1:
  933. goods_dict = parserGoodsDict2Aigc(return_data_check_before_detail)
  934. new_goods_dict = {}
  935. upper_footer_total_progress = len(goods_dict.keys())
  936. upper_footer_finish_progress = 0
  937. upper_footer_error_progress = 0
  938. upper_footer_progress = {"status":"开始处理模特图", "current":upper_footer_finish_progress, "total":upper_footer_total_progress, "error":upper_footer_error_progress}
  939. await sendAsyncMessage(
  940. msg="开始处理模特图",
  941. goods_arts=list(goods_dict.keys()),
  942. status="开始处理模特图",
  943. msg_type="upper_footer_progress",
  944. progress=upper_footer_progress
  945. )
  946. for goods_art_no in goods_dict.keys():
  947. goods_art_dict_info = goods_dict[goods_art_no]
  948. first_goods_art_no_info = goods_art_dict_info.get("货号资料", [])[0]
  949. first_pics = first_goods_art_no_info.get("pics")
  950. gender = goods_art_dict_info.get("性别")
  951. model_id = man_id if "男" in gender else women_id
  952. ceshi_image_path = first_pics.get("侧视-抠图")
  953. save_root_path = ceshi_image_path.split("阴影图处理")[0]
  954. save_image_path = f"{save_root_path}模特图.jpg"
  955. if os.path.isfile(save_image_path):
  956. goods_art_dict_info["模特图"] = save_image_path
  957. new_goods_dict[goods_art_no] = goods_art_dict_info
  958. continue
  959. shutil.copy(ceshi_image_path, save_image_path)
  960. try:
  961. image_path = aigc_clazz.generateUpperShoes(
  962. save_image_path, model_id, save_image_path
  963. )
  964. # image_path = aigc_clazz.generateModelShoesQW(
  965. # save_image_path, model_id, save_image_path
  966. # )
  967. goods_art_dict_info["模特图"] = image_path
  968. new_goods_dict[goods_art_no] = goods_art_dict_info
  969. handler_result.append(
  970. {
  971. "goods_art_no": goods_art_no,
  972. "success": True,
  973. "info": "模特图处理成功",
  974. }
  975. )
  976. upper_footer_finish_progress+=1
  977. upper_footer_progress = {"status":"正在处理模特图", "current":upper_footer_finish_progress, "total":upper_footer_total_progress, "error":upper_footer_error_progress}
  978. await sendAsyncMessage(
  979. msg="模特图处理成功",
  980. goods_arts=[goods_art_no],
  981. status="模特图处理成功",
  982. msg_type="upper_footer_progress",
  983. progress=upper_footer_progress
  984. )
  985. except Exception as e:
  986. os.remove(save_image_path)
  987. handler_result.append(
  988. {
  989. "goods_art_no": goods_art_no,
  990. "success": False,
  991. "info": f"模特图处理失败:{e}",
  992. }
  993. )
  994. upper_footer_error_progress+=1
  995. upper_footer_progress = {"status":"正在处理模特图", "current":upper_footer_finish_progress, "total":upper_footer_total_progress, "error":upper_footer_error_progress}
  996. await sendAsyncMessage(
  997. msg="模特图处理失败",
  998. goods_arts=[goods_art_no],
  999. status="模特图处理失败",
  1000. msg_type="upper_footer_progress",
  1001. progress=upper_footer_progress
  1002. )
  1003. upper_footer_progress = {"status":"模特图处理结束", "current":upper_footer_finish_progress, "total":upper_footer_total_progress, "error":upper_footer_error_progress}
  1004. await sendAsyncMessage(
  1005. msg="模特图处理结束",
  1006. goods_arts=[],
  1007. status="模特图处理结束",
  1008. msg_type="scene_progress",
  1009. progress=upper_footer_progress
  1010. )
  1011. if new_goods_dict is not None or new_goods_dict != {}:
  1012. return_data_check_before_detail["data"][
  1013. "goods_no_dict"
  1014. ] = new_goods_dict
  1015. if is_detail == 0:
  1016. await sendAsyncMessage(
  1017. msg="处理结束",
  1018. data={"output_folder": handler_result_folder, "list": handler_result},
  1019. status="处理结束",
  1020. msg_type="detail_result_progress",
  1021. )
  1022. return True
  1023. detail_total_progress = len(goods_dict.keys())
  1024. detail_finish_progress = 0
  1025. detail_error_progress = 0
  1026. detail_progress = {"status":"开始处理详情页", "current":detail_finish_progress, "total":detail_total_progress, "error":detail_error_progress}
  1027. await sendAsyncMessage(
  1028. msg="开始处理详情页",
  1029. goods_arts=[],
  1030. status="开始处理详情页",
  1031. msg_type="detail_progress",
  1032. progress=detail_progress
  1033. )
  1034. check_for_detail_first_res = run_main.check_for_detail_first_call_back(
  1035. return_data_check_before_detail
  1036. )
  1037. if isinstance(check_for_detail_first_res, partial):
  1038. result = check_for_detail_first_res()
  1039. try:
  1040. config_data = result["config_data"]
  1041. except:
  1042. config_data = result
  1043. if config_data["sign_text"] == "已结束详情处理":
  1044. detail_finish_progress = len(config_data["success_handler"])
  1045. detail_error_progress = detail_total_progress - detail_finish_progress
  1046. detail_progress = {"status":"详情页处理结束", "current":detail_finish_progress, "total":detail_total_progress, "error":detail_error_progress}
  1047. await sendAsyncMessage(
  1048. msg="详情页处理结束",
  1049. goods_arts=[],
  1050. status="详情页处理结束",
  1051. msg_type="detail_progress",
  1052. progress=detail_progress
  1053. )
  1054. print("config_data", config_data)
  1055. out_put_dir = config_data.get("out_put_dir")
  1056. if out_put_dir == None:
  1057. handler_result_folder = ""
  1058. if len(config_data["success_handler"]) > 0:
  1059. for good_art in config_data["success_handler"]:
  1060. handler_result.append(good_art)
  1061. else:
  1062. for good_art in goods_art_no_arrays:
  1063. handler_result.append(
  1064. {
  1065. "goods_art_no": good_art,
  1066. "success": False,
  1067. "info": "处理失败",
  1068. }
  1069. )
  1070. else:
  1071. out_put_dir_path = "{}/{}".format(os.getcwd(), out_put_dir).replace(
  1072. "\\", "/"
  1073. )
  1074. handler_result_folder = os.path.dirname(out_put_dir_path)
  1075. if len(config_data["success_handler"]) == 0:
  1076. for good_art in goods_art_no_arrays:
  1077. handler_result.append(
  1078. {
  1079. "goods_art_no": good_art,
  1080. "success": False,
  1081. "info": "处理失败",
  1082. }
  1083. )
  1084. else:
  1085. if len(online_stores) > 0:
  1086. result_goods_no_dict = return_data_check_before_detail["data"][
  1087. "goods_no_dict"
  1088. ]
  1089. for goods_idx, goods_no_dict in enumerate(
  1090. result_goods_no_dict.keys()
  1091. ):
  1092. all_detail_path_list = config_data["all_detail_path_list"]
  1093. for detail_path in all_detail_path_list:
  1094. if goods_no_dict in detail_path:
  1095. detail_path_replace = detail_path.replace("\\", "/")
  1096. result_goods_no_dict[goods_no_dict][
  1097. "detail_path"
  1098. ] = f"{detail_path_replace}/详情页.jpg"
  1099. upload_total_progress = len(goods_dict.keys())
  1100. upload_finish_progress = 0
  1101. upload_error_progress = 0
  1102. upload_progress = {"status":"开始上传商品数据", "current":upload_finish_progress, "total":upload_total_progress, "error":upload_error_progress}
  1103. await sendAsyncMessage(
  1104. msg="开始上传商品数据",
  1105. goods_arts=[],
  1106. status="开始上传商品数据",
  1107. msg_type="upload_goods_progress",
  1108. progress=upload_progress
  1109. )
  1110. try:
  1111. onlineData.uploadGoods2ThirdParty(
  1112. result_goods_no_dict, online_stores=online_stores
  1113. )
  1114. except Exception as e:
  1115. upload_error_progress = upload_total_progress
  1116. print(f"上传任务出现错误:{e}")
  1117. upload_finish_progress = upload_total_progress
  1118. if upload_error_progress > 0:
  1119. upload_finish_progress = 0
  1120. upload_progress = {"status":"开始上传商品数据", "current":upload_finish_progress, "total":upload_total_progress, "error":upload_error_progress}
  1121. await sendAsyncMessage(
  1122. msg="商品上传第三方成功",
  1123. goods_arts=[],
  1124. status="商品上传第三方成功",
  1125. msg_type="upload_goods_progress",
  1126. progress=upload_progress
  1127. )
  1128. handler_result = config_data["success_handler"]
  1129. else:
  1130. handler_result.append(
  1131. {"goods_art_no": "", "success": False, "info": "处理失败"}
  1132. )
  1133. except UnicornException as e:
  1134. handler_result_folder = ""
  1135. handler_result.append(
  1136. {"goods_art_no": "", "success": False, "info": str(e.msg)}
  1137. )
  1138. print(f"UnicornException 生成错误信息:{e}")
  1139. except Exception as e:
  1140. print(f"详情图生成错误信息:{e}")
  1141. handler_result_folder = ""
  1142. handler_result.append({"goods_art_no": "", "success": False, "info": str(e)})
  1143. await sendAsyncMessage(
  1144. msg="处理结束",
  1145. data={"output_folder": handler_result_folder, "list": handler_result},
  1146. status="处理结束",
  1147. msg_type="detail_result_progress",
  1148. )
  1149. return True
  1150. @app.get("/get_device_tabs", description="获取可执行程序命令列表")
  1151. def get_device_tabs(type: int):
  1152. session = SqlQuery()
  1153. statement = (
  1154. select(DeviceConfigTabs)
  1155. .where(DeviceConfigTabs.mode_type == type)
  1156. .order_by(asc("id"))
  1157. )
  1158. result = session.exec(statement).all()
  1159. session.close()
  1160. sys = CRUD(SysConfigs)
  1161. action_configs = sys.read(session, conditions={"key": "action_configs"})
  1162. session.close()
  1163. return {
  1164. "code": 0,
  1165. "msg": "",
  1166. "data": {"tabs": result, "select_configs": json.loads(action_configs.value)},
  1167. }
  1168. @app.post("/update_tab_name", description="更改tab名称")
  1169. def update_tab_name(params: DeviceConfigTabsReq):
  1170. if params.mode_name == "":
  1171. return {"code": 1, "msg": "名称不能为空", "data": {}}
  1172. session = SqlQuery()
  1173. tabModel = CRUD(DeviceConfigTabs)
  1174. kwargs = {"mode_name": params.mode_name}
  1175. tabModel.updateConditions(session, conditions={"id": params.id}, **kwargs)
  1176. session.close()
  1177. return {
  1178. "code": 0,
  1179. "msg": "",
  1180. "data": None,
  1181. }
  1182. @app.post("/get_device_configs", description="获取可执行程序命令列表")
  1183. def get_device_configs(params: ModelGetDeviceConfig):
  1184. tab_id = params.tab_id
  1185. session = SqlQuery()
  1186. configModel = CRUD(DeviceConfig)
  1187. configList = configModel.read_all(
  1188. session,
  1189. conditions={"tab_id": tab_id},
  1190. order_by="action_index",
  1191. ascending=True,
  1192. )
  1193. return {
  1194. "code": 0,
  1195. "msg": "",
  1196. "data": {"list": configList},
  1197. }
  1198. @app.post("/device_config_detail", description="获取可执行程序详情")
  1199. def device_config_detail(params: ModelGetDeviceConfigDetail):
  1200. action_id = params.id
  1201. session = SqlQuery()
  1202. configModel = CRUD(DeviceConfig)
  1203. model = configModel.read(session, conditions={"id": action_id})
  1204. if model == None:
  1205. return {"code": 1, "msg": "数据不存在", "data": None}
  1206. return {"code": 0, "msg": "", "data": model}
  1207. @app.post("/device_config_detail_query", description="通过条件获取可执行程序详情")
  1208. def device_config_detail_query():
  1209. # tab_id = params.tab_id
  1210. # action_name = params.action_name
  1211. session = SqlQuery()
  1212. sys = CRUD(SysConfigs)
  1213. action_configs = sys.read(session, conditions={"key": "action_configs"})
  1214. action_configs_value = json.loads(action_configs.value)
  1215. left_config = action_configs_value.get("left")
  1216. configModel = CRUD(DeviceConfig)
  1217. model = configModel.read(
  1218. session, conditions={"tab_id": left_config, "action_name": "侧视"}
  1219. )
  1220. if model == None:
  1221. model = configModel.read(session, conditions={"tab_id": left_config})
  1222. return {"code": 0, "msg": "", "data": model}
  1223. @app.post("/remove_config", description="删除一条可执行命令")
  1224. def get_device_configs(params: ModelGetDeviceConfigDetail):
  1225. action_id = params.id
  1226. session = SqlQuery()
  1227. configModel = CRUD(DeviceConfig)
  1228. model = configModel.read(session, conditions={"id": action_id})
  1229. if model == None:
  1230. return {"code": 1, "msg": "数据不存在", "data": None}
  1231. if model.is_system == True:
  1232. return {"code": 1, "msg": "系统配置不允许删除", "data": None}
  1233. configArray = configModel.read_all(session, conditions={"tab_id": model.tab_id})
  1234. if len(configArray) == 1:
  1235. return {"code": 1, "msg": "请至少保留一个配置", "data": None}
  1236. configModel.delete(session, obj_id=action_id)
  1237. return {"code": 0, "msg": "删除成功", "data": None}
  1238. @app.post("/save_device_config", description="创建或修改一条可执行命令")
  1239. def save_device_config(params: SaveDeviceConfig):
  1240. action_id = params.id
  1241. session = SqlQuery()
  1242. deviceConfig = CRUD(DeviceConfig)
  1243. if action_id == None or action_id == 0:
  1244. # 走新增逻辑
  1245. params.id = None
  1246. save_device_config = deviceConfig.create(session, obj_in=params)
  1247. else:
  1248. model = deviceConfig.read(session, conditions={"id": action_id})
  1249. if model == None:
  1250. return {"code": 1, "msg": "数据不存在", "data": None}
  1251. # 走编辑逻辑
  1252. kwargs = params.__dict__
  1253. save_device_config = deviceConfig.update(session, obj_id=action_id, **kwargs)
  1254. return {"code": 0, "msg": "操作成功", "data": save_device_config}
  1255. @app.post("/reset_config", description="创建或修改一条可执行命令")
  1256. def reset_config(params: ModelGetDeviceConfig):
  1257. tab_id = params.tab_id
  1258. if tab_id == None or tab_id == "":
  1259. return {"code": 1, "msg": "参数错误", "data": None}
  1260. session = SqlQuery()
  1261. deviceConfig = CRUD(DeviceConfig)
  1262. first_config = deviceConfig.read(session, conditions={"tab_id": tab_id})
  1263. res = deviceConfig.deleteConditions(session, conditions={"tab_id": tab_id})
  1264. if res is False:
  1265. return {"code": 1, "msg": "操作失败", "data": None}
  1266. actions = json.load(open("action.json", encoding="utf-8"))
  1267. for data in actions:
  1268. data["tab_id"] = tab_id
  1269. data["is_system"] = first_config.is_system
  1270. device_config = DeviceConfig(**data)
  1271. session.add(device_config)
  1272. session.commit()
  1273. # session.close()
  1274. return {"code": 0, "msg": "操作成功", "data": None}
  1275. @app.get("/get_photo_records", description="获取拍照记录")
  1276. def get_photo_records(page: int = 1, size: int = 5):
  1277. session = SqlQuery()
  1278. # photos = CRUD(PhotoRecord)
  1279. print("准备查询拍摄记录", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
  1280. statement = (
  1281. select(PhotoRecord)
  1282. .offset((page - 1) * size)
  1283. .limit(size)
  1284. .order_by(desc("id"))
  1285. .group_by("goods_art_no")
  1286. )
  1287. list = []
  1288. result = session.exec(statement).all()
  1289. print("group 完成 ", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
  1290. join_conditions = [
  1291. {
  1292. "model": DeviceConfig,
  1293. "on": PhotoRecord.action_id == DeviceConfig.id,
  1294. "is_outer": False, # 可选,默认False,设为True则为LEFT JOIN
  1295. }
  1296. ]
  1297. for item in result:
  1298. query = (
  1299. select(PhotoRecord, DeviceConfig.action_name)
  1300. .where(PhotoRecord.goods_art_no == item.goods_art_no)
  1301. .join(DeviceConfig, PhotoRecord.action_id == DeviceConfig.id)
  1302. )
  1303. list_item = session.exec(query).mappings().all()
  1304. list.append(
  1305. {
  1306. "goods_art_no": item.goods_art_no,
  1307. "action_time": item.create_time,
  1308. "items": list_item,
  1309. }
  1310. )
  1311. # session.close()
  1312. print("循环查询 完成 ", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
  1313. return {
  1314. "code": 0,
  1315. "msg": "",
  1316. "data": {"list": list, "page": page, "size": size},
  1317. }
  1318. @app.get("/get_last_photo_record", description="获取最后一条拍照记录")
  1319. def get_last_photo_record():
  1320. session = SqlQuery()
  1321. statement = (
  1322. select(PhotoRecord)
  1323. .where(PhotoRecord.image_path != None)
  1324. .order_by(desc("photo_create_time"))
  1325. )
  1326. result = session.exec(statement).first()
  1327. # session.close()
  1328. return {
  1329. "code": 0,
  1330. "msg": "",
  1331. "data": result,
  1332. }
  1333. @app.get("/get_photo_record_detail", description="通过货号获取拍照记录详情")
  1334. def get_photo_record_detail(goods_art_no: str = None):
  1335. if goods_art_no == None:
  1336. return {"code": 1, "msg": "参数错误", "data": None}
  1337. session = SqlQuery()
  1338. photos = CRUD(PhotoRecord)
  1339. items = photos.read_all(session, conditions={"goods_art_no": goods_art_no})
  1340. # session.close()
  1341. return {
  1342. "code": 0,
  1343. "msg": "",
  1344. "data": {"list": items},
  1345. }
  1346. @app.post("/delect_goods_arts", description="通过货号删除记录")
  1347. def delect_goods_arts(params: PhotoRecordDelete):
  1348. session = SqlQuery()
  1349. photos = CRUD(PhotoRecord)
  1350. for item in params.goods_art_nos:
  1351. photos.deleteConditions(session, conditions={"goods_art_no": item})
  1352. # session.close()
  1353. return {
  1354. "code": 0,
  1355. "msg": "操作成功",
  1356. "data": None,
  1357. }
  1358. def query_config_by_key(key_name):
  1359. """
  1360. 在sys_configs.json格式的数据中查询指定的key,如果匹配则返回整个对象
  1361. Args:
  1362. key_name (str): 要查询的key名称
  1363. Returns:
  1364. dict or None: 匹配的对象或None(如果没有找到)
  1365. """
  1366. try:
  1367. # 获取所有配置数据
  1368. configs = json.load(open("sys_configs.json", encoding="utf-8"))
  1369. # 遍历配置数据查找匹配的key
  1370. for config in configs:
  1371. if config.get("key") == key_name:
  1372. return config
  1373. return None
  1374. except Exception as e:
  1375. print(f"查询配置时出错: {e}")
  1376. return None
  1377. @app.get("/get_sys_config", description="查询系统配置")
  1378. def get_sys_config(key: str = None):
  1379. if key == None:
  1380. return {"code": 1, "msg": "参数错误", "data": None}
  1381. session = SqlQuery()
  1382. photos = CRUD(SysConfigs)
  1383. item = photos.read(session, conditions={"key": key})
  1384. search_data = None if item == None else json.loads(item.value)
  1385. if search_data == None:
  1386. sys_config_json = query_config_by_key(key)
  1387. if sys_config_json != None:
  1388. config = SysConfigs(**sys_config_json)
  1389. session.add(config)
  1390. session.commit() # 合并事务提交
  1391. search_data = json.loads(sys_config_json.get("value"))
  1392. return {
  1393. "code": 0,
  1394. "msg": "",
  1395. "data": search_data,
  1396. }
  1397. @app.post("/update_left_right_config", description="更新左右脚配置")
  1398. def update_left_right_config(params: LeftRightParams):
  1399. session = SqlQuery()
  1400. sysConfig = CRUD(SysConfigs)
  1401. model = sysConfig.read(session, conditions={"key": "action_configs"})
  1402. if model == None:
  1403. return {"code": 1, "msg": "配置不存在", "data": None}
  1404. config_value = json.loads(model.value)
  1405. config_value[params.type] = params.id
  1406. update_value = json.dumps(config_value)
  1407. # 走编辑逻辑
  1408. kwargs = {"key": "action_configs", "value": update_value}
  1409. save_device_config = sysConfig.updateConditions(
  1410. session, conditions={"key": "action_configs"}, **kwargs
  1411. )
  1412. return {"code": 0, "msg": "操作成功", "data": None}
  1413. @app.post("/update_record", description="更新拍照记录")
  1414. def update_record(params: RecordUpdate):
  1415. session = SqlQuery()
  1416. photoRecord = CRUD(PhotoRecord)
  1417. model = photoRecord.read(session, conditions={"id": params.id})
  1418. if model == None:
  1419. return {"code": 1, "msg": "记录不存在", "data": None}
  1420. kwargs = params.__dict__
  1421. save_device_config = photoRecord.update(session, obj_id=params.id, **kwargs)
  1422. return {"code": 0, "msg": "操作成功", "data": save_device_config}
  1423. @app.post("/update_sys_configs", description="创建或修改系统配置")
  1424. def save_sys_configs(params: SysConfigParams):
  1425. session = SqlQuery()
  1426. sysConfig = CRUD(SysConfigs)
  1427. model = sysConfig.read(session, conditions={"key": params.key})
  1428. if model == None:
  1429. return {"code": 1, "msg": "配置不存在", "data": None}
  1430. # 走编辑逻辑
  1431. kwargs = params.__dict__
  1432. save_device_config = sysConfig.updateConditions(
  1433. session, conditions={"key": params.key}, **kwargs
  1434. )
  1435. return {"code": 0, "msg": "操作成功", "data": save_device_config}
  1436. @app.post("/create_main_image", description="创建主图测试")
  1437. def create_main_image(params: MaineImageTest):
  1438. file_path = params.file_path
  1439. onePic = OnePicTest(pic_path=file_path)
  1440. main_out_path = onePic.HandlerMainImage()
  1441. return {"code": 0, "msg": "操作成功", "data": {"main_out_path": main_out_path}}
  1442. def insertEmptyLogoList(session):
  1443. """插入空logo列表"""
  1444. data = {"key": "logo_configs", "value": "[]"}
  1445. config = SysConfigs(**data)
  1446. session.add(config)
  1447. session.commit()
  1448. session.close()
  1449. item = SysConfigs()
  1450. item.key = "logo_configs"
  1451. item.value = "[]"
  1452. return item
  1453. @app.get("/logo_list", description="logo列表")
  1454. def logo_list():
  1455. logo_dir = "{}/data/logo/".format(os.getcwd()).replace("\\", "/")
  1456. check_path(logo_dir)
  1457. logo_files = os.listdir(logo_dir)
  1458. logo_list = []
  1459. for logoItem in logo_files:
  1460. logo_list.append(f"{logo_dir}{logoItem}")
  1461. return {"code": 0, "msg": "操作成功", "data": logo_list}
  1462. @app.post("/add_logo", description="添加logo")
  1463. def add_logo(params: LogoParams):
  1464. logo_path = params.logo_path.replace("\\", "/")
  1465. session = SqlQuery()
  1466. sysConfig = CRUD(SysConfigs)
  1467. item = sysConfig.read(session, conditions={"key": "logo_configs"})
  1468. if item == None:
  1469. item = insertEmptyLogoList(session)
  1470. if os.path.isfile(logo_path) == False:
  1471. return {"code": 1, "msg": "logo文件不存在", "data": None}
  1472. logo_dir = "{}/data/logo/".format(os.getcwd()).replace("\\", "/")
  1473. check_path(logo_dir)
  1474. fpath, fname = os.path.split(logo_path)
  1475. logo_path_info = logo_dir + fname
  1476. shutil.copy(logo_path, logo_path_info) # 复制文件
  1477. logo_files = os.listdir(logo_dir)
  1478. logo_list = []
  1479. for logoItem in logo_files:
  1480. logo_list.append(f"{logo_dir}{logoItem}")
  1481. return {
  1482. "code": 0,
  1483. "msg": "",
  1484. "data": {"logo": logo_path_info},
  1485. }
  1486. @app.post("/delete_logo", description="删除logo")
  1487. def delete_logo(params: LogoParamsupdate):
  1488. logo_path = params.path
  1489. if os.path.isfile(logo_path) == False:
  1490. return {"code": 1, "msg": "logo文件不存在", "data": None}
  1491. os.remove(logo_path)
  1492. logo_dir = "{}/data/logo/".format(os.getcwd()).replace("\\", "/")
  1493. check_path(logo_dir)
  1494. logo_files = os.listdir(logo_dir)
  1495. logo_list = []
  1496. for logoItem in logo_files:
  1497. logo_list.append(f"{logo_dir}{logoItem}")
  1498. return {"code": 0, "msg": "操作成功", "data": logo_list}
  1499. @app.post("/close_other_window", description="关闭窗口")
  1500. def close_other_window():
  1501. hwnd_list = []
  1502. def callback(hwnd, _):
  1503. title = GetWindowText(hwnd)
  1504. if title == "digiCamControl by Duka Istvan":
  1505. hwnd_list.append(hwnd)
  1506. EnumWindows(callback, None)
  1507. if hwnd_list:
  1508. hwnd = hwnd_list[0]
  1509. win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0)
  1510. return {"code": 0, "msg": "关闭成功", "data": {"status": True}}
  1511. return {"code": 0, "msg": "关闭失败", "data": {"status": False}}
  1512. def syncUserJsonConfigs(token):
  1513. hlm_token = token
  1514. headers = {
  1515. "Authorization": f"Bearer {hlm_token}",
  1516. "content-type": "application/json",
  1517. }
  1518. url = settings.DOMAIN + "/api/ai_image/camera_machine/get_all_user_configs"
  1519. result = requests.get(url=url, headers=headers)
  1520. sys_configs = result.json().get("data", {}).get("configs")
  1521. session = SqlQuery()
  1522. sysConfigs = CRUD(SysConfigs)
  1523. if sys_configs:
  1524. sysConfigs.deleteConditions(session, {})
  1525. configList = []
  1526. for config_keys in sys_configs.keys():
  1527. sys_configs[config_keys]
  1528. configList.append(
  1529. {
  1530. "key": config_keys,
  1531. "value": json.dumps(sys_configs[config_keys], ensure_ascii=False),
  1532. }
  1533. )
  1534. batch_insert_sys_configs(session, configList)
  1535. @app.post("/sync_sys_configs", description="同步线上配置到本地")
  1536. def sync_sys_configs(params: SyncLocalConfigs):
  1537. hlm_token = params.token
  1538. headers = {
  1539. "Authorization": f"Bearer {hlm_token}",
  1540. "content-type": "application/json",
  1541. }
  1542. url = settings.DOMAIN + "/api/ai_image/camera_machine/get_all_user_configs"
  1543. result = requests.get(url=url, headers=headers)
  1544. sys_configs = result.json().get("data", {}).get("configs")
  1545. session = SqlQuery()
  1546. sysConfigs = CRUD(SysConfigs)
  1547. if sys_configs:
  1548. sysConfigs.deleteConditions(session, {})
  1549. configList = []
  1550. for config_keys in sys_configs.keys():
  1551. sys_configs[config_keys]
  1552. configList.append(
  1553. {
  1554. "key": config_keys,
  1555. "value": json.dumps(sys_configs[config_keys], ensure_ascii=False),
  1556. }
  1557. )
  1558. batch_insert_sys_configs(session, configList)
  1559. else:
  1560. all_configs = sysConfigs.read_all(session)
  1561. localConfigData = {}
  1562. for local_config in all_configs:
  1563. localConfigData[local_config.key] = json.loads(local_config.value)
  1564. data_json = json.dumps({"configs": localConfigData}, ensure_ascii=False)
  1565. # 同步本地到线上
  1566. url = settings.DOMAIN + "/api/ai_image/camera_machine/update_all_user_configs"
  1567. requests.post(url=url, headers=headers, data=data_json)
  1568. return {"code": 0, "msg": "操作成功", "data": None}
  1569. @app.post("/sync_actions", description="同步左右脚配置到本地")
  1570. def sync_action_configs(params: SyncLocalConfigs):
  1571. hlm_token = params.token
  1572. headers = {
  1573. "Authorization": f"Bearer {hlm_token}",
  1574. "content-type": "application/json",
  1575. }
  1576. url = settings.DOMAIN + "/api/ai_image/camera_machine/get_all_user_tabs"
  1577. result = requests.get(url=url, headers=headers)
  1578. session = SqlQuery()
  1579. deviceConfigs = CRUD(DeviceConfig)
  1580. deviceConfigTabs = CRUD(DeviceConfigTabs)
  1581. tabs = result.json().get("data", {}).get("tabs")
  1582. actions = result.json().get("data", {}).get("actions")
  1583. if tabs:
  1584. # 先删除再创建
  1585. deviceConfigTabs.deleteConditions(session, {})
  1586. deviceConfigs.deleteConditions(session, {})
  1587. batch_insert_device_configsNew(session, tabs, actions)
  1588. else:
  1589. all_actions = deviceConfigs.read_all(session)
  1590. all_tabs = deviceConfigTabs.read_all(session)
  1591. all_tabs_json = [item.model_dump(mode='json') for item in all_tabs]
  1592. all_actions_json = [item.model_dump(mode="json") for item in all_actions]
  1593. data_json = json.dumps(
  1594. {"tabs": all_tabs_json, "actions": all_actions_json}, ensure_ascii=False
  1595. )
  1596. sync_url = settings.DOMAIN + "/api/ai_image/camera_machine/sync_actions"
  1597. result = requests.post(url=sync_url, headers=headers, data=data_json)
  1598. tabs = result.json().get("data", {}).get("tabs")
  1599. actions = result.json().get("data", {}).get("actions")
  1600. insert_action_ids = result.json().get("data", {}).get("insert_action_ids")
  1601. if tabs:
  1602. deviceConfigTabs.deleteConditions(session, {})
  1603. deviceConfigs.deleteConditions(session, {})
  1604. batch_insert_device_configsNew(session, tabs, actions)
  1605. if insert_action_ids:
  1606. for action_item in insert_action_ids:
  1607. photos = CRUD(PhotoRecord)
  1608. old_id = action_item.get("old_id")
  1609. new_id = action_item.get("new_id")
  1610. kwargs = {"action_id": new_id}
  1611. photos.updateConditionsAll(
  1612. session, conditions={"action_id": old_id}, **kwargs
  1613. )
  1614. # 因为左右脚线上id可能会发生变化 所以需要重新同步一下本地得配置信息
  1615. # syncUserJsonConfigs(hlm_token)
  1616. return {"code": 0, "msg": "操作成功", "data": None}