koko f6e83352d7 Document repo structure and ignore local OMX state
Add a root README that explains the active runtime layers and onboarding path, and keep local OMX session state out of version control so developer tooling does not interfere with pulls.

Constraint: Local OMX state is developer-specific and should not block branch sync or appear in shared history
Rejected: Keep onboarding notes untracked | easy to lose and hard to share with the team
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the README aligned with the active app/backend-java/frontend-vue execution path; revisit if the runtime architecture changes
Tested: git diff review; git status after staging
Not-tested: lint, typecheck, unit/integration tests not run (docs and ignore rules only)
2026-04-22 07:16:04 +00:00
2026-04-22 01:09:47 +08:00
2026-04-06 22:26:44 +08:00
2026-04-06 22:26:44 +08:00

crawler-plugin

这个仓库是什么

这个仓库不是一个“单体项目”,而是一个混合工作目录。当前更像是以下三层共同组成的一套系统:

  • app/Python 桌面宿主、Flask 页面承载层、pywebview 本地桥接层、自动化任务入口
  • backend-java/:Java 业务后端,负责任务模型、文件处理、进度缓存、结果组装、落库、下载
  • frontend-vue/:Vue 多页面前端,负责工具页交互和任务发起

如果你是第一次接手这个仓库,不要先把它理解成:

  • 纯 Java 后端项目
  • 纯 Python 自动化项目
  • 纯前后端分离 Web 项目

它当前的真实形态更接近:

Vue 页面 -> Python 桌面桥接/Flask -> Java 任务系统 -> Redis / DB / OSS

同时,Python 自动化还会再去驱动本地紫鸟客户端和浏览器。

先看哪里

如果你的目标是理解当前主线,请按这个顺序读:

  1. app/
  2. backend-java/
  3. frontend-vue/

原因很简单:

  • app/ 决定了桌面端怎么承载页面、怎么暴露本地能力、怎么把任务推给 Python 自动化
  • backend-java/ 决定了任务怎么创建、状态怎么缓存、结果怎么回传、文件怎么生成和下载
  • frontend-vue/ 决定了用户是怎么触发这些链路的

以下目录不要默认当成当前主线:

  • source_code/
  • backend/

它们和 app/ 有明显重叠,更像历史版本、迁移残留或中间态副本。阅读时要先带着“可能不是当前生效版本”的假设。

主线架构怎么分工

Python 层:桌面壳 + 本地桥接 + 自动化执行

app/ 不是单纯的业务后端。它更像一个桌面宿主,负责三件事:

  • 承载 Flask 页面和登录态
  • 通过 pywebview 暴露本地文件选择、保存文件、上传文件、任务入队等能力
  • 启动和调度 Python 自动化任务

这一层解决的是“本地能力”和“桌面壳”的问题,不是最终任务结果的权威存储。

Java 层:任务系统 + 结果系统

backend-java/ 是当前业务核心后端,负责:

  • 文件上传与临时文件管理
  • 任务创建、历史查询、批量轮询
  • Redis 进度缓存
  • 分片结果接收与聚合
  • 结果文件生成
  • OSS 上传
  • 下载接口输出

从模块名看,Java 端已经承接了大部分工具型任务,例如:

  • brand
  • dedupe
  • split
  • convert
  • deletebrand
  • productrisk
  • shopmatch
  • pricetrack

Vue 层:多页面工具前端

frontend-vue/ 不是单页应用,而是多入口页面工程。它的作用主要是:

  • 让用户选择文件或参数
  • 调用 Java API 创建任务或查询任务
  • 调用 pywebview 桥接拿本地能力
  • 在任务执行过程中轮询状态和下载结果

它构建后的产物输出到 new_web_source/,再由 Python/Flask 暴露出来供桌面端使用。

如何理解目录

当前最值得关注的目录

app/

这是当前阅读优先级最高的 Python 目录,重点看这些角色:

  • main.py:创建 pywebview 窗口,暴露本地桥接 API
  • app.pyFlask 应用入口
  • blueprints/:页面、登录、品牌、通信等 HTTP 层
  • amazon/:删除品牌、商品风险、匹配、跟价等自动化任务实现

backend-java/

