feat(发布计划): 新增「校验页面」步骤(expect_el)—— 每一步先确认上一步真的完成了
用户要求:"进行每一步的时候先校验上一步有没有完成,比如相册界面肯定有特征,如果没有到相册界面
就出现执行,你看看怎么处理" → 方案 A:新增只做校验、不带副作用的步骤。
· tasks/generic/task.py:新步骤 expect_el
- 参数:特征元素选择器 / timeout(10) / what("在等什么") / on_missing
- on_missing:skip_rest(默认,**跳过本轮剩余步骤** —— 这一条不发、换下一个号) / notify / stop
- 为此加了 worker 级的 `_skip_rest`:_exec_steps 每步前检查,foreach_account 每轮复位
· 骨架:关键点击前各插一个 —— 相册页(//*[@text='所有照片']) → 素材已选中(desc 选择/预览)
→ 剪辑页(desc 文字/话题) → 发布页(含'添加标题'/'添加作品描述') → 发布按钮
· 通知:新增 task.page.mismatch(页面不对,本轮剩余步骤已跳过)
· 昵称选择器改**两版通吃**(实测 A06=40.7.0):xpath 联合
`//*[@resource-id="…:id/tkv"] | //*[@resource-id="…:id/tk+"]`
—— 40.7 是 tkv、40.6 是 tk+,联合在 40.7 上实测能读到名字;.env(dev)已改,切号入口两版同为 desc=切换账号
· 前端:编辑器面板 + 参数表单 + 发布页就地编辑字段表都认 expect_el
· 文档:TASK_DEV §3(27→28 种)+ §4.7("每步先校验上一步")、NOTIFY、research §七·补(40.7.0 对照表
+ 联合 xpath + 各页特征 + "别按坐标点页签"的坑)、.env.example
· 测试:新增 scripts/tests/test_expect_el.py(特征在/不在、三种 on_missing、选择器为空),全套 7 个用例通过
This commit is contained in:
@@ -22,6 +22,7 @@ var STEP_LIB=[
|
||||
{type:'if_el',label:'条件判断',icon:'❓',cat:'flow',params:{selector_type:'xpath',selector_value:'',timeout:3,ocr_click:false,cmp_op:'',cmp_value:'',cmp_source:'',cmp_group:'',ident_type:'text',ident_value:'',then:[],else:[]}},
|
||||
{type:'mark_done',label:'记为已做',icon:'✅',cat:'flow',params:{selector_type:'text',selector_value:''}},
|
||||
{type:'read_account_name',label:'读取本机账号名字',icon:'🏷',cat:'flow',params:{selector_type:'xpath',selector_value:'',timeout:8,on_missing:'fail'}},
|
||||
{type:'expect_el',label:'校验页面',icon:'🔎',cat:'flow',params:{selector_type:'xpath',selector_value:'',timeout:10,on_missing:'skip_rest',what:''}},
|
||||
{type:'switch_account',label:'切换账号',icon:'🔁',cat:'flow',params:{target:'var:target_name',target_value:'',switch_selector_type:'xpath',switch_selector_value:'',name_selector_type:'',name_selector_value:'',me_selector_type:'descriptionContains',me_selector_value:'我',timeout:8,wait_after:15,verify:true,max_attempts:2,on_login_page:'stop'}},
|
||||
{type:'foreach_account',label:'循环本机待发的号',icon:'🔂',cat:'flow',params:{date_source:'today',fixed_date:'',retry_failed:true,max_accounts:0,children:[]}},
|
||||
{type:'notify',label:'发通知',icon:'🔔',cat:'flow',params:{title:'',message:'',level:'info'}},
|
||||
@@ -474,6 +475,22 @@ var _stepEditor={
|
||||
'<div class="form-group" data-lmode="rounds" style="display:'+(lm==='rounds'?'block':'none')+'"><label>最大循环次数</label><input type="number" class="form-control" data-key="max_iterations" value="'+(p.max_iterations||10)+'" min="1" max="100000"></div>'+
|
||||
'<div class="form-group" data-lmode="time" style="display:'+(lm==='time'?'block':'none')+'"><label>循环时长(秒)</label><input type="number" class="form-control" data-key="loop_duration" value="'+(p.loop_duration||600)+'" min="1"></div></div>';
|
||||
h+='<div class="help">将下方子步骤循环执行指定轮次/时长;<b>一直循环</b>无限跑直到任务被外部停止——配合调度"定时启动+停止"(如 9:00 启动 / 18:00 停止)实现全天候养号,或配合任务"运行时长上限"自动停止</div>';
|
||||
}else if(step.type==='expect_el'){
|
||||
// 校验页面:只做校验、不带副作用 —— 确认"上一步真的完成了"
|
||||
var om=p.on_missing||'skip_rest';
|
||||
h+='<div class="form-row"><div class="form-group"><label>等它出现(这一页的特征元素)</label><input type="text" class="form-control" data-key="selector_value" value="'+esc(p.selector_value||'')+'" placeholder="如 //*[@text=\'所有照片\']"></div>'+
|
||||
'<div class="form-group"><label>最多等(秒)</label><input type="number" class="form-control" data-key="timeout" value="'+(p.timeout||10)+'" min="1" max="60"></div></div>';
|
||||
h+='<div class="form-row"><div class="form-group"><label>选择器类型</label><select class="form-control" data-key="selector_type">'+
|
||||
['xpath','resourceId','descriptionContains','text','description','className'].map(function(t){
|
||||
return '<option value="'+t+'"'+((p.selector_type||'xpath')===t?' selected':'')+'>'+t+'</option>';}).join('')+
|
||||
'</select></div>'+
|
||||
'<div class="form-group"><label>等不到时</label><select class="form-control" data-key="on_missing">'+
|
||||
[['skip_rest','跳过本轮剩余步骤(推荐:这一条不发)'],['notify','只发通知、继续(有盲点风险)'],['stop','停本设备']].map(function(o){
|
||||
return '<option value="'+o[0]+'"'+(om===o[0]?' selected':'')+'>'+o[1]+'</option>';}).join('')+
|
||||
'</select></div></div>';
|
||||
h+='<div class="form-group"><label>说明(写进日志/通知,如"应在相册页")</label><input type="text" class="form-control" data-key="what" value="'+esc(p.what||'')+'"></div>';
|
||||
h+='<div class="help">放在关键点击<b>前面</b>:确认上一步真的完成了(该出现的特征元素在不在)。'+
|
||||
'页面不对就按上面的选项处置 —— 避免在错的页面上继续盲点,最后"跑完了但什么都没发出去"。</div>';
|
||||
}else if(step.type==='foreach_account'){
|
||||
// 循环本机待发的号(发布流程的最外层容器):把"跑哪些号"讲清楚,别让人以为是普通循环
|
||||
const fds=(p.date_source==='fixed')?'fixed':'today';
|
||||
|
||||
@@ -734,6 +734,12 @@ var _RP_FIELDS = {
|
||||
['album_dir', '推到手机哪个目录', 'text'],
|
||||
['to_clipboard', '标题写进手机剪贴板', 'chk'],
|
||||
['max_same_run', '一次推几条', 'num']],
|
||||
expect_el: [['what', '说明(如"应在相册页")', 'text'],
|
||||
['selector_type', '选择器类型', 'seltype'],
|
||||
['selector_value', '等它出现(这一页的特征元素)', 'selval'],
|
||||
['timeout', '最多等(秒)', 'num'],
|
||||
['on_missing', '等不到时', 'sel', [['skip_rest', '跳过本轮剩余步骤(推荐)'],
|
||||
['notify', '只通知、继续'], ['stop', '停本设备']]]],
|
||||
read_account_name: [['selector_type', '选择器类型', 'seltype'],
|
||||
['selector_value', '选择器值(抖音「我」页的昵称)', 'selval'],
|
||||
['timeout', '超时(秒)', 'num'],
|
||||
|
||||
Reference in New Issue
Block a user