Files
cmroubao/docs/design/android-task-running.html
T

76 lines
8.7 KiB
HTML

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>App 任务执行 - 低保真原型</title>
<style>
:root{color-scheme:light;--ink:#17212b;--muted:#5d6973;--line:#cbd3d9;--surface:#fff;--bg:#eef1f3;--primary:#176b52;--warn:#8b5a08;--danger:#a13a32;--focus:#c57414}
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.45 system-ui,-apple-system,"Segoe UI","Microsoft YaHei",sans-serif;letter-spacing:0;padding-top:38px}
.prototype{position:fixed;z-index:30;top:0;left:0;right:0;height:38px;display:grid;place-items:center;background:#2d343a;color:#fff;font-size:12px;font-weight:700}.phone{width:min(100%,420px);min-height:calc(100vh - 38px);margin:auto;background:#f7f8f9;border-inline:1px solid var(--line);padding-bottom:104px}
header{min-height:64px;display:flex;align-items:center;justify-content:space-between;padding:8px 18px;background:#fff;border-bottom:1px solid var(--line)}h1,h2,p{margin-top:0}h1{font-size:19px;margin-bottom:2px}.sub{color:var(--muted);font-size:12px}.status-word{padding:6px 8px;border:1px solid #76a994;color:#0e5942;font-size:12px;font-weight:800}
main{padding:16px}.panel{padding:15px;margin-bottom:14px;background:#fff;border:1px solid var(--line);border-radius:6px}.panel h2{font-size:16px;margin-bottom:12px}
label{font-size:13px;font-weight:700}select,button,a{font:inherit}select{width:100%;min-height:44px;margin-top:6px;padding:8px;border:1px solid #89959e;border-radius:6px;background:#fff}
.current{border-left:4px solid var(--primary);background:#e9f3ef}.current.warn{border-color:var(--warn);background:#fff5df}.current.danger{border-color:var(--danger);background:#fff0ee}.current strong,.current span{display:block}.current strong{font-size:17px}.current span{margin-top:4px;color:var(--muted)}
ol{list-style:none;margin:0;padding:0}li{position:relative;min-height:52px;padding:5px 0 10px 38px;border-left:2px solid #c8d0d5;margin-left:12px}li:last-child{border-left-color:transparent}li::before{content:"";position:absolute;left:-8px;top:7px;width:14px;height:14px;border:2px solid #7b8790;border-radius:50%;background:#fff}li.done::before{background:var(--primary);border-color:var(--primary)}li.now::before{border:4px solid var(--primary)}li strong,li span{display:block}li span{font-size:13px;color:var(--muted)}
.notification{border-left:4px solid #596a78;background:#edf0f2}.notification p{margin:0;color:var(--muted)}.notification-actions{display:flex;gap:8px;margin-top:10px}.notification a{min-height:44px;display:flex;align-items:center;padding:0 12px;border:1px solid #7e8991;border-radius:6px;color:var(--ink);text-decoration:none;font-weight:700}
.bottom{position:fixed;z-index:10;bottom:0;left:50%;transform:translateX(-50%);width:min(100%,420px);display:flex;gap:10px;padding:12px 18px 16px;background:#fff;border-top:1px solid var(--line)}.bottom button,.bottom a{min-height:52px;display:grid;place-items:center;border-radius:6px;font-weight:800;text-decoration:none}.stop{flex:1;border:1px solid var(--danger);background:#fff;color:var(--danger)}.return{flex:1.2;border:0;background:var(--primary);color:#fff}
dialog{width:min(calc(100% - 32px),380px);padding:0;border:1px solid var(--line);border-radius:6px}dialog::backdrop{background:#18212a88}.dialog-body{padding:20px}.dialog-body h2{font-size:19px}.dialog-actions{display:flex;gap:10px;justify-content:flex-end;padding:14px 20px;border-top:1px solid var(--line)}.dialog-actions button{min-height:46px;padding:0 16px;border-radius:6px;font-weight:750}.cancel{border:1px solid #7e8991;background:#fff}.confirm-stop{border:0;background:var(--danger);color:#fff}
button:focus-visible,a:focus-visible,select:focus{outline:3px solid color-mix(in srgb,var(--focus) 45%,transparent);outline-offset:2px}@media(max-width:420px){.phone{border:0}}
</style>
</head>
<body>
<div class="prototype">PROTOTYPE - 仅供确认布局和交互,不是生产实现</div>
<div class="phone">
<header><div><h1>正在执行任务</h1><span class="sub">#DEMO-2407</span></div><span class="status-word" id="statusWord">运行中</span></header>
<main>
<section class="panel">
<label for="scenario">原型状态</label>
<select id="scenario">
<option value="running">正在检查候选</option>
<option value="stopping">正在安全停止</option>
<option value="captcha">验证码拦截 · 安全错误</option>
<option value="manual">低置信度 · 等待人工</option>
</select>
</section>
<section class="panel current" id="current" role="status" aria-live="polite">
<strong>检查候选 3 / 最多 5 个</strong><span>正在核对标题、规格、数量与预算约束。</span>
</section>
<section class="panel" aria-labelledby="stepsTitle">
<h2 id="stepsTitle">执行步骤</h2>
<ol id="steps">
<li class="done"><strong>设备预检</strong><span>权限、应用和网络均可用</span></li>
<li class="done"><strong>理解采购要求</strong><span>原始数量和预算已锁定</span></li>
<li class="done"><strong>打开拼多多并搜索</strong><span>使用派生关键词检索</span></li>
<li class="now"><strong>检查候选</strong><span>有界检查,不自动下单</span></li>
<li><strong>等待人工确认</strong><span>到达后自动化硬停止</span></li>
</ol>
</section>
<section class="panel notification">
<h2>前台服务通知</h2>
<p>切换到拼多多后,可通过持续通知稳定返回本页或请求停止。</p>
<div class="notification-actions"><a href="android-task-running.html">返回任务</a><a href="#stop" id="notificationStop">停止</a></div>
</section>
</main>
<div class="bottom" id="bottom"><button class="stop" id="stop" type="button">安全停止</button><a class="return" href="android-candidate-confirm.html">模拟找到候选</a></div>
</div>
<dialog id="stopDialog" aria-labelledby="stopTitle">
<div class="dialog-body"><h2 id="stopTitle">安全停止任务?</h2><p>系统会等待当前动作到达安全边界,保存执行状态后停止。不会立即销毁状态。</p></div>
<div class="dialog-actions"><button class="cancel" id="cancelStop" type="button">取消</button><button class="confirm-stop" id="confirmStop" type="button">确认停止</button></div>
</dialog>
<script>
const scenario=document.querySelector("#scenario"),current=document.querySelector("#current"),statusWord=document.querySelector("#statusWord"),bottom=document.querySelector("#bottom"),dialog=document.querySelector("#stopDialog"),cancel=document.querySelector("#cancelStop");
const states={
running:{status:"运行中",kind:"",html:"<strong>检查候选 3 / 最多 5 个</strong><span>正在核对标题、规格、数量与预算约束。</span>",actions:'<button class="stop" id="stop" type="button">安全停止</button><a class="return" href="android-candidate-confirm.html">模拟找到候选</a>'},
stopping:{status:"安全停止中",kind:"warn",html:"<strong>正在安全停止</strong><span>等待当前动作结束并保存状态,请勿强制关闭。</span>",actions:'<a class="return" href="android-task-result.html#canceled">查看停止结果</a>'},
captcha:{status:"已安全停止",kind:"danger",html:"<strong>检测到验证码,自动化已停止</strong><span>安全错误 SAFETY_CAPTCHA 不允许自动继续或自动重试。</span>",actions:'<a class="return" href="android-task-result.html#failed">查看失败原因</a>'},
manual:{status:"等待人工",kind:"warn",html:"<strong>AI 结果置信度不足</strong><span>自动化已停止,请转入人工确认,不会猜测继续。</span>",actions:'<a class="return" href="android-candidate-confirm.html#manual">进入人工确认</a>'}
};
function bindStop(){const stop=document.querySelector("#stop");if(stop)stop.addEventListener("click",openStop)}
function openStop(e){if(e)e.preventDefault();dialog.showModal();setTimeout(()=>cancel.focus(),0)}
scenario.addEventListener("change",()=>{const s=states[scenario.value];statusWord.textContent=s.status;current.className="panel current "+s.kind;current.innerHTML=s.html;bottom.innerHTML=s.actions;bindStop()});
document.querySelector("#notificationStop").addEventListener("click",openStop);cancel.addEventListener("click",()=>dialog.close());document.querySelector("#confirmStop").addEventListener("click",()=>{dialog.close();scenario.value="stopping";scenario.dispatchEvent(new Event("change"))});dialog.addEventListener("cancel",e=>{e.preventDefault();dialog.close()});bindStop();
</script>
</body>
</html>