Files
dianxiaomi-crossborder-play…/skill/SKILL.md
T
admin9webs faeb95c6c9 把 DSH skill 也纳入仓库(skill/SKILL.md)
已注册为 dianxiaomi-multiplatform-listing 技能
2026-09-20 17:29:58 +08:00

108 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: dianxiaomi-multiplatform-listing
description: "在店小秘(dianxiaomi)把同一批商品批量建到多个跨境平台的「待发布」,并诊断「点保存没反应」。覆盖 Ozon/TikTok/Shopee/Walmart/速卖通/SHEIN/Temu 的店铺选择、类目弹窗、字段 store 落点、价格币种、图片外链写法、SKU 表结构。触发词:店小秘、dianxiaomi、批量建品、待发布、铺货、多平台、保存没反应、静默拦截、SHEIN 建品、Temu 建品、Temu 全托管、Walmart 建品、速卖通建品、TikTok 建品、Shopee 建品。"
---
# 店小秘多平台批量建品
> 完整配方与逐平台踩坑:Gitea `admin9webs/dianxiaomi-crossborder-playbook`(本机 `~/gitea-push/dianxiaomi-crossborder-playbook/`)
> 本技能是可复用的**操作约定 + 通用技术事实**;具体字段表看仓库各平台目录。
## 0. 第一原则:遇到「点保存没反应」先挂钩子,不要猜字段
**症状**:点「保存」→ 不发 POST、无界面提示、无 `.ant-form-item-has-error`。
**根因**:校验失败了,但报错被 **`MYJ.message.error` 吞掉**;而且报错**层层递进**
(修完 A 才显示 B)——不修完前一层,后一层根本不显示。
**解法**(在点保存**之前**注入):
```js
window.__cap=[];
function wrap(o,n,l){const f=o[n];o[n]=function(){
window.__cap.push(l+': '+[...arguments].map(a=>typeof a==='string'?a:JSON.stringify(a)).join(' '));
return f.apply(o,arguments);};}
['error','warning','info','success'].forEach(k=>wrap(MYJ.message,k,'MYJ.'+k));
['error','warning','info','success'].forEach(k=>wrap(antd.message,k,'antd.'+k));
```
点保存 → 读 `window.__cap`。
**为什么「必填扫描」不够**:扫 `.ant-form-item-required` 且为空,会漏掉
**条件必填**(Temu 省份:产地=中国才出现)和**类目相关的文件字段**
(速卖通商品说明书:部分类目强制)。
已用此法定位:
| 平台 | 被吞掉的报错 |
|---|---|
| 速卖通 | `商品说明书 → 请上传文件!`(类目相关) |
| SHEIN | `有必选规格未选择,请完善后再提交` |
| Temu | `产地选择中国时,省份必填` → `产品变种不能为空!` → `尺寸不能为0或空` → `净重必须小于重量` → `请上传预览图` |
## 1. 通用技术事实
- 站点是 **Vue3 + Pinia SPA**,读 store:
```js
document.querySelector('#app').__vue_app__.config.globalProperties.$pinia._s.get('<store>').$state
```
- Chrome CDP 端口 **9223**,profile `/tmp/dxm7`;helper `/tmp/cdp3.mjs`(**ESM,不能用 require**)
- VNC:`http://192.168.9.122:6097/vnc.html` / `:6100`(免密)
- 列表 API 一律 `POST /api/<平台>Product/pageList.json`,列表在 `data.page.list`
- **`idStr ≠ id`**:大整数 JS 精度丢失,服务端操作(删除/详情)一律用 `idStr`
## 2. 交互约定(血泪换来的)
| 场景 | 正确做法 |
|---|---|
| antd select 选项 | **DOM click** `.ant-select-item-option` 通常可行 |
| 只吃真实鼠标的组件 | `Input.dispatchMouseEvent` 发 `mousePressed`/`mouseReleased` |
| **hover 触发的下拉** | 先 `mouseMoved` 到目标,再 `click`(Walmart「选择图片」) |
| 类名含 `!` 的选择器 | `input[class*="!w-200"]`(`input.!w-200` 是非法 CSS) |
| 长下拉(几百项) | 先 `scrollTop=0`(会残留上次位置),再滚动找 |
| 有 store 直读列表 | **优先读 store**(Temu 类目 1038 个在 `dataState.categories`),比驱动 UI 可靠 |
| 文本输入 | `Object.getOwnPropertyDescriptor(proto,'value').set.call(el,v)` + `input`/`change`/`blur` 事件 |
| 改 store 后校验仍失败 | UI **异步同步**,**再点一次保存**可能就过了 |
## 3. 各平台最独特的一点
| 平台 | 必须知道 |
|---|---|
| **Ozon** | 保存按钮是**「保存并移入待发布」**;价格 **CNY**;改价必须**同时抬高原价**,否则 `售价需小于原价`;回读走 API `variantList[].price(原价)/salePrice(售价)` |
| **TikTok** | 价格 **MYR**;店铺**锁站点**(一个品牌 × 多站点);图片 store 直接吃**外链数组** |
| **Shopee** | 用**单件模式** `type='single'` 绕开变种;价格 **CNY**;列表字段是 `itemName` **不是** title |
| **Walmart** | 保存体是 **zip 的 multipart**(zip 内 `walmartSave.txt`);Brand 必须**点「无品牌」勾选框**(打字无效);图片必须 **hover → 网络图片** 贴 URL |
| **速卖通** | **`check_box` 属性值必须是数组**(否则 `P.forEach is not a function`);图片列用外链 `{id,url,name,width,height,imgId,checked}` |
| **SHEIN** | **店铺锁品类**(箱包店选不了发夹);类目要**两个规格**(点 `.theme-select-box` 加 `尺寸(Size)`);⚠️ **加规格会重建 SKU 行**,顺序必须「规格 → SKU → 尺码表」 |
| **Temu** | 规格用 **`.theme-value-add`** 块(值输入 + 添加按钮),**必须手动输值再点添加**,改 store 无效;报错层层递进 |
## 4. 图片
全部用**外链**(alicdn 等),且必须**无水印**(平台会删带联系方式的图)。
字段形如 `{url, imgUrl, name, width, height}`,多数平台存**数组**,
Walmart 例外(必须走「网络图片」UI,落成 `|` 分隔字符串)。
## 5. 定价口径
Ozon ≤500g 档(用户给定的表,已解出公式):
```
运费成本 = 4.2 + 重量(g) × 0.045
合计成本 = 进货价 + 运费成本
售价 = 合计成本 ÷ (1 − 20%佣金 − 利润率)
价格带 = 0–1500₽ / 0–113¥(≈13.27₽/¥)
```
其它档:budget 500-2500g `重量×0.02345+15.96`;small 1-2000g `重量×0.02534+14.07`。
跨币种:MYR ≈ CNY×0.60;USD = CNY÷6.68525(店小秘 `siteAndUsCurrencyRate`)。
## 6. EAN-13 台账(湖北易千亿彩 · 69803093 段)
- 结构:`69803093` + 4 位产品码 + 1 位校验
- 校验:`(10 - sum(d*(1 if i%2==0 else 3) for i,d in enumerate(d12)) % 10) % 10`
(左起权重 1,3,1,3…;**UPC-A 权重相反**)
- 台账唯一来源 **S03 `/root/ean_*.txt`**(KVM-2 够不到)→ 用号后**必须去 S03 落盘**,否则撞号
- 说明书 §1 例子 `pc 1000 → 6980309310004` 是**错的**,正确 `6980309310007`
## 7. 批量作业约定
- 动辄 1 小时 → `nohup bash run.sh > out.log 2>&1 &` 后台跑,**每条一个日志文件**
- 脚本写成「一个 oid 一条命令」+ shell 循环,**单条失败不拖垮整批**
- **跑之前先检查是否已存在**,否则重试会产生重复(本会话踩过:某商品被建了 3 份)
- 删重复:速卖通 `POST /api/smtProduct/batchDelete.json` body `ids=<idStr>`