The repo already layered file defaults under environment overrides, on both the backend (settings.yml < GOAUTO_*) and the frontend (.env.production < process.env). What was missing was a translator for production: config.yaml only ever existed for the PowerShell launchers, so a packaged binary read none of it and had no database credentials either — SYB was inheriting an existing gap, not creating one. The server now reads config.yaml itself, between settings.yml and the environment. Lookup is GOAUTO_CONFIG, then ./config.yaml, then beside the executable, so a packaged binary works wherever it is started. An absent file is not an error: containers supply everything through the environment. Scalars are read by YAML type and coerced, so an unquoted all-digit password cannot take startup down over a quoting detail. This removed the need for a Read-SybConfig in PowerShell: the launcher just hands over the path it already knows, rather than reimplementing a YAML parser. The server also serves the built frontend when dist is present, which is what .env.production's empty VUE_APP_BASE_API already assumes. The history fallback is restricted to non-API GETs, and is not installed at all without dist, so development 404s stay 404s. Precedence is mutation-tested: applying the local file after the environment instead of before makes the layering test fail. Not verified: the PowerShell change and any Windows deployment — both need a run on the Windows side. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
121 lines
8.1 KiB
Markdown
121 lines
8.1 KiB
Markdown
<!-- gitea-wiki-mirror:start -->
|
||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||
wiki_page: Architecture-and-Code-Map
|
||
wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Architecture-and-Code-Map.-
|
||
wiki_revision: a81b23771f859e89d16a8626735f1f3425d063e2
|
||
synchronized_at: 2026-08-20T01:27:29Z
|
||
<!-- gitea-wiki-mirror:end -->
|
||
|
||
# 架构与代码地图
|
||
|
||
## MVP 架构
|
||
|
||
```text
|
||
go-admin-ui
|
||
│ REST:PDD商品、规则、任务、任务详情
|
||
▼
|
||
go-admin Server ───────── 数据库
|
||
│ ├─ pdd_product
|
||
│ REST:注册/心跳/任务 ├─ collection_rule
|
||
│ ├─ collection_task(任务+结果)
|
||
▼ └─ dimension/value/color_price/sku 子表
|
||
Android Portal/Agent
|
||
├─ 注册、心跳与设备串行锁
|
||
├─ 领取指定任务或空闲领取未指定任务
|
||
├─ 执行任务内的 URL 与规则快照
|
||
└─ 提交结构化结果或明确错误
|
||
```
|
||
|
||
## 最小闭环
|
||
|
||
1. 管理员添加 PDD URL,服务端规范化 URL 并提取唯一 `goods_id`。
|
||
2. 管理员创建规则;规则创建后立即可用于创建任务。
|
||
3. 管理员从一个 PDD 商品创建任务,可指定设备,也可留空等待空闲设备领取。
|
||
4. 任务固化 URL、goods_id 和完整规则快照。
|
||
5. Android 串行执行并把结果写回同一条任务;规格与 SKU 写入任务结果子表。
|
||
6. 同一事务把 `completed` 结果全量覆盖到 PDD 商品最新档案,把 `completed_partial` 明确采集到的字段和规格安全合并;`failed` 不修改商品。
|
||
7. 管理员在任务详情查看原始结构化结果,也可在 PDD 商品页面查看和人工覆盖最新商品资料。
|
||
|
||
## 关键设计
|
||
|
||
- `pdd_product.goods_id` 唯一;重复时提示商品已存在,不重复新增。
|
||
- 规则没有草稿、发布和版本流程;软删除只阻止创建新任务。
|
||
- 已有任务不依赖规则当前状态,始终执行自身 `rule_snapshot`。
|
||
- `collection_task` 同时保存任务生命周期和结果摘要,不建立 `collection_result` 主表。
|
||
- 同一 PDD 商品最多存在一个 `pending` 或 `running` 任务。
|
||
- 指定设备只能由该设备领取;未指定任务由在线空闲设备原子领取。
|
||
- 重置在事务中清空原结果,保留 URL、goods_id、规则和设备快照,状态恢复为 `pending`。
|
||
- Android 本地互斥与服务端原子领取共同保证单设备串行。
|
||
- 原始控件树和截图不持久化;Android Agent 端第一期不使用 OCR/VLM。服务端 SYB 登录验证码识别是唯一例外,见 [#48](https://git.ilapage.cn/OPC/goauto/issues/48)。
|
||
|
||
## 最小业务数据
|
||
|
||
| 表 | 必要内容 |
|
||
|---|---|
|
||
| `agent_device` | 唯一 `install_id`、设备信息、状态、Token 摘要、版本化能力、最后心跳 |
|
||
| `pdd_product` | 唯一 `goods_id`、当前 URL、标题、店铺、数字销量/评价、三态状态和通用多维 `specs_json` 最新值 |
|
||
| `collection_rule` | `id`、`name`、`content_json`、创建/更新时间、`deleted_at` |
|
||
| `collection_task` | 商品/设备外键、五态状态、URL/goods_id/规则快照、租约、结果摘要、错误和时间 |
|
||
| `collection_dimension` | 任务、维度键、名称、排序 |
|
||
| `collection_dimension_value` | 维度、值、排序 |
|
||
| `collection_color_price` | 任务、颜色、该颜色统一使用的整数分价格 |
|
||
| `collection_sku` | 任务、整数分价格、可用性、完整性 |
|
||
| `collection_sku_value` | SKU 与规格值的多对多关联 |
|
||
|
||
`collection_task` 的状态仅为 `pending`、`running`、`completed`、`completed_partial`、`failed`。设备身份和心跳表属于 Agent 领取任务的必要基础,不承载 PDD 业务数据。
|
||
|
||
设备以 JSON 数组保存最后一次注册或心跳上报的版本化能力。v1 任务兼容未上报能力的旧 Agent;v2 任务在创建指定设备任务、获取下一任务、领取和开始四个边界重复校验能力,避免旧 APK 执行未知规则。
|
||
|
||
数据库使用两个可空 guard 列表达跨数据库唯一约束:活动任务的 `active_slot=1`,运行中设备的 `device_run_slot=1`;终态记录对应列为 `NULL`。复合唯一索引据此保证同商品最多一个活动任务、同设备最多一个运行中任务,同时允许保留任意数量的终态历史任务。状态与 guard 列还有数据库检查约束,必须在同一条状态变更语句中更新。
|
||
|
||
## 配置分层
|
||
|
||
配置分三层,下层覆盖上层:
|
||
|
||
| 层 | 文件 | 是否进 Git | 放什么 |
|
||
|---|---|---|---|
|
||
| 1 默认值 | `server/config/settings.yml` | **是** | 应用配置和非机密运维参数(`extend.syb` 的 `baseurl` / `pagesize` / `maxmatches` / `ocrurl`) |
|
||
| 2 部署本地值 | `config.yaml`(仓库根) | **否**(`.gitignore`) | 数据库、端口、顺云宝凭据 |
|
||
| 3 覆盖值 | `GOAUTO_*` 环境变量 | — | 服务、容器和 CI 用;优先级最高 |
|
||
|
||
`[必须]` **凭据只允许出现在第 2、3 层。** `settings.yml` 被 Git 跟踪,任何时候都不能往里写账号密码。
|
||
|
||
服务端自己读第 2 层(`config/local.go` 的 `ApplyLocalConfig`),查找顺序为 `GOAUTO_CONFIG` 指定的路径 → 当前目录 `./config.yaml` → 可执行文件同级目录。**找不到不是错误**:容器场景只用环境变量,本来就没有这个文件。回调注册在 `ApplyEnvironment` 之前,环境变量因此始终有最后决定权。
|
||
|
||
`[必须]` 第 2 层的标量按 YAML 原始类型读取后统一转字符串。纯数字密码不加引号会被 YAML 读成整数,这里不能因此启动失败——但仍应加引号,否则前导零会丢。
|
||
|
||
开发启动脚本把 `config.yaml` 的路径通过 `GOAUTO_CONFIG` 传给服务端,不在 PowerShell 里重复解析 YAML。
|
||
|
||
## 前端伺服
|
||
|
||
`web/.env.production` 的 `VUE_APP_BASE_API` 为空,即生产构建发的是相对请求,**前端与接口必须同源**。服务端在 `dist/index.html` 存在时伺服构建产物并为 history 路由回退到 `index.html`(`app/admin/router/spa.go`)。
|
||
|
||
`[必须]` 回退只对非接口路径的 GET 生效。给写错的接口路径回 200 + HTML,客户端看到的会是 JSON 解析错误而不是 404。
|
||
|
||
`[必须]` `dist` 不存在时不注册 `NoRoute`。开发环境前端跑在 vite 独立端口上,装了回退会把每个真 404 变成一张 HTML 页。
|
||
|
||
## 已建立的工程入口
|
||
|
||
| 功能 | 当前目录 |
|
||
|---|---|
|
||
| 服务端基线 | `server/`(go-admin v2.3.0) |
|
||
| 最小闭环数据模型 | `server/app/goauto/models/` |
|
||
| 数据迁移与约束测试 | `server/app/goauto/migrations/` |
|
||
| go-admin 迁移注册 | `server/cmd/migrate/migration/version-local/1786700000000_goauto_schema.go` |
|
||
| 设备注册、认证、停用与吊销 | `server/app/goauto/device/` |
|
||
| PDD 商品与规则 | `server/app/goauto/product/`、`server/app/goauto/rule/` |
|
||
| PDD 商品档案增量迁移 | `server/cmd/migrate/migration/version-local/1786700500000_pdd_product_archive.go` |
|
||
| 虾皮商品档案与规格映射 | `server/app/goauto/shopeeproduct/`(服务端 API 已实现;Admin 页面待实现) |
|
||
| 虾皮商品档案增量迁移 | `server/cmd/migrate/migration/version-local/1786700600000_shopee_product_archive.go` |
|
||
| SYB 商品明细导入、解析与虾皮档案合并 | `server/app/goauto/sybimport/`(解析、幂等落库、同步编排、导入端点、管理端 API 和 Admin 页面均已实现) |
|
||
| 顺云宝(SYB)ERP HTTP 客户端与登录会话 | `server/app/goauto/sybclient/`(登录、OCR 验证码、会话缓存、列表与明细读取;见 [SYB-ERP-Interface-Contract](SYB-ERP-Interface-Contract)) |
|
||
| SYB 商品明细增量迁移 | `server/cmd/migrate/migration/version-local/1786700700000_syb_product_import.go` |
|
||
| 任务领取、结果、重置与删除 | `server/app/goauto/task/` |
|
||
| 管理端基线 | `web/`(go-admin-ui v3.0.0) |
|
||
| 管理端闭环页面 | `web/src/views/goauto/` |
|
||
| Android Agent 基线 | `android/app/src/main/java/cn/ilapage/goauto/agent/` |
|
||
| Android 无障碍规则执行 | `android/app/src/main/java/cn/ilapage/goauto/agent/automation/` |
|
||
| 三端统一验证 | `scripts/verify.ps1` |
|
||
|
||
以上入口均已落地;新增 API、表或执行动作时必须同步更新本代码地图与共享契约。
|