Commit Graph
19 Commits
Author SHA1 Message Date
butubb 7ce4ae9016 feat(账号): 账号台账(web 页 + 任务取号 + 设备端身份页);fix(剪贴板): 注入通道改走设备端 Agent
一、账号台账(新表 device_account,schema v8)
- core/ledger.py:CRUD、Excel 粘贴解析(Tab 分隔 / 表头乱序缺列 / 是·否布尔 / 逐行留痕)、
  按范围取号(本机台账 / 全部 / 按设备分组)、设备端账号块、dry_run 预览
- 新「账号」顶级 Tab(权限 devices):列表 + 搜索 + 设备筛选 + 增删改 +
  粘贴导入(默认先预览再写,逐行显示 新增/覆盖/跳过/失败 + 留痕)
- 设备池加「账号 N」列(0 个显示"未登记"),点开看该设备账号明细
- 任务「条件判断」新增 cmp_source / cmp_group:候选值可直接来自台账,
  与手填值**合并(OR)**;取不到号时回落手填值,并把原因写进步骤明细与日志
  (否则"永远走 else 分支"而任务照样显示成功,最难查)
- 设备端契约:身份页多推 accounts_b64(base64 JSON;默认不含手机号;
  超预算按整条丢且绝不算字节切),见 doc/DEVICE_AGENT.md §5.2.1
- 备份/文档红线:TABLE_LABELS 加「账号台账」;DATA_MODEL/API/ARCHITECTURE/DEPLOY/
  TASK_DEV/DEVICE_AGENT/DEVELOPMENT/README 同步;顺手补上 DATA_MODEL 漏列的 done_mark

⚠ 台账里的抖音号是**纯号**,只当"比对用的候选值":绝不能拿去填「去重」的身份元素
  (身份是元素原文逐字算 key,格式不同会让去重静默失效)。代码与文档都写明了。

二、剪贴板注入通道(修:平台还在调早期的独立 APK)
- 改为按顺序尝试:设备端 Agent(com.example.deviceagent/.ClipActivity)→
  旧版独立 ClipInject 兜底;两个都没有时报"需要设备端 Agent"(不再只说 ClipInject)
- 读回验证改成**轮询到 3 秒**:透明 Activity 要等窗口拿到焦点才写,
  原来只睡 0.5s 会读到上一次的内容 → 误报"写入可能被拒"(实测内容已写入却回失败)
2026-09-24 16:12:58 +08:00
butubb 876224f876 feat(去重): 跨设备「已做过」账本 —— 同一个号不会做两次 + 「谁做过了」看得见
用户场景(他原话):一台手机登录 5 个抖音号、一共 5 台手机,每个任务只让其中一个
目标号评论;每天跑一次但不知道什么时候跑完,于是"一直重复跑" → 结果
"一个手机还没评论到,一个手机都评论两次了"。

**根因不是"单设备重复",是跨设备没有共享的判断 + 进度不可见。** 所以做两件事:
① 幂等;② 把"谁做过了、还差谁"摆到台面上(不然只能靠重跑确认,而重跑又在制造重复)。

- `core/models.py`:新表 `done_mark`(迁移账本补 v7)。**判据只有 `scope_key` 的
  唯一索引**——多台设备会同时判断"没做过","先查后插"有竞态(两台都插),
  唯一索引 + `INSERT ... ON DUPLICATE KEY`/`INSERT OR IGNORE` 的**受影响行数**才原子。
- `core/dedup.py`(新):`build_key`(`任务|身份|时间桶`)/ `check` / `mark` /
  `list_marks`(带"今天做了几台/几个号"统计)/ `delete_mark` / `clear_job` / `purge_old`。
  自建 app context(照 device_pool 的 `_ctx()`),任务线程/Web/清理都不用关心。
