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:
143
README.md
143
README.md
@@ -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`,则更适合当作你理解新增自动化功能的第一条例子。
|
||||||
|
|||||||
Reference in New Issue
Block a user