106 lines
27 KiB
HTML
106 lines
27 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>PDD 采集管理台 · 最小闭环原型</title>
|
|
<style>
|
|
:root{--ink:#0f172a;--muted:#64748b;--line:#e2e8f0;--bg:#f1f5f9;--panel:#fff;--green:#15803d;--green-soft:#dcfce7;--red:#b91c1c;--red-soft:#fee2e2;--amber:#92400e;--amber-soft:#fef3c7;--nav:#020617}
|
|
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.5 "Segoe UI","Microsoft YaHei",sans-serif}button,input,select,textarea{font:inherit}button{cursor:pointer;min-height:42px}.app{display:grid;grid-template-columns:232px 1fr;min-height:100vh}.side{position:sticky;top:0;height:100vh;padding:22px 14px;background:var(--nav);color:#cbd5e1}.brand{display:flex;align-items:center;gap:10px;padding:0 10px 24px;color:#fff;font-size:17px;font-weight:750}.mark{display:grid;place-items:center;width:32px;height:32px;border-radius:9px;background:linear-gradient(135deg,#4ade80,#15803d);color:#052e16;font-weight:900}.nav-label{padding:12px 10px 6px;color:#64748b;font-size:11px;font-weight:750;letter-spacing:.1em}.nav button{display:flex;align-items:center;gap:10px;width:100%;margin:3px 0;padding:11px 12px;border:0;border-radius:8px;background:transparent;color:#94a3b8;text-align:left}.nav button:hover,.nav button:focus-visible{outline:2px solid #22c55e;background:#0f172a;color:#fff}.nav button.active{background:#14532d;color:#dcfce7}.nav-dot{width:8px;height:8px;border:2px solid currentColor;border-radius:2px}.side-note{position:absolute;right:14px;bottom:18px;left:14px;padding:13px;border-top:1px solid #1e293b;color:#64748b;font-size:12px}.side-note b{display:block;color:#86efac}.main{min-width:0}.top{position:sticky;top:0;z-index:5;display:flex;align-items:center;justify-content:space-between;height:66px;padding:0 28px;border-bottom:1px solid var(--line);background:#fff}.crumb{font-weight:750}.operator{display:flex;align-items:center;gap:10px}.avatar{display:grid;place-items:center;width:34px;height:34px;border-radius:50%;background:#e2e8f0;font-weight:750}.content{padding:26px 28px}.page{display:none}.page.active{display:block}.title-row{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;margin-bottom:22px}h1{margin:0 0 5px;font-size:24px}h2{margin:0;font-size:16px}.sub{margin:0;color:var(--muted)}.actions{display:flex;gap:10px;flex-wrap:wrap}.btn{padding:0 15px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;color:#334155;font-weight:700}.btn:hover,.btn:focus-visible{outline:2px solid #86efac;border-color:#16a34a}.btn.primary{border-color:var(--green);background:var(--green);color:#fff}.btn.danger{border-color:#fecaca;color:var(--red)}.btn:disabled{cursor:not-allowed;opacity:.45}.metrics{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:18px}.metric,.panel{border:1px solid var(--line);border-radius:12px;background:var(--panel)}.metric{padding:18px}.metric small{color:var(--muted);font-weight:650}.metric strong{display:block;margin:7px 0 3px;font-size:29px;line-height:1.2}.good-text{color:var(--green);font-size:12px}.layout{display:grid;grid-template-columns:1.6fr 1fr;gap:16px}.panel-head{display:flex;align-items:center;justify-content:space-between;padding:16px 18px;border-bottom:1px solid var(--line)}.panel-body{padding:18px}.flow{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}.step{padding:14px;border:1px solid var(--line);border-radius:10px}.step b{display:block;font-size:18px}.step span{color:var(--muted);font-size:12px}.badge{display:inline-flex;align-items:center;border-radius:99px;padding:4px 9px;background:#f1f5f9;color:#475569;font-size:12px;font-weight:750}.badge.good{background:var(--green-soft);color:#166534}.badge.warn{background:var(--amber-soft);color:var(--amber)}.badge.bad{background:var(--red-soft);color:#991b1b}.filters{display:flex;gap:10px;padding:14px 16px;border:1px solid var(--line);border-bottom:0;border-radius:12px 12px 0 0;background:#fff}.field{min-width:160px;height:44px;padding:0 12px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;color:var(--ink)}textarea.field{height:190px;padding:12px;resize:vertical;font:13px/1.6 Consolas,monospace}.field:focus{outline:2px solid #86efac;border-color:#16a34a}.table-wrap{overflow:auto;border:1px solid var(--line);border-radius:0 0 12px 12px;background:#fff}table{width:100%;min-width:800px;border-collapse:collapse}th,td{padding:13px 15px;border-bottom:1px solid var(--line);text-align:left;white-space:nowrap}th{background:#f8fafc;color:#64748b;font-size:12px}td a{color:#166534;font-weight:750;text-decoration:none}.mini-btn{min-height:34px;padding:5px 8px;border:0;background:transparent;color:#166534;font-weight:750}.mini-btn:hover,.mini-btn:focus-visible{outline:2px solid #86efac;border-radius:6px}.code{font-family:Consolas,monospace}.rule-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:14px}.rule-card{padding:17px;border:1px solid var(--line);border-radius:12px;background:#fff}.rule-card header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.rule-card p{color:var(--muted)}.scope-note{margin-top:18px;padding:14px 16px;border-left:3px solid #22c55e;background:#f0fdf4;color:#166534}.modal{position:fixed;inset:0;z-index:20;display:none;align-items:center;justify-content:center;padding:20px;background:#020617bb}.modal.open{display:flex}.dialog{width:min(680px,100%);max-height:92vh;overflow:auto;border-radius:15px;background:#fff;box-shadow:0 24px 70px #0008}.dialog.wide{width:min(960px,100%)}.dialog-head,.dialog-foot{display:flex;align-items:center;justify-content:space-between;padding:17px 20px;border-bottom:1px solid var(--line)}.dialog-foot{justify-content:flex-end;gap:10px;border-top:1px solid var(--line);border-bottom:0}.dialog-body{padding:20px}.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:15px}.label{display:grid;gap:6px;font-weight:700}.label.full{grid-column:1/-1}.help{color:var(--muted);font-size:12px;font-weight:400}.detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}.snapshot{padding:14px;border:1px solid var(--line);border-radius:10px;background:#f8fafc}.kv{display:grid;grid-template-columns:130px 1fr;gap:12px;padding:9px 0;border-bottom:1px solid var(--line)}.kv:last-child{border:0}.kv span:first-child{color:var(--muted)}.result-summary{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin:14px 0}.result-summary div{padding:11px;border:1px solid var(--line);border-radius:9px}.result-summary b{display:block}.toast{position:fixed;right:24px;bottom:24px;z-index:30;padding:13px 16px;border-radius:9px;background:#0f172a;color:#fff;opacity:0;transform:translateY(10px);transition:.2s}.toast.show{opacity:1;transform:none}
|
|
@media(max-width:980px){.app{grid-template-columns:74px 1fr}.brand span,.nav button span,.nav-label,.side-note{display:none}.nav button{justify-content:center}.metrics{grid-template-columns:repeat(2,1fr)}.layout{grid-template-columns:1fr}.rule-grid{grid-template-columns:1fr}}
|
|
@media(max-width:680px){body{font-size:16px}.app{display:block}.side{position:fixed;top:auto;right:0;bottom:0;left:0;z-index:10;width:100%;height:68px;padding:6px 8px}.brand,.nav-label,.side-note{display:none}.nav{display:flex;overflow:auto}.nav button{min-width:88px;justify-content:center;flex-direction:column;gap:3px;padding:4px 7px;font-size:12px}.nav button span{display:inline}.top{padding:0 16px}.content{padding:18px 14px 86px}.title-row{display:block}.actions{margin-top:14px}.metrics{grid-template-columns:1fr 1fr}.flow,.result-summary{grid-template-columns:1fr 1fr}.form-grid,.detail-grid{grid-template-columns:1fr}.label.full{grid-column:auto}.filters{overflow:auto}}
|
|
@media(prefers-reduced-motion:reduce){*{transition:none!important}}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="app">
|
|
<aside class="side">
|
|
<div class="brand"><div class="mark">M</div><span>Mobile Ops</span></div>
|
|
<div class="nav-label">最小采集闭环</div>
|
|
<nav class="nav" aria-label="主导航">
|
|
<button class="active" data-page="overview"><i class="nav-dot"></i><span>工作台</span></button>
|
|
<button data-page="products"><i class="nav-dot"></i><span>PDD 商品</span></button>
|
|
<button data-page="rules"><i class="nav-dot"></i><span>采集规则</span></button>
|
|
<button data-page="tasks"><i class="nav-dot"></i><span>采集任务</span></button>
|
|
<button data-page="devices"><i class="nav-dot"></i><span>设备列表</span></button>
|
|
</nav>
|
|
<div class="side-note"><b>MVP 范围已锁定</b>结果只在任务详情查看</div>
|
|
</aside>
|
|
<main class="main">
|
|
<header class="top"><div class="crumb" id="crumb">工作台</div><div class="operator"><span>管理员 · 林默</span><div class="avatar">林</div></div></header>
|
|
<div class="content">
|
|
<section class="page active" id="overview">
|
|
<div class="title-row"><div><h1>PDD 采集闭环</h1><p class="sub">添加商品 → 创建规则 → 创建任务 → Android 执行 → 任务详情</p></div><button class="btn primary" data-open="taskModal">创建任务</button></div>
|
|
<div class="metrics"><div class="metric"><small>PDD 商品</small><strong>12</strong><span class="good-text">goods_id 全部唯一</span></div><div class="metric"><small>可用规则</small><strong>3</strong><span class="good-text">创建即生效</span></div><div class="metric"><small>待执行 / 执行中</small><strong>5 / 2</strong><span class="good-text">无重复活动商品</span></div><div class="metric"><small>今日完成</small><strong>18</strong><span class="good-text">其中部分完成 2</span></div></div>
|
|
<div class="layout"><div class="panel"><div class="panel-head"><h2>当前闭环</h2></div><div class="panel-body"><div class="flow"><div class="step"><b>01</b><span>人工添加 PDD URL</span></div><div class="step"><b>02</b><span>创建可用规则</span></div><div class="step"><b>03</b><span>指定或空闲领取</span></div><div class="step"><b>04</b><span>任务详情看结果</span></div></div><div class="scope-note">当前不接入顺云宝、Shopee、采购、批量任务、规则发布流程或实时屏幕。</div></div></div><div class="panel"><div class="panel-head"><h2>设备状态</h2><button class="mini-btn" data-go="devices">管理设备</button></div><div class="panel-body"><div class="kv"><span>自动注册设备</span><b>6 台</b></div><div class="kv"><span>在线空闲</span><b>3 台</b></div><div class="kv"><span>执行中</span><b>2 台</b></div><div class="kv"><span>已停用</span><b>1 台</b></div></div></div></div>
|
|
</section>
|
|
|
|
<section class="page" id="products">
|
|
<div class="title-row"><div><h1>PDD 商品</h1><p class="sub">人工添加链接;goods_id 重复时不创建第二条商品</p></div><button class="btn primary" data-open="productModal">添加 PDD 链接</button></div>
|
|
<div class="filters"><input class="field" aria-label="搜索商品" placeholder="搜索 goods_id / URL"><select class="field" aria-label="商品状态"><option>全部商品</option><option>有活动任务</option><option>可创建任务</option></select></div>
|
|
<div class="table-wrap"><table><thead><tr><th>商品</th><th>goods_id</th><th>当前 URL</th><th>活动任务</th><th>操作</th></tr></thead><tbody><tr><td><b>PDD-00012</b></td><td class="code">729481506342</td><td class="code">mobile.yangkeduo.com/goods.html?goods_id=729481506342</td><td><span class="badge good">无</span></td><td><button class="mini-btn edit-product">编辑 URL</button><button class="mini-btn create-from-product">创建任务</button></td></tr><tr><td><b>PDD-00011</b></td><td class="code">684215908771</td><td class="code">mobile.yangkeduo.com/goods2.html?goods_id=684215908771</td><td><span class="badge warn">T-073 执行中</span></td><td><button class="mini-btn edit-product">编辑 URL</button><button class="mini-btn" disabled>已有任务</button></td></tr></tbody></table></div>
|
|
</section>
|
|
|
|
<section class="page" id="rules">
|
|
<div class="title-row"><div><h1>采集规则</h1><p class="sub">创建后立即可用;编辑或删除不改变已有任务快照</p></div><button class="btn primary" data-open="ruleModal">创建规则</button></div>
|
|
<div class="rule-grid"><article class="rule-card"><header><div><span class="badge good">可用</span><h2 style="margin-top:9px">PDD 商品详情</h2></div><div><button class="mini-btn edit-rule">编辑</button><button class="mini-btn delete-rule">删除</button></div></header><p>打开规格弹层,采集标题、店铺、销量、评价、颜色、尺码和颜色价格。</p><small class="code">RULE-001 · 更新于 14:12</small></article><article class="rule-card"><header><div><span class="badge good">可用</span><h2 style="margin-top:9px">PDD 简单商品</h2></div><div><button class="mini-btn edit-rule">编辑</button><button class="mini-btn delete-rule">删除</button></div></header><p>用于无尺码维度的单规格商品,仍输出通用规格结构。</p><small class="code">RULE-002 · 更新于 10:40</small></article></div>
|
|
</section>
|
|
|
|
<section class="page" id="tasks">
|
|
<div class="title-row"><div><h1>采集任务</h1><p class="sub">任务和结果共用一条记录;结果只在任务详情查看</p></div><button class="btn primary" data-open="taskModal">创建任务</button></div>
|
|
<div class="filters"><input class="field" aria-label="搜索任务" placeholder="任务 ID / goods_id"><select class="field" aria-label="任务状态"><option>全部状态</option><option>待执行</option><option>执行中</option><option>已完成</option><option>部分完成</option><option>失败</option></select></div>
|
|
<div class="table-wrap"><table><thead><tr><th>任务</th><th>goods_id</th><th>设备</th><th>规则快照</th><th>状态</th><th>操作</th></tr></thead><tbody><tr><td><a href="#" class="task-detail">T-20260814-073</a></td><td class="code">684215908771</td><td>ONEPLUS-02</td><td>PDD 商品详情</td><td><span class="badge good">执行中</span></td><td><button class="mini-btn task-detail">详情</button></td></tr><tr><td><a href="#" class="task-detail">T-20260814-072</a></td><td class="code">729481506342</td><td>HUAWEI-01</td><td>PDD 商品详情</td><td><span class="badge warn">部分完成</span></td><td><button class="mini-btn task-detail">详情 / 重置</button></td></tr><tr><td><a href="#" class="task-detail">T-20260814-071</a></td><td class="code">665029114608</td><td>HUAWEI-08</td><td>PDD 商品详情</td><td><span class="badge bad">验证码失败</span></td><td><button class="mini-btn task-detail">详情 / 删除</button></td></tr></tbody></table></div>
|
|
</section>
|
|
|
|
<section class="page" id="devices">
|
|
<div class="title-row"><div><h1>设备列表</h1><p class="sub">Agent 首次上报即自动注册;无需注册码、人工审核或后台创建</p></div></div>
|
|
<div class="filters"><input class="field" aria-label="搜索设备" placeholder="设备名称 / installId / 型号"><select class="field" aria-label="设备状态"><option>全部状态</option><option>在线空闲</option><option>执行中</option><option>离线</option><option>已停用</option></select></div>
|
|
<div class="table-wrap"><table><thead><tr><th>设备</th><th>安装身份</th><th>型号</th><th>状态</th><th>当前任务</th><th>最后心跳</th><th>操作</th></tr></thead><tbody><tr><td><b>HUAWEI-01</b><br><small class="sub">DEV-0001</small></td><td class="code">c57a…91be</td><td>Mate 60 · Android 14</td><td><span class="badge good">在线空闲</span></td><td>—</td><td>8 秒前</td><td><button class="mini-btn device-detail">详情</button><button class="mini-btn device-disable">停用</button></td></tr><tr><td><b>ONEPLUS-02</b><br><small class="sub">DEV-0002</small></td><td class="code">8af4…20d1</td><td>OnePlus 12 · Android 15</td><td><span class="badge warn">执行中</span></td><td>T-073</td><td>3 秒前</td><td><button class="mini-btn device-detail">详情</button><button class="mini-btn" disabled>执行中</button></td></tr><tr><td><b>HUAWEI-08</b><br><small class="sub">DEV-0008</small></td><td class="code">3de9…8a42</td><td>Pura 70 · Android 14</td><td><span class="badge good">在线空闲</span></td><td>—</td><td>5 秒前</td><td><button class="mini-btn device-detail">详情</button><button class="mini-btn device-disable">停用</button></td></tr><tr><td><b>HUAWEI-03</b><br><small class="sub">DEV-0003</small></td><td class="code">77b2…114c</td><td>Mate 50 · Android 13</td><td><span class="badge bad">已停用</span></td><td>—</td><td>2 天前</td><td><button class="mini-btn device-detail">详情</button><button class="mini-btn device-enable">重新启用</button></td></tr></tbody></table></div>
|
|
<div class="scope-note">自动注册只建立设备身份,不代表设备具备采集条件。任务下发仍需在线、未停用、权限正常且设备空闲。</div>
|
|
</section>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
<div class="modal" id="productModal" role="dialog" aria-modal="true" aria-labelledby="productTitle"><div class="dialog"><div class="dialog-head"><div><h2 id="productTitle">添加 PDD 商品</h2><small>服务端将规范化链接并提取 goods_id</small></div><button class="btn close">关闭</button></div><div class="dialog-body"><label class="label">PDD URL<input id="productUrl" class="field" value="https://mobile.yangkeduo.com/goods.html?goods_id=739552018426"><span class="help">提取失败会拒绝保存;goods_id 已存在时提示已有商品。</span></label></div><div class="dialog-foot"><button class="btn close">取消</button><button class="btn primary" id="saveProduct">解析并添加</button></div></div></div>
|
|
|
|
<div class="modal" id="ruleModal" role="dialog" aria-modal="true" aria-labelledby="ruleTitle"><div class="dialog"><div class="dialog-head"><div><h2 id="ruleTitle">创建采集规则</h2><small>保存后立即可以创建任务</small></div><button class="btn close">关闭</button></div><div class="dialog-body"><div class="form-grid"><label class="label full">规则名称<input class="field" value="PDD 商品详情规则"></label><label class="label full">规则内容<textarea class="field">{"page":"pdd_product_detail","steps":[{"wait":"发起拼单"},{"extract":"title"},{"click":"sku_entry"},{"extract":"dimensions"}]}</textarea><span class="help">任务创建时会复制完整内容;以后编辑不改变旧任务。</span></label></div></div><div class="dialog-foot"><button class="btn close">取消</button><button class="btn primary" id="saveRule">保存并启用</button></div></div></div>
|
|
|
|
<div class="modal" id="taskModal" role="dialog" aria-modal="true" aria-labelledby="taskTitle"><div class="dialog"><div class="dialog-head"><div><h2 id="taskTitle">创建采集任务</h2><small>一个 PDD 商品只能有一个未完成任务</small></div><button class="btn close">关闭</button></div><div class="dialog-body"><div class="form-grid"><label class="label full">PDD 商品<select class="field"><option>PDD-00012 · goods_id 729481506342</option></select></label><label class="label">采集规则<select class="field"><option>PDD 商品详情</option><option>PDD 简单商品</option></select><span class="help">当前内容将固化到任务。</span></label><label class="label">指定设备<select class="field"><option>HUAWEI-01 · 在线空闲</option><option>HUAWEI-08 · 在线空闲</option><option>不指定 · 由空闲设备领取</option></select></label><div class="label full snapshot">创建后 URL、goods_id、规则和设备配置保持不变。任务失败不会自动重试。</div></div></div><div class="dialog-foot"><button class="btn close">取消</button><button class="btn primary" id="confirmTask">创建任务</button></div></div></div>
|
|
|
|
<div class="modal" id="detailModal" role="dialog" aria-modal="true" aria-labelledby="detailTitle"><div class="dialog wide"><div class="dialog-head"><div><h2 id="detailTitle">任务详情 · T-20260814-072</h2><small>部分完成 · 结果与任务保存在同一条记录</small></div><button class="btn close">关闭</button></div><div class="dialog-body"><div class="detail-grid"><section class="snapshot"><h2>不可变输入快照</h2><div class="kv"><span>goods_id</span><b class="code">729481506342</b></div><div class="kv"><span>URL</span><b class="code">goods.html?goods_id=729481506342</b></div><div class="kv"><span>规则</span><b>PDD 商品详情</b></div><div class="kv"><span>设备</span><b>HUAWEI-01</b></div></section><section class="snapshot"><h2>采集结果</h2><div class="kv"><span>标题</span><b>女士轻便运动鞋</b></div><div class="kv"><span>店铺</span><b>步履鞋坊</b></div><div class="kv"><span>销量 / 评价</span><b>2.4 万+ / 3,218</b></div><div class="kv"><span>缺失</span><b>浅粉 38、39</b></div></section></div><div class="result-summary"><div><b>3</b><span class="sub">颜色</span></div><div><b>5</b><span class="sub">尺码</span></div><div><b>12 / 15</b><span class="sub">SKU</span></div><div><b>¥29.90</b><span class="sub">最低颜色价</span></div></div><table style="min-width:0"><thead><tr><th>颜色</th><th>价格</th><th>已采尺码</th></tr></thead><tbody><tr><td>米白</td><td>¥29.90</td><td>35 / 36 / 37 / 38 / 39</td></tr><tr><td>黑色</td><td>¥32.90</td><td>35 / 36 / 37 / 38</td></tr><tr><td>浅粉</td><td>¥31.90</td><td>35 / 36 / 37</td></tr></tbody></table><div class="scope-note">重置会清除以上结果和执行错误,但继续使用左侧的原输入快照重新采集。</div></div><div class="dialog-foot"><button class="btn danger" id="deleteTask">删除失败任务</button><button class="btn" id="resetTask">重置并重新采集</button><button class="btn primary close">关闭</button></div></div></div>
|
|
|
|
<div class="modal" id="deviceModal" role="dialog" aria-modal="true" aria-labelledby="deviceTitle"><div class="dialog"><div class="dialog-head"><div><h2 id="deviceTitle">设备详情 · HUAWEI-01</h2><small>首次上报后由服务端自动建立身份</small></div><button class="btn close">关闭</button></div><div class="dialog-body"><div class="kv"><span>设备 ID</span><b>DEV-0001</b></div><div class="kv"><span>installId</span><b class="code">c57a53df…91be</b></div><div class="kv"><span>认证状态</span><b><span class="badge good">Token 有效</span></b></div><div class="kv"><span>首次注册</span><b>2026-08-14 09:18:32</b></div><div class="kv"><span>最近心跳</span><b>8 秒前</b></div><div class="scope-note">Agent 生成 installId → 提交设备信息 → 服务端立即创建或更新设备 → 返回 Device Token → Agent 持续心跳。全程没有注册码和人工审核。</div></div><div class="dialog-foot"><button class="btn danger" id="revokeToken">撤销设备令牌</button><button class="btn primary close">关闭</button></div></div></div>
|
|
|
|
<div class="toast" id="toast" role="status" aria-live="polite"></div>
|
|
<script>
|
|
const pageNames={overview:'工作台',products:'PDD 商品',rules:'采集规则',tasks:'采集任务',devices:'设备列表'};
|
|
const nav=[...document.querySelectorAll('.nav button')];
|
|
function showPage(id){document.querySelectorAll('.page').forEach(x=>x.classList.toggle('active',x.id===id));nav.forEach(x=>x.classList.toggle('active',x.dataset.page===id));document.querySelector('#crumb').textContent=pageNames[id];scrollTo(0,0)}
|
|
nav.forEach(b=>b.addEventListener('click',()=>showPage(b.dataset.page)));
|
|
document.querySelectorAll('[data-go]').forEach(b=>b.addEventListener('click',()=>showPage(b.dataset.go)));
|
|
function openModal(id){document.querySelector('#'+id).classList.add('open')}
|
|
document.querySelectorAll('[data-open]').forEach(b=>b.addEventListener('click',()=>openModal(b.dataset.open)));
|
|
document.querySelectorAll('.close').forEach(b=>b.addEventListener('click',()=>b.closest('.modal').classList.remove('open')));
|
|
document.querySelectorAll('.modal').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('open')}));
|
|
function toast(message){const t=document.querySelector('#toast');t.textContent=message;t.classList.add('show');setTimeout(()=>t.classList.remove('show'),2400)}
|
|
document.querySelectorAll('.create-from-product').forEach(b=>b.addEventListener('click',()=>openModal('taskModal')));
|
|
document.querySelectorAll('.device-detail').forEach(b=>b.addEventListener('click',()=>openModal('deviceModal')));
|
|
document.querySelectorAll('.device-disable').forEach(b=>b.addEventListener('click',()=>{if(confirm('停用后设备不能领取新任务。确认停用?'))toast('设备已停用(原型)')}));
|
|
document.querySelectorAll('.device-enable').forEach(b=>b.addEventListener('click',()=>toast('设备已重新启用(原型)')));
|
|
document.querySelectorAll('.edit-product').forEach(b=>b.addEventListener('click',()=>{openModal('productModal');document.querySelector('#productTitle').textContent='编辑当前 PDD URL'}));
|
|
document.querySelectorAll('.edit-rule').forEach(b=>b.addEventListener('click',()=>{openModal('ruleModal');document.querySelector('#ruleTitle').textContent='编辑采集规则'}));
|
|
document.querySelectorAll('.delete-rule').forEach(b=>b.addEventListener('click',()=>{if(confirm('删除后不能创建新任务;已有任务仍按规则快照执行。确认删除?'))toast('规则已软删除(原型)')}));
|
|
document.querySelectorAll('.task-detail').forEach(b=>b.addEventListener('click',e=>{e.preventDefault();const text=e.currentTarget.closest('tr').textContent;const running=text.includes('T-20260814-073');const failed=text.includes('T-20260814-071');document.querySelector('#deleteTask').disabled=!failed;document.querySelector('#resetTask').disabled=running;document.querySelector('#detailTitle').textContent='任务详情 · '+(failed?'T-20260814-071':running?'T-20260814-073':'T-20260814-072');document.querySelector('#detailTitle').nextElementSibling.textContent=failed?'失败 · 可删除或重置':running?'执行中 · 禁止删除和重置':'部分完成 · 可重置重新采集';openModal('detailModal')}));
|
|
document.querySelector('#saveProduct').addEventListener('click',()=>{const value=document.querySelector('#productUrl').value;if(value.includes('729481506342')){toast('goods_id 已存在:PDD-00012');return}document.querySelector('#productModal').classList.remove('open');toast('PDD 商品已添加(原型)')});
|
|
document.querySelector('#saveRule').addEventListener('click',()=>{document.querySelector('#ruleModal').classList.remove('open');toast('规则已创建并立即可用(原型)')});
|
|
document.querySelector('#confirmTask').addEventListener('click',()=>{document.querySelector('#taskModal').classList.remove('open');toast('任务已创建,输入快照已固化(原型)');showPage('tasks')});
|
|
document.querySelector('#resetTask').addEventListener('click',()=>{if(confirm('将清除原采集结果,并使用原 URL、goods_id、规则和设备重新采集。确认重置?')){document.querySelector('#detailModal').classList.remove('open');toast('旧结果已清除,任务恢复待执行(原型)')}});
|
|
document.querySelector('#deleteTask').addEventListener('click',()=>{if(confirm('仅失败任务允许删除。确认删除?'))toast('失败任务已删除(原型)')});
|
|
document.querySelector('#revokeToken').addEventListener('click',()=>{if(confirm('撤销后该 Agent 必须重新注册才能连接。确认撤销?'))toast('设备令牌已撤销(原型)')});
|
|
document.addEventListener('keydown',e=>{if(e.key==='Escape')document.querySelectorAll('.modal.open').forEach(m=>m.classList.remove('open'))});
|
|
const initialPage=new URLSearchParams(location.search).get('page');if(pageNames[initialPage])showPage(initialPage);
|
|
</script>
|
|
</body>
|
|
</html>
|