- 任务侧两个部件(**检查在前、记账在后**):
  · `if_el` 新增条件类型 `selector_type="dedup"`:命中=这个身份做过了 → 走 then 分支。
    身份元素在 `ident_type`/`ident_value`(留空 = 用设备 serial,一号一机场景)。
  · 新步骤 `mark_done`「记为已做」(22 种步骤):放动作**成功之后**。
  拆两步的用意:动作失败就不记账,下次重跑还会重试该设备 —— 失败不丢。
- 有效期(`dedup_reset` = day/all/hours)放**任务级**:检查与记账两处各填一份的话,
  填不一致就算出两个 key、去重会**静默失效**,所以强制只配一处(编辑器顶部下拉)。
- 三条防误伤规则(都有测试兜着):
  · 身份读不到 / 身份值过长 → **不去重、当没做过照常执行**。绝不能把"读不到"
    当成空身份——那会让所有设备共用一个 key、第一台记账后其余全被误判成"做过"。
  · `kind='all'`(只做一次)的记录**永不清理**(清了等于语义失效);清理只删 day/hours。
  · 去重的两个易错点在保存时直接告警:身份元素两边不一致、有检查没记账/有记账没检查。
- 「任务 → 去重记录」新子分栏(`static/admin/dedup.js`):统计行 + 明细表 +
  删单条(那个号重跑)/ 清空任务(整批重跑)。接口 3 个(GET/delete/clear,PERM_TASKS)。
- 每日 04:23 清理(挂现有 APScheduler),`TABLE_LABELS` 补中文名(备份覆盖自动派生)。
- AI 建任务草稿校验同步:`dedup` 走自己的规则(要 ident_value、xpath 前缀校验),
  没填身份元素只警告不拦(用设备当身份是合法用法);普通条件空选择器仍然拦。
- 文档:TASK_DEV §4.6(去重专章 + App 内检测的兜底配方与它的三个局限)、
  DATA_MODEL §2.9、API 三个接口、ARCHITECTURE(分层/装配/子分栏/JS 分工/清理)、
  DEPLOY §5.2(15 张表)、步骤数 21→22 全库同步。

自测:单元 + 集成 33 项(**含 8 线程抢同一个身份、恰好一个成功**的原子性断言,
以及"all 记录不被清理""身份读不到不去重""清了能重跑")、
**真机端到端**(cs1 上"检查→动作→记账"跑两遍:第二遍被拦、换 serial 的"另一台设备"
同样被拦、删记录后能重跑)、草稿校验 5 项、GET 冒烟 56 路由 0 个 500。

(注:本分支基于 feat/if-el-multi-value,因为它俩都要改 task.py 的 STEP_TYPES 与
editor.js 的 STEP_LIB 同一区域,分开从 dev 拉必然冲突——这份是超集,合一次两份都进。)
2026-09-24 10:55:29 +08:00
butubb bd51306a2a feat(任务): 「动作配置」分栏——步骤默认值 + 动作录制器
需求:滑动要能"我自己录制";在自定义动作旁边加一个分栏,能配动作默认值、
能录制操作当动作、能自己建立动作。

**步骤默认值**(core/step_defaults.py,存 app_meta.step_defaults 单键,不建表):
- 覆盖 滑动(方向/时长区间/幅度/抖动/拟人)、点击(等待超时)、长按(时长/超时)、
  等待(区间)、按键、输入文字(模式/候选文案/清空);
- **只影响之后新建的步骤**,已有步骤不动;新建时 `_makeStep` 用出厂值打底 + 默认值覆盖;
- 只存与出厂值不同的字段(以后调出厂默认,没配过的能跟着走);
- 字段白名单 + 范围夹取(SPEC):越界夹边界、非法值丢弃 → 手改 JSON 塞脏值也进不来。

**动作录制器**(static/admin/recorder.js):
- 在设备画面上点/划/按键/输入 → 自动翻译成步骤:
  点→命中元素记「点击元素」(选择器)、没命中退化成「点击坐标」(百分比);
  划→「滑动」方向/幅度/时长全按你实际操作算;停顿≥1s 可选记成「等待」(±15%);
