Files
inkreach-official-website/data-cleaning

商品数据清洗(Goods Data Cleaning

本目录存放商品数据清洗相关的全部脚本与规则文件。清洗目标:把右侧 SDS 原产品库 (origin_goods)按规则批量配置为左侧官网商品(goods),替代后台手动逐个点击。

转换规则调查(2026-08-27,基于生产环境只读数据)

数据来源:https://official.inkreach.cc/api 生产接口(JWT 只读拉取): /origin-goods?page=1..3&pageSize=200(共 552 条)、/goods?page=1..2&pageSize=200(共 240 条)、 /tags/categories/countries。未做任何写操作。 原始 JSON 快照存于 runs/survey-2026-08-27/(已加入 .gitignore,不入库)。

1. 右侧原产品(origin_goods)命名结构

右侧只有一个字符串 goodName,整体模式:

国家(物流备注)品名-SKU-工艺位置[-仓库名]
  ↑        ↑         ↑    ↑     ↑
  |        |         |    |     └─ 可选第4段:美西洛杉矶一仓 / 美中亚特兰大仓 等
  |        |         |    └─ 单面印花 / 双面印花 / 直喷双面 / 直喷单面 / 不打印 ...
  |        |         └─ SKU 编码(字母+数字,如 DG001 / C1717 / KRHM003
  |        └─ 包邮 / 不包邮 / DHL包邮*运费结算订单时支付 / 不包邮光板 等变体
  └─ 美国/德国/韩国...(全角括号为主,少量半角混用)

统计(552 条):

  • 541 条匹配 国家(备注)其余 模式;11 条异常
    • 4 条自定义商品(Goods Origin ...source=CUSTOM
    • 2 条缺国家前缀:(不包邮)230g水洗炒雪花T恤-双面印花 / (不包邮)180g纯棉T恤成人款-...
    • 1 条用空格代替括号:法国 180g纯棉T恤-FRTM001-双面印花
    • 2 条半角左括号混用:美国(不包邮)女士高弹中长款瑜伽运动裤-JSD004-...
    • 2 条同上变体
  • 「备注)之后」按 - 分段:387 条 = 3 段(品名-SKU-工艺)、154 条 = 4 段(品名-SKU-工艺-仓库)
  • 物流备注出现的变体形态(示例):包邮不包邮DHL包邮DHL包邮*运费结算订单时支付包邮*运费订单结算时支付不包邮光板
  • 国家前缀出现过的值:美国、德国、英国、意大利、西班牙、西班牙直发、韩国、日本、加拿大、墨西哥、巴西、波兰、澳大利亚

2. 左侧已配置商品(goods)现状 —— 人工配置的实际结果

240 条 goods 记录,覆盖 209 个不同 origin_good_id343 个 origin 尚未配置)。

没有系统级拆分逻辑:前端 GoodsView.vue 提交的是完整原名, 后端 goods.service.ts create/batchCreate 也原样入库。 因此左侧名称与右端的差异(113/240 条被改过)全部是人工在编辑弹窗里改的,且存在多种风格并存。

改名风格分布(113 条改名的归类):

风格 数量 示例
A. 全拆:去前缀去括号,品名+空格+SKU,丢弃工艺段 27 韩国(包邮)200g纯棉T恤-KRTM001-单面印花200g纯棉T恤 KRTM001
B. 半改:仅把长备注缩成「X包邮」,其余原样保留 86 德国(DHL包邮*运费结算订单时支付)230g水洗T恤-DETM002-单面印花德国(DHL包邮)230g水洗T恤-DETM002-单面印花
R0. 保持原名不动 127 多为后期配置(2026-06 后期 ~ 07),未加工

标签体系(生产库现有 3 组 7 个标签)与左侧使用情况:

分组 标签(id) 左侧使用次数
物流渠道 包邮(30) / 不包邮(31) 87 / 153 ← 基本每个商品都挂了物流标签
印刷位置 双面印(35) / 单面印(34) 14 / 14 ← 只有少数挂了
印刷工艺 烫画(32) / 直喷(33) / 不打印(42) 11 / 3 / 1

其他字段:goodPriority 几乎全部为 5positionId 全部为空; 国家字段与名称里的国家前缀一致率 238/240(仅 西班牙直发(...) 两条归入了「西班牙」)。

3. 从字符串解析出的隐含规则(草稿,待确认)

一条原产品字符串可以机械解析出以下信息(541/552 可完全机器解析):

解析项 来源 对应目标字段
国家 第一个 之前文本(需处理:空格分隔、半角括号、「西班牙直发→西班牙」映射) countryId
物流渠道 括号内含「包邮」与否 → 包邮 / 不包邮 tag: 物流渠道
工艺/印刷位置 最后一段的 关键词:单面印花→单面印、双面印花→双面印、直喷→直喷、烫画→烫画、光板/不打印→不打印 tags: 印刷位置 + 印刷工艺
展示名 目标形态(用户口径):品名 SKU(最后一个 - 连接改为空格连接,丢弃工艺/仓库段) goodName

4. 待确认问题(规则定稿前必须回答)

  1. 展示名采用哪种?A 全拆(200g纯棉T恤 KRTM001,推荐—— majority 且官网展示干净)还是 B 保留国家括号?
  2. 同一基础商品的「单面印花」「双面印花」是拆成两个 goods(现状),还是合并为一个 good 并用标签区分? (注意 A 全拆后两者 goodName 完全相同,如 ITTM001 已出现重名两条)
  3. 历史 R0 的 127 条保持原名的记录是否要统一重命名?
  4. 未配置的 343 个 origin 是本次要全部自动配置的目标吗?(其中可能有不应上架的商品)
  5. 仓库名后缀(第 4 段)只做清洗忽略即可,还是需要保留到某个字段?
  6. 国家中文名 → countries 表的映射以 countryName 精确匹配为准?缺失国家(如法国 FRTM001 对应的国家若不存在)如何处理?

执行流水线

[生产库]
   │ ① 备份(pg_dump 全量,安全网)
   ▼
② apps/api/scripts/export-data.mjs 导出 JSON(现有脚本)
   ▼
③ sync-transform.mjs 转换脚本 + sync-rules.config.mjs 规则文件(本目录,待创建)
      读取导出 JSON → 按规则加工 → 输出待导入 JSON + 变更摘要报告(人工检查点)
   ▼
④ apps/api/scripts/import-data.mjs 导入生产库(现有脚本)
   ▼
⑤ 验证:行数对比 / 抽查商品配置 / 官网公开 API 抽查

原则:三步式独立执行,每步可检查、可回滚;规则只改 sync-rules.config.mjs,不改代码; 导入前必须有全量备份;转换脚本为纯函数式(JSON in → JSON out),不直接连接数据库。

目录内容规划

文件 状态 说明
sync-rules.config.mjs 待创建 同步规则文件(品类映射 / 国家分配 / 标签分配 / 优先级策略),规则未定,先占位
sync-transform.mjs 待创建 数据转换脚本
runs/ 待创建 每次执行的导出、转换产物与变更摘要报告(按日期归档);已含 survey-2026-08-27/ 调查快照(gitignore

详细实施计划见 plans/feature/goods-data-cleaning-feature.md