docs(architecture): adopt authorized single-pass purchase

This commit is contained in:
QiuSW
2026-08-04 16:25:34 +08:00
parent 8ba9b231f4
commit cfd5440ac0
23 changed files with 1264 additions and 1835 deletions
+42 -44
View File
@@ -398,12 +398,12 @@
<option value="version_mismatch">未就绪 · 拼多多版本失配</option>
<option value="idle" selected>已就绪 · 尚未轮询</option>
<option value="polling">轮询中 · 暂无任务</option>
<option value="trial">执行中 · 第一趟试选</option>
<option value="trial_done">第一趟完成 · 已释放手机</option>
<option value="dry_run">执行中 · 下单只读演练</option>
<option value="dry_run_ready">演练完成 · 等待真实第二趟</option>
<option value="order_prefence">真实第二趟 · 围栏前校验</option>
<option value="fencing">真实第二趟 · 申请围栏中</option>
<option value="claimed">单趟执行 · 已领取</option>
<option value="selecting">单趟执行 · 选择规格</option>
<option value="gate1">单趟执行 · 闸门一</option>
<option value="quantity_gate2">单趟执行 · 数量与闸门二</option>
<option value="confirm_gate3">单趟执行 · 确认页与闸门三</option>
<option value="fencing">单趟执行 · 申请围栏中</option>
<option value="fence_failed">围栏失败或响应不明 · 不点击</option>
<option value="fenced">围栏后 · 核对同一提交</option>
<option value="waiting_payment">明确已创建 · 等人付款</option>
@@ -469,7 +469,7 @@
<div class="span-2"><dt>商品</dt><dd id="product">暂无商品;轮询会在安全就绪后领取一条任务</dd></div>
<div><dt>颜色分类</dt><dd id="color">—</dd></div>
<div><dt>尺码 / 数量</dt><dd id="size-qty">—</dd></div>
<div><dt>授权单价</dt><dd id="auth-price">—</dd></div>
<div><dt>闸门一单价</dt><dd id="gate1-price">—</dd></div>
<div><dt>金额上限</dt><dd id="price-cap">—</dd></div>
<div class="span-2"><dt>提交围栏</dt><dd id="submission">未建立</dd></div>
</dl>
@@ -583,41 +583,41 @@
const task = {
id: 'CB-20260803-0042',
product: '纯棉圆领短袖 T 恤(原型假数据)',
color: '白色', sizeQty: 'XL / 2 件', authPrice: 'CNY 32.50', cap: 'CNY 80.00'
color: '白色', sizeQty: 'XL / 2 件', gate1Price: 'CNY 32.50', cap: 'CNY 80.00'
};
const records = [
{
id:'REC-DEMO-0042', taskId:'CB-20260803-0042', title:'纯棉圆领短袖 T 恤(原型假数据)', collectedAt:'2026-08-03T13:52:18+08:00',
status:'RECONCILIATION_REQUIRED', spec:'白色 | XL | 2 件', cap:'CNY 80.00', submission:'SUB-DEMO-0042 · 结果不明确',
note:'围栏后网络中断,订单可能已创建。只允许核查同一提交记录,不能重试。', evidence:['商品页截图裁剪(内联假证据)','规格面板截图(内联假证据)'],
timeline:['13:51:04 重新选择同一规格','13:51:41 三道价格闸门通过(假数据)','13:51:58 围栏已建立','13:52:18 点击结果不明确,转人工核查'],
note:'围栏后网络中断,订单可能已创建。只允许核查同一提交记录,不能重试。', evidence:['商品页原始截图(内联假证据)','规格面板原始截图(内联假证据)'],
timeline:['13:51:04 同一趟精确选择规格','13:51:41 三道价格闸门通过(假数据)','13:51:58 围栏已建立','13:52:18 点击结果不明确,转人工核查'],
result:'下单待核查:白色 | XL | CNY 32.50 | 2 件', resultNote:'订单可能已创建、支付未完成。系统不会再次提交,也不会付款。'
},
{
id:'REC-DEMO-0041', taskId:'CB-20260803-0041', title:'办公室桌面收纳盒(原型假数据)', collectedAt:'2026-08-03T12:24:09+08:00',
status:'WAITING_CONFIRMATION', spec:'透明 | L | 2 件', cap:'CNY 60.00', submission:'未建立',
note:'第一趟试选完成,规格面板证据已回传,等待管理员确认。', evidence:['商品页截图裁剪(内联假证据)','规格面板截图(内联假证据)'],
timeline:['12:22:31 打开商品','12:23:04 匹配透明 / L','12:23:38 读取规格面板单价','12:24:09 截图并退出商品页'],
result:'试选:透明 | L | CNY 24.00 | 2 件', resultNote:'这只是试选结果,不代表已下单。'
status:'ORDERING', spec:'透明 | L | 2 件', cap:'CNY 60.00', submission:'未建立',
note:'管理员已开始采购,当前单趟已完成规格与闸门一,正在设置并复核数量。', evidence:['商品页截图(内联假证据)','规格面板原始截图(内联假证据)'],
timeline:['12:22:31 领取一次性授权','12:23:04 精确匹配透明 / L','12:23:38 闸门一读取 CNY 24.00','12:24:09 正在复核数量与闸门二'],
result:'执行中:透明 | L | CNY 24.00 | 2 件', resultNote:'无需等待管理员中途确认;任一门禁失败即停止。'
},
{
id:'REC-DEMO-0038', taskId:'CB-20260803-0038', title:'标签打印纸补货(原型假数据)', collectedAt:'2026-08-03T10:06:42+08:00',
status:'WAITING_PAYMENT', spec:'白色 | 50×30 | 1 件', cap:'CNY 50.00', submission:'SUB-DEMO-0038 · SUBMITTED',
note:'已明确创建待付款订单,自动化已停止,等待人核对后自行付款。', evidence:['订单确认页非敏感截图(内联假证据)'],
timeline:['10:04:22 重新选择同一规格','10:05:10 价格与数量复核通过','10:05:36 获得唯一围栏许可','10:06:42 明确创建待付款订单'],
note:'已明确创建待付款订单,自动化已停止,等待人核对后自行付款。', evidence:['订单确认页内部原始截图(内联假证据)'],
timeline:['10:04:22 同一趟精确选择规格','10:05:10 两次价格与数量复核通过','10:05:36 获得唯一围栏许可','10:06:42 明确创建待付款订单'],
result:'已创建待付款订单:白色 | 50×30 | CNY 46.00 | 1 件', resultNote:'系统只创建待付款订单,付款始终由人完成。'
},
{
id:'REC-DEMO-0032', taskId:'CB-20260803-0032', title:'仓库打包胶带(原型假数据)', collectedAt:'2026-08-03T09:18:05+08:00',
status:'NEEDS_MANUAL', spec:'透明 | 45mm | 4 件', cap:'CNY 55.00', submission:'未建立',
note:'商品页面未取得可信图片,授权价与当前规格面板价格不一致,已转人工。', evidence:[],
note:'设置数量后规格面板价格与闸门一不一致,已在围栏前转人工。', evidence:[],
timeline:['09:16:40 打开商品','09:17:22 匹配透明 / 45mm','09:18:05 价格闸门二不通过,停止自动流程'],
result:'未采购:授权价 CNY 12.00 | 当前价 CNY 13.50', resultNote:'没有创建订单,也没有付款。'
result:'未采购:闸门一 CNY 12.00 | 闸门二 CNY 13.50', resultNote:'没有建立围栏、创建订单或付款。'
}
].sort((a, b) => b.collectedAt.localeCompare(a.collectedAt));
const recordStatus = {
RECONCILIATION_REQUIRED:{label:'结果待核查',tone:'critical'},
WAITING_CONFIRMATION:{label:'等待确认',tone:'caution'},
ORDERING:{label:'采购执行中',tone:'info'},
WAITING_PAYMENT:{label:'待付款',tone:'success'},
NEEDS_MANUAL:{label:'转人工',tone:'caution'}
};
@@ -627,40 +627,38 @@
let detailRequestId = 0;
const baseSteps = {
idle: [],
trial: ['打开商品(待真机判据)', '精确匹配颜色分类与尺码', '从规格面板读取单价', '截图并退出商品页'],
dry: ['重新打开商品(待真机判据)', '精确选择与数量复核', '读取订单确认页非敏感摘要', '验证提交控件唯一后退出'],
order: ['重新选择同一规格', '闸门二:单价必须等于授权价', '数量复核与闸门三', '申请服务端提交围栏', '围栏许可后内部仅点击一次', '调和同一提交结果']
single: ['核对一次性授权并打开商品', '精确选择颜色分类与尺码', '闸门一:读取 SKU 单价并校验上限', '设置数量、读回并执行闸门二', '确认页执行闸门三与控件唯一校验', '申请服务端提交围栏', '首次许可后持久化并内部点击一次', '调和同一提交结果']
};
const scenarios = {
not_ready: { tone:'critical', title:'web 服务不可达', text:'未开始轮询。检查本地网络和服务地址;已完成的本地证据会保留待补传。', web:'bad', device:'ok', version:'ok', leg:'未就绪', legTone:'critical', action:'开始轮询', enabled:false, reason:'web 服务未就绪,不能领取任务。', session:'未启动', step:'连接检查', kind:'idle', active:-1, countdown:'—', fail:'1 / 3' },
version_mismatch: { tone:'critical', title:'拼多多版本与证据不一致', text:'已 fail closed:停止领取真机任务。下一步是由人重新取证并记录 App 版本,不能沿用旧判据。', web:'ok', device:'ok', version:'bad', leg:'版本失配', legTone:'critical', action:'开始轮询', enabled:false, reason:'App 版本失配;必须先完成本项目真机取证。', session:'已停止', step:'等待重新取证', kind:'idle', active:-1, countdown:'—', fail:'0 / 3' },
idle: { tone:'success', title:'设备已就绪(模拟)', text:'三项就绪条件在本场景中均为模拟通过,可以演示定时轮询;不会连接真实设备。', web:'ok', device:'ok', version:'ok', leg:'空闲', legTone:'success', action:'开始轮询', enabled:true, reason:'点击只切换原型状态,不发起网络请求。', session:'未启动', step:'等待开始', kind:'idle', active:-1, countdown:'—', fail:'0 / 3' },
polling: { tone:'info', title:'正在轮询,暂无待领任务', text:'无任务是正常空状态,不计入失败;将按配置间隔继续检查。', web:'ok', device:'ok', version:'ok', leg:'轮询中', legTone:'info', action:'停止轮询', enabled:true, reason:'停止后不再领取新任务。', session:'运行中', step:'等待下一轮', kind:'idle', active:-1, countdown:'00:12', fail:'0 / 3', count:2 },
trial: { tone:'info', title:'第一趟试选正在执行', text:'只勾选规格、读价和截图;不会进入订单确认流程,完成后必须退出商品页释放手机。', web:'ok', device:'ok', version:'ok', leg:'TRIAL · 第一趟试选', legTone:'info', action:'真机步骤执行中', enabled:false, reason:'真机步骤期间禁用硬取消和关闭,避免留下无法判定的中间态。', session:'运行中', step:'读取规格面板单价', kind:'trial', active:2, countdown:'暂停', fail:'0 / 3', lease:'04:18' },
trial_done: { tone:'success', title:'试选已回传,手机已释放', text:'规格与价格证据已保存(模拟);任务等待管理员确认,本设备继续下一轮。', web:'ok', device:'ok', version:'ok', leg:'TRIAL · 已完成', legTone:'success', action:'停止轮询', enabled:true, reason:'手机已退出商品页,可以安全停止轮询。', session:'运行中', step:'等待下一轮', kind:'trial', active:4, countdown:'00:09', fail:'0 / 3', count:3 },
dry_run: { tone:'info', title:'DRY-RUN · 只读演练', text:'只到订单确认页读取非敏感摘要并验证控件唯一;不会提交订单,也不会消费授权。', web:'ok', device:'ok', version:'ok', leg:'DRY-RUN · 不会提交', legTone:'info', action:'只读演练进行中', enabled:false, reason:'演练中不提供提交动作;真机步骤期间受控关闭。', session:'运行中', step:'读取订单确认页', kind:'dry', active:2, countdown:'暂停', fail:'0 / 3', lease:'03:42' },
dry_run_ready: { tone:'success', title:'只读演练已完成', text:'演练证据已回传(模拟)并退出确认页。旧演练不能替代真实第二趟的当前页面事实。', web:'ok', device:'ok', version:'ok', leg:'DRY-RUN · READY', legTone:'success', action:'停止轮询', enabled:true, reason:'等待服务端安排真实第二趟;不会由用户直接触发提交。', session:'运行中', step:'等待真实第二趟', kind:'dry', active:4, countdown:'00:16', fail:'0 / 3', count:4 },
order_prefence: { tone:'caution', title:'真实第二趟 · 围栏前校验', text:'正在重新验证授权、闸门二、数量、闸门三和控件唯一。此时尚无点击许可。', web:'ok', device:'ok', version:'ok', leg:'ORDER · 围栏前', legTone:'caution', action:'安全校验进行中', enabled:false, reason:'没有服务端围栏许可,绝不能点击提交订单。', session:'运行中', step:'闸门三:核对实付款', kind:'order', active:2, countdown:'暂停', fail:'0 / 3', lease:'02:58' },
fencing: { tone:'caution', title:'正在申请服务端提交围栏', text:'等待明确的 click_permitted。超时、冲突、网络失败或响应不明都不会点击。', web:'ok', device:'ok', version:'ok', leg:'ORDER · 申请围栏', legTone:'caution', action:'等待围栏响应', enabled:false, reason:'申请中禁止取消、关闭或重复申请。', session:'运行中', step:'申请唯一提交围栏', kind:'order', active:3, countdown:'暂停', fail:'0 / 3', lease:'02:31' },
fence_failed: { tone:'critical', title:'未获得点击许可', text:'围栏申请失败或响应不明:没有点击提交订单。请按幂等键核查服务端记录,不能直接重试。', web:'bad', device:'ok', version:'ok', leg:'ORDER · 未获许可', legTone:'critical', action:'打开围栏核查说明', enabled:true, safeAction:'review', reason:'只核查围栏状态,不会触发提交。', session:'已停止', step:'核查幂等键', kind:'order', active:3, countdown:'—', fail:'1 / 3', submission:'围栏状态未知 · 幂等键 DEMO-FENCE-042' },
fenced: { tone:'caution', title:'围栏已建立,只核对同一提交', text:'submission_id 已固定。内部流程至多点击一次;用户界面不提供提交、重领、放弃或重试入口。', web:'ok', device:'ok', version:'ok', leg:'ORDER · 已围栏', legTone:'caution', action:'打开同一提交核查说明', enabled:true, safeAction:'review', reason:'只能查看与调和同一提交记录。', session:'受控执行', step:'调和订单结果', kind:'order', active:5, countdown:'暂停', fail:'0 / 3', lease:'01:49', submission:'SUB-DEMO-0042 · FENCED' },
waiting_payment: { tone:'success', title:'已明确创建待付款订单', text:'自动化已停止。系统不会付款;请人在拼多多核对后自行付款,再到采购服务标记。', web:'ok', device:'ok', version:'ok', leg:'WAITING_PAYMENT', legTone:'success', action:'查看待付款说明', enabled:true, safeAction:'paymentInfo', reason:'仅显示人工收口说明,不执行支付。', session:'已停止', step:'等待人工付款', kind:'order', active:6, countdown:'—', fail:'0 / 3', count:5, submission:'SUB-DEMO-0042 · SUBMITTED' },
uncertain: { tone:'critical', title:'订单可能已创建,结果不明确', text:'保持金额预留和永久围栏,只核查 SUB-DEMO-0042;禁止重新领取、放弃授权或再次点击。', web:'ok', device:'ok', version:'ok', leg:'RECONCILIATION_REQUIRED', legTone:'critical', action:'打开人工核查说明', enabled:true, safeAction:'review', reason:'核查不会发起新的下单。可另行导出假证据摘要。', session:'已停止', step:'人工核查同一提交', kind:'order', active:5, countdown:'—', fail:'0 / 3', submission:'SUB-DEMO-0042 · 结果不明确' },
security: { tone:'critical', title:'检测到安全校验,已停止', text:'保留现场并转人工;不尝试绕过验证码、风控、人脸或短信校验。若已围栏,只调和同一提交。', web:'ok', device:'ok', version:'ok', leg:'待人工 · 安全校验', legTone:'critical', action:'打开人工核查说明', enabled:true, safeAction:'review', reason:'只显示核查说明,不提供绕过或继续入口。', session:'已停止', step:'等待人工处理', kind:'order', active:5, countdown:'—', fail:'1 / 3', submission:'SUB-DEMO-0042 · RECONCILIATION_REQUIRED' },
payment_handoff: { tone:'critical', title:'进入外部支付交接,已停止', text:'订单可能已创建、支付未完成。不会读取或输入支付凭据,也没有“继续付款”按钮。', web:'ok', device:'ok', version:'ok', leg:'待人工 · 外部支付', legTone:'critical', action:'打开人工核查说明', enabled:true, safeAction:'paymentInfo', reason:'只显示人工核查与付款边界。', session:'已停止', step:'人工核查同一提交', kind:'order', active:5, countdown:'—', fail:'0 / 3', submission:'SUB-DEMO-0042 · HANDED_OFF' },
manual: { tone:'caution', title:'任务已转人工:授权价与现价不一致', text:'授权 CNY 32.50,规格面板现价 CNY 35.00。没有下单,也不会自动放弃;请联系管理员处理。', web:'ok', device:'ok', version:'ok', leg:'NEEDS_MANUAL', legTone:'caution', action:'导出假诊断摘要', enabled:true, safeAction:'export', reason:'导出仅生成本地假文本,不包含页面全文或敏感信息。', session:'继续轮询其他任务', step:'当前任务已移交', kind:'order', active:1, countdown:'00:11', fail:'0 / 3', submission:'未建立' },
claimed: { tone:'info', title:'已领取管理员授权的采购任务', text:'任务字段与最高总价已锁定;当前只准备打开目标商品,尚未建立提交围栏。', web:'ok', device:'ok', version:'ok', leg:'单趟 · 已领取', legTone:'info', action:'真机步骤执行中', enabled:false, reason:'当前任务已开始,停止轮询只应阻止下一次领取,不能硬取消本任务。', session:'运行中', step:'核对授权与商品', kind:'single', active:0, countdown:'暂停', fail:'0 / 3', lease:'04:48' },
selecting: { tone:'info', title:'正在精确选择颜色与尺码', text:'只在已取证维度容器内精确唯一匹配并读回;缺失、重复或版本变化立即停止。', web:'ok', device:'ok', version:'ok', leg:'单趟 · 选择规格', legTone:'info', action:'真机步骤执行中', enabled:false, reason:'当前受控步骤不能被硬取消。', session:'运行中', step:'精确选择规格', kind:'single', active:1, countdown:'暂停', fail:'0 / 3', lease:'04:18' },
gate1: { tone:'info', title:'闸门一:读取 SKU 单价', text:'当前规格单价必须唯一可读,单价乘数量不得超过管理员授权的最高总价。', web:'ok', device:'ok', version:'ok', leg:'单趟 · 闸门一', legTone:'info', action:'安全校验进行中', enabled:false, reason:'价格不可读或超上限时立即停止。', session:'运行中', step:'闸门一:读取 SKU 单价', kind:'single', active:2, countdown:'暂停', fail:'0 / 3', lease:'03:58' },
quantity_gate2: { tone:'info', title:'数量复核与闸门二', text:'数量必须读回为 2;目标规格不能漂移,第二次单价必须等于闸门一 CNY 32.50。', web:'ok', device:'ok', version:'ok', leg:'单趟 · 闸门二', legTone:'info', action:'安全校验进行中', enabled:false, reason:'数量、规格或价格变化都停止。', session:'运行中', step:'数量读回与闸门二', kind:'single', active:3, countdown:'暂停', fail:'0 / 3', lease:'03:31' },
confirm_gate3: { tone:'caution', title:'确认页与闸门三', text:'正在核对规格、数量、应付总额与提交控件唯一;此时没有点击许可。', web:'ok', device:'ok', version:'ok', leg:'单趟 · 闸门三', legTone:'caution', action:'安全校验进行中', enabled:false, reason:'没有服务端围栏许可,绝不能点击提交订单。', session:'运行中', step:'闸门三:核对应付总额', kind:'single', active:4, countdown:'暂停', fail:'0 / 3', lease:'02:58' },
fencing: { tone:'caution', title:'正在申请服务端提交围栏', text:'等待首次明确的 click_permitted。超时、冲突、网络失败或响应不明都不会点击。', web:'ok', device:'ok', version:'ok', leg:'单趟 · 申请围栏', legTone:'caution', action:'等待围栏响应', enabled:false, reason:'申请中禁止取消、关闭或换 key 重复申请。', session:'运行中', step:'申请唯一提交围栏', kind:'single', active:5, countdown:'暂停', fail:'0 / 3', lease:'02:31' },
fence_failed: { tone:'critical', title:'未获得首次明确点击许可', text:'围栏失败或响应不明:没有点击提交订单。只核查同一幂等键,不能直接重试。', web:'bad', device:'ok', version:'ok', leg:'单趟 · 未获许可', legTone:'critical', action:'打开围栏核查说明', enabled:true, safeAction:'review', reason:'只核查围栏状态,不触发提交。', session:'已停止', step:'核查幂等键', kind:'single', active:5, countdown:'—', fail:'1 / 3', submission:'围栏状态未知 · 幂等键 DEMO-FENCE-042' },
fenced: { tone:'caution', title:'围栏已建立,只核对同一提交', text:'submission_id 已固定。内部流程至多点击一次;界面不提供提交、重领、放弃或重试。', web:'ok', device:'ok', version:'ok', leg:'单趟 · 已围栏', legTone:'caution', action:'打开同一提交核查说明', enabled:true, safeAction:'review', reason:'只能查看与调和同一提交记录。', session:'受控执行', step:'调和订单结果', kind:'single', active:7, countdown:'暂停', fail:'0 / 3', lease:'01:49', submission:'SUB-DEMO-0042 · FENCED' },
waiting_payment: { tone:'success', title:'已明确创建待付款订单', text:'自动化已停止。系统不会付款;请人在拼多多核对后自行付款,再到采购服务标记。', web:'ok', device:'ok', version:'ok', leg:'WAITING_PAYMENT', legTone:'success', action:'查看待付款说明', enabled:true, safeAction:'paymentInfo', reason:'仅显示人工收口说明,不执行支付。', session:'已停止', step:'等待人工付款', kind:'single', active:8, countdown:'—', fail:'0 / 3', count:5, submission:'SUB-DEMO-0042 · SUBMITTED' },
uncertain: { tone:'critical', title:'订单可能已创建,结果不明确', text:'保持金额预留和永久围栏,只核查 SUB-DEMO-0042;禁止重新领取、释放授权或再次点击。', web:'ok', device:'ok', version:'ok', leg:'RECONCILIATION_REQUIRED', legTone:'critical', action:'打开人工核查说明', enabled:true, safeAction:'review', reason:'核查不会发起新的下单。可另行导出假证据摘要。', session:'已停止', step:'人工核查同一提交', kind:'single', active:7, countdown:'—', fail:'0 / 3', submission:'SUB-DEMO-0042 · 结果不明确' },
security: { tone:'critical', title:'检测到安全校验,已停止', text:'不绕过验证码、风控、人脸或短信。若已围栏,只调和同一提交;围栏前转人工。', web:'ok', device:'ok', version:'ok', leg:'待人工 · 安全校验', legTone:'critical', action:'打开人工核查说明', enabled:true, safeAction:'review', reason:'只显示核查说明,不提供绕过或继续。', session:'已停止', step:'等待人工处理', kind:'single', active:7, countdown:'—', fail:'1 / 3', submission:'SUB-DEMO-0042 · RECONCILIATION_REQUIRED' },
payment_handoff: { tone:'critical', title:'进入外部支付交接,已停止', text:'订单可能已创建、支付未完成。不会读取或输入支付凭据,也没有“继续付款”按钮。', web:'ok', device:'ok', version:'ok', leg:'待人工 · 外部支付', legTone:'critical', action:'打开人工核查说明', enabled:true, safeAction:'paymentInfo', reason:'只显示人工核查与付款边界。', session:'已停止', step:'人工核查同一提交', kind:'single', active:7, countdown:'—', fail:'0 / 3', submission:'SUB-DEMO-0042 · HANDED_OFF' },
manual: { tone:'caution', title:'任务已转人工:闸门二价格变化', text:'闸门一 CNY 32.50,数量设置后重读 CNY 35.00。围栏未建立,没有创建订单;需管理员核查后重置。', web:'ok', device:'ok', version:'ok', leg:'NEEDS_MANUAL', legTone:'caution', action:'导出假诊断摘要', enabled:true, safeAction:'export', reason:'导出只生成本地假文本,不含完整 XML、页面全文或敏感字段。', session:'继续轮询其他任务', step:'当前任务已移交', kind:'single', active:3, countdown:'00:11', fail:'0 / 3', submission:'未建立' },
failed_stop: { tone:'critical', title:'连续失败达到阈值,轮询已停止', text:'最近三次均为服务连接失败。检查设置和网络;修复后重新开始普通轮询,不会重试任何提交点击。', web:'bad', device:'ok', version:'ok', leg:'自动停止', legTone:'critical', action:'前往配置', enabled:true, safeAction:'settings', reason:'先修复连接;不会自动恢复轮询。', session:'已停止', step:'等待修复', kind:'idle', active:-1, countdown:'—', fail:'3 / 3', count:4 }
};
const sessionControls = {
not_ready:{label:'开始轮询',enabled:false,reason:'web 服务未就绪,不能领取任务。'},
version_mismatch:{label:'开始轮询',enabled:false,reason:'App 版本失配,必须先完成本项目真机取证。'},
idle:{label:'开始轮询',enabled:true,reason:'只启动普通轮询,不会直接执行下单。'},
idle:{label:'开始轮询',enabled:true,reason:'只启动领取会话;只有已获管理员开始采购授权的任务可执行。'},
polling:{label:'停止轮询',enabled:true,reason:'停止后不再领取新任务。'},
trial:{label:'停止轮询',enabled:false,reason:'真机步骤执行中,禁止硬停止。'},
trial_done:{label:'停止轮询',enabled:true,reason:'手机已退出商品页,可以安全停止轮询。'},
dry_run:{label:'停止轮询',enabled:false,reason:'只读演练执行中,禁止硬停止。'},
dry_run_ready:{label:'停止轮询',enabled:true,reason:'演练已退出确认页,可以安全停止轮询。'},
order_prefence:{label:'停止轮询',enabled:false,reason:'真实第二趟校验中,禁止硬停止。'},
claimed:{label:'停止轮询',enabled:false,reason:'当前任务已领取;停止只应阻止下次领取,不能硬取消本任务。'},
selecting:{label:'停止轮询',enabled:false,reason:'受控真机步骤执行中,禁止硬停止。'},
gate1:{label:'停止轮询',enabled:false,reason:'价格闸门执行中,禁止硬停止。'},
quantity_gate2:{label:'停止轮询',enabled:false,reason:'数量与闸门二执行中,禁止硬停止。'},
confirm_gate3:{label:'停止轮询',enabled:false,reason:'确认页只允许安全校验,禁止硬停止或额外点击。'},
fencing:{label:'停止轮询',enabled:false,reason:'围栏申请中,禁止关闭、取消或重复申请。'},
fence_failed:{label:'开始轮询',enabled:false,reason:'先核查围栏状态;不能用重新轮询绕过不明确结果。'},
fenced:{label:'停止轮询',enabled:false,reason:'已建立围栏,只能调和同一提交。'},
@@ -836,10 +834,10 @@
$('task-id').textContent = hasTask ? task.id : '—'; $('lease').textContent = s.lease || '—';
$('product').textContent = hasTask ? task.product : '暂无商品;轮询会在安全就绪后领取一条任务';
$('color').textContent = hasTask ? task.color : '—'; $('size-qty').textContent = hasTask ? task.sizeQty : '—';
$('auth-price').textContent = hasTask && s.kind !== 'trial' ? task.authPrice : '—'; $('price-cap').textContent = hasTask ? task.cap : '—';
$('gate1-price').textContent = hasTask && ['gate1','quantity_gate2','confirm_gate3','fencing','fence_failed','fenced','waiting_payment','uncertain','security','payment_handoff','manual'].includes($('scenario').value) ? task.gate1Price : '—'; $('price-cap').textContent = hasTask ? task.cap : '—';
$('submission').textContent = s.submission || '未建立';
$('preview-empty').hidden = hasTask; $('product-preview-image').hidden = !hasTask;
$('preview-source').textContent = hasTask ? '来源:商品页截图裁剪(内联假证据)' : '来源:尚无可信图片';
$('preview-source').textContent = hasTask ? '来源:内部原始商品截图(内联假证据)' : '来源:尚无可信图片';
$('preview-time').textContent = hasTask ? '采集时间:2026-08-03 13:51(假数据)' : '采集时间:—';
renderSteps(s.kind, s.active);
$('countdown').textContent = s.countdown; $('failure-count').textContent = s.fail; $('completed-count').textContent = String(s.count || 0);
@@ -888,7 +886,7 @@
window.addEventListener('resize', hideRecordMenu);
$('export-log').addEventListener('click', exportDemo);
$('close-demo').addEventListener('click', () => {
const unsafe = ['trial','dry_run','order_prefence','fencing','fenced'].includes($('scenario').value);
const unsafe = ['claimed','selecting','gate1','quantity_gate2','confirm_gate3','fencing','fenced'].includes($('scenario').value);
showDialog(unsafe ? '当前不能直接关闭' : '关闭窗口协议', unsafe ? '真机或围栏流程处于受控阶段。原生实现需先完成安全停靠或保持同一 submission 调和,不能让关闭看起来等于“可以重来”。' : '原生实现关闭窗口后立即停止普通轮询,不留后台进程。此 HTML 只演示规则,不会关闭浏览器。');
});
$('dialog-close').addEventListener('click', () => $('info-dialog').close());