这是任务系统核心,重点关注:

  • controller:对外 API
  • service:任务创建、进度、结果回传、组装
  • model / mapper:任务和结果模型
  • application.yml:后端依赖配置

frontend-vue/

这是当前工具页前端源码,重点关注:

  • src/shared/bridges/pywebview.ts:前端如何调 Python 本地桥接
  • src/shared/api/java-modules.ts:前端如何调 Java API
  • src/pages/brand/components/:各个具体工具页

不要误判成源码主线的目录

new_web_source/

更像前端构建产物目录,不是首选手改源码位置。

source_code/

app/ 结构高度相似,但从当前仓库关系看,更像旧线或中间迁移副本。

backend/

另一套 Python 后端实现,和当前主线职责不完全一致,更像旧后台线。

用“删除品牌自动化”看懂整个系统

“删除品牌”是这个仓库里很有代表性的一条链路,因为它同时经过:

  • 前端
  • Python 桌面桥接
  • Python 自动化执行
  • Java 任务系统

下面按真实职责来拆。

1. 用户在前端选择文件

用户打开删除品牌页面后,前端并不会直接访问浏览器文件系统,而是通过 pywebview 调 Python 暴露的方法:

  • 选择 Excel 文件
  • 或选择一个文件夹并展开其中的 Excel

这一阶段文件还在用户本地磁盘上。

2. Python 先把本地文件上传给 Java

前端拿到本地路径后,会继续通过 pywebview 调 Python 的文件上传桥接。

这一步的实际执行者是 Python,不是前端浏览器。Python 会:

  1. 按本地路径读取文件
  2. 调用 Java 的 /api/files/upload
  3. multipart/form-data 上传
  4. 从 Java 换回一个 fileKey

这里要注意:

  • 这是 Python -> Java
  • 传的是源文件
  • 目的是让 Java 后续能基于 fileKey 找到文件

3. 前端要求 Java 创建“删除品牌任务”

文件上传完成后,前端调用 Java 的删除品牌运行接口。

Java 在这一阶段做的事情不是“真的去删店铺里的 SKU”,而是:

  1. 根据 fileKey 找到上传文件
  2. 解析删除品牌 Excel
  3. 按国家和 ASIN 组织数据
  4. 尝试匹配对应店铺
  5. 创建 taskId 和结果记录
  6. 把可执行项返回给前端

这一阶段可以理解成:

  • Java 负责建模和建任务
  • Python 还没有开始自动化执行

4. 前端把“可执行项”推入 Python 本地队列

删除品牌不是由 Java 主动发起 Python 执行的,而是前端把某个任务项再推给 Python。

这一步通过 pywebview 暴露的 enqueue_json() 完成,前端会构造一个类似下面的 payload:

  • type: delete-brand-run
  • taskId
  • items

然后交给 Python。

重要区分:

  • 这一步不是 Java 队列
  • 这是 Python 本地进程内队列
  • 当前仓库里对应的是 JSON_TASK_QUEUE

5. Python 的任务监听器开始消费队列

Python 侧有一个任务监听器持续盯着 JSON_TASK_QUEUE

当它收到 delete-brand-run 后,会把任务交给线程池,然后按下面的层次处理:

  1. 任务
  2. 店铺
  3. 国家
  4. ASIN

同时,Python 会在本地维护当前任务状态,例如:

  • 当前店铺
  • 当前国家
  • 当前 ASIN
  • 已处理数量
  • 成功/失败计数

这些状态主要服务于 Python 本地执行期,不是前端最终查询任务状态的权威来源。

6. Python 自动化驱动紫鸟客户端和浏览器

删除品牌的“真正执行动作”发生在这里。

Python 不会直接操作普通浏览器,而是先和紫鸟客户端通信,再接管浏览器调试口。大致过程是:

  1. 连接或启动本机紫鸟客户端
  2. 打开指定店铺
  3. 切换国家
  4. 进入库存/目标页面
  5. 搜索 ASIN
  6. 删除对应 SKU

所以这一段实际上又分两层:

  • Python -> 紫鸟客户端:本地 HTTP IPC
  • Python -> 浏览器:通过调试口/自动化驱动执行页面操作

7. Python 一边执行,一边把结果分片回传给 Java

这条链路的关键点在这里:

  • Python 不是等整个任务做完再一次性提交结果
  • 而是每处理完一部分,就立刻回传给 Java

