api.py 83 KB

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