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