feat: 工具Tab新增应用版本管理(按包名并发查询所有设备安装版本)+ 文档同步更新(README/API/ARCHITECTURE/DEPLOY:工具Tab各工具、条件判断if_el+OCR、STF设备管理、.env密钥配置)
This commit is contained in:
+75
-3
@@ -595,9 +595,11 @@
|
||||
|
||||
---
|
||||
|
||||
## 13. 维护(仅管理员)
|
||||
## 13. 维护 / 工具(仅管理员)
|
||||
|
||||
维护页两个接口都**仅管理员可用**(普通用户即使有业务权限也访问不了,返回 403)。
|
||||
以下接口都**仅管理员可用**(普通用户即使有业务权限也访问不了,返回 403)。
|
||||
维护页现仅含 STF 服务管理;adb 终端、Tailscale 管理、应用管理、STF 设备管理等
|
||||
已集中到"工具"页(页内子分栏),API 不变。
|
||||
|
||||
### POST /api/stf/restart
|
||||
|
||||
@@ -672,7 +674,7 @@ adb 远程终端:用平台 adb 二进制执行任意 adb 命令(20s 超时
|
||||
|
||||
## 15. Tailscale 管理(仅管理员)
|
||||
|
||||
维护页"Tailscale 管理"分区,调用 Tailscale 官方 API v2。所有接口仅管理员可用。
|
||||
工具页"Tailscale 管理"子分栏,调用 Tailscale 官方 API v2。所有接口仅管理员可用。
|
||||
前置:`.env` 配置 `TAILSCALE_API_KEY`(Settings → API Access Tokens)与
|
||||
`TAILSCALE_TAILNET`(tailnet 名,个人账号一般为邮箱前缀);未配置返回 502 并附提示。
|
||||
设备 IP 由 tailnet 分配,API 不可修改,列表只读展示。
|
||||
@@ -739,3 +741,73 @@ adb 远程终端:用平台 adb 二进制执行任意 adb 命令(20s 超时
|
||||
```json
|
||||
{"ok": true, "key": "tskey-auth-...", "id": "k1", "expires": "2026-08-11T01:00:00Z"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 16. 工具(仅管理员)
|
||||
|
||||
工具页(剪贴板注入 / 应用版本管理 / STF 设备管理)接口,均仅管理员可用。
|
||||
|
||||
### POST /api/tools/clipboard/set
|
||||
|
||||
剪贴板注入:把指定文字写入一台或多台设备的剪贴板。
|
||||
|
||||
**请求**(JSON):
|
||||
```json
|
||||
{"serials": ["100.100.10.11:5555", "0123456789ABCDEF"], "text": "要注入的文字"}
|
||||
```
|
||||
设备来源与维护终端一致(本地 adb 含 USB + STF 池)。
|
||||
实现:u2 `jsonrpc.setClipboard`(实测 `cmd clipboard` 在 MIUI 上不存在),支持中文/引号/换行;
|
||||
IP 设备先 adb connect(已连接跳过,绝不 disconnect),USB 设备首次自动推送 atx-agent。
|
||||
|
||||
**响应**:
|
||||
```json
|
||||
{"ok": true, "results": {"100.100.10.11:5555": {"ok": true, "msg": "已注入"}},
|
||||
"ok_count": 1, "fail_count": 0, "error": null}
|
||||
```
|
||||
|
||||
### POST /api/tools/appver
|
||||
|
||||
应用版本管理:查询所有设备上指定包名的安装情况与版本号(并发 10 台)。
|
||||
|
||||
**请求**(JSON):
|
||||
```json
|
||||
{"pkg": "com.ss.android.ugc.aweme"}
|
||||
```
|
||||
|
||||
**响应**:
|
||||
```json
|
||||
{"ok": true, "total": 8, "fail": 0,
|
||||
"results": {"100.100.10.11:5555": {"installed": true, "version_name": "28.5.0", "version_code": "280500"}}}
|
||||
```
|
||||
未安装返回 `installed: false`;查询失败的设备带 `error` 字段。
|
||||
|
||||
### GET /api/stf/devmgmt/status
|
||||
|
||||
STF 设备管理状态:connect_devices.sh 脚本配置的 IP 列表 + 220 上 adb 实际连接状态。
|
||||
|
||||
**响应**:
|
||||
```json
|
||||
{"ok": true,
|
||||
"configured": ["100.100.10.10", "100.100.10.11"],
|
||||
"connected": [{"serial": "100.100.10.10:5555", "state": "device"}]}
|
||||
```
|
||||
|
||||
### POST /api/stf/devmgmt/add
|
||||
|
||||
添加设备:写入 220 上 `connect_devices.sh` 的 DEVICES 列表 + 立即 `docker exec adb adb connect`。
|
||||
设备不可达时 connect 会 15 秒超时兜底(220 侧 `timeout`),但仍保留在脚本中,cron 每 5 分钟自动重试。
|
||||
|
||||
**请求**(JSON):`{"ip": "100.100.10.20"}`(可带 `:5555`,自动归一化)
|
||||
|
||||
**响应**:
|
||||
```json
|
||||
{"ok": true, "msgs": ["已写入脚本 /mnt/data/openstf/connect_devices.sh", "连接超时(设备当前不可达),已保留在脚本中,cron 会每 5 分钟自动重试"]}
|
||||
```
|
||||
|
||||
### POST /api/stf/devmgmt/remove
|
||||
|
||||
移除设备:从脚本 DEVICES 删除 + `adb disconnect`(设备从 STF 池下线,任务不再分配)。
|
||||
注意:断开的是 220(STF provider 侧)的 adb 连接,与本机任务直连的 adb 相互独立。
|
||||
|
||||
**请求**(JSON):`{"ip": "100.100.10.20"}`
|
||||
|
||||
+39
-4
@@ -233,6 +233,32 @@ APK 上传/解析/批量安装。
|
||||
|
||||
元素树解析:递归提取每个节点的 `resource-id/text/content-desc/class/bounds` 等属性,并推荐最佳选择器(优先 xpath)。
|
||||
|
||||
### 3.9 屏幕 OCR(`core/ocr.py`)
|
||||
|
||||
条件判断的 `ocr` 选择器实现:截屏 → RapidOCR(ONNX 推理,中英文模型随包内置)→ 关键词匹配 → 返回文字中心像素坐标(与 u2 `d.click` 一致)。
|
||||
|
||||
- **跨平台**(Windows/Linux/macOS),依赖 `rapidocr_onnxruntime`;服务器无显示器环境建议将 opencv-python 换成 opencv-python-headless
|
||||
- 引擎懒加载单例 + 并发加锁(识别约 0.2-0.5s/次)
|
||||
- 返回坐标约定:像素、原点左上
|
||||
|
||||
### 3.10 STF 设备管理(`core/stf_device_mgmt.py`)
|
||||
|
||||
工具页"STF 设备管理":维护 220 上 OpenSTF 设备池。
|
||||
|
||||
背景:220 的 adb 跑在 Docker 容器(`STF_ADB_CONTAINER`,默认 `adb`)里,设备池由
|
||||
`/mnt/data/openstf/connect_devices.sh`(`STF_SCRIPT_PATH`)的 `DEVICES` 数组维护,cron 每 5 分钟补连。
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `status()` | 脚本配置 IP + 220 adb 实际连接状态 |
|
||||
| `add_device(ip)` | 用 220 的 python3 精确改脚本 DEVICES 块 + `docker exec adb adb connect` |
|
||||
| `remove_device(ip)` | 脚本删条目 + `adb disconnect` |
|
||||
|
||||
关键点:
|
||||
- 脚本编辑用 python3 行级增删(sed 处理多行数组易误伤)
|
||||
- `adb connect` 到不可达 IP 会挂 40s+,220 侧用 `timeout 15` 兜底,超时保留在脚本由 cron 重试
|
||||
- 断开的是 220(STF provider 侧)的 adb 连接,与本机任务直连的 adb 相互独立
|
||||
|
||||
---
|
||||
|
||||
## 4. 任务系统设计
|
||||
@@ -289,13 +315,22 @@ tasks/douyin/actions/like.py — @register_action(ACTIONS) LikeAction
|
||||
|
||||
### 5.2 步骤编辑器
|
||||
|
||||
`generic_steps` 任务的步骤编辑器:
|
||||
- 左侧操作库(拖拽源)
|
||||
- 中间画布(步骤卡片列表,HTML5 Drag API 排序)
|
||||
`generic_steps` 任务的步骤编辑器(任务弹窗已加宽到 1000px):
|
||||
- 左侧操作库(拖拽源,按 交互操作/屏幕与App/流程控制 分组)
|
||||
- 中间画布(步骤卡片列表,HTML5 Drag API 排序 + 跨层级嵌套:循环套循环、动作组)
|
||||
- 每个步骤卡片可展开参数表单
|
||||
- 选择器字段旁有"抓取元素"按钮(独立模态框)
|
||||
- **容器步骤**(loop/group/if_el):卡片内嵌子步骤容器接收拖入;if_el 有"✅找到时/❌未找到时"两个独立分支容器,分支可嵌套任意步骤
|
||||
- **条件判断**(if_el):选择器支持 xpath 等 UI 树选择器或 OCR识别(`core/ocr.py`,截屏匹配图片/画布文字,命中可自动点击)
|
||||
- 所有递归操作(选择打包、存自定义动作、校验、防循环自套)统一遍历 children/then/else 三个子数组
|
||||
|
||||
### 5.3 元素抓取模态框
|
||||
### 5.3 页内子分栏
|
||||
|
||||
任务/工具 Tab 用通用 `showSubTab(tabId, name)` 实现页内子分栏:每个子分栏一个 `.sub-panel`,
|
||||
`_activeSubs` 记住各 Tab 上次选中的子分栏。工具 Tab 集中了全部管理工具(剪贴板注入/adb 终端/
|
||||
Tailscale/应用管理/应用版本/已装应用/STF 设备管理),维护 Tab 仅保留 STF 服务。
|
||||
|
||||
### 5.4 元素抓取模态框
|
||||
|
||||
独立的第二层模态框(`el-picker-overlay`,z-index 1100),不影响任务编辑窗口:
|
||||
1. 选择设备 → 2. 加载截图 + 元素树 → 3. 点击元素/边界框 → 4. 回填选择器
|
||||
|
||||
+9
-4
@@ -74,6 +74,9 @@ pip install -r requirements.txt
|
||||
| uiautomator2 | >=3.0 | Android UI 自动化 |
|
||||
| uiautodev | >=0.14 | UI 元素抓取 |
|
||||
| pyaxmlparser | >=0.3.27 | APK 元信息解析 |
|
||||
| rapidocr_onnxruntime | >=1.4 | 屏幕 OCR(条件判断的 OCR识别 选择器,中英文模型随包内置,跨平台) |
|
||||
|
||||
> 服务器(无显示器/Linux)环境建议把 opencv-python 换成 `opencv-python-headless`(rapidocr 依赖 cv2,两者取一)。
|
||||
|
||||
> uiautomator2 首次连接设备时会自动推送 atx-agent 到设备,无需手动安装。
|
||||
|
||||
@@ -102,16 +105,18 @@ STF_URL = "http://你的STF地址:端口"
|
||||
| `WEB_HOST` | `0.0.0.0` | 仅本机访问改为 `127.0.0.1` |
|
||||
| `WEB_PORT` | `18050` | 端口冲突时修改 |
|
||||
| `ADB_PATH` | 自动识别 | 用自定义 adb 时修改 |
|
||||
| `STF_SSH_TARGET` | `[email protected]` | 维护页"一键重启 STF 容器"的 SSH 目标(需免密登录) |
|
||||
| `STF_SSH_TARGET` | `[email protected]` | 维护页"一键重启 STF 容器"与工具页"STF 设备管理"的 SSH 目标(需免密登录) |
|
||||
| `STF_DOCKER_CONTAINER` | `stf` | 220 上 STF Docker 容器名(`docker ps` 查看) |
|
||||
| `STF_ADB_CONTAINER` | `adb` | 220 上 adb Docker 容器名(STF 设备管理执行 `docker exec adb adb ...`) |
|
||||
| `STF_SCRIPT_PATH` | `/mnt/data/openstf/connect_devices.sh` | STF 设备池脚本路径(工具页增删设备会读写其 DEVICES 列表) |
|
||||
| `TAILSCALE_TAILNET` | 按邮箱前缀 | tailnet 名称/ID(个人账号一般为登录邮箱前缀) |
|
||||
|
||||
> **未配置 `WEB_SECRET_KEY`**:启动时随机生成(每次重启登录态失效,生产务必配置固定值)。
|
||||
> **维护页 Tailscale 前置**:`.env` 写入 `TAILSCALE_API_KEY` 后重启服务;
|
||||
> **工具页 Tailscale 管理前置**:`.env` 写入 `TAILSCALE_API_KEY` 后重启服务;
|
||||
> 未配置时管理分区显示明确提示,不影响其他功能。
|
||||
|
||||
> **维护页 STF 重启前置**:本机需能免密 SSH 到部署机(把本机公钥加入目标机 `authorized_keys`),
|
||||
> 且 `STF_DOCKER_CONTAINER` 与真实容器名一致;未配置好时按钮会返回明确错误。
|
||||
> **维护页 STF 重启 / 工具页 STF 设备管理前置**:本机需能免密 SSH 到部署机(把本机公钥加入目标机 `authorized_keys`),
|
||||
> 且 `STF_DOCKER_CONTAINER`/`STF_ADB_CONTAINER` 与真实容器名一致;未配置好时按钮会返回明确错误。
|
||||
|
||||
### 2.4 启动服务
|
||||
|
||||
|
||||
Reference in New Issue
Block a user