删除品牌这里通常是按 ASIN 逐步回传。

回传方式:

  • Python -> Java
  • Content-Type: application/json
  • 接口:/api/delete-brand/tasks/{taskId}/result

回传的数据里会包含:

  • 当前文件标识
  • chunkIndex
  • chunkTotal
  • 当前国家
  • 当前 ASIN
  • 当前累计进度
  • 本次处理结果

因此,删除品牌这条线里 Python 到 Java 有两种传输:

  1. 源文件上传:multipart/form-data
  2. 执行结果回传:application/json

8. Java 负责接收分片、缓存进度、判断是否可以完结

Java 收到 Python 的结果分片后,不会简单地“收一条写一条最终结果”,而是会先做任务系统层面的处理:

  1. 校验 taskId
  2. 校验分片对应的文件身份
  3. 过滤重复分片
  4. 将结果分片缓存起来
  5. 更新实时进度
  6. 判断某个文件的分片是否收齐
  7. 判断整个任务是否达到 finalize 条件

这一步说明 Java 才是“任务状态和最终结果”的权威系统。

9. Java 在分片收齐后生成最终结果

当 Java 发现所有需要的结果分片都已收齐时,会执行最终组装:

  1. 合并分片
  2. 重建最终结果数据
  3. 生成结果 Excel
  4. 上传 OSS
  5. 更新任务状态
  6. 写入结果记录

如果这一步成功,任务会变成 SUCCESS;否则会进入 FAILED

10. 前端轮询 Java,不轮询 Python

前端展示任务状态时,查询对象是 Java,而不是 Python 本地队列。

前端主要关心的是:

  • 任务详情
  • 批量进度
  • 下载地址

也就是说:

  • Python 负责执行
  • Java 负责对前端提供任务状态与结果

11. 前端最终通过 Java 下载结果,再交给 Python 保存到本地

任务成功后,前端拿到 Java 下载地址,然后再通过 pywebview 调 Python 的保存能力,把文件落回用户本地磁盘。

所以最后一步仍然是混合协作:

  • 下载来源是 Java
  • 本地保存能力来自 Python 桌面桥接

这条例子可以类比到哪些模块

删除品牌不是孤例,它更像当前仓库自动化任务的代表模式。

同类模式至少还能看到这些任务类型:

  • delete-brand-run
  • product-risk-resolve-run
  • shop-match-run
  • price-track

它们的共性通常是:

  1. 前端先建任务
  2. Python 负责本地自动化执行
  3. Java 负责任务状态、结果缓存和最终输出

因此,理解删除品牌这条线之后,再看商品风险、店铺匹配、跟价等模块会容易很多。

接手时最容易踩的坑

不要把 enqueue_json() 当成 Java 队列

它是前端调 Python 的本地桥接,进入的是 Python 进程内队列,不是 Java 消息系统。

不要把 new_web_source/ 当成首选源码目录

它更像构建产物输出,首选还是看 frontend-vue/

不要默认 source_code/backend/ 仍是当前主线

这两个目录有参考价值,但从当前结构看,不应先于 app/backend-java/frontend-vue/ 阅读。

不要把 Python 当成最终任务状态来源

Python 负责执行期状态;前端面向用户看到的任务状态、历史、下载结果,当前主权在 Java。

当前文档的边界

这份 README 基于当前仓库的静态分析整理,有几个边界需要明确:

  • 没有运行仓库程序做启动验证
  • 没有确认最终发布时到底启用哪一个入口
  • source_code/backend/ 的判断是“更像旧线/残留”,不是运行态绝对结论

所以这份文档的目标不是提供启动手册,而是帮助接手开发者先建立正确的系统地图。

一句话结论

理解这个仓库最有效的方式不是按语言分开看,而是按职责看:

  • Python 负责桌面壳、本地桥接、自动化执行
  • Java 负责任务系统、结果系统、下载系统
  • Vue 负责工具页交互和任务发起

而“删除品牌自动化”正好把这三层的协作关系完整串了起来。

S
Description
No description provided
Readme 217 MiB
Languages
Java 70.5%
TypeScript 16.8%
Vue 11.9%
Python 0.5%
JavaScript 0.2%
Other 0.1%