Update seller store experience

This commit is contained in:
R524809
2026-09-08 16:19:38 +08:00
parent ceb644a3f9
commit 319887726e
25 changed files with 31417 additions and 127 deletions
+36 -1
View File
@@ -6,7 +6,7 @@
这是一个全新的云端产品,不是 `ozon-seller-kit` 的本地版重构。目标用户可拥有多个门店,每个门店只能绑定一个平台;平台自身可支持多个市场、国家、语言和币种。因此语言、币种、类目和发布规则不能写死为 Ozon 或中文/俄文。
当前已完成 pnpm monorepo 初始化:包含 Web、NestJS API、BullMQ Worker、WXT 浏览器扩展、共享 API 契约、数据库包、本地基础设施 Compose 与依赖锁文件。API 已实现健康/readiness、集中配置与安全基础、认证、个人工作空间上下文、平台目录/上下文、门店、水印/素材、采集箱与扩展采集入库;Worker 已具备 Ozon 凭据验证、采集记录清理和来源素材转存消费链路,仓库同步尚未接入。Web 已具备完整前端框架(布局、路由、主题)、登录/注册页、页头平台选择器、店铺管理、水印管理、真实采集箱页面和采集数据测试页;浏览器扩展已提供毛子 ERP 风格的网页登录态同步、悬浮窗及 Ozon/1688/淘宝/天猫首版页面状态解析。不要从旧项目复制 SQLite 模型、无鉴权 API、旧 `/trial/:id` 或商品编辑页组件。可选择性复用已经验证过的纯计价公式、采集扩展思路和 AI 任务经验,但必须先适配多租户和云端边界。
当前已完成 pnpm monorepo 初始化:包含 Web、NestJS API、BullMQ Worker、WXT 浏览器扩展、共享 API 契约、数据库包、本地基础设施 Compose 与依赖锁文件。API 已实现健康/readiness、集中配置与安全基础、认证、个人工作空间上下文、平台目录/上下文、门店、水印/素材、采集箱与扩展采集入库;Worker 已具备 Ozon 凭据验证、采集记录清理和按需来源素材转存消费链路,仓库同步尚未接入。Web 已具备完整前端框架(布局、路由、主题)、登录/注册页、页头平台选择器、店铺管理、水印管理、真实采集箱页面和采集数据测试页;浏览器扩展已提供毛子 ERP 风格的网页登录态同步、悬浮窗及 Ozon/1688/淘宝/天猫首版页面状态解析。不要从旧项目复制 SQLite 模型、无鉴权 API、旧 `/trial/:id` 或商品编辑页组件。可选择性复用已经验证过的纯计价公式、采集扩展思路和 AI 任务经验,但必须先适配多租户和云端边界。
当前运行时基线:Node 24.20.0、pnpm 11.25.0、PostgreSQL 18.6、Redis 7.4.11、MinIO `RELEASE.2025-09-07T16-13-09Z`;Web 默认端口为 `8100`,API 默认端口为 `8200`,扩展 dev server 默认端口为 `8110`(仅本地开发用),Worker 无 HTTP 端口。完整目录、依赖边界与版本表见 [`architecture/project-structure.md`](../architecture/project-structure.md) 和 [`architecture/technology-and-deployment.md`](../architecture/technology-and-deployment.md)。
@@ -127,6 +127,40 @@
- **兼容性提醒:** 已有采集记录不会自动重新解析历史 `normalized_payload`。例如上面的现有记录仍标记为 `ozon-public-2.1.0`,只能验证新素材预览;需重新在来源商品页执行“编辑上架”,系统会覆盖同一采集快照,届时在规范化载荷查看新版属性与描述。
- 已通过扩展 `wxt prepare + tsc + build`、Web `vite build`、`tsx --test test/*.test.mts`(5 项,包括 Ozon 页面快照中“类型/原产国/材料”等 5 个特征和富文本描述样本)以及浏览器测试页实测。
### 1.14 开发进度(2026-09-08):重采集素材任务外键修复
- 修复重复“编辑上架”覆盖来源快照时 `collection_asset_transfers.workspace_id` 为空导致的数据库非空约束错误。根因不在新任务插入:旧的复合外键 `(workspace_id, source_variant_id) ... ON DELETE SET NULL` 在删除旧 SKU 时,会按 PostgreSQL 规则同时清空两个引用列,误将不可为空的 `workspace_id` 设为 `NULL`。
- 覆盖流程现在先将历史素材任务的可空 `source_variant_id` 显式置空,再删除旧 SKU。迁移 `014_collection_asset_variant_fk.sql` 同时把外键改为 `ON DELETE SET NULL (source_variant_id)`,从 schema 层杜绝同类删除操作再次触发该错误。已在本地数据库实际执行并核验最终约束定义。
- 该错误发生在同一数据库事务内,因此报错的旧请求会完整回滚,不会留下半成品变体、转存任务或 Outbox 事件。扩展可在 API 开发进程热重载后直接再次点击“编辑上架”。
- 已通过 API TypeScript 检查、`apps/api/test/extension.e2e.test.ts`(首次采集 → 同组 SKU 重采集 → 快照覆盖)和新增的转存任务 `workspace_id` 断言。
### 1.15 已确认设计(2026-09-08):采集图片按需物化
- **新规则取代“采集即转存”:** 采集阶段仅保存候选来源 URL、图片角色、SKU/规格关联、排序与证据;测试页直接加载来源 URL,以最快速度核对且不产生对象存储和下载费用。`media_asset` 只代表 Atlas 已验证、可稳定编辑与发布的正式素材。
- 用户选图进入编辑时建议转存;加水印可在单次任务中临时下载来源图、仅存水印结果(来源失效后不可重试);AI 改图等需要图片字节,通常先转存或在受控任务中临时下载;AI 成功输出和正式发布图片必须是 Atlas 控制的 `media_asset`。不得把来源 URL 直接提交到目标平台,也不得为下载图片读取来源 Cookie 或绕过防盗链。
- 首期**不做自动删除已选择但未发布素材**。该能力涉及引用、编辑草稿、处理中任务、恢复和误删风险,当前不值得引入。以后如需控成本,只能先考虑清理从未被任何商品、派生任务或发布快照引用的素材,并单独立项。
- 完整决策、场景表、AI/水印边界与按需物化要求见 [`media-storage-strategy.md`](../architecture/media-storage-strategy.md)。后续采集、编辑、AI、水印和发布任务开始前必须先读此文;按需物化已通过 `pending_selection` 候选状态和 `POST /api/collection-items/{id}/asset-materializations` 落地,正式商品编辑页尚未接入选图动作。
### 1.16 开发进度(2026-09-08):采集图片按需转存与来源预览
- 已新增迁移 `015_collection_asset_pending_selection.sql`、`016_collection_asset_pending_selection_default.sql`:为素材处理枚举增加 `pending_selection`,并将新候选的默认状态改为该值。枚举变更和使用它的默认值/索引刻意拆为两个迁移事务,避免 PostgreSQL 新枚举值在同一事务中立即使用的限制。
- `POST /api/extension/materials` 现在只保存来源图片候选,绝不自动创建 `collection.assets.materialize.requested` Outbox 事件或下载图片;快照覆盖会取消旧快照中 `pending_selection`、`queued`、`running` 的候选/任务。返回的 `materialization` 新增 `pending_selection` 计数。
- 已新增受 `Idempotency-Key` 保护的 `POST /api/collection-items/{id}/asset-materializations`:只能选当前快照的 `pending_selection` 候选,转为 `queued` 后创建 operation 并投递现有来源素材 Worker。商品编辑、AI、水印和发布后续均复用此入口;采集测试页不会调用它。
- `/collection-test/{collectionItemId}` 现在直接显示候选的来源 URL;已转存素材仍通过短时受控 URL 预览。页面明确区分“候选,未转存”“等待转存”“转存中”“已转存”等状态,方便核对而无需等待或消耗存储。
### 1.17 开发进度(2026-09-08):采集候选视频(首期)
- 已新增并在本地开发数据库执行 `017_collection_video_candidates.sql`:`collection_asset_transfers` 新增 `media_type`(`image` / `video`)和可选 `poster_url`。共享采集契约的素材项新增 `mediaType`(默认为 `image`)及 `posterUrl`;检查读模型和测试页可区分媒体类型。
- Ozon 仅从固定 `webGallery` / `webVideo` 状态读取视频;1688 仅从旧采集器验证过的 `gallery.fields.video|videos` 状态读取;淘宝、天猫仅从旧采集器验证过的 `item.videos` 状态读取。三者都不扫描页面 `video` 标签,因此不会将评价、推荐或广告视频误采为商品视频。
- 首期候选仅接受 HTTPS 的直接 MP4/WebM URL,并保留可用封面 URL。`blob:`、HLS (`m3u8`)、DRM 与未知格式不采集;Worker 按需转存时以 MP4/WebM 文件魔数复核,图片仍限制 20MB,视频限制 200MB。暂不实现视频转码、封面抽帧、时长/尺寸解析、视频水印或发布。
- `/collection-test/{collectionItemId}` 对未转存视频显示 `preload=none` 原生播放器,对已转存视频使用 Atlas 短时预览 URL;与图片一样,采集本身不下载也不产生存储成本。完整规则见 [`media-storage-strategy.md`](../architecture/media-storage-strategy.md)。
### 1.18 开发进度(2026-09-08):旧采集器结构化路径迁移
- Ozon 解析器已对齐旧采集器的结构化合并方案:`webDescription/webRichContent` 富文本优先,`schema.org Product.description` 为兜底;首屏 `webShortCharacteristics`、默认商品页和详情页返回的 `webCharacteristics/webDetailedCharacteristics` 都会合并去重。`ozon-public-2.3.0` 是对应版本;旧快照必须重新采集。
- 1688、淘宝、天猫已加入受限 MAIN-world 商品状态桥:1688 仅投影公开商品的画廊、SKU、价格、参数等固定字段;淘宝/天猫仅投影 `__ICE_APP_CONTEXT__` 中的公开商品结果。桥不提供任意 window 读取、Cookie、请求头或通用 fetch。新采集器将这些结构化数据、JSON-LD、受限详情 DOM 与既有图片 profile 映射为 Atlas 新 `CollectedProductPayload`。
- `/collection-test/{collectionItemId}` 现单独展示商品描述、类目路径、全部特征表、规格轴、SKU 草稿、素材候选,并保留规范化载荷和原始证据,供解析核对。扩展解析器测试覆盖 JSON-LD 描述兜底、完整特征合并和图片白名单。
## 2. 已确认产品决策
| 主题 | 决策 |
@@ -204,6 +238,7 @@ User → Workspace → Membership / Role
- [商品领域数据模型与 DDL](../architecture/product-domain-data-model.md)
- [幂等与 Transactional Outbox](../architecture/transactional-outbox-and-idempotency.md)
- [数据库角色与 RLS](../architecture/database-security.md)
- [商品采集图片与存储策略](../architecture/media-storage-strategy.md)
- [实现前待决与待落地事项](../reviews/implementation-readiness-open-items.md)
- [浏览器采集插件需求与技术方案](../requirements/collector-browser-extension.md)
- [M2.2 / M2.3 扩展采集交接](./m2.2-m2.3-extension-collection.md)