- 两个入口:动作配置页「录制动作」(存成自定义动作,进动作库复用)、
  步骤编辑器滑动那步的「录制手势」(只取手势回填该步骤);
- 画面+元素树走 /api/uiauto/snapshot 一次取齐,**每次操作后自动刷新**,
  所以下一次点击用的是最新的树;执行仍走 /api/screen/{tap,swipe,key,text}(与大屏同一套)。

接口:GET/POST /api/step_defaults(读登录、写需 tasks 权限)。
文档:TASK_DEV §3.1(含翻译规则表与三条实现口径)、API §2.3、DATA_MODEL §5、README。

自测(无头浏览器 + CDP 真模拟拖动):默认值保存→回读→新建滑动步骤确实预填 0.42;
录制器取到画面与元素树;模拟"按住往上划"→ 录出
{direction:up, distance_ratio:0.5, duration_min:0.47, humanize:true}(幅度/时长按实际操作算);
恢复出厂链路 0.6 通过;页面无 JS 报错。
2026-09-20 14:32:35 +08:00
butubb 621d48c800 feat(日志): 任务步骤明细表 + 「日志 → 步骤明细」面板(按设备/任务/时间过滤、按运行归组、导出 CSV)
文本日志只能 grep,"这台设备这次运行为什么失败"翻起来很费劲。新增一张
**结构化**的步骤明细表,把"哪一步、什么类型、哪个选择器、结果、耗时"落库。

- core/models.py:新增 task_step_log(run_id/job/设备/step_path/selector/
  result/detail/duration_ms),索引 run_id、created_at、(serial,created_at)、
  (job_id,created_at);
- core/step_log.py(新):**专用写线程 + 有界队列**批量落库——步骤执行是热路径,
  任务线程只 put_nowait(实测 9000 次入队 31ms),队列满丢弃并计数,绝不阻塞;
  另有保留期清理(默认 14 天,每日 04:13 + 每次启动);
- tasks/generic/task.py:_exec_one 记一条(异常=error / handler 返回 False=miss /
  未知类型=unknown / 概率未触发=skip);_exec_steps 维护路径栈得到 "2.1.3"
  这样的嵌套位置;**单次运行封顶 2000 条**——forever 循环任务否则会写爆表;
- 运行上下文 ctx(run_id/job_id/job_name/device_name)由 TaskManager 生成,
  经 create_worker(serial, params, ctx=None) 传入 worker(扩展点向后兼容);
- 接口:/api/step_logs(过滤+分页)、/runs(按运行归组)、/filters(下拉选项)、
  /download(CSV,带 BOM);
- 前端:日志页拆成「文件日志 / 步骤明细」子分栏 + static/admin/steplog.js。

红线:新表自动进备份覆盖清单(SUMMARY_TABLES 由元数据派生),已补
TABLE_LABELS 中文标签,导出实测 14 张表、coverage_missing 为空。

文档:DATA_MODEL §2.8/§1、API §10.2、ARCHITECTURE §1.1/§2.2/§3.1、
DEVELOPMENT §5.2 与红线表、DEPLOY §5.2、TASK_DEV §8.3、README。
2026-09-16 08:58:43 +08:00
butubb 97cec6e211 feat(通知): 系统级 Webhook 通知子系统(事件目录 + 可插拔适配器 + 防刷屏)
平台此前出了问题只能靠人盯页面。现在各组件统一走 `notifier.notify(事件, **字段)`,
推到企业微信 / 自建服务;**所有可通知点都登记进事件目录,默认全关,用户按 webhook 勾选**。

## 架构(`core/notifier.py` + `core/notify_events.py`)
业务线程调 `notify()` → 只做内存操作(读配置快照/匹配订阅/入队)→ 返回;
后台 1 个 dispatcher(聚合 + 每 hook 限流 + 折叠摘要)+ 3 个 sender(真实 HTTP、退避重试)
负责真正发出去。硬约束:**notify 零 DB、零 HTTP、零阻塞、异常不冒泡**——所以任务线程里
可以直接调(不用 app_context、不用 try/except),但**必须放在所有 `with self._lock` 之外**。

