修复种草图生成:以三合一主图为参考 img2img 生成,按颜色分配(每色优先、超出随机补足);新增 BR/CA/DE/ES/IT/PL/SA 七国配置与提示词;删除验证用测试脚本
This commit is contained in:
@@ -21,6 +21,38 @@ from graph.product import _connect
|
||||
_CAROUSEL_KW = ("轮播", "carousel", "カルーセル")
|
||||
|
||||
|
||||
def _size_rank(size) -> tuple:
|
||||
"""把尺码字符串转成可排序 rank(从小到大)。
|
||||
|
||||
优先级:数字码(90/100...) < 字母码(XS/S/M/L/XL/XXL/3XL...) < 童装年龄码(0/3M、1-2Y...)
|
||||
< 尺寸规格(30*40...) < 未知(字典序兜底) < 均码/Onesize(最后)。
|
||||
"""
|
||||
s = str(size or "").strip().upper()
|
||||
if not s:
|
||||
return (9, 0, "")
|
||||
if s in ("ONESIZE", "ONE SIZE", "FREESIZE", "FREE SIZE", "均码"):
|
||||
return (8, 0, s)
|
||||
if s == "XS":
|
||||
return (2, 0, s)
|
||||
if s in ("S", "M", "L"):
|
||||
return (2, {"S": 1, "M": 2, "L": 3}[s], s)
|
||||
m = re.fullmatch(r"(X+)(L)", s) # XL/XXL/XXXL/XXXXL/XXXXXL
|
||||
if m:
|
||||
return (2, 3 + len(m.group(1)), s)
|
||||
m = re.fullmatch(r"(\d+)XL", s) # 3XL/4XL/5XL
|
||||
if m:
|
||||
return (2, 3 + int(m.group(1)), s)
|
||||
if s.isdigit(): # 数字码:90/100/110...
|
||||
return (1, int(s), s)
|
||||
m = re.fullmatch(r"(\d+)\s*[-/]\s*(\d+)\s*(?:M|Y|YRS|YR)?", s) # 童装年龄码
|
||||
if m:
|
||||
return (3, (int(m.group(1)) + int(m.group(2))) / 2.0, s)
|
||||
m = re.search(r"(\d+(?:\.\d+)?)\s*(?:CM)?\s*[X*]", s) # 尺寸规格:30*40/12CM X 12CM
|
||||
if m:
|
||||
return (4, float(m.group(1)), s)
|
||||
return (5, 0, s) # 未知格式:字典序兜底
|
||||
|
||||
|
||||
def _carousel_col(router, idx: int) -> Optional[int]:
|
||||
"""定位「商品轮播图{idx}」列号:先精确匹配(中文列名),失败则按中/英/日关键词模糊匹配序号。"""
|
||||
try:
|
||||
@@ -109,7 +141,7 @@ def _fill_design_fields(router, spu_code: str, oss_code: str, cn_title: str, en_
|
||||
for row in router.find_spu_rows(spu_code):
|
||||
if only_rows is not None and row not in only_rows:
|
||||
continue # 合并模式:只填本产品块的行
|
||||
lvl = str(router.ws.cell(row, 1).value or "").strip().lower()
|
||||
lvl = str(router.ws.cell(row, router.level_col).value or "").strip().lower()
|
||||
color = str(router.ws.cell(row, color_col).value or "").strip() if color_col else ""
|
||||
if lvl == "spu":
|
||||
if spu_col and oss_code:
|
||||
@@ -213,7 +245,7 @@ def _fill_sku_carousel(router, spu_code: str, color: str, color_col: int,
|
||||
if col is None:
|
||||
continue
|
||||
for row in router.find_spu_rows(spu_code):
|
||||
if (str(router.ws.cell(row, 1).value or "").strip().lower() == "sku"
|
||||
if (str(router.ws.cell(row, router.level_col).value or "").strip().lower() == "sku"
|
||||
and str(router.ws.cell(row, color_col).value or "").strip() == color):
|
||||
router.ws.cell(row, col, str(img))
|
||||
|
||||
@@ -270,30 +302,44 @@ def _read_spu(db_path, spu_code: str) -> Optional[Dict[str, Any]]:
|
||||
|
||||
|
||||
def _read_meta(router) -> tuple:
|
||||
"""读模板顶头元信息:经营站点(第2行第1列)、发货仓(第2行第2列)。
|
||||
"""读模板顶头元信息:经营站点、发货仓(按标签名定位,不依赖固定行列)。
|
||||
|
||||
返回 (origin_province, warehouses):
|
||||
- origin_province:经营站点去掉末尾「站」(如「日本站」→「日本」)
|
||||
- warehouses:发货仓按「、」分隔的列表(如「名古屋仓、inkreach——东京」→ 2 个)
|
||||
"""
|
||||
ws = router.ws
|
||||
site = str(ws.cell(2, 1).value or "").strip()
|
||||
top = max(1, router.group_row - 1) # 元信息区位于分组行之前
|
||||
|
||||
def _val(label: str) -> str:
|
||||
for row in range(1, top + 1):
|
||||
for col in range(1, min(ws.max_column, 30) + 1):
|
||||
if str(ws.cell(row, col).value or "").strip() == label:
|
||||
return str(ws.cell(row + 1, col).value or "").strip()
|
||||
return ""
|
||||
|
||||
site = _val("经营站点")
|
||||
raw = _val("发货仓")
|
||||
if not site and not raw:
|
||||
# 回退:旧版固定位置(第2行第1/2列)
|
||||
site = str(ws.cell(2, 1).value or "").strip()
|
||||
raw = str(ws.cell(2, 2).value or "").strip()
|
||||
origin_province = site[:-1] if site.endswith("站") else site
|
||||
raw = str(ws.cell(2, 2).value or "").strip()
|
||||
warehouses = [w.strip() for w in raw.split("、") if w.strip()]
|
||||
return origin_province, warehouses
|
||||
|
||||
|
||||
def _read_skus(db_path, spu_code: str, sku_code: str) -> List[Dict[str, Any]]:
|
||||
"""该款该颜色的全部尺码 SKU。"""
|
||||
"""该款该颜色的全部尺码 SKU,按尺码从小到大排序(字母码/数字码/童装码/规格码)。"""
|
||||
conn = _connect(db_path)
|
||||
rows = conn.execute(
|
||||
"""SELECT s.*, p.code AS spu_code FROM SKU s
|
||||
JOIN SPU p ON s.spu_id = p.id
|
||||
WHERE p.code = ? AND s.code = ?
|
||||
ORDER BY s.size""", (spu_code, sku_code)).fetchall()
|
||||
WHERE p.code = ? AND s.code = ?""", (spu_code, sku_code)).fetchall()
|
||||
conn.close()
|
||||
return [dict(r) for r in rows]
|
||||
skus = [dict(r) for r in rows]
|
||||
skus.sort(key=lambda sk: _size_rank(sk.get("size")))
|
||||
return skus
|
||||
|
||||
|
||||
def export_product(
|
||||
|
||||
Reference in New Issue
Block a user