Files
Fulfilled-Knowledge/wishfulfilled-wiki/05_需求文档/20260528_USER_ERP_0-1需求重构_可点击参考原型_v1.html
2026-05-29 14:33:56 +08:00

1569 lines
116 KiB
HTML
Raw 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" />
<title>USER ERP 0-1需求重构 · 可点击参考原型 v1</title>
<style>
:root {
--bg: #f5f7fb;
--panel: #ffffff;
--panel-2: #f8fafc;
--text: #142033;
--muted: #66758a;
--line: #dfe5ee;
--line-strong: #cbd5e1;
--blue: #2563eb;
--blue-soft: #e8f0ff;
--green: #15803d;
--green-soft: #e8f7ee;
--amber: #b45309;
--amber-soft: #fff4df;
--red: #b91c1c;
--red-soft: #fdecec;
--purple: #6d28d9;
--purple-soft: #f2ecff;
--nav: #111827;
--nav-soft: #1f2937;
--radius: 8px;
--shadow: 0 16px 36px rgba(15, 23, 42, 0.10);
}
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
background: var(--bg);
color: var(--text);
font-family: "Microsoft YaHei", "Segoe UI", Arial, sans-serif;
letter-spacing: 0;
}
button, input, select { font: inherit; }
button { cursor: pointer; }
.app {
min-height: 100vh;
display: grid;
grid-template-columns: 330px minmax(0, 1fr);
}
.sidebar {
height: 100vh;
position: sticky;
top: 0;
display: grid;
grid-template-columns: 92px 238px;
border-right: 1px solid var(--line);
background: var(--panel);
z-index: 10;
}
.rail {
background: var(--nav);
color: #e5edf7;
display: grid;
grid-template-rows: auto minmax(0, 1fr) auto;
gap: 12px;
padding: 16px 12px;
min-height: 0;
}
.brand {
display: grid;
gap: 4px;
justify-items: center;
padding-bottom: 14px;
border-bottom: 1px solid rgba(255,255,255,.12);
text-align: center;
}
.brand strong { font-size: 14px; color: #fff; }
.brand span { color: #aebbc9; font-size: 12px; }
.rail-nav {
display: grid;
gap: 8px;
align-content: start;
overflow: auto;
min-height: 0;
}
.rail-btn {
min-height: 66px;
border: 0;
border-radius: var(--radius);
background: transparent;
color: #dbe7f5;
display: grid;
justify-items: center;
align-content: center;
gap: 5px;
padding: 8px 4px;
position: relative;
}
.rail-btn:hover, .rail-btn.active { background: var(--nav-soft); color: #fff; }
.rail-btn.active::before {
content: "";
position: absolute;
left: -12px;
top: 12px;
bottom: 12px;
width: 4px;
background: var(--blue);
border-radius: 999px;
}
.rail-icon {
width: 28px;
height: 28px;
border: 1px solid rgba(255,255,255,.25);
border-radius: 7px;
display: grid;
place-items: center;
font-size: 12px;
font-weight: 800;
}
.rail-label { font-size: 12px; line-height: 1.2; text-align: center; }
.rail-foot {
border: 1px solid rgba(255,255,255,.14);
border-radius: var(--radius);
padding: 10px 6px;
display: grid;
gap: 4px;
text-align: center;
color: #cbd5e1;
font-size: 12px;
}
.panel-nav {
display: grid;
grid-template-rows: auto minmax(0, 1fr) auto;
min-height: 0;
padding: 18px 14px;
gap: 14px;
}
.module-head {
padding-bottom: 14px;
border-bottom: 1px solid var(--line);
display: grid;
gap: 4px;
}
.eyebrow {
margin: 0;
color: var(--muted);
font-size: 12px;
font-weight: 700;
}
.module-head h1 {
margin: 0;
font-size: 22px;
line-height: 1.2;
}
.module-head span { color: var(--muted); font-size: 12px; line-height: 1.5; }
.page-nav {
overflow: auto;
min-height: 0;
display: grid;
gap: 7px;
align-content: start;
}
.page-btn, .todo-btn {
border: 1px solid transparent;
background: transparent;
color: var(--text);
border-radius: var(--radius);
min-height: 42px;
padding: 9px 10px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
text-align: left;
}
.page-btn:hover, .todo-btn:hover, .page-btn.active {
background: var(--blue-soft);
border-color: #bcd0ff;
color: #123f9f;
}
.page-btn small {
color: var(--muted);
font-size: 11px;
flex: none;
}
.quick {
border: 1px solid var(--line);
border-radius: var(--radius);
padding: 12px;
background: var(--panel-2);
display: grid;
gap: 8px;
}
.quick-head {
display: flex;
justify-content: space-between;
align-items: center;
color: var(--muted);
font-size: 12px;
font-weight: 700;
}
.main {
min-width: 0;
display: grid;
grid-template-rows: auto minmax(0, 1fr);
}
.topbar {
min-height: 76px;
position: sticky;
top: 0;
z-index: 8;
background: rgba(245, 247, 251, 0.92);
backdrop-filter: blur(12px);
border-bottom: 1px solid var(--line);
padding: 14px 24px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
}
.top-title { display: grid; gap: 4px; }
.top-title strong { font-size: 18px; }
.top-title span { color: var(--muted); font-size: 12px; }
.top-actions {
display: flex;
align-items: center;
justify-content: flex-end;
flex-wrap: wrap;
gap: 8px;
}
.search {
height: 38px;
width: 260px;
display: flex;
align-items: center;
gap: 8px;
border: 1px solid var(--line);
border-radius: var(--radius);
padding: 0 10px;
background: #fff;
color: var(--muted);
font-size: 12px;
}
.search input {
border: 0;
outline: none;
width: 100%;
min-width: 0;
color: var(--text);
background: transparent;
font-size: 13px;
}
select, input[type="date"] {
height: 38px;
border: 1px solid var(--line);
border-radius: var(--radius);
background: #fff;
color: var(--text);
padding: 0 10px;
font-size: 13px;
}
.period {
height: 38px;
border: 1px solid var(--line);
border-radius: var(--radius);
background: #fff;
display: flex;
overflow: hidden;
}
.period button {
border: 0;
background: transparent;
padding: 0 12px;
color: var(--muted);
}
.period button.active { background: var(--blue); color: #fff; }
.content {
padding: 24px;
min-width: 0;
}
.page-head {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 16px;
align-items: start;
margin-bottom: 18px;
}
.page-title {
margin: 0;
font-size: 26px;
line-height: 1.2;
}
.page-desc {
margin: 8px 0 0;
max-width: 900px;
color: var(--muted);
line-height: 1.7;
font-size: 14px;
}
.head-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.grid {
display: grid;
gap: 14px;
}
.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.panel {
background: var(--panel);
border: 1px solid var(--line);
border-radius: var(--radius);
box-shadow: 0 8px 20px rgba(15,23,42,.04);
min-width: 0;
}
.panel-head {
min-height: 58px;
border-bottom: 1px solid var(--line);
padding: 14px 16px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.panel-head h2 {
margin: 0;
font-size: 16px;
line-height: 1.3;
}
.panel-head p, .panel-note {
margin: 4px 0 0;
color: var(--muted);
font-size: 12px;
line-height: 1.5;
}
.panel-body { padding: 16px; }
.metric {
padding: 16px;
display: grid;
gap: 8px;
min-height: 116px;
}
.metric span { color: var(--muted); font-size: 12px; }
.metric strong { font-size: 28px; line-height: 1; }
.metric p { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.5; }
.pill, .stage {
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 3px 8px;
border-radius: 999px;
font-size: 12px;
font-weight: 700;
white-space: nowrap;
}
.pill.blue, .stage.v1 { color: #1d4ed8; background: var(--blue-soft); }
.pill.green { color: var(--green); background: var(--green-soft); }
.pill.amber, .stage.reserve { color: var(--amber); background: var(--amber-soft); }
.pill.red { color: var(--red); background: var(--red-soft); }
.pill.purple, .stage.v2 { color: var(--purple); background: var(--purple-soft); }
.pill.gray { color: var(--muted); background: #eef2f7; }
.list {
display: grid;
gap: 10px;
margin: 0;
padding: 0;
list-style: none;
}
.list li, .task-row, .issue-row {
border: 1px solid var(--line);
border-radius: var(--radius);
background: #fff;
padding: 11px 12px;
display: grid;
gap: 5px;
min-width: 0;
}
.task-row {
grid-template-columns: minmax(0, 1fr) auto;
align-items: center;
}
.task-row strong, .issue-row strong { font-size: 14px; }
.task-row span, .issue-row span, .list li span { color: var(--muted); font-size: 12px; line-height: 1.55; }
.flow {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.flow-step {
border: 1px solid var(--line);
background: #fff;
border-radius: var(--radius);
min-height: 38px;
padding: 8px 10px;
display: flex;
align-items: center;
gap: 8px;
color: var(--text);
font-size: 13px;
}
.flow-step::after {
content: "";
width: 18px;
height: 1px;
background: var(--line-strong);
display: inline-block;
}
.flow-step:last-child::after { display: none; }
.btn {
min-height: 36px;
border: 1px solid var(--line-strong);
border-radius: var(--radius);
background: #fff;
color: var(--text);
padding: 0 12px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
font-size: 13px;
font-weight: 700;
text-decoration: none;
}
.btn:hover { border-color: #9db7ec; color: #1d4ed8; background: #f8fbff; }
.btn.primary { border-color: var(--blue); background: var(--blue); color: #fff; }
.btn.danger { border-color: #f0b3b3; color: var(--red); background: var(--red-soft); }
.btn.ghost { border-color: transparent; background: transparent; color: var(--muted); }
.btn.small { min-height: 30px; padding: 0 9px; font-size: 12px; }
table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
th, td {
padding: 11px 10px;
border-bottom: 1px solid var(--line);
vertical-align: top;
text-align: left;
}
th {
color: var(--muted);
font-size: 12px;
font-weight: 800;
background: #f8fafc;
}
td.actions-cell {
min-width: 150px;
display: flex;
gap: 7px;
flex-wrap: wrap;
}
.table-wrap { overflow: auto; }
.role-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 10px;
}
.role-card {
border: 1px solid var(--line);
border-radius: var(--radius);
background: #fff;
padding: 12px;
display: grid;
gap: 8px;
min-height: 128px;
}
.role-card.active {
border-color: #94b5ff;
box-shadow: inset 0 0 0 1px #94b5ff;
background: #fbfdff;
}
.role-card strong { font-size: 14px; }
.role-card span { color: var(--muted); font-size: 12px; line-height: 1.55; }
.source-bar {
border: 1px solid #bfd2ff;
background: #f4f8ff;
color: #21406d;
border-radius: var(--radius);
padding: 10px 12px;
display: flex;
gap: 8px;
align-items: center;
flex-wrap: wrap;
font-size: 12px;
line-height: 1.5;
}
.drawer-mask, .modal-mask {
position: fixed;
inset: 0;
background: rgba(15,23,42,.32);
z-index: 30;
display: none;
}
.drawer-mask.open, .modal-mask.open { display: block; }
.drawer {
position: fixed;
top: 0;
right: 0;
width: min(640px, 100vw);
height: 100vh;
background: #fff;
z-index: 31;
transform: translateX(100%);
transition: transform .18s ease;
display: grid;
grid-template-rows: auto minmax(0, 1fr) auto;
border-left: 1px solid var(--line);
}
.drawer.open { transform: translateX(0); }
.drawer-head, .drawer-foot {
padding: 16px;
border-bottom: 1px solid var(--line);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.drawer-foot { border-top: 1px solid var(--line); border-bottom: 0; justify-content: flex-end; }
.drawer-body { padding: 16px; overflow: auto; display: grid; gap: 12px; }
.drawer h2 { margin: 0; font-size: 18px; }
.toast {
position: fixed;
left: 50%;
bottom: 24px;
transform: translateX(-50%) translateY(18px);
background: #111827;
color: #fff;
border-radius: var(--radius);
padding: 10px 14px;
font-size: 13px;
opacity: 0;
pointer-events: none;
transition: .18s ease;
z-index: 50;
}
.toast.open { opacity: 1; transform: translateX(-50%) translateY(0); }
.spacer { height: 14px; }
@media (max-width: 1120px) {
.app { grid-template-columns: 1fr; }
.sidebar { position: static; height: auto; grid-template-columns: 1fr; }
.rail { grid-template-rows: auto auto auto; }
.rail-nav { grid-auto-flow: column; grid-auto-columns: 86px; overflow-x: auto; }
.panel-nav { display: block; }
.page-nav { grid-template-columns: repeat(2, minmax(0,1fr)); margin-top: 12px; max-height: 280px; }
.quick { display: none; }
.topbar { position: static; align-items: flex-start; flex-direction: column; }
.top-actions { justify-content: flex-start; }
.search { width: min(100%, 420px); }
.cols-4, .cols-3, .cols-2, .role-grid { grid-template-columns: 1fr; }
.page-head { grid-template-columns: 1fr; }
.head-actions { justify-content: flex-start; }
}
</style>
</head>
<body>
<div class="app">
<aside class="sidebar">
<section class="rail" aria-label="一级模块导航">
<div class="brand">
<strong>USER ERP</strong>
<span>Stage 1 Prototype</span>
</div>
<nav class="rail-nav" id="moduleRail"></nav>
<div class="rail-foot">
<strong>模拟数据</strong>
<span>仅用于流程验证</span>
</div>
</section>
<section class="panel-nav">
<div class="module-head">
<p class="eyebrow">当前模块</p>
<h1 id="moduleTitle">今日作战</h1>
<span id="moduleNote">从异常、资源和今日动作进入业务闭环。</span>
</div>
<nav class="page-nav" id="pageNav"></nav>
<section class="quick">
<div class="quick-head"><span>高频跳转</span><strong>6</strong></div>
<button class="todo-btn" data-route="exceptions"><span>P0/P1异常</span><strong>37</strong></button>
<button class="todo-btn" data-route="demand"><span>需求待评估</span><strong>12</strong></button>
<button class="todo-btn" data-route="branch-cs"><span>客服超时</span><strong>9</strong></button>
<button class="todo-btn" data-route="branch-free"><span>免评缺口</span><strong>4</strong></button>
<button class="todo-btn" data-route="people"><span>额度预警</span><strong>18</strong></button>
<button class="todo-btn" data-route="retro"><span>复盘待写</span><strong>7</strong></button>
</section>
</section>
</aside>
<main class="main">
<header class="topbar">
<div class="top-title">
<strong id="topPageTitle">今日作战台</strong>
<span id="topPageSubtitle">高级主管 / USER运营 / 客服 / 渠道 / KOC-KOL / 财务 / 风险</span>
</div>
<div class="top-actions">
<label class="search">
<span>搜索</span>
<input id="globalSearch" placeholder="需求 / ASIN / 真实人 / 工单 / 风险" />
</label>
<div class="period" id="period">
<button class="active" data-period="day"></button>
<button data-period="week"></button>
<button data-period="month"></button>
</div>
<input type="date" value="2026-05-28" />
<select id="roleSelect">
<option value="owner">高级主管</option>
<option value="ops">USER运营</option>
<option value="channel">渠道运营</option>
<option value="csLead">客服主管</option>
<option value="cs">一线客服</option>
<option value="koc">KOC/KOL运营</option>
<option value="finance">财务/返款</option>
<option value="risk">风险/审核</option>
</select>
<button class="btn" data-action="drawer" data-kind="source">来源 7</button>
</div>
</header>
<section class="content" id="content"></section>
</main>
</div>
<div class="drawer-mask" id="drawerMask"></div>
<aside class="drawer" id="drawer">
<div class="drawer-head">
<div>
<h2 id="drawerTitle">详情</h2>
<p class="panel-note" id="drawerNote">模拟数据,敏感字段默认脱敏。</p>
</div>
<button class="btn" data-action="closeDrawer">关闭</button>
</div>
<div class="drawer-body" id="drawerBody"></div>
<div class="drawer-foot" id="drawerFoot"></div>
</aside>
<div class="toast" id="toast"></div>
<script>
const sourceDocs = [
"00_项目入口分级",
"01_主流程说明",
"02_日常操作页面结构",
"03_功能页面按钮盘点表",
"04_分支流程_完整需求域",
"05_异常流程_完整需求域",
"06_VibeCoding页面验证记录",
"参考20260528_USER_ERP_完整参考原型_v1.html"
];
const modules = [
{ id: "overview", label: "作战", icon: "DB", title: "今日作战", note: "异常、目标、资源和复盘入口。", pages: ["dashboard", "role-workflow"] },
{ id: "dispatch", label: "调度", icon: "PL", title: "需求调度", note: "需求进入、计划生成、资源匹配。", pages: ["demand", "action-matrix"] },
{ id: "branches", label: "分支", icon: "WF", title: "分支流程", note: "IM、EDM、Phone、客服、订单、免评、财务、KOC/KOL、风险。", pages: ["branch-im", "branch-edm", "branch-phone", "branch-cs", "branch-order", "branch-free", "branch-finance", "branch-koc", "branch-risk"] },
{ id: "ops", label: "运营", icon: "OP", title: "运营中心", note: "客服、渠道、真实人、KOC/KOL和风险日常页面。", pages: ["orders", "cs-exec", "cs-mgmt", "channel", "people", "koc-center", "risk-center"] },
{ id: "data", label: "复盘", icon: "BI", title: "复盘验证", note: "异常总表、数据复盘、Vibe Coding验证。", pages: ["exceptions", "retro", "validation"] }
];
const pages = {
"dashboard": { module: "overview", title: "今日作战台", short: "作战台", subtitle: "所有角色每天打开后的第一屏:先看异常、目标缺口、资源压力和今日必须推进的动作。", owner: "高级主管 / USER运营负责人", source: "00/01/02" },
"role-workflow": { module: "overview", title: "角色每日工作流", short: "角色工作流", subtitle: "明确每个岗位每天该看什么、不该先看什么、必须判断什么、复盘什么。", owner: "各岗位负责人", source: "00/02/04" },
"demand": { module: "dispatch", title: "需求与计划调度中心", short: "需求调度", subtitle: "把OA、销售、运营、ASIN异常、客服反馈、KOC/KOL合作请求转成可执行计划。", owner: "USER运营", source: "01/02/03/04", kind: "workflow" },
"action-matrix": { module: "dispatch", title: "按钮行为矩阵", short: "按钮矩阵", subtitle: "覆盖03按钮盘点表中的全部核心按钮。每个按钮均可执行演示或跳转到对应页面。", owner: "产品 / 前端观察员", source: "03" },
"branch-im": { module: "branches", title: "分支二IM推送看板", short: "IM推送", subtitle: "按真实人累计提交评价、额度、风险、未完成单和卡片有效性决定推送策略。", owner: "渠道运营", source: "04/05", kind: "workflow" },
"branch-edm": { module: "branches", title: "分支三EDM每日运营", short: "EDM", subtitle: "先看域名、邮箱、IP信誉、UID/KV人群、H5、AB Test与转化异常。", owner: "EDM运营", source: "04/05", kind: "workflow" },
"branch-phone": { module: "branches", title: "分支四Phone工作流", short: "Phone", subtitle: "处理未接、待回拨、国家/时段/语言匹配和客服承接容量。", owner: "Phone / 客服主管", source: "04/05", kind: "workflow" },
"branch-cs": { module: "branches", title: "分支五:客服承接", short: "客服承接", subtitle: "用户回复、信息缺失、订单登记、催评、售后、投诉和风险升级的执行闭环。", owner: "客服主管", source: "02/04/05", kind: "workflow" },
"branch-order": { module: "branches", title: "分支六A评价型订单", short: "评价订单", subtitle: "测评/回评从订单核验、评价提交、展示确认到返款提交即计12展示才计完成。", owner: "USER运营 / 客服", source: "01/04/05", kind: "workflow" },
"branch-free": { module: "branches", title: "分支六B免评执行", short: "免评执行", subtitle: "KOC/KOL为主IM/EDM/APP协同终点是内容、Code、点击、订单和权重结果。", owner: "KOC/KOL运营 / 渠道运营", source: "04", kind: "workflow" },
"branch-finance": { module: "branches", title: "分支七:财务返款与佣金", short: "返款佣金", subtitle: "用户返款V1必做KOC/KOL佣金V1预留/V2实现双重退款必须进风险。", owner: "财务 / 风险", source: "03/04/05", kind: "workflow" },
"branch-koc": { module: "branches", title: "分支八KOC/KOL协作", short: "KOC/KOL", subtitle: "线索、分层、任务、内容、带货、佣金、风险完整进入需求域。", owner: "KOC/KOL运营", source: "00/01/04/06", kind: "workflow" },
"branch-risk": { module: "branches", title: "分支九:风险与黑名单", short: "风险分支", subtitle: "每次有效互动都复检身份、额度、风险、订单和未关闭承诺。", owner: "风险/审核", source: "01/04/05", kind: "workflow" },
"orders": { module: "ops", title: "评价计划与订单中心", short: "计划订单", subtitle: "测评、回评、免评计划和订单履约的综合页面。", owner: "USER运营", source: "02/03", kind: "workflow" },
"cs-exec": { module: "ops", title: "客服执行中心", short: "客服执行", subtitle: "工单池、聊天、答应配合、催评、订单登记和售后详情。", owner: "一线客服 / 客服主管", source: "02/03/04", kind: "workflow" },
"cs-mgmt": { module: "ops", title: "客服管理中心", short: "客服管理", subtitle: "在线、排班、出勤、目标、绩效、服务质量和工单分配管理。", owner: "客服主管", source: "02/03/04", kind: "workflow" },
"channel": { module: "ops", title: "渠道运营中心", short: "渠道中心", subtitle: "IM、EDM、Phone、APP/H5/卡片、推送配置和渠道漏斗。", owner: "渠道负责人", source: "02/03/04", kind: "workflow" },
"people": { module: "ops", title: "测评人/真实人中心", short: "真实人", subtitle: "自动归并真实人、额度台账、4/4/12、风险历史和人工合并/拆分入口。", owner: "USER运营 / 风险", source: "02/03", kind: "workflow" },
"koc-center": { module: "ops", title: "KOC/KOL协作中心", short: "KOC中心", subtitle: "线索池、达人档案、合作任务、内容记录、带货归因、佣金结算和风险。", owner: "KOC/KOL运营", source: "02/03/04/06", kind: "workflow" },
"risk-center": { module: "ops", title: "风险与黑名单中心", short: "风险中心", subtitle: "风险事件、黑名单、退款比对、关联风险、内容/佣金风险。", owner: "风险/审核", source: "02/03/05", kind: "workflow" },
"exceptions": { module: "data", title: "异常流程总表", short: "异常总表", subtitle: "覆盖需求计划、评价订单、客服、渠道、KOC/KOL、返款、风险异常。", owner: "风险 / 测试", source: "05" },
"retro": { module: "data", title: "数据复盘看板", short: "复盘看板", subtitle: "计划、ASIN、渠道、客服、测评人、KOC/KOL、财务复盘指标。", owner: "业务负责人", source: "01/02/06", kind: "workflow" },
"validation": { module: "data", title: "Vibe Coding页面验证记录", short: "验证记录", subtitle: "现有原型只作为需求验证材料,不作为正式开发底座。", owner: "产品 / 前端观察员", source: "06" }
};
const referencePages = [
{ id: "ref-demand-pool", short: "需求池", title: "需求池 · 完整参考细化", owner: "USER运营", ref: "完整参考原型demand-pool", intent: "承接 OA、销售、运营、ASIN异常、客服反馈和KOC/KOL合作请求统一进入需求评估。", metrics: [["待评估", "12", "含测评/回评/免评/客服"], ["可转计划", "8", "信息已补齐"], ["被退回", "3", "缺ASIN或素材"], ["P0需求", "2", "当天处理"]], steps: ["新增/导入需求", "补齐ASIN/站点/目标", "设置优先级", "进入需求评估", "转计划或退回"], buttons: ["新增需求", "导入OA需求", "评估", "转计划", "补充信息"], retro: ["需求来源转化率", "退回原因", "需求评估耗时", "P0处理时效"] },
{ id: "ref-demand-review", short: "需求评估", title: "需求评估 · ASIN与资源校验", owner: "USER运营", ref: "完整参考原型demand-review", intent: "在生成计划前校验产品状态、库存、评分、近7天掉评、H5/卡片、资源和客服容量。", metrics: [["库存紧张", "1", "需限制节奏"], ["H5缺失", "2", "不可直接推送"], ["掉评触发", "2", "可转回评"], ["资源不足", "5", "需补量"]], steps: ["读取需求", "校验产品/ASIN", "预估人群/客服/渠道", "评估通过或退回", "生成执行计划"], buttons: ["评估通过", "退回补充", "暂缓", "驳回", "生成计划"], retro: ["评估通过率", "产品阻断项", "资源缺口", "退回次数"] },
{ id: "ref-plan-builder", short: "计划生成", title: "从需求生成计划", owner: "USER运营", ref: "完整参考原型plan-builder", intent: "把需求转成测评、回评、免评或客服跟进计划,并设置周期、每日节奏、渠道策略和目标人群。", metrics: [["今日新计划", "9", "含免评2个"], ["待生成", "8", "已评估"], ["冲突计划", "2", "同ASIN/同人群"], ["客服跟进", "4", "独立计划"]], steps: ["选择关联需求", "选择计划类型", "设置目标与周期", "设置渠道策略", "设置真实人额度规则", "生成计划"], buttons: ["生成计划", "进入执行匹配", "保存草稿", "查看现有计划"], retro: ["计划生成耗时", "计划类型占比", "计划取消原因", "目标调整次数"], note: "目标人群必须按真实人判断:同一真实人累计提交评价 < 12 才可进入普通测评/回评;累计提交评价 >= 12 应进入免评或KOC/KOL路径。" },
{ id: "ref-exec-match", short: "执行匹配", title: "执行匹配 · 人群/额度/客服", owner: "USER运营", ref: "完整参考原型exec-match", intent: "生成 audience_snapshot预占 quota_reservations并按容量、语言和工单量分配客服。", metrics: [["候选人群", "1,280", "已排除风险23人"], ["预占额度", "30", "7天有效"], ["可用客服", "5", "按班次分配"], ["KOC入口", "1", "免评补单"]], steps: ["匹配人群", "复检真实人额度", "预占额度", "分配客服", "生成IM/EDM/Phone任务", "记录匹配日志"], buttons: ["匹配人群", "预占额度", "释放预占", "分配客服", "匹配KOC/KOL"], retro: ["预占释放率", "匹配失败原因", "客服容量缺口", "候选人排除原因"] },
{ id: "ref-plan-adjust", short: "计划调整", title: "计划调整 · 补量/暂停/转免评", owner: "USER运营主管", ref: "完整参考原型plan-adjust", intent: "处理完成率不足、库存紧张、产品禁用、渠道失败等计划级异常。", metrics: [["缺口计划", "5", "需补量"], ["暂停计划", "2", "产品/风险"], ["转免评", "1", "测评不可继续"], ["待关闭", "3", "完成或失败"]], steps: ["发现执行偏差", "判断原因", "调整名额或补量", "暂停/恢复/转免评", "写回需求状态"], buttons: ["调整名额", "补量", "暂停", "恢复", "转免评", "关闭计划"], retro: ["补量成功率", "暂停原因", "转免评次数", "目标变更记录"] },
{ id: "ref-review-plan", short: "测评计划", title: "测评计划管理", owner: "USER运营", ref: "完整参考原型review-plan", intent: "查看测评计划目标、周期、完成进度、优先级、风险状态,并进入订单或推送。", metrics: [["进行中", "18", "测评/回评"], ["完成率低", "4", "低于50%"], ["风险计划", "3", "需审核"], ["待复盘", "7", "昨日关闭"]], steps: ["查看计划列表", "筛选站点/状态", "进入订单", "进入推送", "调整计划"], buttons: ["新建测评计划", "订单", "推送", "调整", "复盘"], retro: ["计划完成率", "评价展示率", "掉评率", "计划ROI"] },
{ id: "ref-review-order", short: "评价订单", title: "评价型订单 · 测评/回评", owner: "USER运营 / 客服", ref: "完整参考原型review-order", intent: "跟踪订单校验、评价提交、Amazon展示确认和返款请款不把提交等同于展示完成。", metrics: [["待登记", "31", "客服/用户提交"], ["待展示确认", "22", "未计完成"], ["掉评/差评", "9", "触发回评"], ["待请款", "48", "需财务审核"]], steps: ["订单登记", "订单校验", "提交评价", "计入真实人累计12", "展示确认", "请款返款", "完成或异常关闭"], buttons: ["登记订单", "校验订单", "上传评价", "确认展示", "发起请款", "异常关闭"], retro: ["提交到展示耗时", "展示失败原因", "返款耗时", "评价质量"] },
{ id: "ref-free-review", short: "免评计划", title: "免评执行 · KOC/KOL与站外流量", owner: "KOC/KOL运营", ref: "完整参考原型free-review", intent: "免评不以用户提交评价为终点而以内容发布、Code/点击/订单和权重结果为终点。", metrics: [["免评计划", "6", "进行中"], ["KOC任务", "15", "内容交付"], ["Code订单", "56", "模拟"], ["权重结果", "70%", "目标进度"]], steps: ["创建免评计划", "匹配KOC/KOL或渠道", "发布内容/投放Code", "跟踪点击和订单", "回收权重结果", "复盘"], buttons: ["关联KOC任务", "管理KOC任务", "记录Code", "查看订单", "关闭计划"], retro: ["内容发布率", "Code使用率", "点击转化", "权重变化"] },
{ id: "ref-reply-plan", short: "回评计划", title: "回评计划 · 掉评/差评补救", owner: "USER运营 / 客服", ref: "完整参考原型reply-plan", intent: "针对掉评、差评、未展示或客服反馈触发回评计划,独立跟踪补救口径。", metrics: [["待回评", "22", "掉评/差评"], ["已触达", "15", "IM/客服"], ["待展示", "7", "Amazon确认"], ["关闭异常", "3", "不可继续"]], steps: ["识别掉评/差评", "生成回评计划", "匹配人群", "触达/客服跟进", "展示确认", "关闭"], buttons: ["生成回评", "催评", "转人工", "确认展示", "关闭异常"], retro: ["回评成功率", "掉评补回率", "差评处理耗时", "客服介入效果"] },
{ id: "ref-ticket-pool", short: "工单池", title: "客服执行中心 · 工单池", owner: "客服主管", ref: "完整参考原型ticket-pool", intent: "主管每天优先看未分配、超时、投诉和可转化工单,按班次和能力分配。", metrics: [["待处理", "89", "今日"], ["超时未分配", "3", "P1"], ["在线客服", "12", "可承接"], ["首次回复", "4.2min", "平均"]], steps: ["工单进入", "识别优先级", "自动/手动分配", "转移或升级", "跟踪关闭"], buttons: ["自动分配", "手动分配", "转移", "升级", "关闭"], retro: ["首次回复", "分配耗时", "工单解决率", "投诉率"] },
{ id: "ref-my-tickets", short: "我的工单", title: "一线客服 · 我的工单", owner: "一线客服", ref: "完整参考原型my-tickets", intent: "客服每天只先看自己的待回复、待登记、待催评、待升级工单。", metrics: [["我的待回", "14", "含P1 2个"], ["待登记订单", "6", "RSO/RDO"], ["待催评", "9", "用户答应"], ["待升级", "2", "财务/风险"]], steps: ["打开我的工单", "查看用户上下文", "回复/补信息", "登记订单或催评", "升级/关闭"], buttons: ["回复用户", "登记订单", "催评", "升级", "标记解决"], retro: ["客服处理数", "RSO/RDO", "催评成功", "升级原因"] },
{ id: "ref-user-conversation", short: "用户会话", title: "用户会话与上下文卡", owner: "一线客服", ref: "完整参考原型user-conversation", intent: "在聊天前展示真实人额度、历史订单、风险和承诺,避免客服误导或重复触达。", metrics: [["真实人额度", "5/12", "累计提交评价"], ["月测评", "2/4", "可继续"], ["未关闭承诺", "1", "需跟进"], ["风险提示", "0", "当前正常"]], steps: ["打开会话", "读取上下文卡", "确认额度/风险", "回复用户", "登记结果"], buttons: ["回复", "补信息", "登记订单", "创建承诺", "升级"], retro: ["会话到订单转化", "补信息次数", "承诺完成率", "风险触发次数"] },
{ id: "ref-promise-track", short: "承诺跟踪", title: "用户答应配合跟踪", owner: "客服 / USER运营", ref: "完整参考原型promise-track", intent: "跟踪用户答应下单、答应评价、答应补截图等承诺,超过时限自动提醒。", metrics: [["未完成承诺", "26", "需催办"], ["今日到期", "9", "优先处理"], ["已过期", "4", "需升级"], ["完成率", "68%", "本周"]], steps: ["创建承诺", "设置截止时间", "自动提醒", "客服跟进", "完成/过期/升级"], buttons: ["确认答应", "催办", "标记完成", "标记过期", "升级"], retro: ["承诺完成率", "过期原因", "催办次数", "转化结果"] },
{ id: "ref-review-reminder", short: "催评", title: "待催评列表", owner: "一线客服", ref: "完整参考原型review-reminder", intent: "管理答应评价但未提交/未展示的用户,区分催评、转人工和关闭。", metrics: [["待催评", "33", "今日"], ["已催办", "12", "待反馈"], ["转人工", "5", "复杂问题"], ["关闭", "7", "不可继续"]], steps: ["筛选待催评", "确认订单和承诺", "发送提醒", "用户反馈", "提交/转人工/关闭"], buttons: ["催评", "转人工", "确认提交", "关闭", "查看订单"], retro: ["催评成功率", "催办次数", "转人工原因", "展示确认率"] },
{ id: "ref-cs-dashboard", short: "客服看板", title: "客服管理中心 · Dashboard", owner: "客服主管", ref: "完整参考原型cs-dashboard", intent: "主管实时查看在线、排班、工单趋势、服务质量和转化目标。", metrics: [["在线客服", "12", "当前"], ["今日工单", "89", "模拟"], ["待处理", "23", "需分配"], ["转化率", "67%", "今日"]], steps: ["查看在线状态", "查看趋势", "识别排班缺口", "调整工单分配", "查看绩效"], buttons: ["刷新状态", "调整分配", "查看排班", "查看绩效"], retro: ["客服目标完成", "首次回复", "解决率", "满意度"] },
{ id: "ref-attendance", short: "出勤", title: "客服出勤管理", owner: "客服主管", ref: "完整参考原型attendance", intent: "导入出勤数据,识别迟到、缺勤、早退与班次缺口。", metrics: [["应出勤", "14", "今日"], ["实际出勤", "12", "当前"], ["缺口", "2", "需补班"], ["异常", "3", "迟到/早退"]], steps: ["导入出勤", "匹配排班", "识别异常", "补班或调班", "沉淀绩效"], buttons: ["导入出勤", "标记异常", "补班", "导出"], retro: ["出勤率", "缺口影响", "工单积压", "绩效扣分"] },
{ id: "ref-schedule", short: "排班", title: "客服排班", owner: "客服主管", ref: "完整参考原型schedule", intent: "按国家、语言、时段和工单峰值安排班次与最大工单数。", metrics: [["本周班次", "42", "模拟"], ["晚班缺口", "2", "Phone/客服"], ["峰值时段", "16-20", "需覆盖"], ["最大工单", "15/人", "建议"]], steps: ["查看峰值", "设置班次", "批量排班", "限制最大工单", "发布排班"], buttons: ["设置班次", "批量排班", "调整容量", "发布"], retro: ["班次覆盖率", "峰值积压", "超时回复", "人效"] },
{ id: "ref-cs-performance", short: "客服绩效", title: "客服绩效与月目标", owner: "客服主管", ref: "完整参考原型cs-performance", intent: "管理客服 RSO/RDO、处理工单、满意度、首次回复和月度目标。", metrics: [["RSO目标", "1,200", "月度"], ["RDO目标", "900", "月度"], ["满意度", "96%", "模拟"], ["首次回复", "4.2min", "平均"]], steps: ["设置月目标", "跟踪日完成", "识别低绩效", "复盘原因", "调整排班/训练"], buttons: ["设置月目标", "查看明细", "导出绩效", "复盘"], retro: ["目标达成", "RSO/RDO转化", "客服排名", "培训需求"] },
{ id: "ref-im-push", short: "IM推送", title: "IM推送任务", owner: "渠道运营", ref: "完整参考原型im-push", intent: "基于真实人去重、额度复检、卡片/H5有效性和渠道频控生成IM推送任务。", metrics: [["今日任务", "16", "IM"], ["可推人群", "18,420", "去重后"], ["回复率", "4.8%", "模拟"], ["频控命中", "37", "需排除"]], steps: ["选择计划", "选择 audience_snapshot", "选择卡片/H5", "额度/风险复检", "发送/暂停", "回流结果"], buttons: ["新增推送", "上架", "下架", "批量分配", "配置去重"], retro: ["发送", "点击", "回复", "订单", "退订投诉"] },
{ id: "ref-edm-check", short: "EDM检查", title: "EDM每日检查", owner: "EDM运营", ref: "完整参考原型edm-check", intent: "发信前先检查域名、邮箱、IP信誉、UID/KV人群、H5链接和退订投诉。", metrics: [["域名健康", "2/3", "1个预警"], ["UID人群", "9,880", "今日可发"], ["打开率", "19.4%", "模拟"], ["投诉率", "0.42%", "接近阈值"]], steps: ["基础设施检查", "同步OA计划", "检查UID/KV人群", "检查H5", "生成EDM任务", "AB Test"], buttons: ["检查基础设施", "创建AB Test", "生成任务", "暂停发送"], retro: ["送达", "打开", "点击", "退订", "投诉"] },
{ id: "ref-channel-funnel", short: "渠道漏斗", title: "渠道漏斗对比", owner: "渠道运营", ref: "完整参考原型channel-funnel", intent: "对比IM、EDM、Phone、APP/H5各渠道从触达到订单/评价的漏斗。", metrics: [["IM回复", "4.8%", "模拟"], ["EDM打开", "19.4%", "模拟"], ["Phone接通", "62%", "模拟"], ["APP点击", "8.1%", "模拟"]], steps: ["查看渠道漏斗", "识别低效环节", "调整人群/素材/频控", "复盘转化"], buttons: ["查看IM", "查看EDM", "查看Phone", "配置去重"], retro: ["渠道ROI", "跨渠道重复触达", "转化贡献", "投诉率"] },
{ id: "ref-koc-leads", short: "KOC线索", title: "KOC/KOL线索池", owner: "KOC/KOL运营", ref: "完整参考原型koc-leads", intent: "沉淀KOC/KOL线索来源、站点、垂类、标签、风险和合作状态。", metrics: [["新线索", "18", "本周"], ["待审核", "7", "需建档"], ["合作中", "12", "任务执行"], ["风险线索", "2", "需阻断"]], steps: ["导入/新增线索", "标签分层", "风险审核", "建档", "创建任务"], buttons: ["新增线索", "建档", "创建任务", "标记风险"], retro: ["线索转任务率", "达人质量", "风险命中", "垂类覆盖"] },
{ id: "ref-koc-profile", short: "达人档案", title: "KOC/KOL达人档案", owner: "KOC/KOL运营", ref: "完整参考原型koc-profile", intent: "记录达人平台、账号、垂类、合作历史、佣金规则,并识别是否与测评人身份重叠。", metrics: [["关联测评人", "1", "同一真实人"], ["历史任务", "8", "模拟"], ["内容合格", "92%", "模拟"], ["佣金争议", "1", "待处理"]], steps: ["查看达人档案", "核验平台账号", "识别身份重叠", "查看任务历史", "设置合作规则"], buttons: ["编辑档案", "关联真实人", "创建任务", "暂停合作"], retro: ["内容质量", "带货效果", "身份冲突", "佣金争议"] },
{ id: "ref-koc-task", short: "合作任务", title: "KOC/KOL合作任务", owner: "KOC/KOL运营", ref: "完整参考原型koc-task", intent: "跟踪任务创建、样品/Code、内容发布、链接回收、订单归因和佣金状态。", metrics: [["进行中", "15", "内容任务"], ["待发布", "6", "需催办"], ["待验收", "4", "内容链接"], ["佣金待算", "5", "订单归因"]], steps: ["创建任务", "分配达人", "发放Code/素材", "发布内容", "回收链接/订单", "验收结算"], buttons: ["创建任务", "催发布", "验收内容", "记录Code", "发起佣金"], retro: ["内容发布率", "订单归因", "佣金成本", "达人复用率"] },
{ id: "ref-reviewer-pool", short: "测评人池", title: "测评人/真实人池", owner: "USER运营 / 风险", ref: "完整参考原型reviewer-pool", intent: "查看JOYHUB账号、Amazon账号、Profile、站点、标签和风险状态但额度按真实人聚合。", metrics: [["真实人", "18,420", "模拟"], ["可参与", "12,880", "额度可用"], ["风险排除", "423", "黑名单/弱风险"], ["信息缺失", "306", "需补齐"]], steps: ["筛选测评人", "查看身份链路", "读取额度台账", "复检风险", "加入人群快照"], buttons: ["筛选", "加入快照", "查看额度", "标记风险"], retro: ["可用人群变化", "风险命中", "信息缺失", "转化率"] },
{ id: "ref-reviewer-quota", short: "额度台账", title: "测评人额度明细", owner: "USER运营 / 风险", ref: "完整参考原型reviewer-quota", intent: "按 person_quota_ledgers 查看月度测评≤4、免评≤4、累计提交评价≤12和预占记录。", metrics: [["接近4次", "37", "月测评"], ["累计>=12", "1,204", "转免评"], ["预占超时", "9", "需释放"], ["冲突", "3", "待审核"]], steps: ["读取真实人额度", "查看预占", "提交评价计入累计12", "展示确认计计划完成", "释放/调整"], buttons: ["查看明细", "手动释放预占", "锁定额度", "导出"], retro: ["额度利用率", "预占超时", "归并冲突", "超限拦截"] },
{ id: "ref-identity-merge", short: "真实人归并", title: "真实人归并", owner: "风险 / USER运营", ref: "完整参考原型identity-merge", intent: "V1必须自动归并真实人人工确认/拆分可预留否则4/4/12额度不可落地。", metrics: [["自动归并", "1,280", "今日"], ["高置信", "96%", "姓名/地址/设备"], ["冲突", "11", "需人工"], ["待拆分", "3", "预留"]], steps: ["收集身份线索", "标准化姓名/地址/设备", "自动归并", "写入identity_links", "更新额度台账"], buttons: ["查看归并", "人工确认", "手动合并", "手动拆分"], retro: ["归并准确率", "额度冲突", "人工处理量", "误合并率"] },
{ id: "ref-risk-event", short: "风险事件", title: "风险事件中心", owner: "风险/审核", ref: "完整参考原型risk-event", intent: "统一管理订单、用户、测评人、返款、KOC/KOL相关风险信号和案件。", metrics: [["P0", "6", "强阻断"], ["P1", "31", "当天处理"], ["待复核", "18", "人工"], ["已关闭", "42", "本周"]], steps: ["创建/接收风险信号", "分级", "阻断或提示", "人工审核", "关闭并记录"], buttons: ["创建风险事件", "标记P0", "转案件", "关闭"], retro: ["风险命中率", "误杀率", "处理时效", "关闭原因"] },
{ id: "ref-blacklist", short: "黑名单", title: "黑名单管理", owner: "风险/审核", ref: "完整参考原型blacklist", intent: "支持用户/测评人/KOC/KOL/设备/支付标识等强弱黑名单,并参与每次互动复检。", metrics: [["强风险", "84", "阻断"], ["弱风险", "212", "提示"], ["KOC风险", "7", "内容违规"], ["解除申请", "5", "待审"]], steps: ["新增黑名单", "选择对象类型", "设置强/弱风险", "写入原因", "参与复检"], buttons: ["新增黑名单", "解除", "升级强风险", "查看日志"], retro: ["黑名单命中", "解除率", "重复风险", "申诉结果"] },
{ id: "ref-refund-risk", short: "退款风险", title: "Amazon退款 vs OA返款比对", owner: "财务 / 风险", ref: "完整参考原型refund-risk", intent: "识别Amazon退款、OA返款、非APP用户邮件退款和卡密返款之间的双重退款风险。", metrics: [["双重风险", "9", "需阻断"], ["非APP邮件", "6", "缺设备维度"], ["待补凭证", "12", "财务"], ["已阻断", "4", "今日"]], steps: ["导入退款/返款记录", "按真实人/订单/邮箱匹配", "识别双重退款", "阻断请款", "风险关闭"], buttons: ["比对退款", "阻断返款", "补凭证", "关闭风险"], retro: ["双重退款拦截", "非APP盲区", "凭证缺失", "返款争议"] },
{ id: "ref-refund-audit", short: "返款审核", title: "返款审核", owner: "财务", ref: "完整参考原型refund-audit", intent: "审核用户返款请款、凭证、卡密、订单状态和风险信号。", metrics: [["待审核", "48", "今日"], ["缺凭证", "12", "需补"], ["风险阻断", "9", "退款比对"], ["已返款", "156,200", "月度"]], steps: ["接收请款", "核验订单/评价/展示", "风险比对", "审核通过或退回", "执行返款"], buttons: ["审核通过", "退回补充", "阻断", "执行返款"], retro: ["审核耗时", "返款成功率", "退回原因", "风险金额"] },
{ id: "ref-commission", short: "佣金", title: "KOC/KOL佣金", owner: "财务 / KOC运营", ref: "完整参考原型commission", intent: "V1可预留完整佣金结算入口免评补单相关的订单归因和佣金争议需记录。", metrics: [["待结算", "5", "任务"], ["归因争议", "1", "待审"], ["已结算", "23", "本月"], ["预留项", "V2", "完整实现"]], steps: ["读取KOC任务", "核验订单归因", "计算佣金", "审核争议", "结算"], buttons: ["计算佣金", "发起审核", "标记争议", "结算"], retro: ["佣金成本", "达人ROI", "争议率", "归因准确率"] },
{ id: "ref-report-plan", short: "计划复盘", title: "数据复盘 · 计划看板", owner: "业务负责人", ref: "完整参考原型report-plan", intent: "按计划查看目标、完成、缺口、暂停、转免评、异常和负责人。", metrics: [["计划完成", "83%", "月度"], ["缺口", "253", "目标数"], ["异常关闭", "7", "本周"], ["转免评", "3", "本月"]], steps: ["选择时间", "查看计划趋势", "下钻异常", "生成复盘动作"], buttons: ["筛选", "下钻", "导出", "创建复盘"], retro: ["完成率", "异常率", "资源缺口", "动作闭环"] },
{ id: "ref-report-asin", short: "ASIN复盘", title: "数据复盘 · ASIN看板", owner: "业务负责人", ref: "完整参考原型report-asin", intent: "按ASIN看评价、回评、免评、掉评、权重变化和渠道贡献。", metrics: [["ASIN数", "126", "本月"], ["掉评", "2.1%", "模拟"], ["权重提升", "70%", "免评"], ["库存阻断", "5", "影响计划"]], steps: ["选择ASIN", "查看评价/免评指标", "查看渠道贡献", "生成下一轮计划"], buttons: ["筛选ASIN", "查看趋势", "创建需求"], retro: ["评价质量", "掉评原因", "免评权重", "库存影响"] },
{ id: "ref-report-channel", short: "渠道复盘", title: "数据复盘 · 渠道看板", owner: "渠道负责人", ref: "完整参考原型report-channel", intent: "对比IM、EDM、Phone、APP/H5触达、点击、回复、订单、投诉和ROI。", metrics: [["IM订单", "386", "模拟"], ["EDM订单", "142", "模拟"], ["Phone意向", "86", "模拟"], ["投诉", "0.42%", "EDM"]], steps: ["选择渠道", "查看漏斗", "对比计划", "识别低效原因", "调整策略"], buttons: ["对比渠道", "查看人群", "配置去重", "导出"], retro: ["渠道ROI", "触达疲劳", "重复触达", "投诉退订"] },
{ id: "ref-report-cs", short: "客服复盘", title: "数据复盘 · 客服看板", owner: "客服主管", ref: "完整参考原型report-cs", intent: "复盘客服工单、解决率、满意度、RSO/RDO和目标完成。", metrics: [["工单解决率", "92%", "模拟"], ["满意度", "96%", "模拟"], ["RSO", "892", "月度"], ["RDO", "617", "月度"]], steps: ["查看客服表现", "识别目标缺口", "下钻工单类型", "调整排班和培训"], buttons: ["筛选客服", "查看明细", "设置目标", "导出"], retro: ["人效", "服务质量", "转化目标", "培训动作"] }
];
modules.push({
id: "reference",
label: "细化",
icon: "UX",
title: "完整参考原型细化页",
note: "参考 20260528_USER_ERP_完整参考原型_v1.html把操作台页面拆成可跳转的执行入口。",
pages: referencePages.map(p => p.id)
});
referencePages.forEach(item => {
pages[item.id] = {
module: "reference",
title: item.title,
short: item.short,
subtitle: item.intent,
owner: item.owner,
source: "参考原型/02/03/04/05",
kind: "reference"
};
});
const roles = {
owner: { name: "高级主管", see: "OKR、资源压力、P0异常、跨部门阻塞、计划缺口", avoid: "不先看单条聊天、单条订单字段和普通P3观察项", judge: "是否暂停计划、是否补资源、是否升级跨部门", review: "目标缺口、TOP/BOTTOM任务、异常原因沉淀" },
ops: { name: "USER运营", see: "需求池、计划生成、执行匹配、今日缺口、待补量", avoid: "不把V1边界当需求边界不只看订单页", judge: "需求是否可执行、资源是否匹配、是否转免评/客服/KOC", review: "计划完成、渠道表现、订单与评价口径" },
channel: { name: "渠道运营", see: "IM/EDM/Phone漏斗、人群、频控、卡片/H5、退订投诉", avoid: "不绕过真实人额度,不只按单渠道点击率决策", judge: "是否降频、换素材、换人群、暂停推送", review: "发送、点击、回复、订单、评价、投诉" },
csLead: { name: "客服主管", see: "在线、排班、待处理、首次回复、转化目标、投诉", avoid: "不先看已关闭低风险工单", judge: "是否自动分配、转移、调班、升级投诉", review: "RSO/RDO、首次回复、解决率、目标完成率" },
cs: { name: "一线客服", see: "我的工单、待回复、待催评、待登记订单、答应配合", avoid: "不看全局财务明细和他人敏感资料", judge: "回复、补信息、登记订单、催评、升级", review: "今日处理数、催评结果、用户承诺完成情况" },
koc: { name: "KOC/KOL运营", see: "新线索、标签、合作任务、内容/带货进度、身份冲突", avoid: "不把普通测评完成口径当内容任务完成口径", judge: "是否匹配达人、是否暂停合作、是否要求重提内容", review: "内容链接、Code、订单、佣金争议、风险" },
finance: { name: "财务/返款", see: "待请款、待审核、待返款、双重退款、凭证/卡密", avoid: "不看未到返款条件的普通工单", judge: "是否审核通过、是否阻断重复返款、是否补凭证", review: "返款成功率、异常返款、卡密缺失、争议" },
risk: { name: "风险/审核", see: "黑名单、强弱关联、退款取消、额度超限、敏感导出", avoid: "不只按账号判断不用Profile累计Review替代真实人", judge: "弱风险提示、强风险阻断、拉黑/解除", review: "风险案件、复检记录、归并冲突、异常关闭" }
};
const workflowData = {
demand: {
metrics: [["待评估需求", "12", "OA/销售/客服/KOC入口"], ["资源匹配不足", "5", "人群或客服容量缺口"], ["今日待转计划", "8", "测评/回评/免评/客服"], ["冲突计划", "2", "需主管合并或暂停"]],
do: ["先看P0/P1需求和截止时间", "校验ASIN、库存、评分、产品状态", "确认需求类型:测评/回评/免评/客服/KOC", "检查人群、额度、渠道、客服容量是否能支撑"],
dont: ["不直接从需求跳到推送", "不在未核验产品/库存时生成计划", "不把KOC/KOL合作请求当普通测评单处理"],
steps: ["需求进入", "需求评估", "产品/ASIN校验", "计划生成", "执行匹配", "渠道/客服/KOC任务", "结果回流"],
issues: ["目标高于可用人群/额度", "产品禁用但计划仍执行", "计划有名额但渠道无人群", "渠道有响应但客服容量不足", "完成数口径不一致"],
actions: ["新增需求", "导入OA需求", "需求评估", "生成计划", "匹配人群", "预占额度", "分配客服", "生成推送任务", "调整名额", "暂停计划", "恢复计划", "转免评", "关闭需求"],
review: ["需求转计划耗时", "计划完成率", "资源匹配缺口", "客服容量压力", "被驳回/需补充原因"]
},
"branch-im": {
metrics: [["可推人群", "18,420", "按真实人去重"], ["长期测评人", "1,204", "累计提交评价>=12"], ["回复率", "4.8%", "低于目标需换素材"], ["额度预警", "37", "接近4/4/12"]],
do: ["先按真实人读取person_quota_ledgers", "检查黑名单、退款取消、未完成单", "确认卡片/H5和产品状态有效", "查看今日频控和渠道去重"],
dont: ["不按Profile累计Review分层", "不对累计>=12的真实人推普通测评/回评", "不绕过客服容量继续放量"],
steps: ["人群生成", "额度/风险复检", "选择卡片/H5", "推送", "用户响应", "核验信息", "订单/返款/客服"],
issues: ["IM点击低", "IM回复低于3%", "退订或不感兴趣升高", "卡片产品禁用未同步", "H5链接失效"],
actions: ["新增推送", "上架/下架", "批量分配", "新增卡片", "下架卡片", "配置去重规则"],
review: ["发送", "曝光", "点击", "回复", "订单", "评价", "退订/投诉"]
},
"branch-edm": {
metrics: [["域名健康", "2/3", "1个预警"], ["UID人群", "9,880", "今日可发"], ["打开率", "19.4%", "模拟数据"], ["投诉率", "0.42%", "接近阈值"]],
do: ["先看域名、邮箱、IP信誉", "核对OA计划变化", "检查KV/UID人群数量", "确认H5与产品禁用联动", "回收打开/点击/回复/退订/投诉"],
dont: ["不在信誉异常时继续发送", "不把EDM点击当评价完成", "不忽略菲律宾/国家问题清单"],
steps: ["基础设施检查", "同步OA计划", "检查UID人群", "检查产品/H5", "生成EDM任务", "发送与AB Test", "转化到订单/客服/风险"],
issues: ["EDM域名/IP信誉异常", "KV/UID人群导出失败", "H5链接失效", "退订或不感兴趣升高"],
actions: ["检查基础设施", "创建AB Test", "生成推送任务", "配置去重规则"],
review: ["送达", "打开", "点击", "回复", "退订", "投诉", "订单转化"]
},
"branch-phone": {
metrics: [["待回拨", "86", "含未接"], ["未接率", "38%", "需调整时段"], ["可用客服", "7", "晚班缺1"], ["转KOC线索", "4", "今日新增"]],
do: ["先看未接和待回拨", "按国家/语言/时段匹配客服", "查看问题类型分布", "确认高峰时段客服是否不足"],
dont: ["不在客服容量不足时批量外呼", "不把Phone售后问题直接记为评价转化"],
steps: ["生成电话名单", "匹配国家/语言/时段/排班", "拨打/记录", "转客服/订单/售后/KOC线索", "复盘未接率"],
issues: ["Phone未接率过高", "排班不足", "客服转移失败", "等待用户超时"],
actions: ["创建回拨任务", "设置班次", "批量排班", "转移工单"],
review: ["拨打数", "接通数", "未接率", "订单意向", "KOC意向", "售后问题"]
},
"branch-cs": {
metrics: [["待分配工单", "19", "含P1 6个"], ["首次回复超时", "7", "需主管处理"], ["今日登记订单", "43", "RSO/RDO"], ["答应配合待完成", "26", "需催评"]],
do: ["先看未分配和超时工单", "客服查看上下文卡后再回复", "缺订单/截图/返款信息时创建待补标签", "投诉、诈骗、退款异常立即升级"],
dont: ["不把客服降级成聊天窗口", "不绕过订单核验直接请款", "不查看无关敏感字段"],
steps: ["消息进入", "生成工单", "分配客服", "查看上下文卡", "回复/补信息", "登记订单/催评/上传结果", "关闭或升级"],
issues: ["无客服在线", "工单未分配", "首次回复超时", "客服误登记订单", "用户投诉客服"],
actions: ["自动分配", "手动分配", "转移工单", "回复用户", "登记订单", "催评", "标记解决", "关闭工单", "重开工单", "确认答应", "拒绝", "标记过期"],
review: ["处理工单", "首次回复", "解决率", "RSO/RDO转化", "投诉", "客服目标完成率"]
},
"branch-order": {
metrics: [["待登记订单", "31", "客服/用户提交"], ["待确认评价", "22", "展示未确认"], ["掉评/差评", "9", "触发回评"], ["待请款", "48", "需财务审核"]],
do: ["先核验订单号、店铺、ASIN、订单状态", "用户提交评价立即计入真实人累计12", "Amazon展示确认才计计划完成", "更换/更改/撤销必须留日志"],
dont: ["不把用户提交等同于展示完成", "不对已退款/已取消订单继续返款", "不把免评结果混进评价型完成数"],
steps: ["计划分配人群", "生成/提交订单", "核验订单号", "绑定ASIN/店铺/站点", "上传评价", "展示核验", "返款/请款", "完成/异常关闭"],
issues: ["订单号格式错误", "非公司产品", "店铺下错", "订单已取消/退款", "评论重复绑定", "评论未展示", "掉评/差评"],
actions: ["新建测评计划", "编辑计划", "查看关联订单", "新增订单", "上传订单", "上传回评", "提交排队", "请款", "更换订单", "更改订单", "撤销", "批量导出", "回评确认"],
review: ["订单完成", "评价提交", "展示确认", "返款成功", "掉评率", "异常关闭原因"]
},
"branch-free": {
metrics: [["免评计划", "6", "今日执行"], ["KOC内容待提交", "14", "含超时3"], ["Code订单", "126", "模拟归因"], ["权重结果", "3 ASIN", "待复盘"]],
do: ["先看免评计划目标和协同资源", "拆解KOC/KOL任务、Code、内容协同", "回收点击、Code使用、订单和权重结果", "免评结果单独形成快照"],
dont: ["不以用户提交评价为终点", "不以Amazon展示评价作为完成口径", "不混入测评/回评订单完成数"],
steps: ["免评计划批准", "拆解KOC/KOL/Code/内容任务", "匹配资源", "发布内容/分发Code", "同步IM/EDM/APP", "回收结果", "形成免评结果快照"],
issues: ["KOC/KOL与C类测评人身份重叠", "样品发出未产出内容", "内容链接无效", "带货订单归因失败", "佣金争议"],
actions: ["新建免评计划", "匹配KOC/KOL", "创建合作任务", "分配样品/免评名额", "上传内容链接", "审核内容", "同步订单"],
review: ["内容链接", "Code使用", "点击", "订单", "权重结果", "达人表现", "佣金争议"]
},
"branch-finance": {
metrics: [["待审核请款", "48", "含P0 3"], ["双重退款", "5", "需风险确认"], ["卡密缺失", "6", "V1预留"], ["佣金争议", "3", "V2实现"]],
do: ["先看待审核和P0资金风险", "比对Amazon退款和OA返款", "非APP邮件退款补齐识别线索", "返款成功后回写订单和工单"],
dont: ["不审核未满足条件的请款", "不跳过双重退款比对", "不暴露完整返款账号和卡密"],
steps: ["返款条件满足", "发起请款", "财务审核", "付款/礼品卡", "凭证/卡密通知", "状态回写", "风险复盘"],
issues: ["缺返款账号", "返款账号格式异常", "重复请款", "双重退款", "非APP用户邮件退款", "返款超额", "卡密/凭证缺失"],
actions: ["请款", "审核请款", "确认返款", "标记双重退款", "创建风险事件"],
review: ["待请款", "待审核", "返款成功", "异常返款", "双重退款", "凭证缺失"]
},
"branch-koc": {
metrics: [["新线索", "21", "今日新增"], ["合作任务", "38", "免评/内容/带货"], ["内容待审核", "12", "V2"], ["身份冲突", "4", "需复核"]],
do: ["先看新线索、任务超时、身份冲突", "区分KOC/KOL身份和普通测评人身份", "标签、带货、测评、免评不能混", "内容任务与订单任务分开完成口径"],
dont: ["不因为V1不做完整商家平台就删除KOC/KOL需求", "不把KOC内容任务混成普通测评订单"],
steps: ["新增线索", "身份/标签/风险检查", "自动打标与人工修正", "分层", "匹配任务", "接受/拒绝", "样品/内容/带货执行", "复盘"],
issues: ["KOC标签混乱", "达人重复触达", "内容不合规", "带货订单归因失败", "高风险KOC继续推送"],
actions: ["新增线索", "打标分层", "创建合作任务", "分配样品/免评名额", "上传内容链接", "审核内容", "同步订单", "计算佣金", "暂停合作"],
review: ["线索", "任务", "内容", "带货", "佣金", "风险", "合作等级"]
},
"branch-risk": {
metrics: [["风险事件", "37", "待处理"], ["强关联命中", "8", "阻断"], ["额度超限", "18", "真实人维度"], ["敏感导出", "2", "需审批"]],
do: ["先看P0资金/合规/账号安全", "每次有效互动复检身份、额度、风险", "强风险阻断,弱风险提示人工", "确认风险后同步黑名单"],
dont: ["不只按账号判断风险", "不让黑名单用户继续触达/返款/合作", "不导出未脱敏敏感字段"],
steps: ["风险信号产生", "判断弱/强风险", "弱风险提醒", "强风险阻断", "人工复核", "解除/确认", "黑名单同步/恢复执行"],
issues: ["黑名单命中", "强关联命中", "弱关联命中", "额度超限", "多账号归并冲突", "频控超限", "敏感字段导出风险"],
actions: ["创建风险事件", "复核通过", "排除风险", "新增黑名单", "标记双重退款", "查看审计记录", "手动合并", "手动拆分"],
review: ["风险案件", "黑名单", "退款比对", "额度超限", "强弱关联", "复检记录"]
},
"orders": null,
"cs-exec": null,
"cs-mgmt": null,
"channel": null,
"people": null,
"koc-center": null,
"risk-center": null,
"retro": null
};
workflowData.orders = workflowData["branch-order"];
workflowData["cs-exec"] = workflowData["branch-cs"];
workflowData["cs-mgmt"] = {
metrics: [["在线客服", "17", "晚班缺1"], ["今日工单", "163", "待处理19"], ["首次回复", "8.6分", "目标<10分"], ["目标完成", "76%", "本月"]],
do: ["先看在线、排班、待处理和超时", "检查RSO/RDO目标完成", "处理工单分配压力", "导出回复/转化/目标完成"],
dont: ["不先看已关闭低风险工单", "不调整未确认班次规则", "不忽略投诉工单"],
steps: ["看客服Dashboard", "检查出勤", "调整排班", "分配工单", "跟踪回复统计", "看转化绩效", "设置目标"],
issues: ["无客服在线", "排班不足", "目标异常", "用户投诉客服"],
actions: ["导入出勤", "调整出勤状态", "设置班次", "批量排班", "设置月目标", "导出绩效"],
review: ["出勤", "排班", "处理工单", "首次回复", "转化率", "目标完成率"]
};
workflowData.channel = workflowData["branch-im"];
workflowData.people = {
metrics: [["真实人档案", "42,180", "模拟聚合"], ["额度预警", "18", "接近12"], ["自动归并", "96.3%", "姓名+地址/设备"], ["人工复核", "11", "合并/拆分"]],
do: ["先看额度预警和归并冲突", "确认自动归并是否覆盖姓名+地址、设备、邮箱、电话、Profile、收款信息", "查看真实人下多账号额度一致性", "风险记录与黑名单联动"],
dont: ["不以单JOYHUB ID或Profile替代真实人", "不在归并冲突未解决时继续推普通测评"],
steps: ["识别身份线索", "自动归并真实人", "读取额度台账", "生成候选人群", "预占/释放额度", "互动复检", "人工合并/拆分"],
issues: ["多账号归并冲突", "额度超限", "强关联命中", "弱关联命中"],
actions: ["手动合并", "手动拆分", "查看额度明细", "查看审计记录", "手动释放预占"],
review: ["4/4/12", "预占", "释放", "提交计数", "风险历史", "归并准确率"]
};
workflowData["koc-center"] = workflowData["branch-koc"];
workflowData["risk-center"] = workflowData["branch-risk"];
workflowData.retro = {
metrics: [["计划完成率", "84%", "核心指标"], ["ASIN风险", "9", "低评分/掉评"], ["客服转化", "76%", "RSO/RDO"], ["KOC内容", "31", "已发布/待审"]],
do: ["先看昨日TOP/BOTTOM任务", "看异常原因是否有沉淀动作", "核对计划/订单/评价/免评不同完成口径", "输出本周资源缺口"],
dont: ["不把提交评价和展示确认混成一个指标", "不把免评结果混入评价型计划完成", "不展示未脱敏敏感字段"],
steps: ["结果回流", "指标聚合", "异常归因", "复盘记录", "沉淀动作", "下一轮计划调整"],
issues: ["完成数口径不一致", "渠道响应但客服容量不足", "内容/佣金风险", "双重退款"],
actions: ["创建复盘", "批量导出", "导出绩效", "查看关联推送", "查看关联订单"],
review: ["计划", "ASIN", "渠道", "客服", "测评人", "KOC/KOL", "财务"]
};
const exceptionGroups = [
["需求与执行计划不匹配", [["需求目标高于可用人群/额度", "提醒运营降低目标、拆分周期、转免评或补充渠道", "V1必做"], ["产品禁用但计划仍在执行", "自动暂停计划和下架H5/卡片", "V1必做"], ["库存不足但继续推测评/免评", "限制节奏或暂停", "V1必做"], ["ASIN/店铺/关键词变化未同步", "阻断新推送,生成维护任务", "V1必做"], ["计划有名额但渠道无可推人群", "补充人群、换渠道、延长周期", "V1必做"], ["渠道有响应但客服容量不足", "暂停或降频推送,调整排班", "V1必做"], ["完成数口径不一致", "进入口径复核", "V1必做"]]],
["评价/订单异常", [["订单号格式错误", "提示重填或转客服", "V1必做"], ["非公司产品", "阻断登记,转客服说明", "V1必做"], ["店铺下错", "人工处理,可转免评", "V1必做"], ["订单已取消/退款", "阻断回评和返款,进入风险", "V1必做"], ["评论重复绑定", "阻断或例外审核", "V1必做"], ["评论未展示", "计划不计完成", "V1必做"], ["掉评/差评", "触发回评/紧急催评/风险", "V1必做"]]],
["返款/佣金异常", [["缺返款账号", "客服跟进补齐", "V1必做"], ["重复请款", "阻断并提醒财务", "V1必做"], ["双重退款", "生成风险事件", "V1必做"], ["非APP用户邮件退款", "补充邮箱、订单、地址、收款信息等识别线索", "V1必做"], ["KOC/KOL佣金争议", "进入佣金复核", "V2实现"]]],
["客服异常", [["无客服在线", "提醒主管,暂停部分推送", "V1必做"], ["工单未分配", "自动分配或主管手动分配", "V1必做"], ["首次回复超时", "提醒客服/主管", "V1必做"], ["排班不足", "调整排班或降频推送", "V1必做"], ["客服误登记订单", "更改订单并留痕", "V1必做"]]],
["渠道异常", [["IM点击低", "换素材/卡片/人群", "V1必做"], ["IM回复低于3%", "更换图片/话术", "V1必做"], ["EDM域名/IP信誉异常", "暂停发送、切换账号", "V1必做"], ["KV/UID人群导出失败", "重跑导出", "V1必做"], ["Phone未接率过高", "调整时段/排班/回拨", "V1预留"]]],
["KOC/KOL异常", [["KOC标签混乱", "人工复核标签", "V1预留"], ["KOC/KOL与C类测评人身份重叠", "阻断重复触达,进入冲突复核", "V1必做"], ["达人重复触达", "合并或暂停任务", "V1预留"], ["内容不合规", "驳回、下架、降权", "V2实现"], ["带货订单归因失败", "进入人工归因", "V2实现"]]],
["风险异常", [["黑名单命中", "阻断触达/返款/合作", "V1必做"], ["强关联命中", "阻断并复核", "V1必做"], ["额度超限", "阻断普通测评,转免评池", "V1必做"], ["多账号归并冲突", "按person_quota_ledgers重新汇总", "V1必做"], ["敏感字段导出风险", "强制脱敏/审批", "V1必做"]]]
];
const actionRows = [
["今日作战台","查看异常","进入昨日/今日异常详情","alert、plan、channel_event、ticket、risk_event","-","-","主管、运营","否","V1必做","exceptions"],
["今日作战台","指派处理人","把异常转成可执行任务","alert、staff、shift","task、notification","异常:待处理 -> 已指派","主管、运营","是","V1必做","exceptions"],
["今日作战台","升级异常","P0/P1问题升级主管或跨部门","alert、risk_event、ticket","escalation、notification","异常:待处理 -> 已升级","主管、风险","是","V1必做","exceptions"],
["今日作战台","调整计划","从作战台直接进入计划调整","demand、plan、progress","plan_change_log","计划:进行中 -> 调整中/暂停/补量","主管、运营","是","V1必做","demand"],
["今日作战台","创建复盘","对异常或任务形成复盘记录","plan、channel_event、ticket、order","retrospective","异常:已处理 -> 待复盘","主管、运营","是","V1预留","retro"],
["需求池","新增需求","手动录入销售/运营/KOC-KOL需求","product、asin、staff","demand","需求:草稿","运营、主管","是","V1必做","demand"],
["需求池","导入OA需求","从OA或表格批量导入需求","import_file","demand、import_log","需求:待评估","运营、管理员","是","V1必做","demand"],
["需求池","需求评估","判断需求是否可执行","demand、product、asin、inventory、risk","demand_review","待评估 -> 已通过/需补充/驳回","运营、主管","是","V1必做","demand"],
["需求池","退回补充","信息不足时退回需求人","demand","demand、notification","待评估 -> 需补充","运营","是","V1必做","demand"],
["需求池","生成计划","将需求转成测评/回评/免评/KOC-KOL/客服计划","demand、product、audience、quota、risk","plan、plan_log","已通过 -> 已转计划","运营、主管","是","V1必做","demand"],
["计划编排","拆分计划","一个需求拆成多个站点/渠道/周期计划","demand、plan","plan、plan_relation","计划:草稿/进行中","运营、主管","是","V1预留","demand"],
["计划编排","合并计划","合并同产品/同周期/同目标计划","plan","plan_relation、plan_log","计划:合并/关闭旧计划","主管","是","V1预留","demand"],
["执行匹配","匹配人群","生成候选用户/测评人/KOC-KOL名单","person、reviewer、koc_kol、quota、risk","audience_snapshot、exclusion","匹配:待匹配 -> 完成/不足","运营","是","V1必做","demand"],
["执行匹配","预占额度","锁定测评/免评/Review额度","audience_snapshot、quota_ledger","quota_reservation","额度:可用 -> 预占","运营","是","V1必做","people"],
["执行匹配","手动释放预占","预占超时、计划取消或人群撤出后释放额度","quota_reservation、quota_ledger、plan","quota_reservation_log、quota_ledger","额度:已预占 -> 已释放","主管、管理员","是","V1必做","people"],
["执行匹配","分配客服","按容量、语言、工单量分配承接客服","plan、ticket、shift、agent_capacity","task、ticket_assignment","待分配 -> 已分配","主管、客服主管","是","V1必做","branch-cs"],
["执行匹配","生成推送任务","从计划生成人群和渠道任务","plan、audience、card、h5、channel_config","push_task、channel_event","待发送","渠道运营","是","V1必做","branch-im"],
["执行匹配","匹配KOC/KOL","将需求匹配给合适创作者","koc_kol_profile、task、risk","koc_kol_task","待分配 -> 待接受","KOC/KOL运营","是","V1预留","branch-koc"],
["计划调整","调整名额","增减计划数量","plan、progress、resource","plan_change_log","计划目标变化","运营、主管","是","V1必做","demand"],
["计划调整","暂停计划","禁止继续执行但保留历史","plan、risk、product","plan_log、notification","进行中 -> 暂停","主管","是","V1必做","demand"],
["计划调整","恢复计划","恢复已暂停计划","plan、product、risk","plan_log","暂停 -> 进行中","主管","是","V1必做","demand"],
["计划调整","转免评","普通测评/回评因店铺/订单/用户问题转免评","plan、order、reviewer","plan、order_log","测评/回评 -> 免评","运营、主管","是","V1必做","branch-free"],
["计划调整","关闭需求","需求完成或取消","demand、plan、progress","demand_close_log","需求:已关闭","主管","是","V1必做","demand"],
["测评计划","新建测评计划","从需求或人工创建计划","demand、product、asin","review_plan","草稿/未开始","运营","是","V1必做","orders"],
["测评计划","编辑计划","修改目标、渠道、周期、负责人","review_plan","plan_log","计划字段变化","运营、主管","是","V1必做","orders"],
["测评计划","复制关键词链接","运营执行用","review_plan","copy_event","-","运营","否","V1必做","orders"],
["测评计划","查看关联推送","查看计划下发的渠道任务","plan、push_task","-","-","运营、渠道","否","V1必做","branch-im"],
["测评计划","查看关联订单","查看计划履约订单","plan、order","-","-","运营","否","V1必做","branch-order"],
["回评计划","新建回评计划","因掉评/差评/维稳生成回评计划","asin、review_stats","reply_plan","待开始","运营","是","V1必做","orders"],
["回评计划","调整今日目标","根据评分/掉评变化调整当天目标","reply_plan、asin_stats","plan_log","今日目标变化","运营、主管","是","V1必做","orders"],
["免评计划","新建免评计划","给长期测评人/KOC-KOL/补单池创建免评计划","demand、reviewer、koc_kol","free_plan","待审批/进行中","运营","是","V1必做","branch-free"],
["测评订单","新增订单","记录测评执行单","plan、person、product","review_order","待上传回评/待登记","运营、客服","是","V1必做","branch-order"],
["测评订单","上传订单","绑定Amazon订单号","review_order、amazon_order","review_order、audit_log","订单:待登记 -> 已登记","运营、客服","是","V1必做","branch-order"],
["测评订单","上传回评","绑定评论ID/链接/截图","review_order、comment","review_submission","待回评 -> 待确认/已提交","运营、客服","是","V1必做","branch-order"],
["测评订单","提交排队","评论暂不能绑定,进入排队","review_order、comment_query","review_queue","待确认","运营、客服","是","V1必做","branch-order"],
["测评订单","请款","发起用户返款","review_order、refund_account","refund_request","待请款 -> 待审核","运营、客服","是","V1必做","branch-finance"],
["测评订单","更换订单","用新订单替代原订单","review_order、amazon_order","order_change_log","订单号变化","运营、主管","是","V1必做","branch-order"],
["测评订单","更改订单","修正订单字段","review_order","order_change_log","订单字段变化","运营、主管","是","V1必做","branch-order"],
["测评订单","撤销","撤销错误/风险订单","review_order、risk","order_log、quota_release","进行中 -> 撤销","风险、主管","是","V1必做","branch-order"],
["测评订单","批量导出","导出当前筛选结果","order、permission","export_task","-","有导出权限","是","V1必做","retro"],
["回评订单","回评确认","核验回评是否有效","review_submission、comment","review_display_check","待确认 -> 已回评/未通过","运营、审核","是","V1必做","branch-order"],
["工单池","自动分配","按在线、工单量、排班分配客服","ticket、agent、shift","ticket_assignment","待分配 -> 待处理","客服主管","是","V1必做","branch-cs"],
["工单池","手动分配","指定处理人","ticket、agent","ticket_assignment","待分配 -> 待处理","客服主管","是","V1必做","branch-cs"],
["工单池","转移工单","换客服处理","ticket、agent","ticket_transfer_log","处理人变化","客服、主管","是","V1必做","branch-cs"],
["我的工单","回复用户","处理用户消息","ticket、chat、context_snapshot","chat_message、ticket_log","待处理 -> 处理中/等待用户","客服","是","V1必做","branch-cs"],
["我的工单","登记订单","客服拿到订单号后登记","ticket、amazon_order、person","review_order、ticket_log","工单推进","客服","是","V1必做","branch-cs"],
["我的工单","催评","提醒用户提交评价","ticket、order、followup","reminder_event、followup","催评次数+1","客服、运营","是","V1必做","branch-cs"],
["我的工单","标记解决","用户问题解决","ticket","ticket_log","处理中 -> 已解决","客服","是","V1必做","branch-cs"],
["我的工单","关闭工单","完成或无需继续","ticket","ticket_log","已解决/等待用户 -> 已关闭","客服、主管","是","V1必做","branch-cs"],
["我的工单","重开工单","用户再次反馈","ticket","ticket_log","已关闭 -> 已重开/处理中","客服、主管","是","V1必做","branch-cs"],
["答应配合","确认答应","用户答应评价/反馈","ticket、person","support_followup","待确认 -> 已确认","客服","是","V1必做","branch-cs"],
["答应配合","拒绝","用户拒绝配合","ticket","support_followup","待确认 -> 已拒绝","客服","是","V1必做","branch-cs"],
["答应配合","标记过期","超时未提交","followup","support_followup","已确认 -> 已过期","客服、系统","是","V1必做","branch-cs"],
["出勤管理","导入出勤","导入当天/本月出勤","attendance_file","attendance_record","出勤记录更新","客服主管、人事","是","V1预留","cs-mgmt"],
["出勤管理","调整出勤状态","修正迟到/请假/缺勤","attendance_record","attendance_log","状态变化","客服主管","是","V1必做","cs-mgmt"],
["排班管理","设置班次","给客服设置早/午/晚班","agent、date","shift_schedule","排班变化","客服主管","是","V1必做","cs-mgmt"],
["排班管理","批量排班","一次生成多天排班","agent、date_range","shift_schedule","排班批量变化","客服主管","是","V1必做","cs-mgmt"],
["目标管理","设置月目标","设置RSO/RDO登记和上评目标","agent、period","support_target","目标变化","客服主管","是","V1必做","cs-mgmt"],
["绩效看板","导出绩效","导出回复/转化/目标完成","performance_snapshot","export_task","-","客服主管","是","V1必做","cs-mgmt"],
["IM推送","新增推送","创建IM触达任务","plan、audience、card","im_push_task","草稿/待发送","渠道运营","是","V1必做","branch-im"],
["IM推送","上架/下架","控制任务是否可执行","im_push_task","channel_log","已上架/已下架","渠道运营","是","V1必做","branch-im"],
["IM推送","批量分配","将任务分配到账号/渠道","push_task、im_account","assignment","待分配 -> 已分配","渠道运营","是","V1预留","branch-im"],
["IM卡片","新增卡片","创建卡片素材","product、h5","im_card","已上架/草稿","渠道运营","是","V1必做","branch-im"],
["IM卡片","下架卡片","产品禁用/素材失效时下架","im_card、product","card_log","已上架 -> 已下架","渠道运营","是","V1必做","branch-im"],
["EDM","检查基础设施","确认域名/邮箱/IP信誉","edm_config、deliverability","daily_check","健康/异常","EDM运营","否","V1必做","branch-edm"],
["EDM","创建AB Test","测试标题/素材/按钮","edm_campaign","ab_test","运行中","EDM运营","是","V1预留","branch-edm"],
["Phone","创建回拨任务","对未接/待跟进用户安排电话","tel_pool、agent_shift","tel_task","待拨打","Phone/客服","是","V1预留","branch-phone"],
["渠道配置","配置去重规则","定义跨IM/EDM/APP/Phone/KOC触达的去重、例外和频控条件","channel_config、person、risk、quota","channel_dedup_rule、channel_log","规则生效/停用","渠道主管、管理员","是","V1预留","channel"],
["线索池","新增线索","新增KOC/KOL候选人","source、contact","creator_profile","待审核","KOC/KOL运营","是","V1预留","branch-koc"],
["线索池","打标分层","区分新手KOC、稳定测评者、垂直专家、带货型KOL","creator_profile、metrics","creator_tag、tier_log","分层变化","KOC/KOL运营","是","V1预留","branch-koc"],
["任务管理","创建合作任务","样品、免评、内容、带货任务","demand、product、creator","creator_task","待接受","KOC/KOL运营","是","V1预留","branch-koc"],
["任务管理","分配样品/免评名额","执行合作资源分配","creator_task、inventory、quota","sample_order/free_order","待寄样/待执行","KOC/KOL运营","是","V1预留","branch-free"],
["内容记录","上传内容链接","记录发布内容","creator_task","content_record","待审核/已发布","KOC/KOL运营","是","V2实现","branch-free"],
["内容记录","审核内容","判断内容合规和是否可分发","content_record、content_policy","content_audit","通过/驳回","审核、运营","是","V2实现","branch-free"],
["带货归因","同步订单","记录Code/链接带来的订单","attribution、order","creator_order","待结算","KOC/KOL运营","是","V2实现","branch-free"],
["佣金结算","计算佣金","根据规则生成佣金","creator_order、commission_rule","commission_record","待审核","财务、运营","是","V2实现","branch-finance"],
["风险处理","暂停合作","风险/投诉/作弊时暂停","creator_profile、risk","creator_status_log","可合作 -> 暂停","风险、主管","是","V1预留","branch-koc"],
["真实人归并","手动合并","修正自动归并不足,把多个账号/身份线索合并到同一真实人","person、identity、quota_ledger、risk","person_identity_link、merge_log、quota_ledger","多个身份 -> 同一真实人","主管、风险、管理员","是","V1预留","people"],
["真实人归并","手动拆分","纠正误合并,拆开不同真实人","person、identity、quota_ledger、risk","person_identity_link、split_log、quota_ledger","同一真实人 -> 多个真实人","主管、风险、管理员","是","V1预留","people"],
["额度台账","查看额度明细","查看4/4/12额度、预占、释放、提交计数来源","person、quota_ledger、quota_reservation、review_submission","-","-","运营、客服主管、风险","否","V1必做","people"],
["互动复检","查看审计记录","追溯每次有效互动为什么继续、拦截或转人工","interaction_recheck、person、quota_ledger、risk","-","-","运营、风险、客服主管","否","V1必做","people"],
["风险事件","创建风险事件","人工或系统发现风险","person、order、refund、creator","risk_case","待复核","风险、系统","是","V1必做","risk-center"],
["风险事件","复核通过","确认风险","risk_case","risk_case、blacklist","复核中 -> 确认风险","风险","是","V1必做","risk-center"],
["风险事件","排除风险","解除误报","risk_case","risk_case","复核中 -> 排除","风险","是","V1必做","risk-center"],
["黑名单","新增黑名单","阻断后续触达/返款/合作","person、creator、identity","blacklist_item","生效中","风险","是","V1必做","risk-center"],
["退款比对","标记双重退款","Amazon退款+OA返款命中","refund_records","risk_signal","疑似/确认双重退款","风险、财务","是","V1必做","branch-finance"],
["返款","审核请款","付款前审核","refund_request、order、risk","refund_record","待审核 -> 待返款/失败","财务","是","V1必做","branch-finance"],
["返款","确认返款","完成付款/卡密发送","refund_record","refund_record、notification","待返款 -> 成功","财务","是","V1必做","branch-finance"]
].map((r, i) => ({ id: `ACT-${String(i + 1).padStart(3, "0")}`, page: r[0], name: r[1], meaning: r[2], read: r[3], write: r[4], change: r[5], role: r[6], audit: r[7], stage: r[8], route: r[9] }));
const sampleRows = [
{ id: "REQ-0528-001", type: "回评", asin: "B0USER001 / US", status: "待评估", owner: "USER运营A", risk: "P1", note: "评分低于4.5,客服容量不足" },
{ id: "PLAN-0528-006", type: "免评", asin: "B0USER019 / DE", status: "执行中", owner: "KOC运营B", risk: "P0", note: "长期测评人和KOC任务身份冲突" },
{ id: "CS-0528-033", type: "客服", asin: "B0USER011 / JP", status: "首次回复超时", owner: "客服主管", risk: "P1", note: "待转移工单,用户缺返款信息" },
{ id: "RISK-0528-009", type: "风险", asin: "真实人 P-8842", status: "强关联命中", owner: "风险审核", risk: "P0", note: "多账号归并后累计提交评价达到12" }
];
const state = { route: "dashboard", module: "overview", role: "owner", period: "day" };
const byId = id => document.getElementById(id);
const esc = value => String(value ?? "").replace(/[&<>"']/g, ch => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#039;" }[ch]));
const stageClass = stage => stage.includes("V2") ? "v2" : stage.includes("预留") ? "reserve" : "v1";
function init() {
renderShell();
const hashRoute = location.hash.replace("#", "");
setRoute(pages[hashRoute] ? hashRoute : "dashboard", false);
bindGlobalEvents();
}
function renderShell() {
byId("moduleRail").innerHTML = modules.map(m => `
<button class="rail-btn" data-module="${m.id}" title="${esc(m.title)}">
<span class="rail-icon">${esc(m.icon)}</span>
<span class="rail-label">${esc(m.label)}</span>
</button>
`).join("");
}
function renderPageNav(moduleId) {
const module = modules.find(m => m.id === moduleId);
byId("moduleTitle").textContent = module.title;
byId("moduleNote").textContent = module.note;
byId("pageNav").innerHTML = module.pages.map(id => {
const p = pages[id];
return `<button class="page-btn" data-route="${id}"><span>${esc(p.short)}</span><small>${esc(p.source)}</small></button>`;
}).join("");
document.querySelectorAll(".rail-btn").forEach(btn => btn.classList.toggle("active", btn.dataset.module === moduleId));
}
function setRoute(route, push = true) {
if (!pages[route]) route = "dashboard";
state.route = route;
state.module = pages[route].module;
renderPageNav(state.module);
renderContent();
document.querySelectorAll(".page-btn").forEach(btn => btn.classList.toggle("active", btn.dataset.route === route));
byId("topPageTitle").textContent = pages[route].title;
byId("topPageSubtitle").textContent = `${pages[route].owner} · 来源 ${pages[route].source} · ${state.period === "day" ? "日视图" : state.period === "week" ? "周视图" : "月视图"}`;
if (push) location.hash = route;
window.scrollTo({ top: 0, behavior: "smooth" });
}
function pageHeader(p, actions = "") {
return `
<div class="page-head">
<div>
<div class="source-bar"><strong>需求来源</strong>${sourceDocs.map(d => `<span class="pill gray">${esc(d)}</span>`).join("")}<span class="pill amber">页面数据均为模拟</span></div>
<div class="spacer"></div>
<h1 class="page-title">${esc(p.title)}</h1>
<p class="page-desc">${esc(p.subtitle)}</p>
</div>
<div class="head-actions">
${actions}
<button class="btn" data-action="drawer" data-kind="source">查看来源</button>
<button class="btn primary" data-route="action-matrix">按钮矩阵</button>
</div>
</div>
`;
}
function renderContent() {
const p = pages[state.route];
if (state.route === "dashboard") return renderDashboard();
if (state.route === "role-workflow") return renderRoleWorkflow();
if (state.route === "action-matrix") return renderActionMatrix();
if (state.route === "exceptions") return renderExceptions();
if (state.route === "validation") return renderValidation();
if (pages[state.route]?.kind === "reference") return renderReferencePage(state.route);
return renderWorkflowPage(state.route);
}
function renderDashboard() {
const role = roles[state.role];
const html = `
${pageHeader(pages.dashboard, `<button class="btn" data-route="ref-demand-pool">完整操作台细化</button><button class="btn primary" data-route="demand">进入需求调度</button>`)}
<section class="grid cols-4">
${metric("P0/P1异常", "37", "直接影响今日目标、资金、合规或账号安全")}
${metric("今日必跟进", "84", "需求、计划、催评、返款、内容审核")}
${metric("资源压力", "5类", "人群、额度、客服、KOC/KOL、返款队列")}
${metric("待复盘", "7", "昨日TOP/BOTTOM和异常原因")}
</section>
<div class="spacer"></div>
<section class="grid cols-2">
<article class="panel">
<div class="panel-head"><div><h2>当前角色:${esc(role.name)}</h2><p>切换右上角角色后,本卡片会更新每日工作重点。</p></div><span class="pill blue">角色视图</span></div>
<div class="panel-body grid cols-2">
${infoBox("每天先看", role.see, "green")}
${infoBox("今天不该先看", role.avoid, "amber")}
${infoBox("必须判断", role.judge, "blue")}
${infoBox("复盘数据", role.review, "purple")}
</div>
</article>
<article class="panel">
<div class="panel-head"><div><h2>主业务闭环</h2><p>需求不是从推送开始,必须从需求进入到复盘闭环。</p></div><button class="btn small" data-route="demand">去调度</button></div>
<div class="panel-body">${flow(["需求进入","需求评估","产品校验","计划生成","执行匹配","渠道/客服/KOC任务","用户/达人响应","履约","风险复检","结果回流","复盘"] )}</div>
</article>
</section>
<div class="spacer"></div>
<section class="grid cols-2">
<article class="panel">
<div class="panel-head"><div><h2>今日必须处理</h2><p>点击操作可打开详情或跳转对应页面。</p></div><span class="pill red">模拟</span></div>
<div class="panel-body grid">
${sampleRows.map(row => taskRow(row)).join("")}
</div>
</article>
<article class="panel">
<div class="panel-head"><div><h2>主看板确认项</h2><p>交付前用于确认页面是否照顾每日工作流。</p></div><span class="pill green">已覆盖</span></div>
<div class="panel-body">
<ul class="list">
<li><strong>主看板</strong><span>P0/P1异常、今日任务、目标进度、资源压力、复盘入口都在首屏。</span></li>
<li><strong>分支看板</strong><span>IM、EDM、Phone、客服、评价订单、免评、财务、KOC/KOL、风险均有独立页面。</span></li>
<li><strong>按钮跳转</strong><span>03按钮盘点表已进入按钮行为矩阵每个动作均可点击。</span></li>
<li><strong>口径提醒</strong><span>真实人、4/4/12、提交即计12、展示才计完成、免评独立结果口径均显式展示。</span></li>
<li><strong>模拟数据</strong><span>所有数据均标注为模拟,只用于本地点击和需求验证。</span></li>
</ul>
</div>
</article>
</section>
`;
byId("content").innerHTML = html;
}
function renderRoleWorkflow() {
byId("content").innerHTML = `
${pageHeader(pages["role-workflow"])}
<section class="role-grid">
${Object.entries(roles).map(([id, r]) => `
<button class="role-card ${state.role === id ? "active" : ""}" data-role-card="${id}">
<strong>${esc(r.name)}</strong>
<span>先看:${esc(r.see)}</span>
<span>不先看:${esc(r.avoid)}</span>
</button>
`).join("")}
</section>
<div class="spacer"></div>
<section class="panel">
<div class="panel-head"><div><h2>角色工作流要求</h2><p>用于确认工作人员每天进入系统时的优先级。</p></div><span class="pill blue">Stage 1</span></div>
<div class="panel-body table-wrap">
<table>
<thead><tr><th>角色</th><th>每天先看</th><th>今天不该先看</th><th>必须判断</th><th>复盘数据</th><th>入口</th></tr></thead>
<tbody>
${Object.entries(roles).map(([id, r]) => `<tr><td><strong>${esc(r.name)}</strong></td><td>${esc(r.see)}</td><td>${esc(r.avoid)}</td><td>${esc(r.judge)}</td><td>${esc(r.review)}</td><td><button class="btn small" data-route="${id === "cs" ? "branch-cs" : id === "koc" ? "branch-koc" : id === "finance" ? "branch-finance" : id === "risk" ? "branch-risk" : id === "channel" ? "branch-im" : "dashboard"}">进入</button></td></tr>`).join("")}
</tbody>
</table>
</div>
</section>
`;
}
function renderWorkflowPage(route) {
const p = pages[route];
const data = workflowData[route] || workflowData.demand;
byId("content").innerHTML = `
${pageHeader(p, `<button class="btn primary" data-route="exceptions">看异常</button>`)}
<section class="grid cols-4">${data.metrics.map(m => metric(m[0], m[1], m[2])).join("")}</section>
<div class="spacer"></div>
<section class="grid cols-2">
<article class="panel">
<div class="panel-head"><div><h2>工作人员每天该看什么</h2><p>先看会影响今日目标或阻断流程的项。</p></div><span class="pill green">先看</span></div>
<div class="panel-body"><ul class="list">${data.do.map(x => `<li><strong>${esc(x)}</strong><span>模拟检查项,可点击右侧动作继续。</span></li>`).join("")}</ul></div>
</article>
<article class="panel">
<div class="panel-head"><div><h2>今天不该先看什么</h2><p>避免低价值页面占用操作时间或制造错误口径。</p></div><span class="pill amber">不要先看</span></div>
<div class="panel-body"><ul class="list">${data.dont.map(x => `<li><strong>${esc(x)}</strong><span>必要时由异常、工单或复盘入口进入。</span></li>`).join("")}</ul></div>
</article>
</section>
<div class="spacer"></div>
<section class="panel">
<div class="panel-head"><div><h2>流程点击路径</h2><p>按业务顺序模拟从入口到关闭或复盘。</p></div><button class="btn small" data-action="drawer" data-kind="flow" data-route-key="${route}">查看写入对象</button></div>
<div class="panel-body">${flow(data.steps)}</div>
</section>
<div class="spacer"></div>
<section class="grid cols-2">
<article class="panel">
<div class="panel-head"><div><h2>流程问题点</h2><p>来自05异常流程点击处理会打开演示抽屉。</p></div><span class="pill red">异常</span></div>
<div class="panel-body grid">${data.issues.map((x, idx) => `<div class="issue-row"><strong>${esc(x)}</strong><span>处理状态:待处理 -> 处理中 -> 待复核 -> 已关闭</span><button class="btn small" data-action="drawer" data-kind="issue" data-title="${esc(x)}" data-route-target="exceptions">处理演示</button></div>`).join("")}</div>
</article>
<article class="panel">
<div class="panel-head"><div><h2>可执行按钮</h2><p>按钮来自03盘点表可跳转或执行演示。</p></div><span class="pill blue">${data.actions.length} 项</span></div>
<div class="panel-body" style="display:flex;flex-wrap:wrap;gap:8px">${data.actions.map(name => {
const action = actionRows.find(a => a.name === name);
return action ? `<button class="btn small" data-action-id="${action.id}">${esc(name)}</button>` : `<button class="btn small" data-action="drawer" data-kind="generic" data-title="${esc(name)}">${esc(name)}</button>`;
}).join("")}</div>
</article>
</section>
<div class="spacer"></div>
<section class="panel">
<div class="panel-head"><div><h2>将来复盘数据</h2><p>用于下一轮计划、资源、渠道和人员调度。</p></div><button class="btn small" data-route="retro">进入复盘</button></div>
<div class="panel-body">${data.review.map(x => `<span class="pill gray" style="margin:0 6px 8px 0">${esc(x)}</span>`).join("")}</div>
</section>
`;
}
function renderReferencePage(route) {
const item = referencePages.find(p => p.id === route) || referencePages[0];
const idx = referencePages.findIndex(p => p.id === item.id);
const next = referencePages[idx + 1]?.id || "dashboard";
const prev = referencePages[idx - 1]?.id || "dashboard";
byId("content").innerHTML = `
${pageHeader(pages[route], `<button class="btn" data-route="${prev}">上一页</button><button class="btn primary" data-route="${next}">下一操作页</button>`)}
<section class="grid cols-4">${item.metrics.map(m => metric(m[0], m[1], m[2])).join("")}</section>
<div class="spacer"></div>
<section class="grid cols-2">
<article class="panel">
<div class="panel-head"><div><h2>参考页面与业务定位</h2><p>来自完整参考原型的页面级操作细化保留0-1需求重构的角色、流程、异常和复盘口径。</p></div><span class="pill blue">${esc(item.ref)}</span></div>
<div class="panel-body">
${infoBox("页面目标", item.intent, "blue")}
${item.note ? infoBox("关键口径", item.note, "amber") : infoBox("适用边界", "本页数据均为模拟,主要用于需求验证、按钮盘点和后续开发拆分。", "amber")}
</div>
</article>
<article class="panel">
<div class="panel-head"><div><h2>工作人员每天该看什么</h2><p>该页作为具体操作台时,先看阻断当日执行的状态和任务。</p></div><span class="pill green">日常入口</span></div>
<div class="panel-body">
<ul class="list">
<li><strong>先看</strong><span>${esc(item.metrics.map(m => m[0]).join("、"))}</span></li>
<li><strong>不先看</strong><span>不先下钻低优先级历史明细,不绕过真实人额度、风险复检、客服容量和计划状态。</span></li>
<li><strong>必须判断</strong><span>是否继续执行、暂停、补量、转免评、升级客服/财务/风险或进入复盘。</span></li>
</ul>
</div>
</article>
</section>
<div class="spacer"></div>
<section class="panel">
<div class="panel-head"><div><h2>流程点击路径</h2><p>用于从完整参考原型的页面拆出可开发的点击路径。</p></div><button class="btn small" data-action="drawer" data-kind="flow" data-route-key="${route}">查看写入对象</button></div>
<div class="panel-body">${flow(item.steps)}</div>
</section>
<div class="spacer"></div>
<section class="grid cols-2">
<article class="panel">
<div class="panel-head"><div><h2>可执行按钮</h2><p>按钮先做点击演示,后续 Stage 2 再拆 API、权限和日志。</p></div><span class="pill blue">${item.buttons.length} 项</span></div>
<div class="panel-body" style="display:flex;flex-wrap:wrap;gap:8px">
${item.buttons.map(name => `<button class="btn small" data-action="drawer" data-kind="generic" data-title="${esc(name)}">${esc(name)}</button>`).join("")}
<button class="btn small" data-route="action-matrix">查看按钮矩阵</button>
</div>
</article>
<article class="panel">
<div class="panel-head"><div><h2>流程问题点</h2><p>本页要重点避免的执行偏差。</p></div><span class="pill red">异常入口</span></div>
<div class="panel-body">
<ul class="list">
<li><strong>口径错位</strong><span>测评/回评、免评、客服跟进、KOC任务不能混用完成口径。</span></li>
<li><strong>状态未闭环</strong><span>按钮写入后必须能回到计划、订单、风险或复盘对象。</span></li>
<li><strong>权限越界</strong><span>客服、财务、风险、KOC/KOL角色只能看到完成工作所需字段。</span></li>
<li><strong>模拟数据</strong><span>当前数值只用于验证页面结构,不能作为真实经营数据。</span></li>
</ul>
</div>
</article>
</section>
<div class="spacer"></div>
<section class="panel">
<div class="panel-head"><div><h2>将来复盘数据</h2><p>这些指标会进入计划、ASIN、渠道、客服、真实人、KOC/KOL和财务复盘。</p></div><button class="btn small" data-route="retro">进入复盘看板</button></div>
<div class="panel-body">${item.retro.map(x => `<span class="pill gray" style="margin:0 6px 8px 0">${esc(x)}</span>`).join("")}</div>
</section>
`;
}
function renderActionMatrix() {
byId("content").innerHTML = `
${pageHeader(pages["action-matrix"], `<button class="btn primary" data-route="dashboard">返回主看板</button>`)}
<section class="grid cols-4">
${metric("按钮动作", actionRows.length, "全部可点击")}
${metric("V1必做", actionRows.filter(a => a.stage.includes("V1必做")).length, "第一版关键动作")}
${metric("V1预留", actionRows.filter(a => a.stage.includes("预留")).length, "保留入口/字段/状态")}
${metric("V2实现", actionRows.filter(a => a.stage.includes("V2")).length, "后续完整能力")}
</section>
<div class="spacer"></div>
<section class="panel">
<div class="panel-head"><div><h2>03 功能页面按钮盘点表</h2><p>每行提供执行演示和页面跳转。点击后会打开抽屉或跳转,不存在死按钮。</p></div><span class="pill amber">模拟写入</span></div>
<div class="panel-body table-wrap">
<table>
<thead><tr><th>ID</th><th>页面</th><th>按钮/动作</th><th>业务含义</th><th>读/写对象</th><th>状态变化</th><th>权限</th><th>阶段</th><th>操作</th></tr></thead>
<tbody>
${actionRows.map(a => `
<tr>
<td>${a.id}</td>
<td>${esc(a.page)}</td>
<td><strong>${esc(a.name)}</strong></td>
<td>${esc(a.meaning)}</td>
<td><span class="pill gray">读</span> ${esc(a.read)}<br><span class="pill gray">写</span> ${esc(a.write)}</td>
<td>${esc(a.change)}</td>
<td>${esc(a.role)}<br>审计:${esc(a.audit)}</td>
<td><span class="stage ${stageClass(a.stage)}">${esc(a.stage)}</span></td>
<td class="actions-cell"><button class="btn small" data-action-id="${a.id}">执行演示</button><button class="btn small" data-route="${a.route}">跳转页面</button></td>
</tr>
`).join("")}
</tbody>
</table>
</div>
</section>
`;
}
function renderExceptions() {
byId("content").innerHTML = `
${pageHeader(pages.exceptions, `<button class="btn primary" data-route="dashboard">返回作战台</button>`)}
<section class="grid cols-4">
${metric("P0", "9", "当天处理,主管可见")}
${metric("P1", "18", "24小时内处理")}
${metric("P2", "31", "责任人跟进")}
${metric("P3", "12", "观察项")}
</section>
<div class="spacer"></div>
<section class="grid">
${exceptionGroups.map(group => `
<article class="panel">
<div class="panel-head"><div><h2>${esc(group[0])}</h2><p>发现方式、处理动作、关闭条件后续进入测试用例。</p></div><span class="pill red">${group[1].length}</span></div>
<div class="panel-body table-wrap">
<table>
<thead><tr><th>异常</th><th>处理</th><th>阶段</th><th>操作</th></tr></thead>
<tbody>${group[1].map(row => `<tr><td><strong>${esc(row[0])}</strong></td><td>${esc(row[1])}</td><td><span class="stage ${stageClass(row[2])}">${esc(row[2])}</span></td><td><button class="btn small" data-action="drawer" data-kind="issue" data-title="${esc(row[0])}" data-route-target="exceptions">处理演示</button></td></tr>`).join("")}</tbody>
</table>
</div>
</article>
`).join("")}
</section>
`;
}
function renderValidation() {
byId("content").innerHTML = `
${pageHeader(pages.validation)}
<section class="grid cols-2">
<article class="panel">
<div class="panel-head"><div><h2>已参考原型</h2><p>原型是需求验证材料,不是生产底座。</p></div><span class="pill blue">06</span></div>
<div class="panel-body">
<ul class="list">
<li><strong>C:\\XCODE\\USER\\input\\user-review-system</strong><span>React/Vite原型参考菜单、路由、订单、客服、渠道、风险页面。</span></li>
<li><strong>C:\\XCODE\\USER\\src\\user_erp_mvp_admin_prototype_v10.html</strong><span>参考左侧模块栏、顶部角色/周期、抽屉/弹窗后台布局。</span></li>
<li><strong>C:\\XCODE\\USER\\input\\客服执行.html</strong><span>参考客服执行、分配、排班、绩效、目标管理。</span></li>
<li><strong>C:\\XCODE\\USER\\input\\amazon_operator_test_entry.html</strong><span>参考提评入口、IM账号、推送策略。</span></li>
<li><strong>C:\\XCODE\\USER\\input\\IM 推送业务流.mm</strong><span>参考IM分层和流程已修正为真实人口径。</span></li>
</ul>
</div>
</article>
<article class="panel">
<div class="panel-head"><div><h2>本原型补强方向</h2><p>覆盖现有原型缺口。</p></div><span class="pill green">已补</span></div>
<div class="panel-body">
<ul class="list">
<li><strong>需求与计划调度</strong><span>从需求池到计划、资源、人群、客服、渠道、KOC/KOL任务。</span></li>
<li><strong>客服核心需求</strong><span>客服执行和客服管理均有页面、动作、异常与复盘指标。</span></li>
<li><strong>KOC/KOL完整需求域</strong><span>线索、分层、任务、内容、带货、佣金、风险均进入页面。</span></li>
<li><strong>免评独立闭环</strong><span>免评不再和评价提交混为同一终点。</span></li>
<li><strong>按钮矩阵</strong><span>03中动作全部以可点击入口呈现。</span></li>
</ul>
</div>
</article>
</section>
`;
}
function metric(label, value, note) {
return `<article class="panel metric"><span>${esc(label)}</span><strong>${esc(value)}</strong><p>${esc(note)}</p></article>`;
}
function infoBox(title, text, tone) {
return `<div class="issue-row"><span class="pill ${tone}">${esc(title)}</span><strong>${esc(text)}</strong></div>`;
}
function flow(items) {
return `<div class="flow">${items.map(x => `<span class="flow-step">${esc(x)}</span>`).join("")}</div>`;
}
function taskRow(row) {
const target = row.type === "客服" ? "branch-cs" : row.type === "风险" ? "branch-risk" : row.type === "免评" ? "branch-free" : "demand";
return `<div class="task-row"><div><strong>${esc(row.id)} · ${esc(row.type)} · ${esc(row.status)}</strong><span>${esc(row.asin)} · ${esc(row.owner)} · ${esc(row.note)}</span></div><div><span class="pill ${row.risk === "P0" ? "red" : "amber"}">${esc(row.risk)}</span> <button class="btn small" data-route="${target}">进入</button></div></div>`;
}
function openDrawer(kind, payload = {}) {
const drawer = byId("drawer");
const mask = byId("drawerMask");
const title = byId("drawerTitle");
const note = byId("drawerNote");
const body = byId("drawerBody");
const foot = byId("drawerFoot");
let route = payload.route || payload.routeTarget || state.route;
if (kind === "source") {
title.textContent = "来源与模拟说明";
note.textContent = "本HTML为本地点击参考原型所有业务数据均为模拟。";
body.innerHTML = `<ul class="list">${sourceDocs.map(d => `<li><strong>${esc(d)}</strong><span>已作为页面结构、按钮、分支、异常、复盘或验证依据。</span></li>`).join("")}</ul>`;
foot.innerHTML = `<button class="btn primary" data-route="validation">查看验证记录</button>`;
} else if (kind === "action") {
const a = actionRows.find(x => x.id === payload.id);
route = a.route;
title.textContent = `${a.id} · ${a.name}`;
note.textContent = `${a.page} · ${a.stage} · 审计:${a.audit}`;
body.innerHTML = `
${infoBox("业务含义", a.meaning, "blue")}
${infoBox("读取对象", a.read, "gray")}
${infoBox("写入对象", a.write, "gray")}
${infoBox("状态变化", a.change, "green")}
${infoBox("权限", a.role, "amber")}
<div class="source-bar"><strong>演示结果</strong><span>已模拟生成操作日志、通知、状态变化和复盘引用。</span><span class="pill amber">未写入真实系统</span></div>
`;
foot.innerHTML = `<button class="btn" data-route="action-matrix">返回矩阵</button><button class="btn primary" data-route="${a.route}">跳转到相关页面</button>`;
} else if (kind === "flow") {
const data = workflowData[payload.routeKey] || workflowData.demand;
title.textContent = "流程写入对象";
note.textContent = "模拟展示流程节点与后续Stage 2对象设计的关系。";
body.innerHTML = `${flow(data.steps)}<ul class="list">${data.steps.map((s, i) => `<li><strong>${esc(s)}</strong><span>模拟写入:状态日志、负责人、时间戳、复检结果、复盘引用 #${i + 1}</span></li>`).join("")}</ul>`;
foot.innerHTML = `<button class="btn primary" data-route="${payload.routeKey}">返回当前页</button>`;
} else {
title.textContent = payload.title || "处理演示";
note.textContent = "模拟从发现到关闭的异常状态流。";
body.innerHTML = `
${flow(["待发现","已发现","待处理","处理中","待复核","已关闭"])}
${infoBox("处理要求", "当天能影响目标、资金、合规或账号安全的异常按P0/P1进入主管视图。", "red")}
${infoBox("关闭条件", "必须有处理结论、责任人、操作日志、是否回流计划/客服/风险/复盘。", "green")}
`;
foot.innerHTML = `<button class="btn" data-route="exceptions">查看异常总表</button><button class="btn primary" data-route="${route}">跳转相关页面</button>`;
}
drawer.classList.add("open");
mask.classList.add("open");
}
function closeDrawer() {
byId("drawer").classList.remove("open");
byId("drawerMask").classList.remove("open");
}
function toast(text) {
const el = byId("toast");
el.textContent = text;
el.classList.add("open");
clearTimeout(window.__toastTimer);
window.__toastTimer = setTimeout(() => el.classList.remove("open"), 1800);
}
function bindGlobalEvents() {
document.body.addEventListener("click", event => {
const moduleBtn = event.target.closest("[data-module]");
if (moduleBtn) {
const mod = modules.find(m => m.id === moduleBtn.dataset.module);
if (mod) setRoute(mod.pages[0]);
return;
}
const routeBtn = event.target.closest("[data-route]");
if (routeBtn) {
closeDrawer();
setRoute(routeBtn.dataset.route);
return;
}
const actionBtn = event.target.closest("[data-action-id]");
if (actionBtn) {
openDrawer("action", { id: actionBtn.dataset.actionId });
return;
}
const action = event.target.closest("[data-action]");
if (action) {
if (action.dataset.action === "closeDrawer") closeDrawer();
if (action.dataset.action === "drawer") openDrawer(action.dataset.kind, action.dataset);
return;
}
const roleCard = event.target.closest("[data-role-card]");
if (roleCard) {
state.role = roleCard.dataset.roleCard;
byId("roleSelect").value = state.role;
renderContent();
toast(`已切换到:${roles[state.role].name}`);
}
});
byId("drawerMask").addEventListener("click", closeDrawer);
byId("roleSelect").addEventListener("change", event => {
state.role = event.target.value;
if (state.route === "dashboard" || state.route === "role-workflow") renderContent();
byId("topPageSubtitle").textContent = `${pages[state.route].owner} · 当前角色 ${roles[state.role].name}`;
toast(`角色视图:${roles[state.role].name}`);
});
byId("period").addEventListener("click", event => {
const btn = event.target.closest("button[data-period]");
if (!btn) return;
state.period = btn.dataset.period;
byId("period").querySelectorAll("button").forEach(b => b.classList.toggle("active", b === btn));
setRoute(state.route, false);
toast(`已切换为${btn.textContent}视图`);
});
byId("globalSearch").addEventListener("keydown", event => {
if (event.key !== "Enter") return;
openDrawer("generic", { title: `搜索:${event.target.value || "空关键词"}`, routeTarget: "demand" });
});
window.addEventListener("hashchange", () => {
const route = location.hash.replace("#", "");
if (route && route !== state.route && pages[route]) setRoute(route, false);
});
}
init();
</script>
</body>
</html>