- **事件目录 36 条**(任务批次/单设备/设备/Worker/业务/安装/系统/AI),支持 `task.*` 通配订阅;
  语义分工避免重复告警:`worker.*` 是单次尝试级,`task.device.success/failed` 是唯一权威结论。
- **适配器可插拔**:`wecom`(markdown,按 4096 **字节**截断、超限不截半个汉字)+
  `json`(模板占位符,替换值按 JSON 转义,保存前干跑校验);钉钉/飞书留了插槽(前端置灰)。
- **防打爆四层**:聚合窗口(默认 30s,同批次合并成一条并带样本)→ 令牌桶限流(默认 18/分,
  对齐企微硬限 20)→ 被限流的**折叠成摘要不丢弃** → 有界队列背压。取舍:失败通知最多延迟
  一个窗口,换来群不被刷屏。

## 安全与存储
- 配置只落 `app_meta.notify_webhooks` 一个键(**不建表** → 不涉及备份覆盖红线)。
- URL 本身就是凭据(企微 `?key=`)→ 接口回显/发送记录/日志一律 `mask_url()/scrub()`;
  编辑时留空即不修改;secret 永不回显。DATA_MODEL 的明文凭据告警补上了这一条。
- 发送记录:内存环形缓冲 200 条(重启清空)+ 独立 `logs/notify.log`。

## 接入点(每个都放在锁外、不改 return 顺序)
task_manager(批次开始/结束用新增的 `_BatchTracker` 统一在 finally 计数、单设备成功/失败/
离线/重试/停止/抢占/归还/cron 停止)、device_worker 心跳看门狗、generic 任务选择器连续失效、
apk 安装开始/完成、设备上下线(**状态沿检测**,只报新变化)、备份导出/恢复、经验巡检、
用户登录、服务启停。

## 前端
系统 Tab 新增「通知 / Webhook」子分栏:多条 webhook 列表(URL 打码)+ 编辑弹窗(格式/URL/
密钥/事件勾选树带 ★建议/聚合/限流/自定义模板/预览)+ 发送测试 + 发送记录。

## 自测
- 进程内逻辑 10 组断言全绿:聚合合并、限流+折叠、无配置/全局关静默丢弃、未知事件、
  内部异常不外泄、JSON 转义(标题含引号换行仍合法)、URL/异常消息脱敏、配置校验。
- 端到端(假 webhook 接收端)17 项断言全绿:真实事件投递(user.login / task.batch.no_device)、
  企微请求体形状、**HTTP 200 + errcode 93000 判为失败**、500 重试 3 次、记录里 URL 打码。
- 韧性:webhook 指向黑洞地址时登录耗时 100~114ms(基线 107~133ms,**异步隔离生效**);
  配置写成坏 JSON 服务照常启动、通知静默不发、日志有 error(服务端实测后已复原)。
- 页面:系统 → 通知 面板/弹窗/36 个事件复选框/预览全部正常,无 JS 报错。
- 自测数据已清理(webhook、自建任务、写坏又复原的配置键)。

文档:新增 doc/NOTIFY.md(事件表/配置/格式约束/防刷屏/加事件三步骤/排障)并登记进 doc/README;
API.md §2.11;DATA_MODEL 的 app_meta 键表与明文凭据告警;ARCHITECTURE 线程表/分层/扩展点;
根 README 功能索引与日志表。
2026-09-15 13:55:14 +08:00
butubb 46e6ea1f37 feat(AI 建任务): AI 自己在真机探索 → 写出可调度任务 → 人工确认入库
AI 控制台下新增子分栏「🧭 AI 建任务」:描述要做什么(例:建一个跑 2 小时的任务、自动刷
某 App、随机点赞),AI 用 de_* 工具自己在设备上探索(看屏/读元素树/点按验证),把走通的
路径写成一条任务草稿,经服务端校验后交人在步骤编辑器里核对/手改/试跑,保存才入库。

