Files
loom/docs/原型agent_task_system_merged.html
2026-04-24 17:46:03 +08:00

177 lines
354 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Agent任务系统 v2.1 - 全模块原型</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
:root{--pri:#6366f1;--side:#1e293b;--bdr:#e2e8f0;--txt:#1e293b;--sub:#64748b;--bg:#f1f5f9}
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;overflow:hidden;height:100vh}
.shell{display:flex;height:100vh}
.side{width:220px;background:var(--side);color:#94a3b8;overflow-y:auto;flex-shrink:0;user-select:none;transition:width .3s,opacity .3s;overflow:hidden}
.side.hide{width:0;opacity:0;pointer-events:none}
.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155;display:flex;align-items:center;gap:6px;white-space:nowrap}
.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600;text-transform:uppercase;white-space:nowrap}
.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent;transition:all .1s;white-space:nowrap}
.ni:hover{background:#334155;color:#e2e8f0}
.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}
.frame-wrap{flex:1;position:relative;background:#f1f5f9}
.frame-wrap iframe{width:100%;height:100%;border:none}
.badge{display:inline-block;background:#334155;color:#64748b;font-size:9px;padding:1px 5px;border-radius:3px;margin-left:auto}
</style>
</head>
<body>
<div class="shell">
<aside class="side hide" id="sidebar">
<div class="logo">🤖 Agent任务系统 v2.1</div>
<div class="ng-t">首页</div>
<div class="ni ac" data-src="02_仪表盘.html">🏠 仪表盘 <span class="badge">02</span></div>
<div class="ng-t">权限管理</div>
<div class="ni" data-src="03_组织架构.html">🏢 组织架构 <span class="badge">03</span></div>
<div class="ni" data-src="04_角色管理.html">🎭 角色管理 <span class="badge">04</span></div>
<div class="ni" data-src="05_用户管理.html">👤 用户管理 <span class="badge">05</span></div>
<div class="ni" data-src="12_菜单管理.html">📋 菜单管理 <span class="badge">12</span></div>
<div class="ng-t">产品管理</div>
<div class="ni" data-src="06_产品管理.html">📦 产品管理 <span class="badge">06</span></div>
<div class="ni" data-src="07_渠道码管理.html">🏷️ 渠道码 <span class="badge">07</span></div>
<div class="ni" data-src="13_平台套件.html">🔧 平台套件 <span class="badge">13</span></div>
<div class="ng-t">平台产品账号</div>
<div class="ni" data-src="08_平台产品账号.html">🔗 账号管理 <span class="badge">08</span></div>
<div class="ng-t">Skill中心</div>
<div class="ni" data-src="09_Skill管理.html">🧩 Skill管理 <span class="badge">09</span></div>
<div class="ni" data-src="14_Skill调用日志.html">📊 调用日志 <span class="badge">14</span></div>
<div class="ng-t">任务中心</div>
<div class="ni" data-src="10_任务创建.html">⚡ 任务创建 <span class="badge">10</span></div>
<div class="ni" data-src="11_任务列表.html">📋 任务列表 <span class="badge">11</span></div>
<div class="ng-t">日志</div>
<div class="ni" data-src="15_操作日志.html">📝 操作日志 <span class="badge">15</span></div>
<div class="ni" data-src="16_统计报表.html">📈 统计报表 <span class="badge">16</span></div>
<div class="ng-t">系统设置</div>
<div class="ni" data-src="17_执行器配置.html">⚙️ 执行器配置 <span class="badge">17</span></div>
<div class="ni" data-src="18_脚本模板管理.html">📜 脚本模板 <span class="badge">18</span></div>
<div class="ni" data-src="19_定时任务.html">⏰ 定时任务 <span class="badge">19</span></div>
</aside>
<div class="frame-wrap">
<iframe id="mainFrame"></iframe>
</div>
</div>
<script>
// 所有页面 HTML 内容内嵌
const PAGES = {
"01_登录页.html": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Agent任务系统 v2.0 - 登录<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}\n:root{--pri:#6366f1;--pri-d:#4f46e5;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--err:#ef4444}\nbody{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);min-height:100vh;display:flex;align-items:center;justify-content:center;color:var(--txt)}\n.login-wrap{display:flex;width:900px;max-width:95vw;background:var(--card);border-radius:16px;box-shadow:0 20px 60px rgba(0,0,0,.25);overflow:hidden;min-height:520px}\n.login-left{flex:1;background:linear-gradient(135deg,#4f46e5,#7c3aed);color:#fff;padding:50px 40px;display:flex;flex-direction:column;justify-content:center}\n.login-left h1{font-size:28px;margin-bottom:12px}\n.login-left p{font-size:13px;opacity:.85;line-height:1.8;margin-bottom:20px}\n.login-left .feat{display:flex;flex-direction:column;gap:10px}\n.login-left .feat-i{display:flex;align-items:center;gap:10px;font-size:13px;padding:8px 12px;background:rgba(255,255,255,.12);border-radius:8px}\n.login-left .feat-i span{font-size:18px}\n.login-right{flex:1;padding:50px 40px;display:flex;flex-direction:column;justify-content:center}\n.login-right h2{font-size:22px;font-weight:700;margin-bottom:6px}\n.login-right .sub{font-size:12px;color:var(--sub);margin-bottom:28px}\n.fg{margin-bottom:18px}\n.fl{font-size:12px;font-weight:600;margin-bottom:6px;display:block;color:var(--txt)}\n.fi{width:100%;padding:10px 14px;border:1px solid var(--bdr);border-radius:8px;font-size:13px;outline:none;transition:border .15s}\n.fi:focus{border-color:var(--pri);box-shadow:0 0 0 3px rgba(99,102,241,.12)}\n.fi.err{border-color:var(--err)}\n.err-msg{font-size:11px;color:var(--err);margin-top:4px;display:none}\n.opt{display:flex;justify-content:space-between;align-items:center;margin-bottom:22px;font-size:12px}\n.opt label{display:flex;align-items:center;gap:5px;cursor:pointer;color:var(--sub)}\n.opt a{color:var(--pri);cursor:pointer}\n.btn-login{width:100%;padding:11px;background:var(--pri);color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer;transition:background .15s}\n.btn-login:hover{background:var(--pri-d)}\n.btn-login:disabled{background:#94a3b8;cursor:not-allowed}\n.login-footer{text-align:center;margin-top:20px;font-size:11px;color:var(--sub)}\n.captcha-row{display:flex;gap:10px;align-items:flex-end}\n.captcha-row .fi{flex:1}\n.captcha-img{height:40px;border-radius:6px;border:1px solid var(--bdr);cursor:pointer;background:#f1f5f9;display:flex;align-items:center;justify-content:center;padding:0 16px;font-size:16px;letter-spacing:4px;font-weight:700;color:var(--pri);font-family:monospace;user-select:none}\n/* Toast */\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}\n.toast.show{display:block;animation:tIn .3s}\n.toast.ok{background:#dcfce7;color:#166534;border:1px solid #bbf7d0}\n.toast.er{background:#fee2e2;color:#991b1b;border:1px solid #fecaca}\n@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n/* Loading spinner */\n.spinner{display:inline-block;width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite;margin-right:6px;vertical-align:middle}\n@keyframes spin{to{transform:rotate(360deg)}}\n@media(max-width:768px){.login-left{display:none}.login-wrap{width:95vw}}\n<\/style>\n<\/head>\n<body>\n<div class=\"toast\" id=\"toast\"><\/div>\n<div class=\"login-wrap\">\n<div class=\"login-left\">\n<h1>🤖 Agent任务系统<\/h1>\n<p>企业级Agent任务自动化平台<br>基于角色权限的Skill调度与管理系统 v2.0<\/p>\n<div class=\"feat\">\n<div class=\"feat-i\"><span>🦞<\/span> 龙虾执行器 + 脚本引擎 双执行器架构<\/div>\n<div class=\"feat-i\"><span>🔐<\/span> 部门级角色 + Skill权限 + 多角色并集<\/div>\n<div class=\"feat-i\"><span>📦<\/span> 产品→渠道码→平台账号 全链路管理<\/div>\n<div class=\"feat-i\"><span>⚡<\/span> 三步任务创建 + 交集校验 + 智能调度<\/div>\n<\/div>\n<\/div>\n<div class=\"login-right\">\n<h2>登录<\/h2>\n<p class=\"sub\">欢迎回来,请输入您的账号信息<\/p>\n<form id=\"loginForm\" onsubmit=\"handleLogin(event)\">\n<div class=\"fg\">\n<label class=\"fl\">用户名 / 邮箱 <span style=\"color:var(--err)\">*<\/span><\/label>\n<input class=\"fi\" id=\"username\" type=\"text\" placeholder=\"请输入用户名或邮箱\" value=\"admin\">\n<div class=\"err-msg\" id=\"err-user\">请输入用户名<\/div>\n<\/div>\n<div class=\"fg\">\n<label class=\"fl\">密码 <span style=\"color:var(--err)\">*<\/span><\/label>\n<input class=\"fi\" id=\"password\" type=\"password\" placeholder=\"请输入密码\" value=\"admin123\">\n<div class=\"err-msg\" id=\"err-pass\">请输入密码<\/div>\n<\/div>\n<div class=\"fg\">\n<label class=\"fl\">验证码<\/label>\n<div class=\"captcha-row\">\n<input class=\"fi\" id=\"captcha\" type=\"text\" placeholder=\"请输入验证码\" maxlength=\"4\">\n<div class=\"captcha-img\" id=\"captchaImg\" onclick=\"refreshCaptcha()\" title=\"点击刷新\">A7X2<\/div>\n<\/div>\n<\/div>\n<div class=\"opt\">\n<label><input type=\"checkbox\" checked> 记住登录<\/label>\n<a onclick=\"showToast('请联系管理员重置密码','er')\">忘记密码?<\/a>\n<\/div>\n<button class=\"btn-login\" type=\"submit\" id=\"loginBtn\">登 录<\/button>\n<\/form>\n<div class=\"login-footer\">\nAgent任务系统 v2.0 · 技术栈 Next.js 14 + NestJS + PostgreSQL<br>\n© 2026 星辰科技有限公司\n<\/div>\n<\/div>\n<\/div>\n\n<script>\nfunction refreshCaptcha(){\n const chars='ABCDEFGHJKLMNPQRSTUVWXYZ23456789';\n let c='';for(let i=0;i<4;i++)c+=chars[Math.floor(Math.random()*chars.length)];\n document.getElementById('captchaImg').textContent=c;\n}\n\nfunction showToast(msg,type){\n const t=document.getElementById('toast');\n t.textContent=msg;t.className='toast show '+type;\n setTimeout(()=>t.className='toast',2500);\n}\n\nfunction handleLogin(e){\n e.preventDefault();\n const u=document.getElementById('username').value.trim();\n const p=document.getElementById('password').value.trim();\n const c=document.getElementById('captcha').value.trim();\n let ok=true;\n \n if(!u){document.getElementById('err-user').style.display='block';document.getElementById('username').classList.add('err');ok=false}\n else{document.getElementById('err-user').style.display='none';document.getElementById('username').classList.remove('err')}\n \n if(!p){document.getElementById('err-pass').style.display='block';document.getElementById('password').classList.add('err');ok=false}\n else{document.getElementById('err-pass').style.display='none';document.getElementById('password').classList.remove('err')}\n \n if(!ok)return;\n \n // Simulate login\n const btn=document.getElementById('loginBtn');\n btn.disabled=true;\n btn.innerHTML='<span class=\"spinner\"><\/span>登录中...';\n \n setTimeout(()=>{\n btn.disabled=false;\n btn.textContent='登 录';\n if(u==='admin' && p==='admin123'){\n showToast('✅ 登录成功!正在跳转...','ok');\n setTimeout(()=>{\n if(window.parent&&window.parent!==window){window.parent.postMessage('login-success','*')}else{document.body.innerHTML='<div style=\"display:flex;align-items:center;justify-content:center;height:100vh;flex-direction:column;color:#fff;gap:10px\"><div style=\"font-size:40px\">✅<\/div><div style=\"font-size:18px;font-weight:600\">登录成功<\/div><div style=\"font-size:13px;opacity:.8\">JWT Token 已签发,即将跳转至仪表盘...<\/div><\/div>';}\n },1000);\n }else{\n showToast('❌ 用户名或密码错误','er');\n refreshCaptcha();\n }\n },1500);\n}\n<\/script>\n<\/body>\n<\/html>\n",
"02_仪表盘.html": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Agent任务系统 v2.0 - 仪表盘<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}\n:root{--pri:#6366f1;--pri-l:#818cf8;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--warn:#f59e0b;--err:#ef4444;--side:#1e293b}\nbody{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6}\n.layout{display:flex;min-height:100vh}\n.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}\n.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155;display:flex;align-items:center;gap:6px}\n.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}\n.ni:hover{background:#334155;color:#e2e8f0}\n.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}\n.ng-t{padding:10px 18px 4px;font-size:10px;text-transform:uppercase;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1;display:flex;flex-direction:column}\n.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;position:sticky;top:0;z-index:50}\n.hd .bc{font-size:12px;color:var(--sub)}.hd .bc b{color:var(--txt)}\n.hd .av{width:30px;height:30px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600}\n.ct{padding:24px;flex:1}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}\n.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.card{background:var(--card);border-radius:10px;padding:16px;border:1px solid var(--bdr);margin-bottom:14px;box-shadow:0 1px 2px rgba(0,0,0,.03)}\n.ct-t{font-size:13px;font-weight:600;margin-bottom:12px;display:flex;align-items:center;gap:6px}\n.sg{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin-bottom:20px}\n.sc{background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px;display:flex;align-items:center;gap:12px;cursor:pointer;transition:box-shadow .15s}\n.sc:hover{box-shadow:0 4px 12px rgba(0,0,0,.08)}\n.si{width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:18px}\n.sn{font-size:22px;font-weight:700;line-height:1.2}\n.sl2{font-size:10px;color:var(--sub)}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}\n.tg-ok{background:#dcfce7;color:#166534}.tg-w{background:#fef3c7;color:#92400e}.tg-e{background:#fee2e2;color:#991b1b}\n.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-g{background:#f1f5f9;color:#64748b}\ntable{width:100%;border-collapse:collapse;font-size:12px}\nth,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}\nth{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}\ntr:hover td{background:#fafbfc}\n.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px;background:var(--card)}\n.bar-chart{display:flex;align-items:flex-end;gap:8px;height:160px;padding:10px 0}\n.bar-col{flex:1;display:flex;flex-direction:column;align-items:center;gap:4px}\n.bar{width:100%;border-radius:4px 4px 0 0;transition:height .3s;cursor:pointer;position:relative}\n.bar:hover{opacity:.85}\n.bar-label{font-size:10px;color:var(--sub)}\n.bar-val{font-size:10px;font-weight:600;color:var(--txt)}\n.ring{width:120px;height:120px;border-radius:50%;position:relative;display:flex;align-items:center;justify-content:center}\n.ring-center{font-size:20px;font-weight:700}\n.ring-label{font-size:10px;color:var(--sub)}\n.legend{display:flex;flex-direction:column;gap:8px;font-size:12px}\n.legend-i{display:flex;align-items:center;gap:6px}\n.legend-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}\n.progress-bar{height:6px;background:#e2e8f0;border-radius:99px;overflow:hidden}\n.progress-fill{height:100%;border-radius:99px;transition:width .5s}\n.quick-acts{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:20px}\n.qa{background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px;text-align:center;cursor:pointer;transition:all .15s}\n.qa:hover{border-color:var(--pri);box-shadow:0 2px 8px rgba(99,102,241,.12)}\n.qa .qa-ic{font-size:24px;margin-bottom:6px}\n.qa .qa-t{font-size:12px;font-weight:500}\n<\/style>\n<\/head>\n<body>\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统<\/div>\n<div class=\"ni ac\">🏠 首页/仪表盘<\/div>\n<div class=\"ng-t\">权限管理<\/div>\n<div class=\"ni\" onclick=\"alert('请打开 03_组织架构.html')\">· 组织架构<\/div>\n<div class=\"ni\">· 菜单管理<\/div>\n<div class=\"ni\">· 角色管理<\/div>\n<div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div>\n<div class=\"ni\">· 产品列表<\/div>\n<div class=\"ni\">· 渠道码管理<\/div>\n<div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台账号<\/div>\n<div class=\"ni\">· 平台账号管理<\/div>\n<div class=\"ni\">· 账号模板管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div>\n<div class=\"ni\">· Skill列表<\/div>\n<div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div>\n<div class=\"ni\">· 任务创建<\/div>\n<div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div>\n<div class=\"ni\">· 操作日志<\/div>\n<div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\">\n<div class=\"bc\">🏠 <b>首页<\/b> / 仪表盘<\/div>\n<div style=\"display:flex;align-items:center;gap:10px;font-size:12px\">\n<span>🔔<\/span><span>admin<\/span>\n<div class=\"av\">A<\/div>\n<\/div>\n<\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">仪表盘<\/h1>\n<p class=\"pd\">系统运行概览 · 实时数据统计 · 2026-04-23<\/p>\n\n<!-- Quick Actions -->\n<div class=\"quick-acts\">\n<div class=\"qa\" onclick=\"alert('跳转:任务创建')\"><div class=\"qa-ic\">⚡<\/div><div class=\"qa-t\">创建任务<\/div><\/div>\n<div class=\"qa\" onclick=\"alert('跳转:Skill列表')\"><div class=\"qa-ic\">🧩<\/div><div class=\"qa-t\">管理Skill<\/div><\/div>\n<div class=\"qa\" onclick=\"alert('跳转:平台账号')\"><div class=\"qa-ic\">🔗<\/div><div class=\"qa-t\">平台账号<\/div><\/div>\n<div class=\"qa\" onclick=\"alert('跳转:任务列表')\"><div class=\"qa-ic\">📋<\/div><div class=\"qa-t\">任务列表<\/div><\/div>\n<\/div>\n\n<!-- Stats Cards -->\n<div class=\"sg\">\n<div class=\"sc\" style=\"border-left:3px solid #6366f1\"><div class=\"si\" style=\"background:#ede9fe\">📋<\/div><div><div class=\"sn\" id=\"s-total\">128<\/div><div class=\"sl2\">今日任务总数<\/div><\/div><\/div>\n<div class=\"sc\" style=\"border-left:3px solid #22c55e\"><div class=\"si\" style=\"background:#dcfce7\">✅<\/div><div><div class=\"sn\" id=\"s-ok\">96<\/div><div class=\"sl2\">执行成功<\/div><\/div><\/div>\n<div class=\"sc\" style=\"border-left:3px solid #ef4444\"><div class=\"si\" style=\"background:#fee2e2\">❌<\/div><div><div class=\"sn\" id=\"s-fail\">8<\/div><div class=\"sl2\">执行失败<\/div><\/div><\/div>\n<div class=\"sc\" style=\"border-left:3px solid #f59e0b\"><div class=\"si\" style=\"background:#fef3c7\">⏳<\/div><div><div class=\"sn\" id=\"s-run\">24<\/div><div class=\"sl2\">运行中<\/div><\/div><\/div>\n<div class=\"sc\" style=\"border-left:3px solid #3b82f6\"><div class=\"si\" style=\"background:#dbeafe\">👥<\/div><div><div class=\"sn\">56<\/div><div class=\"sl2\">活跃用户<\/div><\/div><\/div>\n<div class=\"sc\" style=\"border-left:3px solid #8b5cf6\"><div class=\"si\" style=\"background:#f3e8ff\">🧩<\/div><div><div class=\"sn\">23<\/div><div class=\"sl2\">已注册Skill<\/div><\/div><\/div>\n<\/div>\n\n<div style=\"display:grid;grid-template-columns:2fr 1fr;gap:14px\">\n<!-- Bar Chart -->\n<div class=\"card\">\n<div class=\"ct-t\">📊 最近7天任务趋势<\/div>\n<div class=\"bar-chart\" id=\"barChart\"><\/div>\n<\/div>\n\n<!-- Pie / Executor distribution -->\n<div class=\"card\">\n<div class=\"ct-t\">🔄 执行器分布<\/div>\n<div style=\"display:flex;align-items:center;gap:20px;justify-content:center;padding:10px 0\">\n<div class=\"ring\" style=\"background:conic-gradient(#6366f1 0% 62%,#22c55e 62% 100%)\">\n<div style=\"width:80px;height:80px;background:var(--card);border-radius:50%;display:flex;flex-direction:column;align-items:center;justify-content:center\">\n<div class=\"ring-center\">128<\/div>\n<div class=\"ring-label\">总计<\/div>\n<\/div>\n<\/div>\n<div class=\"legend\">\n<div class=\"legend-i\"><div class=\"legend-dot\" style=\"background:#6366f1\"><\/div>🦞 龙虾执行器 <b>62%<\/b> (79)<\/div>\n<div class=\"legend-i\"><div class=\"legend-dot\" style=\"background:#22c55e\"><\/div>📜 脚本引擎 <b>38%<\/b> (49)<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div style=\"display:grid;grid-template-columns:1fr 1fr;gap:14px\">\n<!-- Skill ranking -->\n<div class=\"card\">\n<div class=\"ct-t\">🔥 热门Skill Top 5<\/div>\n<div style=\"display:flex;flex-direction:column;gap:10px\">\n<div><div style=\"display:flex;justify-content:space-between;font-size:12px;margin-bottom:3px\"><span>🥇 竞品分析Agent<\/span><span>386次<\/span><\/div><div class=\"progress-bar\"><div class=\"progress-fill\" style=\"width:100%;background:#6366f1\"><\/div><\/div><\/div>\n<div><div style=\"display:flex;justify-content:space-between;font-size:12px;margin-bottom:3px\"><span>🥈 数据采集脚本<\/span><span>241次<\/span><\/div><div class=\"progress-bar\"><div class=\"progress-fill\" style=\"width:62%;background:#818cf8\"><\/div><\/div><\/div>\n<div><div style=\"display:flex;justify-content:space-between;font-size:12px;margin-bottom:3px\"><span>🥉 素材生成Agent<\/span><span>198次<\/span><\/div><div class=\"progress-bar\"><div class=\"progress-fill\" style=\"width:51%;background:#a78bfa\"><\/div><\/div><\/div>\n<div><div style=\"display:flex;justify-content:space-between;font-size:12px;margin-bottom:3px\"><span>4. 评论监控脚本<\/span><span>156次<\/span><\/div><div class=\"progress-bar\"><div class=\"progress-fill\" style=\"width:40%;background:#c4b5fd\"><\/div><\/div><\/div>\n<div><div style=\"display:flex;justify-content:space-between;font-size:12px;margin-bottom:3px\"><span>5. 投放优化Agent<\/span><span>132次<\/span><\/div><div class=\"progress-bar\"><div class=\"progress-fill\" style=\"width:34%;background:#ddd6fe\"><\/div><\/div><\/div>\n<\/div>\n<\/div>\n\n<!-- Department task stats -->\n<div class=\"card\">\n<div class=\"ct-t\">🏢 部门任务统计<\/div>\n<div style=\"display:flex;flex-direction:column;gap:10px\">\n<div><div style=\"display:flex;justify-content:space-between;font-size:12px;margin-bottom:3px\"><span>投放部<\/span><span>68次 (53%)<\/span><\/div><div class=\"progress-bar\"><div class=\"progress-fill\" style=\"width:100%;background:#22c55e\"><\/div><\/div><\/div>\n<div><div style=\"display:flex;justify-content:space-between;font-size:12px;margin-bottom:3px\"><span>运营部<\/span><span>35次 (27%)<\/span><\/div><div class=\"progress-bar\"><div class=\"progress-fill\" style=\"width:52%;background:#3b82f6\"><\/div><\/div><\/div>\n<div><div style=\"display:flex;justify-content:space-between;font-size:12px;margin-bottom:3px\"><span>技术部<\/span><span>15次 (12%)<\/span><\/div><div class=\"progress-bar\"><div class=\"progress-fill\" style=\"width:22%;background:#f59e0b\"><\/div><\/div><\/div>\n<div><div style=\"display:flex;justify-content:space-between;font-size:12px;margin-bottom:3px\"><span>产品部<\/span><span>10次 (8%)<\/span><\/div><div class=\"progress-bar\"><div class=\"progress-fill\" style=\"width:15%;background:#ef4444\"><\/div><\/div><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<!-- Recent tasks table -->\n<div class=\"card\">\n<div class=\"ct-t\">🕒 最新任务动态 <a style=\"margin-left:auto;font-size:11px;color:var(--pri);cursor:pointer\">查看全部 →<\/a><\/div>\n<div class=\"tw\"><table>\n<tr><th>ID<\/th><th>Skill名称<\/th><th>执行器<\/th><th>产品<\/th><th>创建人<\/th><th>状态<\/th><th>耗时<\/th><th>时间<\/th><\/tr>\n<tr><td>#1024<\/td><td>竞品分析Agent<\/td><td><span class=\"tg tg-p\">🦞龙虾<\/span><\/td><td>ProductA<\/td><td>张三<\/td><td><span class=\"tg tg-ok\">成功<\/span><\/td><td>2m18s<\/td><td>09:05<\/td><\/tr>\n<tr><td>#1023<\/td><td>数据采集脚本<\/td><td><span class=\"tg tg-ok\">📜脚本<\/span><\/td><td>ProductB<\/td><td>李四<\/td><td><span class=\"tg tg-w\">运行中<\/span><\/td><td>1m42s<\/td><td>09:02<\/td><\/tr>\n<tr><td>#1022<\/td><td>素材生成Agent<\/td><td><span class=\"tg tg-p\">🦞龙虾<\/span><\/td><td>ProductA<\/td><td>王五<\/td><td><span class=\"tg tg-ok\">成功<\/span><\/td><td>3m05s<\/td><td>08:58<\/td><\/tr>\n<tr><td>#1021<\/td><td>评论监控脚本<\/td><td><span class=\"tg tg-ok\">📜脚本<\/span><\/td><td>ProductC<\/td><td>赵六<\/td><td><span class=\"tg tg-e\">失败<\/span><\/td><td>0m12s<\/td><td>08:50<\/td><\/tr>\n<tr><td>#1020<\/td><td>投放优化Agent<\/td><td><span class=\"tg tg-p\">🦞龙虾<\/span><\/td><td>ProductA<\/td><td>张三<\/td><td><span class=\"tg tg-ok\">成功<\/span><\/td><td>4m30s<\/td><td>08:45<\/td><\/tr>\n<tr><td>#1019<\/td><td>价格监控Agent<\/td><td><span class=\"tg tg-p\">🦞龙虾<\/span><\/td><td>ProductB<\/td><td>钱七<\/td><td><span class=\"tg tg-ok\">成功<\/span><\/td><td>1m56s<\/td><td>08:40<\/td><\/tr>\n<tr><td>#1018<\/td><td>日报生成脚本<\/td><td><span class=\"tg tg-ok\">📜脚本<\/span><\/td><td>-<\/td><td>李四<\/td><td><span class=\"tg tg-ok\">成功<\/span><\/td><td>0m28s<\/td><td>08:35<\/td><\/tr>\n<\/table><\/div>\n<\/div>\n\n<!-- System status -->\n<div class=\"card\">\n<div class=\"ct-t\">🖥️ 系统状态<\/div>\n<div style=\"display:grid;grid-template-columns:repeat(4,1fr);gap:14px\">\n<div style=\"text-align:center;padding:10px\"><div style=\"font-size:11px;color:var(--sub);margin-bottom:4px\">龙虾执行器<\/div><div style=\"font-size:14px;font-weight:700;color:var(--ok)\">🟢 正常<\/div><div style=\"font-size:10px;color:var(--sub);margin-top:2px\">ping: 23ms<\/div><\/div>\n<div style=\"text-align:center;padding:10px\"><div style=\"font-size:11px;color:var(--sub);margin-bottom:4px\">脚本引擎<\/div><div style=\"font-size:14px;font-weight:700;color:var(--ok)\">🟢 正常<\/div><div style=\"font-size:10px;color:var(--sub);margin-top:2px\">并发: 8/20<\/div><\/div>\n<div style=\"text-align:center;padding:10px\"><div style=\"font-size:11px;color:var(--sub);margin-bottom:4px\">数据库<\/div><div style=\"font-size:14px;font-weight:700;color:var(--ok)\">🟢 正常<\/div><div style=\"font-size:10px;color:var(--sub);margin-top:2px\">连接: 12/100<\/div><\/div>\n<div style=\"text-align:center;padding:10px\"><div style=\"font-size:11px;color:var(--sub);margin-bottom:4px\">消息队列<\/div><div style=\"font-size:14px;font-weight:700;color:var(--warn)\">🟡 队列积压<\/div><div style=\"font-size:10px;color:var(--sub);margin-top:2px\">堆积: 42<\/div><\/div>\n<\/div>\n<\/div>\n\n<\/div>\n<\/div>\n<\/div>\n\n<script>\n// Animated bar chart\nconst data=[\n{day:'4/17',val:85},{day:'4/18',val:120},{day:'4/19',val:95},\n{day:'4/20',val:140},{day:'4/21',val:110},{day:'4/22',val:160},{day:'4/23',val:128}\n];\nconst max=Math.max(...data.map(d=>d.val));\nconst chart=document.getElementById('barChart');\ndata.forEach(d=>{\n const col=document.createElement('div');col.className='bar-col';\n const val=document.createElement('div');val.className='bar-val';val.textContent=d.val;\n const bar=document.createElement('div');bar.className='bar';\n bar.style.cssText=`background:linear-gradient(180deg,#6366f1,#a78bfa);height:0px`;\n const lbl=document.createElement('div');lbl.className='bar-label';lbl.textContent=d.day;\n col.append(val,bar,lbl);chart.append(col);\n setTimeout(()=>{bar.style.height=(d.val/max*140)+'px'},100);\n});\n\n// Simulated real-time counter\nlet total=128;\nsetInterval(()=>{\n if(Math.random()>.7){\n total++;document.getElementById('s-total').textContent=total;\n const ok=parseInt(document.getElementById('s-ok').textContent);\n if(Math.random()>.2)document.getElementById('s-ok').textContent=ok+1;\n else{\n const f=parseInt(document.getElementById('s-fail').textContent);\n document.getElementById('s-fail').textContent=f+1;\n }\n }\n},3000);\n<\/script>\n<\/body>\n<\/html>\n",
"03_组织架构.html": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style>\n<meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\">\n<title>Agent任务系统 v2.0 - 组织架构<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}\n:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--side:#1e293b}\nbody{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6}\n.layout{display:flex;min-height:100vh}\n.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}\n.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}\n.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}\n.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}\n.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}\n.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}\n.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.card{background:var(--card);border-radius:10px;padding:16px;border:1px solid var(--bdr);margin-bottom:14px}\n.ct-t{font-size:13px;font-weight:600;margin-bottom:12px;display:flex;align-items:center;gap:6px}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}\n.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}\n.btn-s{background:var(--ok);color:#fff}\n.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}\n.btn-sm{padding:5px 10px;font-size:11px}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}\n.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-g{background:#f1f5f9;color:#64748b}\ntable{width:100%;border-collapse:collapse;font-size:12px}\nth,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}\nth{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}\n.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}\n.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none}.fi:focus{border-color:var(--pri)}\n.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}\n.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n/* Tree */\n.tr-n{padding:3px 0;font-size:12px}\n.tr-r{display:flex;align-items:center;gap:6px;padding:5px 8px;border-radius:6px;cursor:pointer}\n.tr-r:hover{background:#f1f5f9}.tr-r.sel{background:rgba(99,102,241,.1);color:var(--pri)}\n.tr-t{width:14px;text-align:center;color:var(--sub);font-size:10px;cursor:pointer}\n.tr-c{padding-left:22px;border-left:1px dashed var(--bdr);margin-left:11px}\n.tr-c.hide{display:none}\n/* Modal */\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}\n.mo.show{display:flex}\n.mc{background:var(--card);border-radius:14px;width:90%;max-width:560px;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2);animation:mIn .2s}\n@keyframes mIn{from{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}\n.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}\n.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}\n.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}\n.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}\n@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n<\/style>\n<\/head>\n<body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<!-- Modal: 新增/编辑组织 -->\n<div class=\"mo\" id=\"modal-org\">\n<div class=\"mc\">\n<div class=\"mh\"><h3 id=\"modal-org-title\">新增组织<\/h3><button class=\"mx\" onclick=\"closeModal('modal-org')\">✕<\/button><\/div>\n<div class=\"mb\">\n<div class=\"fg\"><label class=\"fl\">上级组织<\/label><select class=\"fs\"><option>星辰科技有限公司<\/option><option>├ 投放部<\/option><option>├ 运营部<\/option><option>├ 技术部<\/option><option>├ 产品部<\/option><\/select><\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">组织名称 <span style=\"color:var(--err)\">*<\/span><\/label><input class=\"fi\" placeholder=\"请输入组织名称\"><\/div>\n<div class=\"fg\"><label class=\"fl\">组织类型 <span style=\"color:var(--err)\">*<\/span><\/label><select class=\"fs\"><option value=\"\">请选择<\/option><option>公司<\/option><option>部门<\/option><option>小组<\/option><\/select><\/div>\n<\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">负责人<\/label><select class=\"fs\"><option value=\"\">请选择<\/option><option>张三<\/option><option>李四<\/option><option>王五<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">排序号<\/label><input class=\"fi\" type=\"number\" value=\"0\"><\/div>\n<\/div>\n<div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>禁用<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">备注<\/label><textarea class=\"fi\" rows=\"2\" placeholder=\"可选\"><\/textarea><\/div>\n<\/div>\n<div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeModal('modal-org')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeModal('modal-org');showToast('保存成功','ok')\">保存<\/button><\/div>\n<\/div><\/div>\n\n<!-- Modal: 确认删除 -->\n<div class=\"mo\" id=\"modal-del\">\n<div class=\"mc\" style=\"max-width:400px\">\n<div class=\"mh\"><h3>⚠️ 确认删除<\/h3><button class=\"mx\" onclick=\"closeModal('modal-del')\">✕<\/button><\/div>\n<div class=\"mb\" style=\"text-align:center;padding:24px\">\n<div style=\"font-size:40px;margin-bottom:10px\">🗑️<\/div>\n<p style=\"font-size:14px;font-weight:600;margin-bottom:6px\">确定要删除该组织吗?<\/p>\n<p style=\"font-size:12px;color:var(--sub)\">删除后该组织下的子部门和人员将移至上级组织<br>此操作不可恢复<\/p>\n<\/div>\n<div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeModal('modal-del')\">取消<\/button><button class=\"btn btn-d\" onclick=\"closeModal('modal-del');showToast('已删除','ok')\">确认删除<\/button><\/div>\n<\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div>\n<div class=\"ni ac\">· 组织架构<\/div>\n<div class=\"ni\">· 菜单管理<\/div>\n<div class=\"ni\">· 角色管理<\/div>\n<div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div>\n<div class=\"ng-t\">平台账号<\/div><div class=\"ni\">· 账号管理<\/div><div class=\"ni\">· 账号模板<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\">🏢 权限管理 / <b style=\"color:var(--txt)\">组织架构<\/b><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">组织架构管理<\/h1>\n<p class=\"pd\">公司 → 部门 → 小组 三级树形结构 · 支持拖拽排序 · 部门下可挂载角色和成员<\/p>\n\n<div style=\"display:grid;grid-template-columns:300px 1fr;gap:14px\">\n<!-- Left: Tree -->\n<div class=\"card\">\n<div class=\"ct-t\">🏢 组织树 <button class=\"btn btn-p btn-sm\" style=\"margin-left:auto\" onclick=\"openModal('modal-org','新增组织')\">+ 新增<\/button><\/div>\n<div style=\"margin-bottom:8px;padding:6px 10px;background:#f8fafc;border-radius:6px;display:flex;align-items:center;gap:6px\"><span>🔍<\/span><input style=\"border:none;background:none;outline:none;font-size:11px;width:100%\" placeholder=\"搜索组织名称\"><\/div>\n<div id=\"orgTree\">\n<div class=\"tr-n\"><div class=\"tr-r\" onclick=\"toggleTree(this)\"><span class=\"tr-t\">▼<\/span><span>🏢<\/span><span class=\"tr-l\" style=\"font-weight:700\">星辰科技有限公司<\/span><\/div>\n<div class=\"tr-c\">\n <div class=\"tr-n\"><div class=\"tr-r sel\" onclick=\"toggleTree(this);selectOrg('投放部','department',12,4)\"><span class=\"tr-t\">▼<\/span><span>🏬<\/span><span>投放部<\/span><span class=\"tg tg-g\" style=\"margin-left:auto;font-size:9px\">12人<\/span><\/div>\n <div class=\"tr-c\">\n <div class=\"tr-n\"><div class=\"tr-r\" onclick=\"selectOrg('投放一组','team',4,0)\"><span class=\"tr-t\">·<\/span><span>👥<\/span><span>投放一组<\/span><\/div><\/div>\n <div class=\"tr-n\"><div class=\"tr-r\" onclick=\"selectOrg('投放二组','team',5,0)\"><span class=\"tr-t\">·<\/span><span>👥<\/span><span>投放二组<\/span><\/div><\/div>\n <div class=\"tr-n\"><div class=\"tr-r\" onclick=\"selectOrg('投放三组','team',3,0)\"><span class=\"tr-t\">·<\/span><span>👥<\/span><span>投放三组<\/span><\/div><\/div>\n <\/div><\/div>\n <div class=\"tr-n\"><div class=\"tr-r\" onclick=\"toggleTree(this);selectOrg('运营部','department',8,2)\"><span class=\"tr-t\">▼<\/span><span>🏬<\/span><span>运营部<\/span><span class=\"tg tg-g\" style=\"margin-left:auto;font-size:9px\">8人<\/span><\/div>\n <div class=\"tr-c\">\n <div class=\"tr-n\"><div class=\"tr-r\" onclick=\"selectOrg('内容运营组','team',4,0)\"><span class=\"tr-t\">·<\/span><span>👥<\/span><span>内容运营组<\/span><\/div><\/div>\n <div class=\"tr-n\"><div class=\"tr-r\" onclick=\"selectOrg('社区运营组','team',4,0)\"><span class=\"tr-t\">·<\/span><span>👥<\/span><span>社区运营组<\/span><\/div><\/div>\n <\/div><\/div>\n <div class=\"tr-n\"><div class=\"tr-r\" onclick=\"toggleTree(this);selectOrg('技术部','department',10,3)\"><span class=\"tr-t\">▶<\/span><span>🏬<\/span><span>技术部<\/span><span class=\"tg tg-g\" style=\"margin-left:auto;font-size:9px\">10人<\/span><\/div>\n <div class=\"tr-c hide\">\n <div class=\"tr-n\"><div class=\"tr-r\"><span class=\"tr-t\">·<\/span><span>👥<\/span><span>前端组<\/span><\/div><\/div>\n <div class=\"tr-n\"><div class=\"tr-r\"><span class=\"tr-t\">·<\/span><span>👥<\/span><span>后端组<\/span><\/div><\/div>\n <div class=\"tr-n\"><div class=\"tr-r\"><span class=\"tr-t\">·<\/span><span>👥<\/span><span>运维组<\/span><\/div><\/div>\n <\/div><\/div>\n <div class=\"tr-n\"><div class=\"tr-r\" onclick=\"selectOrg('产品部','department',6,1)\"><span class=\"tr-t\">▶<\/span><span>🏬<\/span><span>产品部<\/span><span class=\"tg tg-g\" style=\"margin-left:auto;font-size:9px\">6人<\/span><\/div><div class=\"tr-c hide\"><\/div><\/div>\n<\/div><\/div>\n<\/div><\/div>\n\n<!-- Right: Detail Panel -->\n<div>\n<div class=\"card\" id=\"orgDetail\">\n<div class=\"ct-t\">📝 <span id=\"detailTitle\">投放部<\/span> · 详情\n<div style=\"margin-left:auto;display:flex;gap:6px\">\n<button class=\"btn btn-p btn-sm\" onclick=\"openModal('modal-org','编辑组织')\">编辑<\/button>\n<button class=\"btn btn-sm btn-d\" onclick=\"openModal('modal-del')\">删除<\/button>\n<\/div><\/div>\n<div style=\"display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-bottom:16px;font-size:12px\">\n<div><span style=\"color:var(--sub)\">类型:<\/span><span class=\"tg tg-i\" id=\"detailType\">部门<\/span><\/div>\n<div><span style=\"color:var(--sub)\">成员数:<\/span><b id=\"detailCount\">12人<\/b><\/div>\n<div><span style=\"color:var(--sub)\">下辖组数:<\/span><b id=\"detailTeams\">4组<\/b><\/div>\n<div><span style=\"color:var(--sub)\">负责人:<\/span><b>张三<\/b><\/div>\n<div><span style=\"color:var(--sub)\">状态:<\/span><span class=\"tg tg-ok\">启用<\/span><\/div>\n<div><span style=\"color:var(--sub)\">创建时间:<\/span>2026-01-15<\/div>\n<\/div>\n<\/div>\n\n<!-- 角色列表 -->\n<div class=\"card\">\n<div class=\"ct-t\">🎭 部门角色 <span class=\"tg tg-g\">部门级角色<\/span><\/div>\n<div class=\"tw\"><table>\n<tr><th>角色名称<\/th><th>角色编码<\/th><th>成员数<\/th><th>Skill数<\/th><th>状态<\/th><\/tr>\n<tr><td><span class=\"tg tg-p\">投放主管<\/span><\/td><td>dept_tf_manager<\/td><td>3<\/td><td>8<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><\/tr>\n<tr><td><span class=\"tg tg-i\">投放专员<\/span><\/td><td>dept_tf_staff<\/td><td>9<\/td><td>5<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><\/tr>\n<tr><td><span class=\"tg tg-p\">数据分析师<\/span><\/td><td>dept_tf_analyst<\/td><td>2<\/td><td>4<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><\/tr>\n<\/table><\/div><\/div>\n\n<!-- 成员列表 -->\n<div class=\"card\">\n<div class=\"ct-t\">👥 部门成员 <span class=\"tg tg-g\" id=\"memberBadge\">12人<\/span>\n<button class=\"btn btn-sm btn-g\" style=\"margin-left:auto\">导出<\/button><\/div>\n<div class=\"tw\"><table>\n<tr><th>姓名<\/th><th>工号<\/th><th>所属小组<\/th><th>角色<\/th><th>入职日期<\/th><th>状态<\/th><\/tr>\n<tr><td>张三<\/td><td>EMP001<\/td><td>投放一组<\/td><td><span class=\"tg tg-p\">投放主管<\/span><\/td><td>2024-03-01<\/td><td><span class=\"tg tg-ok\">在职<\/span><\/td><\/tr>\n<tr><td>李四<\/td><td>EMP002<\/td><td>投放一组<\/td><td><span class=\"tg tg-i\">投放专员<\/span><\/td><td>2024-06-15<\/td><td><span class=\"tg tg-ok\">在职<\/span><\/td><\/tr>\n<tr><td>王五<\/td><td>EMP003<\/td><td>投放二组<\/td><td><span class=\"tg tg-i\">投放专员<\/span><\/td><td>2024-08-20<\/td><td><span class=\"tg tg-ok\">在职<\/span><\/td><\/tr>\n<tr><td>赵六<\/td><td>EMP004<\/td><td>投放二组<\/td><td><span class=\"tg tg-p\">投放主管<\/span> <span class=\"tg tg-i\">数据分析师<\/span><\/td><td>2024-02-10<\/td><td><span class=\"tg tg-ok\">在职<\/span><\/td><\/tr>\n<tr><td>钱七<\/td><td>EMP005<\/td><td>投放三组<\/td><td><span class=\"tg tg-i\">投放专员<\/span><\/td><td>2025-01-05<\/td><td><span class=\"tg tg-ok\">在职<\/span><\/td><\/tr>\n<tr><td>孙八<\/td><td>EMP006<\/td><td>投放一组<\/td><td><span class=\"tg tg-i\">投放专员<\/span><\/td><td>2025-03-18<\/td><td><span class=\"tg tg-ok\">在职<\/span><\/td><\/tr>\n<\/table><\/div><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<script>\nfunction toggleTree(el){\n const c=el.closest('.tr-n').querySelector('.tr-c');\n if(!c)return;\n const t=el.querySelector('.tr-t');\n if(c.classList.contains('hide')){c.classList.remove('hide');t.textContent='▼'}\n else{c.classList.add('hide');t.textContent='▶'}\n}\nfunction selectOrg(name,type,count,teams){\n document.querySelectorAll('.tr-r').forEach(r=>r.classList.remove('sel'));\n event.currentTarget.classList.add('sel');\n document.getElementById('detailTitle').textContent=name;\n document.getElementById('detailType').textContent=type==='department'?'部门':'小组';\n document.getElementById('detailCount').textContent=count+'人';\n document.getElementById('detailTeams').textContent=teams+'组';\n document.getElementById('memberBadge').textContent=count+'人';\n}\nfunction openModal(id,title){document.getElementById(id).classList.add('show');if(title&&document.getElementById(id.replace('modal-','modal-')+'-title'))document.getElementById('modal-org-title').textContent=title}\nfunction closeModal(id){document.getElementById(id).classList.remove('show')}\nfunction showToast(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body>\n<\/html>\n",
"04_角色管理.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 - 角色管理<\/title>\n<style>*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6}.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}.card{background:var(--card);border-radius:10px;padding:16px;border:1px solid var(--bdr);margin-bottom:14px}.ct-t{font-size:13px;font-weight:600;margin-bottom:12px;display:flex;align-items:center;gap:6px}.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px}.btn-p{background:var(--pri);color:#fff}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-g{background:#f1f5f9;color:#64748b}.tg-w{background:#fef3c7;color:#92400e}table{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none}.fi:focus{border-color:var(--pri)}.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}.tb{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:120px}.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff}.tabs{display:flex;gap:0;border-bottom:2px solid var(--bdr);margin-bottom:16px}.tab{padding:8px 16px;font-size:12px;font-weight:500;color:var(--sub);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px}.tab.ac{color:var(--pri);border-bottom-color:var(--pri);font-weight:600}.tab:hover{color:var(--txt)}.tab-ct{display:none}.tab-ct.show{display:block}.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:720px;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.pg{display:flex;align-items:center;justify-content:space-between;padding:10px 0;font-size:12px;color:var(--sub)}.pgb{padding:4px 10px;border:1px solid var(--bdr);border-radius:5px;font-size:11px;cursor:pointer;background:var(--card);margin:0 2px}.pgb.ac{background:var(--pri);color:#fff;border-color:var(--pri)}.ck label{display:flex;align-items:center;gap:5px;padding:3px 0;cursor:pointer;font-size:12px}.ck .ch{padding-left:22px}<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n<!-- Modal: 新增/编辑角色 -->\n<div class=\"mo\" id=\"modal-role\"><div class=\"mc\"><div class=\"mh\"><h3 id=\"mrTitle\">新增角色<\/h3><button class=\"mx\" onclick=\"closeM('modal-role')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fr\"><div class=\"fg\"><label class=\"fl\">角色名称 <span style=\"color:var(--err)\">*<\/span><\/label><input class=\"fi\" placeholder=\"如:投放主管\"><\/div><div class=\"fg\"><label class=\"fl\">角色编码 <span style=\"color:var(--err)\">*<\/span><\/label><input class=\"fi\" placeholder=\"如:dept_tf_manager\"><\/div><\/div>\n<div class=\"fr\"><div class=\"fg\"><label class=\"fl\">所属部门 <span style=\"color:var(--err)\">*<\/span><\/label><select class=\"fs\" id=\"roleDept\"><option>投放部<\/option><option>运营部<\/option><option>技术部<\/option><option>产品部<\/option><\/select><\/div><div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>禁用<\/option><\/select><\/div><\/div>\n<div class=\"fg\"><label class=\"fl\">描述<\/label><textarea class=\"fi\" rows=\"2\" placeholder=\"角色职责描述\"><\/textarea><\/div>\n<hr style=\"border:none;border-top:1px solid var(--bdr);margin:16px 0\">\n<div class=\"ct-t\">🔑 四要素配置<\/div>\n<!-- Tabs for 4 elements -->\n<div class=\"tabs\"><div class=\"tab ac\" onclick=\"switchRoleTab(0)\">📋 菜单权限<\/div><div class=\"tab\" onclick=\"switchRoleTab(1)\">📦 产品范围<\/div><div class=\"tab\" onclick=\"switchRoleTab(2)\">🧩 Skill权限<\/div><div class=\"tab\" onclick=\"switchRoleTab(3)\">🔗 平台账号<\/div><\/div>\n<div class=\"tab-ct show\" id=\"rtab0\">\n<div class=\"ck\">\n<label><input type=\"checkbox\" checked> <b>全选<\/b><\/label>\n<div class=\"ch\"><label><input type=\"checkbox\" checked> 📁 首页<\/label><\/div>\n<div class=\"ch\"><label><input type=\"checkbox\" checked> 📁 权限管理<\/label>\n<div class=\"ch\"><label><input type=\"checkbox\" checked> 组织架构 (org:view, org:create, org:edit, org:delete)<\/label><\/div>\n<div class=\"ch\"><label><input type=\"checkbox\" checked> 角色管理 (role:view, role:create, role:edit)<\/label><\/div>\n<div class=\"ch\"><label><input type=\"checkbox\"> 用户管理 (user:view, user:create)<\/label><\/div>\n<\/div>\n<div class=\"ch\"><label><input type=\"checkbox\" checked> 📁 产品管理<\/label>\n<div class=\"ch\"><label><input type=\"checkbox\" checked> 产品列表 (product:view, product:create, product:edit)<\/label><\/div>\n<div class=\"ch\"><label><input type=\"checkbox\" checked> 渠道码管理 (channel:view, channel:create)<\/label><\/div>\n<\/div>\n<div class=\"ch\"><label><input type=\"checkbox\" checked> 📁 Skill中心<\/label><\/div>\n<div class=\"ch\"><label><input type=\"checkbox\" checked> 📁 任务中心<\/label><\/div>\n<\/div><\/div>\n<div class=\"tab-ct\" id=\"rtab1\">\n<p style=\"font-size:12px;color:var(--sub);margin-bottom:10px\">勾选该角色可操作的产品范围:<\/p>\n<div class=\"ck\">\n<label><input type=\"checkbox\" checked> ProductA — 跨境电商旗舰店<\/label>\n<label><input type=\"checkbox\" checked> ProductB — 国内直播电商<\/label>\n<label><input type=\"checkbox\"> ProductC — 社交媒体矩阵<\/label>\n<label><input type=\"checkbox\"> ProductD — 搜索引擎营销<\/label>\n<\/div><\/div>\n<div class=\"tab-ct\" id=\"rtab2\">\n<p style=\"font-size:12px;color:var(--sub);margin-bottom:10px\">勾选该角色可调用的Skill:<\/p>\n<div class=\"ck\">\n<label><input type=\"checkbox\" checked> 🦞 竞品分析Agent<\/label>\n<label><input type=\"checkbox\" checked> 📜 数据采集脚本<\/label>\n<label><input type=\"checkbox\" checked> 🦞 素材生成Agent<\/label>\n<label><input type=\"checkbox\"> 📜 评论监控脚本<\/label>\n<label><input type=\"checkbox\"> 🦞 投放优化Agent<\/label>\n<label><input type=\"checkbox\"> 📜 日报生成脚本<\/label>\n<\/div><\/div>\n<div class=\"tab-ct\" id=\"rtab3\">\n<p style=\"font-size:12px;color:var(--sub);margin-bottom:10px\">该角色可使用的平台账号(归属角色级别):<\/p>\n<div class=\"tw\"><table><tr><th>平台<\/th><th>账号名<\/th><th>状态<\/th><th>绑定<\/th><\/tr>\n<tr><td>🔴 小红书<\/td><td>品牌旗舰店_01<\/td><td><span class=\"tg tg-ok\">正常<\/span><\/td><td><input type=\"checkbox\" checked><\/td><\/tr>\n<tr><td>🎵 抖音<\/td><td>官方账号_A<\/td><td><span class=\"tg tg-ok\">正常<\/span><\/td><td><input type=\"checkbox\" checked><\/td><\/tr>\n<tr><td>📘 Facebook<\/td><td>Brand_Page_01<\/td><td><span class=\"tg tg-ok\">正常<\/span><\/td><td><input type=\"checkbox\"><\/td><\/tr>\n<tr><td>🐦 Twitter<\/td><td>@brand_official<\/td><td><span class=\"tg tg-w\">即将过期<\/span><\/td><td><input type=\"checkbox\"><\/td><\/tr>\n<\/table><\/div><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-role')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-role');showT('保存成功','ok')\">保存<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\"><aside class=\"side\"><div class=\"logo\">🤖 Agent任务系统<\/div><div class=\"ni\">🏠 首页<\/div><div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni ac\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div><div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ng-t\">平台/Skill/任务<\/div><div class=\"ni\">· 平台账号<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div><\/aside>\n<div class=\"main\"><div class=\"hd\">🔐 权限管理 / <b style=\"color:var(--txt)\">角色管理<\/b><\/div>\n<div class=\"ct\"><h1 class=\"pt\">角色管理<\/h1><p class=\"pd\">部门级角色 · 四要素配置(菜单权限+产品范围+Skill权限+平台账号)· 用户多角色并集<\/p>\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索角色名称/编码\"><\/div>\n<select class=\"sl\"><option>全部部门<\/option><option>投放部<\/option><option>运营部<\/option><option>技术部<\/option><option>产品部<\/option><\/select>\n<select class=\"sl\"><option>全部状态<\/option><option>启用<\/option><option>禁用<\/option><\/select>\n<button class=\"btn btn-p\" style=\"margin-left:auto\" onclick=\"openM('modal-role','新增角色')\">+ 新增角色<\/button>\n<\/div>\n<div class=\"tw\"><table>\n<tr><th><input type=\"checkbox\"><\/th><th>角色名称<\/th><th>角色编码<\/th><th>所属部门<\/th><th>菜单权限<\/th><th>产品范围<\/th><th>Skill数<\/th><th>平台账号<\/th><th>成员数<\/th><th>状态<\/th><th>操作<\/th><\/tr>\n<tr><td><input type=\"checkbox\"><\/td><td><b>超级管理员<\/b><\/td><td>super_admin<\/td><td><span class=\"tg tg-g\">全局<\/span><\/td><td><span class=\"tg tg-p\">全部<\/span><\/td><td><span class=\"tg tg-p\">全部<\/span><\/td><td>23<\/td><td>全部<\/td><td>2<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openM('modal-role','编辑角色')\">编辑<\/button><\/td><\/tr>\n<tr><td><input type=\"checkbox\"><\/td><td><b>投放主管<\/b><\/td><td>dept_tf_mgr<\/td><td><span class=\"tg tg-i\">投放部<\/span><\/td><td>12项<\/td><td>2个产品<\/td><td>8<\/td><td>4个<\/td><td>3<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openM('modal-role','编辑角色')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\">删除<\/button><\/td><\/tr>\n<tr><td><input type=\"checkbox\"><\/td><td><b>投放专员<\/b><\/td><td>dept_tf_staff<\/td><td><span class=\"tg tg-i\">投放部<\/span><\/td><td>8项<\/td><td>2个产品<\/td><td>5<\/td><td>2个<\/td><td>9<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openM('modal-role','编辑角色')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\">删除<\/button><\/td><\/tr>\n<tr><td><input type=\"checkbox\"><\/td><td><b>数据分析师<\/b><\/td><td>dept_tf_analyst<\/td><td><span class=\"tg tg-i\">投放部<\/span><\/td><td>6项<\/td><td>全部<\/td><td>4<\/td><td>0个<\/td><td>2<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openM('modal-role','编辑角色')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\">删除<\/button><\/td><\/tr>\n<tr><td><input type=\"checkbox\"><\/td><td><b>运营主管<\/b><\/td><td>dept_yy_mgr<\/td><td><span class=\"tg tg-p\">运营部<\/span><\/td><td>10项<\/td><td>3个产品<\/td><td>6<\/td><td>3个<\/td><td>2<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openM('modal-role','编辑角色')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\">删除<\/button><\/td><\/tr>\n<tr><td><input type=\"checkbox\"><\/td><td><b>运营专员<\/b><\/td><td>dept_yy_staff<\/td><td><span class=\"tg tg-p\">运营部<\/span><\/td><td>6项<\/td><td>2个产品<\/td><td>3<\/td><td>2个<\/td><td>6<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openM('modal-role','编辑角色')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\">删除<\/button><\/td><\/tr>\n<tr><td><input type=\"checkbox\"><\/td><td><b>开发工程师<\/b><\/td><td>dept_tech_dev<\/td><td><span class=\"tg tg-w\">技术部<\/span><\/td><td>5项<\/td><td>全部<\/td><td>10<\/td><td>0个<\/td><td>7<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openM('modal-role','编辑角色')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\">删除<\/button><\/td><\/tr>\n<tr><td><input type=\"checkbox\"><\/td><td><b>产品经理<\/b><\/td><td>dept_pm_mgr<\/td><td><span class=\"tg tg-g\">产品部<\/span><\/td><td>8项<\/td><td>全部<\/td><td>2<\/td><td>0个<\/td><td>3<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openM('modal-role','编辑角色')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\">删除<\/button><\/td><\/tr>\n<\/table><\/div>\n<div class=\"pg\"><span>共 8 条,每页 10 条<\/span><div><span class=\"pgb ac\">1<\/span><\/div><\/div>\n\n<div class=\"card\" style=\"margin-top:16px;border:2px dashed var(--pri)\">\n<div class=\"ct-t\">💡 角色权限规则说明<\/div>\n<div style=\"font-size:12px;color:var(--sub);line-height:2\">\n<b>RB-01<\/b> 角色必须归属于一个部门(部门级角色)<br>\n<b>RB-02<\/b> 用户可绑定多个角色,最终权限 = 所有角色权限并集<br>\n<b>RB-03<\/b> 角色四要素:菜单权限 + 产品范围 + Skill权限 + 平台账号<br>\n<b>RB-05<\/b> 平台账号归属角色而非用户,角色成员共享<br>\n<b>RB-06<\/b> 任务创建时校验交集(用户产品 ∩ Skill产品 ∩ 账号产品 ≠ ∅)\n<\/div><\/div>\n<\/div><\/div><\/div>\n<script>\nfunction switchRoleTab(i){document.querySelectorAll('.tab').forEach((t,j)=>{t.classList.toggle('ac',j===i)});document.querySelectorAll('.tab-ct').forEach((c,j)=>{c.classList.toggle('show',j===i)})}\nfunction openM(id,t){document.getElementById(id).classList.add('show');if(t)document.getElementById('mrTitle').textContent=t}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script><\/body><\/html>\n",
"05_用户管理.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 用户管理<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.card{background:var(--card);border-radius:10px;padding:16px;border:1px solid var(--bdr);margin-bottom:14px}\n.tb{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:120px}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}.btn-s{background:var(--ok);color:#fff}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-g{background:#f1f5f9;color:#64748b}.tg-w{background:#fef3c7;color:#92400e}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px;position:sticky;top:0}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}.fl .rq{color:var(--err)}.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none;transition:border .12s}.fi:focus{border-color:var(--pri);box-shadow:0 0 0 2px rgba(99,102,241,.1)}.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:680px;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2);animation:mIn .2s}@keyframes mIn{from{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.pg{display:flex;align-items:center;justify-content:space-between;padding:10px 0;font-size:12px;color:var(--sub)}.pgb{padding:4px 10px;border:1px solid var(--bdr);border-radius:5px;font-size:11px;cursor:pointer;background:var(--card);margin:0 2px}.pgb.ac{background:var(--pri);color:#fff;border-color:var(--pri)}\n.tabs{display:flex;gap:0;border-bottom:2px solid var(--bdr);margin-bottom:16px}.tab{padding:8px 16px;font-size:12px;font-weight:500;color:var(--sub);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px}.tab.ac{color:var(--pri);border-bottom-color:var(--pri);font-weight:600}.tab:hover{color:var(--txt)}.tab-ct{display:none}.tab-ct.show{display:block}\n.multi-select{display:flex;flex-wrap:wrap;gap:6px;padding:8px;border:1px solid var(--bdr);border-radius:7px;min-height:38px;cursor:pointer}.ms-tag{display:flex;align-items:center;gap:4px;background:#ede9fe;color:#6b21a8;padding:2px 8px;border-radius:4px;font-size:11px}.ms-tag .ms-x{cursor:pointer;font-weight:700;color:#6b21a8}.ms-drop{position:absolute;top:100%;left:0;right:0;background:var(--card);border:1px solid var(--bdr);border-radius:7px;box-shadow:0 4px 12px rgba(0,0,0,.1);z-index:10;max-height:200px;overflow-y:auto;display:none}.ms-drop.show{display:block}.ms-opt{padding:7px 12px;font-size:12px;cursor:pointer;display:flex;align-items:center;gap:6px}.ms-opt:hover{background:#f1f5f9}.ms-opt.sel{background:#ede9fe;color:#6b21a8}\n.grant-row{display:flex;gap:8px;align-items:center;padding:8px;border:1px solid var(--bdr);border-radius:7px;margin-bottom:8px;font-size:12px}\n.note{background:#eff6ff;border-left:3px solid var(--pri);padding:8px 12px;border-radius:0 6px 6px 0;font-size:11px;color:var(--sub);margin-bottom:14px}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<!-- Modal: 新增/编辑用户 -->\n<div class=\"mo\" id=\"modal-user\"><div class=\"mc\"><div class=\"mh\"><h3 id=\"muTitle\">新增用户<\/h3><button class=\"mx\" onclick=\"closeM('modal-user')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">用户名 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mu-name\" placeholder=\"请输入用户名\"><\/div>\n<div class=\"fg\"><label class=\"fl\">密码 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mu-pwd\" type=\"password\" placeholder=\"至少6位\" value=\"\"><\/div>\n<\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">邮箱<\/label><input class=\"fi\" type=\"email\" placeholder=\"user@example.com\"><\/div>\n<div class=\"fg\"><label class=\"fl\">手机号<\/label><input class=\"fi\" placeholder=\"13800138000\"><\/div>\n<\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">所属部门 <span class=\"rq\">*<\/span><\/label>\n<select class=\"fs\" id=\"mu-dept\" onchange=\"onDeptChange(this.value)\">\n<option value=\"\">请选择部门<\/option>\n<option value=\"tf\">投放部<\/option>\n<option value=\"yy\">运营部<\/option>\n<option value=\"tech\">技术部<\/option>\n<option value=\"pm\">产品部<\/option>\n<\/select>\n<\/div>\n<div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>禁用<\/option><\/select><\/div>\n<\/div>\n\n<div class=\"note\">⚠️ RB-02: 用户只能绑定本部门下的角色。切换部门时自动清空已选角色(RB-08)<\/div>\n\n<div class=\"fg\"><label class=\"fl\">绑定角色(多选)<span class=\"rq\">*<\/span><\/label>\n<div style=\"position:relative\" id=\"roleSelectWrap\">\n<div class=\"multi-select\" id=\"roleSelect\" onclick=\"toggleDrop('roleDrop')\">\n<span style=\"color:var(--sub);font-size:11px\" id=\"rolePlaceholder\">请先选择部门<\/span>\n<\/div>\n<div class=\"ms-drop\" id=\"roleDrop\"><\/div>\n<\/div>\n<\/div>\n\n<hr style=\"border:none;border-top:1px solid var(--bdr);margin:16px 0\">\n<div class=\"fg\"><label class=\"fl\">额外产品授权(跨组协作)<\/label>\n<div id=\"grantList\">\n<div class=\"grant-row\"><select class=\"fs\" style=\"width:200px\"><option>ProductC — 社交媒体矩阵<\/option><option>ProductD — 搜索引擎营销<\/option><\/select><input class=\"fi\" type=\"date\" style=\"width:150px\" value=\"2026-12-31\"><button class=\"btn btn-d btn-sm\" onclick=\"this.closest('.grant-row').remove()\">删除<\/button><\/div>\n<\/div>\n<button class=\"btn btn-g btn-sm\" onclick=\"addGrant()\" style=\"margin-top:6px\">+ 添加授权<\/button>\n<\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-user')\">取消<\/button><button class=\"btn btn-p\" onclick=\"saveUser()\">保存<\/button><\/div><\/div><\/div>\n\n<!-- Modal: 确认删除 -->\n<div class=\"mo\" id=\"modal-del\"><div class=\"mc\" style=\"max-width:400px\"><div class=\"mh\"><h3>⚠️ 确认删除<\/h3><button class=\"mx\" onclick=\"closeM('modal-del')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:24px\"><div style=\"font-size:40px;margin-bottom:10px\">🗑️<\/div><p style=\"font-size:14px;font-weight:600;margin-bottom:6px\">确定要删除该用户吗?<\/p><p style=\"font-size:12px;color:var(--sub)\">删除后该用户的角色绑定和平台产品账号将一并清除<br>此操作不可恢复<\/p><\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-del')\">取消<\/button><button class=\"btn btn-d\" onclick=\"closeM('modal-del');showT('✅ 已删除','ok')\">确认删除<\/button><\/div><\/div><\/div>\n\n<!-- Modal: 重置密码 -->\n<div class=\"mo\" id=\"modal-pwd\"><div class=\"mc\" style=\"max-width:420px\"><div class=\"mh\"><h3>🔑 重置密码<\/h3><button class=\"mx\" onclick=\"closeM('modal-pwd')\">✕<\/button><\/div><div class=\"mb\"><div class=\"fg\"><label class=\"fl\">用户<\/label><input class=\"fi\" value=\"张三\" disabled><\/div><div class=\"fg\"><label class=\"fl\">新密码 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" type=\"password\" placeholder=\"至少6位\"><\/div><div class=\"fg\"><label class=\"fl\">确认密码 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" type=\"password\" placeholder=\"再次输入\"><\/div><\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-pwd')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-pwd');showT('✅ 密码已重置','ok')\">确认重置<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div>\n<div class=\"ni\">· 组织架构<\/div>\n<div class=\"ni\">· 菜单管理<\/div>\n<div class=\"ni\">· 角色管理<\/div>\n<div class=\"ni ac\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni\">· 操作日志<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>🔐 权限管理 / <b style=\"color:var(--txt)\">用户管理<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">用户管理<\/h1>\n<p class=\"pd\">用户CRUD · 部门角色绑定(多角色)· 切换部门自动清空角色(RB-08) · 额外产品授权<\/p>\n\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索用户名/工号\" id=\"searchInput\" oninput=\"filterTable()\"><\/div>\n<select class=\"sl\" id=\"filterDept\" onchange=\"filterTable()\"><option value=\"\">全部部门<\/option><option value=\"投放部\">投放部<\/option><option value=\"运营部\">运营部<\/option><option value=\"技术部\">技术部<\/option><option value=\"产品部\">产品部<\/option><\/select>\n<select class=\"sl\" id=\"filterRole\" onchange=\"filterTable()\"><option value=\"\">全部角色<\/option><option value=\"投放主管\">投放主管<\/option><option value=\"投放专员\">投放专员<\/option><option value=\"运营主管\">运营主管<\/option><option value=\"开发工程师\">开发工程师<\/option><\/select>\n<select class=\"sl\" id=\"filterStatus\" onchange=\"filterTable()\"><option value=\"\">全部状态<\/option><option value=\"启用\">启用<\/option><option value=\"禁用\">禁用<\/option><\/select>\n<button class=\"btn btn-g btn-sm\">导出<\/button>\n<button class=\"btn btn-p\" style=\"margin-left:auto\" onclick=\"openAdd()\">+ 新增用户<\/button>\n<\/div>\n\n<div class=\"tw\"><table id=\"userTable\">\n<thead><tr><th><input type=\"checkbox\" onclick=\"toggleAll(this)\"><\/th><th>用户名<\/th><th>工号<\/th><th>所属部门<\/th><th>角色<\/th><th>平台产品账号<\/th><th>额外授权<\/th><th>状态<\/th><th>创建时间<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody id=\"tbody\">\n<tr data-dept=\"投放部\" data-role=\"投放主管\" data-status=\"启用\" data-name=\"张三\"><td><input type=\"checkbox\"><\/td><td><b>张三<\/b><\/td><td>EMP001<\/td><td><span class=\"tg tg-i\">投放部<\/span> / 投放一组<\/td><td><span class=\"tg tg-p\">投放主管<\/span><\/td><td><span class=\"tg tg-g\">3个<\/span><\/td><td>-<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2024-03-01<\/td><td><button class=\"btn-l\" onclick=\"openEdit('张三','投放部','投放主管')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-pwd')\">重置密码<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-dept=\"投放部\" data-role=\"投放专员\" data-status=\"启用\" data-name=\"李四\"><td><input type=\"checkbox\"><\/td><td><b>李四<\/b><\/td><td>EMP002<\/td><td><span class=\"tg tg-i\">投放部<\/span> / 投放一组<\/td><td><span class=\"tg tg-i\">投放专员<\/span><\/td><td><span class=\"tg tg-g\">2个<\/span><\/td><td>-<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2024-06-15<\/td><td><button class=\"btn-l\" onclick=\"openEdit('李四','投放部','投放专员')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-pwd')\">重置密码<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-dept=\"投放部\" data-role=\"投放专员\" data-status=\"启用\" data-name=\"王五\"><td><input type=\"checkbox\"><\/td><td><b>王五<\/b><\/td><td>EMP003<\/td><td><span class=\"tg tg-i\">投放部<\/span> / 投放二组<\/td><td><span class=\"tg tg-i\">投放专员<\/span><\/td><td><span class=\"tg tg-g\">1个<\/span><\/td><td>-<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2024-08-20<\/td><td><button class=\"btn-l\" onclick=\"openEdit('王五','投放部','投放专员')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-pwd')\">重置密码<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-dept=\"投放部\" data-role=\"投放主管\" data-status=\"启用\" data-name=\"赵六\"><td><input type=\"checkbox\"><\/td><td><b>赵六<\/b><\/td><td>EMP004<\/td><td><span class=\"tg tg-i\">投放部<\/span> / 投放二组<\/td><td><span class=\"tg tg-p\">投放主管<\/span> <span class=\"tg tg-i\">数据分析师<\/span><\/td><td><span class=\"tg tg-g\">4个<\/span><\/td><td><span class=\"tg tg-w\">1项<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2024-02-10<\/td><td><button class=\"btn-l\" onclick=\"openEdit('赵六','投放部','投放主管')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-pwd')\">重置密码<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-dept=\"运营部\" data-role=\"运营主管\" data-status=\"启用\" data-name=\"钱七\"><td><input type=\"checkbox\"><\/td><td><b>钱七<\/b><\/td><td>EMP005<\/td><td><span class=\"tg tg-p\">运营部<\/span> / 内容运营组<\/td><td><span class=\"tg tg-p\">运营主管<\/span><\/td><td><span class=\"tg tg-g\">2个<\/span><\/td><td>-<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2025-01-05<\/td><td><button class=\"btn-l\" onclick=\"openEdit('钱七','运营部','运营主管')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-pwd')\">重置密码<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-dept=\"技术部\" data-role=\"开发工程师\" data-status=\"启用\" data-name=\"孙八\"><td><input type=\"checkbox\"><\/td><td><b>孙八<\/b><\/td><td>EMP006<\/td><td><span class=\"tg tg-w\">技术部<\/span> / 后端组<\/td><td><span class=\"tg tg-i\">开发工程师<\/span><\/td><td><span class=\"tg tg-g\">0个<\/span><\/td><td>-<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2025-03-18<\/td><td><button class=\"btn-l\" onclick=\"openEdit('孙八','技术部','开发工程师')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-pwd')\">重置密码<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-dept=\"产品部\" data-role=\"产品经理\" data-status=\"禁用\" data-name=\"周九\"><td><input type=\"checkbox\"><\/td><td><b>周九<\/b><\/td><td>EMP007<\/td><td><span class=\"tg tg-g\">产品部<\/span><\/td><td><span class=\"tg tg-g\">产品经理<\/span><\/td><td><span class=\"tg tg-g\">1个<\/span><\/td><td>-<\/td><td><span class=\"tg tg-e\">禁用<\/span><\/td><td>2025-04-01<\/td><td><button class=\"btn-l\" onclick=\"openEdit('周九','产品部','产品经理')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-pwd')\">重置密码<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<\/tbody>\n<\/table><\/div>\n<div class=\"pg\"><span id=\"pgInfo\">共 7 条,每页 10 条<\/span><div><span class=\"pgb ac\">1<\/span><\/div><\/div>\n\n<div class=\"card\" style=\"margin-top:16px;border:2px dashed var(--pri)\">\n<div style=\"font-size:13px;font-weight:600;margin-bottom:8px\">💡 业务规则说明<\/div>\n<div style=\"font-size:11px;color:var(--sub);line-height:2\">\n<b>RB-02<\/b> 用户只能绑定本部门角色:user.org_id === role.org_id<br>\n<b>RB-03<\/b> 支持多角色:用户可绑定本部门下多个角色<br>\n<b>RB-04<\/b> 多角色权限取并集:有效权限 = ∪所有角色权限<br>\n<b>RB-08<\/b> 切换部门清空角色:切换部门时自动清空原有角色绑定,需重新选择<br>\n<b>额外授权<\/b> 跨组协作产品授权,设置有效期\n<\/div><\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nconst DEPT_ROLES={tf:['投放主管','投放专员','数据分析师'],yy:['运营主管','运营专员'],tech:['开发工程师','运维工程师','测试工程师'],pm:['产品经理','UI设计师']};\nlet selectedRoles=[];\n\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\n\nfunction openAdd(){\n document.getElementById('muTitle').textContent='新增用户';\n document.getElementById('mu-name').value='';\n document.getElementById('mu-pwd').value='';\n document.getElementById('mu-dept').value='';\n selectedRoles=[];renderRoles();\n document.getElementById('rolePlaceholder').textContent='请先选择部门';\n openM('modal-user');\n}\n\nfunction openEdit(name,dept,role){\n document.getElementById('muTitle').textContent='编辑用户 — '+name;\n document.getElementById('mu-name').value=name;\n document.getElementById('mu-pwd').value='••••••';\n const deptMap={'投放部':'tf','运营部':'yy','技术部':'tech','产品部':'pm'};\n document.getElementById('mu-dept').value=deptMap[dept]||'';\n onDeptChange(deptMap[dept]||'');\n selectedRoles=[role];renderRoles();\n openM('modal-user');\n}\n\nfunction onDeptChange(val){\n selectedRoles=[];\n const drop=document.getElementById('roleDrop');\n const ph=document.getElementById('rolePlaceholder');\n if(!val){drop.innerHTML='';ph.textContent='请先选择部门';ph.style.display='';renderRoles();return}\n ph.style.display='none';\n const roles=DEPT_ROLES[val]||[];\n drop.innerHTML=roles.map(r=>`<div class=\"ms-opt\" onclick=\"toggleRole('${r}')\">${r}<\/div>`).join('');\n renderRoles();\n showT('⚠️ 已切换部门,角色已清空(RB-08)','er');\n}\n\nfunction toggleDrop(id){\n const d=document.getElementById(id);\n if(!document.getElementById('mu-dept').value){showT('请先选择部门','er');return}\n d.classList.toggle('show');\n}\n\nfunction toggleRole(r){\n const i=selectedRoles.indexOf(r);\n if(i>=0)selectedRoles.splice(i,1);else selectedRoles.push(r);\n renderRoles();\n}\n\nfunction removeRole(r){\n selectedRoles=selectedRoles.filter(x=>x!==r);renderRoles();\n}\n\nfunction renderRoles(){\n const sel=document.getElementById('roleSelect');\n const ph=document.getElementById('rolePlaceholder');\n sel.querySelectorAll('.ms-tag').forEach(t=>t.remove());\n if(selectedRoles.length===0){ph.style.display='';if(document.getElementById('mu-dept').value)ph.textContent='点击选择角色(可多选)'}\n else{ph.style.display='none';selectedRoles.forEach(r=>{const t=document.createElement('span');t.className='ms-tag';t.innerHTML=r+` <span class=\"ms-x\" onclick=\"event.stopPropagation();removeRole('${r}')\">×<\/span>`;sel.insertBefore(t,ph)})}\n document.querySelectorAll('#roleDrop .ms-opt').forEach(o=>{const n=o.textContent.replace('✓ ','');o.classList.toggle('sel',selectedRoles.includes(n));o.innerHTML=(selectedRoles.includes(n)?'✓ ':'')+n});\n}\n\nfunction saveUser(){\n const name=document.getElementById('mu-name').value;\n const dept=document.getElementById('mu-dept').value;\n if(!name){showT('请输入用户名','er');return}\n if(!dept){showT('请选择部门','er');return}\n if(!selectedRoles.length){showT('请至少选择一个角色','er');return}\n closeM('modal-user');showT('✅ 保存成功','ok');\n}\n\nfunction addGrant(){\n const list=document.getElementById('grantList');\n const row=document.createElement('div');row.className='grant-row';\n row.innerHTML=`<select class=\"fs\" style=\"width:200px\"><option>ProductC — 社交媒体矩阵<\/option><option>ProductD — 搜索引擎营销<\/option><option>ProductE — 内容营销平台<\/option><\/select><input class=\"fi\" type=\"date\" style=\"width:150px\"><button class=\"btn btn-d btn-sm\" onclick=\"this.closest('.grant-row').remove()\">删除<\/button>`;\n list.appendChild(row);\n}\n\nfunction filterTable(){\n const q=document.getElementById('searchInput').value.toLowerCase();\n const dept=document.getElementById('filterDept').value;\n const role=document.getElementById('filterRole').value;\n const status=document.getElementById('filterStatus').value;\n let count=0;\n document.querySelectorAll('#tbody tr').forEach(tr=>{\n const n=tr.dataset.name.toLowerCase();\n const d=tr.dataset.dept;\n const r=tr.dataset.role;\n const s=tr.dataset.status;\n const show=(!q||n.includes(q))&&(!dept||d===dept)&&(!role||r.includes(role))&&(!status||s===status);\n tr.style.display=show?'':'none';\n if(show)count++;\n });\n document.getElementById('pgInfo').textContent=`共 ${count} 条,每页 10 条`;\n}\n\nfunction toggleAll(cb){document.querySelectorAll('#tbody input[type=checkbox]').forEach(c=>c.checked=cb.checked)}\n\n// Close dropdowns on outside click\ndocument.addEventListener('click',e=>{if(!e.target.closest('#roleSelectWrap'))document.getElementById('roleDrop').classList.remove('show')});\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>\n",
"06_产品管理.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 产品管理<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.card{background:var(--card);border-radius:10px;padding:16px;border:1px solid var(--bdr);margin-bottom:14px}\n.tb{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:120px}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}.btn-s{background:var(--ok);color:#fff}.btn-w{background:var(--warn);color:#fff}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-g{background:#f1f5f9;color:#64748b}.tg-w{background:#fef3c7;color:#92400e}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px;position:sticky;top:0}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}.fl .rq{color:var(--err)}.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none;transition:border .12s}.fi:focus{border-color:var(--pri);box-shadow:0 0 0 2px rgba(99,102,241,.1)}.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:680px;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2);animation:mIn .2s}@keyframes mIn{from{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}.toast.wn{background:#fef3c7;color:#92400e}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.pg{display:flex;align-items:center;justify-content:space-between;padding:10px 0;font-size:12px;color:var(--sub)}.pgb{padding:4px 10px;border:1px solid var(--bdr);border-radius:5px;font-size:11px;cursor:pointer;background:var(--card);margin:0 2px}.pgb.ac{background:var(--pri);color:#fff;border-color:var(--pri)}\n.tabs{display:flex;gap:0;border-bottom:2px solid var(--bdr);margin-bottom:16px}.tab{padding:8px 16px;font-size:12px;font-weight:500;color:var(--sub);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px}.tab.ac{color:var(--pri);border-bottom-color:var(--pri);font-weight:600}.tab:hover{color:var(--txt)}\n.stat{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}.stat-c{background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px 16px}.stat-c .sv{font-size:22px;font-weight:700;color:var(--txt)}.stat-c .sl2{font-size:11px;color:var(--sub)}\n.note{background:#eff6ff;border-left:3px solid var(--pri);padding:8px 12px;border-radius:0 6px 6px 0;font-size:11px;color:var(--sub);margin-bottom:14px}\n.import-zone{border:2px dashed var(--bdr);border-radius:10px;padding:30px;text-align:center;cursor:pointer;transition:border .2s}.import-zone:hover{border-color:var(--pri);background:#f8fafc}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<!-- Modal: 新增/编辑产品 -->\n<div class=\"mo\" id=\"modal-prod\"><div class=\"mc\"><div class=\"mh\"><h3 id=\"mpTitle\">新增产品<\/h3><button class=\"mx\" onclick=\"closeM('modal-prod')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">产品名称 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mp-name\" placeholder=\"请输入产品名称\"><\/div>\n<div class=\"fg\"><label class=\"fl\">产品代号 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mp-code\" placeholder=\"如 PROD001,唯一\"><\/div>\n<\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">所属平台 <span class=\"rq\">*<\/span><\/label>\n<select class=\"fs\" id=\"mp-platform\"><option value=\"\">请选择平台<\/option><option value=\"xhs\">小红书<\/option><option value=\"dy\">抖音<\/option><option value=\"wx\">微信公众号<\/option><option value=\"wb\">微博<\/option><option value=\"fb\">Facebook<\/option><option value=\"tt\">TikTok<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">所属部门 <span class=\"rq\">*<\/span><\/label>\n<select class=\"fs\" id=\"mp-dept\"><option value=\"\">请选择部门<\/option><option>投放部<\/option><option>运营部<\/option><option>技术部<\/option><\/select><\/div>\n<\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">所属小组<\/label>\n<select class=\"fs\" id=\"mp-team\"><option value=\"\">请选择小组<\/option><option>投放一组<\/option><option>投放二组<\/option><option>内容运营组<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">负责人<\/label>\n<select class=\"fs\"><option value=\"\">请选择<\/option><option>张三<\/option><option>李四<\/option><option>王五<\/option><\/select><\/div>\n<\/div>\n<div class=\"note\">⚠️ RB-09: 内导渠道码和自然渠道码必填且唯一<\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">内导渠道码 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mp-ic\" placeholder=\"如 IC20240301A,唯一\"><\/div>\n<div class=\"fg\"><label class=\"fl\">自然渠道码 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mp-nc\" placeholder=\"如 NC20240301A,唯一\"><\/div>\n<\/div>\n<div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>禁用<\/option><\/select><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-prod')\">取消<\/button><button class=\"btn btn-p\" onclick=\"saveProd()\">保存<\/button><\/div><\/div><\/div>\n\n<!-- Modal: 导入 -->\n<div class=\"mo\" id=\"modal-import\"><div class=\"mc\" style=\"max-width:520px\"><div class=\"mh\"><h3>📤 批量导入产品<\/h3><button class=\"mx\" onclick=\"closeM('modal-import')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"import-zone\" onclick=\"document.getElementById('fileInput').click()\">\n<div style=\"font-size:36px;margin-bottom:8px\">📂<\/div>\n<p style=\"font-weight:600;font-size:13px\">点击上传 或 拖拽文件到此处<\/p>\n<p style=\"font-size:11px;color:var(--sub);margin-top:4px\">支持 .csv / .xlsx,最大10MB<\/p>\n<input type=\"file\" id=\"fileInput\" accept=\".csv,.xlsx\" style=\"display:none\" onchange=\"onFileSelect(this)\">\n<\/div>\n<div id=\"fileInfo\" style=\"display:none;margin-top:12px;padding:10px;background:#f8fafc;border-radius:7px;font-size:12px\">\n<div style=\"display:flex;justify-content:space-between;align-items:center\"><span id=\"fileName\"><\/span><button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"clearFile()\">移除<\/button><\/div>\n<div style=\"margin-top:8px;padding:8px;background:#ecfdf5;border-radius:5px;font-size:11px;color:#166534\" id=\"previewInfo\"><\/div>\n<\/div>\n<div style=\"margin-top:12px\"><a href=\"#\" class=\"btn-l\" onclick=\"event.preventDefault();showT('📥 模板已下载','ok')\">📥 下载导入模板<\/a><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-import')\">取消<\/button><button class=\"btn btn-p\" id=\"importBtn\" disabled onclick=\"doImport()\">开始导入<\/button><\/div><\/div><\/div>\n\n<!-- Modal: 确认删除 -->\n<div class=\"mo\" id=\"modal-del\"><div class=\"mc\" style=\"max-width:400px\"><div class=\"mh\"><h3>⚠️ 确认删除<\/h3><button class=\"mx\" onclick=\"closeM('modal-del')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:24px\"><div style=\"font-size:40px;margin-bottom:10px\">🗑️<\/div><p style=\"font-size:14px;font-weight:600;margin-bottom:6px\" id=\"delMsg\">确定要删除该产品吗?<\/p><p style=\"font-size:12px;color:var(--sub)\">删除后关联的渠道码绑定将同步解除<\/p><\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-del')\">取消<\/button><button class=\"btn btn-d\" onclick=\"closeM('modal-del');showT('✅ 已删除','ok')\">确认删除<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni ac\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni\">· 操作日志<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>📦 产品管理 / <b style=\"color:var(--txt)\">产品列表<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">产品管理<\/h1>\n<p class=\"pd\">产品CRUD · 内导/自然渠道码 · CSV/Excel批量导入 · 按平台/部门/小组筛选<\/p>\n\n<div class=\"stat\">\n<div class=\"stat-c\"><div class=\"sv\">156<\/div><div class=\"sl2\">产品总数<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--ok)\">142<\/div><div class=\"sl2\">启用中<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--err)\">14<\/div><div class=\"sl2\">已禁用<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--pri)\">6<\/div><div class=\"sl2\">平台数<\/div><\/div>\n<\/div>\n\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索产品名称/代号/渠道码\" id=\"sInput\" oninput=\"filterT()\"><\/div>\n<select class=\"sl\" id=\"fPlat\" onchange=\"filterT()\"><option value=\"\">全部平台<\/option><option value=\"小红书\">小红书<\/option><option value=\"抖音\">抖音<\/option><option value=\"微信公众号\">微信公众号<\/option><option value=\"微博\">微博<\/option><option value=\"Facebook\">Facebook<\/option><option value=\"TikTok\">TikTok<\/option><\/select>\n<select class=\"sl\" id=\"fDept\" onchange=\"filterT()\"><option value=\"\">全部部门<\/option><option value=\"投放部\">投放部<\/option><option value=\"运营部\">运营部<\/option><\/select>\n<select class=\"sl\" id=\"fSt\" onchange=\"filterT()\"><option value=\"\">全部状态<\/option><option value=\"启用\">启用<\/option><option value=\"禁用\">禁用<\/option><\/select>\n<button class=\"btn btn-g btn-sm\" onclick=\"showT('📥 导出成功','ok')\">导出<\/button>\n<button class=\"btn btn-w btn-sm\" onclick=\"openM('modal-import')\">📤 导入<\/button>\n<button class=\"btn btn-p\" style=\"margin-left:auto\" onclick=\"openAdd()\">+ 新增产品<\/button>\n<\/div>\n\n<div class=\"tw\"><table>\n<thead><tr><th><input type=\"checkbox\" onclick=\"document.querySelectorAll('#ptb input[type=checkbox]').forEach(c=>c.checked=this.checked)\"><\/th><th>产品名称<\/th><th>产品代号<\/th><th>平台<\/th><th>部门/小组<\/th><th>内导渠道码<\/th><th>自然渠道码<\/th><th>负责人<\/th><th>状态<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody id=\"ptb\">\n<tr data-plat=\"小红书\" data-dept=\"投放部\" data-st=\"启用\" data-q=\"美妆种草达人 PROD001 IC001 NC001\"><td><input type=\"checkbox\"><\/td><td><b>美妆种草达人<\/b><\/td><td>PROD001<\/td><td><span class=\"tg tg-e\" style=\"background:#ffe4e6;color:#be123c\">小红书<\/span><\/td><td>投放部 / 投放一组<\/td><td><code>IC001<\/code><\/td><td><code>NC001<\/code><\/td><td>张三<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('美妆种草达人','PROD001','IC001','NC001')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"小红书\" data-dept=\"投放部\" data-st=\"启用\" data-q=\"护肤品评测 PROD002 IC002 NC002\"><td><input type=\"checkbox\"><\/td><td><b>护肤品评测<\/b><\/td><td>PROD002<\/td><td><span class=\"tg tg-e\" style=\"background:#ffe4e6;color:#be123c\">小红书<\/span><\/td><td>投放部 / 投放一组<\/td><td><code>IC002<\/code><\/td><td><code>NC002<\/code><\/td><td>张三<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('护肤品评测','PROD002','IC002','NC002')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"抖音\" data-dept=\"投放部\" data-st=\"启用\" data-q=\"抖音带货王 PROD003 IC003 NC003\"><td><input type=\"checkbox\"><\/td><td><b>抖音带货王<\/b><\/td><td>PROD003<\/td><td><span class=\"tg tg-i\">抖音<\/span><\/td><td>投放部 / 投放二组<\/td><td><code>IC003<\/code><\/td><td><code>NC003<\/code><\/td><td>王五<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('抖音带货王','PROD003','IC003','NC003')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"抖音\" data-dept=\"运营部\" data-st=\"启用\" data-q=\"短视频营销 PROD004 IC004 NC004\"><td><input type=\"checkbox\"><\/td><td><b>短视频营销<\/b><\/td><td>PROD004<\/td><td><span class=\"tg tg-i\">抖音<\/span><\/td><td>运营部 / 内容运营组<\/td><td><code>IC004<\/code><\/td><td><code>NC004<\/code><\/td><td>钱七<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('短视频营销','PROD004','IC004','NC004')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"微信公众号\" data-dept=\"运营部\" data-st=\"启用\" data-q=\"品牌公众号 PROD005 IC005 NC005\"><td><input type=\"checkbox\"><\/td><td><b>品牌公众号<\/b><\/td><td>PROD005<\/td><td><span class=\"tg tg-ok\" style=\"background:#dcfce7;color:#166534\">微信公众号<\/span><\/td><td>运营部 / 内容运营组<\/td><td><code>IC005<\/code><\/td><td><code>NC005<\/code><\/td><td>钱七<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('品牌公众号','PROD005','IC005','NC005')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"Facebook\" data-dept=\"投放部\" data-st=\"启用\" data-q=\"海外社媒投放 PROD006 IC006 NC006\"><td><input type=\"checkbox\"><\/td><td><b>海外社媒投放<\/b><\/td><td>PROD006<\/td><td><span class=\"tg tg-p\">Facebook<\/span><\/td><td>投放部 / 投放二组<\/td><td><code>IC006<\/code><\/td><td><code>NC006<\/code><\/td><td>赵六<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('海外社媒投放','PROD006','IC006','NC006')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"TikTok\" data-dept=\"投放部\" data-st=\"禁用\" data-q=\"TikTok达人推广 PROD007 IC007 NC007\"><td><input type=\"checkbox\"><\/td><td><b>TikTok达人推广<\/b><\/td><td>PROD007<\/td><td><span class=\"tg tg-w\">TikTok<\/span><\/td><td>投放部 / 投放一组<\/td><td><code>IC007<\/code><\/td><td><code>NC007<\/code><\/td><td>李四<\/td><td><span class=\"tg tg-e\">禁用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('TikTok达人推广','PROD007','IC007','NC007')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"微博\" data-dept=\"运营部\" data-st=\"启用\" data-q=\"微博话题营销 PROD008 IC008 NC008\"><td><input type=\"checkbox\"><\/td><td><b>微博话题营销<\/b><\/td><td>PROD008<\/td><td><span class=\"tg tg-w\" style=\"background:#fef3c7;color:#92400e\">微博<\/span><\/td><td>运营部<\/td><td><code>IC008<\/code><\/td><td><code>NC008<\/code><\/td><td>钱七<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('微博话题营销','PROD008','IC008','NC008')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<\/tbody>\n<\/table><\/div>\n<div class=\"pg\"><span id=\"pgi\">共 8 条,每页 10 条<\/span><div><span class=\"pgb ac\">1<\/span><\/div><\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\n\nfunction openAdd(){\n document.getElementById('mpTitle').textContent='新增产品';\n document.getElementById('mp-name').value='';\n document.getElementById('mp-code').value='';\n document.getElementById('mp-ic').value='';\n document.getElementById('mp-nc').value='';\n document.getElementById('mp-platform').value='';\n document.getElementById('mp-dept').value='';\n openM('modal-prod');\n}\n\nfunction openEdit(name,code,ic,nc){\n document.getElementById('mpTitle').textContent='编辑产品 — '+name;\n document.getElementById('mp-name').value=name;\n document.getElementById('mp-code').value=code;\n document.getElementById('mp-ic').value=ic;\n document.getElementById('mp-nc').value=nc;\n openM('modal-prod');\n}\n\nfunction saveProd(){\n const n=document.getElementById('mp-name').value;\n const c=document.getElementById('mp-code').value;\n const ic=document.getElementById('mp-ic').value;\n const nc=document.getElementById('mp-nc').value;\n if(!n){showT('请输入产品名称','er');return}\n if(!c){showT('请输入产品代号','er');return}\n if(!ic){showT('内导渠道码必填(RB-09)','er');return}\n if(!nc){showT('自然渠道码必填(RB-09)','er');return}\n closeM('modal-prod');showT('✅ 保存成功','ok');\n}\n\nfunction filterT(){\n const q=document.getElementById('sInput').value.toLowerCase();\n const plat=document.getElementById('fPlat').value;\n const dept=document.getElementById('fDept').value;\n const st=document.getElementById('fSt').value;\n let c=0;\n document.querySelectorAll('#ptb tr').forEach(tr=>{\n const d=tr.dataset;\n const show=(!q||d.q.toLowerCase().includes(q))&&(!plat||d.plat===plat)&&(!dept||d.dept===dept)&&(!st||d.st===st);\n tr.style.display=show?'':'none';if(show)c++;\n });\n document.getElementById('pgi').textContent=`共 ${c} 条,每页 10 条`;\n}\n\nfunction onFileSelect(input){\n if(input.files.length){\n document.getElementById('fileInfo').style.display='block';\n document.getElementById('fileName').textContent='📄 '+input.files[0].name+' ('+Math.round(input.files[0].size/1024)+'KB)';\n document.getElementById('previewInfo').textContent='✅ 预检通过:解析出 23 条数据,其中 2 条重复将覆盖';\n document.getElementById('importBtn').disabled=false;\n }\n}\nfunction clearFile(){\n document.getElementById('fileInfo').style.display='none';\n document.getElementById('fileInput').value='';\n document.getElementById('importBtn').disabled=true;\n}\nfunction doImport(){\n closeM('modal-import');showT('✅ 成功导入 21 条,覆盖 2 条','ok');\n}\n\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>\n",
"07_渠道码管理.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 渠道码管理<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.card{background:var(--card);border-radius:10px;padding:16px;border:1px solid var(--bdr);margin-bottom:14px}\n.tb{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:140px}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-w{background:#fef3c7;color:#92400e}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-g{background:#f1f5f9;color:#64748b}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}.fl .rq{color:var(--err)}.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none}.fi:focus{border-color:var(--pri)}.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:560px;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.pg{display:flex;align-items:center;justify-content:space-between;padding:10px 0;font-size:12px;color:var(--sub)}.pgb{padding:4px 10px;border:1px solid var(--bdr);border-radius:5px;font-size:11px;cursor:pointer;background:var(--card);margin:0 2px}.pgb.ac{background:var(--pri);color:#fff;border-color:var(--pri)}\n.tabs{display:flex;gap:0;border-bottom:2px solid var(--bdr);margin-bottom:16px}.tab{padding:10px 20px;font-size:13px;font-weight:500;color:var(--sub);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px}.tab.ac{color:var(--pri);border-bottom-color:var(--pri);font-weight:600}.tab:hover{color:var(--txt)}\n.stat{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}.stat-c{background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px 16px}.stat-c .sv{font-size:22px;font-weight:700}.stat-c .sl2{font-size:11px;color:var(--sub)}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<div class=\"mo\" id=\"modal-ch\"><div class=\"mc\"><div class=\"mh\"><h3 id=\"mcTitle\">新增渠道码<\/h3><button class=\"mx\" onclick=\"closeM('modal-ch')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">渠道码 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mc-code\" placeholder=\"如 IC20240301A\"><\/div>\n<div class=\"fg\"><label class=\"fl\">渠道名称 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mc-name\" placeholder=\"渠道名称\"><\/div>\n<\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">渠道类型 <span class=\"rq\">*<\/span><\/label><select class=\"fs\" id=\"mc-type\"><option>内导(internal)<\/option><option>自然(natural)<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>禁用<\/option><\/select><\/div>\n<\/div>\n<div class=\"fg\"><label class=\"fl\">备注<\/label><input class=\"fi\" placeholder=\"可选备注\"><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-ch')\">取消<\/button><button class=\"btn btn-p\" onclick=\"saveCh()\">保存<\/button><\/div><\/div><\/div>\n\n<div class=\"mo\" id=\"modal-bind\"><div class=\"mc\"><div class=\"mh\"><h3>🔗 渠道码绑定产品<\/h3><button class=\"mx\" onclick=\"closeM('modal-bind')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fg\"><label class=\"fl\">渠道码<\/label><input class=\"fi\" value=\"IC001 — 小红书内导A\" disabled><\/div>\n<div class=\"fg\"><label class=\"fl\">已绑定产品<\/label>\n<div id=\"bindList\">\n<div style=\"display:flex;align-items:center;gap:8px;padding:6px;background:#f8fafc;border-radius:6px;margin-bottom:6px;font-size:12px\"><span style=\"flex:1\">美妆种草达人 (PROD001)<\/span><span class=\"tg tg-ok\">已绑定<\/span><button class=\"btn-l\" style=\"color:var(--err);font-size:11px\" onclick=\"this.closest('div').remove();showT('已解绑','ok')\">解绑<\/button><\/div>\n<div style=\"display:flex;align-items:center;gap:8px;padding:6px;background:#f8fafc;border-radius:6px;margin-bottom:6px;font-size:12px\"><span style=\"flex:1\">护肤品评测 (PROD002)<\/span><span class=\"tg tg-ok\">已绑定<\/span><button class=\"btn-l\" style=\"color:var(--err);font-size:11px\" onclick=\"this.closest('div').remove();showT('已解绑','ok')\">解绑<\/button><\/div>\n<\/div><\/div>\n<div class=\"fg\"><label class=\"fl\">添加绑定<\/label>\n<div style=\"display:flex;gap:8px\"><select class=\"fs\" style=\"flex:1\"><option>PROD003 — 抖音带货王<\/option><option>PROD004 — 短视频营销<\/option><option>PROD005 — 品牌公众号<\/option><\/select><button class=\"btn btn-p btn-sm\" onclick=\"addBind()\">绑定<\/button><\/div>\n<\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-bind')\">关闭<\/button><\/div><\/div><\/div>\n\n<div class=\"mo\" id=\"modal-del\"><div class=\"mc\" style=\"max-width:400px\"><div class=\"mh\"><h3>⚠️ 确认删除<\/h3><button class=\"mx\" onclick=\"closeM('modal-del')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:20px\"><div style=\"font-size:36px;margin-bottom:8px\">🗑️<\/div><p style=\"font-size:13px;font-weight:600\">确定删除该渠道码?<\/p><p style=\"font-size:11px;color:var(--sub);margin-top:4px\">已绑定产品的渠道码需先解绑<\/p><\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-del')\">取消<\/button><button class=\"btn btn-d\" onclick=\"closeM('modal-del');showT('✅ 已删除','ok')\">确认删除<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni ac\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni\">· 操作日志<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>📦 产品管理 / <b style=\"color:var(--txt)\">渠道码管理<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">渠道码管理<\/h1>\n<p class=\"pd\">内导渠道码 + 自然渠道码独立管理 · 渠道码与产品关联绑定 · 关联产品统计<\/p>\n\n<div class=\"stat\">\n<div class=\"stat-c\"><div class=\"sv\">48<\/div><div class=\"sl2\">渠道码总数<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--pri)\">26<\/div><div class=\"sl2\">内导渠道码<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--ok)\">22<\/div><div class=\"sl2\">自然渠道码<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--warn)\">156<\/div><div class=\"sl2\">关联产品数<\/div><\/div>\n<\/div>\n\n<div class=\"tabs\" id=\"mainTabs\">\n<div class=\"tab ac\" onclick=\"switchTab(0)\">内导渠道码<\/div>\n<div class=\"tab\" onclick=\"switchTab(1)\">自然渠道码<\/div>\n<\/div>\n\n<!-- 内导渠道码 Tab -->\n<div class=\"tab-ct show\" id=\"tab0\">\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索渠道码/名称\" oninput=\"filterCh(0,this.value)\"><\/div>\n<select class=\"sl\" onchange=\"filterChSt(0,this.value)\"><option value=\"\">全部状态<\/option><option value=\"启用\">启用<\/option><option value=\"禁用\">禁用<\/option><\/select>\n<button class=\"btn btn-p\" style=\"margin-left:auto\" onclick=\"openAddCh('internal')\">+ 新增内导渠道码<\/button>\n<\/div>\n<div class=\"tw\"><table><thead><tr><th>渠道码<\/th><th>渠道名称<\/th><th>类型<\/th><th>关联产品数<\/th><th>状态<\/th><th>创建时间<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody class=\"chBody\" data-tab=\"0\">\n<tr data-q=\"IC001 小红书内导A\" data-st=\"启用\"><td><code>IC001<\/code><\/td><td>小红书内导A<\/td><td><span class=\"tg tg-i\">内导<\/span><\/td><td><b>3<\/b><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2024-01-15<\/td><td><button class=\"btn-l\" onclick=\"openEditCh('IC001','小红书内导A','internal')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-bind')\">绑定<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"IC002 小红书内导B\" data-st=\"启用\"><td><code>IC002<\/code><\/td><td>小红书内导B<\/td><td><span class=\"tg tg-i\">内导<\/span><\/td><td><b>2<\/b><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2024-02-20<\/td><td><button class=\"btn-l\" onclick=\"openEditCh('IC002','小红书内导B','internal')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-bind')\">绑定<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"IC003 抖音内导A\" data-st=\"启用\"><td><code>IC003<\/code><\/td><td>抖音内导A<\/td><td><span class=\"tg tg-i\">内导<\/span><\/td><td><b>5<\/b><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2024-03-10<\/td><td><button class=\"btn-l\" onclick=\"openEditCh('IC003','抖音内导A','internal')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-bind')\">绑定<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"IC004 微信内导A\" data-st=\"禁用\"><td><code>IC004<\/code><\/td><td>微信内导A<\/td><td><span class=\"tg tg-i\">内导<\/span><\/td><td><b>0<\/b><\/td><td><span class=\"tg tg-e\">禁用<\/span><\/td><td>2024-04-01<\/td><td><button class=\"btn-l\" onclick=\"openEditCh('IC004','微信内导A','internal')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-bind')\">绑定<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"IC005 Facebook内导A\" data-st=\"启用\"><td><code>IC005<\/code><\/td><td>Facebook内导A<\/td><td><span class=\"tg tg-i\">内导<\/span><\/td><td><b>1<\/b><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2024-05-15<\/td><td><button class=\"btn-l\" onclick=\"openEditCh('IC005','Facebook内导A','internal')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-bind')\">绑定<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<\/tbody><\/table><\/div>\n<\/div>\n\n<!-- 自然渠道码 Tab -->\n<div class=\"tab-ct\" id=\"tab1\" style=\"display:none\">\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索渠道码/名称\" oninput=\"filterCh(1,this.value)\"><\/div>\n<select class=\"sl\" onchange=\"filterChSt(1,this.value)\"><option value=\"\">全部状态<\/option><option value=\"启用\">启用<\/option><option value=\"禁用\">禁用<\/option><\/select>\n<button class=\"btn btn-p\" style=\"margin-left:auto\" onclick=\"openAddCh('natural')\">+ 新增自然渠道码<\/button>\n<\/div>\n<div class=\"tw\"><table><thead><tr><th>渠道码<\/th><th>渠道名称<\/th><th>类型<\/th><th>关联产品数<\/th><th>状态<\/th><th>创建时间<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody class=\"chBody\" data-tab=\"1\">\n<tr data-q=\"NC001 小红书自然A\" data-st=\"启用\"><td><code>NC001<\/code><\/td><td>小红书自然A<\/td><td><span class=\"tg tg-ok\">自然<\/span><\/td><td><b>4<\/b><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2024-01-15<\/td><td><button class=\"btn-l\" onclick=\"openEditCh('NC001','小红书自然A','natural')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-bind')\">绑定<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"NC002 抖音自然A\" data-st=\"启用\"><td><code>NC002<\/code><\/td><td>抖音自然A<\/td><td><span class=\"tg tg-ok\">自然<\/span><\/td><td><b>3<\/b><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2024-02-20<\/td><td><button class=\"btn-l\" onclick=\"openEditCh('NC002','抖音自然A','natural')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-bind')\">绑定<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"NC003 微博自然A\" data-st=\"启用\"><td><code>NC003<\/code><\/td><td>微博自然A<\/td><td><span class=\"tg tg-ok\">自然<\/span><\/td><td><b>1<\/b><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>2024-03-10<\/td><td><button class=\"btn-l\" onclick=\"openEditCh('NC003','微博自然A','natural')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-bind')\">绑定<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"NC004 TikTok自然A\" data-st=\"禁用\"><td><code>NC004<\/code><\/td><td>TikTok自然A<\/td><td><span class=\"tg tg-ok\">自然<\/span><\/td><td><b>0<\/b><\/td><td><span class=\"tg tg-e\">禁用<\/span><\/td><td>2024-04-05<\/td><td><button class=\"btn-l\" onclick=\"openEditCh('NC004','TikTok自然A','natural')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-bind')\">绑定<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<\/tbody><\/table><\/div>\n<\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\n\nfunction switchTab(i){\n document.querySelectorAll('#mainTabs .tab').forEach((t,j)=>{t.classList.toggle('ac',j===i)});\n document.querySelectorAll('.tab-ct').forEach((c,j)=>{c.style.display=j===i?'block':'none'});\n}\n\nfunction openAddCh(type){\n document.getElementById('mcTitle').textContent='新增'+(type==='internal'?'内导':'自然')+'渠道码';\n document.getElementById('mc-code').value='';\n document.getElementById('mc-name').value='';\n document.getElementById('mc-type').value=type==='internal'?'内导(internal)':'自然(natural)';\n openM('modal-ch');\n}\n\nfunction openEditCh(code,name,type){\n document.getElementById('mcTitle').textContent='编辑渠道码 — '+code;\n document.getElementById('mc-code').value=code;\n document.getElementById('mc-name').value=name;\n document.getElementById('mc-type').value=type==='internal'?'内导(internal)':'自然(natural)';\n openM('modal-ch');\n}\n\nfunction saveCh(){\n if(!document.getElementById('mc-code').value){showT('请输入渠道码','er');return}\n if(!document.getElementById('mc-name').value){showT('请输入渠道名称','er');return}\n closeM('modal-ch');showT('✅ 保存成功','ok');\n}\n\nfunction addBind(){\n const list=document.getElementById('bindList');\n const d=document.createElement('div');\n d.style.cssText='display:flex;align-items:center;gap:8px;padding:6px;background:#f8fafc;border-radius:6px;margin-bottom:6px;font-size:12px';\n d.innerHTML='<span style=\"flex:1\">新绑定产品<\/span><span class=\"tg tg-ok\">已绑定<\/span><button class=\"btn-l\" style=\"color:var(--err);font-size:11px\" onclick=\"this.closest(\\'div\\').remove();showT(\\'已解绑\\',\\'ok\\')\">解绑<\/button>';\n list.appendChild(d);\n showT('✅ 绑定成功','ok');\n}\n\nfunction filterCh(tab,q){\n q=q.toLowerCase();\n document.querySelectorAll(`.chBody[data-tab=\"${tab}\"] tr`).forEach(tr=>{\n tr.style.display=(!q||tr.dataset.q.toLowerCase().includes(q))?'':'none';\n });\n}\nfunction filterChSt(tab,st){\n document.querySelectorAll(`.chBody[data-tab=\"${tab}\"] tr`).forEach(tr=>{\n tr.style.display=(!st||tr.dataset.st===st)?'':'none';\n });\n}\n\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>\n",
"08_平台产品账号.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 平台产品账号管理<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.tb{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:150px}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}.btn-s{background:var(--ok);color:#fff}.btn-w{background:var(--warn);color:#fff}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-g{background:#f1f5f9;color:#64748b}.tg-w{background:#fef3c7;color:#92400e}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}.fl .rq{color:var(--err)}.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none}.fi:focus{border-color:var(--pri)}.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:620px;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}.toast.wn{background:#fef3c7;color:#92400e}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.pg{display:flex;align-items:center;justify-content:space-between;padding:10px 0;font-size:12px;color:var(--sub)}.pgb{padding:4px 10px;border:1px solid var(--bdr);border-radius:5px;font-size:11px;cursor:pointer;background:var(--card);margin:0 2px}.pgb.ac{background:var(--pri);color:#fff;border-color:var(--pri)}\n.stat{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}.stat-c{background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px 16px}.stat-c .sv{font-size:22px;font-weight:700}.stat-c .sl2{font-size:11px;color:var(--sub)}\n.note{background:#eff6ff;border-left:3px solid var(--pri);padding:8px 12px;border-radius:0 6px 6px 0;font-size:11px;color:var(--sub);margin-bottom:14px}\n.auto-fill{background:#f0fdf4;border:1px solid #bbf7d0;border-radius:7px;padding:8px 12px;font-size:12px;color:#166534}\n.pwd-wrap{position:relative}.pwd-toggle{position:absolute;right:10px;top:50%;transform:translateY(-50%);cursor:pointer;font-size:14px;background:none;border:none}\n.test-result{padding:8px 12px;border-radius:7px;font-size:12px;margin-top:8px;display:none}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<!-- Modal: 添加/编辑平台产品账号 -->\n<div class=\"mo\" id=\"modal-acc\"><div class=\"mc\"><div class=\"mh\"><h3 id=\"maTitle\">添加平台产品账号<\/h3><button class=\"mx\" onclick=\"closeM('modal-acc')\">✕<\/button><\/div><div class=\"mb\">\n\n<div class=\"note\">📋 表单联动:选择平台 → 自动带出地址 → 筛选该平台下产品 → 填写登录凭据<\/div>\n\n<div class=\"fg\"><label class=\"fl\">选择平台 <span class=\"rq\">*<\/span><\/label>\n<select class=\"fs\" id=\"ma-plat\" onchange=\"onPlatChange(this.value)\">\n<option value=\"\">请选择平台<\/option>\n<option value=\"xhs\">小红书<\/option>\n<option value=\"dy\">抖音<\/option>\n<option value=\"wx\">微信公众号<\/option>\n<option value=\"wb\">微博<\/option>\n<option value=\"fb\">Facebook<\/option>\n<option value=\"tt\">TikTok<\/option>\n<\/select><\/div>\n\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">平台名称<\/label><input class=\"fi auto-fill\" id=\"ma-platname\" readonly placeholder=\"选择平台后自动带出\"><\/div>\n<div class=\"fg\"><label class=\"fl\">平台地址<\/label><input class=\"fi auto-fill\" id=\"ma-platurl\" readonly placeholder=\"选择平台后自动带出\"><\/div>\n<\/div>\n\n<div class=\"fg\"><label class=\"fl\">产品代号 <span class=\"rq\">*<\/span><\/label>\n<select class=\"fs\" id=\"ma-product\" disabled>\n<option value=\"\">请先选择平台<\/option>\n<\/select>\n<div style=\"font-size:10px;color:var(--sub);margin-top:4px\" id=\"prodHint\">仅展示所选平台下且在您产品范围(data_scope)内的产品<\/div>\n<\/div>\n\n<hr style=\"border:none;border-top:1px solid var(--bdr);margin:16px 0\">\n<div style=\"font-size:13px;font-weight:600;margin-bottom:12px\">🔑 登录凭据<\/div>\n\n<div class=\"fg\"><label class=\"fl\">登录账号 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"ma-login\" placeholder=\"平台登录账号\"><\/div>\n\n<div class=\"fg\"><label class=\"fl\">登录密码 <span class=\"rq\">*<\/span><\/label>\n<div class=\"pwd-wrap\"><input class=\"fi\" id=\"ma-pwd\" type=\"password\" placeholder=\"平台登录密码\"><button class=\"pwd-toggle\" onclick=\"togglePwd('ma-pwd',this)\">👁️<\/button><\/div><\/div>\n\n<div class=\"fg\"><label class=\"fl\">谷歌密钥(二次验证)<\/label>\n<div class=\"pwd-wrap\"><input class=\"fi\" id=\"ma-gkey\" type=\"password\" placeholder=\"可选,谷歌二次验证密钥\"><button class=\"pwd-toggle\" onclick=\"togglePwd('ma-gkey',this)\">👁️<\/button><\/div>\n<div style=\"font-size:10px;color:var(--sub);margin-top:4px\">加密存储,展示时仅显示后4位<\/div><\/div>\n\n<div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>禁用<\/option><\/select><\/div>\n\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-acc')\">取消<\/button><button class=\"btn btn-s btn-sm\" onclick=\"testConn()\" style=\"margin-right:auto\">🔌 连通测试<\/button><button class=\"btn btn-p\" onclick=\"saveAcc()\">保存<\/button><\/div><\/div><\/div>\n\n<!-- Modal: 连通测试结果 -->\n<div class=\"mo\" id=\"modal-test\"><div class=\"mc\" style=\"max-width:420px\"><div class=\"mh\"><h3>🔌 连通测试<\/h3><button class=\"mx\" onclick=\"closeM('modal-test')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:20px\">\n<div id=\"testLoading\" style=\"display:none\"><div style=\"font-size:36px;animation:spin 1s linear infinite\">⏳<\/div><p style=\"margin-top:8px;font-size:13px\">正在测试连通性...<\/p><\/div>\n<div id=\"testOk\" style=\"display:none\"><div style=\"font-size:36px\">✅<\/div><p style=\"margin-top:8px;font-size:14px;font-weight:600;color:var(--ok)\">连通成功!<\/p><p style=\"font-size:12px;color:var(--sub);margin-top:4px\">账号验证通过,可以正常使用<\/p><\/div>\n<div id=\"testFail\" style=\"display:none\"><div style=\"font-size:36px\">❌<\/div><p style=\"margin-top:8px;font-size:14px;font-weight:600;color:var(--err)\">连通失败<\/p><p style=\"font-size:12px;color:var(--sub);margin-top:4px\">账号或密码错误,请检查后重试<\/p><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-test')\">关闭<\/button><\/div><\/div><\/div>\n\n<!-- Modal: 确认删除 -->\n<div class=\"mo\" id=\"modal-del\"><div class=\"mc\" style=\"max-width:400px\"><div class=\"mh\"><h3>⚠️ 确认删除<\/h3><button class=\"mx\" onclick=\"closeM('modal-del')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:20px\"><div style=\"font-size:36px;margin-bottom:8px\">🗑️<\/div><p style=\"font-size:13px;font-weight:600\">确定删除该平台产品账号?<\/p><p style=\"font-size:11px;color:var(--sub);margin-top:4px\">有运行中任务引用的账号不可删除<\/p><\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-del')\">取消<\/button><button class=\"btn btn-d\" onclick=\"closeM('modal-del');showT('✅ 已删除','ok')\">确认删除<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni ac\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni\">· 操作日志<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>🔐 平台产品账号 / <b style=\"color:var(--txt)\">账号管理<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>张三<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">张<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">平台产品账号管理<\/h1>\n<p class=\"pd\">v2.1变更:归属用户 · 选择平台→自动带出地址→选择产品代号→填写登录凭据 · 联动产品管理数据<\/p>\n\n<div class=\"note\">⚠️ <b>v2.1变更<\/b>:平台产品账号归属于<b>用户<\/b>(非角色),用户自行管理各平台的产品登录凭据。管理员可查看所有用户的账号。<\/div>\n\n<div class=\"stat\">\n<div class=\"stat-c\"><div class=\"sv\">12<\/div><div class=\"sl2\">我的账号总数<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--ok)\">10<\/div><div class=\"sl2\">启用中<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--err)\">2<\/div><div class=\"sl2\">已禁用<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--pri)\">4<\/div><div class=\"sl2\">覆盖平台<\/div><\/div>\n<\/div>\n\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索账号/产品代号\" id=\"sInput\" oninput=\"filterT()\"><\/div>\n<select class=\"sl\" id=\"fPlat\" onchange=\"filterT()\"><option value=\"\">全部平台<\/option><option value=\"小红书\">小红书<\/option><option value=\"抖音\">抖音<\/option><option value=\"Facebook\">Facebook<\/option><option value=\"TikTok\">TikTok<\/option><\/select>\n<select class=\"sl\" id=\"fSt\" onchange=\"filterT()\"><option value=\"\">全部状态<\/option><option value=\"启用\">启用<\/option><option value=\"禁用\">禁用<\/option><\/select>\n<button class=\"btn btn-p\" style=\"margin-left:auto\" onclick=\"openAdd()\">+ 添加平台产品账号<\/button>\n<\/div>\n\n<div class=\"tw\"><table>\n<thead><tr><th>平台<\/th><th>平台地址<\/th><th>产品代号<\/th><th>产品名称<\/th><th>登录账号<\/th><th>登录密码<\/th><th>谷歌密钥<\/th><th>状态<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody id=\"atb\">\n<tr data-plat=\"小红书\" data-st=\"启用\" data-q=\"xhs_user01 PROD001 美妆种草达人\"><td><span class=\"tg tg-e\" style=\"background:#ffe4e6;color:#be123c\">📕 小红书<\/span><\/td><td style=\"font-size:11px\">pro.xiaohongshu.com<\/td><td><code>PROD001<\/code><\/td><td>美妆种草达人<\/td><td>xhs_user01<\/td><td>••••••••<\/td><td>••••5A2F<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('小红书','PROD001','xhs_user01')\">编辑<\/button> <button class=\"btn-l\" onclick=\"doTest(true)\">测试<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"小红书\" data-st=\"启用\" data-q=\"xhs_user02 PROD002 护肤品评测\"><td><span class=\"tg tg-e\" style=\"background:#ffe4e6;color:#be123c\">📕 小红书<\/span><\/td><td style=\"font-size:11px\">pro.xiaohongshu.com<\/td><td><code>PROD002<\/code><\/td><td>护肤品评测<\/td><td>xhs_user02<\/td><td>••••••••<\/td><td>-<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('小红书','PROD002','xhs_user02')\">编辑<\/button> <button class=\"btn-l\" onclick=\"doTest(true)\">测试<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"抖音\" data-st=\"启用\" data-q=\"dy_admin01 PROD003 抖音带货王\"><td><span class=\"tg tg-i\">🎵 抖音<\/span><\/td><td style=\"font-size:11px\">business.douyin.com<\/td><td><code>PROD003<\/code><\/td><td>抖音带货王<\/td><td>dy_admin01<\/td><td>••••••••<\/td><td>••••8B3D<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('抖音','PROD003','dy_admin01')\">编辑<\/button> <button class=\"btn-l\" onclick=\"doTest(true)\">测试<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"抖音\" data-st=\"启用\" data-q=\"dy_ops02 PROD004 短视频营销\"><td><span class=\"tg tg-i\">🎵 抖音<\/span><\/td><td style=\"font-size:11px\">business.douyin.com<\/td><td><code>PROD004<\/code><\/td><td>短视频营销<\/td><td>dy_ops02<\/td><td>••••••••<\/td><td>-<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('抖音','PROD004','dy_ops02')\">编辑<\/button> <button class=\"btn-l\" onclick=\"doTest(false)\">测试<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"Facebook\" data-st=\"启用\" data-q=\"fb_ads_01 PROD006 海外社媒投放\"><td><span class=\"tg tg-p\">📘 Facebook<\/span><\/td><td style=\"font-size:11px\">business.facebook.com<\/td><td><code>PROD006<\/code><\/td><td>海外社媒投放<\/td><td>fb_ads_01<\/td><td>••••••••<\/td><td>••••C71E<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('Facebook','PROD006','fb_ads_01')\">编辑<\/button> <button class=\"btn-l\" onclick=\"doTest(true)\">测试<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-plat=\"TikTok\" data-st=\"禁用\" data-q=\"tt_creator PROD007 TikTok达人推广\"><td><span class=\"tg tg-w\">🎶 TikTok<\/span><\/td><td style=\"font-size:11px\">ads.tiktok.com<\/td><td><code>PROD007<\/code><\/td><td>TikTok达人推广<\/td><td>tt_creator<\/td><td>••••••••<\/td><td>-<\/td><td><span class=\"tg tg-e\">禁用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('TikTok','PROD007','tt_creator')\">编辑<\/button> <button class=\"btn-l\" onclick=\"doTest(false)\">测试<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<\/tbody>\n<\/table><\/div>\n<div class=\"pg\"><span>共 6 条<\/span><div><span class=\"pgb ac\">1<\/span><\/div><\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nconst PLAT_INFO={xhs:{name:'小红书',url:'pro.xiaohongshu.com',products:['PROD001 — 美妆种草达人','PROD002 — 护肤品评测']},dy:{name:'抖音',url:'business.douyin.com',products:['PROD003 — 抖音带货王','PROD004 — 短视频营销']},wx:{name:'微信公众号',url:'mp.weixin.qq.com',products:['PROD005 — 品牌公众号']},wb:{name:'微博',url:'weibo.com',products:['PROD008 — 微博话题营销']},fb:{name:'Facebook',url:'business.facebook.com',products:['PROD006 — 海外社媒投放']},tt:{name:'TikTok',url:'ads.tiktok.com',products:['PROD007 — TikTok达人推广']}};\n\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\n\nfunction onPlatChange(val){\n const info=PLAT_INFO[val];\n const nameF=document.getElementById('ma-platname');\n const urlF=document.getElementById('ma-platurl');\n const prodS=document.getElementById('ma-product');\n if(!info){nameF.value='';urlF.value='';prodS.innerHTML='<option value=\"\">请先选择平台<\/option>';prodS.disabled=true;return}\n nameF.value=info.name;\n urlF.value=info.url;\n prodS.disabled=false;\n prodS.innerHTML='<option value=\"\">请选择产品代号<\/option>'+info.products.map(p=>`<option>${p}<\/option>`).join('');\n showT('✅ 已加载 '+info.name+' 平台信息','ok');\n}\n\nfunction openAdd(){\n document.getElementById('maTitle').textContent='添加平台产品账号';\n document.getElementById('ma-plat').value='';\n document.getElementById('ma-platname').value='';\n document.getElementById('ma-platurl').value='';\n document.getElementById('ma-product').innerHTML='<option value=\"\">请先选择平台<\/option>';\n document.getElementById('ma-product').disabled=true;\n document.getElementById('ma-login').value='';\n document.getElementById('ma-pwd').value='';\n document.getElementById('ma-gkey').value='';\n openM('modal-acc');\n}\n\nfunction openEdit(plat,code,login){\n document.getElementById('maTitle').textContent='编辑平台产品账号';\n const platKey=Object.keys(PLAT_INFO).find(k=>PLAT_INFO[k].name===plat);\n if(platKey){\n document.getElementById('ma-plat').value=platKey;\n onPlatChange(platKey);\n }\n document.getElementById('ma-login').value=login;\n document.getElementById('ma-pwd').value='••••••••';\n document.getElementById('ma-gkey').value='';\n openM('modal-acc');\n}\n\nfunction saveAcc(){\n const plat=document.getElementById('ma-plat').value;\n const prod=document.getElementById('ma-product').value;\n const login=document.getElementById('ma-login').value;\n const pwd=document.getElementById('ma-pwd').value;\n if(!plat){showT('请选择平台','er');return}\n if(!prod){showT('请选择产品代号','er');return}\n if(!login){showT('请输入登录账号','er');return}\n if(!pwd){showT('请输入登录密码','er');return}\n closeM('modal-acc');showT('✅ 保存成功','ok');\n}\n\nfunction togglePwd(id,btn){\n const f=document.getElementById(id);\n if(f.type==='password'){f.type='text';btn.textContent='🙈'}\n else{f.type='password';btn.textContent='👁️'}\n}\n\nfunction doTest(success){\n openM('modal-test');\n document.getElementById('testLoading').style.display='block';\n document.getElementById('testOk').style.display='none';\n document.getElementById('testFail').style.display='none';\n setTimeout(()=>{\n document.getElementById('testLoading').style.display='none';\n if(success){document.getElementById('testOk').style.display='block'}\n else{document.getElementById('testFail').style.display='block'}\n },1500);\n}\n\nfunction testConn(){\n const plat=document.getElementById('ma-plat').value;\n const login=document.getElementById('ma-login').value;\n if(!plat||!login){showT('请先填写平台和账号信息','er');return}\n doTest(Math.random()>0.3);\n}\n\nfunction filterT(){\n const q=document.getElementById('sInput').value.toLowerCase();\n const plat=document.getElementById('fPlat').value;\n const st=document.getElementById('fSt').value;\n document.querySelectorAll('#atb tr').forEach(tr=>{\n const d=tr.dataset;\n const show=(!q||d.q.toLowerCase().includes(q))&&(!plat||d.plat===plat)&&(!st||d.st===st);\n tr.style.display=show?'':'none';\n });\n}\n\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<style>@keyframes spin{from{transform:rotate(0)}to{transform:rotate(360deg)}}<\/style>\n<\/body><\/html>\n",
"09_Skill管理.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - Skill管理<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.tb{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:140px}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}.btn-s{background:var(--ok);color:#fff}.btn-w{background:var(--warn);color:#fff}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-g{background:#f1f5f9;color:#64748b}.tg-w{background:#fef3c7;color:#92400e}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}.fl .rq{color:var(--err)}.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none}.fi:focus{border-color:var(--pri)}.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:720px;max-height:88vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.tabs{display:flex;gap:0;border-bottom:2px solid var(--bdr);margin-bottom:16px}.tab{padding:10px 20px;font-size:13px;font-weight:500;color:var(--sub);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px}.tab.ac{color:var(--pri);border-bottom-color:var(--pri);font-weight:600}.tab:hover{color:var(--txt)}\n.stat{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}.stat-c{background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px 16px}.stat-c .sv{font-size:22px;font-weight:700}.stat-c .sl2{font-size:11px;color:var(--sub)}\n.note{background:#eff6ff;border-left:3px solid var(--pri);padding:8px 12px;border-radius:0 6px 6px 0;font-size:11px;color:var(--sub);margin-bottom:14px}\n.exec-box{border:2px solid var(--bdr);border-radius:10px;padding:14px;margin-bottom:14px;transition:border .2s}.exec-box.active{border-color:var(--pri);background:#faf5ff}\n.exec-radio{display:flex;gap:12px;margin-bottom:14px}.er-item{flex:1;border:2px solid var(--bdr);border-radius:10px;padding:14px;cursor:pointer;text-align:center;transition:all .15s}.er-item:hover{border-color:#a5b4fc}.er-item.sel{border-color:var(--pri);background:#ede9fe}.er-item .er-icon{font-size:28px;margin-bottom:6px}.er-item .er-t{font-size:13px;font-weight:600}.er-item .er-d{font-size:10px;color:var(--sub)}\n.param-row{display:flex;gap:8px;align-items:center;padding:8px;border:1px solid var(--bdr);border-radius:6px;margin-bottom:6px;font-size:12px}\n.json-area{width:100%;min-height:100px;padding:10px;border:1px solid var(--bdr);border-radius:7px;font-size:11px;font-family:monospace;resize:vertical}\n.test-log{background:#1e293b;color:#a5f3fc;padding:12px;border-radius:8px;font-family:monospace;font-size:11px;max-height:200px;overflow-y:auto;margin-top:10px}\n.ms-wrap{position:relative}.multi-select{display:flex;flex-wrap:wrap;gap:4px;padding:6px 10px;border:1px solid var(--bdr);border-radius:7px;min-height:36px;cursor:pointer;font-size:11px}.ms-tag{background:#ede9fe;color:#6b21a8;padding:2px 6px;border-radius:3px;display:flex;align-items:center;gap:3px}.ms-tag .x{cursor:pointer;font-weight:700}.ms-drop{position:absolute;top:100%;left:0;right:0;background:var(--card);border:1px solid var(--bdr);border-radius:7px;box-shadow:0 4px 12px rgba(0,0,0,.1);z-index:10;max-height:180px;overflow-y:auto;display:none}.ms-drop.show{display:block}.ms-opt{padding:6px 10px;font-size:11px;cursor:pointer}.ms-opt:hover{background:#f1f5f9}.ms-opt.sel{background:#ede9fe}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<!-- Modal: 注册/编辑Skill -->\n<div class=\"mo\" id=\"modal-skill\"><div class=\"mc\"><div class=\"mh\"><h3 id=\"msTitle\">注册Skill<\/h3><button class=\"mx\" onclick=\"closeM('modal-skill')\">✕<\/button><\/div><div class=\"mb\">\n\n<div class=\"tabs\" id=\"skillTabs\"><div class=\"tab ac\" onclick=\"switchST(0)\">基本信息<\/div><div class=\"tab\" onclick=\"switchST(1)\">执行器配置<\/div><div class=\"tab\" onclick=\"switchST(2)\">产品范围<\/div><div class=\"tab\" onclick=\"switchST(3)\">参数映射<\/div><div class=\"tab\" onclick=\"switchST(4)\">测试台<\/div><\/div>\n\n<!-- Tab0: 基本信息 -->\n<div class=\"st-ct\" id=\"st0\">\n<div class=\"fr\"><div class=\"fg\"><label class=\"fl\">Skill名称 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"ms-name\" placeholder=\"如 小红书笔记发布\"><\/div>\n<div class=\"fg\"><label class=\"fl\">分类<\/label><select class=\"fs\"><option>内容发布<\/option><option>数据采集<\/option><option>账号运营<\/option><option>广告投放<\/option><option>数据分析<\/option><\/select><\/div><\/div>\n<div class=\"fg\"><label class=\"fl\">描述<\/label><textarea class=\"fi\" rows=\"2\" placeholder=\"Skill功能描述\"><\/textarea><\/div>\n<div class=\"fg\"><label class=\"fl\">执行器类型 <span class=\"rq\">*<\/span> (RB-13)<\/label>\n<div class=\"exec-radio\"><div class=\"er-item sel\" onclick=\"selExec('lobster')\"><div class=\"er-icon\">🦞<\/div><div class=\"er-t\">龙虾执行器<\/div><div class=\"er-d\">第三方Agent平台<\/div><\/div><div class=\"er-item\" onclick=\"selExec('script')\"><div class=\"er-icon\">📜<\/div><div class=\"er-t\">脚本执行器<\/div><div class=\"er-d\">系统预置模板<\/div><\/div><\/div>\n<\/div><\/div>\n\n<!-- Tab1: 执行器配置 -->\n<div class=\"st-ct\" id=\"st1\" style=\"display:none\">\n<div id=\"lobsterConfig\">\n<div class=\"note\">🦞 龙虾执行器:配置第三方Agent平台连接参数<\/div>\n<div class=\"fg\"><label class=\"fl\">API地址 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" placeholder=\"https://api.lobster-agent.com/v1\" value=\"https://api.lobster-agent.com/v1\"><\/div>\n<div class=\"fr\"><div class=\"fg\"><label class=\"fl\">API Key <span class=\"rq\">*<\/span><\/label><input class=\"fi\" type=\"password\" value=\"sk-lobster-xxxx\" id=\"lob-key\"><\/div>\n<div class=\"fg\"><label class=\"fl\">Agent ID <span class=\"rq\">*<\/span><\/label><input class=\"fi\" placeholder=\"agent_xxx\" value=\"agent_xhs_publish_01\"><\/div><\/div>\n<button class=\"btn btn-s btn-sm\" onclick=\"showT('✅ 龙虾平台连通成功','ok')\">🔌 测试连通性<\/button>\n<\/div>\n<div id=\"scriptConfig\" style=\"display:none\">\n<div class=\"note\">📜 脚本执行器:选择系统预置脚本模板<\/div>\n<div class=\"fg\"><label class=\"fl\">脚本模板 <span class=\"rq\">*<\/span><\/label><select class=\"fs\" id=\"scriptTpl\" onchange=\"onScriptTpl(this.value)\"><option value=\"\">请选择<\/option><option value=\"py1\">Python - 通用HTTP请求<\/option><option value=\"py2\">Python - 数据清洗脚本<\/option><option value=\"sh1\">Shell - 文件处理<\/option><option value=\"node1\">Node.js - API调用<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">环境变量<\/label><div id=\"envVars\"><div class=\"param-row\"><input class=\"fi\" style=\"width:120px\" value=\"API_KEY\" readonly><input class=\"fi\" style=\"flex:1\" placeholder=\"变量值\"><button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"this.closest('.param-row').remove()\">✕<\/button><\/div><\/div><button class=\"btn btn-g btn-sm\" onclick=\"addEnv()\" style=\"margin-top:6px\">+ 添加变量<\/button><\/div>\n<div class=\"fr\"><div class=\"fg\"><label class=\"fl\">超时时间(秒)<\/label><input class=\"fi\" type=\"number\" value=\"30\"><\/div><div class=\"fg\"><label class=\"fl\">脚本类型<\/label><input class=\"fi\" value=\"python\" readonly id=\"scriptType\"><\/div><\/div>\n<\/div><\/div>\n\n<!-- Tab2: 产品范围 -->\n<div class=\"st-ct\" id=\"st2\" style=\"display:none\">\n<div class=\"note\">⚠️ Skill绑定产品范围,执行时 Skill.product_scope ∩ 用户角色.data_scope = 可用产品<\/div>\n<div class=\"fg\"><label class=\"fl\">绑定产品范围<\/label>\n<div class=\"ms-wrap\"><div class=\"multi-select\" id=\"prodSelect\" onclick=\"document.getElementById('prodDrop').classList.toggle('show')\"><span class=\"ms-tag\">PROD001 美妆种草达人 <span class=\"x\" onclick=\"event.stopPropagation();this.closest('.ms-tag').remove()\">×<\/span><\/span><span class=\"ms-tag\">PROD002 护肤品评测 <span class=\"x\" onclick=\"event.stopPropagation();this.closest('.ms-tag').remove()\">×<\/span><\/span><span class=\"ms-tag\">PROD003 抖音带货王 <span class=\"x\" onclick=\"event.stopPropagation();this.closest('.ms-tag').remove()\">×<\/span><\/span><\/div>\n<div class=\"ms-drop\" id=\"prodDrop\"><div class=\"ms-opt sel\" onclick=\"this.classList.toggle('sel')\">✓ PROD001 — 美妆种草达人<\/div><div class=\"ms-opt sel\" onclick=\"this.classList.toggle('sel')\">✓ PROD002 — 护肤品评测<\/div><div class=\"ms-opt sel\" onclick=\"this.classList.toggle('sel')\">✓ PROD003 — 抖音带货王<\/div><div class=\"ms-opt\" onclick=\"this.classList.toggle('sel')\">PROD004 — 短视频营销<\/div><div class=\"ms-opt\" onclick=\"this.classList.toggle('sel')\">PROD005 — 品牌公众号<\/div><div class=\"ms-opt\" onclick=\"this.classList.toggle('sel')\">PROD006 — 海外社媒投放<\/div><\/div><\/div><\/div>\n<\/div>\n\n<!-- Tab3: 参数映射 -->\n<div class=\"st-ct\" id=\"st3\" style=\"display:none\">\n<div class=\"fg\"><label class=\"fl\">inputSchema (JSON Schema)<\/label>\n<textarea class=\"json-area\" id=\"schemaArea\">{\n \"type\": \"object\",\n \"properties\": {\n \"product_id\": {\"type\": \"string\", \"title\": \"产品\", \"x-component\": \"ProductSelector\"},\n \"content\": {\"type\": \"string\", \"title\": \"发布内容\"},\n \"tags\": {\"type\": \"array\", \"title\": \"标签\", \"items\": {\"type\": \"string\"}}\n },\n \"required\": [\"product_id\", \"content\"]\n}<\/textarea><\/div>\n<div class=\"fg\"><label class=\"fl\">参数映射<\/label>\n<div id=\"paramMap\">\n<div class=\"param-row\"><span style=\"width:120px\">product_id<\/span><span>→<\/span><input class=\"fi\" style=\"flex:1\" value=\"{{product.code}}\"><select class=\"sl\" style=\"width:100px\"><option>表达式<\/option><option>常量<\/option><\/select><\/div>\n<div class=\"param-row\"><span style=\"width:120px\">content<\/span><span>→<\/span><input class=\"fi\" style=\"flex:1\" value=\"{{input.content}}\"><select class=\"sl\" style=\"width:100px\"><option>表达式<\/option><option>常量<\/option><\/select><\/div>\n<div class=\"param-row\"><span style=\"width:120px\">tags<\/span><span>→<\/span><input class=\"fi\" style=\"flex:1\" value=\"{{input.tags}}\"><select class=\"sl\" style=\"width:100px\"><option>表达式<\/option><option>常量<\/option><\/select><\/div>\n<\/div><\/div><\/div>\n\n<!-- Tab4: 测试台 -->\n<div class=\"st-ct\" id=\"st4\" style=\"display:none\">\n<div class=\"note\">⚠️ 仅管理员可用测试台<\/div>\n<div class=\"fg\"><label class=\"fl\">测试参数 (JSON)<\/label>\n<textarea class=\"json-area\" rows=\"4\">{\n \"product_id\": \"PROD001\",\n \"content\": \"测试发布内容\",\n \"tags\": [\"美妆\", \"种草\"]\n}<\/textarea><\/div>\n<button class=\"btn btn-p\" onclick=\"runTest()\">▶️ 执行测试<\/button>\n<div class=\"test-log\" id=\"testLog\" style=\"display:none\">\n<div>> 正在连接龙虾执行器...<\/div>\n<div style=\"color:#fbbf24\">> 提交任务到 agent_xhs_publish_01<\/div>\n<div>> 任务ID: task_20260423_001<\/div>\n<div>> 状态: RUNNING → RUNNING → SUCCEEDED<\/div>\n<div style=\"color:#4ade80\">> ✅ 执行成功,耗时 3.2s<\/div>\n<div>> 输出: {\"status\":\"published\",\"post_id\":\"xhs_98765\"}<\/div>\n<\/div><\/div>\n\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-skill')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-skill');showT('✅ Skill已保存','ok')\">保存<\/button><\/div><\/div><\/div>\n\n<!-- Modal: 删除 -->\n<div class=\"mo\" id=\"modal-del\"><div class=\"mc\" style=\"max-width:400px\"><div class=\"mh\"><h3>⚠️ 确认删除<\/h3><button class=\"mx\" onclick=\"closeM('modal-del')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:20px\"><div style=\"font-size:36px\">🗑️<\/div><p style=\"font-size:13px;font-weight:600;margin-top:8px\">确定删除该Skill?<\/p><p style=\"font-size:11px;color:var(--sub);margin-top:4px\">已有角色引用的Skill需先解除关联<\/p><\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-del')\">取消<\/button><button class=\"btn btn-d\" onclick=\"closeM('modal-del');showT('✅ 已删除','ok')\">确认删除<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni ac\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni\">· 操作日志<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>🧠 Skill中心 / <b style=\"color:var(--txt)\">Skill列表<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">Skill管理<\/h1>\n<p class=\"pd\">双执行器(龙虾🦞+脚本📜)· 产品范围绑定 · 参数映射 · 测试台<\/p>\n\n<div class=\"stat\">\n<div class=\"stat-c\"><div class=\"sv\">18<\/div><div class=\"sl2\">Skill总数<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:#dc2626\">🦞 12<\/div><div class=\"sl2\">龙虾执行器<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--pri)\">📜 6<\/div><div class=\"sl2\">脚本执行器<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--ok)\">16<\/div><div class=\"sl2\">启用中<\/div><\/div>\n<\/div>\n\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索Skill名称\" id=\"sInput\" oninput=\"filterT()\"><\/div>\n<select class=\"sl\" id=\"fCat\" onchange=\"filterT()\"><option value=\"\">全部分类<\/option><option value=\"内容发布\">内容发布<\/option><option value=\"数据采集\">数据采集<\/option><option value=\"账号运营\">账号运营<\/option><option value=\"广告投放\">广告投放<\/option><\/select>\n<select class=\"sl\" id=\"fExec\" onchange=\"filterT()\"><option value=\"\">全部执行器<\/option><option value=\"lobster\">🦞 龙虾<\/option><option value=\"script\">📜 脚本<\/option><\/select>\n<select class=\"sl\" id=\"fSt\" onchange=\"filterT()\"><option value=\"\">全部状态<\/option><option value=\"启用\">启用<\/option><option value=\"禁用\">禁用<\/option><\/select>\n<button class=\"btn btn-p\" style=\"margin-left:auto\" onclick=\"openAdd()\">+ 注册Skill<\/button>\n<\/div>\n\n<div class=\"tw\"><table><thead><tr><th>Skill名称<\/th><th>分类<\/th><th>执行器<\/th><th>产品范围<\/th><th>调用次数<\/th><th>成功率<\/th><th>状态<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody id=\"stb\">\n<tr data-q=\"小红书笔记发布\" data-cat=\"内容发布\" data-exec=\"lobster\" data-st=\"启用\"><td><b>小红书笔记发布<\/b><\/td><td><span class=\"tg tg-i\">内容发布<\/span><\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞 龙虾<\/span><\/td><td>3个产品<\/td><td>1,256<\/td><td><span style=\"color:var(--ok);font-weight:600\">98.2%<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('小红书笔记发布')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"抖音视频上传\" data-cat=\"内容发布\" data-exec=\"lobster\" data-st=\"启用\"><td><b>抖音视频上传<\/b><\/td><td><span class=\"tg tg-i\">内容发布<\/span><\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞 龙虾<\/span><\/td><td>2个产品<\/td><td>892<\/td><td><span style=\"color:var(--ok);font-weight:600\">96.5%<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('抖音视频上传')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"竞品数据采集\" data-cat=\"数据采集\" data-exec=\"script\" data-st=\"启用\"><td><b>竞品数据采集<\/b><\/td><td><span class=\"tg tg-p\">数据采集<\/span><\/td><td><span class=\"tg tg-p\">📜 脚本<\/span><\/td><td>5个产品<\/td><td>3,401<\/td><td><span style=\"color:var(--ok);font-weight:600\">99.1%<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('竞品数据采集')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"Facebook广告投放\" data-cat=\"广告投放\" data-exec=\"lobster\" data-st=\"启用\"><td><b>Facebook广告投放<\/b><\/td><td><span class=\"tg tg-w\">广告投放<\/span><\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞 龙虾<\/span><\/td><td>1个产品<\/td><td>567<\/td><td><span style=\"color:var(--warn);font-weight:600\">89.3%<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('Facebook广告投放')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"数据清洗脚本\" data-cat=\"数据采集\" data-exec=\"script\" data-st=\"启用\"><td><b>数据清洗脚本<\/b><\/td><td><span class=\"tg tg-p\">数据采集<\/span><\/td><td><span class=\"tg tg-p\">📜 脚本<\/span><\/td><td>全部产品<\/td><td>5,123<\/td><td><span style=\"color:var(--ok);font-weight:600\">99.8%<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('数据清洗脚本')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"TikTok达人匹配\" data-cat=\"账号运营\" data-exec=\"lobster\" data-st=\"禁用\"><td><b>TikTok达人匹配<\/b><\/td><td><span class=\"tg tg-ok\" style=\"background:#dcfce7;color:#166534\">账号运营<\/span><\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞 龙虾<\/span><\/td><td>1个产品<\/td><td>45<\/td><td><span style=\"color:var(--err);font-weight:600\">72.0%<\/span><\/td><td><span class=\"tg tg-e\">禁用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEdit('TikTok达人匹配')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<\/tbody><\/table><\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nlet curExec='lobster';\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\n\nfunction switchST(i){document.querySelectorAll('#skillTabs .tab').forEach((t,j)=>t.classList.toggle('ac',j===i));document.querySelectorAll('.st-ct').forEach((c,j)=>{c.style.display=j===i?'block':'none'})}\n\nfunction selExec(type){\n curExec=type;\n document.querySelectorAll('.er-item').forEach(e=>e.classList.remove('sel'));\n event.currentTarget.classList.add('sel');\n document.getElementById('lobsterConfig').style.display=type==='lobster'?'block':'none';\n document.getElementById('scriptConfig').style.display=type==='script'?'block':'none';\n}\n\nfunction onScriptTpl(v){\n const types={py1:'python',py2:'python',sh1:'shell',node1:'node'};\n document.getElementById('scriptType').value=types[v]||'';\n}\n\nfunction openAdd(){\n document.getElementById('msTitle').textContent='注册Skill';\n document.getElementById('ms-name').value='';\n switchST(0);openM('modal-skill');\n}\n\nfunction openEdit(name){\n document.getElementById('msTitle').textContent='编辑Skill — '+name;\n document.getElementById('ms-name').value=name;\n switchST(0);openM('modal-skill');\n}\n\nfunction addEnv(){\n const list=document.getElementById('envVars');\n const d=document.createElement('div');d.className='param-row';\n d.innerHTML='<input class=\"fi\" style=\"width:120px\" placeholder=\"变量名\"><input class=\"fi\" style=\"flex:1\" placeholder=\"变量值\"><button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"this.closest(\\'.param-row\\').remove()\">✕<\/button>';\n list.appendChild(d);\n}\n\nfunction runTest(){\n const log=document.getElementById('testLog');\n log.style.display='block';\n log.innerHTML='<div>> 正在连接执行器...<\/div>';\n setTimeout(()=>log.innerHTML+='<div style=\"color:#fbbf24\">> 提交任务...<\/div>',500);\n setTimeout(()=>log.innerHTML+='<div>> 任务ID: task_'+Date.now()+'<\/div>',1000);\n setTimeout(()=>log.innerHTML+='<div>> 状态: RUNNING<\/div>',1500);\n setTimeout(()=>{log.innerHTML+='<div style=\"color:#4ade80\">> ✅ 执行成功,耗时 2.8s<\/div>';log.innerHTML+='<div>> 输出: {\"status\":\"ok\"}<\/div>'},2500);\n}\n\nfunction filterT(){\n const q=document.getElementById('sInput').value.toLowerCase();\n const cat=document.getElementById('fCat').value;\n const exec=document.getElementById('fExec').value;\n const st=document.getElementById('fSt').value;\n document.querySelectorAll('#stb tr').forEach(tr=>{\n const d=tr.dataset;\n const show=(!q||d.q.toLowerCase().includes(q))&&(!cat||d.cat===cat)&&(!exec||d.exec===exec)&&(!st||d.st===st);\n tr.style.display=show?'':'none';\n });\n}\n\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\ndocument.addEventListener('click',e=>{if(!e.target.closest('.ms-wrap'))document.querySelectorAll('.ms-drop').forEach(d=>d.classList.remove('show'))});\n<\/script>\n<\/body><\/html>\n",
"10_任务创建.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 任务创建<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px;max-width:900px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.card{background:var(--card);border-radius:10px;padding:20px;border:1px solid var(--bdr);margin-bottom:14px}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}.btn-s{background:var(--ok);color:#fff}.btn-lg{padding:10px 28px;font-size:14px}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-w{background:#fef3c7;color:#92400e}\n.fg{margin-bottom:16px}.fl{font-size:12px;font-weight:600;margin-bottom:6px;display:block}.fl .rq{color:var(--err)}.fi{width:100%;padding:9px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none}.fi:focus{border-color:var(--pri);box-shadow:0 0 0 2px rgba(99,102,241,.1)}.fs{width:100%;padding:9px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.note{background:#eff6ff;border-left:3px solid var(--pri);padding:8px 12px;border-radius:0 6px 6px 0;font-size:11px;color:var(--sub);margin-bottom:14px}\n.warn{background:#fef2f2;border-left:3px solid var(--err);padding:8px 12px;border-radius:0 6px 6px 0;font-size:11px;color:#991b1b;margin-bottom:14px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:500px;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.steps{display:flex;align-items:center;margin-bottom:24px}.step{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--sub)}.step.ac{color:var(--pri);font-weight:600}.step .sn{width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;border:2px solid var(--bdr);color:var(--sub)}.step.ac .sn{background:var(--pri);color:#fff;border-color:var(--pri)}.step.done .sn{background:var(--ok);color:#fff;border-color:var(--ok)}.step-line{flex:1;height:2px;background:var(--bdr);margin:0 10px}.step-line.done{background:var(--ok)}\n.skill-card{border:2px solid var(--bdr);border-radius:10px;padding:14px;cursor:pointer;transition:all .15s;margin-bottom:8px}.skill-card:hover{border-color:#a5b4fc;background:#faf5ff}.skill-card.sel{border-color:var(--pri);background:#ede9fe}.skill-card .sk-name{font-weight:600;font-size:13px}.skill-card .sk-desc{font-size:11px;color:var(--sub);margin-top:2px}\n.prod-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;max-height:200px;overflow-y:auto}.prod-item{border:1px solid var(--bdr);border-radius:8px;padding:8px 12px;cursor:pointer;font-size:12px;transition:all .12s}.prod-item:hover{border-color:var(--pri)}.prod-item.sel{border-color:var(--pri);background:#ede9fe}.prod-item .pi-name{font-weight:600}.prod-item .pi-code{font-size:10px;color:var(--sub)}\n.ch-fill{background:#f0fdf4;border:1px solid #bbf7d0;border-radius:7px;padding:8px 12px;font-size:12px;color:#166534;margin-top:8px}\n.step-ct{display:none}.step-ct.show{display:block}\n.tag-input{display:flex;flex-wrap:wrap;gap:4px;padding:6px 10px;border:1px solid var(--bdr);border-radius:7px;min-height:36px;align-items:center}.tag-input .tag{background:#ede9fe;color:#6b21a8;padding:2px 6px;border-radius:3px;font-size:11px;display:flex;align-items:center;gap:3px}.tag-input .tag .x{cursor:pointer;font-weight:700}.tag-input input{border:none;outline:none;font-size:12px;flex:1;min-width:80px}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<div class=\"mo\" id=\"modal-ok\"><div class=\"mc\" style=\"max-width:440px\"><div class=\"mh\"><h3>🎉 任务已提交<\/h3><button class=\"mx\" onclick=\"closeM('modal-ok')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:20px\">\n<div style=\"font-size:48px;margin-bottom:12px\">✅<\/div>\n<p style=\"font-size:16px;font-weight:700;margin-bottom:4px\">任务创建成功!<\/p>\n<p style=\"font-size:12px;color:var(--sub)\">任务ID: TASK-20260423-001<\/p>\n<div style=\"margin-top:16px;padding:12px;background:#f8fafc;border-radius:8px;font-size:12px;text-align:left\">\n<div style=\"display:flex;justify-content:space-between;margin-bottom:4px\"><span style=\"color:var(--sub)\">Skill<\/span><span style=\"font-weight:600\">小红书笔记发布<\/span><\/div>\n<div style=\"display:flex;justify-content:space-between;margin-bottom:4px\"><span style=\"color:var(--sub)\">执行器<\/span><span>🦞 龙虾执行器<\/span><\/div>\n<div style=\"display:flex;justify-content:space-between;margin-bottom:4px\"><span style=\"color:var(--sub)\">产品<\/span><span>PROD001 美妆种草达人<\/span><\/div>\n<div style=\"display:flex;justify-content:space-between\"><span style=\"color:var(--sub)\">状态<\/span><span class=\"tg tg-w\">PENDING<\/span><\/div>\n<\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-ok');resetWizard()\">继续创建<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-ok')\">查看任务列表<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni ac\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni\">· 操作日志<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>📋 任务中心 / <b style=\"color:var(--txt)\">任务创建<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>张三<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">张<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">任务创建<\/h1>\n<p class=\"pd\">选Skill → 选产品 → 填参数 → 提交(双重权限校验:Skill权限 + 产品范围交集)<\/p>\n\n<!-- Steps -->\n<div class=\"steps\" id=\"stepsBar\">\n<div class=\"step ac\" id=\"s1\"><div class=\"sn\">1<\/div>选择Skill<\/div>\n<div class=\"step-line\" id=\"sl1\"><\/div>\n<div class=\"step\" id=\"s2\"><div class=\"sn\">2<\/div>选择产品<\/div>\n<div class=\"step-line\" id=\"sl2\"><\/div>\n<div class=\"step\" id=\"s3\"><div class=\"sn\">3<\/div>填写参数<\/div>\n<div class=\"step-line\" id=\"sl3\"><\/div>\n<div class=\"step\" id=\"s4\"><div class=\"sn\">4<\/div>确认提交<\/div>\n<\/div>\n\n<!-- Step 1: 选择Skill -->\n<div class=\"step-ct show\" id=\"sc1\">\n<div class=\"card\">\n<div class=\"note\">📋 仅展示您角色skill_scope中的Skill(RB-07),合并所有角色取并集<\/div>\n<div style=\"margin-bottom:12px\"><input class=\"fi\" placeholder=\"🔍 搜索Skill名称...\" oninput=\"filterSkills(this.value)\"><\/div>\n<div id=\"skillList\">\n<div class=\"skill-card\" onclick=\"selSkill(this,'小红书笔记发布','🦞 龙虾','内容发布')\"><div style=\"display:flex;justify-content:space-between;align-items:center\"><div class=\"sk-name\">小红书笔记发布<\/div><div><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞 龙虾<\/span> <span class=\"tg tg-i\">内容发布<\/span><\/div><\/div><div class=\"sk-desc\">自动发布小红书笔记,支持图文和视频<\/div><\/div>\n<div class=\"skill-card\" onclick=\"selSkill(this,'抖音视频上传','🦞 龙虾','内容发布')\"><div style=\"display:flex;justify-content:space-between;align-items:center\"><div class=\"sk-name\">抖音视频上传<\/div><div><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞 龙虾<\/span> <span class=\"tg tg-i\">内容发布<\/span><\/div><\/div><div class=\"sk-desc\">批量上传抖音短视频<\/div><\/div>\n<div class=\"skill-card\" onclick=\"selSkill(this,'竞品数据采集','📜 脚本','数据采集')\"><div style=\"display:flex;justify-content:space-between;align-items:center\"><div class=\"sk-name\">竞品数据采集<\/div><div><span class=\"tg tg-p\">📜 脚本<\/span> <span class=\"tg tg-p\">数据采集<\/span><\/div><\/div><div class=\"sk-desc\">采集竞品在各平台的数据指标<\/div><\/div>\n<div class=\"skill-card\" onclick=\"selSkill(this,'Facebook广告投放','🦞 龙虾','广告投放')\"><div style=\"display:flex;justify-content:space-between;align-items:center\"><div class=\"sk-name\">Facebook广告投放<\/div><div><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞 龙虾<\/span> <span class=\"tg tg-w\">广告投放<\/span><\/div><\/div><div class=\"sk-desc\">自动化Facebook广告创建和投放<\/div><\/div>\n<\/div>\n<div style=\"margin-top:14px;text-align:right\"><button class=\"btn btn-p\" id=\"nextBtn1\" disabled onclick=\"goStep(2)\">下一步 →<\/button><\/div>\n<\/div><\/div>\n\n<!-- Step 2: 选择产品 -->\n<div class=\"step-ct\" id=\"sc2\">\n<div class=\"card\">\n<div class=\"note\">⚠️ 产品范围 = Skill.product_scope ∩ 用户角色.data_scope(RB-12交集校验)<\/div>\n<div style=\"margin-bottom:8px;font-size:12px;color:var(--sub)\">已选Skill: <b id=\"selSkillName\" style=\"color:var(--txt)\">-<\/b><\/div>\n<div style=\"margin-bottom:12px\"><input class=\"fi\" placeholder=\"🔍 搜索产品...\" oninput=\"filterProds(this.value)\"><\/div>\n<div class=\"prod-grid\" id=\"prodList\">\n<div class=\"prod-item\" onclick=\"selProd(this,'PROD001')\" data-q=\"PROD001 美妆种草达人 小红书\"><div class=\"pi-name\">📕 美妆种草达人<\/div><div class=\"pi-code\">PROD001 · 小红书 · 投放一组<\/div><\/div>\n<div class=\"prod-item\" onclick=\"selProd(this,'PROD002')\" data-q=\"PROD002 护肤品评测 小红书\"><div class=\"pi-name\">📕 护肤品评测<\/div><div class=\"pi-code\">PROD002 · 小红书 · 投放一组<\/div><\/div>\n<div class=\"prod-item\" onclick=\"selProd(this,'PROD003')\" data-q=\"PROD003 抖音带货王 抖音\"><div class=\"pi-name\">🎵 抖音带货王<\/div><div class=\"pi-code\">PROD003 · 抖音 · 投放二组<\/div><\/div>\n<div class=\"prod-item\" onclick=\"selProd(this,'PROD006')\" data-q=\"PROD006 海外社媒投放 Facebook\"><div class=\"pi-name\">📘 海外社媒投放<\/div><div class=\"pi-code\">PROD006 · Facebook · 投放二组<\/div><\/div>\n<\/div>\n<div class=\"ch-fill\" id=\"chFill\" style=\"display:none\">✅ 渠道码已自动填充 — 内导: <b id=\"chIC\">-<\/b> · 自然: <b id=\"chNC\">-<\/b><\/div>\n<div style=\"margin-top:14px;display:flex;justify-content:space-between\"><button class=\"btn btn-g\" onclick=\"goStep(1)\">← 上一步<\/button><button class=\"btn btn-p\" id=\"nextBtn2\" disabled onclick=\"goStep(3)\">下一步 →<\/button><\/div>\n<\/div><\/div>\n\n<!-- Step 3: 填写参数 -->\n<div class=\"step-ct\" id=\"sc3\">\n<div class=\"card\">\n<div style=\"margin-bottom:12px;font-size:12px;color:var(--sub)\">Skill: <b id=\"s3Skill\" style=\"color:var(--txt)\">-<\/b> | 产品: <b id=\"s3Prod\" style=\"color:var(--txt)\">-<\/b><\/div>\n<div class=\"note\">📋 动态表单由Skill的inputSchema自动渲染(react-jsonschema-form)<\/div>\n<div class=\"fg\"><label class=\"fl\">产品 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"f-prod\" readonly style=\"background:#f0fdf4;border-color:#bbf7d0;color:#166534\"><\/div>\n<div class=\"fg\"><label class=\"fl\">发布内容 <span class=\"rq\">*<\/span><\/label><textarea class=\"fi\" rows=\"4\" id=\"f-content\" placeholder=\"请输入发布内容...\">今日美妆好物分享!这款面霜太绝了,上脸不油腻,保湿效果超棒✨ #美妆好物 #种草分享<\/textarea><\/div>\n<div class=\"fg\"><label class=\"fl\">标签<\/label>\n<div class=\"tag-input\" id=\"tagInput\"><span class=\"tag\">美妆 <span class=\"x\" onclick=\"this.closest('.tag').remove()\">×<\/span><\/span><span class=\"tag\">种草 <span class=\"x\" onclick=\"this.closest('.tag').remove()\">×<\/span><\/span><input placeholder=\"输入后回车添加\" onkeydown=\"addTag(event)\"><\/div><\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">发布时间<\/label><select class=\"fs\"><option>立即发布<\/option><option>定时发布<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">内导渠道码<\/label><input class=\"fi\" id=\"f-ic\" readonly style=\"background:#f8fafc\"><\/div>\n<\/div>\n<div style=\"margin-top:14px;display:flex;justify-content:space-between\"><button class=\"btn btn-g\" onclick=\"goStep(2)\">← 上一步<\/button><button class=\"btn btn-p\" onclick=\"goStep(4)\">下一步 →<\/button><\/div>\n<\/div><\/div>\n\n<!-- Step 4: 确认提交 -->\n<div class=\"step-ct\" id=\"sc4\">\n<div class=\"card\">\n<h3 style=\"font-size:15px;margin-bottom:14px\">📋 确认任务信息<\/h3>\n<div style=\"background:#f8fafc;border-radius:8px;padding:14px;font-size:12px;margin-bottom:14px\">\n<div style=\"display:grid;grid-template-columns:100px 1fr;gap:6px 12px\">\n<span style=\"color:var(--sub)\">Skill<\/span><span id=\"c-skill\" style=\"font-weight:600\">-<\/span>\n<span style=\"color:var(--sub)\">执行器<\/span><span id=\"c-exec\">-<\/span>\n<span style=\"color:var(--sub)\">产品<\/span><span id=\"c-prod\">-<\/span>\n<span style=\"color:var(--sub)\">内导渠道码<\/span><span id=\"c-ic\">-<\/span>\n<span style=\"color:var(--sub)\">发布内容<\/span><span id=\"c-content\" style=\"max-width:500px;word-break:break-all\">-<\/span>\n<span style=\"color:var(--sub)\">标签<\/span><span id=\"c-tags\">-<\/span>\n<\/div><\/div>\n<div class=\"note\">✅ Skill权限校验通过 · 产品范围交集校验通过 · 参数校验通过<\/div>\n<div style=\"display:flex;justify-content:space-between\"><button class=\"btn btn-g\" onclick=\"goStep(3)\">← 上一步<\/button><button class=\"btn btn-p btn-lg\" onclick=\"submitTask()\">🚀 提交任务<\/button><\/div>\n<\/div><\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nlet curStep=1,selSkillData=null,selProdData=null;\nconst PROD_CH={PROD001:{ic:'IC001',nc:'NC001'},PROD002:{ic:'IC002',nc:'NC002'},PROD003:{ic:'IC003',nc:'NC003'},PROD006:{ic:'IC006',nc:'NC006'}};\n\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\n\nfunction goStep(n){\n curStep=n;\n for(let i=1;i<=4;i++){\n document.getElementById('sc'+i).classList.toggle('show',i===n);\n const s=document.getElementById('s'+i);\n s.classList.toggle('ac',i===n);\n s.classList.toggle('done',i<n);\n if(i<4){const l=document.getElementById('sl'+i);l.classList.toggle('done',i<n)}\n }\n if(n===3&&selProdData){\n document.getElementById('s3Skill').textContent=selSkillData.name;\n document.getElementById('s3Prod').textContent=selProdData;\n document.getElementById('f-prod').value=selProdData;\n document.getElementById('f-ic').value=PROD_CH[selProdData]?.ic||'';\n }\n if(n===4){\n document.getElementById('c-skill').textContent=selSkillData.name;\n document.getElementById('c-exec').textContent=selSkillData.exec;\n document.getElementById('c-prod').textContent=selProdData;\n document.getElementById('c-ic').textContent=PROD_CH[selProdData]?.ic||'-';\n document.getElementById('c-content').textContent=document.getElementById('f-content').value||'-';\n const tags=[];document.querySelectorAll('#tagInput .tag').forEach(t=>tags.push(t.textContent.replace('×','')));\n document.getElementById('c-tags').textContent=tags.join(', ')||'-';\n }\n}\n\nfunction selSkill(el,name,exec,cat){\n document.querySelectorAll('.skill-card').forEach(c=>c.classList.remove('sel'));\n el.classList.add('sel');\n selSkillData={name,exec,cat};\n document.getElementById('nextBtn1').disabled=false;\n document.getElementById('selSkillName').textContent=name;\n}\n\nfunction selProd(el,code){\n document.querySelectorAll('.prod-item').forEach(c=>c.classList.remove('sel'));\n el.classList.add('sel');\n selProdData=code;\n document.getElementById('nextBtn2').disabled=false;\n const ch=PROD_CH[code];\n if(ch){\n document.getElementById('chFill').style.display='block';\n document.getElementById('chIC').textContent=ch.ic;\n document.getElementById('chNC').textContent=ch.nc;\n }\n}\n\nfunction filterSkills(q){\n q=q.toLowerCase();\n document.querySelectorAll('.skill-card').forEach(c=>{\n c.style.display=c.querySelector('.sk-name').textContent.toLowerCase().includes(q)?'':'none';\n });\n}\nfunction filterProds(q){\n q=q.toLowerCase();\n document.querySelectorAll('.prod-item').forEach(c=>{\n c.style.display=c.dataset.q.toLowerCase().includes(q)?'':'none';\n });\n}\n\nfunction addTag(e){\n if(e.key==='Enter'&&e.target.value.trim()){\n e.preventDefault();\n const tag=document.createElement('span');tag.className='tag';\n tag.innerHTML=e.target.value.trim()+' <span class=\"x\" onclick=\"this.closest(\\'.tag\\').remove()\">×<\/span>';\n e.target.parentNode.insertBefore(tag,e.target);\n e.target.value='';\n }\n}\n\nfunction submitTask(){openM('modal-ok')}\n\nfunction resetWizard(){\n selSkillData=null;selProdData=null;\n document.querySelectorAll('.skill-card,.prod-item').forEach(c=>c.classList.remove('sel'));\n document.getElementById('nextBtn1').disabled=true;\n document.getElementById('nextBtn2').disabled=true;\n document.getElementById('chFill').style.display='none';\n goStep(1);\n}\n\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>\n",
"11_任务列表.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 任务列表<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.tb{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:140px}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}.btn-s{background:var(--ok);color:#fff}.btn-w{background:var(--warn);color:#fff}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-w{background:#fef3c7;color:#92400e}.tg-g{background:#f1f5f9;color:#64748b}.tg-run{background:#bfdbfe;color:#1d4ed8;animation:pulse 2s infinite}\n@keyframes pulse{0%,100%{opacity:1}50%{opacity:.6}}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.stat{display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin-bottom:16px}.stat-c{background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px 16px}.stat-c .sv{font-size:22px;font-weight:700}.stat-c .sl2{font-size:11px;color:var(--sub)}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.pg{display:flex;align-items:center;justify-content:space-between;padding:10px 0;font-size:12px;color:var(--sub)}.pgb{padding:4px 10px;border:1px solid var(--bdr);border-radius:5px;font-size:11px;cursor:pointer;background:var(--card);margin:0 2px}.pgb.ac{background:var(--pri);color:#fff;border-color:var(--pri)}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:650px;max-height:88vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.tabs{display:flex;gap:0;border-bottom:2px solid var(--bdr);margin-bottom:14px}.tab{padding:8px 14px;font-size:12px;font-weight:500;color:var(--sub);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px}.tab.ac{color:var(--pri);border-bottom-color:var(--pri);font-weight:600}.tab:hover{color:var(--txt)}\n.detail-row{display:flex;border-bottom:1px solid var(--bdr);font-size:12px}.detail-row:last-child{border:none}.dr-l{width:100px;padding:8px 0;color:var(--sub);font-weight:500;flex-shrink:0}.dr-v{padding:8px 0;flex:1}\n.log-box{background:#1e293b;color:#a5f3fc;padding:12px;border-radius:8px;font-family:monospace;font-size:11px;max-height:200px;overflow-y:auto}\n.json-box{background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:10px;font-family:monospace;font-size:11px;max-height:160px;overflow-y:auto;white-space:pre-wrap}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<!-- Modal: 任务详情 -->\n<div class=\"mo\" id=\"modal-detail\"><div class=\"mc\"><div class=\"mh\"><h3>📋 任务详情<\/h3><button class=\"mx\" onclick=\"closeM('modal-detail')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"tabs\" id=\"dtTabs\"><div class=\"tab ac\" onclick=\"switchDT(0)\">基本信息<\/div><div class=\"tab\" onclick=\"switchDT(1)\">输入参数<\/div><div class=\"tab\" onclick=\"switchDT(2)\">执行结果<\/div><div class=\"tab\" onclick=\"switchDT(3)\">执行日志<\/div><\/div>\n<div id=\"dt0\">\n<div class=\"detail-row\"><div class=\"dr-l\">任务ID<\/div><div class=\"dr-v\"><code>TASK-001<\/code><\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">Skill<\/div><div class=\"dr-v\">小红书笔记发布<\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">执行器<\/div><div class=\"dr-v\"><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞 龙虾<\/span><\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">产品<\/div><div class=\"dr-v\">PROD001 · 美妆种草达人<\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">创建人<\/div><div class=\"dr-v\">张三<\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">状态<\/div><div class=\"dr-v\"><span class=\"tg tg-ok\">SUCCEEDED<\/span><\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">创建时间<\/div><div class=\"dr-v\">2026-04-23 10:30:15<\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">耗时<\/div><div class=\"dr-v\">3.2s<\/div><\/div>\n<\/div>\n<div id=\"dt1\" style=\"display:none\"><div class=\"json-box\">{\n \"product_id\": \"PROD001\",\n \"content\": \"今日美妆好物分享!这款面霜太绝了...\",\n \"tags\": [\"美妆\", \"种草\"],\n \"channel_code\": \"IC001\"\n}<\/div><\/div>\n<div id=\"dt2\" style=\"display:none\"><div class=\"json-box\">{\n \"status\": \"published\",\n \"post_id\": \"xhs_98765\",\n \"post_url\": \"https://www.xiaohongshu.com/explore/98765\",\n \"published_at\": \"2026-04-23T10:30:18Z\"\n}<\/div><\/div>\n<div id=\"dt3\" style=\"display:none\"><div class=\"log-box\"><div>[10:30:15] 任务创建,状态: PENDING<\/div><div>[10:30:15] 权限校验通过: Skill=小红书笔记发布, Product=PROD001<\/div><div>[10:30:15] 路由到龙虾执行器: agent_xhs_publish_01<\/div><div style=\"color:#fbbf24\">[10:30:16] 状态变更: PENDING → RUNNING<\/div><div>[10:30:16] 龙虾平台任务ID: lob_task_abc123<\/div><div>[10:30:17] 轮询龙虾状态: RUNNING<\/div><div>[10:30:18] 轮询龙虾状态: SUCCEEDED<\/div><div style=\"color:#4ade80\">[10:30:18] ✅ 任务执行成功,耗时 3.2s<\/div><\/div><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-detail')\">关闭<\/button><\/div><\/div><\/div>\n\n<!-- Modal: 确认取消 -->\n<div class=\"mo\" id=\"modal-cancel\"><div class=\"mc\" style=\"max-width:400px\"><div class=\"mh\"><h3>⚠️ 取消任务<\/h3><button class=\"mx\" onclick=\"closeM('modal-cancel')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:20px\"><div style=\"font-size:36px\">⏹️<\/div><p style=\"font-size:13px;font-weight:600;margin-top:8px\">确定取消运行中的任务?<\/p><p style=\"font-size:11px;color:var(--sub);margin-top:4px\">将向执行器发送停止信号<\/p><\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-cancel')\">返回<\/button><button class=\"btn btn-d\" onclick=\"closeM('modal-cancel');showT('✅ 任务已取消','ok')\">确认取消<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni ac\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni\">· 操作日志<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>📋 任务中心 / <b style=\"color:var(--txt)\">任务列表<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>张三<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">张<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">任务列表<\/h1>\n<p class=\"pd\">按data_scope过滤 · 任务详情抽屉 · 取消/重试操作<\/p>\n\n<div class=\"stat\">\n<div class=\"stat-c\"><div class=\"sv\">1,234<\/div><div class=\"sl2\">任务总数<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--ok)\">1,089<\/div><div class=\"sl2\">成功<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--err)\">45<\/div><div class=\"sl2\">失败<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:#1d4ed8\">8<\/div><div class=\"sl2\">运行中<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--warn)\">92<\/div><div class=\"sl2\">超时<\/div><\/div>\n<\/div>\n\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索任务ID/Skill名称\" id=\"sInput\" oninput=\"filterT()\"><\/div>\n<select class=\"sl\" id=\"fSt\" onchange=\"filterT()\"><option value=\"\">全部状态<\/option><option value=\"SUCCEEDED\">成功<\/option><option value=\"FAILED\">失败<\/option><option value=\"RUNNING\">运行中<\/option><option value=\"PENDING\">等待中<\/option><option value=\"TIMEOUT\">超时<\/option><\/select>\n<select class=\"sl\" id=\"fExec\" onchange=\"filterT()\"><option value=\"\">全部执行器<\/option><option value=\"lobster\">🦞 龙虾<\/option><option value=\"script\">📜 脚本<\/option><\/select>\n<select class=\"sl\"><option>最近7天<\/option><option>最近30天<\/option><option>全部<\/option><\/select>\n<button class=\"btn btn-g btn-sm\" onclick=\"showT('📥 导出成功','ok')\">导出<\/button>\n<\/div>\n\n<div class=\"tw\"><table>\n<thead><tr><th>任务ID<\/th><th>Skill<\/th><th>执行器<\/th><th>产品<\/th><th>创建人<\/th><th>状态<\/th><th>耗时<\/th><th>创建时间<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody id=\"ttb\">\n<tr data-q=\"TASK-001 小红书笔记发布\" data-st=\"SUCCEEDED\" data-exec=\"lobster\"><td><code>TASK-001<\/code><\/td><td>小红书笔记发布<\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞<\/span><\/td><td>PROD001<\/td><td>张三<\/td><td><span class=\"tg tg-ok\">SUCCEEDED<\/span><\/td><td>3.2s<\/td><td>04-23 10:30<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"TASK-002 抖音视频上传\" data-st=\"SUCCEEDED\" data-exec=\"lobster\"><td><code>TASK-002<\/code><\/td><td>抖音视频上传<\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞<\/span><\/td><td>PROD003<\/td><td>张三<\/td><td><span class=\"tg tg-ok\">SUCCEEDED<\/span><\/td><td>5.8s<\/td><td>04-23 10:15<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"TASK-003 竞品数据采集\" data-st=\"RUNNING\" data-exec=\"script\"><td><code>TASK-003<\/code><\/td><td>竞品数据采集<\/td><td><span class=\"tg tg-p\">📜<\/span><\/td><td>PROD002<\/td><td>李四<\/td><td><span class=\"tg tg-run\">RUNNING<\/span><\/td><td>12s...<\/td><td>04-23 10:28<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-cancel')\">取消<\/button><\/td><\/tr>\n<tr data-q=\"TASK-004 Facebook广告投放\" data-st=\"FAILED\" data-exec=\"lobster\"><td><code>TASK-004<\/code><\/td><td>Facebook广告投放<\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞<\/span><\/td><td>PROD006<\/td><td>赵六<\/td><td><span class=\"tg tg-e\">FAILED<\/span><\/td><td>1.5s<\/td><td>04-23 09:45<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button> <button class=\"btn-l\" style=\"color:var(--warn)\" onclick=\"showT('🔄 已重新提交','ok')\">重试<\/button><\/td><\/tr>\n<tr data-q=\"TASK-005 数据清洗脚本\" data-st=\"SUCCEEDED\" data-exec=\"script\"><td><code>TASK-005<\/code><\/td><td>数据清洗脚本<\/td><td><span class=\"tg tg-p\">📜<\/span><\/td><td>PROD001<\/td><td>张三<\/td><td><span class=\"tg tg-ok\">SUCCEEDED<\/span><\/td><td>0.8s<\/td><td>04-23 09:30<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"TASK-006 小红书笔记发布\" data-st=\"TIMEOUT\" data-exec=\"lobster\"><td><code>TASK-006<\/code><\/td><td>小红书笔记发布<\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞<\/span><\/td><td>PROD002<\/td><td>王五<\/td><td><span class=\"tg tg-w\">TIMEOUT<\/span><\/td><td>30s<\/td><td>04-23 09:00<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button> <button class=\"btn-l\" style=\"color:var(--warn)\" onclick=\"showT('🔄 已重新提交','ok')\">重试<\/button><\/td><\/tr>\n<tr data-q=\"TASK-007 竞品数据采集\" data-st=\"PENDING\" data-exec=\"script\"><td><code>TASK-007<\/code><\/td><td>竞品数据采集<\/td><td><span class=\"tg tg-p\">📜<\/span><\/td><td>PROD003<\/td><td>张三<\/td><td><span class=\"tg tg-g\">PENDING<\/span><\/td><td>-<\/td><td>04-23 10:29<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-cancel')\">取消<\/button><\/td><\/tr>\n<tr data-q=\"TASK-008 抖音视频上传\" data-st=\"RUNNING\" data-exec=\"lobster\"><td><code>TASK-008<\/code><\/td><td>抖音视频上传<\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞<\/span><\/td><td>PROD004<\/td><td>李四<\/td><td><span class=\"tg tg-run\">RUNNING<\/span><\/td><td>6s...<\/td><td>04-23 10:29<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-cancel')\">取消<\/button><\/td><\/tr>\n<\/tbody><\/table><\/div>\n<div class=\"pg\"><span>共 8 条<\/span><div><span class=\"pgb ac\">1<\/span><span class=\"pgb\">2<\/span><span class=\"pgb\">3<\/span><\/div><\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\nfunction switchDT(i){document.querySelectorAll('#dtTabs .tab').forEach((t,j)=>t.classList.toggle('ac',j===i));['dt0','dt1','dt2','dt3'].forEach((d,j)=>document.getElementById(d).style.display=j===i?'block':'none')}\nfunction filterT(){\n const q=document.getElementById('sInput').value.toLowerCase();\n const st=document.getElementById('fSt').value;\n const exec=document.getElementById('fExec').value;\n document.querySelectorAll('#ttb tr').forEach(tr=>{\n const d=tr.dataset;\n const show=(!q||d.q.toLowerCase().includes(q))&&(!st||d.st===st)&&(!exec||d.exec===exec);\n tr.style.display=show?'':'none';\n });\n}\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>\n",
"12_菜单管理.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 菜单管理<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-w{background:#fef3c7;color:#92400e}.tg-g{background:#f1f5f9;color:#64748b}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}.fl .rq{color:var(--err)}.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none}.fi:focus{border-color:var(--pri)}.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:580px;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.tree-row{display:flex;align-items:center;gap:6px;padding:7px 12px;font-size:12px;border-bottom:1px solid #f1f5f9;cursor:pointer}.tree-row:hover{background:#f8fafc}.tree-toggle{width:18px;text-align:center;cursor:pointer;color:var(--sub);font-size:10px}.tree-icon{font-size:14px}.tree-name{flex:1;font-weight:500}.tree-children{margin-left:24px}.tree-children.hide{display:none}\n.btn-group{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}\n.tabs{display:flex;gap:0;border-bottom:2px solid var(--bdr);margin-bottom:16px}.tab{padding:8px 16px;font-size:12px;font-weight:500;color:var(--sub);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px}.tab.ac{color:var(--pri);border-bottom-color:var(--pri);font-weight:600}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<!-- Modal: 新增/编辑菜单 -->\n<div class=\"mo\" id=\"modal-menu\"><div class=\"mc\"><div class=\"mh\"><h3 id=\"mmTitle\">新增菜单<\/h3><button class=\"mx\" onclick=\"closeM('modal-menu')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fg\"><label class=\"fl\">菜单类型 <span class=\"rq\">*<\/span><\/label><select class=\"fs\" id=\"mm-type\" onchange=\"onMenuType(this.value)\"><option value=\"directory\">目录(directory)<\/option><option value=\"menu\">菜单(menu)<\/option><option value=\"link\">外链(link)<\/option><\/select><\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">菜单名称 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mm-name\" placeholder=\"如 产品管理\"><\/div>\n<div class=\"fg\"><label class=\"fl\">父级菜单<\/label><select class=\"fs\" id=\"mm-parent\"><option value=\"0\">顶级菜单<\/option><option>权限管理<\/option><option>产品管理<\/option><option>Skill中心<\/option><option>任务中心<\/option><option>日志中心<\/option><option>系统设置<\/option><\/select><\/div>\n<\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">路由路径 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mm-path\" placeholder=\"/product\"><\/div>\n<div class=\"fg\"><label class=\"fl\">图标<\/label><input class=\"fi\" placeholder=\"如 📦 或 icon-product\"><\/div>\n<\/div>\n<div class=\"fr\" id=\"compRow\">\n<div class=\"fg\"><label class=\"fl\">前端组件路径<\/label><input class=\"fi\" placeholder=\"pages/product/index\"><\/div>\n<div class=\"fg\"><label class=\"fl\">排序号 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" type=\"number\" value=\"1\"><\/div>\n<\/div>\n<div class=\"fr\">\n<div class=\"fg\"><label class=\"fl\">是否可见<\/label><select class=\"fs\"><option>显示<\/option><option>隐藏<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>禁用<\/option><\/select><\/div>\n<\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-menu')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-menu');showT('✅ 菜单已保存','ok')\">保存<\/button><\/div><\/div><\/div>\n\n<!-- Modal: 新增/编辑按钮 -->\n<div class=\"mo\" id=\"modal-btn\"><div class=\"mc\" style=\"max-width:480px\"><div class=\"mh\"><h3 id=\"mbTitle\">新增按钮<\/h3><button class=\"mx\" onclick=\"closeM('modal-btn')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fg\"><label class=\"fl\">所属菜单<\/label><input class=\"fi\" id=\"mb-menu\" readonly value=\"产品列表\"><\/div>\n<div class=\"fg\"><label class=\"fl\">按钮名称 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mb-name\" placeholder=\"如 新增\"><\/div>\n<div class=\"fg\"><label class=\"fl\">权限标识 <span class=\"rq\">*<\/span> <span style=\"font-size:10px;color:var(--sub)\">(全局唯一,格式: 模块:操作)<\/span><\/label><input class=\"fi\" id=\"mb-code\" placeholder=\"如 product:create\"><\/div>\n<div class=\"fg\"><label class=\"fl\">按钮类型<\/label><select class=\"fs\"><option>primary<\/option><option>default<\/option><option>danger<\/option><option>warning<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>禁用<\/option><\/select><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-btn')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-btn');showT('✅ 按钮已保存','ok')\">保存<\/button><\/div><\/div><\/div>\n\n<!-- Modal: 删除 -->\n<div class=\"mo\" id=\"modal-del\"><div class=\"mc\" style=\"max-width:400px\"><div class=\"mh\"><h3>⚠️ 确认删除<\/h3><button class=\"mx\" onclick=\"closeM('modal-del')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:20px\"><div style=\"font-size:36px\">🗑️<\/div><p style=\"font-size:13px;font-weight:600;margin-top:8px\" id=\"delMsg\">确定删除?<\/p><p style=\"font-size:11px;color:var(--sub);margin-top:4px\">删除需确保无子菜单、无角色引用<\/p><\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-del')\">取消<\/button><button class=\"btn btn-d\" onclick=\"closeM('modal-del');showT('✅ 已删除','ok')\">确认删除<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni ac\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni\">· 操作日志<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>🔐 权限管理 / <b style=\"color:var(--txt)\">菜单管理<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">菜单管理<\/h1>\n<p class=\"pd\">菜单树形管理(目录/菜单/外链)· 按钮操作管理 · 权限树 · button_code全局唯一<\/p>\n\n<div style=\"display:flex;gap:8px;margin-bottom:14px\">\n<button class=\"btn btn-p\" onclick=\"openAddMenu()\">+ 新增菜单<\/button>\n<button class=\"btn btn-g btn-sm\" onclick=\"expandAll()\">全部展开<\/button>\n<button class=\"btn btn-g btn-sm\" onclick=\"collapseAll()\">全部收起<\/button>\n<\/div>\n\n<div style=\"display:flex;gap:16px\">\n<!-- 左侧: 菜单树 -->\n<div style=\"flex:1;background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px\">\n<div style=\"font-size:13px;font-weight:600;margin-bottom:10px\">📋 菜单树<\/div>\n\n<div class=\"tree-row\" onclick=\"showBtns('dashboard')\"><span class=\"tree-toggle\" onclick=\"event.stopPropagation();toggleTree('t-home')\">▼<\/span><span class=\"tree-icon\">📁<\/span><span class=\"tree-name\">首页<\/span><span class=\"tg tg-i\">目录<\/span><span style=\"margin-left:6px\"><button class=\"btn-l btn-sm\" onclick=\"event.stopPropagation();openEditMenu('首页','directory')\">编辑<\/button><\/span><\/div>\n<div class=\"tree-children\" id=\"t-home\">\n<div class=\"tree-row\" onclick=\"showBtns('dashboard')\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">仪表盘<\/span><span class=\"tg tg-ok\">菜单<\/span><span style=\"margin-left:6px\"><button class=\"btn-l btn-sm\" onclick=\"event.stopPropagation();openEditMenu('仪表盘','menu')\">编辑<\/button><\/span><\/div>\n<\/div>\n\n<div class=\"tree-row\"><span class=\"tree-toggle\" onclick=\"toggleTree('t-perm')\">▼<\/span><span class=\"tree-icon\">📁<\/span><span class=\"tree-name\">权限管理<\/span><span class=\"tg tg-i\">目录<\/span><span style=\"margin-left:6px\"><button class=\"btn-l btn-sm\" onclick=\"event.stopPropagation();openEditMenu('权限管理','directory')\">编辑<\/button><\/span><\/div>\n<div class=\"tree-children\" id=\"t-perm\">\n<div class=\"tree-row\" onclick=\"showBtns('org')\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">组织架构<\/span><span class=\"tg tg-ok\">菜单<\/span><span style=\"margin-left:6px\"><button class=\"btn-l btn-sm\" onclick=\"event.stopPropagation();openEditMenu('组织架构','menu')\">编辑<\/button><\/span><\/div>\n<div class=\"tree-row\" onclick=\"showBtns('menu-mgmt')\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">菜单管理<\/span><span class=\"tg tg-ok\">菜单<\/span><span style=\"margin-left:6px\"><button class=\"btn-l btn-sm\" onclick=\"event.stopPropagation();openEditMenu('菜单管理','menu')\">编辑<\/button><\/span><\/div>\n<div class=\"tree-row\" onclick=\"showBtns('role')\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">角色管理<\/span><span class=\"tg tg-ok\">菜单<\/span><span style=\"margin-left:6px\"><button class=\"btn-l btn-sm\" onclick=\"event.stopPropagation();openEditMenu('角色管理','menu')\">编辑<\/button><\/span><\/div>\n<div class=\"tree-row\" onclick=\"showBtns('user')\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">用户管理<\/span><span class=\"tg tg-ok\">菜单<\/span><span style=\"margin-left:6px\"><button class=\"btn-l btn-sm\" onclick=\"event.stopPropagation();openEditMenu('用户管理','menu')\">编辑<\/button><\/span><\/div>\n<\/div>\n\n<div class=\"tree-row\"><span class=\"tree-toggle\" onclick=\"toggleTree('t-prod')\">▼<\/span><span class=\"tree-icon\">📁<\/span><span class=\"tree-name\">产品管理<\/span><span class=\"tg tg-i\">目录<\/span><span style=\"margin-left:6px\"><button class=\"btn-l btn-sm\" onclick=\"event.stopPropagation();openEditMenu('产品管理','directory')\">编辑<\/button><\/span><\/div>\n<div class=\"tree-children\" id=\"t-prod\">\n<div class=\"tree-row\" onclick=\"showBtns('product')\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">产品列表<\/span><span class=\"tg tg-ok\">菜单<\/span><span style=\"margin-left:6px\"><button class=\"btn-l btn-sm\" onclick=\"event.stopPropagation();openEditMenu('产品列表','menu')\">编辑<\/button><\/span><\/div>\n<div class=\"tree-row\" onclick=\"showBtns('channel')\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">渠道码<\/span><span class=\"tg tg-ok\">菜单<\/span><\/div>\n<div class=\"tree-row\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">平台套件<\/span><span class=\"tg tg-ok\">菜单<\/span><\/div>\n<\/div>\n\n<div class=\"tree-row\"><span class=\"tree-toggle\" onclick=\"toggleTree('t-skill')\">▼<\/span><span class=\"tree-icon\">📁<\/span><span class=\"tree-name\">Skill中心<\/span><span class=\"tg tg-i\">目录<\/span><\/div>\n<div class=\"tree-children\" id=\"t-skill\">\n<div class=\"tree-row\" onclick=\"showBtns('skill')\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">Skill列表<\/span><span class=\"tg tg-ok\">菜单<\/span><\/div>\n<div class=\"tree-row\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">调用日志<\/span><span class=\"tg tg-ok\">菜单<\/span><\/div>\n<\/div>\n\n<div class=\"tree-row\"><span class=\"tree-toggle\" onclick=\"toggleTree('t-task')\">▼<\/span><span class=\"tree-icon\">📁<\/span><span class=\"tree-name\">任务中心<\/span><span class=\"tg tg-i\">目录<\/span><\/div>\n<div class=\"tree-children\" id=\"t-task\">\n<div class=\"tree-row\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">任务创建<\/span><span class=\"tg tg-ok\">菜单<\/span><\/div>\n<div class=\"tree-row\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">任务列表<\/span><span class=\"tg tg-ok\">菜单<\/span><\/div>\n<\/div>\n\n<div class=\"tree-row\"><span class=\"tree-toggle\" onclick=\"toggleTree('t-sys')\">▼<\/span><span class=\"tree-icon\">📁<\/span><span class=\"tree-name\">系统设置<\/span><span class=\"tg tg-i\">目录<\/span><\/div>\n<div class=\"tree-children\" id=\"t-sys\">\n<div class=\"tree-row\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">执行器配置<\/span><span class=\"tg tg-ok\">菜单<\/span><\/div>\n<div class=\"tree-row\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">📄<\/span><span class=\"tree-name\">脚本模板<\/span><span class=\"tg tg-ok\">菜单<\/span><\/div>\n<div class=\"tree-row\"><span class=\"tree-toggle\"><\/span><span class=\"tree-icon\">🔗<\/span><span class=\"tree-name\">龙虾平台<\/span><span class=\"tg tg-w\">外链<\/span><\/div>\n<\/div>\n<\/div>\n\n<!-- 右侧: 按钮管理 -->\n<div style=\"width:380px;background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px\">\n<div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:10px\"><div style=\"font-size:13px;font-weight:600\">🔘 按钮管理 — <span id=\"btnMenuName\">产品列表<\/span><\/div><button class=\"btn btn-p btn-sm\" onclick=\"openAddBtn()\">+ 新增按钮<\/button><\/div>\n\n<div class=\"tw\"><table><thead><tr><th>按钮名称<\/th><th>权限标识<\/th><th>类型<\/th><th>状态<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody id=\"btnTb\">\n<tr><td><b>新增<\/b><\/td><td><code>product:create<\/code><\/td><td><span class=\"tg tg-i\">primary<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEditBtn('新增','product:create')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr><td><b>编辑<\/b><\/td><td><code>product:update<\/code><\/td><td><span class=\"tg tg-g\">default<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEditBtn('编辑','product:update')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr><td><b>删除<\/b><\/td><td><code>product:delete<\/code><\/td><td><span class=\"tg tg-e\">danger<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEditBtn('删除','product:delete')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr><td><b>导入<\/b><\/td><td><code>product:import<\/code><\/td><td><span class=\"tg tg-w\">warning<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEditBtn('导入','product:import')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr><td><b>导出<\/b><\/td><td><code>product:export<\/code><\/td><td><span class=\"tg tg-g\">default<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEditBtn('导出','product:export')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<\/tbody><\/table><\/div>\n<\/div>\n<\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nconst BTN_DATA={product:[{n:'新增',c:'product:create',t:'primary'},{n:'编辑',c:'product:update',t:'default'},{n:'删除',c:'product:delete',t:'danger'},{n:'导入',c:'product:import',t:'warning'},{n:'导出',c:'product:export',t:'default'}],role:[{n:'新增',c:'role:create',t:'primary'},{n:'编辑',c:'role:update',t:'default'},{n:'删除',c:'role:delete',t:'danger'},{n:'复制',c:'role:copy',t:'default'}],user:[{n:'新增',c:'user:create',t:'primary'},{n:'编辑',c:'user:update',t:'default'},{n:'删除',c:'user:delete',t:'danger'},{n:'重置密码',c:'user:reset-pwd',t:'warning'}],skill:[{n:'注册',c:'skill:create',t:'primary'},{n:'编辑',c:'skill:update',t:'default'},{n:'删除',c:'skill:delete',t:'danger'},{n:'测试',c:'skill:test',t:'warning'}],org:[{n:'新增',c:'org:create',t:'primary'},{n:'编辑',c:'org:update',t:'default'},{n:'删除',c:'org:delete',t:'danger'}],dashboard:[],channel:[{n:'新增',c:'channel:create',t:'primary'},{n:'编辑',c:'channel:update',t:'default'},{n:'绑定',c:'channel:bindProduct',t:'default'}],'menu-mgmt':[{n:'新增菜单',c:'menu:create',t:'primary'},{n:'编辑菜单',c:'menu:update',t:'default'},{n:'新增按钮',c:'button:create',t:'primary'}]};\n\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\n\nfunction toggleTree(id){const el=document.getElementById(id);el.classList.toggle('hide');const toggle=el.previousElementSibling.querySelector('.tree-toggle');toggle.textContent=el.classList.contains('hide')?'▶':'▼'}\nfunction expandAll(){document.querySelectorAll('.tree-children').forEach(c=>{c.classList.remove('hide');c.previousElementSibling.querySelector('.tree-toggle').textContent='▼'})}\nfunction collapseAll(){document.querySelectorAll('.tree-children').forEach(c=>{c.classList.add('hide');c.previousElementSibling.querySelector('.tree-toggle').textContent='▶'})}\n\nfunction showBtns(key){\n document.getElementById('btnMenuName').textContent=event?.currentTarget?.querySelector('.tree-name')?.textContent||key;\n const btns=BTN_DATA[key]||[];\n const tb=document.getElementById('btnTb');\n const tgMap={primary:'tg-i',default:'tg-g',danger:'tg-e',warning:'tg-w'};\n tb.innerHTML=btns.length?btns.map(b=>`<tr><td><b>${b.n}<\/b><\/td><td><code>${b.c}<\/code><\/td><td><span class=\"tg ${tgMap[b.t]}\">${b.t}<\/span><\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\" onclick=\"openEditBtn('${b.n}','${b.c}')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>`).join(''):'<tr><td colspan=\"5\" style=\"text-align:center;color:var(--sub);padding:20px\">暂无按钮<\/td><\/tr>';\n}\n\nfunction openAddMenu(){document.getElementById('mmTitle').textContent='新增菜单';document.getElementById('mm-name').value='';document.getElementById('mm-path').value='';openM('modal-menu')}\nfunction openEditMenu(name,type){document.getElementById('mmTitle').textContent='编辑菜单 — '+name;document.getElementById('mm-name').value=name;document.getElementById('mm-type').value=type;openM('modal-menu')}\nfunction openAddBtn(){document.getElementById('mbTitle').textContent='新增按钮';document.getElementById('mb-name').value='';document.getElementById('mb-code').value='';document.getElementById('mb-menu').value=document.getElementById('btnMenuName').textContent;openM('modal-btn')}\nfunction openEditBtn(name,code){document.getElementById('mbTitle').textContent='编辑按钮';document.getElementById('mb-name').value=name;document.getElementById('mb-code').value=code;openM('modal-btn')}\nfunction onMenuType(v){document.getElementById('compRow').style.display=v==='link'?'none':'grid'}\n\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>\n",
"13_平台套件.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 平台套件<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}\n.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:140px}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}.fl .rq{color:var(--err)}.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none}.fi:focus{border-color:var(--pri)}.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:560px;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px;margin-bottom:16px}\n.p-card{background:var(--card);border:1px solid var(--bdr);border-radius:12px;padding:18px;transition:all .15s;cursor:pointer}.p-card:hover{border-color:var(--pri);box-shadow:0 4px 12px rgba(99,102,241,.1)}.p-card .pc-icon{font-size:32px;margin-bottom:8px}.p-card .pc-name{font-size:15px;font-weight:700;margin-bottom:2px}.p-card .pc-url{font-size:11px;color:var(--sub);word-break:break-all}.p-card .pc-stat{display:flex;gap:12px;margin-top:10px;font-size:11px;color:var(--sub)}.pc-stat span{display:flex;align-items:center;gap:3px}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<div class=\"mo\" id=\"modal-plat\"><div class=\"mc\"><div class=\"mh\"><h3 id=\"mpTitle\">新增平台<\/h3><button class=\"mx\" onclick=\"closeM('modal-plat')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fg\"><label class=\"fl\">平台名称 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mp-name\" placeholder=\"如 小红书\"><\/div>\n<div class=\"fg\"><label class=\"fl\">平台地址 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mp-url\" placeholder=\"https://www.xiaohongshu.com\"><\/div>\n<div class=\"fg\"><label class=\"fl\">平台图标<\/label><input class=\"fi\" placeholder=\"emoji 或 图标URL\"><\/div>\n<div class=\"fg\"><label class=\"fl\">备注<\/label><textarea class=\"fi\" rows=\"2\" placeholder=\"平台备注信息\"><\/textarea><\/div>\n<div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>禁用<\/option><\/select><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-plat')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-plat');showT('✅ 平台已保存','ok')\">保存<\/button><\/div><\/div><\/div>\n\n<div class=\"mo\" id=\"modal-prod\"><div class=\"mc\"><div class=\"mh\"><h3 id=\"mprTitle\">新增产品代号<\/h3><button class=\"mx\" onclick=\"closeM('modal-prod')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fg\"><label class=\"fl\">所属平台<\/label><input class=\"fi\" id=\"mpr-plat\" readonly><\/div>\n<div class=\"fg\"><label class=\"fl\">产品代号 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" placeholder=\"如 PROD001\"><\/div>\n<div class=\"fg\"><label class=\"fl\">产品名称 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" placeholder=\"如 美妆种草达人\"><\/div>\n<div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>禁用<\/option><\/select><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-prod')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-prod');showT('✅ 产品代号已保存','ok')\">保存<\/button><\/div><\/div><\/div>\n\n<div class=\"mo\" id=\"modal-del\"><div class=\"mc\" style=\"max-width:400px\"><div class=\"mh\"><h3>⚠️ 确认删除<\/h3><button class=\"mx\" onclick=\"closeM('modal-del')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:20px\"><div style=\"font-size:36px\">🗑️<\/div><p style=\"font-size:13px;font-weight:600;margin-top:8px\">确定删除?<\/p><p style=\"font-size:11px;color:var(--sub);margin-top:4px\">已关联账号的平台/产品需先解除<\/p><\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-del')\">取消<\/button><button class=\"btn btn-d\" onclick=\"closeM('modal-del');showT('✅ 已删除','ok')\">确认删除<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni ac\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni\">· 操作日志<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>📦 产品管理 / <b style=\"color:var(--txt)\">平台套件<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">平台套件管理<\/h1>\n<p class=\"pd\">平台(t_platform) → 产品代号(t_product) 两级管理 · 为平台产品账号提供选择源<\/p>\n\n<div style=\"display:flex;gap:8px;margin-bottom:14px;flex-wrap:wrap\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索平台名称\" id=\"sInput\" oninput=\"filterCards()\"><\/div>\n<button class=\"btn btn-p\" onclick=\"openAddPlat()\">+ 新增平台<\/button>\n<\/div>\n\n<!-- 平台卡片 -->\n<div class=\"card-grid\" id=\"platCards\">\n<div class=\"p-card\" data-q=\"小红书\" onclick=\"showPlatDetail('xhs')\"><div class=\"pc-icon\">📕<\/div><div class=\"pc-name\">小红书<\/div><div class=\"pc-url\">https://www.xiaohongshu.com<\/div><div class=\"pc-stat\"><span>📦 3 产品<\/span><span>👤 12 账号<\/span><span class=\"tg tg-ok\">启用<\/span><\/div><\/div>\n<div class=\"p-card\" data-q=\"抖音\" onclick=\"showPlatDetail('douyin')\"><div class=\"pc-icon\">🎵<\/div><div class=\"pc-name\">抖音<\/div><div class=\"pc-url\">https://www.douyin.com<\/div><div class=\"pc-stat\"><span>📦 2 产品<\/span><span>👤 8 账号<\/span><span class=\"tg tg-ok\">启用<\/span><\/div><\/div>\n<div class=\"p-card\" data-q=\"Facebook\" onclick=\"showPlatDetail('fb')\"><div class=\"pc-icon\">📘<\/div><div class=\"pc-name\">Facebook<\/div><div class=\"pc-url\">https://www.facebook.com<\/div><div class=\"pc-stat\"><span>📦 2 产品<\/span><span>👤 5 账号<\/span><span class=\"tg tg-ok\">启用<\/span><\/div><\/div>\n<div class=\"p-card\" data-q=\"TikTok\" onclick=\"showPlatDetail('tiktok')\"><div class=\"pc-icon\">🎬<\/div><div class=\"pc-name\">TikTok<\/div><div class=\"pc-url\">https://www.tiktok.com<\/div><div class=\"pc-stat\"><span>📦 1 产品<\/span><span>👤 3 账号<\/span><span class=\"tg tg-ok\">启用<\/span><\/div><\/div>\n<div class=\"p-card\" data-q=\"微信公众号\" onclick=\"showPlatDetail('wechat')\"><div class=\"pc-icon\">💬<\/div><div class=\"pc-name\">微信公众号<\/div><div class=\"pc-url\">https://mp.weixin.qq.com<\/div><div class=\"pc-stat\"><span>📦 1 产品<\/span><span>👤 2 账号<\/span><span class=\"tg tg-e\">禁用<\/span><\/div><\/div>\n<\/div>\n\n<!-- 平台详情+产品代号 -->\n<div id=\"platDetail\" style=\"display:none\">\n<div style=\"display:flex;align-items:center;gap:8px;margin-bottom:12px\">\n<button class=\"btn btn-g btn-sm\" onclick=\"hidePlatDetail()\">← 返回<\/button>\n<span style=\"font-size:15px;font-weight:700\" id=\"pdName\">小红书<\/span>\n<button class=\"btn btn-g btn-sm\" onclick=\"openEditPlat()\">编辑平台<\/button>\n<button class=\"btn btn-d btn-sm\" onclick=\"openM('modal-del')\">删除平台<\/button>\n<\/div>\n\n<div style=\"background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px;margin-bottom:14px\">\n<div style=\"display:flex;gap:20px;font-size:12px\"><div><span style=\"color:var(--sub)\">平台地址:<\/span><span id=\"pdUrl\">https://www.xiaohongshu.com<\/span><\/div><div><span style=\"color:var(--sub)\">状态:<\/span><span class=\"tg tg-ok\">启用<\/span><\/div><div><span style=\"color:var(--sub)\">关联账号:<\/span><span id=\"pdAcct\">12<\/span><\/div><\/div>\n<\/div>\n\n<div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:10px\">\n<span style=\"font-size:13px;font-weight:600\">📦 产品代号列表<\/span>\n<button class=\"btn btn-p btn-sm\" onclick=\"openAddProd()\">+ 新增产品代号<\/button>\n<\/div>\n<div class=\"tw\"><table><thead><tr><th>产品代号<\/th><th>产品名称<\/th><th>关联账号数<\/th><th>状态<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody id=\"prodTb\">\n<tr><td><code>PROD001<\/code><\/td><td>美妆种草达人<\/td><td>5<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr><td><code>PROD002<\/code><\/td><td>护肤品评测<\/td><td>4<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr><td><code>PROD007<\/code><\/td><td>母婴好物推荐<\/td><td>3<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<\/tbody><\/table><\/div>\n<\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nconst PLAT={xhs:{name:'小红书',url:'https://www.xiaohongshu.com',acct:12,prods:[{c:'PROD001',n:'美妆种草达人',a:5},{c:'PROD002',n:'护肤品评测',a:4},{c:'PROD007',n:'母婴好物推荐',a:3}]},douyin:{name:'抖音',url:'https://www.douyin.com',acct:8,prods:[{c:'PROD003',n:'抖音带货王',a:5},{c:'PROD004',n:'短视频营销',a:3}]},fb:{name:'Facebook',url:'https://www.facebook.com',acct:5,prods:[{c:'PROD006',n:'海外社媒投放',a:3},{c:'PROD008',n:'品牌广告',a:2}]},tiktok:{name:'TikTok',url:'https://www.tiktok.com',acct:3,prods:[{c:'PROD009',n:'TikTok达人',a:3}]},wechat:{name:'微信公众号',url:'https://mp.weixin.qq.com',acct:2,prods:[{c:'PROD005',n:'品牌公众号',a:2}]}};\n\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\n\nfunction showPlatDetail(key){\n const p=PLAT[key];if(!p)return;\n document.getElementById('platDetail').style.display='block';\n document.getElementById('platCards').style.display='none';\n document.getElementById('pdName').textContent=p.name;\n document.getElementById('pdUrl').textContent=p.url;\n document.getElementById('pdAcct').textContent=p.acct;\n document.getElementById('prodTb').innerHTML=p.prods.map(pr=>`<tr><td><code>${pr.c}<\/code><\/td><td>${pr.n}<\/td><td>${pr.a}<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td><button class=\"btn-l\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>`).join('');\n}\nfunction hidePlatDetail(){document.getElementById('platDetail').style.display='none';document.getElementById('platCards').style.display='grid'}\nfunction openAddPlat(){document.getElementById('mpTitle').textContent='新增平台';document.getElementById('mp-name').value='';document.getElementById('mp-url').value='';openM('modal-plat')}\nfunction openEditPlat(){document.getElementById('mpTitle').textContent='编辑平台';document.getElementById('mp-name').value=document.getElementById('pdName').textContent;document.getElementById('mp-url').value=document.getElementById('pdUrl').textContent;openM('modal-plat')}\nfunction openAddProd(){document.getElementById('mprTitle').textContent='新增产品代号';document.getElementById('mpr-plat').value=document.getElementById('pdName').textContent;openM('modal-prod')}\nfunction filterCards(){const q=document.getElementById('sInput').value.toLowerCase();document.querySelectorAll('.p-card').forEach(c=>{c.style.display=c.dataset.q.toLowerCase().includes(q)?'':'none'})}\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>\n",
"14_Skill调用日志.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - Skill调用日志<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.tb{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:140px}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-w{background:#fef3c7;color:#92400e}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.stat{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}.stat-c{background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px 16px}.stat-c .sv{font-size:22px;font-weight:700}.stat-c .sl2{font-size:11px;color:var(--sub)}\n.pg{display:flex;align-items:center;justify-content:space-between;padding:10px 0;font-size:12px;color:var(--sub)}.pgb{padding:4px 10px;border:1px solid var(--bdr);border-radius:5px;font-size:11px;cursor:pointer;background:var(--card);margin:0 2px}.pgb.ac{background:var(--pri);color:#fff;border-color:var(--pri)}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:650px;max-height:88vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.log-box{background:#1e293b;color:#a5f3fc;padding:12px;border-radius:8px;font-family:monospace;font-size:11px;max-height:200px;overflow-y:auto;margin-top:10px}\n.json-box{background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:10px;font-family:monospace;font-size:11px;max-height:160px;overflow-y:auto;white-space:pre-wrap}\n.detail-row{display:flex;border-bottom:1px solid var(--bdr);font-size:12px}.detail-row:last-child{border:none}.dr-l{width:90px;padding:8px 0;color:var(--sub);font-weight:500;flex-shrink:0}.dr-v{padding:8px 0;flex:1}\n.tabs{display:flex;border-bottom:2px solid var(--bdr);margin-bottom:14px}.tab{padding:8px 14px;font-size:12px;font-weight:500;color:var(--sub);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px}.tab.ac{color:var(--pri);border-bottom-color:var(--pri);font-weight:600}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<div class=\"mo\" id=\"modal-log\"><div class=\"mc\"><div class=\"mh\"><h3>📋 调用详情<\/h3><button class=\"mx\" onclick=\"closeM('modal-log')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"tabs\" id=\"lgTabs\"><div class=\"tab ac\" onclick=\"switchLT(0)\">基本信息<\/div><div class=\"tab\" onclick=\"switchLT(1)\">请求参数<\/div><div class=\"tab\" onclick=\"switchLT(2)\">响应结果<\/div><div class=\"tab\" onclick=\"switchLT(3)\">执行日志<\/div><\/div>\n<div id=\"lt0\"><div class=\"detail-row\"><div class=\"dr-l\">调用ID<\/div><div class=\"dr-v\"><code>LOG-20260423-001<\/code><\/div><\/div><div class=\"detail-row\"><div class=\"dr-l\">Skill<\/div><div class=\"dr-v\">小红书笔记发布<\/div><\/div><div class=\"detail-row\"><div class=\"dr-l\">执行器<\/div><div class=\"dr-v\">🦞 龙虾执行器<\/div><\/div><div class=\"detail-row\"><div class=\"dr-l\">调用者<\/div><div class=\"dr-v\">张三(投放一组)<\/div><\/div><div class=\"detail-row\"><div class=\"dr-l\">状态<\/div><div class=\"dr-v\"><span class=\"tg tg-ok\">SUCCESS<\/span><\/div><\/div><div class=\"detail-row\"><div class=\"dr-l\">耗时<\/div><div class=\"dr-v\">3.2s<\/div><\/div><div class=\"detail-row\"><div class=\"dr-l\">时间<\/div><div class=\"dr-v\">2026-04-23 10:30:15<\/div><\/div><\/div>\n<div id=\"lt1\" style=\"display:none\"><div class=\"json-box\">{\n \"product_id\": \"PROD001\",\n \"content\": \"今日美妆好物分享!\",\n \"tags\": [\"美妆\", \"种草\"],\n \"channel_code\": \"IC001\"\n}<\/div><\/div>\n<div id=\"lt2\" style=\"display:none\"><div class=\"json-box\">{\n \"status\": \"published\",\n \"post_id\": \"xhs_98765\",\n \"post_url\": \"https://www.xiaohongshu.com/explore/98765\"\n}<\/div><\/div>\n<div id=\"lt3\" style=\"display:none\"><div class=\"log-box\"><div>[10:30:15] 开始调用 Skill: 小红书笔记发布<\/div><div>[10:30:15] 参数校验通过<\/div><div>[10:30:15] 路由: 龙虾执行器 → agent_xhs_publish_01<\/div><div style=\"color:#fbbf24\">[10:30:16] 执行中...<\/div><div style=\"color:#4ade80\">[10:30:18] ✅ 调用成功 (3.2s)<\/div><\/div><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-log')\">关闭<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni ac\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni\">· 操作日志<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>🧠 Skill中心 / <b style=\"color:var(--txt)\">调用日志<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">Skill调用日志<\/h1>\n<p class=\"pd\">全量调用记录 · 请求/响应追踪 · 执行日志<\/p>\n\n<div class=\"stat\">\n<div class=\"stat-c\"><div class=\"sv\">12,456<\/div><div class=\"sl2\">总调用<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--ok)\">12,102<\/div><div class=\"sl2\">成功<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--err)\">354<\/div><div class=\"sl2\">失败<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\">2.4s<\/div><div class=\"sl2\">平均耗时<\/div><\/div>\n<\/div>\n\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索Skill/调用者\" id=\"sInput\" oninput=\"filterT()\"><\/div>\n<select class=\"sl\" id=\"fSt\" onchange=\"filterT()\"><option value=\"\">全部状态<\/option><option value=\"SUCCESS\">成功<\/option><option value=\"FAILED\">失败<\/option><option value=\"TIMEOUT\">超时<\/option><\/select>\n<select class=\"sl\" id=\"fExec\" onchange=\"filterT()\"><option value=\"\">全部执行器<\/option><option value=\"lobster\">🦞 龙虾<\/option><option value=\"script\">📜 脚本<\/option><\/select>\n<select class=\"sl\"><option>最近7天<\/option><option>最近30天<\/option><option>全部<\/option><\/select>\n<button class=\"btn btn-g btn-sm\" style=\"margin-left:auto\" onclick=\"showT('📥 导出成功','ok')\">导出CSV<\/button>\n<\/div>\n\n<div class=\"tw\"><table><thead><tr><th>调用ID<\/th><th>Skill<\/th><th>执行器<\/th><th>产品<\/th><th>调用者<\/th><th>状态<\/th><th>耗时<\/th><th>时间<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody id=\"ltb\">\n<tr data-q=\"LOG-001 小红书笔记发布 张三\" data-st=\"SUCCESS\" data-exec=\"lobster\"><td><code style=\"font-size:10px\">LOG-001<\/code><\/td><td>小红书笔记发布<\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞<\/span><\/td><td>PROD001<\/td><td>张三<\/td><td><span class=\"tg tg-ok\">SUCCESS<\/span><\/td><td>3.2s<\/td><td>04-23 10:30<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-log')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"LOG-002 抖音视频上传 张三\" data-st=\"SUCCESS\" data-exec=\"lobster\"><td><code style=\"font-size:10px\">LOG-002<\/code><\/td><td>抖音视频上传<\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞<\/span><\/td><td>PROD003<\/td><td>张三<\/td><td><span class=\"tg tg-ok\">SUCCESS<\/span><\/td><td>5.8s<\/td><td>04-23 10:15<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-log')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"LOG-003 竞品数据采集 李四\" data-st=\"SUCCESS\" data-exec=\"script\"><td><code style=\"font-size:10px\">LOG-003<\/code><\/td><td>竞品数据采集<\/td><td><span class=\"tg tg-p\">📜<\/span><\/td><td>PROD002<\/td><td>李四<\/td><td><span class=\"tg tg-ok\">SUCCESS<\/span><\/td><td>1.1s<\/td><td>04-23 10:00<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-log')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"LOG-004 Facebook广告 赵六\" data-st=\"FAILED\" data-exec=\"lobster\"><td><code style=\"font-size:10px\">LOG-004<\/code><\/td><td>Facebook广告投放<\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞<\/span><\/td><td>PROD006<\/td><td>赵六<\/td><td><span class=\"tg tg-e\">FAILED<\/span><\/td><td>1.5s<\/td><td>04-23 09:45<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-log')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"LOG-005 数据清洗 王五\" data-st=\"SUCCESS\" data-exec=\"script\"><td><code style=\"font-size:10px\">LOG-005<\/code><\/td><td>数据清洗脚本<\/td><td><span class=\"tg tg-p\">📜<\/span><\/td><td>PROD001<\/td><td>王五<\/td><td><span class=\"tg tg-ok\">SUCCESS<\/span><\/td><td>0.8s<\/td><td>04-23 09:30<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-log')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"LOG-006 小红书笔记 王五\" data-st=\"TIMEOUT\" data-exec=\"lobster\"><td><code style=\"font-size:10px\">LOG-006<\/code><\/td><td>小红书笔记发布<\/td><td><span class=\"tg tg-e\" style=\"background:#fef2f2;color:#dc2626\">🦞<\/span><\/td><td>PROD002<\/td><td>王五<\/td><td><span class=\"tg tg-w\">TIMEOUT<\/span><\/td><td>30s<\/td><td>04-23 09:00<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-log')\">详情<\/button><\/td><\/tr>\n<\/tbody><\/table><\/div>\n<div class=\"pg\"><span>共 6 条(示例)<\/span><div><span class=\"pgb ac\">1<\/span><span class=\"pgb\">2<\/span><\/div><\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\nfunction switchLT(i){document.querySelectorAll('#lgTabs .tab').forEach((t,j)=>t.classList.toggle('ac',j===i));['lt0','lt1','lt2','lt3'].forEach((d,j)=>document.getElementById(d).style.display=j===i?'block':'none')}\nfunction filterT(){const q=document.getElementById('sInput').value.toLowerCase();const st=document.getElementById('fSt').value;const exec=document.getElementById('fExec').value;document.querySelectorAll('#ltb tr').forEach(tr=>{const d=tr.dataset;tr.style.display=(!q||d.q.toLowerCase().includes(q))&&(!st||d.st===st)&&(!exec||d.exec===exec)?'':'none'})}\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>\n",
"15_操作日志.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 操作日志<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.tb{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:140px}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-w{background:#fef3c7;color:#92400e}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-g{background:#f1f5f9;color:#64748b}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.pg{display:flex;align-items:center;justify-content:space-between;padding:10px 0;font-size:12px;color:var(--sub)}.pgb{padding:4px 10px;border:1px solid var(--bdr);border-radius:5px;font-size:11px;cursor:pointer;background:var(--card);margin:0 2px}.pgb.ac{background:var(--pri);color:#fff;border-color:var(--pri)}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:600px;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.json-box{background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:10px;font-family:monospace;font-size:11px;max-height:200px;overflow-y:auto;white-space:pre-wrap}\n.detail-row{display:flex;border-bottom:1px solid var(--bdr);font-size:12px}.detail-row:last-child{border:none}.dr-l{width:80px;padding:8px 0;color:var(--sub);font-weight:500;flex-shrink:0}.dr-v{padding:8px 0;flex:1}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<div class=\"mo\" id=\"modal-detail\"><div class=\"mc\"><div class=\"mh\"><h3>📋 操作详情<\/h3><button class=\"mx\" onclick=\"closeM('modal-detail')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"detail-row\"><div class=\"dr-l\">日志ID<\/div><div class=\"dr-v\"><code>OPLOG-001<\/code><\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">操作人<\/div><div class=\"dr-v\">admin<\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">模块<\/div><div class=\"dr-v\">用户管理<\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">操作<\/div><div class=\"dr-v\"><span class=\"tg tg-ok\">新增<\/span><\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">IP<\/div><div class=\"dr-v\">192.168.1.100<\/div><\/div>\n<div class=\"detail-row\"><div class=\"dr-l\">时间<\/div><div class=\"dr-v\">2026-04-23 10:30:15<\/div><\/div>\n<div style=\"margin-top:10px;font-size:12px;font-weight:600;margin-bottom:6px\">请求参数<\/div>\n<div class=\"json-box\">{\n \"username\": \"zhangsan\",\n \"real_name\": \"张三\",\n \"dept_id\": 3,\n \"role_ids\": [1, 2]\n}<\/div>\n<div style=\"margin-top:10px;font-size:12px;font-weight:600;margin-bottom:6px\">变更内容<\/div>\n<div class=\"json-box\">{\n \"before\": null,\n \"after\": {\n \"id\": 15,\n \"username\": \"zhangsan\",\n \"status\": 1\n }\n}<\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-detail')\">关闭<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni ac\">· 操作日志<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>📝 日志中心 / <b style=\"color:var(--txt)\">操作日志<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">操作日志<\/h1>\n<p class=\"pd\">全局操作审计 · 变更追踪 · 请求参数/变更内容记录<\/p>\n\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索操作人/模块\" id=\"sInput\" oninput=\"filterT()\"><\/div>\n<select class=\"sl\" id=\"fMod\" onchange=\"filterT()\"><option value=\"\">全部模块<\/option><option value=\"用户管理\">用户管理<\/option><option value=\"角色管理\">角色管理<\/option><option value=\"产品管理\">产品管理<\/option><option value=\"Skill管理\">Skill管理<\/option><option value=\"任务管理\">任务管理<\/option><option value=\"平台产品账号\">平台产品账号<\/option><option value=\"登录\">登录<\/option><\/select>\n<select class=\"sl\" id=\"fAct\" onchange=\"filterT()\"><option value=\"\">全部操作<\/option><option value=\"新增\">新增<\/option><option value=\"编辑\">编辑<\/option><option value=\"删除\">删除<\/option><option value=\"登录\">登录<\/option><option value=\"导出\">导出<\/option><\/select>\n<select class=\"sl\"><option>最近7天<\/option><option>最近30天<\/option><option>全部<\/option><\/select>\n<button class=\"btn btn-g btn-sm\" style=\"margin-left:auto\" onclick=\"showT('📥 导出成功','ok')\">导出<\/button>\n<\/div>\n\n<div class=\"tw\"><table><thead><tr><th>日志ID<\/th><th>操作人<\/th><th>模块<\/th><th>操作<\/th><th>描述<\/th><th>IP<\/th><th>时间<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody id=\"otb\">\n<tr data-q=\"OPLOG-001 admin 用户管理\" data-mod=\"用户管理\" data-act=\"新增\"><td><code style=\"font-size:10px\">OPLOG-001<\/code><\/td><td>admin<\/td><td>用户管理<\/td><td><span class=\"tg tg-ok\">新增<\/span><\/td><td>新增用户: 张三<\/td><td>192.168.1.100<\/td><td>04-23 10:30<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"OPLOG-002 admin 角色管理\" data-mod=\"角色管理\" data-act=\"编辑\"><td><code style=\"font-size:10px\">OPLOG-002<\/code><\/td><td>admin<\/td><td>角色管理<\/td><td><span class=\"tg tg-i\">编辑<\/span><\/td><td>修改角色权限: 投放一组主管<\/td><td>192.168.1.100<\/td><td>04-23 10:25<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"OPLOG-003 张三 任务管理\" data-mod=\"任务管理\" data-act=\"新增\"><td><code style=\"font-size:10px\">OPLOG-003<\/code><\/td><td>张三<\/td><td>任务管理<\/td><td><span class=\"tg tg-ok\">新增<\/span><\/td><td>创建任务: 小红书笔记发布<\/td><td>192.168.1.105<\/td><td>04-23 10:20<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"OPLOG-004 admin Skill管理\" data-mod=\"Skill管理\" data-act=\"编辑\"><td><code style=\"font-size:10px\">OPLOG-004<\/code><\/td><td>admin<\/td><td>Skill管理<\/td><td><span class=\"tg tg-i\">编辑<\/span><\/td><td>更新Skill: 竞品数据采集 执行器配置<\/td><td>192.168.1.100<\/td><td>04-23 10:15<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"OPLOG-005 admin 平台产品账号\" data-mod=\"平台产品账号\" data-act=\"新增\"><td><code style=\"font-size:10px\">OPLOG-005<\/code><\/td><td>admin<\/td><td>平台产品账号<\/td><td><span class=\"tg tg-ok\">新增<\/span><\/td><td>新增账号: 小红书-PROD001-beauty01<\/td><td>192.168.1.100<\/td><td>04-23 10:10<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"OPLOG-006 admin 产品管理\" data-mod=\"产品管理\" data-act=\"删除\"><td><code style=\"font-size:10px\">OPLOG-006<\/code><\/td><td>admin<\/td><td>产品管理<\/td><td><span class=\"tg tg-e\">删除<\/span><\/td><td>删除产品: 测试产品X<\/td><td>192.168.1.100<\/td><td>04-23 09:50<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"OPLOG-007 李四 登录\" data-mod=\"登录\" data-act=\"登录\"><td><code style=\"font-size:10px\">OPLOG-007<\/code><\/td><td>李四<\/td><td>登录<\/td><td><span class=\"tg tg-g\">登录<\/span><\/td><td>用户登录成功<\/td><td>192.168.1.108<\/td><td>04-23 09:30<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button><\/td><\/tr>\n<tr data-q=\"OPLOG-008 张三 任务管理\" data-mod=\"任务管理\" data-act=\"导出\"><td><code style=\"font-size:10px\">OPLOG-008<\/code><\/td><td>张三<\/td><td>任务管理<\/td><td><span class=\"tg tg-w\">导出<\/span><\/td><td>导出任务列表(共45条)<\/td><td>192.168.1.105<\/td><td>04-23 09:15<\/td><td><button class=\"btn-l\" onclick=\"openM('modal-detail')\">详情<\/button><\/td><\/tr>\n<\/tbody><\/table><\/div>\n<div class=\"pg\"><span>共 8 条<\/span><div><span class=\"pgb ac\">1<\/span><span class=\"pgb\">2<\/span><\/div><\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\nfunction filterT(){const q=document.getElementById('sInput').value.toLowerCase();const mod=document.getElementById('fMod').value;const act=document.getElementById('fAct').value;document.querySelectorAll('#otb tr').forEach(tr=>{const d=tr.dataset;tr.style.display=(!q||d.q.toLowerCase().includes(q))&&(!mod||d.mod===mod)&&(!act||d.act===act)?'':'none'})}\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>",
"16_统计报表.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 统计报表<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}.btn-p{background:var(--pri);color:#fff}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\n.stat{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:20px}.stat-c{background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:16px}.stat-c .sv{font-size:26px;font-weight:700}.stat-c .sl2{font-size:11px;color:var(--sub)}.stat-c .delta{font-size:11px;margin-top:4px}\n.chart-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:14px}.chart-card{background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:16px}.chart-card h3{font-size:13px;font-weight:600;margin-bottom:12px}\n.bar-chart{display:flex;align-items:flex-end;gap:8px;height:160px;padding-top:10px}.bar-col{display:flex;flex-direction:column;align-items:center;flex:1}.bar-fill{width:100%;border-radius:4px 4px 0 0;transition:height .5s;min-height:4px}.bar-label{font-size:9px;color:var(--sub);margin-top:4px;white-space:nowrap}.bar-val{font-size:10px;font-weight:600;margin-bottom:2px}\n.pie-chart{display:flex;align-items:center;gap:20px}.pie-svg{width:140px;height:140px}.pie-legend{font-size:11px}.pie-legend div{display:flex;align-items:center;gap:6px;margin-bottom:6px}.pie-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}\n.line-chart{position:relative;height:160px;border-left:1px solid var(--bdr);border-bottom:1px solid var(--bdr)}.line-chart svg{width:100%;height:100%}\n.rank-list{font-size:12px}.rank-item{display:flex;align-items:center;gap:8px;padding:6px 0;border-bottom:1px solid #f1f5f9}.rank-num{width:20px;height:20px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;color:#fff;flex-shrink:0}.rank-name{flex:1}.rank-val{font-weight:600}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.tabs{display:flex;border-bottom:2px solid var(--bdr);margin-bottom:16px}.tab{padding:8px 16px;font-size:12px;font-weight:500;color:var(--sub);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px}.tab.ac{color:var(--pri);border-bottom-color:var(--pri);font-weight:600}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">日志/设置<\/div><div class=\"ni\">· 操作日志<\/div><div class=\"ni ac\">· 统计报表<\/div><div class=\"ni\">· 系统设置<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>📊 日志中心 / <b style=\"color:var(--txt)\">统计报表<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">统计报表<\/h1>\n<p class=\"pd\">任务执行趋势 · Skill调用分布 · 产品/用户排行<\/p>\n\n<div style=\"display:flex;gap:8px;margin-bottom:16px\">\n<select class=\"sl\" id=\"dateRange\" onchange=\"refreshCharts()\"><option>最近7天<\/option><option>最近30天<\/option><option>本月<\/option><option>上月<\/option><\/select>\n<button class=\"btn btn-g btn-sm\" onclick=\"refreshCharts()\">🔄 刷新<\/button>\n<button class=\"btn btn-g btn-sm\" onclick=\"showT('📥 报表已导出','ok')\">导出PDF<\/button>\n<\/div>\n\n<div class=\"stat\">\n<div class=\"stat-c\"><div class=\"sv\">1,234<\/div><div class=\"sl2\">任务总数<\/div><div class=\"delta\" style=\"color:var(--ok)\">↑ 12.5% vs 上周<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--ok)\">96.3%<\/div><div class=\"sl2\">成功率<\/div><div class=\"delta\" style=\"color:var(--ok)\">↑ 1.2%<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\">2.4s<\/div><div class=\"sl2\">平均耗时<\/div><div class=\"delta\" style=\"color:var(--ok)\">↓ 0.3s<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\">18<\/div><div class=\"sl2\">活跃Skill<\/div><div class=\"delta\" style=\"color:var(--sub)\">— 持平<\/div><\/div>\n<\/div>\n\n<div class=\"chart-grid\">\n<!-- 任务趋势 -->\n<div class=\"chart-card\"><h3>📈 任务执行趋势(7日)<\/h3>\n<div class=\"bar-chart\" id=\"trendChart\">\n<div class=\"bar-col\"><div class=\"bar-val\">156<\/div><div class=\"bar-fill\" style=\"height:65%;background:var(--pri)\"><\/div><div class=\"bar-label\">04-17<\/div><\/div>\n<div class=\"bar-col\"><div class=\"bar-val\">189<\/div><div class=\"bar-fill\" style=\"height:78%;background:var(--pri)\"><\/div><div class=\"bar-label\">04-18<\/div><\/div>\n<div class=\"bar-col\"><div class=\"bar-val\">145<\/div><div class=\"bar-fill\" style=\"height:60%;background:var(--pri)\"><\/div><div class=\"bar-label\">04-19<\/div><\/div>\n<div class=\"bar-col\"><div class=\"bar-val\">201<\/div><div class=\"bar-fill\" style=\"height:84%;background:var(--pri)\"><\/div><div class=\"bar-label\">04-20<\/div><\/div>\n<div class=\"bar-col\"><div class=\"bar-val\">178<\/div><div class=\"bar-fill\" style=\"height:74%;background:var(--pri)\"><\/div><div class=\"bar-label\">04-21<\/div><\/div>\n<div class=\"bar-col\"><div class=\"bar-val\">210<\/div><div class=\"bar-fill\" style=\"height:88%;background:var(--pri)\"><\/div><div class=\"bar-label\">04-22<\/div><\/div>\n<div class=\"bar-col\"><div class=\"bar-val\">155<\/div><div class=\"bar-fill\" style=\"height:64%;background:var(--pri)\"><\/div><div class=\"bar-label\">04-23<\/div><\/div>\n<\/div><\/div>\n\n<!-- 执行器分布 -->\n<div class=\"chart-card\"><h3>🎯 执行器分布<\/h3>\n<div class=\"pie-chart\">\n<svg class=\"pie-svg\" viewBox=\"0 0 42 42\"><circle cx=\"21\" cy=\"21\" r=\"15.9\" fill=\"transparent\" stroke=\"#6366f1\" stroke-width=\"6\" stroke-dasharray=\"67 33\" stroke-dashoffset=\"25\"/><circle cx=\"21\" cy=\"21\" r=\"15.9\" fill=\"transparent\" stroke=\"#f59e0b\" stroke-width=\"6\" stroke-dasharray=\"33 67\" stroke-dashoffset=\"58\"/><\/svg>\n<div class=\"pie-legend\">\n<div><div class=\"pie-dot\" style=\"background:#6366f1\"><\/div>🦞 龙虾执行器 <b>67%<\/b> (827)<\/div>\n<div><div class=\"pie-dot\" style=\"background:#f59e0b\"><\/div>📜 脚本执行器 <b>33%<\/b> (407)<\/div>\n<\/div><\/div><\/div>\n\n<!-- 状态分布 -->\n<div class=\"chart-card\"><h3>📊 任务状态分布<\/h3>\n<div class=\"bar-chart\">\n<div class=\"bar-col\"><div class=\"bar-val\">1,089<\/div><div class=\"bar-fill\" style=\"height:90%;background:var(--ok)\"><\/div><div class=\"bar-label\">成功<\/div><\/div>\n<div class=\"bar-col\"><div class=\"bar-val\">45<\/div><div class=\"bar-fill\" style=\"height:12%;background:var(--err)\"><\/div><div class=\"bar-label\">失败<\/div><\/div>\n<div class=\"bar-col\"><div class=\"bar-val\">8<\/div><div class=\"bar-fill\" style=\"height:6%;background:#3b82f6\"><\/div><div class=\"bar-label\">运行中<\/div><\/div>\n<div class=\"bar-col\"><div class=\"bar-val\">92<\/div><div class=\"bar-fill\" style=\"height:18%;background:var(--warn)\"><\/div><div class=\"bar-label\">超时<\/div><\/div>\n<\/div><\/div>\n\n<!-- Skill排行 -->\n<div class=\"chart-card\"><h3>🏆 Skill调用排行 TOP5<\/h3>\n<div class=\"rank-list\">\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:#f59e0b\">1<\/div><div class=\"rank-name\">数据清洗脚本<\/div><div class=\"rank-val\">5,123<\/div><\/div>\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:#94a3b8\">2<\/div><div class=\"rank-name\">竞品数据采集<\/div><div class=\"rank-val\">3,401<\/div><\/div>\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:#d97706\">3<\/div><div class=\"rank-name\">小红书笔记发布<\/div><div class=\"rank-val\">1,256<\/div><\/div>\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:var(--sub)\">4<\/div><div class=\"rank-name\">抖音视频上传<\/div><div class=\"rank-val\">892<\/div><\/div>\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:var(--sub)\">5<\/div><div class=\"rank-name\">Facebook广告投放<\/div><div class=\"rank-val\">567<\/div><\/div>\n<\/div><\/div>\n<\/div>\n\n<!-- 产品/用户排行 -->\n<div class=\"chart-grid\">\n<div class=\"chart-card\"><h3>📦 产品任务量排行<\/h3>\n<div class=\"rank-list\">\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:#f59e0b\">1<\/div><div class=\"rank-name\">PROD001 美妆种草达人<\/div><div class=\"rank-val\">456<\/div><\/div>\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:#94a3b8\">2<\/div><div class=\"rank-name\">PROD003 抖音带货王<\/div><div class=\"rank-val\">312<\/div><\/div>\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:#d97706\">3<\/div><div class=\"rank-name\">PROD002 护肤品评测<\/div><div class=\"rank-val\">289<\/div><\/div>\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:var(--sub)\">4<\/div><div class=\"rank-name\">PROD006 海外社媒投放<\/div><div class=\"rank-val\">177<\/div><\/div>\n<\/div><\/div>\n<div class=\"chart-card\"><h3>👤 用户活跃排行<\/h3>\n<div class=\"rank-list\">\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:#f59e0b\">1<\/div><div class=\"rank-name\">张三(投放一组)<\/div><div class=\"rank-val\">389 任务<\/div><\/div>\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:#94a3b8\">2<\/div><div class=\"rank-name\">李四(投放二组)<\/div><div class=\"rank-val\">267 任务<\/div><\/div>\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:#d97706\">3<\/div><div class=\"rank-name\">王五(投放一组)<\/div><div class=\"rank-val\">198 任务<\/div><\/div>\n<div class=\"rank-item\"><div class=\"rank-num\" style=\"background:var(--sub)\">4<\/div><div class=\"rank-name\">赵六(投放二组)<\/div><div class=\"rank-val\">156 任务<\/div><\/div>\n<\/div><\/div>\n<\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\nfunction refreshCharts(){\n document.querySelectorAll('.bar-fill').forEach(b=>{\n const h=parseInt(b.style.height);\n b.style.height='0%';\n setTimeout(()=>b.style.height=h+'%',50);\n });\n showT('📊 数据已刷新','ok');\n}\n<\/script>\n<\/body><\/html>",
"17_执行器配置.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 执行器配置<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}.btn-s{background:var(--ok);color:#fff}.btn-w{background:var(--warn);color:#fff}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-w{background:#fef3c7;color:#92400e}\n.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}.fl .rq{color:var(--err)}.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none}.fi:focus{border-color:var(--pri)}.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:580px;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.exec-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}.exec-card{background:var(--card);border:2px solid var(--bdr);border-radius:12px;padding:20px;transition:all .15s}.exec-card:hover{border-color:#a5b4fc}.exec-card .ec-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}.ec-icon{font-size:36px}.ec-title{font-size:16px;font-weight:700}.ec-desc{font-size:11px;color:var(--sub);margin-bottom:12px}\n.config-row{display:flex;justify-content:space-between;align-items:center;padding:8px 0;border-bottom:1px solid #f1f5f9;font-size:12px}.config-row:last-child{border:none}.cr-label{color:var(--sub)}.cr-val{font-weight:500}\n.health-bar{display:flex;gap:2px;margin-top:8px}.hb-dot{width:8px;height:20px;border-radius:2px}\n.note{background:#eff6ff;border-left:3px solid var(--pri);padding:8px 12px;border-radius:0 6px 6px 0;font-size:11px;color:var(--sub);margin-bottom:14px}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<div class=\"mo\" id=\"modal-lobster\"><div class=\"mc\"><div class=\"mh\"><h3>🦞 龙虾执行器配置<\/h3><button class=\"mx\" onclick=\"closeM('modal-lobster')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fg\"><label class=\"fl\">API地址 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" value=\"https://api.lobster-agent.com/v1\"><\/div>\n<div class=\"fg\"><label class=\"fl\">API Key <span class=\"rq\">*<\/span><\/label><input class=\"fi\" type=\"password\" value=\"sk-lobster-production-key-xxx\"><\/div>\n<div class=\"fr\"><div class=\"fg\"><label class=\"fl\">超时时间(秒)<\/label><input class=\"fi\" type=\"number\" value=\"30\"><\/div><div class=\"fg\"><label class=\"fl\">重试次数<\/label><input class=\"fi\" type=\"number\" value=\"3\"><\/div><\/div>\n<div class=\"fr\"><div class=\"fg\"><label class=\"fl\">并发上限<\/label><input class=\"fi\" type=\"number\" value=\"10\"><\/div><div class=\"fg\"><label class=\"fl\">轮询间隔(ms)<\/label><input class=\"fi\" type=\"number\" value=\"2000\"><\/div><\/div>\n<div class=\"fg\"><label class=\"fl\">回调URL<\/label><input class=\"fi\" value=\"https://agent.example.com/api/callback/lobster\"><\/div>\n<div style=\"margin-top:10px\"><button class=\"btn btn-s btn-sm\" onclick=\"showT('✅ 龙虾平台连通正常','ok')\">🔌 测试连通性<\/button><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-lobster')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-lobster');showT('✅ 配置已保存','ok')\">保存<\/button><\/div><\/div><\/div>\n\n<div class=\"mo\" id=\"modal-script\"><div class=\"mc\"><div class=\"mh\"><h3>📜 脚本执行器配置<\/h3><button class=\"mx\" onclick=\"closeM('modal-script')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fg\"><label class=\"fl\">工作目录 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" value=\"/opt/agent-scripts/\"><\/div>\n<div class=\"fr\"><div class=\"fg\"><label class=\"fl\">Python路径<\/label><input class=\"fi\" value=\"/usr/bin/python3\"><\/div><div class=\"fg\"><label class=\"fl\">Node路径<\/label><input class=\"fi\" value=\"/usr/bin/node\"><\/div><\/div>\n<div class=\"fr\"><div class=\"fg\"><label class=\"fl\">全局超时(秒)<\/label><input class=\"fi\" type=\"number\" value=\"60\"><\/div><div class=\"fg\"><label class=\"fl\">并发上限<\/label><input class=\"fi\" type=\"number\" value=\"5\"><\/div><\/div>\n<div class=\"fg\"><label class=\"fl\">沙箱模式<\/label><select class=\"fs\"><option>Docker容器<\/option><option>本地进程<\/option><option>虚拟环境<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">日志目录<\/label><input class=\"fi\" value=\"/var/log/agent-scripts/\"><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-script')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-script');showT('✅ 配置已保存','ok')\">保存<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">系统设置<\/div><div class=\"ni ac\">· 执行器配置<\/div><div class=\"ni\">· 脚本模板<\/div><div class=\"ni\">· 定时任务<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>⚙️ 系统设置 / <b style=\"color:var(--txt)\">执行器配置<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">执行器配置<\/h1>\n<p class=\"pd\">双执行器管理 · 连接参数 · 健康监控 · 并发/超时/重试策略<\/p>\n\n<div class=\"note\">⚠️ 仅超级管理员可修改执行器配置(RB-13)<\/div>\n\n<div class=\"exec-grid\">\n<!-- 龙虾执行器 -->\n<div class=\"exec-card\" style=\"border-color:#dc2626\">\n<div class=\"ec-head\"><div><div class=\"ec-icon\">🦞<\/div><div class=\"ec-title\">龙虾执行器<\/div><\/div><span class=\"tg tg-ok\">运行中<\/span><\/div>\n<div class=\"ec-desc\">第三方Agent平台,通过API对接龙虾平台执行任务<\/div>\n<div class=\"config-row\"><span class=\"cr-label\">API地址<\/span><span class=\"cr-val\">api.lobster-agent.com<\/span><\/div>\n<div class=\"config-row\"><span class=\"cr-label\">超时<\/span><span class=\"cr-val\">30s<\/span><\/div>\n<div class=\"config-row\"><span class=\"cr-label\">重试<\/span><span class=\"cr-val\">3次<\/span><\/div>\n<div class=\"config-row\"><span class=\"cr-label\">并发<\/span><span class=\"cr-val\">10<\/span><\/div>\n<div class=\"config-row\"><span class=\"cr-label\">当前任务<\/span><span class=\"cr-val\" style=\"color:var(--pri);font-weight:700\">3 / 10<\/span><\/div>\n<div style=\"font-size:11px;color:var(--sub);margin-top:8px\">最近24h健康状态<\/div>\n<div class=\"health-bar\" id=\"hb1\"><\/div>\n<div style=\"margin-top:12px;display:flex;gap:6px\">\n<button class=\"btn btn-p btn-sm\" onclick=\"openM('modal-lobster')\">⚙️ 配置<\/button>\n<button class=\"btn btn-s btn-sm\" onclick=\"showT('✅ 连通正常 (120ms)','ok')\">🔌 测试<\/button>\n<button class=\"btn btn-w btn-sm\" onclick=\"showT('🔄 已重启','ok')\">🔄 重启<\/button>\n<\/div><\/div>\n\n<!-- 脚本执行器 -->\n<div class=\"exec-card\" style=\"border-color:var(--pri)\">\n<div class=\"ec-head\"><div><div class=\"ec-icon\">📜<\/div><div class=\"ec-title\">脚本执行器<\/div><\/div><span class=\"tg tg-ok\">运行中<\/span><\/div>\n<div class=\"ec-desc\">系统内置脚本引擎,支持Python/Node.js/Shell脚本<\/div>\n<div class=\"config-row\"><span class=\"cr-label\">工作目录<\/span><span class=\"cr-val\">/opt/agent-scripts/<\/span><\/div>\n<div class=\"config-row\"><span class=\"cr-label\">超时<\/span><span class=\"cr-val\">60s<\/span><\/div>\n<div class=\"config-row\"><span class=\"cr-label\">并发<\/span><span class=\"cr-val\">5<\/span><\/div>\n<div class=\"config-row\"><span class=\"cr-label\">沙箱<\/span><span class=\"cr-val\">Docker容器<\/span><\/div>\n<div class=\"config-row\"><span class=\"cr-label\">当前任务<\/span><span class=\"cr-val\" style=\"color:var(--pri);font-weight:700\">1 / 5<\/span><\/div>\n<div style=\"font-size:11px;color:var(--sub);margin-top:8px\">最近24h健康状态<\/div>\n<div class=\"health-bar\" id=\"hb2\"><\/div>\n<div style=\"margin-top:12px;display:flex;gap:6px\">\n<button class=\"btn btn-p btn-sm\" onclick=\"openM('modal-script')\">⚙️ 配置<\/button>\n<button class=\"btn btn-s btn-sm\" onclick=\"showT('✅ 脚本引擎正常','ok')\">🔌 测试<\/button>\n<button class=\"btn btn-w btn-sm\" onclick=\"showT('🔄 已重启','ok')\">🔄 重启<\/button>\n<\/div><\/div>\n<\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\nfunction initHealth(id){const el=document.getElementById(id);let html='';for(let i=0;i<24;i++){const ok=Math.random()>0.08;html+=`<div class=\"hb-dot\" style=\"background:${ok?'var(--ok)':'var(--err)'}\" title=\"${23-i}h前: ${ok?'正常':'异常'}\"><\/div>`}el.innerHTML=html}\ninitHealth('hb1');initHealth('hb2');\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>",
"18_脚本模板管理.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 脚本模板管理<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.tb{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:140px}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}.btn-s{background:var(--ok);color:#fff}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-w{background:#fef3c7;color:#92400e}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}.fl .rq{color:var(--err)}.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none}.fi:focus{border-color:var(--pri)}.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:700px;max-height:88vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.code-area{width:100%;min-height:200px;padding:12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;font-family:'Fira Code',monospace;background:#1e293b;color:#e2e8f0;resize:vertical;line-height:1.5;tab-size:4}\n.code-header{display:flex;justify-content:space-between;align-items:center;background:#334155;padding:6px 12px;border-radius:7px 7px 0 0;font-size:11px;color:#94a3b8}.code-area.no-top{border-radius:0 0 7px 7px}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<div class=\"mo\" id=\"modal-tpl\"><div class=\"mc\"><div class=\"mh\"><h3 id=\"mtTitle\">新增脚本模板<\/h3><button class=\"mx\" onclick=\"closeM('modal-tpl')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fr\"><div class=\"fg\"><label class=\"fl\">模板名称 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mt-name\" placeholder=\"如 通用HTTP请求\"><\/div>\n<div class=\"fg\"><label class=\"fl\">脚本类型 <span class=\"rq\">*<\/span><\/label><select class=\"fs\" id=\"mt-type\" onchange=\"onTplType(this.value)\"><option value=\"python\">Python<\/option><option value=\"node\">Node.js<\/option><option value=\"shell\">Shell<\/option><\/select><\/div><\/div>\n<div class=\"fg\"><label class=\"fl\">描述<\/label><textarea class=\"fi\" rows=\"2\" placeholder=\"模板功能描述\"><\/textarea><\/div>\n<div class=\"fg\"><label class=\"fl\">脚本代码 <span class=\"rq\">*<\/span><\/label>\n<div class=\"code-header\"><span id=\"codeLang\">Python<\/span><button class=\"btn btn-g btn-sm\" style=\"color:#94a3b8;border-color:#475569\" onclick=\"formatCode()\">格式化<\/button><\/div>\n<textarea class=\"code-area no-top\" id=\"codeArea\">#!/usr/bin/env python3\nimport requests\nimport json\nimport os\n\ndef main():\n \"\"\"通用HTTP请求模板\"\"\"\n api_key = os.environ.get('API_KEY', '')\n url = os.environ.get('TARGET_URL', '')\n \n headers = {\n 'Authorization': f'Bearer {api_key}',\n 'Content-Type': 'application/json'\n }\n \n response = requests.get(url, headers=headers)\n result = response.json()\n \n print(json.dumps({\n 'status': 'success',\n 'data': result\n }))\n\nif __name__ == '__main__':\n main()<\/textarea><\/div>\n<div class=\"fg\"><label class=\"fl\">环境变量声明<\/label>\n<div id=\"envList\">\n<div style=\"display:flex;gap:6px;margin-bottom:4px;font-size:11px\"><input class=\"fi\" style=\"width:120px\" value=\"API_KEY\" readonly><input class=\"fi\" style=\"flex:1\" value=\"API密钥\"><select class=\"sl\" style=\"width:80px\"><option>必填<\/option><option>可选<\/option><\/select><\/div>\n<div style=\"display:flex;gap:6px;margin-bottom:4px;font-size:11px\"><input class=\"fi\" style=\"width:120px\" value=\"TARGET_URL\" readonly><input class=\"fi\" style=\"flex:1\" value=\"目标URL\"><select class=\"sl\" style=\"width:80px\"><option>必填<\/option><option>可选<\/option><\/select><\/div>\n<\/div>\n<button class=\"btn btn-g btn-sm\" onclick=\"addEnvDecl()\" style=\"margin-top:4px\">+ 添加变量<\/button><\/div>\n<div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>禁用<\/option><\/select><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-tpl')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-tpl');showT('✅ 模板已保存','ok')\">保存<\/button><\/div><\/div><\/div>\n\n<div class=\"mo\" id=\"modal-del\"><div class=\"mc\" style=\"max-width:400px\"><div class=\"mh\"><h3>⚠️ 确认删除<\/h3><button class=\"mx\" onclick=\"closeM('modal-del')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:20px\"><div style=\"font-size:36px\">🗑️<\/div><p style=\"font-size:13px;font-weight:600;margin-top:8px\">确定删除该脚本模板?<\/p><p style=\"font-size:11px;color:var(--sub);margin-top:4px\">已被Skill引用的模板需先解除关联<\/p><\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-del')\">取消<\/button><button class=\"btn btn-d\" onclick=\"closeM('modal-del');showT('✅ 已删除','ok')\">确认删除<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">系统设置<\/div><div class=\"ni\">· 执行器配置<\/div><div class=\"ni ac\">· 脚本模板<\/div><div class=\"ni\">· 定时任务<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>⚙️ 系统设置 / <b style=\"color:var(--txt)\">脚本模板管理<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">脚本模板管理<\/h1>\n<p class=\"pd\">脚本执行器预置模板 · 代码编辑器 · 环境变量声明 · Skill引用<\/p>\n\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索模板名称\" id=\"sInput\" oninput=\"filterT()\"><\/div>\n<select class=\"sl\" id=\"fType\" onchange=\"filterT()\"><option value=\"\">全部类型<\/option><option value=\"python\">Python<\/option><option value=\"node\">Node.js<\/option><option value=\"shell\">Shell<\/option><\/select>\n<button class=\"btn btn-p\" style=\"margin-left:auto\" onclick=\"openAdd()\">+ 新增模板<\/button>\n<\/div>\n\n<div class=\"tw\"><table><thead><tr><th>模板名称<\/th><th>脚本类型<\/th><th>环境变量<\/th><th>引用Skill<\/th><th>状态<\/th><th>更新时间<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody id=\"ttb\">\n<tr data-q=\"通用HTTP请求\" data-type=\"python\"><td><b>通用HTTP请求<\/b><\/td><td><span class=\"tg tg-i\">🐍 Python<\/span><\/td><td>API_KEY, TARGET_URL<\/td><td>2个Skill<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>04-23 10:00<\/td><td><button class=\"btn-l\" onclick=\"openEdit('通用HTTP请求','python')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"数据清洗脚本\" data-type=\"python\"><td><b>数据清洗脚本<\/b><\/td><td><span class=\"tg tg-i\">🐍 Python<\/span><\/td><td>INPUT_PATH, OUTPUT_PATH<\/td><td>1个Skill<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>04-22 15:30<\/td><td><button class=\"btn-l\" onclick=\"openEdit('数据清洗脚本','python')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"文件处理\" data-type=\"shell\"><td><b>文件处理<\/b><\/td><td><span class=\"tg tg-w\">🐚 Shell<\/span><\/td><td>FILE_DIR<\/td><td>0个Skill<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>04-20 09:00<\/td><td><button class=\"btn-l\" onclick=\"openEdit('文件处理','shell')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"API调用\" data-type=\"node\"><td><b>API调用<\/b><\/td><td><span class=\"tg tg-p\">📦 Node.js<\/span><\/td><td>API_ENDPOINT, TOKEN<\/td><td>1个Skill<\/td><td><span class=\"tg tg-ok\">启用<\/span><\/td><td>04-19 14:20<\/td><td><button class=\"btn-l\" onclick=\"openEdit('API调用','node')\">编辑<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<\/tbody><\/table><\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nconst CODE={python:`#!/usr/bin/env python3\\nimport requests\\nimport json\\nimport os\\n\\ndef main():\\n api_key = os.environ.get('API_KEY', '')\\n url = os.environ.get('TARGET_URL', '')\\n resp = requests.get(url, headers={'Authorization': f'Bearer {api_key}'})\\n print(json.dumps({'status': 'success', 'data': resp.json()}))\\n\\nif __name__ == '__main__':\\n main()`,node:`const axios = require('axios');\\n\\nasync function main() {\\n const endpoint = process.env.API_ENDPOINT;\\n const token = process.env.TOKEN;\\n const res = await axios.get(endpoint, {\\n headers: { Authorization: \\`Bearer \\${token}\\` }\\n });\\n console.log(JSON.stringify({ status: 'success', data: res.data }));\\n}\\n\\nmain().catch(console.error);`,shell:`#!/bin/bash\\nset -e\\n\\nFILE_DIR=\\${FILE_DIR:-/tmp}\\n\\necho \"Processing files in $FILE_DIR\"\\nfor f in \"$FILE_DIR\"/*; do\\n echo \"Processing: $f\"\\ndone\\necho '{\"status\":\"success\"}'`};\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\nfunction openAdd(){document.getElementById('mtTitle').textContent='新增脚本模板';document.getElementById('mt-name').value='';document.getElementById('mt-type').value='python';document.getElementById('codeArea').value=CODE.python;document.getElementById('codeLang').textContent='Python';openM('modal-tpl')}\nfunction openEdit(name,type){document.getElementById('mtTitle').textContent='编辑模板 — '+name;document.getElementById('mt-name').value=name;document.getElementById('mt-type').value=type;document.getElementById('codeArea').value=CODE[type]||'';document.getElementById('codeLang').textContent={python:'Python',node:'Node.js',shell:'Shell'}[type];openM('modal-tpl')}\nfunction onTplType(v){const labels={python:'Python',node:'Node.js',shell:'Shell'};document.getElementById('codeLang').textContent=labels[v];document.getElementById('codeArea').value=CODE[v]||''}\nfunction formatCode(){showT('✅ 代码已格式化','ok')}\nfunction addEnvDecl(){const list=document.getElementById('envList');const d=document.createElement('div');d.style.cssText='display:flex;gap:6px;margin-bottom:4px;font-size:11px';d.innerHTML='<input class=\"fi\" style=\"width:120px\" placeholder=\"变量名\"><input class=\"fi\" style=\"flex:1\" placeholder=\"描述\"><select class=\"sl\" style=\"width:80px\"><option>必填<\/option><option>可选<\/option><\/select>';list.appendChild(d)}\nfunction filterT(){const q=document.getElementById('sInput').value.toLowerCase();const type=document.getElementById('fType').value;document.querySelectorAll('#ttb tr').forEach(tr=>{const d=tr.dataset;tr.style.display=(!q||d.q.toLowerCase().includes(q))&&(!type||d.type===type)?'':'none'})}\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>",
"19_定时任务.html": "<!DOCTYPE html><html lang=\"zh-CN\"><head><script>if(window!==window.top)document.documentElement.classList.add(\"in-iframe\")<\/script><style>.in-iframe .side{display:none!important}.in-iframe .main{margin-left:0!important}.in-iframe .layout{min-height:auto}<\/style><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"><title>Agent任务系统 v2.1 - 定时任务<\/title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}:root{--pri:#6366f1;--bg:#f1f5f9;--card:#fff;--txt:#1e293b;--sub:#64748b;--bdr:#e2e8f0;--ok:#22c55e;--err:#ef4444;--warn:#f59e0b;--side:#1e293b}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;background:var(--bg);color:var(--txt);line-height:1.6;font-size:13px}\n.layout{display:flex;min-height:100vh}.side{width:220px;background:var(--side);color:#94a3b8;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:100}.side .logo{padding:16px 18px;font-size:14px;font-weight:700;color:#fff;border-bottom:1px solid #334155}.ni{display:flex;align-items:center;gap:8px;padding:9px 18px;font-size:12px;color:#94a3b8;cursor:pointer;border-left:3px solid transparent}.ni:hover{background:#334155;color:#e2e8f0}.ni.ac{background:rgba(99,102,241,.15);color:#818cf8;border-left-color:#818cf8;font-weight:600}.ng-t{padding:10px 18px 4px;font-size:10px;letter-spacing:1px;color:#475569;font-weight:600}\n.main{margin-left:220px;flex:1}.hd{height:52px;background:var(--card);border-bottom:1px solid var(--bdr);display:flex;align-items:center;justify-content:space-between;padding:0 24px;font-size:12px;color:var(--sub);position:sticky;top:0;z-index:50}.ct{padding:24px}\n.pt{font-size:20px;font-weight:700;margin-bottom:4px}.pd{font-size:12px;color:var(--sub);margin-bottom:20px}\n.tb{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}.sb{display:flex;align-items:center;gap:6px;background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px}.sb input{border:none;background:none;outline:none;font-size:12px;width:140px}\n.sl{border:1px solid var(--bdr);border-radius:7px;padding:7px 12px;font-size:12px;background:#fff;cursor:pointer}\n.btn{padding:7px 16px;border-radius:7px;font-size:12px;font-weight:500;border:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:all .12s}.btn-p{background:var(--pri);color:#fff}.btn-p:hover{background:#4f46e5}.btn-d{background:#fee2e2;color:#dc2626}.btn-g{background:transparent;color:var(--sub);border:1px solid var(--bdr)}.btn-sm{padding:5px 10px;font-size:11px}.btn-s{background:var(--ok);color:#fff}.btn-w{background:var(--warn);color:#fff}\n.btn-l{background:none;border:none;color:var(--pri);padding:0;font-size:12px;cursor:pointer}.btn-l:hover{text-decoration:underline}\n.tg{display:inline-block;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:600}.tg-ok{background:#dcfce7;color:#166534}.tg-e{background:#fee2e2;color:#991b1b}.tg-i{background:#dbeafe;color:#1e40af}.tg-p{background:#f3e8ff;color:#6b21a8}.tg-w{background:#fef3c7;color:#92400e}.tg-g{background:#f1f5f9;color:#64748b}\ntable{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--bdr)}th{background:#f8fafc;font-weight:600;color:var(--sub);font-size:11px}tr:hover td{background:#fafbfc}.tw{overflow-x:auto;border:1px solid var(--bdr);border-radius:8px}\n.fg{margin-bottom:14px}.fl{font-size:12px;font-weight:500;margin-bottom:5px;display:block}.fl .rq{color:var(--err)}.fi{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;outline:none}.fi:focus{border-color:var(--pri)}.fs{width:100%;padding:8px 12px;border:1px solid var(--bdr);border-radius:7px;font-size:12px;background:#fff}.fr{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.mo{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:200}.mo.show{display:flex}.mc{background:var(--card);border-radius:14px;width:90%;max-width:620px;max-height:88vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2)}.mh{padding:14px 20px;border-bottom:1px solid var(--bdr);display:flex;justify-content:space-between;align-items:center}.mh h3{font-size:15px}.mx{cursor:pointer;font-size:18px;color:var(--sub);background:none;border:none}.mb{padding:20px}.mf{padding:14px 20px;border-top:1px solid var(--bdr);display:flex;justify-content:flex-end;gap:8px}\n.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:8px;font-size:13px;font-weight:500;z-index:300;display:none}.toast.show{display:block;animation:tIn .3s}.toast.ok{background:#dcfce7;color:#166534}.toast.er{background:#fee2e2;color:#991b1b}@keyframes tIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n.stat{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}.stat-c{background:var(--card);border:1px solid var(--bdr);border-radius:10px;padding:14px 16px}.stat-c .sv{font-size:22px;font-weight:700}.stat-c .sl2{font-size:11px;color:var(--sub)}\n.cron-help{background:#f8fafc;border:1px solid var(--bdr);border-radius:7px;padding:10px;font-size:11px;margin-top:6px}.cron-help code{background:#ede9fe;padding:1px 4px;border-radius:3px;font-size:10px}\n.switch{position:relative;width:36px;height:20px;display:inline-block}.switch input{opacity:0;width:0;height:0}.slider{position:absolute;cursor:pointer;inset:0;background:#cbd5e1;border-radius:20px;transition:.2s}.slider:before{content:'';position:absolute;height:16px;width:16px;left:2px;bottom:2px;background:#fff;border-radius:50%;transition:.2s}.switch input:checked+.slider{background:var(--ok)}.switch input:checked+.slider:before{transform:translateX(16px)}\n.timeline{display:flex;gap:2px;margin-top:4px}.tl-dot{width:6px;height:16px;border-radius:2px;font-size:0}\n<\/style><\/head><body>\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<div class=\"mo\" id=\"modal-cron\"><div class=\"mc\"><div class=\"mh\"><h3 id=\"mcTitle\">新增定时任务<\/h3><button class=\"mx\" onclick=\"closeM('modal-cron')\">✕<\/button><\/div><div class=\"mb\">\n<div class=\"fg\"><label class=\"fl\">任务名称 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"mc-name\" placeholder=\"如 每日竞品数据采集\"><\/div>\n<div class=\"fg\"><label class=\"fl\">关联Skill <span class=\"rq\">*<\/span><\/label><select class=\"fs\" id=\"mc-skill\"><option>竞品数据采集<\/option><option>小红书笔记发布<\/option><option>数据清洗脚本<\/option><option>抖音视频上传<\/option><option>Facebook广告投放<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">关联产品 <span class=\"rq\">*<\/span><\/label><select class=\"fs\"><option>PROD001 — 美妆种草达人<\/option><option>PROD002 — 护肤品评测<\/option><option>PROD003 — 抖音带货王<\/option><option>全部产品<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">Cron表达式 <span class=\"rq\">*<\/span><\/label><input class=\"fi\" id=\"cronInput\" value=\"0 8 * * *\" oninput=\"parseCron(this.value)\">\n<div class=\"cron-help\">\n<div id=\"cronDesc\" style=\"font-weight:600;color:var(--pri);margin-bottom:4px\">📅 每天 08:00 执行<\/div>\n常用: <code>0 8 * * *<\/code> 每天8点 · <code>0 */2 * * *<\/code> 每2小时 · <code>0 9 * * 1<\/code> 每周一9点 · <code>0 0 1 * *<\/code> 每月1号\n<\/div><\/div>\n<div class=\"fg\"><label class=\"fl\">执行参数 (JSON)<\/label><textarea class=\"fi\" rows=\"3\" style=\"font-family:monospace;font-size:11px\">{\n \"product_id\": \"PROD001\",\n \"mode\": \"incremental\"\n}<\/textarea><\/div>\n<div class=\"fr\"><div class=\"fg\"><label class=\"fl\">失败重试<\/label><select class=\"fs\"><option>重试3次<\/option><option>重试1次<\/option><option>不重试<\/option><\/select><\/div>\n<div class=\"fg\"><label class=\"fl\">超时(秒)<\/label><input class=\"fi\" type=\"number\" value=\"120\"><\/div><\/div>\n<div class=\"fg\"><label class=\"fl\">状态<\/label><select class=\"fs\"><option>启用<\/option><option>暂停<\/option><\/select><\/div>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-cron')\">取消<\/button><button class=\"btn btn-p\" onclick=\"closeM('modal-cron');showT('✅ 定时任务已保存','ok')\">保存<\/button><\/div><\/div><\/div>\n\n<div class=\"mo\" id=\"modal-log\"><div class=\"mc\"><div class=\"mh\"><h3>📋 最近执行记录<\/h3><button class=\"mx\" onclick=\"closeM('modal-log')\">✕<\/button><\/div><div class=\"mb\">\n<table><thead><tr><th>执行时间<\/th><th>状态<\/th><th>耗时<\/th><th>结果<\/th><\/tr><\/thead><tbody>\n<tr><td>04-23 08:00:00<\/td><td><span class=\"tg tg-ok\">成功<\/span><\/td><td>12.3s<\/td><td>采集 156 条<\/td><\/tr>\n<tr><td>04-22 08:00:00<\/td><td><span class=\"tg tg-ok\">成功<\/span><\/td><td>11.8s<\/td><td>采集 142 条<\/td><\/tr>\n<tr><td>04-21 08:00:00<\/td><td><span class=\"tg tg-e\">失败<\/span><\/td><td>30s<\/td><td>超时<\/td><\/tr>\n<tr><td>04-20 08:00:00<\/td><td><span class=\"tg tg-ok\">成功<\/span><\/td><td>10.5s<\/td><td>采集 138 条<\/td><\/tr>\n<tr><td>04-19 08:00:00<\/td><td><span class=\"tg tg-ok\">成功<\/span><\/td><td>13.1s<\/td><td>采集 161 条<\/td><\/tr>\n<\/tbody><\/table>\n<\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-log')\">关闭<\/button><\/div><\/div><\/div>\n\n<div class=\"mo\" id=\"modal-del\"><div class=\"mc\" style=\"max-width:400px\"><div class=\"mh\"><h3>⚠️ 确认删除<\/h3><button class=\"mx\" onclick=\"closeM('modal-del')\">✕<\/button><\/div><div class=\"mb\" style=\"text-align:center;padding:20px\"><div style=\"font-size:36px\">🗑️<\/div><p style=\"font-size:13px;font-weight:600;margin-top:8px\">确定删除该定时任务?<\/p><\/div><div class=\"mf\"><button class=\"btn btn-g\" onclick=\"closeM('modal-del')\">取消<\/button><button class=\"btn btn-d\" onclick=\"closeM('modal-del');showT('✅ 已删除','ok')\">确认删除<\/button><\/div><\/div><\/div>\n\n<div class=\"layout\">\n<aside class=\"side\">\n<div class=\"logo\">🤖 Agent任务系统 v2.1<\/div>\n<div class=\"ni\">🏠 首页<\/div>\n<div class=\"ng-t\">权限管理<\/div><div class=\"ni\">· 组织架构<\/div><div class=\"ni\">· 菜单管理<\/div><div class=\"ni\">· 角色管理<\/div><div class=\"ni\">· 用户管理<\/div>\n<div class=\"ng-t\">产品管理<\/div><div class=\"ni\">· 产品列表<\/div><div class=\"ni\">· 渠道码<\/div><div class=\"ni\">· 平台套件<\/div>\n<div class=\"ng-t\">平台产品账号<\/div><div class=\"ni\">· 账号管理<\/div>\n<div class=\"ng-t\">Skill中心<\/div><div class=\"ni\">· Skill列表<\/div><div class=\"ni\">· 调用日志<\/div>\n<div class=\"ng-t\">任务中心<\/div><div class=\"ni\">· 任务创建<\/div><div class=\"ni\">· 任务列表<\/div>\n<div class=\"ng-t\">系统设置<\/div><div class=\"ni\">· 执行器配置<\/div><div class=\"ni\">· 脚本模板<\/div><div class=\"ni ac\">· 定时任务<\/div>\n<\/aside>\n<div class=\"main\">\n<div class=\"hd\"><div>⚙️ 系统设置 / <b style=\"color:var(--txt)\">定时任务<\/b><\/div><div style=\"display:flex;align-items:center;gap:10px\"><span>🔔<\/span><span>admin<\/span><div style=\"width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600\">A<\/div><\/div><\/div>\n<div class=\"ct\">\n<h1 class=\"pt\">定时任务管理<\/h1>\n<p class=\"pd\">Cron定时调度 · 关联Skill+产品 · 执行记录 · 启停控制<\/p>\n\n<div class=\"stat\">\n<div class=\"stat-c\"><div class=\"sv\">8<\/div><div class=\"sl2\">定时任务<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--ok)\">6<\/div><div class=\"sl2\">运行中<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--warn)\">2<\/div><div class=\"sl2\">已暂停<\/div><\/div>\n<div class=\"stat-c\"><div class=\"sv\" style=\"color:var(--ok)\">94.2%<\/div><div class=\"sl2\">成功率(7日)<\/div><\/div>\n<\/div>\n\n<div class=\"tb\">\n<div class=\"sb\"><span>🔍<\/span><input placeholder=\"搜索任务名称\" id=\"sInput\" oninput=\"filterT()\"><\/div>\n<select class=\"sl\" id=\"fSt\" onchange=\"filterT()\"><option value=\"\">全部状态<\/option><option value=\"运行中\">运行中<\/option><option value=\"已暂停\">已暂停<\/option><\/select>\n<button class=\"btn btn-p\" style=\"margin-left:auto\" onclick=\"openAdd()\">+ 新增定时任务<\/button>\n<\/div>\n\n<div class=\"tw\"><table><thead><tr><th>任务名称<\/th><th>Skill<\/th><th>Cron<\/th><th>产品<\/th><th>下次执行<\/th><th>最近7次<\/th><th>状态<\/th><th>开关<\/th><th>操作<\/th><\/tr><\/thead>\n<tbody id=\"ctb\">\n<tr data-q=\"每日竞品数据采集\" data-st=\"运行中\"><td><b>每日竞品数据采集<\/b><\/td><td>竞品数据采集<\/td><td><code>0 8 * * *<\/code><\/td><td>PROD001<\/td><td style=\"color:var(--pri)\">明天 08:00<\/td><td><div class=\"timeline\" id=\"tl1\"><\/div><\/td><td><span class=\"tg tg-ok\">运行中<\/span><\/td><td><label class=\"switch\"><input type=\"checkbox\" checked onchange=\"toggleCron(this)\"><span class=\"slider\"><\/span><\/label><\/td><td><button class=\"btn-l\" onclick=\"openEdit('每日竞品数据采集')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-log')\">记录<\/button> <button class=\"btn-l\" style=\"color:var(--warn)\" onclick=\"showT('▶️ 手动触发成功','ok')\">触发<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"定时数据清洗\" data-st=\"运行中\"><td><b>定时数据清洗<\/b><\/td><td>数据清洗脚本<\/td><td><code>0 */4 * * *<\/code><\/td><td>全部<\/td><td style=\"color:var(--pri)\">今天 20:00<\/td><td><div class=\"timeline\" id=\"tl2\"><\/div><\/td><td><span class=\"tg tg-ok\">运行中<\/span><\/td><td><label class=\"switch\"><input type=\"checkbox\" checked onchange=\"toggleCron(this)\"><span class=\"slider\"><\/span><\/label><\/td><td><button class=\"btn-l\" onclick=\"openEdit('定时数据清洗')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-log')\">记录<\/button> <button class=\"btn-l\" style=\"color:var(--warn)\" onclick=\"showT('▶️ 手动触发成功','ok')\">触发<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"每周一小红书发布\" data-st=\"运行中\"><td><b>每周一小红书发布<\/b><\/td><td>小红书笔记发布<\/td><td><code>0 9 * * 1<\/code><\/td><td>PROD001<\/td><td style=\"color:var(--pri)\">下周一 09:00<\/td><td><div class=\"timeline\" id=\"tl3\"><\/div><\/td><td><span class=\"tg tg-ok\">运行中<\/span><\/td><td><label class=\"switch\"><input type=\"checkbox\" checked onchange=\"toggleCron(this)\"><span class=\"slider\"><\/span><\/label><\/td><td><button class=\"btn-l\" onclick=\"openEdit('每周一小红书发布')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-log')\">记录<\/button> <button class=\"btn-l\" style=\"color:var(--warn)\" onclick=\"showT('▶️ 手动触发成功','ok')\">触发<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"抖音视频批量上传\" data-st=\"运行中\"><td><b>抖音视频批量上传<\/b><\/td><td>抖音视频上传<\/td><td><code>30 10 * * *<\/code><\/td><td>PROD003<\/td><td style=\"color:var(--pri)\">明天 10:30<\/td><td><div class=\"timeline\" id=\"tl4\"><\/div><\/td><td><span class=\"tg tg-ok\">运行中<\/span><\/td><td><label class=\"switch\"><input type=\"checkbox\" checked onchange=\"toggleCron(this)\"><span class=\"slider\"><\/span><\/label><\/td><td><button class=\"btn-l\" onclick=\"openEdit('抖音视频批量上传')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-log')\">记录<\/button> <button class=\"btn-l\" style=\"color:var(--warn)\" onclick=\"showT('▶️ 手动触发成功','ok')\">触发<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"Facebook广告效果汇总\" data-st=\"已暂停\"><td><b style=\"color:var(--sub)\">Facebook广告效果汇总<\/b><\/td><td>Facebook广告投放<\/td><td><code>0 18 * * 5<\/code><\/td><td>PROD006<\/td><td style=\"color:var(--sub)\">已暂停<\/td><td><div class=\"timeline\" id=\"tl5\"><\/div><\/td><td><span class=\"tg tg-w\">已暂停<\/span><\/td><td><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCron(this)\"><span class=\"slider\"><\/span><\/label><\/td><td><button class=\"btn-l\" onclick=\"openEdit('Facebook广告效果汇总')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-log')\">记录<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<tr data-q=\"月度报表生成\" data-st=\"已暂停\"><td><b style=\"color:var(--sub)\">月度报表生成<\/b><\/td><td>数据清洗脚本<\/td><td><code>0 0 1 * *<\/code><\/td><td>全部<\/td><td style=\"color:var(--sub)\">已暂停<\/td><td><div class=\"timeline\" id=\"tl6\"><\/div><\/td><td><span class=\"tg tg-w\">已暂停<\/span><\/td><td><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCron(this)\"><span class=\"slider\"><\/span><\/label><\/td><td><button class=\"btn-l\" onclick=\"openEdit('月度报表生成')\">编辑<\/button> <button class=\"btn-l\" onclick=\"openM('modal-log')\">记录<\/button> <button class=\"btn-l\" style=\"color:var(--err)\" onclick=\"openM('modal-del')\">删除<\/button><\/td><\/tr>\n<\/tbody><\/table><\/div>\n\n<\/div><\/div><\/div>\n\n<script>\nfunction openM(id){document.getElementById(id).classList.add('show')}\nfunction closeM(id){document.getElementById(id).classList.remove('show')}\nfunction showT(m,t){const e=document.getElementById('toast');e.textContent=m;e.className='toast show '+t;setTimeout(()=>e.className='toast',2500)}\nfunction openAdd(){document.getElementById('mcTitle').textContent='新增定时任务';document.getElementById('mc-name').value='';openM('modal-cron')}\nfunction openEdit(name){document.getElementById('mcTitle').textContent='编辑 — '+name;document.getElementById('mc-name').value=name;openM('modal-cron')}\nfunction toggleCron(el){const tr=el.closest('tr');const st=tr.querySelector('.tg');if(el.checked){st.className='tg tg-ok';st.textContent='运行中';tr.dataset.st='运行中';showT('✅ 已启用','ok')}else{st.className='tg tg-w';st.textContent='已暂停';tr.dataset.st='已暂停';showT('⏸️ 已暂停','ok')}}\nfunction parseCron(v){const desc=document.getElementById('cronDesc');const map={'0 8 * * *':'📅 每天 08:00 执行','0 */2 * * *':'📅 每2小时执行','0 9 * * 1':'📅 每周一 09:00 执行','0 0 1 * *':'📅 每月1号 00:00 执行','30 10 * * *':'📅 每天 10:30 执行','0 18 * * 5':'📅 每周五 18:00 执行','0 */4 * * *':'📅 每4小时执行'};desc.textContent=map[v]||'📅 自定义表达式: '+v}\nfunction filterT(){const q=document.getElementById('sInput').value.toLowerCase();const st=document.getElementById('fSt').value;document.querySelectorAll('#ctb tr').forEach(tr=>{const d=tr.dataset;tr.style.display=(!q||d.q.toLowerCase().includes(q))&&(!st||d.st===st)?'':'none'})}\nfunction initTimelines(){for(let i=1;i<=6;i++){const el=document.getElementById('tl'+i);if(!el)continue;let html='';for(let j=0;j<7;j++){const ok=Math.random()>0.15;html+=`<div class=\"tl-dot\" style=\"background:${ok?'var(--ok)':'var(--err)'}\" title=\"${7-j}天前: ${ok?'成功':'失败'}\"><\/div>`}el.innerHTML=html}}\ninitTimelines();\ndocument.querySelectorAll('.mo').forEach(m=>m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('show')}));\n<\/script>\n<\/body><\/html>"
};
// 页面名映射(用于拦截 alert('跳转:xxx'))
const NAV_MAP = {"任务创建": "10_任务创建.html", "任务列表": "11_任务列表.html", "Skill列表": "09_Skill管理.html", "Skill管理": "09_Skill管理.html", "平台账号": "08_平台产品账号.html", "组织架构": "03_组织架构.html", "角色管理": "04_角色管理.html", "用户管理": "05_用户管理.html", "菜单管理": "12_菜单管理.html", "产品管理": "06_产品管理.html", "产品列表": "06_产品管理.html", "渠道码管理": "07_渠道码管理.html", "平台套件": "13_平台套件.html", "平台账号管理": "08_平台产品账号.html", "调用日志": "14_Skill调用日志.html", "操作日志": "15_操作日志.html", "统计报表": "16_统计报表.html", "执行器配置": "17_执行器配置.html", "脚本模板": "18_脚本模板管理.html", "脚本模板管理": "18_脚本模板管理.html", "定时任务": "19_定时任务.html", "仪表盘": "02_仪表盘.html"};
const frame = document.getElementById('mainFrame');
const sidebar = document.getElementById('sidebar');
// 加载指定页面到 iframe
function loadPage(name) {
if (!PAGES[name]) { console.warn('page not found:', name); return; }
frame.srcdoc = PAGES[name];
}
// 更新侧边栏高亮
function setActive(name) {
document.querySelectorAll('.ni').forEach(n => n.classList.remove('ac'));
const target = document.querySelector('.ni[data-src="' + name + '"]');
if (target) target.classList.add('ac');
}
// 导航入口
function navigate(name) {
if (!PAGES[name]) return;
loadPage(name);
setActive(name);
}
// 侧边栏点击
document.querySelectorAll('.ni[data-src]').forEach(item => {
item.addEventListener('click', function() {
navigate(this.dataset.src);
});
});
// 监听子页面消息(登录成功 + 导航请求)
window.addEventListener('message', function(e) {
if (e.data === 'login-success') {
sidebar.classList.remove('hide');
navigate('02_仪表盘.html');
} else if (e.data && e.data.type === 'nav' && e.data.target) {
navigate(e.data.target);
}
});
// iframe load 后注入桥接脚本:隐藏子页面自带侧边栏 + 拦截 alert 跳转
frame.addEventListener('load', function() {
try {
const d = frame.contentDocument;
if (!d) return;
// 隐藏子页面自带的侧边栏(它们有自己的 .side,可能样式冲突;外层 .side.hide 已起作用,子页面的 .side 这里隐藏)
let s = d.getElementById('_injected_style');
if (!s) { s = d.createElement('style'); s.id = '_injected_style'; d.head && d.head.appendChild(s); }
s.textContent = '.side{display:none!important}.main{margin-left:0!important}.layout{min-height:auto}';
// 注入桥接:把 alert("跳转:XXX") 或 alert("请打开 XX_xxx.html") 转为导航
if (!d.getElementById('_injected_bridge')) {
const sc = d.createElement('script');
sc.id = '_injected_bridge';
sc.textContent = `
(function(){
const NAV_MAP = ${JSON.stringify(NAV_MAP)};
const origAlert = window.alert;
window.alert = function(msg) {
try {
const s = String(msg);
// 形如 "请打开 03_组织架构.html"
let m = s.match(/(\d{2}_[^\s]+\.html)/);
if (m) { window.parent.postMessage({type:'nav', target: m[1]}, '*'); return; }
// 形如 "跳转:任务创建" 或 "跳转:任务创建"
m = s.match(/跳转[::]\s*(.+)/);
if (m) {
const key = m[1].trim();
if (NAV_MAP[key]) { window.parent.postMessage({type:'nav', target: NAV_MAP[key]}, '*'); return; }
}
} catch(err) {}
return origAlert.call(window, msg);
};
// 暴露给子页面主动调用
window.__navigate = function(target) {
window.parent.postMessage({type:'nav', target: target}, '*');
};
})();
`;
(d.body || d.documentElement).appendChild(sc);
}
} catch (e) { console.warn(e); }
});
// 初始加载登录页
loadPage('01_登录页.html');
</script>
</body>
</html>