feat(编辑器): 选择器值旁边加「{变量}」按钮 + 「点击元素」补变量说明
用户反馈:"我看你这个点击元素也没有说点击变量啊" —— 上一版只在输入框 placeholder
里提了一句,等于没说:placeholder 只在空值时才显形,也没个能点的东西。
· 选择器值右边加 **「{变量}」按钮**(在「抓取元素/测试」旁边):点一下弹出
`{本次要发的名字}`(本轮要发的那个号)/ `{本机账号名字}`(读到的本机账号),
选中即插到光标处;通用编辑器和「发布计划」页的就地编辑**两处都有**
· **「点击元素」参数面板加说明块**:讲清"每轮都不一样的东西怎么点"——
类型选 textContains、值填 `{本次要发的名字}`;变量为空会变空串 + 记警告,
**不会拿 `{…}` 字面量去乱点**
· doc/TASK_DEV §3.3 补一句"编辑器里点按钮就行,不用记写法"
This commit is contained in:
+53
-2
@@ -81,6 +81,8 @@ function _selRowHtml(p, extra, withOcr, withDedup, keys){
|
||||
var toggle=withOcr?' onchange="_stepEditor._condTypeChanged(this)"':'';
|
||||
var pick=_can('devices')?'<button class="btn btn-xs btn-pick" onclick="_stepEditor.openPicker(this)">抓取元素</button>':'';
|
||||
var test=_can('devices')?'<button class="btn btn-xs" onclick="_stepEditor._testStep(this)" title="在设备上试执行本步骤,验证选择器是否命中">测试</button>':'';
|
||||
// 变量按钮:选择器值里可以直接写 {本次要发的名字} —— 点它弹出来选,省得记写法
|
||||
var varbtn='<button class="btn btn-xs" onclick="_stepEditor.insertVar(this)" title="把变量插进选择器值:{本次要发的名字}=本轮要发的那个号,{本机账号名字}=读到的本机账号">{变量}</button>';
|
||||
var isScreen=p[kType]==='screen', isFg=p[kType]==='foreground';
|
||||
var valLabel=isScreen?'屏幕状态':(isFg?'前台包名':'选择器值');
|
||||
var valHtml;
|
||||
@@ -90,7 +92,7 @@ function _selRowHtml(p, extra, withOcr, withDedup, keys){
|
||||
'<option value="on"'+(p[kVal]==='on'?' selected':'')+'>亮屏时就命中</option></select>';
|
||||
}else{
|
||||
valHtml='<input type="text" class="form-control" data-key="'+kVal+'" value="'+esc(p[kVal]||'')+
|
||||
'" placeholder="'+(isFg?'如 com.ss.android.ugc.aweme':'如 点赞;可用 {本次要发的名字} / {本机账号名字}')+'">'+(isFg?'':pick+test);
|
||||
'" placeholder="'+(isFg?'如 com.ss.android.ugc.aweme':'如 点赞;可用 {本次要发的名字} / {本机账号名字}')+'">'+(isFg?'':pick+test+varbtn);
|
||||
}
|
||||
var head='<div class="form-group"'+(keys.hideValue?' style="grid-column:span 3"':'')+'>'+
|
||||
'<label>选择器类型</label><select class="form-control" data-key="'+kType+'"'+toggle+'>'+opts+'</select></div>';
|
||||
@@ -379,7 +381,13 @@ var _stepEditor={
|
||||
h+=_humanizeRowHtml(p,'<div class="form-group"><label>幅度(屏占比)</label><input type="number" class="form-control" data-key="distance_ratio" value="'+(p.distance_ratio!=null?p.distance_ratio:0.6)+'" step="0.05" min="0.1" max="0.9"></div>');
|
||||
h+='<div class="help">想要"照我划的那一下原样重放",请用操作库里的《录制手势》步骤——那个是纯轨迹回放,不套这里的参数</div>';
|
||||
}else if(step.type==='click'){
|
||||
h+=_selRowHtml(p,'<div class="form-group"><label>等待超时(秒)</label><input type="number" class="form-control" data-key="wait_timeout" value="'+(p.wait_timeout||2)+'" step="0.5" min="0.5"></div>');
|
||||
h+=_selRowHtml(p,'<div class="form-group"><label>等待超时(秒)</label><input type="number" class="form-control" data-key="wait_timeout" value="'+(p.wait_timeout||2)+'" step="0.5" min="0.5"></div>'
|
||||
+'<div class="help"><b>要用"每轮都不一样的东西"点元素?</b>选择器值里可以直接写变量,'
|
||||
+'点值输入框右边的 <b>{变量}</b> 按钮插入:<code>{本次要发的名字}</code>(循环轮到 / 要发的那条计划的名字)、'
|
||||
+'<code>{本机账号名字}</code>(「读取文字」/「读取本机账号名字」读到的)。'
|
||||
+'例:在账号列表里点自己要发的那个号 —— 类型选 <b>textContains(文本包含)</b>、值填 <code>{本次要发的名字}</code>。'
|
||||
+'<br>变量那一刻还是空的(还没轮到 / 没读到)→ 值会变成空串并记一条警告,'
|
||||
+'这一步就是"找不到元素",<b>不会拿 {…} 字面量去乱点</b>。</div>');
|
||||
}else if(step.type==='long_click'){
|
||||
h+=_selRowHtml(p,'<div class="form-row"><div class="form-group"><label>长按时长(秒)</label><input type="number" class="form-control" data-key="duration" value="'+(p.duration||1.0)+'" step="0.5" min="0.3"></div>'+
|
||||
'<div class="form-group"><label>等待超时(秒)</label><input type="number" class="form-control" data-key="wait_timeout" value="'+(p.wait_timeout||2)+'" step="0.5" min="0.5"></div></div>');
|
||||
@@ -918,6 +926,49 @@ var _stepEditor={
|
||||
setTimeout(function(){self._renderCanvas();},0);
|
||||
},
|
||||
// 条件判断:候选值来源切到"平台给"(本次要发的名字 / 发布计划)时,把"比对的值"藏起来
|
||||
// 在选择器值里插入变量占位符:点「{变量}」→ 弹出两个变量 → 选中即插到光标处
|
||||
insertVar:function(btn){
|
||||
var old=document.getElementById('_varMenu');
|
||||
if(old){old.remove();}
|
||||
var box=btn.closest('.sel-picker')||btn.parentNode;
|
||||
var input=box.querySelector('input[data-key],textarea[data-key]')||box.querySelector('input,textarea');
|
||||
if(!input){return;}
|
||||
var items=[['{本次要发的名字}','本轮要发的那个号(循环块给的)'],
|
||||
['{本机账号名字}','读到的本机账号(读取文字/读取本机账号名字)']];
|
||||
var menu=document.createElement('div');
|
||||
menu.id='_varMenu';
|
||||
menu.style.cssText='position:fixed;z-index:9999;background:#fff;border:1px solid #d0d5dd;'
|
||||
+'border-radius:6px;box-shadow:0 6px 16px rgba(0,0,0,.16);padding:4px;min-width:260px;font-size:12px';
|
||||
menu.innerHTML=items.map(function(o){
|
||||
return '<div class="_varItem" data-v="'+o[0]+'" style="padding:6px 8px;cursor:pointer;border-radius:4px">'
|
||||
+'<code style="font-weight:600">'+o[0]+'</code>'
|
||||
+'<div style="color:#667085;margin-top:2px">'+o[1]+'</div></div>';}).join('');
|
||||
menu.querySelectorAll('._varItem').forEach(function(el){
|
||||
el.onmouseenter=function(){el.style.background='#f2f4f7';};
|
||||
el.onmouseleave=function(){el.style.background='';};
|
||||
el.onclick=function(e){
|
||||
e.stopPropagation();
|
||||
var t=input.value||'';
|
||||
var a=input.selectionStart==null?t.length:input.selectionStart;
|
||||
var b=input.selectionEnd==null?t.length:input.selectionEnd;
|
||||
input.value=t.slice(0,a)+el.dataset.v+t.slice(b);
|
||||
try{input.setSelectionRange(a+el.dataset.v.length,a+el.dataset.v.length);}catch(_){}
|
||||
input.dispatchEvent(new Event('input',{bubbles:true}));
|
||||
input.dispatchEvent(new Event('change',{bubbles:true}));
|
||||
input.focus();
|
||||
menu.remove();
|
||||
};
|
||||
});
|
||||
document.body.appendChild(menu);
|
||||
var r=btn.getBoundingClientRect();
|
||||
menu.style.left=Math.max(8,Math.min(r.left,window.innerWidth-280))+'px';
|
||||
menu.style.top=(r.bottom+4)+'px';
|
||||
setTimeout(function(){
|
||||
document.addEventListener('click',function h(){
|
||||
var m=document.getElementById('_varMenu'); if(m){m.remove();}
|
||||
document.removeEventListener('click',h);});
|
||||
},0);
|
||||
},
|
||||
_cmpSourceChanged:function(sel){
|
||||
// 同 _condTypeChanged:先把 DOM 的值同步回 _steps,否则重渲染会吞掉刚改的东西
|
||||
this._syncFromDom();
|
||||
|
||||
@@ -968,10 +968,14 @@ function _rpField(type, p, f, path) {
|
||||
var pick = (kind === 'selval' && typeof _can === 'function' && _can('devices'))
|
||||
? '<button class="btn btn-xs btn-pick" style="margin-left:4px" onclick="_stepEditor.openPicker(this)">抓取元素</button>'
|
||||
: '';
|
||||
// 「{变量}」:选择器值里写 {本次要发的名字}(本轮要发的那个号)—— 点它插进去,不用记写法
|
||||
var varbtn = (kind === 'selval' && typeof _stepEditor !== 'undefined' && _stepEditor.insertVar)
|
||||
? '<button class="btn btn-xs" style="margin-left:4px" onclick="_stepEditor.insertVar(this)" title="插入变量:{本次要发的名字}=本轮要发的那个号">{变量}</button>'
|
||||
: '';
|
||||
var ph = (kind === 'selval') ? ' placeholder="如 点赞;可用 {本次要发的名字}"' : '';
|
||||
return '<div class="form-group"' + span + ' style="margin-bottom:0">' + head
|
||||
+ '<div style="display:flex"><input type="text" class="form-control"' + ph + ' ' + attrs + ' value="'
|
||||
+ esc(v == null ? '' : v) + '">' + pick + '</div></div>';
|
||||
+ esc(v == null ? '' : v) + '">' + pick + varbtn + '</div></div>';
|
||||
}
|
||||
|
||||
// 抓取元素回填后:把选择器类型下拉也切过去(通用编辑器那套要看 .sc-body,这里结构不同)
|
||||
|
||||
Reference in New Issue
Block a user