链路:POST /api/agent/run{mode:"designer", settings}
  → Agent 自探 → 本地工具 submit_task(draft)
  → core/task_draft 校验(失败把 errors 回灌模型让它改)
  → 只暂存(运行态 + app_meta.agent_task_draft,**不落库**)
  → SSE done{mode,draft,warnings} → 页面草稿预览 → openTaskModal(null, prefill) 预填

关键实现
- core/task_draft.py(新):把执行器的"静默跳过点"(未知 type/空 selector/空 children/
  嵌套>5/节点>60/cron 非法/必填缺失)前移成显式 error——POST /api/jobs 对 params 是盲存的,
  执行器又静默跳过错误步骤,没有这道闸门就是"任务建好了、跑起来什么都没做"。
  归一化兜底任务名/target/schedule/retry/时长;页面填的设置以 overrides 优先于模型。
  故意**不比执行器更严**:loop_mode 近义值归一(count→rounds)、缺 max_iterations 补默认 10
  (执行器本来就默认)——实测卡太死会把一轮探索耗在改字段上。
  有副作用的步骤(评论/发送/购买/删除…)只警告并把触发概率压到 30%(编辑器可改回)。
- mcp_agent/agent.py:双系统提示词(CHAT/DESIGNER)+ 平台级本地工具
  (LOCAL_TOOL_SPECS,不进 MCP)+ 每工具调用上限 40 + designer 输出上限 8192 +
  **json.loads 容错**(草稿被截断时给模型可读错误,而不是整轮失败)。
- web/agent_api.py:mode/settings 透传、submit_task 处理器(app_context 内校验+暂存)、
  done 带 draft、GET /api/agent/task_draft{,+POST,/clear}(草稿走 app_meta,不新建表)。
- 前端:static/admin/taskgen.js + #agent-sub-taskgen 子面板(showSubTab 机制);
  tasks.js 的 openTaskModal(jobId, prefill) + 信封归一化 + 唯一 draftKey;
  agent.js 按 mode 门控(一个 run 只有一个事件队列,两个 EventSource 会互相瓜分事件)。

顺带修掉一个 chat 也踩的协议 bug:一轮里同时调 de_screenshot 与别的工具时,截图图像会被
插在两条 tool 消息之间 → 模型侧判"工具回应不足"直接 400。改为本轮 tool 消息发完再附图像,
_repair_tool_messages 也改成只数**连续**的 tool 消息。

真机实测(Redmi 22120RN86C,设置页):8 步探索(含 tap_text 验证)→ submit_task 一次通过 →
草稿 8 个顶层步骤(screen_on/open_app/wait_el/click/wait/key_event…)、max_duration 1800、
无 click_xy、3 条 evidence;页面恢复草稿 + 预填编辑器 + 提示块渲染均正常,无 JS 报错。
自测数据已清理(草稿已丢弃、未创建任何任务)。

文档:AI_TASK_GEN.md 状态改「P0 已实现」+ §10 实现记录(差异/护栏/未做项)、AI_CONSOLE.md
(子分栏、designer 分支、SSE done 负载、app_meta 键)、API.md、DATA_MODEL.md、ARCHITECTURE.md、
DEVELOPMENT.md(自测入口)、README.md 索引、backlog 勾掉 P0。
2026-09-13 23:08:59 +08:00
butubb dad1af8b0b feat: 设备端应用商店(平台侧)—— Agent 直连拉清单/下载/安装,绕开 MIUI 的 USB 安装拦截
背景:`adb install` 在 MIUI 上被「USB 安装」拦下(USER_RESTRICTED),必须人工点确认;
而**由设备上的 App 自己调系统安装器**走的是普通应用安装流程,不触发那道拦截。

平台侧实现(设备端 Agent APK 在另一个仓库,契约见 doc/DEVICE_AGENT.md):

