module_online_data.py 36 KB

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