选品建listing 复用配方(2026-09-30):速卖通 4/4 进待发布配方 + Shopee 授权异常现状 + 前置店铺自检/图片门槛

- 速卖通建品/RECIPE-2026-09-30.md:必填项(货值/物流属性/包装后尺寸整数/关税)、重量命中「重量(kg)」、CKEditor、图片≥400px、回读口径
- shopee建品/RECIPE-2026-09-30.md + README-授权状态:页面事实 + 无授权店铺的证据链与解锁步骤(历史 47 条证明是授权异常而非未授权)
- README:新增「可复用配方」节,指向技能 atomk-hermes-skills/dianxiaomi-multiplatform-push 与 product-pool-ops/listing-spec
This commit is contained in:
agent committed 2026-09-30 16:25:51 +08:00
1 parent e6048d50cc
commit b54e9063f1
4 files changed
+218

No files matched your search

+114
View File
@@ -0,0 +1,114 @@
# 速卖通(AliExpress POP)「选品建listing」完整配方
> 2026-09-30 实测跑通:**4/4 进「待发布」,采集箱 0 残留**(RV8I478D / ZQI01T5J / XSSIERBV / XAGOKS9C)。
> 目标态 = 待发布(`dxmState=offline & dxmOfflineState=waitPublish`),**绝不点「发布」**。
## 0. 页面与接口事实
| 项 | 值 |
|---|---|
| 创建页 | `https://www.dianxiaomi.com/web/smt/add`(标题「店小秘--添加速卖通产品」) |
| 编辑页 | `/web/smt/edit?id=<id>` —— **实测打不开**:`GET /api/smtProduct/edit.json?id=` 无论 id 传什么都返回同一份 12,592 字节的**添加页引导包**(modelList/unitList),不含商品数据 → 不要指望它做回读 |
| 保存 | `POST /api/smtProduct/add.json`(点「保存」触发;**不点「发布」**) |
| 列表 | `POST /api/smtProduct/pageList.json`,body: `pageNo&pageSize&total&searchType=0&searchValue&shopId=-1&dxmState&dxmOfflineState` |
| 列表页 | 待发布 `/web/smt/smtProductList/offline`、采集箱 `…/draft`、在线 `…/online` |
| 类目 | 点「选择分类」→ 弹窗标题**「选择类目」**、搜索框 `input[placeholder*=搜索分类]`、结果行 `.search-result-item` |
| 单位 | **kg / cm**(Ozon 是 g / mm,别混) |
| 店铺 | 10 家:BlessLuckA、Laikeet、Sunbeam、AliMingPro1、Key、Deanoyal… |
## 1. 执行顺序(顺序错了就被挡)
```
① 店铺(必须最先!类目树随店铺/站点变)
② 类目(中文品类词搜索 → 点结果行,弹窗自动关)
③ 标题(insertText)
④ 来源URL(无 label,用 placeholder 定位)
⑤ 零售价格 / 库存数量 / 货值 / 商品编码
⑥ 重量(kg)、包装尺寸(cm) ×3、包装后尺寸(cm) ×3
⑦ 图片(选择图片 → 网络图片 → 粘 URL → 添加)
⑧ 物流属性(铅笔图标弹窗 → 普货 → 确定)
⑨ 是否原箱(下拉,必填)、报价是否含关税(radio value=1 不含关税报价)
⑩ PC端描述(CKEditor 4)
⑪ 保存 → 回读 pageList
```
## 2. 逐字段硬知识(每条都踩过)
1. **不选店铺 → 「选择分类」根本打不开**(弹窗不出现,表现为 `no-modal`)。脚本里店铺选择必须在类目前。
2. **类目搜索词必须是中文**:`旗帜→横幅(Banners)`、`托特包→Tote Bags`、`护照夹→护照套/护照夹`。
**英文搜不到**(`Tote Bags` → 命中 0 → 保存报「请选择分类」)。
结果行文本形如 `Luggage & Bags(箱包)/Kids' Bags(童包)/Tote Bags(托特包)`(分隔符 `/`,中英双语),
**点行即选中并关窗**,没有可用的「选择」确认按钮。
* 已知瑕疵:`托特包` 命中 3 条时会选到第一条「童包」,优先命中父级段(`Women Bags`)的逻辑已加,但速卖通树里未必存在该英文段 → 需要时人工在页面上点一次。
3. **图片门槛 单边 ≥400px**:喂 10 张图,速卖通**静默只收 6 张**(300×224 / 300×195 / 367×344 / 300×213 被丢)。
→ 建输入前先按真实尺寸过滤:`build-add-input.py --min-side 400`(会下载探尺寸)。
模块:`.productMainImgModule`,头按钮文案「选择图片」;弹层 tab:本地图片 / **网络图片** / 图片银行 / 引用采集图片;
网络图片 tab 的 textarea placeholder「请填写图片URL地址,多个地址用回车换行」→ 点「添加」。
回读口令:`主图最多选用6张,已经选用了6张`(上限 **6 张主图**)。
4. **保存必填项(缺一个就整单失败)**——错误清单来自 `MYJ.message.error` 钩子 + `.ant-form-item-explain-error`:
| 报错原文 | 要填什么 | 正确写法 |
|---|---|---|
| 请输入货值 | 货值(CNY) | 用成本价兜底(`cost_cny`) |
| 物流属性必填! | 物流属性 | **不是普通下拉**:点 `.single-logistics-attr-edit` 铅笔 → `.batch-edit-modal` → 选「普货」→ 确定 |
| 包装后尺寸请填写整数! | 包装后尺寸 | **整数 cm**;包装尺寸与包装后尺寸都要填,且**尺寸建议整体向上取整** |
| 请选择报价是否含关税! | radio | `input[type=radio][value=1]` = 不含关税报价 |
| 请输入重量 | 重量(kg) | **必须精确命中「重量(kg)」**:类目属性里还有「重量(Item Weight)」,用 `/重量/` 会填错字段(护照夹实测被拒) |
| 请选择分类 | 类目 | 见第 2 条 |
5. **重量下限**:46g → 0.046 → 字段只留 2 位小数变 `0.04` → 被拒「请输入重量」。
安全写法:`wkg = max(0.05, ceil(g/10)/100)` → 0.046→0.05、0.075→0.08、0.097→0.10。
6. **描述是 CKEditor 4 两个实例**:`ckeditor30`=PC端描述、`ckeditor31`=无线端描述(实测确认)。
**必须按实例所属 form-item 定位**:
```js
const hit = Object.keys(CKEDITOR.instances).find(k => {
const el = CKEDITOR.instances[k].element?.$; return el && formItem.contains(el);
});
CKEDITOR.instances[hit].setData(html); CKEDITOR.instances[hit].updateElement();
```
* editable 元素的 `id` **不等于**实例名 → 用 `CKEDITOR.instances[ed.id]` 会落空;
* 退化成「改 iframe innerHTML / contenteditable」时 model 不同步 = 白填。
* 实测成功回读:`ckeditor:ckeditor30:len=2290`。
7. **`pageList` 不返回 `detail` / `packageWeight` / `packageLength`**(100 行全空)→
**不能**用它判断描述/重量/尺寸是否存进去,只能看保存时有没有报错。别把空值当「没保存」。
## 3. 脚本
```bash
D=/home/admin9webs/dsh-dingtalk-workspace/listing-spec
# ① 生成输入(含 400px 图过滤 + 中文类目词)
python3 $D/platform-shared/build-add-input.py pending-package-*.json \
--platform 速卖通 --out /tmp/smt_input.json --min-side 400
# ② 干跑(只填不保存,验证选择器)
node $D/platform-smt/smtbatch.mjs --input /tmp/smt_input.json --only <oid> --dry
# ③ 正式建listing(只保存 → 待发布)
node $D/platform-smt/smtbatch.mjs --input /tmp/smt_input.json --only <oid>
# ④ 回读验收(待发布有没有 + 采集箱有没有本轮新草稿)
node $D/platform-smt/verify-landing.mjs --oids <oid1>,<oid2> --keywords "kw1,kw2"
```
* `platform-shared/dxm-add-lib.mjs`:公共交互库(CDP 真实点击/滚动、setByLabel(insertText)、
`setNumberByLabel`(原生 setter,避免小数被吃)、`pickCategoryBySearch`、`addImagesByUrl`、
`setRichTextByLabel`(CKEditor)、`setLogisticsAttr`、`listShopOptions`、`readErrors`)。
* `platform-shared/preflight-shops.mjs`:**每轮批量前先跑**——查每个平台有没有授权店铺。
* `platform-shared/build-add-input.py`:把待上架 package 转成建listing输入;图按真实尺寸过滤;
英文类目叶 → 中文搜索词映射表 `CAT_KW`(命中不了就补这张表,别在页面上手点)。
## 4. 验收口径(实测结果)
```
RV8I478D ✅ 待发布 1 | 草稿 0 | 横幅 ¥6.65 图6
ZQI01T5J ✅ 待发布 1 | 草稿 0 | 托特包 ¥5.30 图6
XSSIERBV ✅ 待发布 1 | 草稿 0 | 护照套/护照夹 ¥6.90 图6
XAGOKS9C ✅ 待发布 1 | 草稿 0 | 托特包 ¥15.90 图6
```
* 采集箱里**有**大量历史草稿(有些是 2022/2023 年的),按关键词搜会误报残留 →
回读脚本只把**最近 N 分钟**建的草稿算成本轮残留(`--since-min`,默认 180)。
* SKU 前缀不能单独当判据:RV8I478D 的 SKU 是 1688 供应商码 `ZSJLQ_1be`,不含 oid → 回读用「SKU 前缀 **或** 标题关键词」双条件。
## 5. 仍未解决 / 待补
* 类目分支优选(托特包落「童包」而非「女包」)——需要人工确认或补父级英文段。
* `包装后尺寸` 与 `包装尺寸` 目前都填同一组向上取整值;如需精算需接速卖通计抛规则。
* 变种(多变种)模式未做:本配方用单品/单 SKU 路径;带变种的类目需要补变种行填写。
* 运费模板/服务模板未设置(`freightTemplateId=null`),发布前需人工在页面选或做「运费推荐生成」。