- web/device_agent_api.py(新):
  * 设备侧 `/api/device/agent/{bootstrap,apk/<id>,report}` —— 无登录会话,靠
    `X-Device-Token`(常量时间比对)鉴权;`X-Device-Fingerprint` 让平台认出是哪台设备
    (换 IP 也认得出,并把平台分配的名称回给它);**默认关闭,关闭时统一 404**,
    不暴露接口存在性;只读清单与文件,不返回任何配置/密钥
  * 管理侧 `/api/agent-store/{config,logs}` —— 登录 + 应用管理权限;启用时自动生成令牌,
    可一键重置(旧令牌立即失效)
- core/models.py:新增 `device_install_log`(下载/安装记录,自动裁剪保留 500 条)
- 应用管理页新增「📱 设备端应用商店」面板:开关 / 接入地址 / 令牌(复制·重置)/ 安装记录;
  面板里写明它与「平台批量推送」的分工
- doc/DEVICE_AGENT.md(新):**两个仓库共享的接口契约** —— 接入流程、三个设备接口的
  完整规格与错误码、adb 指令协议(剪贴板/身份显示/配置下发)、版本兼容约定、安全须知;
  API.md、DATA_MODEL.md、doc/README.md 索引同步

验证:
- 后端 9 组用例:默认关闭 404、无/错令牌 401、指纹认出设备名、清单、下载、上报与失败
  原因落库、关闭后重新 404、重置令牌后旧令牌立即失效、未登录管理端被拒 —— 全通过
- 真实浏览器:面板渲染、点开关 → 自动生成令牌 → 设备端带令牌拉到清单且 device.name=A08、
  无 JS 报错;测试后已把开关还原为关闭
- 全量回归 105 项通过(42 GET + 62 写探测 + 7 关键业务)
2026-09-13 14:40:38 +08:00
butubb 79cdf61ed2 feat: 自动认领开关 + 全站按设备名称显示
一、指纹匹配自动认领(可选,默认关)
- 发现设置新增「指纹匹配自动认领」勾选(app_meta: discovery_auto_claim,默认 0)
- 打开后:扫描发现某设备指纹与池中已有记录一致(同一台换了 IP)→ 自动迁移记录到新地址
  并同步分组/任务引用,零点击;关闭时维持"识别自动 + 人工点一次确认"
- 默认关的原因:认领会改写分组/任务引用(数据结构变动),交人工确认更稳妥
- 扫描结果与状态行会显示本轮自动认领了几台

二、设备名称在界面上呈现(凡选择/展示设备处都显示名称)
- 新增前端 helper `devText(name, serial)`(base.js):有名称→「名称 · serial」
- 监控页设备表:名称加粗为主、地址作副行(未命名显示橙色提醒);任务概况的覆盖设备
  chip 也优先显示名称(tooltip 保留完整地址)
- AI 控制台:目标设备下拉、实时画面设备下拉、目标/运行中提示都带名称(serial→name 映射)
- 任务编辑器「指定设备」下拉、分组编辑的设备勾选列表:带名称
- 后端 `/api/devices` 新增 `items`([{serial,name,model}],`devices` 保持兼容);
  `/api/agent/devices` 增加 `name` 字段
- MCP `de_list_devices` 返回 `name`,并在工具说明与 Agent 系统提示里要求"汇报用名称、
  调工具用 serial"

文档:API.md(items/name/auto_claim + §6.2.1 名称呈现表)、MCP.md(工具返回)

