feat(category): 类目树、类目属性、属性字典维护系统构建完成
This commit is contained in:
+62
-6
@@ -293,7 +293,7 @@ M3.5 与 M3.6 均已收口。真实来源回归中若要提升 Ozon 自动类目
|
||||
|
||||
- 类目/商品类型树、类型属性定义和字典候选值归属 `platform_id`,同一平台的全部门店共用,不再按门店复制。Ozon 与未来 Wildberries 等平台分别使用自己的适配器和外部 ID 语义;本阶段**不创建、不读取门店差异层**。
|
||||
- 门店连接、卖家凭据、商品/SKU 已填属性、发布状态和错误仍是工作空间业务数据。平台参考目录不保存客户商品、价格、库存或发布事实。
|
||||
- 这项平台级能力已经独立落地,但商品编辑器仍使用 `022_store_catalog_cache.sql` 的门店级类目 UUID、属性和字典 API。不得直接删除旧表或把新旧 UUID 混用;编辑器迁移必须通过 Ozon 外部 ID 做双读/回填后再切换。
|
||||
- 商品编辑器已由迁移 `027` 和新版 API 切到平台级类目 UUID、属性和字典缓存。`022_store_catalog_cache.sql` 的门店表与列暂时保留为兼容/回滚数据,不得在发布链路迁移完成前删除。
|
||||
|
||||
#### 1.33.2 类目树、属性和字典的标识规则
|
||||
|
||||
@@ -357,12 +357,68 @@ BullMQ Worker(最多 5 次,5 秒起指数退避)
|
||||
|
||||
1. 调整定时调度公平性:树之后不能等待全部类型属性完成才开始字典;应在属性和字典之间设置配额/轮转,并优先近期使用或管理员选中的类型。
|
||||
2. 为超过 10000 项的大字典实现可续传游标或分片同步周期。当前任务会正确标记 `is_complete=false`,但下一次仍从头读取,不能持续推进到第 10001 项以后。
|
||||
3. 将商品编辑器由门店级缓存迁移到平台级目录:按 `description_category_id + type_id` 和属性 ID 回填,先双读/兼容保存,再切换外键和 API,最后才讨论清理 `022` 表。
|
||||
3. ~~将商品编辑器由门店级缓存迁移到平台级目录。~~ 已由第 3 步完成;后续只在发布迁移和稳定性验证后讨论清理 `022` 表。
|
||||
4. 增加平台目录 PostgreSQL 集成测试,覆盖系统管理员隔离、凭据版本替换、手动幂等复用、定时去重、失败保留旧缓存、完整字典停用旧值及跨平台 ID 拒绝。
|
||||
5. 在浏览器完成管理员菜单、直达路由、凭据弹窗、任务轮询、类目/属性/字典展示的回归,并确认 API/Worker 进程都使用迁移后的当前代码。
|
||||
|
||||
完整架构边界见 [`platform-product-reference-catalog.md`](../architecture/platform-product-reference-catalog.md),HTTP 契约见 [`platform-catalog-admin.md`](../api/platform-catalog-admin.md)。
|
||||
|
||||
### 1.34 开发进度与交接(2026-09-20):平台目录刷新方案第 1 步
|
||||
|
||||
第 1 步后端基础已完成,尚未开始系统后台页面、商品编辑器和发布链路迁移:
|
||||
|
||||
- 新增并实际应用 `025_platform_catalog_refresh_policy.sql`、`026_platform_catalog_refresh_policy_audit.sql`:按平台保存类型属性/字典的 14/21 天默认策略及不可变的阈值修改前后值;按 tree、attributes、dictionary、dictionary_search 保存独立资源状态;为同步 run 增加 high/low 优先级和提升时间;增加管理员属性批次及固定类型快照。没有创建门店级新表,也没有删除旧缓存。
|
||||
- 迁移从历史成功 run 回填资源状态。应用后实际回读:Ozon 共有 7365 个活动可发布类型,其中 687 个类型属性 fresh、6678 个 missing,stale/expired 均为 0;另回填 1 个树状态和 1 个字典状态。默认策略已为所有现有平台写入 14/21 天。
|
||||
- 平台目录调度器已改为只自动维护每周类目树。类型属性和字典不再进入周期自动候选;属性只从管理员批次中每个平台最多 6 个活动任务地逐步领取,字典保留单项任务。管理员批次支持 `missing_expired`、`missing_stale_expired`、`all` 三种冻结范围。
|
||||
- 新增刷新策略、属性状态汇总、批次创建/列表/详情管理 API。相同平台一次只允许一个活动属性批次;空批次返回明确错误;批次允许部分失败。现有树/单属性/单字典接口保持兼容。
|
||||
- 平台 run 和独立 BullMQ 队列 `atlas-platform-catalog` 已支持 high/low 优先级;missing/严格超过过期阈值为 high,恰好 21 天仍为 low。低优先级 queued 任务可提升并复用同一 run,不能打断已经 running 的请求;旧 `atlas-dispatch` 暂时保留消费历史平台任务的兼容分支。
|
||||
- 平台同步成功会在同一发布事务更新 `last_success_at/is_complete` 并清除错误;失败只记录资源错误,不延长新鲜期或清空上次成功缓存。字典管理读取已改用资源状态判断完整性。
|
||||
- 已通过 API/Worker/Database TypeScript 检查、5 项系统管理员参数单元测试和 9 项 Worker 测试;迁移已在真实 PostgreSQL 应用,并用回滚事务验证批次/平台外键。`git diff --check` 通过。
|
||||
|
||||
运行态提醒:维护者管理的 API/Worker 进程不会由 AI 重启。若当前 Worker 是修改前启动的旧进程,它仍会执行旧的 24 小时属性候选;需要维护者在检查代码后自行重启 API 和 Worker,新的每周树/无属性字典周期调度才会生效。
|
||||
|
||||
第 1 步已经用户确认,随后完成的第 2 步见下一节;此前已有的类目树固定搜索框和展开修复已保留。
|
||||
|
||||
### 1.35 开发进度与交接(2026-09-20):平台目录刷新方案第 2 步
|
||||
|
||||
第 2 步系统后台页面已完成,尚未开始商品编辑器和发布链路迁移:
|
||||
|
||||
- 「平台类目与属性」页已接入平台刷新策略,可配置类型属性和属性字典各自的新鲜/过期天数;类目树固定 7 天。表单执行 `1..365` 和“过期严格大于新鲜”校验,保存说明明确不会立即创建全量任务。
|
||||
- 缓存新鲜度表单现已从主页面移入弹窗;操作区通过“缓存新鲜度设置”按钮打开。保存成功后关闭弹窗并刷新策略、类目及当前属性状态,保存失败时保留弹窗和用户输入。
|
||||
- “最近同步任务”的手动刷新按钮现显示请求中的 loading 状态;刷新成功提示“同步任务刷新成功”,失败使用统一 API 错误消息。后台每 5 秒静默轮询仍保持无提示,避免周期性打扰管理员。
|
||||
- 类型属性区展示 fresh/stale/expired/missing 汇总以及最近批次。三个操作分别覆盖 missing+expired、missing+stale+expired、全部类型;前两个显示命中数并在 0 时禁用,“同步全部类型属性”为红色危险按钮,必须在含类型数量和耗时提示的二次确认后才请求 API。
|
||||
- 批次表展示完成比例、成功/运行/等待/失败数量与最终状态;同平台存在活动批次时禁用新建。页面每 5 秒静默刷新任务和批次,不让操作按钮周期性闪烁加载态。
|
||||
- 类目树保留此前完成的固定搜索框和手动展开修复,并在可发布叶子展示类型属性缓存状态。选择类型后,属性卡标题重复显示类型状态;字典属性在表格和候选值 Drawer 中展示独立缓存状态、最近成功时间、完整/部分状态及候选值数量,仍保留单字典手动同步。
|
||||
- 最近任务表新增 high/low 优先级以及 weekly、admin_batch、user_access、publish 等触发来源文案。页面主文件只协调状态和请求;刷新策略、属性批次、缓存标签、任务表均拆为独立组件。
|
||||
- API 的类目和属性读模型补充最近资源错误及字典新鲜度字段,用于后台观测;没有改变普通商品编辑 API。
|
||||
- 浏览器实测:页面无横向溢出;类目搜索可自动展开到匹配叶子;missing/fresh 类型状态正确;fresh 类型属性表和 missing 字典 Drawer 正常;全量同步仅打开危险确认层,验收过程没有创建批次或同步任务。
|
||||
|
||||
验证:Web TypeScript 与 production build、API TypeScript/build 和 5 项管理 API 单元测试通过,`git diff --check` 通过。页面在维护者现有 API 上完成浏览器回归;Vite 验收服务使用 5174 并在验收后关闭。API/Worker 未由 AI 启动、重启或停止。
|
||||
|
||||
第 2 步已验收,第 3 步完成情况见下一节;第 4 步也已在用户确认后完成,见 1.37。
|
||||
|
||||
### 1.36 开发进度与交接(2026-09-20):平台目录刷新方案第 3 步
|
||||
|
||||
- 新增并实际应用 `027_product_editor_platform_catalog.sql`。迁移按 `platform_id + description_category_id + type_id` 将既有 `store_product_category_id` 回填到 `platform_product_category_id`,同步回填未映射属性的原平台类目;旧门店列和三张门店缓存表继续保留,新保存会尽量反写对应门店类目 UUID,便于回滚。
|
||||
- 商品编辑器类目树、类型属性和字典全部改读平台级表。切换同平台目标店铺不再清空类目;动态属性 schema 返回 `attribute_id`,字典 API 用该平台属性 UUID 限定候选值,不再只按可能重复的 `dictionary_id` 定位。
|
||||
- 普通读取已实现 14/21 天状态机:fresh 直接返回;stale 返回旧缓存并创建/复用 low `user_access` run;expired/missing 创建/复用 high run,API 最多等待 5 秒,未完成则返回 HTTP `202`、空当前选项和 cache 元数据。前端最多轮询 20 次,过期旧值不进入当前控件。
|
||||
- 平台级部分字典的本地未命中关键词现在使用独立 `dictionary_search:{attribute_id}:{hash}` 作用域。`platform_catalog_sync_runs` 保存规范化 `search_key`;Worker 调 Ozon 搜索接口,命中值先写入 Atlas,再更新该词的成功状态,不会把局部搜索误标为完整字典。
|
||||
- 草稿保存和本地 validation 已改用平台 schema/字典。expired/missing schema 下,只允许原样保留已有属性并保存其他商品字段;类目变化或属性改写会返回刷新中错误。expired/missing 字典不能校验新候选值,旧草稿值仍可保留。
|
||||
- 产品 API 契约更新为 `platform_product_category_id`,过渡期仍接受旧 `store_product_category_id` 并通过外部 ID 映射。属性/字典响应统一返回 `cache.status`、最近成功时间、fresh/expire 时间、完整性、刷新 run 和重试间隔。
|
||||
- 验证已通过:contracts/API/Worker/Web TypeScript;`product-editor.e2e.test.ts` 与 `platform-catalog-admin.unit.test.ts` 共 13 项;迁移在本地 PostgreSQL 成功执行;`027` 约束和旧引用回填已实际验证。API/Worker 未由 AI 启动、重启或停止。
|
||||
|
||||
第 4 步首次发布预检已完成,见下一节。旧门店目录表暂不清理;需要等待真正的 Ozon 发布 job 复用预检服务并完成稳定性验证后另行决策。
|
||||
|
||||
### 1.37 开发进度与交接(2026-09-20):平台目录刷新方案第 4 步
|
||||
|
||||
- 新增 `POST /api/product-platform-profiles/{profile_id}/publish-preflights`。请求明确给出本次待首次上架的 `variant_ids`;只接受当前 profile 下 `not_listed` / `failed` 的未删除 SKU,拒绝 imported、submitting、跨商品和已删除 SKU。
|
||||
- 发布预检先检查当前 `platform_product_category_id` 的 schema。fresh 直接使用;stale 使用缓存并创建/复用 low `publish` 任务;expired/missing 创建/复用 high `publish` 任务。低优先级 queued 任务在资源过期后复用原 run 并提升为 high。
|
||||
- schema 可用后,只从本次 SKU 集合的已确认商品/SKU 属性草稿提取实际使用的字典。未填写的可选字典、其他 SKU 和同类型下未使用字典都不会创建任务;不扫描其他类型,也不使用旧门店目录。
|
||||
- 多个 high schema/字典任务共用一个最多 5 秒等待窗口。schema 刷新成功后会基于新 schema 再计算字典依赖;窗口内未完成返回 HTTP `202` 和 `status=refreshing`,客户端可重试同一预检,不能退回过期缓存。
|
||||
- 最终本地校验除标题、型号、品牌、必填属性、offer ID、价格、包装和图片外,新增“所用字典缓存未过期且候选 ID 仍为活动值”检查。stale 字典可以完成本次发布校验并在后台刷新;expired/missing 会返回刷新中问题。
|
||||
- 预检响应包含 schema 与每个已用字典的统一 cache 元数据,以及本次创建/复用的目录 runs。真正的 `product_publish_job`、发布快照、Ozon `/v3/product/import` 调用和轮询仍未实现;预检 ready 不能解释为已提交或已发布。
|
||||
- 代码按目录编排、最终校验、HTTP 入口拆分在独立组件中,没有把逻辑继续堆入 `product-editor.service.ts`。API 集成测试覆盖 stale 的 low publish 任务、expired 的 high 提升、只刷新已用字典和不触达未用字典。
|
||||
|
||||
## 2. 已确认产品决策
|
||||
|
||||
| 主题 | 决策 |
|
||||
@@ -381,7 +437,7 @@ BullMQ Worker(最多 5 次,5 秒起指数退避)
|
||||
| 采集 SKU | 只有来源给出稳定 SKU/组合证据时创建多个 SKU;不能把规格轴做笛卡尔积。没有专属 SKU 图时,真实 SKU 继承父商品默认图而不复制资产。 |
|
||||
| 媒体 | 采集主图/详情图是商品候选池;来源明确给出 SKU、或可靠的规格轴值(如颜色)与图片关系时才自动绑定。其余素材由编辑页人工选择。 |
|
||||
| 发布与在线商品 | 商品采集、编辑、定价、AI 媒体和首次导入至 Ozon 后台是核心闭环。正式发布使用官方 Seller API,按一 SKU 一 import item/offer 执行并轮询结果;首期不传库存或仓库,用户在 Ozon 后台设置库存。已导入 SKU 不可再次上架,未上架 SKU 仍可首次上架;SPU 在当前平台汇总为未上架/已部分上架/已上架。在线商品由异步 Ozon API 同步,按 Ozon 商品 SKU 展示,亦包含非 Atlas 发布商品。 |
|
||||
| 平台商品参考目录 | `platform_id` 下共享类目/类型树、属性定义和字典候选值;同平台门店共用,本阶段不维护门店差异层。定时同步、系统管理员页面和手动排队已实现;商品编辑器的门店级引用待迁移,见 [`platform-product-reference-catalog.md`](../architecture/platform-product-reference-catalog.md)。 |
|
||||
| 平台商品参考目录 | `platform_id` 下共享类目/类型树、属性定义和字典候选值;同平台门店共用,本阶段不维护门店差异层。定时同步、系统管理员页面、手动排队、商品编辑器读取和发布预检已实现;真正的 Ozon 发布 job 待开发。 |
|
||||
|
||||
## 3. Ozon 已核对结论
|
||||
|
||||
@@ -424,12 +480,12 @@ User → Workspace → Membership / Role
|
||||
|
||||
下一步建议按以下顺序推进:
|
||||
|
||||
> 注意:下面的清单不能覆盖 2026-09-18 的 [Ozon 参考目录决策](../architecture/platform-product-reference-catalog.md)。平台目录、后台和同步基础链路已经实现;现有门店级商品编辑契约在完成兼容迁移前继续生效。
|
||||
> 注意:下面的清单不能覆盖 2026-09-18 的 [Ozon 参考目录决策](../architecture/platform-product-reference-catalog.md)。平台目录、后台、同步基础链路和商品编辑器迁移已经实现;旧门店目录只作为兼容/回滚数据保留。
|
||||
|
||||
当前执行顺序:
|
||||
|
||||
1. 完成平台目录首次预热并修正属性/字典调度公平性和大字典续传;补 PostgreSQL 集成测试与系统管理员浏览器回归。
|
||||
2. 按 Ozon 外部 ID 建立新旧目录映射和双读,迁移商品编辑器到平台级类目、属性和候选值;在验证前保留门店级缓存与外键。
|
||||
1. 将真正的 `publish-jobs` 创建事务接入已经完成的发布预检服务,固化发布快照后再实现 Ozon `/v3/product/import` 与结果轮询;不得重新实现另一套目录判断。
|
||||
2. 完成平台目录首次预热并修正大字典续传;补系统管理员浏览器回归。旧门店目录继续保留,暂不清理。
|
||||
3. 在真实采集来源中继续回归候选媒体按需物化,然后完成定价、AI 任务、首次发布和在线商品同步的剩余纵向闭环。
|
||||
|
||||
### 历史计划(仅供追溯)
|
||||
|
||||
Reference in New Issue
Block a user