module_online_data.py 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. import base64
  2. import requests
  3. import settings
  4. import json, asyncio
  5. import numpy as np
  6. from utils.common import message_queue
  7. from middleware import UnicornException
  8. from PIL import Image
  9. import io, time
  10. from logger import logger
  11. # logger = logging.getLogger(__name__)
  12. class JsonEncoder(json.JSONEncoder):
  13. """Convert numpy classes to JSON serializable objects."""
  14. def default(self, obj):
  15. if isinstance(obj, (np.integer, np.floating, np.bool_)):
  16. return obj.item()
  17. elif isinstance(obj, np.ndarray):
  18. return obj.tolist()
  19. else:
  20. return super(JsonEncoder, self).default(obj)
  21. def download_image_with_pil(url, save_path):
  22. """通过url保存图片"""
  23. try:
  24. # 发送请求获取图片数据
  25. response = requests.get(url)
  26. image_data = response.content
  27. # 使用PIL处理下载的图片
  28. image = Image.open(io.BytesIO(image_data))
  29. image = image.convert("RGB")
  30. # 根据当前时间生成文件名
  31. # 保存图片
  32. image.save(save_path)
  33. return save_path
  34. except Exception as e:
  35. print("保存错误",e)
  36. return "error"
  37. class AIGCDataRequest(object):
  38. def __init__(self, token):
  39. self.s = requests.session()
  40. self.token = token
  41. self.post_headers = {
  42. "Authorization": token,
  43. }
  44. def uploadImage(self, local_path: str) -> str:
  45. post_headers = {"Authorization": self.token}
  46. url = settings.DOMAIN + "/api/upload"
  47. resultData = self.s.post(
  48. url, files={"file": open(local_path, "rb")}, headers=post_headers
  49. ).json()
  50. return resultData["data"]["url"]
  51. def center_paste_image(
  52. self, source_image_path, output_path, width=900, ratio=(3, 4)
  53. ):
  54. """
  55. 将一张PNG透明图片居中粘贴到指定尺寸和比例的背景上,保持透明度
  56. Args:
  57. source_image_path: 源PNG图片路径
  58. output_path: 输出图片路径
  59. width: 目标图片宽度
  60. ratio: 目标图片比例 (宽:高)
  61. """
  62. # 计算目标尺寸 (900 x 1200)
  63. target_width = width
  64. target_height = int(width * ratio[1] / ratio[0])
  65. # 创建透明背景图片(RGBA模式)
  66. background = Image.new(
  67. "RGBA", (target_width, target_height), (255, 255, 255, 0)
  68. )
  69. # 打开源图片
  70. source_img = Image.open(source_image_path)
  71. # 确保源图片是RGBA模式以保持透明度
  72. if source_img.mode != "RGBA":
  73. source_img = source_img.convert("RGBA")
  74. # 调整源图片大小以适应目标尺寸,保持原图比例
  75. source_width, source_height = source_img.size
  76. scale = min(target_width / source_width, target_height / source_height)
  77. new_width = int(source_width * scale)
  78. new_height = int(source_height * scale)
  79. # 调整源图片尺寸
  80. source_img_resized = source_img.resize(
  81. (new_width, new_height), Image.Resampling.LANCZOS
  82. )
  83. # 计算居中粘贴位置
  84. paste_x = (target_width - new_width) // 2
  85. paste_y = (target_height - new_height) // 2
  86. # 将调整后的源图片居中粘贴到背景上,保留透明度
  87. background.paste(source_img_resized, (paste_x, paste_y), source_img_resized)
  88. # 如果需要保存为PNG格式以保持透明度
  89. if output_path.lower().endswith(".png"):
  90. background.save(output_path, format="PNG")
  91. else:
  92. # 如果保存为JPG等不支持透明度的格式,转换为RGB并使用白色背景
  93. background = background.convert("RGB")
  94. background.save(output_path)
  95. source_img.close()
  96. return background
  97. def generateProductScene(self, local_path, prompt, save_path):
  98. imageUrl = self.uploadImage(local_path)
  99. print("imageUrl", imageUrl)
  100. data = {
  101. "site": 1,
  102. "base_image": imageUrl,
  103. "keyword": prompt,
  104. "model_type": 1,
  105. "gemini_model": "gemini-2.5-flash-image-preview",
  106. }
  107. """生成场景图"""
  108. try:
  109. url = settings.DOMAIN + "/api/ai_image/inspired/command_to_image"
  110. resultData = self.s.post(url, data=data, headers=self.post_headers, timeout=80).json()
  111. code = resultData.get("code", 0)
  112. message = resultData.get("message", "")
  113. if code != 0:
  114. raise UnicornException(message)
  115. image_arr = resultData.get("data", None).get("image", [])
  116. if len(image_arr) == 0:
  117. raise UnicornException("场景图生成失败")
  118. image_url = image_arr[0]
  119. save_image_path = download_image_with_pil(image_url, save_path)
  120. return save_image_path
  121. except:
  122. raise UnicornException("场景图生成失败")
  123. def generateProductSceneQW(self, local_path, prompt, save_path):
  124. '''千问生成场景图'''
  125. imageUrl = self.uploadImage(local_path)
  126. data = {
  127. "machine_type": 0, # 0鞋;1服装
  128. "generate_type": 0, # 生成类型,这里指代得是场景图还是模特图;0场景图;1模特图
  129. "base_image": imageUrl,
  130. "prompt": prompt
  131. }
  132. """生成场景图"""
  133. url = settings.DOMAIN + "/api/ai_image/main/image_edit_generate"
  134. resultData = self.s.post(url, data=data, headers=self.post_headers).json()
  135. code = resultData.get("code", 0)
  136. message = resultData.get("message", "")
  137. if code != 0:
  138. raise UnicornException(message)
  139. image_url = resultData.get("data", None).get("image_url", '')
  140. if image_url == "" or image_url is None:
  141. raise UnicornException("场景图生成失败")
  142. save_image_path = download_image_with_pil(image_url, save_path)
  143. return save_image_path
  144. def generateModelShoesQW(self, local_path, model_id, save_path):
  145. '''千问生成场景图'''
  146. imageUrl = self.uploadImage(local_path)
  147. data = {
  148. "machine_type": 0, # 0鞋;1服装
  149. "generate_type": 1, # 生成类型,这里指代得是场景图还是模特图;0场景图;1模特图
  150. "base_image": imageUrl,
  151. "model_template_id": model_id,
  152. }
  153. """生成场景图"""
  154. url = settings.DOMAIN + "/api/ai_image/main/image_edit_generate"
  155. resultData = self.s.post(url, data=data, headers=self.post_headers).json()
  156. code = resultData.get("code", 0)
  157. message = resultData.get("message", "")
  158. if code != 0:
  159. raise UnicornException(message)
  160. image_url = resultData.get("data", None).get("image_url", '')
  161. if image_url == "" or image_url is None:
  162. raise UnicornException("模特图生成失败")
  163. save_image_path = download_image_with_pil(image_url, save_path)
  164. return save_image_path
  165. def searchProgress(self, id):
  166. """查询进度"""
  167. try:
  168. url = settings.DOMAIN + "/api/ai_image/main/search_bacth_progress"
  169. data = {"site": 1, "generate_ids": [id], "type": "aigc_pro"}
  170. resultData = self.s.post(url, json=data, headers=self.post_headers, timeout=10)
  171. resultData = resultData.json()
  172. code = resultData.get("code", 0)
  173. message = resultData.get("message", "")
  174. if code != 0:
  175. raise UnicornException(message)
  176. data_result = resultData.get("data", [])
  177. print("查询进度", data_result)
  178. logger.info(f"查询进度:{data_result}")
  179. if len(data_result) == 0:
  180. return -1, None
  181. data_item = data_result[0]
  182. status = data_item.get("status", -1)
  183. result_image = None
  184. # 只有在完成状态下才返回图片URL
  185. if status == 2: # 完成
  186. result_image_urls = data_item.get("result_image_urls", [])
  187. result_image_urls = [] if result_image_urls is None else result_image_urls
  188. result_image = result_image_urls[0] if len(result_image_urls) > 0 else None
  189. return status, result_image
  190. except requests.Timeout:
  191. print("查询进度超时")
  192. return -1, None
  193. except Exception as e:
  194. print(f"查询进度异常: {e}")
  195. return -1, None
  196. def generateUpperShoes(self, local_path, model_id, save_path):
  197. """生成上脚图"""
  198. print("生成上脚图", local_path, model_id, save_path)
  199. imageUrl = self.uploadImage(local_path)
  200. data = {
  201. "site": 1,
  202. "model_template_id": model_id,
  203. "base_image": imageUrl,
  204. "creatClass": "鞋子上脚图-鞋子上脚图",
  205. "creatTimer": 40,
  206. "pname": "OnFeetImage",
  207. }
  208. """生成上脚图"""
  209. url = settings.DOMAIN + "/api/ai_image/main/upper_footer"
  210. resultData = self.s.post(url, data=data, headers=self.post_headers).json()
  211. print("生成上脚图", resultData)
  212. code = resultData.get("code", 0)
  213. message = resultData.get("message", "")
  214. if code != 0:
  215. raise UnicornException(message)
  216. generate_ids = resultData.get("data", None).get("generate_ids", [])
  217. if len(generate_ids) == 0:
  218. raise UnicornException("模特图生成失败")
  219. generate_id = generate_ids[0]
  220. search_times = 80
  221. status = 0
  222. result_image = None
  223. print("generate_id", generate_id)
  224. while search_times > 0:
  225. print(f"模特图查询第{search_times}次")
  226. logger.info(f"模特图查询第{search_times}次")
  227. status, result_image = self.searchProgress(generate_id)
  228. # status: -1=失败, 0=排队中, 1=进行中, 2=完成
  229. if status == 2: # 完成
  230. break
  231. if status == -1: # 失败
  232. break
  233. # status为0(排队中)或1(进行中)时继续查询
  234. time.sleep(1)
  235. search_times -= 1
  236. # 循环结束后检查最终状态
  237. if status == -1 or (status != 2 and search_times <= 0):
  238. raise UnicornException("模特图生成失败")
  239. save_image_path = download_image_with_pil(result_image, save_path)
  240. print("上脚图save_image_path",result_image, save_image_path)
  241. return save_image_path
  242. def generateModelFitting(self, local_path, model_id, face_type, save_path):
  243. """生成上脚图"""
  244. imageUrl = self.uploadImage(local_path)
  245. data = {
  246. "site": 1,
  247. "scene_key": model_id,
  248. "topsImg": imageUrl,
  249. "generate_type": 1,
  250. "face_type": face_type,
  251. "pname": "ModelFitting_clothing",
  252. }
  253. print("生成上脚图", local_path, model_id, save_path)
  254. print("生成上脚图==>data", data)
  255. """生成上脚图"""
  256. url = settings.DOMAIN + "/api/ai_image/clothing/model_fitting_vk"
  257. resultData = self.s.post(url, data=data, headers=self.post_headers)
  258. # print("模特图resultData", resultData.content)
  259. resultData = resultData.json()
  260. code = resultData.get("code", 0)
  261. message = resultData.get("message", "")
  262. if code != 0:
  263. raise UnicornException(message)
  264. generate_ids = resultData.get("data", None).get("generate_ids", [])
  265. if len(generate_ids) == 0:
  266. raise UnicornException("模特图生成失败")
  267. generate_id = generate_ids[0]
  268. search_times = 80
  269. status = 0
  270. result_image = None
  271. while search_times > 0:
  272. print(f"查询第{search_times}次")
  273. status, result_image = self.searchProgress(generate_id)
  274. # status: -1=失败, 0=排队中, 1=进行中, 2=完成
  275. if status == 2: # 完成
  276. break
  277. if status == -1: # 失败
  278. break
  279. # status为0(排队中)或1(进行中)时继续查询
  280. time.sleep(1)
  281. search_times -= 1
  282. # 循环结束后检查最终状态
  283. if status == -1 or (status != 2 and search_times <= 0):
  284. raise UnicornException("模特图生成失败")
  285. save_image_path = download_image_with_pil(result_image, save_path)
  286. print("上脚图save_image_path",result_image, save_image_path)
  287. return save_image_path
  288. def generateProductSceneQW(self, local_path, prompt, save_path):
  289. """千问生成场景图"""
  290. imageUrl = self.uploadImage(local_path)
  291. data = {
  292. "machine_type": 1, # 0鞋;1服装
  293. "generate_type": 0, # 生成类型,这里指代得是场景图还是模特图;0场景图;1模特图
  294. "base_image": imageUrl,
  295. "prompt": prompt,
  296. }
  297. """生成场景图"""
  298. url = settings.DOMAIN + "/api/ai_image/main/image_edit_generate"
  299. resultData = self.s.post(url, data=data, headers=self.post_headers).json()
  300. code = resultData.get("code", 0)
  301. message = resultData.get("message", "")
  302. if code != 0:
  303. raise UnicornException(message)
  304. image_url = resultData.get("data", None).get("image_url", "")
  305. if image_url == "" or image_url is None:
  306. raise UnicornException("场景图生成失败")
  307. save_image_path = download_image_with_pil(image_url, save_path)
  308. return save_image_path
  309. def generateModelclothingQW(self, local_path, model_id, save_path):
  310. """千问生成场景图"""
  311. imageUrl = self.uploadImage(local_path)
  312. data = {
  313. "machine_type": 1, # 0鞋;1服装
  314. "generate_type": 1, # 生成类型,这里指代得是场景图还是模特图;0场景图;1模特图
  315. "base_image": imageUrl,
  316. "model_template_id": model_id,
  317. }
  318. """生成场景图"""
  319. url = settings.DOMAIN + "/api/ai_image/main/image_edit_generate"
  320. resultData = self.s.post(url, data=data, headers=self.post_headers).json()
  321. code = resultData.get("code", 0)
  322. message = resultData.get("message", "")
  323. if code != 0:
  324. raise UnicornException(message)
  325. image_url = resultData.get("data", None).get("image_url", "")
  326. if image_url == "" or image_url is None:
  327. raise UnicornException("模特图生成失败")
  328. save_image_path = download_image_with_pil(image_url, save_path)
  329. return save_image_path
  330. class OnlineDataRequest(object):
  331. def __init__(self, token):
  332. self.s = requests.session()
  333. self.token = token
  334. self.post_headers = {
  335. "Authorization": token,
  336. # "Origin": settings.Headers["Origin"],
  337. # "Host": settings.Headers["Host"],
  338. "Content-Length": "0",
  339. "Content-Type": "application/json",
  340. "Accept": "application/json",
  341. }
  342. print("28 Authorization:", self.post_headers["Authorization"])
  343. def refresh_headers(self, token):
  344. self.post_headers = {
  345. "Authorization": token,
  346. # "Origin": settings.Headers["Origin"],
  347. # "Host": settings.Headers["Host"],
  348. "Content-Length": "0",
  349. "Content-Type": "application/json",
  350. "Accept": "application/json",
  351. }
  352. def auth_user(self):
  353. # 用户登录
  354. url = "{domain}/api/auth/user".format(domain=settings.DOMAIN)
  355. s = requests.session()
  356. _s = s.get(url=url, headers=settings.Headers)
  357. response_data = _s.json()
  358. return response_data
  359. def logout(self):
  360. url = "{domain}/api/auth/logout".format(domain=settings.DOMAIN)
  361. s = requests.session()
  362. _s = s.post(url=url, headers=settings.Headers)
  363. def get_change_bar_code(self, code):
  364. url = "{domain}/api/hct/open/sting_search_goods?string={code}".format(
  365. domain=settings.DOMAIN, code=code
  366. )
  367. try:
  368. s = requests.get(url)
  369. goods_art_no = s.json()["data"]["goods_art_no"]
  370. return goods_art_no
  371. except BaseException as e:
  372. print(e)
  373. return
  374. def get_goods_art_no_info(self, numbers_list=None, goods_art_list=None, token=None):
  375. # 获取商品基础信息,入参为商品的编号
  376. url = "{domain}/api/backend/produce/goods/info".format(domain=settings.DOMAIN)
  377. print("执行 get_goods_art_no_info ", url)
  378. if numbers_list:
  379. data = {"numbers": numbers_list}
  380. print("请求编码:", numbers_list)
  381. else:
  382. data = {"goods_art_nos": goods_art_list}
  383. print("请求货号:", goods_art_list)
  384. print("请求货号=====>", self.token)
  385. print("执行 get_goods_art_no_info----------------", data)
  386. post_headers = {
  387. "Authorization": token,
  388. # "Origin": settings.Headers["Origin"],
  389. # "Host": settings.Headers["Host"],
  390. "Content-Length": "",
  391. "Content-Type": "application/json",
  392. "Accept": "application/json",
  393. }
  394. data = json.dumps(data)
  395. post_headers["Content-Length"] = str(len(data))
  396. _s = self.s.post(url=url, data=data, headers=post_headers)
  397. # _s = self.s.get(url=url, params=params, headers=settings.Headers)
  398. response_data = _s.json()
  399. # print(response_data)
  400. # print("\n")
  401. goods_number_data = {}
  402. # ["", "", "", "", "", "", "", "", "", "", "", ]
  403. if "data" not in response_data:
  404. return {}
  405. for data in response_data["data"]:
  406. if numbers_list:
  407. number = data["number"]
  408. else:
  409. number = data["goods_art_no"].upper()
  410. goods_number_data[number] = {}
  411. goods_number_data[number]["商品面料"] = data["fabric"]
  412. goods_number_data[number]["商品内里"] = data["lining"]
  413. goods_number_data[number]["商品鞋底"] = data["sole"]
  414. goods_number_data[number]["后帮高"] = data["back_height"]
  415. goods_number_data[number]["前掌宽"] = data["forefoot_width"]
  416. goods_number_data[number]["鞋跟高"] = data["heel_height"]
  417. goods_number_data[number]["FAB介绍"] = data["fab_info"]
  418. goods_number_data[number]["编号"] = data["number"]
  419. goods_number_data[number]["商品货号"] = data["goods_art_no"].upper()
  420. goods_number_data[number]["款号"] = data["goods_number"].upper()
  421. goods_number_data[number]["颜色名称"] = data["color"]
  422. goods_number_data[number]["所属企划"] = data["projects"][0]
  423. goods_number_data[number]["设计方名称"] = data["purchasing_unit"]
  424. goods_number_data[number]["供应商"] = data["supplier_name"]
  425. goods_number_data[number]["供应商编码"] = data["supplier_code"].lstrip("0")
  426. goods_number_data[number]["供应商货号"] = data["supplier_goods_artno"]
  427. goods_number_data[number]["销售工厂"] = data["sales_factory_name"]
  428. goods_number_data[number]["销售组织"] = data["man_org_name"]
  429. goods_number_data[number]["是否SAP"] = data["source"]
  430. goods_number_data[number]["OEM报价"] = data["oem_price"]
  431. goods_number_data[number]["出厂价"] = data["ex_factory_price"]
  432. goods_number_data[number]["首单货期"] = data["earliest_delivery_date"]
  433. goods_number_data[number]["包装"] = data["package_specification"]
  434. goods_number_data[number]["创建日期"] = data["created_at"]
  435. goods_number_data[number]["货号图"] = data["image"]
  436. return goods_number_data
  437. def get_on_goods_all_art(self, number):
  438. # 获取商品基础信息,入参为商品的编号
  439. url = "{domain}/api/backend/produce/goods/query/numbers?number={number}".format(
  440. domain=settings.DOMAIN, number=number
  441. )
  442. _s = self.s.get(url=url, headers=self.post_headers)
  443. response_data = _s.json()
  444. print(number, response_data)
  445. """
  446. 14250230 {'data': {'goods_number': 'AC5200117', 'brother_goods_arts': [{'number': '14250232', 'goods_art_no': 'AC52001173', 'color': '杏色'}, {'number': '14250231', 'goods_art_no': 'AC52001172', 'color': '灰色'}, {'number': '14250230', 'goods_art_no': 'AC52001171', 'color': '黑色'}]}, 'code': 0, 'message': 'success'}
  447. """
  448. return (
  449. response_data["data"]["goods_number"],
  450. response_data["data"]["brother_goods_arts"],
  451. response_data["data"]["goods_art_no"],
  452. )
  453. def get_views(self, image_url):
  454. url = "http://{}/shoes_category".format(settings.VIEW_DEAL_DOMAIN)
  455. data = {
  456. "train_path": "./datasets/Shoes_Dataset/Train/angle",
  457. "model_filename": "./models/0320/output0320.pth",
  458. "validate_path": image_url,
  459. }
  460. _s = requests.post(
  461. url=url,
  462. data=json.dumps(data),
  463. )
  464. response_data = _s.json()
  465. return response_data["classify_result"]
  466. def uploadImage(self, local_path: str) -> str:
  467. post_headers = {"Authorization": self.token}
  468. url = settings.DOMAIN + "/api/upload"
  469. resultData = self.s.post(
  470. url, files={"file": open(local_path, "rb")}, headers=post_headers
  471. ).json()
  472. return resultData["data"]["url"]
  473. def get_current_menu(self):
  474. def get_menu(_menu_dict, _data):
  475. for menu in _data:
  476. _menu_dict[menu["key"]] = {}
  477. for mods in menu["mods_arr"]:
  478. _menu_dict[menu["key"]][mods["key"]] = mods["name"]
  479. if "_child" in menu:
  480. get_menu(_menu_dict, menu["_child"])
  481. return _menu_dict
  482. url = "{domain}/api/backend/basic/get_current_menu".format(
  483. domain=settings.DOMAIN,
  484. )
  485. _s = self.s.get(url=url, headers=settings.Headers)
  486. response_data = _s.json()
  487. try:
  488. menu_data = response_data["data"]["pc_menu"]
  489. menu_dict = {}
  490. menu_dict = get_menu(menu_dict, menu_data)
  491. except:
  492. menu_dict = {}
  493. # print(json.dumps(menu_dict,ensure_ascii=False))
  494. # raise 1
  495. return menu_dict
  496. # 获取所有资源的配置
  497. def get_resource_config(self):
  498. url = "{domain}/api/openai/query_client_addons".format(domain=settings.DOMAIN)
  499. _s = self.s.get(
  500. url=url, headers=self.post_headers, params={"type": "client_camera"}
  501. )
  502. response_data = _s.json()
  503. return response_data
  504. # 拍照日志上报
  505. def add_auto_photo_logs(self, data):
  506. url = "{domain}/api/openai/add_auto_photo_logs".format(domain=settings.DOMAIN)
  507. post_data = {
  508. "goods_no": data["goods_art_no"],
  509. "take_photo_created_at": data["take_photo_created_at"],
  510. "photo_created_at": data["photo_create_time"],
  511. "image_dispose_mode": data["image_deal_mode"],
  512. "photo_serial_number": data["image_index"],
  513. }
  514. post_data = json.dumps(post_data)
  515. _s = self.s.post(url=url, headers=self.post_headers, data=post_data)
  516. response_data = _s.json()
  517. if settings.IS_TEST:
  518. print("209-----拍照日志上报 add_auto_photo_logs")
  519. print(response_data)
  520. return response_data
  521. def upload_pic_list_data(self, data):
  522. url = "{domain}/api/backend/goods/save/images".format(domain=settings.DOMAIN)
  523. data = json.dumps(data)
  524. self.post_headers["Content-Length"] = str(len(data))
  525. _s = self.s.post(url=url, data=data, headers=self.post_headers)
  526. response_data = _s.json()
  527. try:
  528. if response_data["code"] == 0 and response_data["message"] == "success":
  529. return True
  530. else:
  531. print(data)
  532. print(response_data)
  533. return False
  534. except BaseException as e:
  535. print(data)
  536. print(e)
  537. print(response_data)
  538. return False
  539. def upload_pic(self, goods_data):
  540. # 检查货号图是否存在
  541. url = "{domain}/api/backend/upload".format(domain=settings.DOMAIN)
  542. # print(url)
  543. headers = {
  544. "Authorization": settings.Headers["Authorization"],
  545. "User-Agent": settings.Headers["User-Agent"],
  546. "Origin": settings.Headers["Origin"],
  547. "Host": settings.Headers["Host"],
  548. }
  549. files = [
  550. (
  551. "file",
  552. (
  553. goods_data["file_path"],
  554. goods_data["image_io"],
  555. "image/{}".format(goods_data["e"]),
  556. ),
  557. )
  558. ]
  559. _s = requests.post(url=url, headers=headers, files=files)
  560. response_data = _s.json()
  561. return response_data["data"]["url"]
  562. # 查询是否已有详情图
  563. def check_detail_image(self, goods_art_no, token):
  564. url = "{domain}/api/backend/goods/check_detail_image?number={number}".format(
  565. domain=settings.DOMAIN, number=goods_art_no
  566. )
  567. _s = self.s.get(url=url, headers=self.post_headers)
  568. response_data = _s.json()
  569. # print(response_data)
  570. return response_data["data"]["hasDetailImage"]
  571. # 调用API识别是否是拖鞋
  572. def yolo_shoes_category(self, image_url):
  573. url = "{domain}/api/ai_image/main/yolo_shoes_category".format(
  574. domain=settings.DOMAIN
  575. )
  576. post_data = {
  577. "image_url": image_url,
  578. }
  579. post_data = json.dumps(post_data)
  580. _s = self.s.post(url=url, headers=self.post_headers, data=post_data)
  581. response_data = _s.json()
  582. if settings.IS_TEST:
  583. print("278-----yolo_shoes_category")
  584. print(response_data)
  585. r_data = None
  586. try:
  587. r_data = response_data["data"]["category"]
  588. except BaseException as e:
  589. print("285", e)
  590. return r_data
  591. # 图片上传by IO
  592. def upload_image_by_io(self, image_io) -> str:
  593. post_headers = {"Authorization": settings.Authorization}
  594. url = settings.DOMAIN + "/api/upload"
  595. resultData = self.s.post(
  596. url, files={"file": image_io}, headers=post_headers
  597. ).json()
  598. return resultData["data"]["url"]
  599. def upload_goods_api(self, params):
  600. """上传商品api"""
  601. post_headers = {
  602. "Authorization": self.token,
  603. "Content-Type": "application/json",
  604. }
  605. url = settings.DOMAIN + "/api/ai_image/camera_machine/publish_goods"
  606. postData = json.dumps(params)
  607. # print("上传商品api==>url", url)
  608. # print("上传第三方数据打印", params)
  609. resultData = self.s.post(url, data=postData, headers=post_headers).json()
  610. print("上传商品api==>resultData", resultData)
  611. return resultData
  612. def sendSocketMessage(self, code=0, msg="", data=None, device_status=2,msg_type="upload_goods_progress"):
  613. data = {
  614. "code": code,
  615. "msg": msg,
  616. "status": device_status,
  617. "data": data,
  618. "msg_type": msg_type,
  619. }
  620. loop = asyncio.get_event_loop()
  621. loop.create_task(message_queue.put(data))
  622. def uploadGoods2ThirdParty(self, goods_no_dict=None, online_stores=[]):
  623. params = []
  624. message_type = "upload_goods_progress"
  625. if goods_no_dict == None:
  626. return
  627. success_goods_arts = []
  628. for store in online_stores:
  629. for goods_no in goods_no_dict.keys():
  630. goods_data = goods_no_dict[goods_no]
  631. detail_path = goods_data.get("detail_path", "")
  632. if detail_path == "":
  633. continue
  634. goods_title = goods_data.get("商品标题", "")
  635. if goods_title == "":
  636. continue
  637. goods_price = goods_data.get("商品价格", 0)
  638. if goods_price == '':
  639. goods_price = 0
  640. if goods_price == 0:
  641. continue
  642. skuList = []
  643. itemImageInfoList = []
  644. itemSkuImageList = []
  645. sku_list_basic = goods_data.get("货号资料", [])
  646. quantity = 9999
  647. skuPropValueList = []
  648. for skuIdx, sku_data in enumerate(sku_list_basic):
  649. sku_goods_art_no = sku_data.get("货号", "")
  650. color_name = sku_data.get("颜色名称", "")
  651. size = sku_data.get("尺寸", 37)
  652. # 尺码
  653. mainImages = sku_data.get("800x800", [])
  654. if not mainImages:
  655. continue
  656. success_goods_arts.append(sku_goods_art_no)
  657. mainImagePath = mainImages[0]
  658. imageUrl = self.uploadImage(local_path=mainImagePath)
  659. skuNameJson = []
  660. skuNameJson.append({"propName":"颜色","propValue":color_name})
  661. skuNameJson.append({"propName":"尺寸","propValue":size})
  662. skuItemData = {
  663. "颜色": color_name,
  664. "尺寸": size,
  665. "skuPropName":color_name,
  666. "skuNo": sku_goods_art_no,
  667. "originalPrice": float(goods_price),
  668. "newSkuWeight": int(1),
  669. "skuMainImageUrl": str(imageUrl),
  670. "skuName": f"颜色:{color_name};尺寸:{size}",
  671. "sellingPrice": float(goods_price),
  672. "quantity": int(quantity),
  673. "showOrder": int(skuIdx + 1),
  674. "skuNameJson":skuNameJson
  675. }
  676. skuList.append(skuItemData)
  677. itemImage = {
  678. "imageUrl": str(imageUrl),
  679. "imageType": 0,
  680. "imageItem": int(skuIdx),
  681. "imageIndex": 10,
  682. }
  683. itemImageInfoList.append(itemImage)
  684. imageJson = {
  685. "imageUrl": str(imageUrl),
  686. "imageType": 1,
  687. "showOrder": 1,
  688. }
  689. skuPropValueList.append(
  690. {
  691. "imageJson": [imageJson],
  692. "propValue": str(color_name),
  693. "showOrder": 1,
  694. }
  695. )
  696. itemSkuImageList.append(
  697. {
  698. "propName": "颜色",
  699. "isImageProp": 1,
  700. "propShowOrder": 1,
  701. "skuPropValueList": skuPropValueList,
  702. }
  703. )
  704. itemSkuImageList.append({
  705. "propName": "尺寸",
  706. "isImageProp": 0,
  707. "propShowOrder": 1,
  708. "showOrder": 0,
  709. "propValue": str(size),
  710. "skuPropValueList":[{
  711. "propValue": str(size),
  712. "showOrder": 1,
  713. }]
  714. })
  715. detailImageUrl = self.uploadImage(local_path=detail_path)
  716. category_info = "流行男鞋>>休闲鞋>>时尚休闲鞋"
  717. itemData = {
  718. "catePathName": category_info, # 分类
  719. "itemName": str(goods_title), # 商品标题
  720. "itemNo": str(goods_no),
  721. "brandName": store, # 品牌名称
  722. "sellingPrice": float(goods_price), # 售价(未划线价)
  723. "originalPrice": float(goods_price), # 划线价
  724. "quantity": int(quantity), # 库存数量
  725. "propInfoList": [
  726. {"propName": "品牌", "propIndex": 2, "propValue": "Vali"},
  727. {
  728. "propName": "平台类目",
  729. "propIndex": 3,
  730. "propValue": category_info,
  731. },
  732. ],
  733. "skuList": skuList,
  734. "itemImageInfoList": itemImageInfoList,
  735. "itemSkuImageList": itemSkuImageList,
  736. "wapDescription": f'<img src="{detailImageUrl}"/>',
  737. "pcDescription": f'<img src="{detailImageUrl}"/>',
  738. }
  739. params.append(itemData)
  740. json_params = str(params) # 直接转换为字符串表示
  741. print("json_params", json_params)
  742. # 使用base64编码
  743. encoded = base64.b64encode(json_params.encode("utf-8")).decode("utf-8")
  744. self.upload_goods_api({"bizcontent": encoded, "online_stores": online_stores})
  745. print("商品上传第三方成功")
  746. return True
  747. class GetOnlineDataHLM(OnlineDataRequest):
  748. def __init__(self, token):
  749. super().__init__(token)
  750. self.token = token
  751. def upload_pic(self, goods_data, token):
  752. # 检查货号图是否存在
  753. url = "{domain}/api/backend/upload".format(domain=settings.DOMAIN)
  754. # print(url)
  755. headers = {
  756. "Authorization": self.token,
  757. # 'User-Agent': settings.Headers["User-Agent"],
  758. # 'Origin': settings.Headers["Origin"],
  759. # 'Host': settings.Headers["Host"],
  760. }
  761. files = [
  762. (
  763. "file",
  764. (
  765. goods_data["file_path"],
  766. goods_data["image_io"],
  767. "image/{}".format(goods_data["e"]),
  768. ),
  769. )
  770. ]
  771. _s = requests.post(url=url, headers=headers, files=files)
  772. response_data = _s.json()
  773. return response_data["data"]["url"]
  774. def upload_pic_list_data(self, data, token):
  775. url = "{domain}/api/backend/goods/save/images".format(domain=settings.DOMAIN)
  776. data = json.dumps(data)
  777. self.post_headers["Content-Length"] = str(len(data))
  778. _s = self.s.post(url=url, data=data, headers=self.post_headers)
  779. response_data = _s.json()
  780. try:
  781. if response_data["code"] == 0 and response_data["message"] == "success":
  782. return True
  783. else:
  784. print(response_data)
  785. return False
  786. except BaseException as e:
  787. print(e)
  788. print(response_data)
  789. return False
  790. def get_goods_art_no_info(self, numbers_list=None, goods_art_list=None, token=None):
  791. # 获取商品基础信息,入参为商品的编号
  792. url = "{domain}/api/backend/goods_client/goods_query".format(
  793. domain=settings.DOMAIN
  794. )
  795. data = {"goods_art_list": goods_art_list}
  796. print("url:", url)
  797. print("请求货号:", goods_art_list)
  798. post_headers = {
  799. "Authorization": token,
  800. # "Origin": settings.Headers["Origin"],
  801. # "Host": settings.Headers["Host"],
  802. "Content-Length": "",
  803. "Content-Type": "application/json",
  804. "Accept": "application/json",
  805. }
  806. data = json.dumps(data)
  807. print(post_headers)
  808. print(data)
  809. # post_headers["Content-Length"] = str(len(data))
  810. _s = self.s.post(url=url, data=data, headers=post_headers)
  811. # _s = self.s.get(url=url, params=params, headers=settings.Headers)
  812. response_data = _s.json()
  813. print(response_data)
  814. print("\n")
  815. goods_number_data = {}
  816. # ["", "", "", "", "", "", "", "", "", "", "", ]
  817. if "data" not in response_data:
  818. return {}
  819. for data in response_data["data"]:
  820. goods_art_no = str(data["goods_art_no"])
  821. goods_number_data[goods_art_no] = {}
  822. goods_number_data[goods_art_no]["商品货号"] = data[
  823. "goods_art_no"
  824. ].upper()
  825. goods_number_data[goods_art_no]["款号"] = data[
  826. "goods_number"
  827. ].upper()
  828. goods_number_data[goods_art_no]["商品面料"] = data["fabric"]
  829. goods_number_data[goods_art_no]["商品内里"] = data["lining"]
  830. goods_number_data[goods_art_no]["商品鞋底"] = data["sole"]
  831. goods_number_data[goods_art_no]["鞋垫"] = data["insole"]
  832. goods_number_data[goods_art_no]["颜色名称"] = data["color"]
  833. goods_number_data[goods_art_no]["商品标题"] = data["goods_title"]
  834. goods_number_data[goods_art_no]["商品价格"] = data["retail_price"]
  835. goods_number_data[goods_art_no]["尺码"] = data["size"]
  836. goods_number_data[goods_art_no]["性别"] = data["gender"]
  837. goods_number_data[goods_art_no]["token"] = self.token
  838. print("货号数据:", goods_number_data)
  839. return goods_number_data
  840. def uploadImage(self, local_path: str) -> str:
  841. post_headers = {"Authorization": settings.Authorization}
  842. url = settings.DOMAIN + "/api/upload"
  843. resultData = self.s.post(
  844. url, files={"file": open(local_path, "rb")}, headers=post_headers
  845. ).json()
  846. return resultData["data"]["url"]
  847. # ============pixian抠图处理==========================
  848. def dispose_point(self, _type):
  849. # 扣分 sub;add为增加分数,每次操作一分
  850. url = "{domain}/api/ai_image/client/dispose_point".format(
  851. domain=settings.DOMAIN
  852. )
  853. data = {"type": _type}
  854. _s = self.s.post(
  855. url=url, headers=self.post_headers, data=json.dumps(data), timeout=10
  856. )
  857. response_data = _s.json()
  858. return response_data
  859. def send_message(self, text):
  860. # 发送钉钉消息
  861. url = "{domain}/api/ai_image/client/send_message".format(domain=settings.DOMAIN)
  862. data = {"message": text}
  863. _s = self.s.post(
  864. url=url, headers=self.post_headers, data=json.dumps(data), timeout=10
  865. )
  866. response_data = _s.json()
  867. return response_data
  868. def get_cutout_image_times(self):
  869. # 获取抠图剩余次数
  870. url = "{domain}/api/ai_image/client/search_company_balance".format(
  871. domain=settings.DOMAIN
  872. )
  873. _s = self.s.post(url=url, headers=self.post_headers, timeout=10)
  874. response_data = _s.json()
  875. if "data" not in response_data:
  876. return False
  877. else:
  878. return response_data["data"]
  879. def get_key_secret(self):
  880. # 获取抠图剩余次数
  881. url = "{domain}/api/ai_image/client/get_key_serect".format(
  882. domain=settings.DOMAIN
  883. )
  884. _s = self.s.post(url=url, headers=self.post_headers, timeout=10)
  885. response_data = _s.json()
  886. return response_data["data"]