自测(全通过):自动认领端到端(开开关→扫描→自动迁址 + 名称保留 + 分组/任务引用同步 +
待连接池清理 + 开关默认关且可持久化);名称显示浏览器验证(监控页/覆盖设备 chip/AI 目标与
观看下拉/任务编辑器/分组弹窗/发现设置开关);设备指纹与人工认领回归
2026-09-11 11:16:24 +08:00
butubb 470c76221e feat: 顶栏新增「系统」栏目——数据备份导出/导入恢复子分栏(仅管理员)
monitor.html:导航 .tabs 追加「系统」(data-perm=admin) + #tab-system 面板,
内含「数据备份 / 导入恢复」两个子分栏;base.js _activeSubs 记忆子分栏并在
showTab 里切回;system.js:导出(含 APK 勾选→zip 下载)、导入(选文件→
校验预览:文件/schema/表行数/告警→确认应用,原生 confirm),全程含
「全量快照含密钥」警告与重启生效提示。
2026-09-09 14:49:40 +08:00
butubb e24458a085 feat: AI 控制台升级为顶级 Tab——DeepSeek 风格聊天界面(气泡+流式渲染+思考折叠),实时 MCP 步骤卡片(工具/参数/截图缩略),SSE 流式输出(delta/step/done/error 事件),配置模态(模型/Key/设备前端可配);工具页旧子栏移除 2026-09-04 13:09:34 +08:00
butubb fea5a57fc3 feat(M2): Web AI 控制台——工具页新增子分栏:模型/Key/设备前端可配置(app_meta 存储,key 打码回显),指令执行 + 步骤流轮询(含截图缩略)+ 回答展示;Agent 加 on_step 回调、后台线程单实例运行 2026-09-04 12:54:17 +08:00
butubb 441ff7c7da feat: 设备分组移入工具页(原顶级 tab 删除)——工具页新增「设备分组」子分栏,分组管理入口与其他设备工具聚合 2026-09-04 10:15:44 +08:00
butubb 4efe17c1c9 feat: 设备自动发现——定时扫描局域网+Tailscale 网段开放 adb 5555 的设备进入待连接池,用户确认后才加入正式设备池(不自动连接);socket 并发探测+adb 短超时验证(state=device 过滤 unauthorized),配置存 app_meta 可前端调整;配套:adb_connect_light 验证短超时、DISABLE_SCHEDULER 回归开关 2026-08-30 10:57:07 +08:00
butubb 265e47a1f4 fix: 测试此步骤弹窗全链路修复——closeTestModal 恢复(阶段3误删导致关不掉)、test-overlay 层级 1200(高于编辑器/元素抓取弹窗)、tasks_api 补 _log(后端500)、GenericStepsWorker 旧签名调用修复(测试执行失败) 2026-08-19 15:00:27 +08:00
butubb e07b339a51 feat: 大屏增强——一键亮屏按钮、卡片显示设备名+IP+熄屏状态(thumb 响应头 X-Screen-State)、点击卡片进入设备操作弹窗(实时流+触控+按键+文字),工具页远程看屏子分栏移除并入大屏 2026-08-19 14:17:33 +08:00
butubb 83ba489f57 feat: 前端整体改版(仪表控制台主题:自托管 Bricolage Grotesque+IBM Plex Mono 字体、暖纸底+墨色+深青主色、卡片/表格/徽章/模态框/Toast 全面细化、Tab 切换动画)+ fix: showTab 硬编码 tab 列表移除维护后索引错位、tools 分支调用已删的 loadStfDevMgmt、导航移除失效维护Tab 2026-08-19 14:03:02 +08:00
butubb 98244d8161 feat: 设备池管理面板(新增/停用/删除/一键重连,调度数据源规范化入口)+ STF 设备管理增删桥接同步设备池(迁移期) 2026-08-18 08:02:13 +08:00
butubb 645938b305 阶段2: USB 远程 adb server 打通(220 host 网络 5037 全接口监听,无需改 220)+ 自建远程看屏(MJPEG 流 + u2 触控 tap/swipe/key/text,ws-scrcpy 不在 npm 改自建) 2026-08-17 16:50:12 +08:00
butubb 060157ea1a refactor: 前端JS拆分为8个模块(base/list/monitor/editor/tasks/tools/apps/admin,按依赖顺序加载)+ 删除废弃文件(start_web.bat/main.py/fix_web.bat/cleanup.py,web已全覆盖)+ 文档同步 + 修复/api/summary缺导入 2026-08-11 14:53:04 +08:00