docs: 同步交接摘要 / PRD / 原型,并记录品牌改名「深学在线」

- 交接摘要补 §一·三十五~§一·三十八:角色与授权、需求收敛(4 角色 / 10 菜单 / 取消二期)、
  PC 端重搭后的 UI 修复与卡片式基线、品牌改名与新标识
- PRD 与功能逻辑卷只改标题行与产品代号线;**文件名不动** —— verify-docs.py 按路径读,
  全库还有 20+ 处按文件名引用,改名会连带炸脚本
- 原型 index / admin-web / teacher-app / student-app 的品牌区改「深学在线」,
  admin-web 的 .mark(10 处)换成内嵌的新标 data URI,保持原型"单文件自包含"的约定
- 根 AGENTS.md 与 frontend-pc 的规范同步:接线检查补第 ⑨ 项(SVG 资产是不是合法 XML ——
  SVG 注释里出现连续两个减号就 not well-formed,图标裂开而控制台一句话都不报)、
  「最容易写错的约定」6 -> 7 条(新增品牌标)
- deploy/docker-compose.yml 只改头注释里的项目名(compose 的 name 与七牛对象前缀都没动)
This commit is contained in:
2026-10-10 16:49:04 +08:00
parent 1f3c485ceb
commit 7df078e0ea
22 changed files with 1158 additions and 1093 deletions
+127 -212
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>填报通 · 管理端(PC)交互原型</title>
<title>深学在线 · 管理端(PC)交互原型</title>
<style>
:root{
--ink:#1b2430; --ink2:#4a5768; --ink3:#8b95a3; --ink4:#b3b9c1;
@@ -76,8 +76,12 @@ figcaption .note{display:block;margin-top:8px;color:var(--ink3);font-size:12px}
}
.brand{padding:17px 17px 15px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:9px}
.brand .mark{
width:28px;height:28px;border-radius:7px;background:var(--ink);color:#fff;flex:none;
display:flex;align-items:center;justify-content:center;font-family:var(--font-display);font-size:15px;font-weight:600;
width:28px;height:28px;border-radius:7px;flex:none;
/* 深学在线 标识:方(卷宗)+ 环(在线)。与 frontend-pc 的
src/assets/images/logo.svg 同一形状,这里内嵌是为了原型
「单文件自包含、零外部依赖」—— 不能引外部图片。
原型自己的色板是墨色,所以底仍用 var(--ink),只取白色形状。 */
background:var(--ink) url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><circle cx='36.25' cy='26.62' r='16.31' fill='none' stroke='%23fff' stroke-width='5.9' stroke-opacity='.76'/><rect x='8.5' y='22.65' width='34' height='34' rx='10.4' fill='%23fff'/></svg>") center/112% no-repeat;
}
.brand .bn{font-family:var(--font-display);font-size:15px;font-weight:600;letter-spacing:.05em}
.brand .bs{font-size:9.5px;color:var(--ink4);font-family:var(--font-mono);letter-spacing:.08em;margin-top:2px}
@@ -288,9 +292,9 @@ td.num{font-family:var(--font-mono);text-align:right}
<header class="masthead">
<div class="kicker">Prototype · 管理端 PC · V1.2</div>
<h1>填报通 · <em>管理端</em>交互原型</h1>
<h1>深学在线 · <em>管理端</em>交互原型</h1>
<p class="sub">
11 屏:<strong>工作台 → 任务向导(命名试跑) → 名单导入 → 报考范围 → 数据看板 → 终审 → 导出中心</strong>,加上 <strong>表单设计器 / 材料规则配置 / 历史数据整理器 / 名单加入申请审批</strong>。<br>
10 屏:<strong>工作台 → 任务向导(命名试跑) → 名单导入 → 报考范围 → 数据看板 → 终审 → 导出中心</strong>,加上 <strong>表单设计器 / 材料规则配置 / 角色与授权</strong>。<br>
移动端是「档案室」,桌面端往「<strong>台账</strong>」方向走——表格、树形、批量操作。信息密度比手机端高一个量级,因为管理员是坐在电脑前做批量决策的人。<br>
<span style="font-size:12.5px;color:var(--ink3)">后三屏是**追溯矩阵审计后补的**:三者都是复杂交互,光靠文字描述开发会理解偏。</span>
</p>
@@ -313,7 +317,7 @@ td.num{font-family:var(--font-mono);text-align:right}
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/tasks</div>
</div><div class="view">
<aside class="side">
<div class="brand"><div class="mark">填</div><div><div class="bn">填报通</div><div class="bs">ADMIN CONSOLE</div></div></div>
<div class="brand"><div class="mark"></div><div><div class="bn">深学在线</div><div class="bs">ADMIN CONSOLE</div></div></div>
<nav class="nav">
<a class="on"><svg class="ico"><use href="#i-home"/></svg>工作台</a>
<div class="grp">收集管理</div>
@@ -390,7 +394,7 @@ td.num{font-family:var(--font-mono);text-align:right}
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/tasks/new?step=7</div>
</div><div class="view">
<aside class="side">
<div class="brand"><div class="mark">填</div><div><div class="bn">填报通</div><div class="bs">ADMIN CONSOLE</div></div></div>
<div class="brand"><div class="mark"></div><div><div class="bn">深学在线</div><div class="bs">ADMIN CONSOLE</div></div></div>
<nav class="nav">
<a><svg class="ico"><use href="#i-home"/></svg>工作台</a>
<div class="grp">收集管理</div>
@@ -528,7 +532,7 @@ td.num{font-family:var(--font-mono);text-align:right}
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/tasks/1/roster/import</div>
</div><div class="view">
<aside class="side">
<div class="brand"><div class="mark">填</div><div><div class="bn">填报通</div><div class="bs">ADMIN CONSOLE</div></div></div>
<div class="brand"><div class="mark"></div><div><div class="bn">深学在线</div><div class="bs">ADMIN CONSOLE</div></div></div>
<nav class="nav">
<a><svg class="ico"><use href="#i-home"/></svg>工作台</a>
<div class="grp">收集管理</div>
@@ -635,7 +639,7 @@ td.num{font-family:var(--font-mono);text-align:right}
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/tasks/1/scope</div>
</div><div class="view">
<aside class="side">
<div class="brand"><div class="mark">填</div><div><div class="bn">填报通</div><div class="bs">ADMIN CONSOLE</div></div></div>
<div class="brand"><div class="mark"></div><div><div class="bn">深学在线</div><div class="bs">ADMIN CONSOLE</div></div></div>
<nav class="nav">
<a><svg class="ico"><use href="#i-home"/></svg>工作台</a>
<div class="grp">收集管理</div>
@@ -734,7 +738,7 @@ td.num{font-family:var(--font-mono);text-align:right}
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/tasks/1/dashboard</div>
</div><div class="view">
<aside class="side">
<div class="brand"><div class="mark">填</div><div><div class="bn">填报通</div><div class="bs">ADMIN CONSOLE</div></div></div>
<div class="brand"><div class="mark"></div><div><div class="bn">深学在线</div><div class="bs">ADMIN CONSOLE</div></div></div>
<nav class="nav">
<a><svg class="ico"><use href="#i-home"/></svg>工作台</a>
<div class="grp">收集管理</div>
@@ -834,7 +838,7 @@ td.num{font-family:var(--font-mono);text-align:right}
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/review?status=pending_final</div>
</div><div class="view">
<aside class="side">
<div class="brand"><div class="mark">填</div><div><div class="bn">填报通</div><div class="bs">ADMIN CONSOLE</div></div></div>
<div class="brand"><div class="mark"></div><div><div class="bn">深学在线</div><div class="bs">ADMIN CONSOLE</div></div></div>
<nav class="nav">
<a><svg class="ico"><use href="#i-home"/></svg>工作台</a>
<div class="grp">收集管理</div>
@@ -913,7 +917,7 @@ td.num{font-family:var(--font-mono);text-align:right}
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/export/new</div>
</div><div class="view">
<aside class="side">
<div class="brand"><div class="mark">填</div><div><div class="bn">填报通</div><div class="bs">ADMIN CONSOLE</div></div></div>
<div class="brand"><div class="mark"></div><div><div class="bn">深学在线</div><div class="bs">ADMIN CONSOLE</div></div></div>
<nav class="nav">
<a><svg class="ico"><use href="#i-home"/></svg>工作台</a>
<div class="grp">收集管理</div>
@@ -1017,7 +1021,7 @@ td.num{font-family:var(--font-mono);text-align:right}
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/tasks/new?step=4</div>
</div><div class="view">
<aside class="side">
<div class="brand"><div class="mark">填</div><div><div class="bn">填报通</div><div class="bs">ADMIN CONSOLE</div></div></div>
<div class="brand"><div class="mark"></div><div><div class="bn">深学在线</div><div class="bs">ADMIN CONSOLE</div></div></div>
<nav class="nav">
<a><svg class="ico"><use href="#i-home"/></svg>工作台</a>
<div class="grp">收集管理</div>
@@ -1155,7 +1159,7 @@ td.num{font-family:var(--font-mono);text-align:right}
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/tasks/new?step=5</div>
</div><div class="view">
<aside class="side">
<div class="brand"><div class="mark">填</div><div><div class="bn">填报通</div><div class="bs">ADMIN CONSOLE</div></div></div>
<div class="brand"><div class="mark"></div><div><div class="bn">深学在线</div><div class="bs">ADMIN CONSOLE</div></div></div>
<nav class="nav">
<a><svg class="ico"><use href="#i-home"/></svg>工作台</a>
<div class="grp">收集管理</div>
@@ -1254,240 +1258,151 @@ td.num{font-family:var(--font-mono);text-align:right}
</figcaption>
</figure>
<!-- ⑩ 历史数据整理器 -->
<!-- ⑪ 角色与授权 -->
<figure>
<div class="frame-wrap"><div class="origin">
<div class="win"><div class="wbar">
<div class="lights"><i></i><i></i><i></i></div>
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/cleanup</div>
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/roles</div>
</div><div class="view">
<aside class="side">
<div class="brand"><div class="mark">填</div><div><div class="bn">填报通</div><div class="bs">ADMIN CONSOLE</div></div></div>
<div class="brand"><div class="mark"></div><div><div class="bn">深学在线</div><div class="bs">ADMIN CONSOLE</div></div></div>
<nav class="nav">
<a><svg class="ico"><use href="#i-home"/></svg>工作台</a>
<div class="grp">收集管理</div>
<a><svg class="ico"><use href="#i-task"/></svg>收集任务</a>
<a><svg class="ico"><use href="#i-users"/></svg>名单管理</a>
<a><svg class="ico"><use href="#i-check-circle"/></svg>终审<span class="nb">23</span></a>
<a><svg class="ico"><use href="#i-chart"/></svg>数据看板</a>
<a><svg class="ico"><use href="#i-download"/></svg>导出中心</a>
<div class="grp">工具</div>
<a class="on"><svg class="ico"><use href="#i-wand"/></svg>历史数据整理</a>
</nav>
<div class="who"><div class="av">王</div><div><div class="wn">王老师</div><div class="wr">学校管理员</div></div></div>
</aside>
<div class="main">
<div class="topbar"><h2>历史数据整理</h2><span class="crumb">把已有的乱文件夹,一键变成规范包</span></div>
<div class="scroll">
<div class="note info" style="margin-bottom:16px">
<svg class="ico"><use href="#i-bulb"/></svg>
<div><b>不需要重新收集。</b>把手上已有的压缩包或文件夹传上来,系统会用与正式收集<b>完全相同的规则</b>改名、压缩、体检,输出一份可直接上报的规范包 + 一份问题清单。</div>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:start">
<div class="card">
<header>① 上传<span class="sp"><span class="pill ok"><svg class="ico"><use href="#i-check"/></svg>已解析</span></span></header>
<div class="body">
<div style="display:flex;align-items:center;gap:12px;padding:13px;border:1px solid var(--line);border-radius:9px;background:#faf9f6;margin-bottom:12px">
<svg class="ico" style="font-size:24px;color:var(--ink4)"><use href="#i-folder"/></svg>
<div style="flex:1">
<div style="font-size:13px;font-weight:600;font-family:var(--font-mono)">24中技数控1班.rar</div>
<div style="font-size:11px;color:var(--ink3);margin-top:3px;font-family:var(--font-mono)">436 MB · 4 个目录 · 112 个文件</div>
</div>
</div>
<div class="note ok" style="margin-bottom:0">
<svg class="ico"><use href="#i-check-circle"/></svg>
<div>已按<b>「姓名-证件号-材料名」</b>解析出 28 名学生的 4 类材料,无需命名规范即可识别。</div>
</div>
</div>
</div>
<div class="card">
<header>② 定期体检报告<span class="sp"><span class="hint">用真实数据实测得出</span></span></header>
<div class="body" style="padding:0">
<table>
<thead><tr><th>问题类型</th><th style="width:70px">数量</th><th style="width:96px">占比</th><th style="width:100px">处理</th></tr></thead>
<tbody>
<tr><td>命名违规</td><td class="num" style="font-weight:600">59</td><td class="mono">52.7%</td><td><span class="pill auto">自动修复</span></td></tr>
<tr><td>体积超标(&gt;1M)</td><td class="num" style="font-weight:600">31</td><td class="mono">27.7%</td><td><span class="pill auto">自动压缩</span></td></tr>
<tr><td>证件号与名单不符</td><td class="num" style="font-weight:600;color:var(--seal)">5</td><td class="mono">17.9%</td><td><span class="pill warn">3 自动 · 2 待确认</span></td></tr>
<tr style="background:var(--seal-soft)"><td>疑似串档</td><td class="num" style="font-weight:600;color:var(--seal)">1</td><td class="mono">3.6%</td><td><span class="pill crit">必须人工</span></td></tr>
<tr><td>分辨率不足</td><td class="num">1</td><td class="mono">3.6%</td><td><span class="pill warn">提示重传</span></td></tr>
<tr><td>散图待归属</td><td class="num">0</td><td class="mono">—</td><td><span class="pill gray">—</span></td></tr>
</tbody>
</table>
<div class="body" style="border-top:1px solid var(--line);padding-top:13px">
<div class="note info" style="margin-bottom:0">
<svg class="ico"><use href="#i-bulb"/></svg>
<div><b>112 个文件里 59 个需要改名、31 个需要压缩,但只有 1 个必须你亲自判断。</b>其余 90 个系统全自动处理。</div>
</div>
</div>
</div>
</div>
</div>
<div class="card">
<header>③ 输出结果<span class="sp"><span class="pill jade" style="background:var(--jade);color:#fff">规范化包已生成</span></span></header>
<div class="body">
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin-bottom:16px">
<div class="stat" style="border-color:#cfe0d6;background:var(--jade-soft)"><div class="lbl">原始总量</div><div class="num" style="font-size:22px;color:var(--ink2)">475 MB</div></div>
<div class="stat" style="border-color:#cfe0d6;background:var(--jade-soft)"><div class="lbl">规范化后</div><div class="num" style="font-size:22px;color:var(--jade)">37 MB</div></div>
<div class="stat" style="border-color:#cfe0d6;background:var(--jade-soft)"><div class="lbl">压缩率</div><div class="num" style="font-size:22px;color:var(--jade)">92%</div></div>
</div>
<div style="display:flex;gap:10px">
<button class="btn jade"><svg class="ico"><use href="#i-download"/></svg>下载规范化包</button>
<button class="btn ghost"><svg class="ico"><use href="#i-download"/></svg>下载体检报告(Excel)</button>
<button class="btn ghost"><svg class="ico"><use href="#i-check"/></svg>把结果导入为正式任务</button>
</div>
</div>
</div>
</div>
</div>
</div></div></div></div>
<figcaption>
<span class="tag">STEP 10 · 差异化获客功能</span>
<span class="title">历史数据整理器:让老师先看到价值,再谈上线</span>
客户手里往往已经有一堆历史乱数据(本例是 <b style="font-family:var(--font-mono)">436MB</b> 的 rar)。<b>不需要重新收集</b>,直接传上来就能产出规范包和问题清单——这是最有力的演示,也是最有效的获客入口。
<span class="note">报告里的数字<b>全部来自真实实测</b>:命名违规 59、体积超标 31、证件号异常 5(其中 3 个可自动、2 个待确认)、疑似串档 1、分辨率不足 1。最后那句"<b>90 个系统全自动处理,只有 1 个必须你亲自判断</b>",比任何功能列表都有说服力。</span>
</figcaption>
</figure>
<!-- ⑪ 名单加入申请审批(客户确认新增) -->
<figure>
<div class="frame-wrap"><div class="origin">
<div class="win"><div class="wbar">
<div class="lights"><i></i><i></i><i></i></div>
<div class="url"><svg class="ico"><use href="#i-shield"/></svg>https://admin.tianbaotong.cn/roster/join-requests</div>
</div><div class="view">
<aside class="side">
<div class="brand"><div class="mark">填</div><div><div class="bn">填报通</div><div class="bs">ADMIN CONSOLE</div></div></div>
<nav class="nav">
<a><svg class="ico"><use href="#i-home"/></svg>工作台</a>
<div class="grp">收集管理</div>
<a><svg class="ico"><use href="#i-task"/></svg>收集任务</a>
<a class="on"><svg class="ico"><use href="#i-users"/></svg>名单管理<span class="nb">5</span></a>
<a><svg class="ico"><use href="#i-check-circle"/></svg>终审<span class="nb">23</span></a>
<a><svg class="ico"><use href="#i-chart"/></svg>数据看板</a>
<a><svg class="ico"><use href="#i-download"/></svg>导出中心</a>
<div class="grp">工具</div>
<a><svg class="ico"><use href="#i-wand"/></svg>历史数据整理</a>
<div class="grp">组织与账号</div>
<a><svg class="ico"><use href="#i-org"/></svg>组织架构</a>
<a><svg class="ico"><use href="#i-users"/></svg>账号管理</a>
<a class="on"><svg class="ico"><use href="#i-lock"/></svg>角色与授权</a>
<div class="grp">平台运维</div>
<a><svg class="ico"><use href="#i-list"/></svg>操作日志</a>
</nav>
<div class="who"><div class="av">王</div><div><div class="wn">王老师</div><div class="wr">学校管理员</div></div></div>
</aside>
<div class="main">
<div class="topbar">
<h2>名单加入申请</h2><span class="crumb">24中技数控1班 · 2026年9月认定</span>
<span class="sp"><button class="btn ghost sm">导出申请清单</button></span>
<h2>角色与授权</h2><span class="crumb">江西省机电技师学院 · 4 个内置角色 + 1 个自定义</span>
<span class="sp"><span class="hint">内置角色的权限由代码决定,不可修改</span></span>
</div>
<div class="scroll">
<div class="note info" style="margin-bottom:16px">
<svg class="ico"><use href="#i-bulb"/></svg>
<div><b>这些人在门禁没匹配上,主动申请加入名单。</b>通过后会<b>自动建成名册项</b>,该学生凭微信再次进入即可直接填报,不用重输。<br>
<span style="font-size:11.5px;color:var(--ink3)">申请本身<b>不能填报</b>——通道只解决"进名单",不绕过门禁。</span></div>
</div>
<div style="display:grid;grid-template-columns:236px 1fr;gap:16px;align-items:start">
<div style="display:grid;grid-template-columns:1fr 300px;gap:16px;align-items:start">
<div class="card" style="margin:0">
<header>待审申请<span class="sp"><span class="pill warn">5 条待处理</span></span></header>
<div class="body" style="padding:0">
<table>
<thead><tr>
<th style="width:26px"><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"></th>
<th>申请人</th><th>身份证号</th><th>手机号</th><th>自述班级 / 说明</th><th style="width:74px">等待</th><th style="width:132px">操作</th>
</tr></thead>
<tbody>
<tr>
<td><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"></td>
<td><b>李四</b></td>
<td class="mono">361004********3318</td>
<td class="mono">138****8888</td>
<td><span style="font-size:11.5px">24中技数控2班</span><br><span style="font-size:11px;color:var(--ink3)">我是这学期转到2班的</span></td>
<td class="mono">2.5h</td>
<td><button class="btn jade sm">通过</button> <button class="btn ghost sm">驳回</button></td>
</tr>
<tr>
<td><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"></td>
<td><b>王芳</b> <span class="pill auto" style="font-size:10px">他任务已有</span></td>
<td class="mono">360105********1628</td>
<td class="mono">139****2233</td>
<td><span style="font-size:11.5px">—</span><br><span style="font-size:11px;color:var(--jade)">2026年3月认定 已在本校名单</span></td>
<td class="mono">5.1h</td>
<td><button class="btn jade sm">通过</button> <button class="btn ghost sm">驳回</button></td>
</tr>
<tr>
<td><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"></td>
<td><b>赵敏</b></td>
<td class="mono">361029********4021</td>
<td class="mono">137****9012</td>
<td><span style="font-size:11.5px">24中技数控1班</span><br><span style="font-size:11px;color:var(--ink3)">名单上把我的名字写错了</span></td>
<td class="mono">7.8h</td>
<td><button class="btn jade sm">通过</button> <button class="btn ghost sm">驳回</button></td>
</tr>
<tr>
<td><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"></td>
<td><b>陈强</b></td>
<td class="mono">362502********1830</td>
<td class="mono">135****6677</td>
<td><span style="font-size:11.5px">—</span><br><span style="font-size:11px;color:var(--ink3)">朋友说这里可以报名</span></td>
<td class="mono">21.3h</td>
<td><button class="btn jade sm">通过</button> <button class="btn ghost sm">驳回</button></td>
</tr>
<tr>
<td><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"></td>
<td><b>孙悦</b> <span class="pill crit" style="font-size:10px">第 2 次申请</span></td>
<td class="mono">361024********0917</td>
<td class="mono">136****3344</td>
<td><span style="font-size:11.5px">24中技数控2班</span><br><span style="font-size:11px;color:var(--seal)">上次被驳回:班级不在本次范围</span></td>
<td class="mono">26.5h</td>
<td><button class="btn jade sm">通过</button> <button class="btn ghost sm">驳回</button></td>
</tr>
</tbody>
</table>
<header style="font-size:12.5px;padding:11px 13px">角色<span class="sp"><button class="btn primary sm">新建</button></span></header>
<div class="body" style="padding:6px">
<div style="display:flex;align-items:center;gap:6px;padding:8px 10px;border-radius:6px;font-size:12.5px">
<span style="flex:1">平台运营</span><span class="pill gray" style="font-size:10px">内置</span><span class="pill gray" style="font-size:10px">不可分配</span><span style="font-size:11px;color:var(--ink3)">0 人</span>
</div>
<div style="display:flex;align-items:center;gap:6px;padding:8px 10px;border-radius:6px;font-size:12.5px">
<span style="flex:1">学校管理员</span><span class="pill gray" style="font-size:10px">内置</span><span style="font-size:11px;color:var(--ink3)">1 人</span>
</div>
<div style="display:flex;align-items:center;gap:6px;padding:8px 10px;border-radius:6px;font-size:12.5px">
<span style="flex:1">班主任</span><span class="pill gray" style="font-size:10px">内置</span><span style="font-size:11px;color:var(--ink3)">1 人</span>
</div>
<div style="display:flex;align-items:center;gap:6px;padding:8px 10px;border-radius:6px;font-size:12.5px">
<span style="flex:1">学生</span><span class="pill gray" style="font-size:10px">内置</span><span style="font-size:11px;color:var(--ink3)">11 人</span>
</div>
<div style="display:flex;align-items:center;gap:6px;padding:8px 10px;border-radius:6px;font-size:12.5px;background:var(--jade-soft)">
<span style="flex:1;font-weight:600">年级审核员</span><span class="pill auto" style="font-size:10px">自定义</span><span style="font-size:11px;color:var(--ink3)">0 人</span>
</div>
</div>
</div>
<div style="display:flex;flex-direction:column;gap:14px">
<div class="card" style="margin:0">
<header style="font-size:12.5px;padding:11px 13px">批量处理</header>
<div class="body" style="padding:13px">
<button class="btn jade" style="width:100%;justify-content:center;margin-bottom:9px">通过已选(2 条)</button>
<div class="note warn" style="padding:9px 11px;font-size:11.5px;line-height:1.65;margin-bottom:9px">
<svg class="ico" style="font-size:13px"><use href="#i-alert"/></svg>
<div><b>驳回必须逐条填原因</b>,不支持批量驳回</div>
<header>
年级审核员 <span class="mono" style="font-weight:400;color:var(--ink3)">GRADE_AUDITOR</span>
<span class="sp">
<button class="btn ghost sm">刷新</button>
<button class="btn ghost sm">编辑</button>
<button class="btn ghost sm">停用</button>
<button class="btn ghost sm">删除</button>
</span>
</header>
<div class="body">
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:10px;font-size:12.5px;margin-bottom:12px">
<div><div style="color:var(--ink3);font-size:11px;margin-bottom:3px">类型</div>自定义</div>
<div><div style="color:var(--ink3);font-size:11px;margin-bottom:3px">用户类型</div>班主任</div>
<div><div style="color:var(--ink3);font-size:11px;margin-bottom:3px">数据范围</div>仅本人</div>
<div><div style="color:var(--ink3);font-size:11px;margin-bottom:3px">账号数</div>0</div>
</div>
<div style="font-size:11px;color:var(--ink3);line-height:1.7">
批量通过时会弹出确认框,逐条列出将建册的人员,<b>不提供"全选"快捷键</b>。
<div class="note warn" style="margin-bottom:14px">
<svg class="ico"><use href="#i-alert"/></svg>
<div><b>有未保存的改动。</b>点「保存授权」后<b>立即生效</b>——已登录的账号不需要重新登录(服务端会清掉这个角色的授权缓存)。</div>
</div>
<div style="font-size:12.5px;font-weight:600;margin-bottom:4px">能做什么(权限码)</div>
<div style="font-size:11.5px;color:var(--ink3);margin-bottom:9px">决定按钮与接口能不能用;勾了才会真的生效</div>
<div style="font-size:11.5px;color:var(--ink2);margin-bottom:6px">名册</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:6px 14px;font-size:12.5px;margin-bottom:12px">
<label><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"> 名册查看 <span class="mono" style="font-size:11px;color:var(--ink3)">roster:view</span></label>
<label><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"> 名册修改(仅本班) <span class="mono" style="font-size:11px;color:var(--ink3)">roster:manageOwn</span></label>
<label><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"> 名册导入与修改(全租户) <span class="mono" style="font-size:11px;color:var(--ink3)">roster:manage</span></label>
</div>
<div style="font-size:11.5px;color:var(--ink2);margin-bottom:6px">审核</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:6px 14px;font-size:12.5px;margin-bottom:12px">
<label><input type="checkbox" checked style="accent-color:var(--jade);width:14px;height:14px"> 初审(班主任) <span class="mono" style="font-size:11px;color:var(--ink3)">audit:first</span></label>
<label><input type="checkbox" checked style="accent-color:var(--jade);width:14px;height:14px"> 教师代传材料 <span class="mono" style="font-size:11px;color:var(--ink3)">file:proxyUpload</span></label>
<label><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"> 终审(管理员) <span class="mono" style="font-size:11px;color:var(--ink3)">audit:final</span></label>
<label><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"> 撤回审核 <span class="mono" style="font-size:11px;color:var(--ink3)">audit:withdraw</span></label>
</div>
<div style="font-size:11.5px;color:var(--ink2);margin-bottom:6px">平台运营<span class="hint" style="margin-left:6px">学校租户配不了这一组</span></div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:6px 14px;font-size:12.5px;color:var(--ink3);margin-bottom:14px">
<label><input type="checkbox" disabled style="width:14px;height:14px"> 租户与套餐管理 <span class="mono" style="font-size:11px">tenant:manage</span> <span class="pill crit" style="font-size:10px">平台级,学校不可授予</span></label>
<label><input type="checkbox" disabled style="width:14px;height:14px"> 全量操作日志 <span class="mono" style="font-size:11px">log:viewAll</span> <span class="pill crit" style="font-size:10px">平台级,学校不可授予</span></label>
</div>
<div style="font-size:12.5px;font-weight:600;margin-bottom:4px">看得见哪些入口(菜单)</div>
<div style="font-size:11.5px;color:var(--ink3);margin-bottom:9px">只影响左侧菜单显不显示 —— 真正的权限在上面那一栏,绕过前端只会拿到 40301</div>
<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:6px 14px;font-size:12.5px">
<label><input type="checkbox" checked style="accent-color:var(--jade);width:14px;height:14px"> 工作台</label>
<label><input type="checkbox" checked style="accent-color:var(--jade);width:14px;height:14px"> 收集任务</label>
<label><input type="checkbox" checked style="accent-color:var(--jade);width:14px;height:14px"> 审核</label>
<label><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"> 导出中心</label>
<label><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"> 通知记录</label>
<label><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"> 字典管理</label>
<label><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"> 组织架构</label>
<label><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"> 账号管理</label>
<label><input type="checkbox" style="accent-color:var(--jade);width:14px;height:14px"> 角色与授权</label>
</div>
<div style="margin-top:14px">
<button class="btn primary sm">保存授权</button>
<button class="btn ghost sm">撤销改动</button>
<span class="hint" style="margin-left:8px">保存后立即生效;已登录的账号不需要重新登录</span>
</div>
</div>
</div>
<div class="card" style="margin:0">
<header style="font-size:12.5px;padding:11px 13px">本任务申请统计</header>
<header style="font-size:12.5px;padding:11px 13px">内置角色点开是什么样</header>
<div class="body" style="padding:13px">
<div class="row" style="display:flex;justify-content:space-between;padding:7px 0;border-bottom:1px dashed var(--line);font-size:12.5px"><span style="color:var(--ink2)">待审核</span><b>5</b></div>
<div class="row" style="display:flex;justify-content:space-between;padding:7px 0;border-bottom:1px dashed var(--line);font-size:12.5px"><span style="color:var(--ink2)">已通过</span><b style="color:var(--jade)">12</b></div>
<div class="row" style="display:flex;justify-content:space-between;padding:7px 0;border-bottom:1px dashed var(--line);font-size:12.5px"><span style="color:var(--ink2)">已驳回</span><b>3</b></div>
<div class="row" style="display:flex;justify-content:space-between;padding:7px 0;font-size:12.5px"><span style="color:var(--ink2)">通过率</span><b>80%</b></div>
<div class="note info" style="margin-top:11px;padding:9px 11px;font-size:11.5px;line-height:1.6">
<svg class="ico" style="font-size:13px"><use href="#i-check-circle"/></svg>
<div>12 人已通过并自动入册</div>
<div class="note info" style="margin-bottom:0">
<svg class="ico"><use href="#i-lock"/></svg>
<div><b>只读。</b>权限矩阵照着显示(可以拿它当模板照着勾),但勾选框是禁用的、没有「保存授权」按钮。<br>
<span style="font-size:11.5px;color:var(--ink3)">要不同的能力范围,请<b>新建一个自定义角色</b>——而不是去改内置的。</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div></div></div></div>
<figcaption>
<span class="tag">STEP 11 · 客户确认新增</span>
<span class="title">名单加入申请:给门禁一条受控的出口,而不是开后门</span>
门禁不通过的人原先只能"联系老师",老师再手工加名单。<b>几百人的社会收集场景下,老师会被拖垮</b>。这一屏把加人这件事从"老师手工"变成"学生自助 + 老师逐条裁决"。
<span class="note">四个细节:<br>
① <b>「他任务已有」标记</b>——王芳的证件号在「2026年3月认定」的名册里匹配上了,系统主动提示"这可能是本校学生",帮管理员判断;<br>
② <b>「第 2 次申请」标记</b>——孙悦上次被驳回,管理员能看到上次的驳回原因,避免重复纠结;<br>
③ <b>「驳回必须逐条填原因」</b>且批量通过不提供全选——身份认定环节的误操作代价极高,与"批量通过只带绿色项"同源;<br>
④ 顶部那句<b>「申请本身不能填报」</b>是设计边界:通道只解决"进名单",不绕过门禁。</span>
<span class="tag">STEP 10 · 角色与授权</span>
<span class="title">权限是契约、不是配置:内置角色只读,自定义角色可配</span>
内置角色现在只剩 4 个(平台运营 / 学校管理员 / 班主任 / 学生),权限写在后端代码里(<span class="mono">BuiltinRole</span>)、界面上<b>只读</b>。租户可另建自定义角色,于是"谁能做什么"第一次变成客户可以自己配的东西 —— 而这类功能一旦做松,代价是<b>管理员把自己锁在系统外</b>。
<span class="note">五个细节:<br>
① <b>内置角色只读</b>——可以看、不能改。它的权限是前后端契约(权限码定义在代码里),改它等于改代码;界面上正确的做法是"照着它新建一个";<br>
② <b>「看得见」与「有权限」分开</b>——菜单只决定左侧显示哪些入口,真正的访问控制是权限码校验(绕过前端只会拿到 40301);<br>
③ <b>平台级权限与平台专用菜单在界面上禁用</b>,服务端也会以 40301 拒绝——"学校管理员给自己人造一个平台账号"是这套系统里最不可逆的越权;<br>
④ <b>改完立即生效</b>——服务端在写授权时清掉该角色的缓存,所以不必"重新登录看看生效没有";停用角色同理(立刻不再给权限,而不是等 token 过期);<br>
⑤ <b>防自锁</b>——不允许去掉自己进入本页所依赖的最后一条「角色与授权」权限/菜单,也不允许删掉唯一的管理员角色;这类错误只能靠 SQL 救回来。</span>
</figcaption>
</figure>
@@ -1529,8 +1444,8 @@ td.num{font-family:var(--font-mono);text-align:right}
如果下拉里只写"P1 / P2 / P3",管理员必须去翻文档才知道选哪个。**把档位的适用条件直接写在选项里**,配置界面本身就变成说明书。
</div>
<div class="aside-card">
<h4><span class="n">09</span>为什么整理器是获客利器</h4>
客户手里普遍已有历史乱数据(本例 436MB 的 rar)。让他们**先看到价值再谈上线**:不重新收集,30 秒内出一份体检报告和规范包。报告里"<b>90 个系统全自动处理,只有 1 个必须你亲自判断</b>"这句话,比任何功能列表都有说服力。
<h4><span class="n">09</span>为什么内置角色只读、自定义角色才能改</h4>
内置角色的权限<b>定义在后端代码里</b>(权限码是前后端契约:后端用它校验、前端用它控制按钮显隐)。把它做成"界面上可改",等于把一份契约拆成两处维护——而两处一旦不一致,表现是"按钮显示出来了、点了报 40301"。更要紧的是:一次误操作就能把管理员锁在系统外,而这类错误<b>不可逆</b>。所以界面上只读,需要别的能力范围时<b>新建一个自定义角色</b>。
</div>
</div>
</section>