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 会读到上一次的内容 → 误报"写入可能被拒"(实测内容已写入却回失败)
This commit is contained in:
+10
-1
@@ -225,12 +225,21 @@ def validate_steps(steps, depth=1, path="steps", errors=None, warnings=None,
|
||||
# 执行器对认不出的运算符是"一律不命中",写错了会静默走 else,
|
||||
# 所以在这里拦住,别让 AI 草稿悄悄变成"永远不命中"
|
||||
cmp_op = (params.get("cmp_op") or "").strip()
|
||||
cmp_src = (params.get("cmp_source") or "").strip()
|
||||
if cmp_src not in ("", "manual", "device", "all", "group"):
|
||||
errors.append(f"{here}.params.cmp_source: 不支持的候选值来源 {cmp_src!r}"
|
||||
f"(可用:空/manual/device/all/group)")
|
||||
if cmp_src == "group" and not (params.get("cmp_group") or "").strip():
|
||||
warnings.append(f"{here}: 候选值来源是「按设备分组」,但没填分组名 —— 取不到号")
|
||||
if cmp_op:
|
||||
from tasks.generic.task import CMP_OPS
|
||||
if cmp_op not in CMP_OPS:
|
||||
errors.append(f"{here}.params.cmp_op: 不支持的比对运算符 {cmp_op!r}"
|
||||
f"(可用:{'、'.join(CMP_OPS)})")
|
||||
elif not str(params.get("cmp_value") or "").strip():
|
||||
elif not str(params.get("cmp_value") or "").strip() \
|
||||
and cmp_src not in ("device", "all", "group"):
|
||||
# 候选值来自台账时允许手填留空(台账取号就够);
|
||||
# 其余情况仍要求填值,否则永远不命中
|
||||
errors.append(f"{here}.params.cmp_value: 选了文本比对"
|
||||
f"({cmp_op})就必须填比对的值,否则永远不命中")
|
||||
elif (params.get("selector_type") or "xpath") == "screen":
|
||||
|
||||
Reference in New Issue
Block a user