Files
Dev Agent 883a925db5 feat: Agent任务系统 v2.1 完整实现
- 后端: FastAPI + SQLAlchemy 2.0 + Pydantic v2 + Celery (19个API模块)
- 前端: React 18 + TypeScript + Ant Design 5 + Zustand (19个页面组件)
- 权限: RBAC四维权限体系 (RB-01~RB-13)
- 任务: 四步向导创建 + 双执行器(龙虾/脚本) + 定时调度
- 部署: Docker Compose 6服务 + Nginx反代 + Alembic迁移

统计: 88个文件 | 8779行代码 | 默认账号: admin/admin123
2026-04-24 09:10:47 +00:00

3455 lines
87 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 产品需求文档(PRD)</title>
<style>
*{box-sizing:border-box}
:root{
--pri:#6366f1;
--pri-l:#eef2ff;
--txt:#0f172a;
--sub:#64748b;
--muted:#94a3b8;
--bdr:#e2e8f0;
--bg:#f8fafc;
--code-bg:#f1f5f9;
--tbl-head:#f8fafc;
--ok:#16a34a;--ok-bg:#dcfce7;
--warn:#b45309;--warn-bg:#fef3c7;
--err:#dc2626;--err-bg:#fee2e2;
}
html,body{margin:0;padding:0}
body{
font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;
color:var(--txt);
background:var(--bg);
line-height:1.7;
-webkit-font-smoothing:antialiased;
}
.layout{display:flex;max-width:1400px;margin:0 auto;min-height:100vh}
/* Sidebar TOC */
.sidebar{
position:sticky;top:0;
width:280px;height:100vh;overflow-y:auto;
background:#fff;border-right:1px solid var(--bdr);
padding:24px 18px;flex-shrink:0;
}
.sidebar h2{font-size:13px;color:var(--sub);text-transform:uppercase;letter-spacing:1px;margin:0 0 12px;font-weight:600}
.sidebar .toc{font-size:13px}
.sidebar .toc ul{list-style:none;padding:0;margin:0}
.sidebar .toc li{margin:2px 0}
.sidebar .toc a{
color:var(--sub);text-decoration:none;
display:block;padding:5px 10px;border-radius:6px;
border-left:2px solid transparent;transition:all .12s;
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.sidebar .toc a:hover{background:var(--pri-l);color:var(--pri)}
.sidebar .toc > ul > li > a{font-weight:600;color:var(--txt);margin-top:8px}
.sidebar .toc > ul > li > ul a{padding-left:20px;font-size:12px}
.sidebar .toc > ul > li > ul > li > ul a{padding-left:32px;font-size:11.5px;color:var(--muted)}
.sidebar .toc a.active{background:var(--pri-l);color:var(--pri);border-left-color:var(--pri);font-weight:600}
/* Content */
.content{
flex:1;padding:40px 48px 120px;
max-width:100%;overflow-x:hidden;
}
.content > :first-child{margin-top:0}
/* Headings */
h1,h2,h3,h4,h5{
font-weight:700;line-height:1.35;
margin:32px 0 14px;scroll-margin-top:24px;
}
h1{
font-size:30px;padding-bottom:14px;
border-bottom:3px solid var(--pri);margin-top:0;
}
h2{
font-size:22px;padding-bottom:8px;
border-bottom:1px solid var(--bdr);
margin-top:42px;
}
h2::before{
content:"";display:inline-block;
width:4px;height:20px;background:var(--pri);
margin-right:10px;vertical-align:-3px;border-radius:2px;
}
h3{font-size:17px;margin-top:28px;color:#1e293b}
h4{font-size:15px;margin-top:20px;color:#334155}
h5{font-size:14px;color:var(--sub)}
/* Meta info table (first table) */
p{margin:10px 0}
hr{border:none;border-top:1px dashed var(--bdr);margin:36px 0}
/* Inline code */
code{
background:var(--code-bg);color:#be185d;
padding:2px 6px;border-radius:4px;
font-family:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
font-size:.88em;
}
pre{
background:#0f172a;color:#e2e8f0;
padding:16px 20px;border-radius:10px;overflow-x:auto;
font-size:13px;line-height:1.6;margin:14px 0;
}
pre code{background:transparent;color:inherit;padding:0;font-size:inherit}
/* Tables */
table{
width:100%;border-collapse:collapse;
margin:14px 0;font-size:13px;
background:#fff;border-radius:8px;overflow:hidden;
box-shadow:0 1px 2px rgba(0,0,0,.04);
border:1px solid var(--bdr);
}
th,td{
padding:10px 14px;text-align:left;
border-bottom:1px solid var(--bdr);
vertical-align:top;
}
th{
background:var(--tbl-head);color:var(--sub);
font-weight:600;font-size:12px;
text-transform:uppercase;letter-spacing:.5px;
border-bottom:2px solid var(--bdr);
}
tr:last-child td{border-bottom:none}
tr:hover td{background:#fafbfc}
/* Lists */
ul,ol{padding-left:24px;margin:10px 0}
li{margin:4px 0}
li > ul,li > ol{margin:4px 0}
/* Emphasis */
strong{color:var(--pri);font-weight:600}
em{color:var(--sub)}
/* Blockquote */
blockquote{
border-left:4px solid var(--pri);
background:var(--pri-l);
margin:14px 0;padding:10px 18px;
color:#3730a3;border-radius:0 8px 8px 0;
}
/* Back to top */
.back-top{
position:fixed;right:24px;bottom:24px;
width:44px;height:44px;border-radius:50%;
background:var(--pri);color:#fff;
display:flex;align-items:center;justify-content:center;
font-size:20px;cursor:pointer;border:none;
box-shadow:0 4px 14px rgba(99,102,241,.4);
opacity:0;pointer-events:none;transition:opacity .2s;z-index:100;
}
.back-top.show{opacity:1;pointer-events:auto}
/* Print */
@media print{
.sidebar,.back-top{display:none}
.content{padding:0}
body{background:#fff}
table{box-shadow:none}
h1,h2,h3{page-break-after:avoid}
tr,table{page-break-inside:avoid}
}
/* Responsive */
@media(max-width:960px){
.layout{flex-direction:column}
.sidebar{position:static;width:100%;height:auto;max-height:none;border-right:none;border-bottom:1px solid var(--bdr)}
.content{padding:24px}
h1{font-size:24px}
h2{font-size:18px}
table{font-size:12px}
th,td{padding:8px 10px}
}
</style>
</head>
<body>
<div class="layout">
<aside class="sidebar">
<h2>📋 文档目录</h2>
<nav class="toc"><div class="toc">
<ul>
<li><a href="#_1">一、产品概述</a><ul>
<li><a href="#11">1.1 产品定位</a></li>
<li><a href="#12">1.2 核心能力</a></li>
<li><a href="#13">1.3 默认账号</a></li>
</ul>
</li>
<li><a href="#_2">二、系统模块总览</a></li>
<li><a href="#rb">三、全局业务规则(RB)</a></li>
<li><a href="#_3">四、全局交互规范</a><ul>
<li><a href="#41-toast">4.1 Toast 反馈</a></li>
<li><a href="#42-modal">4.2 Modal 弹窗</a></li>
<li><a href="#43">4.3 表格通用</a></li>
<li><a href="#44">4.4 权限与可见性</a></li>
</ul>
</li>
<li><a href="#01">01. 登录页</a><ul>
<li><a href="#11_1">1.1 页面目标</a></li>
<li><a href="#12_1">1.2 页面结构</a></li>
<li><a href="#13_1">1.3 表单字段</a></li>
<li><a href="#14">1.4 操作细节</a></li>
<li><a href="#15">1.5 交互规则</a></li>
</ul>
</li>
<li><a href="#02">02. 仪表盘(首页)</a><ul>
<li><a href="#21">2.1 页面目标</a></li>
<li><a href="#22">2.2 页面结构</a></li>
<li><a href="#23">2.3 操作细节</a></li>
<li><a href="#24">2.4 交互规则</a></li>
<li><a href="#25">2.5 提示反馈</a></li>
</ul>
</li>
<li><a href="#03">03. 组织架构</a><ul>
<li><a href="#31">3.1 页面目标</a></li>
<li><a href="#32">3.2 页面结构</a></li>
<li><a href="#33">3.3 数据字段</a></li>
<li><a href="#34">3.4 操作细节</a></li>
<li><a href="#35">3.5 表单字段(新增/编辑组织弹窗)</a></li>
<li><a href="#36">3.6 交互规则</a></li>
</ul>
</li>
<li><a href="#04">04. 角色管理</a><ul>
<li><a href="#41">4.1 页面目标</a></li>
<li><a href="#42">4.2 页面结构</a></li>
<li><a href="#43_1">4.3 列表字段</a></li>
<li><a href="#44_1">4.4 操作细节</a></li>
<li><a href="#45">4.5 表单字段(弹窗)</a></li>
<li><a href="#46">4.6 提示反馈</a></li>
</ul>
</li>
<li><a href="#05">05. 用户管理</a><ul>
<li><a href="#51">5.1 页面目标</a></li>
<li><a href="#52">5.2 页面结构</a></li>
<li><a href="#53">5.3 操作细节</a></li>
<li><a href="#54">5.4 表单字段(新增/编辑)</a></li>
<li><a href="#55">5.5 提示反馈</a></li>
</ul>
</li>
<li><a href="#06">06. 产品管理</a><ul>
<li><a href="#61">6.1 页面目标</a></li>
<li><a href="#62">6.2 页面结构</a></li>
<li><a href="#63">6.3 列表字段</a></li>
<li><a href="#64">6.4 操作细节</a></li>
<li><a href="#65">6.5 表单字段</a></li>
<li><a href="#66">6.6 提示反馈</a></li>
</ul>
</li>
<li><a href="#07">07. 渠道码管理</a><ul>
<li><a href="#71">7.1 页面目标</a></li>
<li><a href="#72">7.2 页面结构</a></li>
<li><a href="#73">7.3 列表字段</a></li>
<li><a href="#74">7.4 操作细节</a></li>
<li><a href="#75">7.5 表单字段(新增/编辑)</a></li>
<li><a href="#76">7.6 提示反馈</a></li>
</ul>
</li>
<li><a href="#08">08. 平台产品账号</a><ul>
<li><a href="#81">8.1 页面目标</a></li>
<li><a href="#82">8.2 页面结构</a></li>
<li><a href="#83">8.3 列表字段</a></li>
<li><a href="#84">8.4 操作细节</a></li>
<li><a href="#85">8.5 表单字段</a></li>
<li><a href="#86">8.6 提示反馈</a></li>
</ul>
</li>
<li><a href="#09-skill">09. Skill 管理</a><ul>
<li><a href="#91">9.1 页面目标</a></li>
<li><a href="#92">9.2 页面结构</a></li>
<li><a href="#93">9.3 列表字段</a></li>
<li><a href="#94">9.4 操作细节</a></li>
<li><a href="#95">9.5 表单字段</a></li>
<li><a href="#96">9.6 提示反馈</a></li>
</ul>
</li>
<li><a href="#10">10. 任务创建(四步向导)</a><ul>
<li><a href="#101">10.1 页面目标</a></li>
<li><a href="#102">10.2 页面结构</a></li>
<li><a href="#103">10.3 关键字段</a></li>
<li><a href="#104">10.4 操作细节</a></li>
<li><a href="#105">10.5 交互规则 / 校验</a></li>
<li><a href="#106">10.6 提示反馈</a></li>
</ul>
</li>
<li><a href="#11_2">11. 任务列表</a><ul>
<li><a href="#111">11.1 页面目标</a></li>
<li><a href="#112">11.2 页面结构</a></li>
<li><a href="#113">11.3 状态枚举</a></li>
<li><a href="#114">11.4 操作细节</a></li>
<li><a href="#115">11.5 详情弹窗内容</a></li>
<li><a href="#116">11.6 按钮显示规则</a></li>
<li><a href="#117">11.7 提示反馈</a></li>
</ul>
</li>
<li><a href="#12_2">12. 菜单管理</a><ul>
<li><a href="#121">12.1 页面目标</a></li>
<li><a href="#122">12.2 页面结构</a></li>
<li><a href="#123">12.3 数据字段</a></li>
<li><a href="#124">12.4 操作细节</a></li>
<li><a href="#125">12.5 表单字段</a></li>
<li><a href="#126">12.6 提示反馈</a></li>
</ul>
</li>
<li><a href="#13_2">13. 平台套件</a><ul>
<li><a href="#131">13.1 页面目标</a></li>
<li><a href="#132">13.2 页面结构</a></li>
<li><a href="#133">13.3 数据字段</a></li>
<li><a href="#134">13.4 操作细节</a></li>
<li><a href="#135">13.5 表单字段</a></li>
<li><a href="#136">13.6 提示反馈</a></li>
</ul>
</li>
<li><a href="#14-skill">14. Skill 调用日志</a><ul>
<li><a href="#141">14.1 页面目标</a></li>
<li><a href="#142">14.2 页面结构</a></li>
<li><a href="#143">14.3 操作细节</a></li>
<li><a href="#144">14.4 详情弹窗</a></li>
<li><a href="#145">14.5 状态枚举</a></li>
<li><a href="#146">14.6 提示反馈</a></li>
</ul>
</li>
<li><a href="#15_1">15. 操作日志(审计)</a><ul>
<li><a href="#151">15.1 页面目标</a></li>
<li><a href="#152">15.2 页面结构</a></li>
<li><a href="#153">15.3 模块与操作枚举</a></li>
<li><a href="#154">15.4 操作细节</a></li>
<li><a href="#155">15.5 提示反馈</a></li>
</ul>
</li>
<li><a href="#16">16. 统计报表</a><ul>
<li><a href="#161">16.1 页面目标</a></li>
<li><a href="#162">16.2 页面结构</a></li>
<li><a href="#163">16.3 操作细节</a></li>
<li><a href="#164">16.4 指标示例</a></li>
<li><a href="#165">16.5 提示反馈</a></li>
</ul>
</li>
<li><a href="#17">17. 执行器配置</a><ul>
<li><a href="#171">17.1 页面目标</a></li>
<li><a href="#172">17.2 页面结构</a></li>
<li><a href="#173">17.3 卡片字段</a></li>
<li><a href="#174">17.4 操作细节</a></li>
<li><a href="#175">17.5 表单字段</a></li>
<li><a href="#176">17.6 交互规则</a></li>
<li><a href="#177">17.7 提示反馈</a></li>
</ul>
</li>
<li><a href="#18">18. 脚本模板管理</a><ul>
<li><a href="#181">18.1 页面目标</a></li>
<li><a href="#182">18.2 页面结构</a></li>
<li><a href="#183">18.3 操作细节</a></li>
<li><a href="#184">18.4 表单字段</a></li>
<li><a href="#185">18.5 交互规则</a></li>
<li><a href="#186">18.6 提示反馈</a></li>
</ul>
</li>
<li><a href="#19">19. 定时任务</a><ul>
<li><a href="#191">19.1 页面目标</a></li>
<li><a href="#192">19.2 页面结构</a></li>
<li><a href="#193">19.3 操作细节</a></li>
<li><a href="#194">19.4 表单字段</a></li>
<li><a href="#195">19.5 执行记录弹窗</a></li>
<li><a href="#196">19.6 交互规则</a></li>
<li><a href="#197">19.7 提示反馈</a></li>
</ul>
</li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<h1 id="agent-v21-prd">Agent 任务系统 v2.1 产品需求文档(PRD)</h1>
<table>
<thead>
<tr>
<th>项</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>文档版本</td>
<td>v2.1</td>
</tr>
<tr>
<td>产出时间</td>
<td>2026-04-24</td>
</tr>
<tr>
<td>产品形态</td>
<td>Web 管理后台(Next.js 14 + NestJS + PostgreSQL)</td>
</tr>
<tr>
<td>文档来源</td>
<td>基于高保真原型 <code>agent_task_system_merged.html</code> 反向拆解</td>
</tr>
<tr>
<td>说明</td>
<td>本文档按模块编写 PRD,每个模块包含:页面目标、页面结构、数据字段、<strong>按钮级操作细节</strong>、表单字段、交互规则、提示反馈</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="_1">一、产品概述</h2>
<h3 id="11">1.1 产品定位</h3>
<p>企业级 <strong>Agent 任务自动化平台</strong>,提供基于角色权限的 Skill 调度与管理能力,支持龙虾 Agent + 脚本引擎双执行器架构。</p>
<h3 id="12">1.2 核心能力</h3>
<ul>
<li><strong>权限体系</strong>:组织(公司 → 部门 → 小组)→ 角色(部门级)→ 菜单/产品/Skill/账号四维权限</li>
<li><strong>产品链路</strong>:产品 → 渠道码(内导 + 自然)→ 平台产品账号 → 归属用户</li>
<li><strong>Skill 中心</strong>:龙虾 Agent + 脚本模板双执行器,支持参数映射与测试台</li>
<li><strong>任务调度</strong>:四步向导创建任务、交集校验、实时执行、定时调度</li>
<li><strong>观测能力</strong>:任务列表、Skill 调用日志、操作日志、统计报表</li>
<li><strong>系统设置</strong>:执行器节点管理、脚本模板库、定时任务</li>
</ul>
<h3 id="13">1.3 默认账号</h3>
<ul>
<li>用户名:<code>admin</code> / 密码:<code>admin123</code></li>
<li>登录成功后进入仪表盘</li>
</ul>
<hr />
<h2 id="_2">二、系统模块总览</h2>
<table>
<thead>
<tr>
<th>编号</th>
<th>模块名</th>
<th>分组</th>
<th>核心职责</th>
</tr>
</thead>
<tbody>
<tr>
<td>01</td>
<td>登录页</td>
<td>入口</td>
<td>账号密码 + 验证码登录</td>
</tr>
<tr>
<td>02</td>
<td>仪表盘</td>
<td>首页</td>
<td>系统运行概览、快捷入口、实时数据</td>
</tr>
<tr>
<td>03</td>
<td>组织架构</td>
<td>权限管理</td>
<td>公司/部门/小组三级树</td>
</tr>
<tr>
<td>04</td>
<td>角色管理</td>
<td>权限管理</td>
<td>部门级角色 + 四维权限配置</td>
</tr>
<tr>
<td>05</td>
<td>用户管理</td>
<td>权限管理</td>
<td>用户 CRUD、多角色绑定、跨部门授权</td>
</tr>
<tr>
<td>12</td>
<td>菜单管理</td>
<td>权限管理</td>
<td>菜单树 + 按钮权限维护</td>
</tr>
<tr>
<td>06</td>
<td>产品管理</td>
<td>产品管理</td>
<td>产品 CRUD、渠道码绑定、批量导入</td>
</tr>
<tr>
<td>07</td>
<td>渠道码管理</td>
<td>产品管理</td>
<td>内导/自然渠道码独立管理、产品绑定</td>
</tr>
<tr>
<td>13</td>
<td>平台套件</td>
<td>产品管理</td>
<td>平台 + 产品代号两级关系维护</td>
</tr>
<tr>
<td>08</td>
<td>平台产品账号</td>
<td>平台账号</td>
<td>用户自管平台登录凭据、连通测试</td>
</tr>
<tr>
<td>09</td>
<td>Skill 管理</td>
<td>Skill 中心</td>
<td>双执行器 Skill 注册、参数映射、测试</td>
</tr>
<tr>
<td>14</td>
<td>Skill 调用日志</td>
<td>Skill 中心</td>
<td>历史调用审计、详情与日志回放</td>
</tr>
<tr>
<td>10</td>
<td>任务创建</td>
<td>任务中心</td>
<td>四步向导:Skill → 产品 → 参数 → 确认</td>
</tr>
<tr>
<td>11</td>
<td>任务列表</td>
<td>任务中心</td>
<td>任务检索、取消、重试、详情查看</td>
</tr>
<tr>
<td>15</td>
<td>操作日志</td>
<td>日志</td>
<td>系统增删改 + 登录审计</td>
</tr>
<tr>
<td>16</td>
<td>统计报表</td>
<td>日志</td>
<td>多维度可视化统计</td>
</tr>
<tr>
<td>17</td>
<td>执行器配置</td>
<td>系统设置</td>
<td>龙虾/脚本执行器节点配置</td>
</tr>
<tr>
<td>18</td>
<td>脚本模板管理</td>
<td>系统设置</td>
<td>Python/Node/Shell 模板库</td>
</tr>
<tr>
<td>19</td>
<td>定时任务</td>
<td>系统设置</td>
<td>Cron 调度、执行记录、手动触发</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="rb">三、全局业务规则(RB)</h2>
<table>
<thead>
<tr>
<th>编号</th>
<th>规则</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>RB-01</td>
<td>角色归属部门</td>
<td>角色分"全局角色"与"部门级角色",部门级角色仅在所属部门内可选</td>
</tr>
<tr>
<td>RB-02</td>
<td>用户多角色取并集</td>
<td>用户可绑定多个角色,有效权限 = ∪ 所有角色的权限</td>
</tr>
<tr>
<td>RB-03</td>
<td>密码规则</td>
<td>至少 6 位;重置后原 Token 失效</td>
</tr>
<tr>
<td>RB-04</td>
<td>删除用户级联</td>
<td>用户删除后,角色绑定与平台产品账号一并清除</td>
</tr>
<tr>
<td>RB-06</td>
<td>菜单权限</td>
<td>角色的菜单权限决定左侧导航可见项</td>
</tr>
<tr>
<td>RB-07</td>
<td>Skill 权限并集</td>
<td>任务创建仅展示当前用户所有角色 <code>skill_scope</code> 的并集</td>
</tr>
<tr>
<td>RB-08</td>
<td>部门切换清空角色</td>
<td>用户切换部门时自动清空已选角色(避免权限跨部门带入)</td>
</tr>
<tr>
<td>RB-09</td>
<td>渠道码必填</td>
<td>新建产品时 <code>内导渠道码</code> 与 <code>自然渠道码</code> 均必填</td>
</tr>
<tr>
<td>RB-12</td>
<td>产品范围交集校验</td>
<td>任务可选产品 = <code>Skill.product_scope</code> ∩ <code>用户角色.data_scope</code></td>
</tr>
<tr>
<td>RB-13</td>
<td>执行器类型二选一</td>
<td>Skill 的执行器 = 龙虾 Agent 或 脚本模板(互斥);执行器配置仅超级管理员可改</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="_3">四、全局交互规范</h2>
<h3 id="41-toast">4.1 Toast 反馈</h3>
<ul>
<li>成功:绿底绿字(<code>#dcfce7</code> / <code>#166534</code>),文案格式 <code>✅ xxx 成功</code></li>
<li>错误:红底红字(<code>#fee2e2</code> / <code>#991b1b</code>),文案格式 <code>❌ xxx</code> 或 <code>请输入 xxx</code></li>
<li>显示时长:2.5 秒自动隐藏,从顶部透明下滑渐现</li>
</ul>
<h3 id="42-modal">4.2 Modal 弹窗</h3>
<ul>
<li>所有模态框右上角提供 <code>✕</code> 关闭</li>
<li>点击半透明遮罩关闭弹窗</li>
<li>保存按钮通常位于页脚右侧(主按钮紫色 <code>#6366f1</code>),取消按钮左侧(灰色边框)</li>
<li>删除确认弹窗独立样式:红色主按钮、🗑️ 图标、说明"此操作不可恢复"</li>
</ul>
<h3 id="43">4.3 表格通用</h3>
<ul>
<li>表头支持批量选择(复选框)</li>
<li>行内操作列放在最右:常见为 <code>编辑 / 删除 / 其他</code></li>
<li>搜索 + 下拉筛选均实时触发(<code>oninput</code> / <code>onchange</code> → <code>filterT()</code>)</li>
<li>分页栏位于底部:<code>共 X 条</code> + 页码</li>
</ul>
<h3 id="44">4.4 权限与可见性</h3>
<ul>
<li>左侧菜单由当前角色的 <code>menu_scope</code> 决定(RB-06)</li>
<li>按钮级权限由 <code>button_code</code> 决定(如 <code>product:create</code>)</li>
<li>超级管理员 (<code>super_admin</code>) 可见全部模块</li>
</ul>
<hr />
<h1 id="prd">五、模块 PRD 详情</h1>
<hr />
<h2 id="01">01. 登录页</h2>
<h3 id="11_1">1.1 页面目标</h3>
<p>通过账号密码(+ 验证码)验证用户身份,登录成功后签发 JWT Token 并跳转仪表盘。</p>
<h3 id="12_1">1.2 页面结构</h3>
<table>
<thead>
<tr>
<th>区块</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>左侧品牌区</td>
<td>产品名 <code>🤖 Agent任务系统</code>、Slogan、4 条核心特性</td>
</tr>
<tr>
<td>右侧登录表单</td>
<td>标题、欢迎语、用户名 / 密码 / 验证码输入、选项栏、登录按钮、页脚</td>
</tr>
<tr>
<td>Toast 反馈区</td>
<td>右上角,登录结果提示</td>
</tr>
</tbody>
</table>
<h3 id="13_1">1.3 表单字段</h3>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>默认</th>
<th>校验</th>
</tr>
</thead>
<tbody>
<tr>
<td>用户名 / 邮箱</td>
<td>text</td>
<td>是</td>
<td><code>admin</code></td>
<td>非空,否则显示"请输入用户名"</td>
</tr>
<tr>
<td>密码</td>
<td>password</td>
<td>是</td>
<td><code>admin123</code></td>
<td>非空,否则显示"请输入密码"</td>
</tr>
<tr>
<td>验证码</td>
<td>text(4 位)</td>
<td>否(前端未强制)</td>
<td>空</td>
<td>最多 4 位</td>
</tr>
<tr>
<td>记住登录</td>
<td>checkbox</td>
<td>否</td>
<td>已勾选</td>
<td>—</td>
</tr>
</tbody>
</table>
<h3 id="14">1.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>验证码图片</td>
<td><code>A7X2</code> 验证码图</td>
<td>点击刷新验证码(随机生成 4 位大写字母数字,排除易混字符)</td>
<td>始终可用</td>
<td>无</td>
</tr>
<tr>
<td>选项栏</td>
<td>忘记密码?</td>
<td>Toast:<code>请联系管理员重置密码</code></td>
<td>始终可用</td>
<td>无</td>
</tr>
<tr>
<td>表单页脚</td>
<td><code>登 录</code></td>
<td>1. 前端校验用户名/密码非空;2. 置 disabled + loading;3. 1.5s 后:若 <code>admin/admin123</code> → Toast <code>✅ 登录成功!正在跳转...</code> + 1s 后 <code>postMessage('login-success')</code> 通知父容器;否则 → Toast <code>❌ 用户名或密码错误</code> + 刷新验证码</td>
<td>校验通过后</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="15">1.5 交互规则</h3>
<ul>
<li>登录接口失败时,清空验证码并刷新</li>
<li>嵌入 iframe 中时通过 <code>window.parent.postMessage('login-success','*')</code> 通知宿主应用展开侧边栏并跳转仪表盘</li>
</ul>
<hr />
<h2 id="02">02. 仪表盘(首页)</h2>
<h3 id="21">2.1 页面目标</h3>
<p>系统运行概览 + 实时数据统计 + 快捷入口,提供用户日常首屏视图。</p>
<h3 id="22">2.2 页面结构</h3>
<ol>
<li><strong>面包屑 + 用户信息</strong> 顶栏</li>
<li><strong>快捷入口区</strong>:4 个方块(创建任务 / 管理 Skill / 平台账号 / 任务列表)</li>
<li><strong>今日指标卡</strong>:6 张卡(今日任务总数 / 成功 / 失败 / 运行中 / 活跃用户 / 已注册 Skill)</li>
<li><strong>图表行 1</strong>:最近 7 天任务趋势(柱状图)+ 执行器分布(环形 Legend)</li>
<li><strong>图表行 2</strong>:热门 Skill Top 5 + 部门任务统计(进度条)</li>
<li><strong>最新任务动态</strong>:任务列表(8 行,ID / Skill / 执行器 / 产品 / 创建人 / 状态 / 耗时 / 时间)</li>
<li><strong>系统状态</strong>:4 组(龙虾 / 脚本引擎 / 数据库 / 消息队列)</li>
</ol>
<h3 id="23">2.3 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>快捷入口</td>
<td>⚡ 创建任务</td>
<td>跳转"10. 任务创建"</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>快捷入口</td>
<td>🧩 管理 Skill</td>
<td>跳转"09. Skill 管理"</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>快捷入口</td>
<td>🔗 平台账号</td>
<td>跳转"08. 平台产品账号"</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>快捷入口</td>
<td>📋 任务列表</td>
<td>跳转"11. 任务列表"</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>最新任务动态</td>
<td>查看全部 →</td>
<td>跳转"11. 任务列表"</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>图表柱子</td>
<td>柱子 hover</td>
<td>高亮对应柱子并展示数值</td>
<td>鼠标悬停</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="24">2.4 交互规则</h3>
<ul>
<li>柱状图进入视图后自带高度缓动动画(100ms 起)</li>
<li>每 3 秒模拟一次实时刷新:有 30% 概率 <code>今日任务总数 +1</code>,其中 80% 加到"成功",20% 加到"失败"</li>
<li>指标卡 hover 显示轻微阴影提升</li>
</ul>
<h3 id="25">2.5 提示反馈</h3>
<ul>
<li>无负面反馈(只读页面)</li>
</ul>
<hr />
<h2 id="03">03. 组织架构</h2>
<h3 id="31">3.1 页面目标</h3>
<p>维护 <code>公司 → 部门 → 小组</code> 三级树形结构,部门节点挂载角色与成员。</p>
<h3 id="32">3.2 页面结构</h3>
<ol>
<li><strong>左栏 · 组织树</strong>:搜索框 + 树(含展开/收起、当前选中高亮、新增按钮)</li>
<li><strong>右栏 · 详情面板</strong>:组织信息(类型 / 成员数 / 下辖组数 / 负责人 / 状态 / 创建时间)+ 编辑/删除按钮</li>
<li><strong>部门角色列表</strong>:角色名称 / 角色编码 / 成员数 / Skill 数 / 状态</li>
<li><strong>部门成员列表</strong>:姓名 / 工号 / 所属小组 / 角色 / 入职日期 / 状态 + 导出按钮</li>
<li><strong>弹窗</strong>:新增/编辑组织、确认删除</li>
</ol>
<h3 id="33">3.3 数据字段</h3>
<ul>
<li>组织树节点:组织名、图标(🏢 公司 / 🏬 部门 / 👥 小组)、成员数徽章</li>
<li>详情:类型(公司/部门/小组)、成员数、下辖组数、负责人、状态、创建时间</li>
<li>角色列表列:角色名称、角色编码、成员数、Skill 数、状态</li>
<li>成员列表列:姓名、工号、所属小组、角色(多标签)、入职日期、状态</li>
</ul>
<h3 id="34">3.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>组织树卡头</td>
<td>+ 新增</td>
<td>打开 <code>新增组织</code> 弹窗</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>树节点</td>
<td>▼/▶ 折叠符</td>
<td><code>toggleTree()</code> 切换子节点展开/折叠</td>
<td>节点有子项</td>
<td>无</td>
</tr>
<tr>
<td>树节点</td>
<td>节点行</td>
<td><code>selectOrg()</code> 选中该节点、更新右侧详情面板(类型/成员/下辖组/徽章)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>详情面板</td>
<td>编辑</td>
<td>打开 <code>编辑组织</code> 弹窗(标题动态)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>详情面板</td>
<td>删除</td>
<td>打开 <code>⚠️ 确认删除</code> 弹窗</td>
<td>始终</td>
<td>有</td>
</tr>
<tr>
<td>成员列表</td>
<td>导出</td>
<td>导出当前部门成员(CSV)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>删除弹窗</td>
<td>确认删除</td>
<td>Toast <code>已删除</code>,关闭弹窗;子部门/人员自动移至上级</td>
<td>始终</td>
<td>—</td>
</tr>
<tr>
<td>新增/编辑弹窗</td>
<td>保存</td>
<td>Toast <code>保存成功</code>,关闭</td>
<td>校验通过</td>
<td>无</td>
</tr>
<tr>
<td>新增/编辑弹窗</td>
<td>取消 / ✕</td>
<td>关闭不保存</td>
<td>始终</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="35">3.5 表单字段(新增/编辑组织弹窗)</h3>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>默认</th>
<th>选项</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<tr>
<td>上级组织</td>
<td>select</td>
<td>否</td>
<td>星辰科技有限公司</td>
<td>公司/部门下拉</td>
<td>根节点无上级</td>
</tr>
<tr>
<td>组织名称</td>
<td>input</td>
<td>是</td>
<td>—</td>
<td>—</td>
<td>非空</td>
</tr>
<tr>
<td>组织类型</td>
<td>select</td>
<td>是</td>
<td>—</td>
<td>公司 / 部门 / 小组</td>
<td>必选</td>
</tr>
<tr>
<td>负责人</td>
<td>select</td>
<td>否</td>
<td>—</td>
<td>用户列表</td>
<td>—</td>
</tr>
<tr>
<td>排序号</td>
<td>number</td>
<td>否</td>
<td>0</td>
<td>—</td>
<td>—</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否</td>
<td>启用</td>
<td>启用 / 禁用</td>
<td>—</td>
</tr>
<tr>
<td>备注</td>
<td>textarea(2 行)</td>
<td>否</td>
<td>—</td>
<td>—</td>
<td>—</td>
</tr>
</tbody>
</table>
<h3 id="36">3.6 交互规则</h3>
<ul>
<li>删除节点时提示"删除后该组织下的子部门和人员将移至上级组织"</li>
<li>树节点高亮通过 <code>.sel</code> 类控制</li>
<li>搜索框实时过滤树节点(前端)</li>
</ul>
<hr />
<h2 id="04">04. 角色管理</h2>
<h3 id="41">4.1 页面目标</h3>
<p>部门级角色管理,通过 4 个维度配置权限(菜单 + 产品范围 + Skill + 平台账号),支持多角色并集。</p>
<h3 id="42">4.2 页面结构</h3>
<ol>
<li><strong>筛选栏</strong>:搜索框(角色名/编码)+ 部门下拉 + 状态下拉 + <code>+ 新增角色</code> 按钮</li>
<li><strong>角色列表</strong>:表格 10 列(含批量 checkbox)</li>
<li><strong>新增/编辑弹窗</strong>:4 个 Tab</li>
<li><strong>业务规则说明卡</strong>:RB-01 ~ RB-06</li>
</ol>
<h3 id="43_1">4.3 列表字段</h3>
<p>复选框、角色名称、角色编码、所属部门、菜单权限(X 项/全部)、产品范围(X 个/全部)、Skill 数、平台账号(X 个/全部)、成员数、状态、操作</p>
<h3 id="44_1">4.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>筛选栏</td>
<td>+ 新增角色</td>
<td>打开弹窗,标题 <code>新增角色</code>、表单清空</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>编辑</td>
<td>打开弹窗,标题 <code>编辑角色 — {名}</code>,回填</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>删除</td>
<td>删除(超级管理员行隐藏此按钮)</td>
<td>每行(非 super_admin)</td>
<td>—</td>
</tr>
<tr>
<td>弹窗 Tab</td>
<td>📋 菜单权限 / 📦 产品范围 / 🧩 Skill 权限 / 🔗 平台账号</td>
<td><code>switchRoleTab(i)</code> 切换</td>
<td>弹窗打开时</td>
<td>无</td>
</tr>
<tr>
<td>菜单权限 Tab</td>
<td>全选 checkbox</td>
<td>级联选中所有子菜单</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>弹窗</td>
<td>取消 / ✕</td>
<td>关闭</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>弹窗</td>
<td>保存</td>
<td>Toast <code>保存成功</code>、关闭</td>
<td>必填校验通过</td>
<td>无</td>
</tr>
<tr>
<td>表头</td>
<td>全选 checkbox</td>
<td>批量勾选所有行</td>
<td>始终</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="45">4.5 表单字段(弹窗)</h3>
<p><strong>基本信息(表单顶部,非 Tab 内)</strong></p>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>选项</th>
</tr>
</thead>
<tbody>
<tr>
<td>角色名称</td>
<td>input</td>
<td>是</td>
<td>—</td>
</tr>
<tr>
<td>角色编码</td>
<td>input</td>
<td>是</td>
<td>唯一</td>
</tr>
<tr>
<td>所属部门</td>
<td>select</td>
<td>是</td>
<td>投放部 / 运营部 / 技术部 / 产品部</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否</td>
<td>启用 / 禁用</td>
</tr>
<tr>
<td>描述</td>
<td>textarea</td>
<td>否</td>
<td>—</td>
</tr>
</tbody>
</table>
<p><strong>Tab 0 菜单权限</strong>:菜单树 + 全选 checkbox,一级包含:首页、权限管理、产品管理、Skill 中心、任务中心。</p>
<p><strong>Tab 1 产品范围</strong>:多选 checkbox,选项 <code>ProductA ~ ProductD</code>。</p>
<p><strong>Tab 2 Skill 权限</strong>:多选 checkbox,选项:竞品分析 Agent、数据采集脚本、素材生成 Agent、评论监控脚本、投放优化 Agent、价格监控 Agent。</p>
<p><strong>Tab 3 平台账号</strong>:表格(平台 / 账号 / 状态 / 绑定 checkbox)。</p>
<h3 id="46">4.6 提示反馈</h3>
<ul>
<li>成功:<code>保存成功</code></li>
<li>失败:输入非空校验不通过时显示 <code>请输入角色名称</code> 等</li>
</ul>
<hr />
<h2 id="05">05. 用户管理</h2>
<h3 id="51">5.1 页面目标</h3>
<p>用户 CRUD、部门-角色联动、跨组协作的额外产品授权、多角色绑定。</p>
<h3 id="52">5.2 页面结构</h3>
<ol>
<li><strong>筛选栏</strong>:搜索框 + 部门/角色/状态下拉 + 导出 + <code>+ 新增用户</code></li>
<li><strong>用户列表</strong>:表格(复选框、用户名、工号、所属部门/分组、角色、平台产品账号数、额外授权数、状态、创建时间、操作)</li>
<li><strong>新增/编辑用户弹窗</strong></li>
<li><strong>重置密码弹窗</strong> / <strong>删除确认弹窗</strong></li>
<li><strong>业务规则说明</strong>:RB-02、RB-03、RB-04、RB-08</li>
</ol>
<h3 id="53">5.3 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>筛选栏</td>
<td>导出</td>
<td>导出用户列表(CSV)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>筛选栏</td>
<td>+ 新增用户</td>
<td>打开新增弹窗(清空)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>编辑</td>
<td>打开编辑弹窗(回填)</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>重置密码</td>
<td>打开重置密码弹窗</td>
<td>每行</td>
<td>是(弹窗内)</td>
</tr>
<tr>
<td>列表行</td>
<td>删除</td>
<td>打开删除确认弹窗</td>
<td>每行</td>
<td>是(弹窗内)</td>
</tr>
<tr>
<td>表头</td>
<td>全选 checkbox</td>
<td>批量选中所有行</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>编辑弹窗·部门</td>
<td>select change</td>
<td><code>onDeptChange()</code>:清空已选角色、刷新角色列表、Toast <code>⚠️ 已切换部门,角色已清空(RB-08)</code></td>
<td>切换部门</td>
<td>—</td>
</tr>
<tr>
<td>编辑弹窗·角色</td>
<td>多选框</td>
<td>展开下拉,勾选/取消角色</td>
<td>已选部门</td>
<td>无</td>
</tr>
<tr>
<td>编辑弹窗</td>
<td>+ 添加授权</td>
<td><code>addGrant()</code> 追加一行(产品 select + 有效期 date + 删除按钮)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>编辑弹窗·授权行</td>
<td>删除</td>
<td>移除该授权行</td>
<td>行存在</td>
<td>无</td>
</tr>
<tr>
<td>编辑弹窗</td>
<td>取消</td>
<td>关闭</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>编辑弹窗</td>
<td>保存</td>
<td>校验后 Toast <code>✅ 保存成功</code></td>
<td>必填通过</td>
<td>无</td>
</tr>
<tr>
<td>重置密码弹窗</td>
<td>确认重置</td>
<td>Toast <code>✅ 密码已重置</code>;原 Token 失效</td>
<td>两次密码一致</td>
<td>—</td>
</tr>
<tr>
<td>删除确认弹窗</td>
<td>确认删除</td>
<td>Toast <code>✅ 已删除</code>;级联清除角色绑定与账号</td>
<td>始终</td>
<td>—</td>
</tr>
</tbody>
</table>
<h3 id="54">5.4 表单字段(新增/编辑)</h3>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>默认</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>用户名</td>
<td>input</td>
<td>是</td>
<td>—</td>
<td>唯一</td>
</tr>
<tr>
<td>密码</td>
<td>password</td>
<td>是(新增时)</td>
<td>—</td>
<td>至少 6 位(RB-03)</td>
</tr>
<tr>
<td>邮箱</td>
<td>email</td>
<td>否</td>
<td>—</td>
<td>格式校验</td>
</tr>
<tr>
<td>手机号</td>
<td>tel</td>
<td>否</td>
<td>—</td>
<td>格式校验</td>
</tr>
<tr>
<td>所属部门</td>
<td>select</td>
<td>是</td>
<td>—</td>
<td>tf/yy/tech/pm</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否</td>
<td>启用</td>
<td>启用 / 禁用</td>
</tr>
<tr>
<td>绑定角色</td>
<td>multi-select</td>
<td>是</td>
<td>—</td>
<td>根据部门动态加载,至少选 1 个</td>
</tr>
<tr>
<td>额外产品授权</td>
<td>动态行(产品 select + 有效期 date)</td>
<td>否</td>
<td>空</td>
<td>跨部门/小组协作用(RB-02 并集)</td>
</tr>
</tbody>
</table>
<p><strong>部门-角色联动字典</strong>:
- tf(投放部)→ 投放主管、投放专员、数据分析师
- yy(运营部)→ 运营主管、运营专员
- tech(技术部)→ 开发工程师、运维工程师、测试工程师
- pm(产品部)→ 产品经理、UI 设计师</p>
<h3 id="55">5.5 提示反馈</h3>
<ul>
<li>保存成功 / 已删除 / 密码已重置(绿色)</li>
<li><code>请输入用户名</code> / <code>请至少选择一个角色</code> / <code>⚠️ 已切换部门,角色已清空(RB-08)</code>(红色)</li>
</ul>
<hr />
<h2 id="06">06. 产品管理</h2>
<h3 id="61">6.1 页面目标</h3>
<p>产品 CRUD、渠道码(内导/自然)必填绑定、CSV 批量导入、多维筛选。</p>
<h3 id="62">6.2 页面结构</h3>
<ol>
<li><strong>统计卡</strong>:产品总数 / 启用中 / 已禁用 / 平台数</li>
<li><strong>筛选栏</strong>:搜索 + 平台/部门/状态下拉 + 导出 + 📤 导入 + <code>+ 新增产品</code></li>
<li><strong>产品列表</strong>:8 列 + 操作</li>
<li><strong>新增/编辑弹窗</strong> / <strong>批量导入弹窗</strong> / <strong>删除确认弹窗</strong></li>
</ol>
<h3 id="63">6.3 列表字段</h3>
<p>复选框、产品名称、产品代号(唯一)、平台、部门/小组、内导渠道码(如 <code>IC001</code>)、自然渠道码(如 <code>NC001</code>)、负责人、状态</p>
<h3 id="64">6.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>筛选栏</td>
<td>导出</td>
<td>Toast <code>📥 导出成功</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>筛选栏</td>
<td>📤 导入</td>
<td>打开 <code>批量导入产品</code> 弹窗</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>筛选栏</td>
<td>+ 新增产品</td>
<td>打开新增弹窗</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>编辑 / 删除</td>
<td>同模式</td>
<td>每行</td>
<td>删除是</td>
</tr>
<tr>
<td>导入弹窗</td>
<td>上传区</td>
<td><code>fileInput.click()</code> 触发文件选择</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>导入弹窗</td>
<td>清除文件</td>
<td>清空已选文件,禁用 <code>开始导入</code></td>
<td>文件已选</td>
<td>无</td>
</tr>
<tr>
<td>导入弹窗</td>
<td>📥 下载导入模板</td>
<td>Toast <code>📥 模板已下载</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>导入弹窗</td>
<td>开始导入</td>
<td>Toast <code>✅ 成功导入 21 条,覆盖 2 条</code></td>
<td>文件已选</td>
<td>无</td>
</tr>
<tr>
<td>导入弹窗</td>
<td>取消</td>
<td>关闭</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>新增/编辑弹窗</td>
<td>保存</td>
<td>校验渠道码必填(RB-09),Toast <code>✅ 保存成功</code></td>
<td>校验通过</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="65">6.5 表单字段</h3>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>选项</th>
</tr>
</thead>
<tbody>
<tr>
<td>产品名称</td>
<td>input</td>
<td>是</td>
<td>—</td>
</tr>
<tr>
<td>产品代号</td>
<td>input</td>
<td>是(唯一)</td>
<td>—</td>
</tr>
<tr>
<td>所属平台</td>
<td>select</td>
<td>是</td>
<td>小红书 / 抖音 / 微信公众号 / 微博 / Facebook / TikTok</td>
</tr>
<tr>
<td>所属部门</td>
<td>select</td>
<td>是</td>
<td>投放部 / 运营部 / 技术部</td>
</tr>
<tr>
<td>所属小组</td>
<td>select</td>
<td>否</td>
<td>投放一/二组、内容运营组 等</td>
</tr>
<tr>
<td>负责人</td>
<td>select</td>
<td>否</td>
<td>用户列表</td>
</tr>
<tr>
<td><strong>内导渠道码</strong></td>
<td>input</td>
<td><strong>是(RB-09)</strong></td>
<td>唯一</td>
</tr>
<tr>
<td><strong>自然渠道码</strong></td>
<td>input</td>
<td><strong>是(RB-09)</strong></td>
<td>唯一</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否</td>
<td>启用 / 禁用</td>
</tr>
</tbody>
</table>
<h3 id="66">6.6 提示反馈</h3>
<ul>
<li>成功:<code>✅ 保存成功</code> / <code>✅ 成功导入 X 条,覆盖 Y 条</code></li>
<li>失败:<code>内导渠道码必填(RB-09)</code> / <code>自然渠道码必填(RB-09)</code></li>
</ul>
<hr />
<h2 id="07">07. 渠道码管理</h2>
<h3 id="71">7.1 页面目标</h3>
<p>按 Tab 分别管理 <strong>内导渠道码</strong> 与 <strong>自然渠道码</strong>,支持与产品的双向绑定。</p>
<h3 id="72">7.2 页面结构</h3>
<ol>
<li><strong>统计卡</strong>:渠道码总数 / 内导数 / 自然数 / 关联产品数</li>
<li><strong>Tab</strong>:内导渠道码 | 自然渠道码(互斥显示)</li>
<li>每个 Tab 内:搜索 + 状态下拉 + <code>+ 新增 {类型} 渠道码</code> + 列表</li>
<li><strong>新增/编辑渠道码弹窗</strong> / <strong>绑定产品弹窗</strong> / <strong>删除确认弹窗</strong></li>
</ol>
<h3 id="73">7.3 列表字段</h3>
<p>渠道码(<code>IC001</code> 代码样式)、渠道名称、类型(内导/自然)、关联产品数、状态、创建时间、操作(编辑 / 绑定 / 删除)</p>
<h3 id="74">7.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tab</td>
<td>内导 / 自然</td>
<td><code>switchTab(i)</code> 切换列表</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>Tab 头</td>
<td>+ 新增内导/自然渠道码</td>
<td>打开新增弹窗(type 预设)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>编辑 / 绑定 / 删除</td>
<td>分别打开对应弹窗</td>
<td>每行</td>
<td>删除是</td>
</tr>
<tr>
<td>绑定弹窗</td>
<td>解绑(每行)</td>
<td>移除该产品绑定,Toast <code>已解绑</code></td>
<td>存在绑定</td>
<td>无</td>
</tr>
<tr>
<td>绑定弹窗</td>
<td>绑定</td>
<td>将下拉选中产品加入已绑定列表,Toast <code>✅ 绑定成功</code></td>
<td>选中产品</td>
<td>无</td>
</tr>
<tr>
<td>绑定弹窗</td>
<td>关闭</td>
<td>关闭</td>
<td>始终</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="75">7.5 表单字段(新增/编辑)</h3>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>选项</th>
</tr>
</thead>
<tbody>
<tr>
<td>渠道码</td>
<td>input</td>
<td>是(唯一)</td>
<td>—</td>
</tr>
<tr>
<td>渠道名称</td>
<td>input</td>
<td>是</td>
<td>—</td>
</tr>
<tr>
<td>渠道类型</td>
<td>select</td>
<td>是</td>
<td>内导(internal)/ 自然(natural)</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否</td>
<td>启用 / 禁用</td>
</tr>
<tr>
<td>备注</td>
<td>input</td>
<td>否</td>
<td>—</td>
</tr>
</tbody>
</table>
<h3 id="76">7.6 提示反馈</h3>
<ul>
<li><code>✅ 保存成功</code> / <code>✅ 绑定成功</code> / <code>已解绑</code></li>
<li><code>请输入渠道码</code> / <code>请输入渠道名称</code></li>
</ul>
<hr />
<h2 id="08">08. 平台产品账号</h2>
<h3 id="81">8.1 页面目标</h3>
<p><strong>v2.1 变更</strong>:平台产品账号归属 <strong>用户</strong>(非角色),由用户自行维护各平台登录凭据,支持连通测试。</p>
<h3 id="82">8.2 页面结构</h3>
<ol>
<li><strong>变更说明条</strong>(顶部 note)</li>
<li><strong>统计卡</strong>:我的账号总数 / 启用中 / 已禁用 / 覆盖平台</li>
<li><strong>筛选栏</strong>:搜索 + 平台/状态下拉 + <code>+ 添加平台产品账号</code></li>
<li><strong>账号列表</strong>:6 行、8 列</li>
<li><strong>新增/编辑弹窗</strong>(含密码加密显示 + 连通测试)</li>
<li><strong>连通测试结果弹窗</strong> / <strong>删除确认弹窗</strong></li>
</ol>
<h3 id="83">8.3 列表字段</h3>
<p>平台(图标+文字)、平台地址(URL)、产品代号(<code>PROD001</code>)、产品名称、登录账号、登录密码(<code>●●●●●●</code>)、谷歌密钥(<code>●●●●5A2F</code> 部分显示)、状态</p>
<h3 id="84">8.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>筛选栏</td>
<td>+ 添加平台产品账号</td>
<td>打开新增弹窗</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>编辑</td>
<td>打开编辑弹窗,<code>openEdit(plat, code, login)</code> 回填</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>测试</td>
<td>执行连通测试,打开测试结果弹窗(随机成功/失败)</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>删除</td>
<td>打开删除弹窗(有任务引用的账号禁止删除)</td>
<td>每行</td>
<td>是</td>
</tr>
<tr>
<td>弹窗</td>
<td>选择平台(select)</td>
<td><code>onPlatChange()</code> 自动填充平台名/地址、按平台过滤产品列表</td>
<td>始终</td>
<td>—</td>
</tr>
<tr>
<td>弹窗</td>
<td>👁️ 显示/隐藏密码</td>
<td><code>togglePwd()</code> 切换密码字段 <code>type=password↔text</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>弹窗</td>
<td>🔌 连通测试</td>
<td>1.5s 后随机 Toast <code>✅ 连通成功!</code> 或 <code>连通失败</code></td>
<td>平台/账号已填</td>
<td>无</td>
</tr>
<tr>
<td>弹窗</td>
<td>保存 / 取消</td>
<td>保存后 <code>✅ 保存成功</code></td>
<td>校验通过</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="85">8.5 表单字段</h3>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>选择平台</td>
<td>select</td>
<td>是</td>
<td>小红书(xhs) / 抖音(dy) / 微信公众号(wx) / 微博(wb) / Facebook(fb) / TikTok(tt)</td>
</tr>
<tr>
<td>平台名称</td>
<td>input readonly</td>
<td>—</td>
<td>随平台联动</td>
</tr>
<tr>
<td>平台地址</td>
<td>input readonly</td>
<td>—</td>
<td>随平台联动(如 <code>pro.xiaohongshu.com</code>)</td>
</tr>
<tr>
<td>产品代号</td>
<td>select</td>
<td>是</td>
<td>按所选平台 + 用户 <code>data_scope</code> 动态加载</td>
</tr>
<tr>
<td>登录账号</td>
<td>input</td>
<td>是</td>
<td>—</td>
</tr>
<tr>
<td>登录密码</td>
<td>password</td>
<td>是</td>
<td>👁️ 可切换显隐</td>
</tr>
<tr>
<td>谷歌密钥(2FA)</td>
<td>password</td>
<td>否</td>
<td>—</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否</td>
<td>启用 / 禁用</td>
</tr>
</tbody>
</table>
<p><strong>平台信息字典(PLAT_INFO)</strong>:
- <code>xhs</code> → 小红书 / <code>pro.xiaohongshu.com</code> / 产品 <code>[PROD001, PROD002]</code>
- <code>dy</code> → 抖音 / <code>business.douyin.com</code> / <code>[PROD003, PROD004]</code>
- <code>wx</code> → 微信公众号 / <code>mp.weixin.qq.com</code> / <code>[PROD005]</code>
- <code>wb</code> → 微博 / <code>weibo.com</code> / <code>[PROD008]</code>
- <code>fb</code> → Facebook / <code>business.facebook.com</code> / <code>[PROD006]</code>
- <code>tt</code> → TikTok / <code>ads.tiktok.com</code> / <code>[PROD007]</code></p>
<h3 id="86">8.6 提示反馈</h3>
<ul>
<li><code>✅ 已加载 {平台}平台信息</code> / <code>✅ 保存成功</code> / <code>✅ 已删除</code></li>
<li><code>✅ 连通成功!</code> / <code>连通失败</code></li>
<li><code>请选择平台</code> / <code>请选择产品代号</code></li>
</ul>
<hr />
<h2 id="09-skill">09. Skill 管理</h2>
<h3 id="91">9.1 页面目标</h3>
<p>Skill 注册与管理,支持 <strong>双执行器</strong>(龙虾 Agent / 脚本模板)、产品范围绑定、JSON Schema 参数映射、内置测试台。</p>
<h3 id="92">9.2 页面结构</h3>
<ol>
<li><strong>统计卡</strong>:Skill 总数 / 龙虾数 / 脚本数 / 启用中</li>
<li><strong>筛选栏</strong>:搜索 + 分类/执行器/状态下拉 + <code>+ 注册 Skill</code></li>
<li><strong>Skill 列表</strong>:6 行、7 列</li>
<li><strong>注册/编辑 Skill 弹窗</strong>:5 Tab(基本信息 / 执行器配置 / 产品范围 / 参数映射 / 测试台)</li>
<li><strong>删除确认弹窗</strong></li>
</ol>
<h3 id="93">9.3 列表字段</h3>
<p>Skill 名称、分类、执行器(🦞 龙虾 / 📜 脚本)、产品范围(X 个或全部)、调用次数、成功率(带颜色)、状态</p>
<h3 id="94">9.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>筛选栏</td>
<td>+ 注册 Skill</td>
<td>打开弹窗,标题 <code>注册 Skill</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>编辑 / 删除</td>
<td>弹窗回填 / 删除弹窗</td>
<td>每行</td>
<td>删除是;<strong>已被角色引用需先解除</strong></td>
</tr>
<tr>
<td>弹窗 Tab</td>
<td>5 Tab 切换</td>
<td><code>switchST(i)</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>Tab 0</td>
<td>执行器类型 radio(龙虾/脚本)</td>
<td><code>selExec()</code> 显隐对应配置区(RB-13)</td>
<td>必选</td>
<td>—</td>
</tr>
<tr>
<td>Tab 1 龙虾</td>
<td>🔌 测试连通性</td>
<td>Toast <code>✅ 龙虾平台连通成功</code></td>
<td>配置完整</td>
<td>无</td>
</tr>
<tr>
<td>Tab 1 脚本</td>
<td>脚本模板 select</td>
<td><code>onScriptTpl()</code> 联动脚本类型</td>
<td>选中模板</td>
<td>—</td>
</tr>
<tr>
<td>Tab 1 脚本</td>
<td>+ 添加环境变量</td>
<td><code>addEnv()</code> 追加 KV 行</td>
<td>脚本模式</td>
<td>无</td>
</tr>
<tr>
<td>Tab 1 脚本</td>
<td>环境变量行·删除</td>
<td>移除该行</td>
<td>行存在</td>
<td>无</td>
</tr>
<tr>
<td>Tab 2</td>
<td>产品多选框</td>
<td>展开下拉,勾选/取消</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>Tab 3</td>
<td>inputSchema textarea</td>
<td>可编辑 JSON Schema</td>
<td>始终</td>
<td>合法 JSON</td>
</tr>
<tr>
<td>Tab 3</td>
<td>参数映射行</td>
<td>为每个字段选择「表达式/常量」</td>
<td>始终</td>
<td>—</td>
</tr>
<tr>
<td>Tab 4</td>
<td>测试参数 JSON textarea</td>
<td>可编辑</td>
<td>始终</td>
<td>合法 JSON</td>
</tr>
<tr>
<td>Tab 4</td>
<td>▶️ 执行测试</td>
<td><code>runTest()</code>:每 500ms 追加日志,2.5s 完成</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>弹窗</td>
<td>保存</td>
<td>Toast <code>✅ Skill 已保存</code></td>
<td>校验通过</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="95">9.5 表单字段</h3>
<p><strong>Tab 0 基本信息</strong></p>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
</tr>
</thead>
<tbody>
<tr>
<td>Skill 名称</td>
<td>input</td>
<td>是</td>
</tr>
<tr>
<td>分类</td>
<td>select</td>
<td>否(内容发布 / 数据采集 / 账号运营 / 广告投放 / 数据分析)</td>
</tr>
<tr>
<td>描述</td>
<td>textarea</td>
<td>否</td>
</tr>
<tr>
<td>执行器类型</td>
<td>radio</td>
<td>是(RB-13,二选一)</td>
</tr>
</tbody>
</table>
<p><strong>Tab 1 执行器配置 · 龙虾模式</strong></p>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>默认</th>
</tr>
</thead>
<tbody>
<tr>
<td>API 地址</td>
<td>url</td>
<td>是</td>
<td><code>https://api.lobster-agent.com/v1</code></td>
</tr>
<tr>
<td>API Key</td>
<td>password</td>
<td>是</td>
<td><code>sk-lobster-xxxx</code></td>
</tr>
<tr>
<td>Agent ID</td>
<td>input</td>
<td>是</td>
<td><code>agent_xhs_publish_01</code></td>
</tr>
</tbody>
</table>
<p><strong>Tab 1 执行器配置 · 脚本模式</strong></p>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>默认</th>
</tr>
</thead>
<tbody>
<tr>
<td>脚本模板</td>
<td>select</td>
<td>是</td>
<td>Python-通用HTTP / Python-数据清洗 / Shell-文件处理 / Node.js-API 调用</td>
</tr>
<tr>
<td>环境变量(KV 动态行)</td>
<td>动态组</td>
<td>否</td>
<td>预填 1 行 <code>API_KEY</code></td>
</tr>
<tr>
<td>超时时间(秒)</td>
<td>number</td>
<td>否</td>
<td>30</td>
</tr>
<tr>
<td>脚本类型</td>
<td>input readonly</td>
<td>否</td>
<td>联动自填 python/shell/node</td>
</tr>
</tbody>
</table>
<p><strong>Tab 2 产品范围</strong>:多选 <code>PROD001 ~ PROD006</code></p>
<p><strong>Tab 3 参数映射</strong>:JSON Schema + 逐字段映射(表达式/常量)</p>
<p><strong>Tab 4 测试台</strong>:测试参数 JSON + 日志输出区</p>
<h3 id="96">9.6 提示反馈</h3>
<ul>
<li><code>✅ 龙虾平台连通成功</code> / <code>✅ Skill 已保存</code> / <code>✅ 已删除</code></li>
<li>点击弹窗外关闭所有多选下拉 <code>.ms-drop</code></li>
</ul>
<hr />
<h2 id="10">10. 任务创建(四步向导)</h2>
<h3 id="101">10.1 页面目标</h3>
<p>通过 <strong>4 步向导</strong> 创建任务:选择 Skill → 选择产品 → 填写参数 → 确认提交,过程包含 RB-07/RB-12 权限与交集校验。</p>
<h3 id="102">10.2 页面结构</h3>
<ol>
<li><strong>步骤条</strong>(4 个节点 + 连线)</li>
<li><strong>Step 1</strong>:Skill 卡片列表(搜索 + 选择)+ 规则提示条</li>
<li><strong>Step 2</strong>:产品卡片列表(搜索 + 选择)+ 交集提示条 + 渠道码自动填充提示</li>
<li><strong>Step 3</strong>:参数表单(自动回填 Skill + 产品 + 渠道码)</li>
<li><strong>Step 4</strong>:确认信息预览 + 校验通过条</li>
<li><strong>成功弹窗</strong>:任务 ID + 基本信息 + "继续创建/查看任务列表"</li>
</ol>
<h3 id="103">10.3 关键字段</h3>
<ul>
<li>Skill 卡:名称、执行器、分类、描述</li>
<li>产品卡:名称、代号、平台、投放组</li>
<li>参数表单:产品(只读)、发布内容、标签、发布时间、内导渠道码(只读,自动填充)</li>
<li>渠道码映射(PROD_CH):<code>PROD001→IC001/NC001</code> 等</li>
</ul>
<h3 id="104">10.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>Step 1 搜索框</td>
<td>输入</td>
<td><code>filterSkills()</code> 实时过滤卡片</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>Step 1</td>
<td>Skill 卡</td>
<td><code>selSkill()</code> 记录选中,解锁下一步</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>Step 1 右下</td>
<td>下一步 →</td>
<td><code>goStep(2)</code>:当前步骤 done、下一步 active</td>
<td><strong>已选 Skill</strong></td>
<td>无</td>
</tr>
<tr>
<td>Step 2 搜索框</td>
<td>输入</td>
<td><code>filterProds()</code> 实时过滤</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>Step 2</td>
<td>产品卡</td>
<td><code>selProd()</code> 记录选中 + 显示渠道码填充提示</td>
<td>交集内产品</td>
<td>—</td>
</tr>
<tr>
<td>Step 2 右下</td>
<td>上一步 / 下一步 →</td>
<td>前后切换</td>
<td>下一步需已选产品</td>
<td>无</td>
</tr>
<tr>
<td>Step 3</td>
<td>标签输入</td>
<td><code>Enter</code> 键 <code>addTag()</code> 追加标签</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>Step 3</td>
<td>标签 ×</td>
<td>删除该标签</td>
<td>标签存在</td>
<td>无</td>
</tr>
<tr>
<td>Step 3 右下</td>
<td>上一步 / 下一步 →</td>
<td>切换</td>
<td>下一步需内容非空</td>
<td>无</td>
</tr>
<tr>
<td>Step 4 右下</td>
<td>🚀 提交任务</td>
<td>打开成功弹窗(任务 ID <code>TASK-20260423-001</code>)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>成功弹窗</td>
<td>继续创建</td>
<td><code>resetWizard()</code> 回到 Step 1、清空所有状态</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>成功弹窗</td>
<td>查看任务列表</td>
<td>跳转"11. 任务列表"</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>成功弹窗</td>
<td>✕</td>
<td>关闭弹窗</td>
<td>始终</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="105">10.5 交互规则 / 校验</h3>
<ul>
<li><strong>Step 1 提示</strong>:<code>📋 仅展示您角色 skill_scope 中的 Skill(RB-07),合并所有角色取并集</code></li>
<li><strong>Step 2 提示</strong>:<code>⚠️ 产品范围 = Skill.product_scope ∩ 用户角色.data_scope(RB-12 交集校验)</code></li>
<li><strong>渠道码提示</strong>:选中产品后出现 <code>✅ 渠道码已自动填充 — 内导: IC001 · 自然: NC001</code></li>
<li><strong>Step 4 校验条</strong>:<code>✅ Skill 权限校验通过 · 产品范围交集校验通过 · 参数校验通过</code></li>
<li>步骤切换使用 <code>.step-ct.show</code> 类控制显示;步骤节点三态:active / done / pending</li>
</ul>
<h3 id="106">10.6 提示反馈</h3>
<ul>
<li>成功弹窗文案:<code>🎉 任务已提交</code> + <code>任务创建成功!</code> + 任务 ID</li>
<li>搜索占位:<code>🔍 搜索 Skill 名称...</code> / <code>🔍 搜索产品...</code></li>
</ul>
<hr />
<h2 id="11_2">11. 任务列表</h2>
<h3 id="111">11.1 页面目标</h3>
<p>展示所有任务,支持状态/执行器/时间范围筛选,提供详情、取消、重试行内操作。</p>
<h3 id="112">11.2 页面结构</h3>
<ol>
<li><strong>统计卡 × 5</strong>:任务总数(1,234)/ 成功(1,089)/ 失败(45)/ 运行中(8)/ 超时(92)</li>
<li><strong>筛选栏</strong>:搜索(任务 ID/Skill 名)+ 状态/执行器/时间范围下拉 + 导出</li>
<li><strong>列表</strong>:任务 ID / Skill / 执行器 / 产品 / 创建人 / 状态 / 耗时 / 创建时间 / 操作</li>
<li><strong>详情弹窗</strong>(4 Tab:基本信息 / 输入参数 / 执行结果 / 执行日志)</li>
<li><strong>取消确认弹窗</strong></li>
<li><strong>分页</strong></li>
</ol>
<h3 id="113">11.3 状态枚举</h3>
<p><code>SUCCEEDED</code>(绿)/ <code>FAILED</code>(红)/ <code>RUNNING</code>(黄,带 <code>...</code>)/ <code>PENDING</code>(灰)/ <code>TIMEOUT</code>(橙)</p>
<h3 id="114">11.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>筛选栏</td>
<td>搜索 / 状态 / 执行器 / 时间范围</td>
<td><code>filterT()</code> 按 <code>data-q / data-st / data-exec</code> 过滤</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>筛选栏</td>
<td>导出</td>
<td>Toast <code>📥 导出成功</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>详情</td>
<td>打开 <code>📋 任务详情</code> 弹窗</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>取消</td>
<td>打开取消确认弹窗 → Toast <code>✅ 任务已取消</code></td>
<td><strong>仅 RUNNING / PENDING</strong></td>
<td>是</td>
</tr>
<tr>
<td>列表行</td>
<td>重试</td>
<td>Toast <code>🔄 已重新提交</code></td>
<td><strong>仅 FAILED / TIMEOUT</strong></td>
<td>无</td>
</tr>
<tr>
<td>详情弹窗 Tab</td>
<td>基本信息 / 输入参数 / 执行结果 / 执行日志</td>
<td><code>switchDT(i)</code></td>
<td>弹窗打开时</td>
<td>无</td>
</tr>
<tr>
<td>分页</td>
<td>页码</td>
<td>切换当前页</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>取消弹窗</td>
<td>取消 / 确认取消</td>
<td>关闭 / 向执行器发停止信号</td>
<td>始终</td>
<td>—</td>
</tr>
</tbody>
</table>
<h3 id="115">11.5 详情弹窗内容</h3>
<ul>
<li><strong>Tab 0 基本信息</strong>:任务 ID、Skill、执行器、产品、创建人、状态(带色标签)、创建时间、耗时</li>
<li><strong>Tab 1 输入参数</strong>:JSON 展示(product_id / content / tags / channel_code)</li>
<li><strong>Tab 2 执行结果</strong>:JSON 展示(status / post_id / post_url / published_at)</li>
<li><strong>Tab 3 执行日志</strong>:深色日志盒,带时间戳 + 彩色级别(状态变更用黄色/绿色)</li>
</ul>
<h3 id="116">11.6 按钮显示规则</h3>
<table>
<thead>
<tr>
<th>状态</th>
<th>显示按钮</th>
</tr>
</thead>
<tbody>
<tr>
<td>SUCCEEDED</td>
<td>详情</td>
</tr>
<tr>
<td>FAILED</td>
<td>详情 + 重试</td>
</tr>
<tr>
<td>RUNNING</td>
<td>详情 + 取消</td>
</tr>
<tr>
<td>PENDING</td>
<td>详情 + 取消</td>
</tr>
<tr>
<td>TIMEOUT</td>
<td>详情 + 重试</td>
</tr>
</tbody>
</table>
<h3 id="117">11.7 提示反馈</h3>
<ul>
<li><code>📥 导出成功</code> / <code>✅ 任务已取消</code> / <code>🔄 已重新提交</code></li>
<li>取消弹窗文案:<code>⚠️ 取消任务</code> / <code>确定取消运行中的任务?</code> / <code>将向执行器发送停止信号</code></li>
</ul>
<hr />
<h2 id="12_2">12. 菜单管理</h2>
<h3 id="121">12.1 页面目标</h3>
<p>维护系统菜单树(目录/菜单/外链)+ 每个菜单下的按钮权限码。</p>
<h3 id="122">12.2 页面结构</h3>
<ol>
<li><strong>操作栏</strong>:+ 新增菜单 / 全部展开 / 全部收起</li>
<li><strong>左侧 菜单树</strong>:可展开/收起、行内编辑按钮、点击行切换右侧按钮视图</li>
<li><strong>右侧 按钮管理</strong>:标题显示当前菜单名、按钮列表表格、+ 新增按钮</li>
<li><strong>菜单编辑弹窗</strong> / <strong>按钮编辑弹窗</strong> / <strong>删除确认弹窗</strong></li>
</ol>
<h3 id="123">12.3 数据字段</h3>
<ul>
<li>菜单树:图标(📁 目录 / 📄 菜单 / 🔗 外链)、菜单名、行内"编辑"链接</li>
<li>按钮权限表:按钮名称、权限标识(<code>product:create</code>)、类型(primary/default/danger/warning)、状态</li>
</ul>
<p><strong>按钮权限库(BTN_DATA)示例</strong>:
- <code>product</code>:新增 / 编辑 / 删除 / 导入 / 导出
- <code>role</code>:新增 / 编辑 / 删除 / 复制
- <code>user</code>:新增 / 编辑 / 删除 / 重置密码
- <code>skill</code>:注册 / 编辑 / 删除 / 测试
- <code>channel</code>:新增 / 编辑 / 绑定
- <code>menu-mgmt</code>:新增菜单 / 编辑菜单 / 新增按钮</p>
<h3 id="124">12.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>操作栏</td>
<td>+ 新增菜单</td>
<td>打开菜单弹窗(清空)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>操作栏</td>
<td>全部展开 / 全部收起</td>
<td><code>expandAll()</code> / <code>collapseAll()</code> 更新树</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>菜单树</td>
<td>▼/▶</td>
<td><code>toggleTree()</code> 局部折叠</td>
<td>节点有子项</td>
<td>无</td>
</tr>
<tr>
<td>菜单树</td>
<td>行点击</td>
<td><code>showBtns(key)</code> 更新右侧按钮表</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>菜单树</td>
<td>编辑(每行)</td>
<td>打开菜单弹窗(回填)</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>按钮表</td>
<td>+ 新增按钮</td>
<td>打开按钮弹窗(自动填充所属菜单)</td>
<td>当前已选菜单</td>
<td>无</td>
</tr>
<tr>
<td>按钮表</td>
<td>编辑(每行)</td>
<td>打开按钮弹窗(回填)</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>按钮表</td>
<td>删除(每行)</td>
<td>删除确认弹窗 → Toast <code>✅ 已删除</code></td>
<td>每行</td>
<td>是</td>
</tr>
<tr>
<td>弹窗</td>
<td>保存</td>
<td>Toast <code>✅ 菜单已保存</code> / <code>✅ 按钮已保存</code></td>
<td>校验通过</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="125">12.5 表单字段</h3>
<p><strong>菜单编辑弹窗</strong></p>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>默认</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>菜单类型</td>
<td>select</td>
<td>是</td>
<td>directory</td>
<td>directory / menu / link;<strong>link 时隐藏组件路径与排序</strong></td>
</tr>
<tr>
<td>菜单名称</td>
<td>input</td>
<td>是</td>
<td>—</td>
<td>—</td>
</tr>
<tr>
<td>父级菜单</td>
<td>select</td>
<td>否</td>
<td>顶级</td>
<td>顶级 / 权限管理 / 产品管理 / …</td>
</tr>
<tr>
<td>路由路径</td>
<td>input</td>
<td>是</td>
<td>—</td>
<td>形如 <code>/product</code></td>
</tr>
<tr>
<td>图标</td>
<td>input</td>
<td>否</td>
<td>—</td>
<td>—</td>
</tr>
<tr>
<td>前端组件路径</td>
<td>input</td>
<td>否</td>
<td>—</td>
<td><code>link</code> 类型时隐藏</td>
</tr>
<tr>
<td>排序号</td>
<td>number</td>
<td>是</td>
<td>1</td>
<td>—</td>
</tr>
<tr>
<td>是否可见</td>
<td>select</td>
<td>否</td>
<td>显示</td>
<td>显示/隐藏</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否</td>
<td>启用</td>
<td>启用/禁用</td>
</tr>
</tbody>
</table>
<p><strong>按钮编辑弹窗</strong></p>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>所属菜单</td>
<td>input readonly</td>
<td>—</td>
<td>自动填充</td>
</tr>
<tr>
<td>按钮名称</td>
<td>input</td>
<td>是</td>
<td>—</td>
</tr>
<tr>
<td>权限标识</td>
<td>input</td>
<td>是</td>
<td>唯一,形如 <code>product:create</code></td>
</tr>
<tr>
<td>按钮类型</td>
<td>select</td>
<td>否</td>
<td>primary / default / danger / warning</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否</td>
<td>启用 / 禁用</td>
</tr>
</tbody>
</table>
<h3 id="126">12.6 提示反馈</h3>
<ul>
<li><code>✅ 菜单已保存</code> / <code>✅ 按钮已保存</code> / <code>✅ 已删除</code></li>
<li>删除确认说明:<code>删除需确保无子菜单、无角色引用</code></li>
</ul>
<hr />
<h2 id="13_2">13. 平台套件</h2>
<h3 id="131">13.1 页面目标</h3>
<p>维护 <strong>平台 + 产品代号</strong> 两级关系,为"08 平台产品账号"提供选择源。</p>
<h3 id="132">13.2 页面结构</h3>
<ol>
<li><strong>搜索栏</strong>:搜索平台名 + <code>+ 新增平台</code></li>
<li><strong>平台卡片网格</strong>(主视图):5 个平台卡(小红书/抖音/Facebook/TikTok/微信公众号)</li>
<li><strong>平台详情</strong>(点卡片后进入):← 返回 + 平台名 + 编辑/删除 + 信息块 + 产品代号表</li>
<li><strong>平台编辑弹窗</strong> / <strong>产品代号编辑弹窗</strong> / <strong>删除确认弹窗</strong></li>
</ol>
<h3 id="133">13.3 数据字段</h3>
<ul>
<li>平台卡:图标+名称、平台地址、产品数、账号数、状态</li>
<li>详情块:平台地址、状态、关联账号数</li>
<li>产品代号表:产品代号(<code>PROD001</code>)、产品名称、关联账号数、状态</li>
</ul>
<h3 id="134">13.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>搜索栏</td>
<td>搜索</td>
<td><code>filterCards()</code> 按 <code>data-q</code> 过滤</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>搜索栏</td>
<td>+ 新增平台</td>
<td>打开平台弹窗(清空)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>平台卡</td>
<td>卡片点击</td>
<td><code>showPlatDetail(key)</code> 进入详情视图</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>详情</td>
<td>← 返回</td>
<td><code>hidePlatDetail()</code> 回到列表</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>详情</td>
<td>编辑平台</td>
<td>打开平台弹窗(回填名称/地址)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>详情</td>
<td>删除平台</td>
<td>删除确认弹窗 → Toast <code>✅ 已删除</code></td>
<td><strong>无关联账号</strong></td>
<td>是</td>
</tr>
<tr>
<td>产品代号表</td>
<td>+ 新增产品代号</td>
<td>打开产品代号弹窗(自动填充平台)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>产品代号表</td>
<td>编辑 / 删除(每行)</td>
<td>弹窗</td>
<td>每行</td>
<td>删除是</td>
</tr>
<tr>
<td>弹窗</td>
<td>保存</td>
<td>Toast <code>✅ 平台已保存</code> / <code>✅ 产品代号已保存</code></td>
<td>校验通过</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="135">13.5 表单字段</h3>
<p><strong>平台编辑弹窗</strong></p>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
</tr>
</thead>
<tbody>
<tr>
<td>平台名称</td>
<td>input</td>
<td>是</td>
</tr>
<tr>
<td>平台地址</td>
<td>input</td>
<td>是(<code>https://...</code>)</td>
</tr>
<tr>
<td>平台图标</td>
<td>input</td>
<td>否(emoji 或 URL)</td>
</tr>
<tr>
<td>备注</td>
<td>textarea</td>
<td>否</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否(启用/禁用)</td>
</tr>
</tbody>
</table>
<p><strong>产品代号编辑弹窗</strong></p>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
</tr>
</thead>
<tbody>
<tr>
<td>所属平台</td>
<td>input readonly</td>
<td>—</td>
</tr>
<tr>
<td>产品代号</td>
<td>input</td>
<td>是(<code>PROD001</code> 格式)</td>
</tr>
<tr>
<td>产品名称</td>
<td>input</td>
<td>是</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否</td>
</tr>
</tbody>
</table>
<h3 id="136">13.6 提示反馈</h3>
<ul>
<li><code>✅ 平台已保存</code> / <code>✅ 产品代号已保存</code> / <code>✅ 已删除</code></li>
<li>删除说明:<code>已关联账号的平台/产品需先解除</code></li>
</ul>
<hr />
<h2 id="14-skill">14. Skill 调用日志</h2>
<h3 id="141">14.1 页面目标</h3>
<p>展示全部 Skill 调用历史,支持多维筛选、查看详情与日志回放、CSV 导出。</p>
<h3 id="142">14.2 页面结构</h3>
<ol>
<li><strong>统计卡 × 4</strong>:总调用(12,456)/ 成功(12,102)/ 失败(354)/ 平均耗时(2.4s)</li>
<li><strong>筛选栏</strong>:搜索(Skill/调用者)+ 状态/执行器/时间范围下拉 + 导出 CSV</li>
<li><strong>列表</strong>:调用 ID / Skill / 执行器 / 产品 / 调用者 / 状态 / 耗时 / 时间 / 操作</li>
<li><strong>详情弹窗</strong>:4 Tab(基本信息 / 请求参数 / 响应结果 / 执行日志)</li>
<li><strong>分页</strong></li>
</ol>
<h3 id="143">14.3 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>筛选栏</td>
<td>搜索 / 状态 / 执行器 / 时间范围</td>
<td><code>filterT()</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>筛选栏</td>
<td>导出 CSV</td>
<td>Toast <code>📥 导出成功</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>详情</td>
<td>打开详情弹窗</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>详情弹窗 Tab</td>
<td>切换</td>
<td><code>switchLT(i)</code></td>
<td>弹窗打开</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="144">14.4 详情弹窗</h3>
<ul>
<li>基本信息:调用 ID(<code>LOG-20260423-001</code>)、Skill、执行器、调用者(含分组)、状态、耗时、时间</li>
<li>请求参数:JSON</li>
<li>响应结果:JSON(post_id / post_url 等)</li>
<li>执行日志:带时间戳、彩色级别的日志盒</li>
</ul>
<h3 id="145">14.5 状态枚举</h3>
<p><code>SUCCESS</code> / <code>FAILED</code> / <code>TIMEOUT</code></p>
<h3 id="146">14.6 提示反馈</h3>
<ul>
<li><code>📥 导出成功</code></li>
</ul>
<hr />
<h2 id="15_1">15. 操作日志(审计)</h2>
<h3 id="151">15.1 页面目标</h3>
<p>记录全局的新增/编辑/删除/登录/导出行为,支持审计追踪与变更对比。</p>
<h3 id="152">15.2 页面结构</h3>
<ol>
<li><strong>筛选栏</strong>:搜索(操作人/模块)+ 模块/操作/时间下拉 + 导出</li>
<li><strong>列表</strong>:日志 ID(<code>OPLOG-xxx</code>)/ 操作人 / 模块 / 操作 / 描述 / IP / 时间</li>
<li><strong>详情弹窗</strong>:基本信息 + 请求参数 JSON + 变更 before/after JSON 对比</li>
<li><strong>分页</strong></li>
</ol>
<h3 id="153">15.3 模块与操作枚举</h3>
<ul>
<li>模块:用户管理 / 角色管理 / 产品管理 / Skill 管理 / 任务管理 / 平台产品账号 / 登录</li>
<li>操作:新增 / 编辑 / 删除 / 登录 / 导出</li>
</ul>
<h3 id="154">15.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>筛选栏</td>
<td>搜索 / 模块 / 操作</td>
<td><code>filterT()</code> 过滤</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>筛选栏</td>
<td>导出</td>
<td>Toast <code>📥 导出成功</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>详情</td>
<td>打开详情弹窗</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>详情弹窗</td>
<td>关闭</td>
<td>关闭弹窗</td>
<td>始终</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="155">15.5 提示反馈</h3>
<ul>
<li><code>📥 导出成功</code></li>
</ul>
<hr />
<h2 id="16">16. 统计报表</h2>
<h3 id="161">16.1 页面目标</h3>
<p>多维度可视化展板:任务趋势、执行器分布、状态分布、Skill/产品/用户排行。</p>
<h3 id="162">16.2 页面结构</h3>
<ol>
<li><strong>KPI 卡 × 4</strong>:任务总数 / 成功率 / 平均耗时 / 活跃 Skill(含环比)</li>
<li><strong>图表行 1</strong>:任务执行趋势(7 日柱状)+ 执行器分布(饼图 SVG)</li>
<li><strong>图表行 2</strong>:任务状态分布(柱状)+ Skill 调用 Top 5(排名列表)</li>
<li><strong>图表行 3</strong>:产品任务量 Top X + 用户活跃 Top X</li>
<li><strong>控制栏</strong>:时间范围下拉 + 刷新 + 导出 PDF</li>
</ol>
<h3 id="163">16.3 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>控制栏</td>
<td>时间范围 select</td>
<td><code>onchange → refreshCharts()</code> 重绘</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>控制栏</td>
<td>刷新</td>
<td><code>refreshCharts()</code> 所有柱子归零 → 50ms 后恢复(动画)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>控制栏</td>
<td>导出 PDF</td>
<td>Toast <code>📥 报表已导出</code></td>
<td>始终</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="164">16.4 指标示例</h3>
<ul>
<li>任务总数:1,234</li>
<li>成功率:96.3%</li>
<li>平均耗时:2.4s</li>
<li>活跃 Skill:18</li>
<li>7 日趋势:<code>[156, 189, 145, 201, 178, 210, 155]</code></li>
<li>执行器分布:龙虾 67% / 脚本 33%</li>
<li>状态分布:成功 1089 / 失败 45 / 运行中 8 / 超时 92</li>
<li>Top 5 Skill:数据清洗脚本 5123、竞品数据采集 3401、小红书笔记发布 1256 …</li>
<li>时间范围选项:最近 7 天 / 最近 30 天 / 本月 / 上月</li>
</ul>
<h3 id="165">16.5 提示反馈</h3>
<ul>
<li><code>📥 报表已导出</code> / <code>📊 数据已刷新</code></li>
</ul>
<hr />
<h2 id="17">17. 执行器配置</h2>
<h3 id="171">17.1 页面目标</h3>
<p>管理 <strong>龙虾 Agent</strong> 与 <strong>脚本引擎</strong> 两个执行器的节点配置、健康监控、并发/超时/重试策略。</p>
<h3 id="172">17.2 页面结构</h3>
<ol>
<li><strong>权限提示条</strong>:<code>仅超级管理员可修改(RB-13)</code></li>
<li><strong>执行器卡片 × 2</strong>:龙虾执行器 / 脚本执行器</li>
<li>每卡片包含:状态标签、描述、参数块、当前任务占用(n/N)、最近 24 小时健康度(24 个圆点 timeline)、3 个操作按钮</li>
<li><strong>龙虾配置弹窗</strong> / <strong>脚本配置弹窗</strong></li>
</ol>
<h3 id="173">17.3 卡片字段</h3>
<p><strong>龙虾执行器</strong>:API 地址 / 超时(30s)/ 重试(3 次)/ 并发上限(10)/ 当前 3/10</p>
<p><strong>脚本执行器</strong>:工作目录 / 超时(60s)/ 并发上限(5)/ 沙箱模式 / 当前 1/5</p>
<h3 id="174">17.4 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>龙虾卡片</td>
<td>⚙️ 配置</td>
<td>打开龙虾配置弹窗</td>
<td>超级管理员</td>
<td>无</td>
</tr>
<tr>
<td>龙虾卡片</td>
<td>🔌 测试</td>
<td>Toast <code>✅ 龙虾平台连通正常</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>龙虾卡片</td>
<td>🔄 重启</td>
<td>Toast <code>🔄 已重启</code></td>
<td>超级管理员</td>
<td>无</td>
</tr>
<tr>
<td>脚本卡片</td>
<td>⚙️ 配置 / 🔌 测试 / 🔄 重启</td>
<td>同上(脚本版)</td>
<td>同上</td>
<td>无</td>
</tr>
<tr>
<td>龙虾弹窗</td>
<td>🔌 测试连通性</td>
<td>Toast <code>✅ 龙虾平台连通正常</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>配置弹窗</td>
<td>取消</td>
<td>关闭</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>配置弹窗</td>
<td>保存</td>
<td>Toast <code>✅ 配置已保存</code></td>
<td>校验通过</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="175">17.5 表单字段</h3>
<p><strong>龙虾配置弹窗</strong></p>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>默认</th>
</tr>
</thead>
<tbody>
<tr>
<td>API 地址</td>
<td>text</td>
<td>是</td>
<td>示例值</td>
</tr>
<tr>
<td>API Key</td>
<td>password</td>
<td>是</td>
<td>示例值</td>
</tr>
<tr>
<td>超时时间(秒)</td>
<td>number</td>
<td>否</td>
<td>30</td>
</tr>
<tr>
<td>重试次数</td>
<td>number</td>
<td>否</td>
<td>3</td>
</tr>
<tr>
<td>并发上限</td>
<td>number</td>
<td>否</td>
<td>10</td>
</tr>
<tr>
<td>轮询间隔(ms)</td>
<td>number</td>
<td>否</td>
<td>2000</td>
</tr>
<tr>
<td>回调 URL</td>
<td>text</td>
<td>否</td>
<td>示例值</td>
</tr>
</tbody>
</table>
<p><strong>脚本配置弹窗</strong></p>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>默认</th>
</tr>
</thead>
<tbody>
<tr>
<td>工作目录</td>
<td>text</td>
<td>是</td>
<td>—</td>
</tr>
<tr>
<td>Python 路径</td>
<td>text</td>
<td>否</td>
<td><code>/usr/bin/python3</code></td>
</tr>
<tr>
<td>Node 路径</td>
<td>text</td>
<td>否</td>
<td><code>/usr/bin/node</code></td>
</tr>
<tr>
<td>全局超时(秒)</td>
<td>number</td>
<td>否</td>
<td>60</td>
</tr>
<tr>
<td>并发上限</td>
<td>number</td>
<td>否</td>
<td>5</td>
</tr>
<tr>
<td>沙箱模式</td>
<td>select</td>
<td>否</td>
<td>Docker 容器 / 本地进程 / 虚拟环境</td>
</tr>
<tr>
<td>日志目录</td>
<td>text</td>
<td>否</td>
<td>—</td>
</tr>
</tbody>
</table>
<h3 id="176">17.6 交互规则</h3>
<ul>
<li><code>initHealth(id)</code> 生成 24 个小圆点,随机展示成功/异常状态,悬停显示 tooltip</li>
</ul>
<h3 id="177">17.7 提示反馈</h3>
<ul>
<li><code>✅ 龙虾平台连通正常</code> / <code>✅ 脚本引擎正常</code> / <code>🔄 已重启</code> / <code>✅ 配置已保存</code></li>
</ul>
<hr />
<h2 id="18">18. 脚本模板管理</h2>
<h3 id="181">18.1 页面目标</h3>
<p>维护脚本执行器使用的预置模板,支持 Python/Node.js/Shell 代码编辑 + 环境变量声明 + Skill 引用追踪。</p>
<h3 id="182">18.2 页面结构</h3>
<ol>
<li><strong>筛选栏</strong>:搜索(模板名)+ 脚本类型下拉 + <code>+ 新增模板</code></li>
<li><strong>模板列表</strong>:模板名 / 脚本类型 / 环境变量(逗号列表)/ 引用 Skill 数 / 状态 / 更新时间</li>
<li><strong>新增/编辑弹窗</strong>:表单 + 代码编辑器(<code>code-area</code>)+ 环境变量动态行</li>
<li><strong>删除确认弹窗</strong></li>
</ol>
<h3 id="183">18.3 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>筛选栏</td>
<td>搜索 / 脚本类型</td>
<td><code>filterT()</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>筛选栏</td>
<td>+ 新增模板</td>
<td>打开弹窗(清空)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>编辑</td>
<td>打开弹窗(回填)</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>删除</td>
<td>删除确认弹窗</td>
<td>每行</td>
<td>是(需先解除 Skill 引用)</td>
</tr>
<tr>
<td>弹窗·代码区</td>
<td>格式化</td>
<td>Toast <code>✅ 代码已格式化</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>弹窗·环境变量</td>
<td>+ 添加变量</td>
<td>追加变量行</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>弹窗</td>
<td>取消 / 保存</td>
<td>关闭 / Toast <code>✅ 模板已保存</code></td>
<td>校验通过</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="184">18.4 表单字段</h3>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>模板名称</td>
<td>input</td>
<td>是</td>
<td>placeholder <code>如 通用 HTTP 请求</code></td>
</tr>
<tr>
<td>脚本类型</td>
<td>select</td>
<td>是</td>
<td>Python / Node.js / Shell(切换时联动示例代码)</td>
</tr>
<tr>
<td>描述</td>
<td>textarea(2 行)</td>
<td>否</td>
<td>—</td>
</tr>
<tr>
<td>脚本代码</td>
<td>textarea(大)</td>
<td>是</td>
<td>类型切换时预填示例模板(<code>CODE</code> 字典)</td>
</tr>
<tr>
<td>环境变量声明</td>
<td>动态表</td>
<td>否</td>
<td>每行:变量名(只读)/ 描述 / 必填(select 必填/可选)</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否</td>
<td>启用 / 禁用</td>
</tr>
</tbody>
</table>
<h3 id="185">18.5 交互规则</h3>
<ul>
<li>切换脚本类型 → <code>onTplType()</code> 自动填充示例代码(Python/Node/Shell)</li>
<li>动态添加环境变量行:<code>appendChild</code> 到 <code>envList</code></li>
</ul>
<h3 id="186">18.6 提示反馈</h3>
<ul>
<li><code>✅ 代码已格式化</code> / <code>✅ 模板已保存</code> / <code>✅ 已删除</code></li>
<li>删除前警告:<code>已被 Skill 引用的模板需先解除关联</code></li>
</ul>
<hr />
<h2 id="19">19. 定时任务</h2>
<h3 id="191">19.1 页面目标</h3>
<p>管理 Cron 定时调度任务,关联 Skill + 产品 + 参数,支持执行记录查看、启停、手动触发。</p>
<h3 id="192">19.2 页面结构</h3>
<ol>
<li><strong>统计卡 × 4</strong>:定时任务(8)/ 运行中(6)/ 已暂停(2)/ 7 日成功率(94.2%)</li>
<li><strong>筛选栏</strong>:搜索 + 状态下拉 + <code>+ 新增定时任务</code></li>
<li><strong>列表</strong>:任务名 / Skill / Cron 表达式 / 产品 / 下次执行 / 最近 7 次(timeline)/ 状态 / 开关</li>
<li><strong>新增/编辑弹窗</strong>(含 Cron 解析)</li>
<li><strong>执行记录弹窗</strong> / <strong>删除确认弹窗</strong></li>
</ol>
<h3 id="193">19.3 操作细节</h3>
<table>
<thead>
<tr>
<th>位置</th>
<th>按钮</th>
<th>行为</th>
<th>条件</th>
<th>二次确认</th>
</tr>
</thead>
<tbody>
<tr>
<td>筛选栏</td>
<td>搜索 / 状态</td>
<td><code>filterT()</code></td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>筛选栏</td>
<td>+ 新增定时任务</td>
<td>打开弹窗(清空)</td>
<td>始终</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>编辑</td>
<td>打开弹窗(回填)</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>记录</td>
<td>打开执行记录弹窗(展示最近 5 次)</td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>触发</td>
<td>Toast <code>▶️ 手动触发成功</code></td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>列表行</td>
<td>删除</td>
<td>删除确认弹窗 → Toast <code>✅ 已删除</code></td>
<td>每行</td>
<td>是</td>
</tr>
<tr>
<td>列表行</td>
<td>开关 toggle</td>
<td>启用/暂停切换,同步状态标签;Toast <code>✅ 已启用</code> / <code>⏸️ 已暂停</code></td>
<td>每行</td>
<td>无</td>
</tr>
<tr>
<td>弹窗</td>
<td>保存</td>
<td>Toast <code>✅ 定时任务已保存</code></td>
<td>校验通过</td>
<td>无</td>
</tr>
</tbody>
</table>
<h3 id="194">19.4 表单字段</h3>
<table>
<thead>
<tr>
<th>字段</th>
<th>类型</th>
<th>必填</th>
<th>默认</th>
<th>选项/说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>任务名称</td>
<td>input</td>
<td>是</td>
<td>—</td>
<td>如 <code>每日竞品数据采集</code></td>
</tr>
<tr>
<td>关联 Skill</td>
<td>select</td>
<td>是</td>
<td>—</td>
<td>竞品数据采集 / 小红书笔记发布 / 数据清洗脚本 / 抖音视频上传 / Facebook广告投放</td>
</tr>
<tr>
<td>关联产品</td>
<td>select</td>
<td>是</td>
<td>—</td>
<td>PROD001 / PROD002 / PROD003 / 全部产品</td>
</tr>
<tr>
<td>Cron 表达式</td>
<td>input</td>
<td>是</td>
<td><code>0 8 * * *</code></td>
<td>—</td>
</tr>
<tr>
<td>帮助文本</td>
<td>动态文本</td>
<td>—</td>
<td>实时解析</td>
<td>下述对照表</td>
</tr>
<tr>
<td>执行参数(JSON)</td>
<td>textarea(3 行)</td>
<td>否</td>
<td>示例 JSON</td>
<td>必须为合法 JSON</td>
</tr>
<tr>
<td>失败重试</td>
<td>select</td>
<td>否</td>
<td>—</td>
<td>重试 3 次 / 重试 1 次 / 不重试</td>
</tr>
<tr>
<td>超时(秒)</td>
<td>number</td>
<td>否</td>
<td>120</td>
<td>—</td>
</tr>
<tr>
<td>状态</td>
<td>select</td>
<td>否</td>
<td>启用</td>
<td>启用 / 暂停</td>
</tr>
</tbody>
</table>
<p><strong>Cron 解析对照</strong>:
- <code>0 8 * * *</code> → <code>📅 每天 08:00 执行</code>
- <code>0 */2 * * *</code> → <code>📅 每 2 小时执行</code>
- <code>0 9 * * 1</code> → <code>📅 每周一 09:00 执行</code>
- <code>0 0 1 * *</code> → <code>📅 每月 1 号 00:00 执行</code>
- <code>30 10 * * *</code> → <code>📅 每天 10:30 执行</code>
- <code>0 18 * * 5</code> → <code>📅 每周五 18:00 执行</code>
- <code>0 */4 * * *</code> → <code>📅 每 4 小时执行</code>
- 其他 → <code>📅 自定义表达式: {输入值}</code></p>
<h3 id="195">19.5 执行记录弹窗</h3>
<p>表格:执行时间(YYYY-MM-DD HH:MM:SS)/ 状态(成功/失败 标签)/ 耗时(s)/ 结果文本</p>
<h3 id="196">19.6 交互规则</h3>
<ul>
<li>Cron 表达式输入实时解析 → <code>parseCron(value)</code> 更新帮助文本</li>
<li>开关 toggle:启用 → <code>tg tg-ok</code> <code>运行中</code>;暂停 → <code>tg tg-w</code> <code>已暂停</code>;同步更新 <code>data-st</code></li>
<li><code>initTimelines()</code> 为每行生成 7 个圆点(近 7 日执行成功/失败)</li>
</ul>
<h3 id="197">19.7 提示反馈</h3>
<ul>
<li><code>✅ 定时任务已保存</code> / <code>▶️ 手动触发成功</code> / <code>✅ 已删除</code> / <code>✅ 已启用</code> / <code>⏸️ 已暂停</code></li>
</ul>
<hr />
<h1 id="_4">六、待完善 / 开发注意事项</h1>
<table>
<thead>
<tr>
<th>项</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>数据权限隔离</td>
<td>后端需严格按 RB-07/RB-12 做 Skill 权限并集 + 产品范围交集校验,前端仅展示性过滤</td>
</tr>
<tr>
<td>密码与密钥加密</td>
<td>平台账号密码、API Key、谷歌 2FA 密钥需服务端加密存储(AES),仅返回掩码</td>
</tr>
<tr>
<td>删除前置校验</td>
<td>用户/Skill/平台/产品/模板/菜单删除前都需检查引用关系,前端原型已提示</td>
</tr>
<tr>
<td>导入文件格式</td>
<td>产品批量导入需约定 CSV/Excel 模板字段与校验规则</td>
</tr>
<tr>
<td>日志规模</td>
<td>操作日志、Skill 调用日志量级大,需分库或冷热分层存储</td>
</tr>
<tr>
<td>权限按钮码</td>
<td><code>button_code</code> 需跟前端按钮统一字典,前后端共享枚举</td>
</tr>
<tr>
<td>执行器选择</td>
<td>RB-13 执行器类型互斥,后端需校验保存时 <code>executor_type</code> 只能设置一份配置</td>
</tr>
<tr>
<td>时区</td>
<td>Cron 执行、日志时间建议统一使用服务器本地时区 + UTC 存储,前端按当前用户时区展示</td>
</tr>
<tr>
<td>二次确认统一</td>
<td>所有删除/取消类操作都需弹窗确认(本原型已遵循)</td>
</tr>
<tr>
<td>响应式支持</td>
<td>登录页已做移动端隐藏左栏,其他后台页默认 PC 端 1280+,移动端不在当前版本范围</td>
</tr>
</tbody>
</table>
<hr />
<p><strong>文档结束。</strong> 本 PRD 覆盖 19 个原型页面、按钮级操作细节、字段清单与业务规则,可直接用于开发排期、测试用例编写与原型评审。</p>
</main>
</div>
<button class="back-top" id="backTop" title="回到顶部">↑</button>
<script>
// Back to top
const bt=document.getElementById('backTop');
window.addEventListener('scroll',()=>{
if(window.scrollY>400)bt.classList.add('show');else bt.classList.remove('show');
});
bt.addEventListener('click',()=>window.scrollTo({top:0,behavior:'smooth'}));
// TOC active highlight on scroll
const links=document.querySelectorAll('.toc a');
const headings=[...document.querySelectorAll('.content h2, .content h3')];
function onScroll(){
const y=window.scrollY+120;
let current=headings[0];
for(const h of headings){if(h.offsetTop<=y)current=h;else break;}
if(!current)return;
links.forEach(a=>{
a.classList.toggle('active',a.getAttribute('href')==='#'+current.id);
});
}
window.addEventListener('scroll',onScroll);onScroll();
</script>
</body>
</html>