From e82fd64695db67dafa1f7ff630f284025e4e0a94 Mon Sep 17 00:00:00 2001 From: butubb <1422726308@qq.com> Date: Thu, 24 Sep 2026 13:39:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=8E=BB=E9=87=8D):=20=E3=80=8C=E8=AE=B0?= =?UTF-8?q?=E4=B8=BA=E5=B7=B2=E5=81=9A=E3=80=8D=E7=95=99=E7=A9=BA=20=3D=20?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E8=B7=9F=E9=9A=8F=E4=B8=8A=E9=9D=A2=E3=80=8C?= =?UTF-8?q?=E5=8E=BB=E9=87=8D=E3=80=8D=E6=A3=80=E6=9F=A5=E7=9A=84=E8=BA=AB?= =?UTF-8?q?=E4=BB=BD=EF=BC=88=E4=B8=8D=E5=86=8D=E8=A6=81=E6=B1=82=E9=85=8D?= =?UTF-8?q?=E4=B8=A4=E9=81=8D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户提的(他说得对):"这个标记已做不是应该是我上面的条件判断命中哪一个就用哪一个做吗? 这怎么还要自己选择元素啊"。 原来的设计要求检查与记账**各配一次身份元素** —— 一旦一边填了、另一边忘了,两边算出的 key 不一致 → **去重静默失效**(现象就是"去重没生效、还是重复做",他刚踩过)。 而我在"有效期"上为了避免两处配置特意强制放任务级,却在"身份"上要求填两遍,自相矛盾。 改成: - `tasks/generic/task.py`:「去重」条件解析出的身份存进 `self._last_ident`; `_exec_mark_done` 的身份元素**留空时复用它**(检查与记账必然是同一个字符串)。 三种情况分清(这是关键,别退化成"用设备"误标): ① 自己填了身份元素 → 用自己填的(显式优先) ② 留空 + 上面跑过去重检查 → **复用那个身份** ③ 留空 + 检查**跑了但没读到身份**(页面没到)→ **不记账**,下次重跑重试 —— 绝不能退回设备身份,那会在"什么都没做成"时把设备标成已做 ④ 留空 + 任务里根本没有去重检查 → 退回设备身份(一号一机场景) - `static/admin/editor.js`:`mark_done` 面板文案改为"留空 = 自动跟随上面检查的身份(推荐)"; 校验里记账侧的**空值不再参与身份比对**(留空是合法的、且会自动对齐), 只有"填了、且和检查侧不一样"才告警,并在文案里建议留空。 - `doc/TASK_DEV.md` §4.6:身份只需在检查侧配一次(带一张四种组合的表);步骤表同步。 验证:新增 11 项(复用后账本身份 == 检查身份、换设备仍能命中=去重真生效、 显式填身份仍优先、无检查时退回设备、**读不到身份时不记账也不误标设备**); 原 dedup 套件(单元 + 真机)+ 编辑器语法回归全过; 把用户**生产任务的真实 JSON** 喂给新校验 —— **0 条警告**(旧版会报一条"身份不一致", 但现在留空=自动跟随是正确配置)。 --- doc/TASK_DEV.md | 24 ++++++++++++++++-------- static/admin/editor.js | 20 ++++++++++++-------- tasks/generic/task.py | 31 +++++++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/doc/TASK_DEV.md b/doc/TASK_DEV.md index 32b8032..03b5c23 100644 --- a/doc/TASK_DEV.md +++ b/doc/TASK_DEV.md @@ -136,7 +136,7 @@ from .generic import task # 触发 @register_task(当前唯一任务类型) | 19 | `notify` | 发通知 | — | `title`("")、`message`("")、`level`("info") | — | 推一条**自定义**通知(事件 `task.notify.custom`):标题正文自己写,支持 `{device} {serial} {job} {time} {app} {screen}`;谁收到取决于 webhook 的事件订阅。两者都空则跳过 | | 20 | `stop_self` | 停止本设备 | — | `reason`("") | — | 只停**本设备**的任务(其它设备照跑):置 worker 停止位,后续步骤不再执行,任务记成**被停止而不是失败**(不触发重试) | | 21 | `gesture` | 录制手势 | `points`(录出来的) | `speed`(1.0) | — | **纯录制回放**:把录下的轨迹点列 `[[x,y,t_ms],…]` 按原路径与时长交给设备插值,不做弧线/抖动/手速加工。与「滑动」是两套东西,见 §3.2 | -| 22 | `mark_done` | 记为已做 | —(身份元素可选填 `selector_type`/`selector_value`) | — | — | 把身份值记进**去重账本**(跨设备共享)。放动作**成功之后**——失败不记账,下次重跑会重试。留空 = 用设备 `serial` 当身份。**配套「条件判断 → 去重」用**,见 §4.6 | +| 22 | `mark_done` | 记为已做 | —(身份元素可选填 `selector_type`/`selector_value`) | — | — | 把身份值记进**去重账本**(跨设备共享)。放动作**成功之后**——失败不记账,下次重跑会重试。**留空 = 自动跟随上面「去重」检查的身份(推荐)**;没有前置检查时才退回设备 `serial`。见 §4.6 | ### 3.2 录制手势:**纯录制、纯回放**(`core/gesture.py`) @@ -375,21 +375,29 @@ from .generic import task # 触发 @register_task(当前唯一任务类型) "then": [{"type": "stop_self", "params": {"reason": "这个号今天已经评过了"}}], "else": [ {"type": "click", "params": {"selector_type": "text", "selector_value": "发送"}}, - {"type": "mark_done", "params": {"selector_type": "resourceId", - "selector_value": "com.ss.android.ugc.aweme:id/506"}} + {"type": "mark_done", "params": {}} // 身份留空 = 自动跟随上面检查用的身份 ]}} ``` **身份值**(去重的"谁")= 身份元素读出来的文本(上例=抖音号)。 -留空则该步骤用**设备 `serial`** 当身份(适合"一号一机")。 + +身份**只需在检查侧配一次**: + +| 位置 | 身份元素 | 结果 | +|---|---|---| +| 条件判断(去重) | 填账号元素 | 检查用这个身份 | +| **记为已做** | **留空(推荐)** | **自动跟随上面检查刚解析出的身份** —— 检查与记账必然用同一个 key | +| 记为已做 | 也填了 | 用自己填的;**与检查侧不一致时编辑器会告警** | +| 记为已做 | 留空 + 任务里没有去重检查 | 退回**设备 `serial`** 当身份("一号一机"场景) | + +> ⚠ 为什么把「留空 = 自动跟随」做成默认:检查与记账算的是同一个 key, +> 两处各配一遍、一边填了一边忘了 → 两个 key → **去重静默失效**(最难查的那种 bug, +> 现象是"去重没生效、还是重复做")。编辑器保存时会告警「两处身份不一致」 +> 「有去重检查但没有记为已做」「有记为已做但没有去重检查」。 **有效期**(去重多久算"新的一轮")在**任务级**配一次:`dedup_reset` = `day`(默认,每天一次) / `all`(只做一次)/ `hours`(每 `dedup_hours` 小时)。任务编辑器顶部有「去重有效期」下拉。 -> ⚠ **为什么有效期和身份元素都强制"只配一处"**:检查与记账两边算的是同一个 key, -> 一边填得不一样就会算出两个 key → **去重静默失效**(最难查的那种 bug)。 -> 编辑器保存时会直接告警:「身份元素不一致」「有去重检查但没有记为已做」等。 - **四条必须知道的语义**: | 情况 | 行为 | 为什么 | diff --git a/static/admin/editor.js b/static/admin/editor.js index 6e36df9..254bbf3 100644 --- a/static/admin/editor.js +++ b/static/admin/editor.js @@ -507,12 +507,13 @@ var _stepEditor={ true, true, isDedup?{hideValue:true}:null)+identRow; }else if(step.type==='mark_done'){ h+=_selRowHtml(p, - '