9.8 KiB
aliChoice(速卖通全托管)配方 — 已跑通(批量进行中)
路由:https://www.dianxiaomi.com/web/smtChoice/add 列表:/web/smtChoice/{draft=采集箱, offline=待发布}
已经打通的(批量脚本 alcbatch.mjs,单条已验证保存成功)
- 店铺:
店铺名称下拉(实测 2 家:XYZ Store/UniStyle Bag Store),取第一家 →shopId=4393191 - 备货类型:下拉
国内履约/海外备货→ 取第一个(→productType='1') - 类目:
选择分类弹窗 → 用sh_build.selectCategory(c, cat_kw, cat_kw)(与 SHEIN/Temu 同一套) - 标题 →
smtChoiceAddBasicStore.formState.subject(⚠️ 不是 Joom 的name) - 主图 →
smtChoiceAddProductStore.formState.mainImage[](吃{url,imgUrl,name,width,height}) - PC端描述 →
smtChoiceAddStore.describeInfoData.detail+ CKEditor setData(见下) - SKU 行 →
smtChoiceSkuDataStore.formState.skuDataList[]字段:skuPrice / skuCode / scItemBarCode / packageWeight / packageLength / packageWidth / packageHeight / logisticAttrListJson / logisticAttrList / imageList - 必填类目属性(品牌 / 高关注化学品 / 产地)→
fillRequiredSelects()现已能自动填 (产地会输「中国」过滤后选中国大陆)
✅ 「请选择物流属性」已解(保存两遍)
保存时钩子给 MYJ.error: 校验失败,DOM 里是一个没有 label 的报错块:
<div class="ant-form-item-has-error">
<span></span><i class="iconfont icon_edit2 link ml-4"></i>
<div class="text-red-500 font-size-12 mr-[20px]">请选择物流属性</div>
</div>
解法(保存两遍):
- 先点一次保存 → 报错块出现
- 点报错块里的
i.icon_edit2→ 弹出「修改物流属性」modal(20 个复选框,按大类分组: 禁运 / 普货 / 纯电 / 强磁 / 特货(液体·粉末·膏体·其他) / 特敏 / 内电(8 种电池) / 外电 / 弱磁) - 勾 普货 → 点「确定」→ 再点保存 →
您的产品已保存到「待发布」
对应 SKU 行的 logisticAttrListJson / logisticAttrList 两个字段。
✅ PC端描述是 CKEditor,写 textarea 没用
DOM 里那个 TEXTAREA 是 display:none 的藏匿字段,真实控件是 CKEditor
(aria-label「所见即所得编辑器, cked…」)。两种赋值方式,实测都写上才稳:
// 1) 给编辑器实例 setData(本例 window.CKEDITOR.instances 有 2 个实例)
Object.values(window.CKEDITOR.instances).forEach(x => x.setData(html));
// 2) 同时写 store
pinia._s.get('smtChoiceAddStore').$state.describeInfoData.detail = html;
另一个未验证项:4 个规格组都是 0 选项## 另一个未验证项:4 个规格组都是 0 选项
smtChoiceSkuAttrStore.formState.skuAttrs 有 4 组:
Ships From(200007763) / Color(14) / Number of Pcs(200116262) / Bulk Buy(200483263),
但 options 都是 0(值在 _options 或要异步加载),DOM 里能看到值(卡其色/粉红/6Pc/Set…)。
实测:不选变种值也能保存成功(保存链路里没有因为变种报错),所以批量里先不选。
单条顺序(批量脚本里的固定顺序)
店铺 → 备货类型 → 类目 → 标题/主图/SKU行 → 必填属性(品牌/高关注化学品/产地) → PC端描述(CKEditor) → 保存① → 物流属性(普货) → 保存② → 待发布
本轮顺手修好的共享 bug(shein建品/sh_build.mjs 的 fillRequiredSelects)
之前它在 aliChoice 上一个必填属性都填不上,三个原因,都已修:
- select 分支的必填判断只看
label.ant-form-item-required,而速卖通系的属性是.attr-label.required(label 上还常带*前缀)→ 现在三种标记都认 - 容器项「产品属性」本身也带
*,会被当成一个字段去点 → 现在跳过含嵌套.ant-form-item的项 - 点开下拉后按
.pop()取最后一个可见下拉,容易读到上一个字段残留的列表 (曾把化学物列表当国家列表)→ 现在①每次点前先Esc②按与点击点的距离挑下拉 ③产地/Origin 先Input.insertText('中国')过滤
⚠️ 批量首次运行的成败分类(6 条:2 成功 / 4 失败)→ 已停批量
| 现象 | 根因 | 处置 |
|---|---|---|
请上传文件!(商品说明书) |
健康/医疗类目强制资质文件(与 HOOK.md 里速卖通 POP 那条同源) | 换不要求说明书的类目;无干净替代类目的商品只能人工处理 |
请选择产品属性(是否包含电池) |
该下拉点不开(no-dd),疑似要先把别的属性选完才可用 |
待查:单独 dump 这个控件的依赖关系 |
请选择物流属性 |
已知,走「保存①→点 icon_edit2→勾普货→保存②」 | 批量里已实现 |
选类目失败:no-path |
cat_kw 在 aliChoice 类目树里搜不到 |
已修:依次回退 cat_fb(tk_input 里给的后备品类词) |
结论:aliChoice 能不能铺,取决于类目能不能选到不要求资质文件的那一支。
下一轮建议:先把 48 条的 cat_kw → 实际类目 跑一遍 dry(不保存),
把落到健康/医疗/化妆品等强资质类目的商品挑出来,再决定是换词还是跳过。
失败记录现在会带 errItems(例如 商品说明书:请上传文件!),见 alc_done.json。
第二次批量(带 dry 扫描出来的类目表)进展与新的失败类
alcdry.mjs 先扫类目(不保存),把每个商品**第一个不强制「商品说明书」**的品类词写进
alc_route.json(47/47 都有可用类目;例:温度计「温度计」强制说明书 → 回退到「家用电器」说明书=否)。
alcbatch.mjs 之后只读这张表,不再猜类目。
结果:商品说明书 类失败归零;但冒出两类新的必填(都是类目动态属性/SKU 级):
现象(errItems) |
猜测与下一步 |
|---|---|
(无label):请选择SKU分类 |
SKU 行上有个 SKU分类 下拉要选(Temu 的 SKU 表也有这一列)。下一步:定位它的落点(可能 skuDataList[].skuClassification)或走 UI 选第一项 |
材质(Material): / 尺寸(Size): |
类目动态属性里把下拉当文本的项,fillRequiredSelects 选了但值没生效(红色提示为空)→ 下一步 dump 这两项的控件类型(可能是可搜索 select 或 input) |
成材率从 2/6 提升到 5/8,其余靠这两类补齐。
根因修正(第 4 轮):那串「材质/尺寸/品牌」报错其实是类目弹窗没关
复现时 selectCategory 返回了 path:… / MODAL-STILL-OPEN —— 类目弹窗还开着,
后面所有必填属性的点击全被遮罩挡住,于是保存时报出一串看起来五花八门的必填
(品牌/产地/材质/尺寸),让人误以为是「属性选不上」。真正要修的是关弹窗。
修法(sh_build.mjs 的 selectCategory 收尾循环):3 轮 → 6 轮,每一轮都试
确定|选择 → 再试 关闭|取消 → 点右上角 × → 发 Escape;第 4 轮起再点一次
.ant-modal-wrap(遮罩)兜底。返回值里仍带 MODAL-STILL-OPEN 便于发现没关干净。
第二类:材质(Material) 是文本输入,不是下拉
fillRequiredSelects 只处理 select 和勾选组,遇到 INPUT.ant-input 直接跳过,
所以材质永远填不上。新增 fillRequiredTextInputs(c, values):
- 只挑必填 + 空 + 含
input.ant-input/textarea.ant-input的叶子表单项 - 用原生 setter 写值 + 派发
input/change/blur values按顺序发(不够就重复最后一个)
批量里给的候选值:先从标题里猜材质词(plastic/cotton/polyester/stainless steel/metal/
silicone/wood/resin/aluminum/alloy/fabric/nylon/glass/ceramic/leather),再退 Polyester、Other。
⚠️ 这是兜底值,材质属于商品事实,后续应人工抽查(尤其非纺织类)。
第 5 轮:请选择SKU分类 是原生 <select>(不是 antd)
报错项的 DOM:
<div class="ant-form-item-has-error">
<select class="w-180! shrink-0 g-form-component">
<option disabled selected>请选择</option>
<option value="1">单品单件</option><option value="2">同款多件</option><option value="3">混合套装</option>
…
</select>
</div>
antd 系的 .ant-select 选择器一个都匹配不到 → 新增
fillNativeSelects(c, ['单品单件','件/个']):遍历可见原生 select,
值为空/停在下拉占位项时,优先选含「单品单件」「件/个」的项,否则选第一个可用项,
sel.value=… + 派发 input/change。效果:失败从 6/10 降到 8/10,SKU分类 类失败归零。
⚠️ 自己引入的数据质量问题(已修,未落库)
fillRequiredTextInputs 一开始对所有文本必填都发同一个材质词,
结果把「颜色(Color)」填成了 Resin。已改为按字段名给值(helper 支持传函数):
颜色|Color→ 标题里的颜色词,兜底Multicolor材质|Material→ 标题里的材质词,兜底Polyester图案|Pattern→Solid;尺寸|Size→Medium;其余 →Other
查过 alc_done.json:被填错的 866537106657 当时是失败状态(errItems=["颜色(Color):"]),
没有落成脏数据,已用新代码重跑。
第 5 轮的自我踩坑(留个记录)
给「文本必填按字段名给值」打补丁时,我用 const t = String(it.title) 存标题——
t 是外层任务循环变量,块级 const 把它推进 TDZ,整批 8 条当场挂在
ReferenceError: Cannot access 't' before initialization。改名 ttl 后恢复。
教训:往批量脚本里塞局部变量前,先看一眼外层循环变量叫什么(同一函数里 t 已经被占用)。