Clarify the current automation example in onboarding docs

Update the README so new contributors start from the latest patrol-delete automation flow instead of treating delete-brand as the primary example. Keep the older delete-brand path as contrast for the file-driven workflow.

Constraint: Recent repository changes made patrol-delete the newest automation module, so the onboarding example needed to match current development reality
Rejected: Leave delete-brand as the primary example | would mislead readers about the latest automation entry point
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Revisit this section when a newer automation module replaces patrol-delete as the primary example
Tested: README diff review
Not-tested: lint, typecheck, unit/integration tests not run (documentation-only change)
This commit is contained in:
koko
2026-04-22 08:33:02 +00:00
parent f6e83352d7
commit dc6ecc1edf

143
README.md
View File

@@ -131,55 +131,61 @@
另一套 Python 后端实现,和当前主线职责不完全一致,更像旧后台线。 另一套 Python 后端实现,和当前主线职责不完全一致,更像旧后台线。
## 用“删除品牌自动化”看懂整个系统 ## 用“patrol-delete”看懂最近新增的自动化链路
“删除品牌”是这个仓库里很有代表性的一条链路,因为它同时经过: 从最近的提交看,`patrol-delete` 是当前最新落地的一条自动化模块。它同样同时经过:
- 前端 - 前端
- Python 桌面桥接 - Python 桌面桥接
- Python 自动化执行 - Python 自动化执行
- Java 任务系统 - Java 任务系统
下面按真实职责来拆。 但它和“删除品牌”有一个关键差别:
### 1. 用户在前端选择文件 - `delete-brand` 更偏“本地 Excel 文件驱动”
- `patrol-delete` 更偏“店铺输入 + 任务模板 + 串行自动化执行”
用户打开删除品牌页面后,前端并不会直接访问浏览器文件系统,而是通过 `pywebview` 调 Python 暴露的方法: 如果你想快速理解当前新增自动化功能的开发方式,优先看这条线更合适。
- 选择 Excel 文件 下面按职责来拆。
- 或选择一个文件夹并展开其中的 Excel
这一阶段文件还在用户本地磁盘上。 ### 1. 用户先在前端输入店铺,并加入备选区
### 2. Python 先把本地文件上传给 Java 用户打开 `patrol-delete` 页面后,不是先选本地文件,而是:
前端拿到本地路径后,会继续通过 `pywebview` 调 Python 的文件上传桥接。 - 输入店铺名
- 将店铺加入备选区
- 勾选要处理的店铺
- 点击“匹配店铺”
这一步的实际执行者是 Python不是前端浏览器。Python 会: 这一阶段前端的核心职责是收集“要处理哪个店铺”。
1. 按本地路径读取文件 ### 2. 前端先让 Java 做店铺匹配
2. 调用 Java 的 `/api/files/upload`
3.`multipart/form-data` 上传 前端不会直接把“店铺名”交给 Python 执行,而是先调用 Java 的匹配接口。
4. 从 Java 换回一个 `fileKey`
Java 在这一阶段负责:
1. 根据店铺名查索引
2. 判断是否能命中店铺
3. 返回 `shopId`、平台、公司、匹配状态等信息
这里要注意: 这里要注意:
- 这是 `Python -> Java` - 这是 `frontend -> Java`
- 的是源文件 - 的是先把“可执行店铺”筛出来
- 目的是让 Java 后续能基于 `fileKey` 找到文件 - Python 还没有开始实际自动化
### 3. 前端要求 Java 创建“删除品牌任务” ### 3. 前端要求 Java 创建“patrol-delete 任务”
文件上传完成后,前端调用 Java 的删除品牌运行接口。 匹配通过后,前端调用 Java 的建任务接口。
Java 在这一阶段做的事情不是“真的去删店铺里的 SKU”,而是: Java 在这一阶段做的事情不是“立刻去删商品”,而是:
1. 根据 `fileKey` 找到上传文件 1. 接收店铺与模板结构
2. 解析删除品牌 Excel 2. 创建 `taskId`
3. 按国家和 ASIN 组织数据 3. 创建结果记录
4. 尝试匹配对应店铺 4. 返回当前任务项的初始数据给前端
5. 创建 `taskId` 和结果记录
6. 把可执行项返回给前端
这一阶段可以理解成: 这一阶段可以理解成:
@@ -188,13 +194,17 @@ Java 在这一阶段做的事情不是“真的去删店铺里的 SKU”
### 4. 前端把“可执行项”推入 Python 本地队列 ### 4. 前端把“可执行项”推入 Python 本地队列
删除品牌不是由 Java 主动发起 Python 执行的,而是前端把某个任务项再推给 Python。 `patrol-delete` 不是由 Java 主动调用 Python而是前端把任务 payload 推给 Python。
这一步通过 `pywebview` 暴露的 `enqueue_json()` 完成,前端会构造一个类似下面的 payload 这一步通过 `pywebview` 暴露的 `enqueue_json()` 完成,前端会构造一个类似下面的 payload
- `type: delete-brand-run` - `type: patrol-delete-run`
- `taskId` - `taskId`
- `user_id`
- `items` - `items`
- `template_rows`
- `country_sections`
- `cart_ratios`
然后交给 Python。 然后交给 Python。
@@ -208,35 +218,36 @@ Java 在这一阶段做的事情不是“真的去删店铺里的 SKU”
Python 侧有一个任务监听器持续盯着 `JSON_TASK_QUEUE` Python 侧有一个任务监听器持续盯着 `JSON_TASK_QUEUE`
当它收到 `delete-brand-run` 后,会把任务交给线程池,然后按下面的层次处理: `patrol-delete` 这条链路的设计Python 拿到任务后会按店铺串行执行,再在店铺内部做页面自动化。
1. 任务 这一层的职责重点是:
2. 店铺
3. 国家 1. 根据 `taskId` 和店铺信息定位当前任务
4. ASIN 2. 串行执行当前店铺,避免多个店铺同时抢本地浏览器环境
3. 按模板结构产出各国家的删除结果与购物车比例
4. 在执行过程中持续回传 Java
同时Python 会在本地维护当前任务状态,例如: 同时Python 会在本地维护当前任务状态,例如:
- 当前店铺 - 当前店铺
- 当前国家 - 当前步骤
- 当前 ASIN - 已完成/失败数量
- 已处理数量 - 是否需要继续下一个店铺
- 成功/失败计数
这些状态主要服务于 Python 本地执行期,不是前端最终查询任务状态的权威来源。 这些状态主要服务于 Python 本地执行期,不是前端最终查询任务状态的权威来源。
### 6. Python 自动化驱动紫鸟客户端和浏览器 ### 6. Python 自动化驱动紫鸟客户端和浏览器
删除品牌的“真正执行动作”发生在这里。 `patrol-delete` 的“真正执行动作”发生在这里。
Python 不会直接操作普通浏览器,而是先和紫鸟客户端通信,再接管浏览器调试口。大致过程是: Python 不会直接操作普通浏览器,而是先和紫鸟客户端通信,再接管浏览器调试口。大致过程是:
1. 连接或启动本机紫鸟客户端 1. 连接或启动本机紫鸟客户端
2. 打开指定店铺 2. 打开指定店铺
3. 切换国家 3. 进入需要巡店/删除的目标页面
4. 进入库存/目标页面 4. 根据模板中的国家块、状态和数量条件读取页面数据
5. 搜索 ASIN 5. 找到符合删除条件的商品
6. 删除对应 SKU 6. 执行删除并整理结果
所以这一段实际上又分两层: 所以这一段实际上又分两层:
@@ -250,39 +261,49 @@ Python 不会直接操作普通浏览器,而是先和紫鸟客户端通信,
- Python 不是等整个任务做完再一次性提交结果 - Python 不是等整个任务做完再一次性提交结果
- 而是每处理完一部分,就立刻回传给 Java - 而是每处理完一部分,就立刻回传给 Java
删除品牌这里通常是按 ASIN 逐步回传。 `patrol-delete` 这里是按“店铺结果分片”回传,更强调:
- `shopName`
- `submissionId`
- `chunkIndex`
- `chunkTotal`
- `shopDone`
- `countrySections`
- `cartRatios`
- `error`
回传方式: 回传方式:
- `Python -> Java` - `Python -> Java`
- `Content-Type: application/json` - `Content-Type: application/json`
- 接口:`/api/delete-brand/tasks/{taskId}/result` - 接口:`/api/patrol-delete/tasks/{taskId}/result`
回传的数据里会包含: 回传的数据里会包含:
- 当前文件标识 - 当前店铺标识
- `chunkIndex` - `chunkIndex`
- `chunkTotal` - `chunkTotal`
- 当前国家 - 该店铺当前片段的国家结果
- 当前 ASIN - 购物车比例
- 当前累计进度 - 当前片段是否已结束
- 本次处理结果 - 失败时的错误信息
因此,删除品牌这条线里 Python 到 Java 有两种传输: 因此,`patrol-delete` 这条线里更核心的是一类传输:
1. 源文件上传:`multipart/form-data` 1. 执行结果回传:`application/json`
2. 执行结果回传:`application/json`
它不依赖“先上传本地 Excel 文件”这个前置动作。
### 8. Java 负责接收分片、缓存进度、判断是否可以完结 ### 8. Java 负责接收分片、缓存进度、判断是否可以完结
Java 收到 Python 的结果分片后,不会简单地“收一条写一条最终结果”,而是会先做任务系统层面的处理: Java 收到 Python 的结果分片后,不会简单地“收一条写一条最终结果”,而是会先做任务系统层面的处理:
1. 校验 `taskId` 1. 校验 `taskId`
2. 校验分片对应的文件身份 2. `taskId + shopName` 聚合店铺结果
3. 过滤重复分片 3. 过滤重复分片
4. 将结果分片缓存起来 4. 将结果分片缓存起来
5. 更新实时进度 5. 更新实时进度
6. 判断某个文件的分片是否收齐 6. 判断某个店铺是否已 `shopDone`
7. 判断整个任务是否达到 finalize 条件 7. 判断整个任务是否达到 finalize 条件
这一步说明 Java 才是“任务状态和最终结果”的权威系统。 这一步说明 Java 才是“任务状态和最终结果”的权威系统。
@@ -326,10 +347,11 @@ Java 收到 Python 的结果分片后,不会简单地“收一条写一条最
## 这条例子可以类比到哪些模块 ## 这条例子可以类比到哪些模块
删除品牌不是孤例,它更像当前仓库自动化任务的代表模式。 `patrol-delete` 不是孤例,它更像当前仓库最近新增自动化模块的代表模式。
同类模式至少还能看到这些任务类型: 同类模式至少还能看到这些任务类型:
- `patrol-delete-run`
- `delete-brand-run` - `delete-brand-run`
- `product-risk-resolve-run` - `product-risk-resolve-run`
- `shop-match-run` - `shop-match-run`
@@ -341,7 +363,12 @@ Java 收到 Python 的结果分片后,不会简单地“收一条写一条最
2. Python 负责本地自动化执行 2. Python 负责本地自动化执行
3. Java 负责任务状态、结果缓存和最终输出 3. Java 负责任务状态、结果缓存和最终输出
因此,理解删除品牌这条线之后,再看商品风险、店铺匹配、跟价等模块会容易很多。 其中:
- `patrol-delete` 更适合理解“店铺驱动 + 模板驱动”的新链路
- `delete-brand` 更适合理解“本地文件上传 + 文件解析驱动”的旧链路
理解这两条线之后,再看商品风险、店铺匹配、跟价等模块会容易很多。
## 接手时最容易踩的坑 ## 接手时最容易踩的坑
@@ -379,4 +406,4 @@ Python 负责执行期状态;前端面向用户看到的任务状态、历史
- Java 负责任务系统、结果系统、下载系统 - Java 负责任务系统、结果系统、下载系统
- Vue 负责工具页交互和任务发起 - Vue 负责工具页交互和任务发起
“删除品牌自动化”正好把这三层的协作关系完整串了起来 其中,“删除品牌自动化”更适合帮助你理解旧的文件驱动链路;当前最新落地的 `patrol-delete`,则更适合当作你理解新增自动化功能的第一条例子