这是给学员看的完整演练 demo。
角色:小王,某互联网公司 HR 专员,Excel 管候选人管到崩溃,想做个内部工具。
目标:跟业务助手智能体(本 Skill)从 0 到 1 把招聘后台做出来,并经历 4 种典型往返。
读这份 demo 之前,请先看 examples/README.md 入门。
下面所有「学员说」都是小王原话,所有「Skill 说」都是 Skill 应该输出的话(学员看到的)。
学员说:
我是 HR 专员,平时用 Excel 管候选人,候选人多了根本管不过来,经常漏掉简历、漏约面试,想搞个工具。
Skill 说:
收到。听起来你现在的痛点是「候选人多、流程乱、容易漏」。我接着问两个问题,问完就给你出产品文档。
1. 这个工具主要给你自己用,还是 HR 团队几个人一起用?
2. 一个候选人从你收到简历到入职,中间大致要走几步?每一步你大概做什么?
学员说:
主要是给我自己用,偶尔组长会看。流程是这样的:业务部门先发「招聘需求」(岗位、人数、要求),我在招聘网站收简历,把候选人录入,然后 HR 面试 → 业务面试 → 管理层终面 → 发 offer → 入职。每轮面试要记评价。
Skill 说:
明白了。最后一个问题,我想确认下:
1. 除了「候选人主表」,你还需要单独维护「招聘需求」和「面试评价」吗?(我建议分开,更清晰)
2. 候选人要记录哪些字段?我先猜几个你看够不够:姓名、应聘岗位、来源渠道、当前阶段、最近联系时间、备注。
学员说:
字段差不多,再加一个「期望薪资」吧。需求和面试评价分开放,这样我能从需求看进度。
风格不用太花哨,简洁能用就行,像 Vercel 那种。
Skill 说:
好的,我现在去写产品文档,会写到 outputs/prd-hr-recruitment-v0.1.md,写完我告诉你。
阶段一执行清单(对照 SKILL.md 第 3 节)
Skill 写出 outputs/prd-hr-recruitment-v0.1.md,关键内容(节选):
---
产品名: HR 招聘后台
版本: v0.1
最后更新: 2026-06-09
---
## 1. 产品定位
为 HR 专员提供一个集中管理招聘需求、候选人、面试评价的内部工具,
替代当前用 Excel 管理候选人时容易漏掉简历、漏约面试的痛点。
## 2. 目标用户
- 主要:HR 专员(自己用)
- 次要:HR 组长(只看统计和进度)
## 3. 使用场景
- 每天:查看候选人进度、安排面试、记录面试评价
- 每周:汇总招聘需求完成情况、统计漏掉的简历
## 4. 核心功能列表
- [x] P0 招聘需求管理(发布、编辑、关闭)
- [x] P0 候选人管理(录入、编辑、状态推进、删除)
- [x] P0 面试评价记录(HR 面试 / 业务面试 / 管理层终面)
- [x] P0 仪表盘(招聘需求完成度、漏掉的简历提醒)
- [ ] P1 候选人搜索、按岗位筛选
- [ ] P1 导出候选人 Excel
## 5. 字段定义
### 5.1 招聘需求
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| 标题 | 文本 | 是 | 例如「高级前端工程师」 |
| 部门 | 文本 | 是 | 业务部门 |
| 人数 | 数字 | 是 | 招聘人数 |
| 状态 | 枚举 | 是 | 开放/已满/已关闭 |
### 5.2 候选人
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| 姓名 | 文本 | 是 | |
| 应聘岗位 | 关联 | 是 | 关联到招聘需求 |
| 来源渠道 | 枚举 | 否 | BOSS/拉勾/猎聘/内推 |
| 当前阶段 | 枚举 | 是 | 简历筛选/HR 面试/业务面试/管理层终面/已发 offer/已入职/已淘汰 |
| 最近联系时间 | 日期 | 否 | |
| 期望薪资 | 数字 | 否 | 单位:千元 |
| 备注 | 文本 | 否 | |
### 5.3 面试评价
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| 候选人 | 关联 | 是 | 关联到候选人 |
| 面试轮次 | 枚举 | 是 | HR 面试/业务面试/管理层终面 |
| 面试官 | 文本 | 是 | |
| 评价 | 文本 | 是 | |
| 日期 | 日期 | 是 | |
## 6. 视觉风格
- 风格:Vercel / shadcn UI 风格,简洁清晰
- 左侧主导航,顶部 16px 固定栏
- 浅色 + 深色双主题
- 5 种状态色(绿/黄/红/蓝/灰)
## 7. 业务规则
- 候选人必须依次经过 HR 面试 → 业务面试 → 管理层终面 → offer
- 同一候选人同一轮次可以有多次面试评价(允许二面)
Skill 说:
PRD 已经写到 outputs/prd-hr-recruitment-v0.1.md。
请逐项审阅:产品定位、目标用户、核心功能、字段定义、视觉风格、业务规则。
有问题直接说「修改 XX 部分」,没问题就说「OK 开始生成 Demo」。
阶段二执行清单(对照 SKILL.md 第 4 节)
学员说:OK
Skill 基于 PRD 生成 outputs/demo-hr-recruitment/index.html(单文件 HTML,55KB 左右),完成后告诉学员:
Skill 说:
Demo 已经写到 outputs/demo-hr-recruitment/index.html。
双击在浏览器打开就能用,数据存在 localStorage,刷新不丢。
包含 6 个视图:仪表盘 / 招聘需求 / 候选人列表 / 候选人看板 / 面试评价 / 设置。
学员打开 demo,看到左侧导航、浅色主题、能新建招聘需求、能录入候选人、能切换候选人阶段。点击保存按钮后刷新页面,数据还在。
阶段三执行清单(对照 SKILL.md 第 5 节)
lg:pl-60 + 固定左侧)hr-recruitment__data_v1)references/crud-pattern.md)学员用了一周 Demo,业务部门反馈「面试官有没有认真面试我们也不知道」,想给每个面试评价加个「面试官评分 1-5」。
学员说:再加一个「面试官评分」字段,1-5 分,放在面试评价里。
这是一次典型的「改字段」反馈 → 路由到场景 A:用户完善 PRD 后再次生成。
score ?? null 兜底(老数据没有这个字段不崩)Skill 说:
我准备做 3 处改动:
1. PRD 5.3 面试评价 加一行「面试官评分(数字 1-5,选填)」,版本升到 v0.2
2. Demo 的「面试评价」弹窗加这个字段,列表里展示出来
3. CHANGELOG.md 加一条 v0.2 记录
老数据兼容:没有这个字段的旧评价会显示为「—」。
确认后我改。
PRD 5.3 节插入:
| 面试官评分 | 数字 | 否 | 1-5 分,业务部门可见 |
代码关键片段(Alpine.js data + 模板):
// data 里加字段
const defaultEval = { id: ..., 候选人, 面试轮次, 面试官, 评价, 日期, 面试官评分: null };
// 保存时兜底
saveAll(items.map(x => ({ ...x, 面试官评分: x.面试官评分 ?? null })));
// 模板展示(用中文「/5」避免引号转义问题)
<td>
<span x-text="item.面试官评分 ? item.面试官评分 + String.fromCharCode(47) + String(5) : String.fromCharCode(0x2014)"></span>
</td>
更直观的写法(单引号转义用 \):
// 或者用反引号包字符串,避开单引号转义
<td>
<span x-text="item.面试官评分 ? item.面试官评分 + `/5` : `—`"></span>
</td>
CHANGELOG.md 顶部新增:
## v0.2 - 2026-06-15 - 新增面试官评分字段
业务反馈:业务部门希望看到面试官对候选人的打分。
### 变更
- 字段:`面试评价.面试官评分`(数字 1-5,选填)
- PRD:5.3 节,版本 v0.1 → v0.2
- Demo:面试评价 Modal 加输入框,列表加展示列
### 数据兼容
- 老评价无此字段,读取时显示「—」,不报错
Skill 说:
改完了,这次改了 3 处:
1. PRD 5.3 加了一行 + 升到 v0.2
2. Demo 面试评价 Modal 加了输入框,列表里会展示「X/5」
3. CHANGELOG.md 顶部加了一段 v0.2 记录
老数据兼容,没有评分的评价显示「—」。
验证方法:打开 Demo → 面试评价 → 新建一个评价 → 输入 4 → 保存 → 列表里看到「4/5」。
场景 A 自检(对照 references/iteration-patterns.md 第 2 节)
?? null)学员继续用了两周,中间跟 Skill 提过一些零碎业务规则,现在想让 Skill 把这些都正式写进 PRD。
学员说:把咱们之前聊天里说的那些业务规则也写到 PRD 里
Skill 回看过去几周的对话,挑出 4 条事实陈述(过滤掉寒暄、确认、疑问):
和当前 PRD 比对:
Skill 说:
我准备把以下 4 条对话内容合并到 PRD 第 7 节「业务规则」,版本 v0.2 → v0.3:
1. (新) 候选人通过 HR 面试后 24 小时内必须安排业务面试,系统超期提醒
2. (新) 已淘汰候选人保留 90 天,到期自动清理
3. (补全) 管理层终面必须有 HR 组长参与,业务部门不可跳过
4. (新) 招聘需求发布超过 60 天未招满,自动标记为「暂停」
确认后我写入 PRD。
学员说:第 3 条改成「必须有 HR 组长在场」,不是「参与」。其他 OK。
PRD 第 7 节追加 4 条 + 版本升到 v0.3:
## 7. 业务规则
- 候选人必须依次经过 HR 面试 → 业务面试 → 管理层终面 → offer
- 同一候选人同一轮次可以有多次面试评价(允许二面)
- **(v0.3 新增)** 候选人通过 HR 面试后 24 小时内必须安排业务面试,系统超期提醒
- **(v0.3 新增)** 已淘汰候选人保留 90 天,到期自动清理
- **(v0.3 补全)** 管理层终面必须有 HR 组长在场,业务部门不可跳过
- **(v0.3 新增)** 招聘需求发布超过 60 天未招满,自动标记为「暂停」
CHANGELOG.md 顶部加:
## v0.3 - 2026-06-22 - 业务规则补充
### 变更
- 合并对话中的 4 条业务规则到 PRD 第 7 节
- 版本 v0.2 → v0.3
### 下一步
PRD 改完了。要重新生成应用吗?这些规则会落到 Demo 的提醒和自动任务里。
Skill 说:
PRD 改完了,版本升到 v0.3。
这 4 条规则里有 3 条涉及 Demo 的逻辑改动(超期提醒、90 天清理、60 天暂停),需要重新生成应用才会生效。
要我现在重新生成吗?
场景 B 自检(对照 references/iteration-patterns.md 第 3 节)
一个月后,公司换了招聘流程:HR 面试 → 笔试 → 业务面试 → 终面。
学员说:流程大改一下,HR 面试和业务面试中间加一个笔试环节,笔试不通过直接淘汰。
当前阶段 枚举值变化→ 影响 > 30% 代码 → 路由到场景 C:重大改动重生成。
Skill 说:
这次是大改,影响 5 个地方。我建议冻结当前 v0.3 作为 snapshot,然后开 v1.0 整页重写。
冻结操作:
-outputs/demo-hr-recruitment/→outputs/demo-hr-recruitment-v0.3-snapshot-20260708/
-outputs/prd-hr-recruitment-v0.3.md→outputs/_archive/prd-hr-recruitment-v0.3.md
你的老数据(hr-recruitment__data_v1)会通过迁移函数升级,不会丢。
确认后我开始?
学员说:OK
新 PRD v1.0 关键差异:
---
产品名: HR 招聘后台
版本: v1.0 (基于 v0.3 重大重构)
最后更新: 2026-07-08
---
## 5.2 候选人(变更)
| 当前阶段 | 枚举 | 是 | 简历筛选/HR 面试/**笔试**/业务面试/管理层终面/已发 offer/已入职/已淘汰 |
## 5.3 面试评价(变更)
| 面试轮次 | 枚举 | 是 | HR 面试/**笔试**/业务面试/管理层终面 |
## 7. 业务规则(变更)
- **(v1.0 新增)** 笔试环节,HR 面试通过后必须先笔试,通过后才能进入业务面试
- **(v1.0 新增)** 笔试不通过直接淘汰,不进入业务面试
- 其他规则沿用 v0.3
数据迁移函数(在 Demo 启动时执行):
function migrateData_v0_v1(oldData) {
// 候选人阶段:原「HR 面试」之后,如果是已经过 HR 面试没安排业务面试的,保持原样不动
// 新流程只在 v1.0 之后生效,老候选人保留阶段
return {
...oldData,
version: 2,
招聘需求: oldData.招聘需求 || [],
候选人: (oldData.候选人 || []).map(c => ({
...c,
// 阶段值不变,看板新列「笔试」先显示为空
})),
面试评价: oldData.面试评价 || [],
};
}
// 启动时检测版本
const stored = JSON.parse(localStorage.getItem(HR_KEY) || "null");
if (stored && stored.version !== 2) {
const migrated = migrateData_v0_v1(stored);
// 备份老数据
localStorage.setItem("hr-recruitment__backup_v0", JSON.stringify(stored));
localStorage.setItem(HR_KEY, JSON.stringify(migrated));
}
CHANGELOG.md 顶部大事记:
## v1.0 - 2026-07-08 - 重大重构:加入笔试环节
⚠️ **Breaking**:候选人阶段枚举扩展,数据模型版本 v1 → v2
自动迁移函数 `migrateData_v0_v1` 启动时执行,老数据自动备份到 `hr-recruitment__backup_v0`
### 主要变化
- [业务] 新增笔试环节,HR 面试 → 笔试 → 业务面试 → 终面
- [业务] 笔试不通过直接淘汰
- [技术] 候选人看板新增「笔试」列
- [数据] `当前阶段` 枚举扩展,新增「笔试」
- [数据] `面试轮次` 枚举扩展,新增「笔试」
- [数据] 老数据自动迁移,老阶段值不变
### 回滚方法
如果 v1.0 有问题,把 `outputs/demo-hr-recruitment-v0.3-snapshot-20260708/` 复制回来即可。
Skill 说:
v1.0 已经写完,整页重写,数据自动迁移。
这次改了:
1. 候选人阶段枚举加了「笔试」
2. 面试评价枚举加了「笔试」
3. 候选人看板新增「笔试」列
4. 业务规则加了「笔试不通过直接淘汰」
5. 启动时自动迁移老数据,老候选人阶段值保持不变
验证方法:
1. 打开 Demo(刷新一次,触发迁移)
2. 找一个 v0.3 时代的候选人,确认他还在,阶段没变
3. 在控制台输入 localStorage.getItem("hr-recruitment__backup_v0"),能看到老数据备份
4. 找一个新候选人推到「笔试」阶段,看板新列应该有他
场景 C 自检(对照 references/iteration-patterns.md 第 4 节)
__backup_v0v1.0 上线第二天,学员觉得首页仪表盘数字太小,想用公司主色。
学员说:首页仪表盘那几个大数字(在招岗位数、面试安排数、入职人数)调大一点,颜色用我们公司蓝 #1E40AF,字号大两号。
找 demo-hr-recruitment/index.html 里仪表盘大数字的 class,把:
<div class="text-3xl font-semibold text-slate-900 dark:text-slate-100">
<span x-text="stats.openJobs"></span>
</div>
改成:
<div class="text-5xl font-bold text-[#1E40AF] dark:text-blue-400">
<span x-text="stats.openJobs"></span>
</div>
其他几个数字同样处理。
CHANGELOG.md 顶部加补丁记录(不升版本号):
## patch - 2026-07-09 - 仪表盘数字字号调大 + 公司蓝
### 变更
- 仪表盘 4 个大数字:text-3xl → text-5xl
- 颜色:slate-900 → #1E40AF(亮)/ blue-400(暗)
- 不改 PRD(纯视觉微调)
Skill 说:
仪表盘改完了,刷新浏览器看看。
改了:
- 4 个大数字字号 text-3xl → text-5xl
- 颜色换成 #1E40AF(你们公司蓝),深色模式下用 blue-400
PRD 没改(纯视觉),CHANGELOG 加了一条 patch 记录。
验证方法:打开 Demo 首页 → 看到仪表盘 4 个大数字变大变蓝 → 切到深色模式 → 数字变成浅蓝。
场景 D 自检(对照 references/iteration-patterns.md 第 5 节)
outputs/
├── prd-hr-recruitment-v1.0.md (当前 PRD)
├── _archive/
│ └── prd-hr-recruitment-v0.3.md (老版本)
├── demo-hr-recruitment/
│ ├── index.html (v1.0 应用)
│ ├── CHANGELOG.md (v0.2 / v0.3 / v1.0 / patch 全记录)
│ └── README.md (用户手册)
└── demo-hr-recruitment-v0.3-snapshot-20260708/ (冻结的老版本)
└── index.html (出问题可回滚)
references/iteration-patterns.md 各场景末尾)references/iteration-patterns.mdoutputs/demo-hr-recruitment/index.htmlreferences/crud-pattern.mdreferences/prd-template.md 和 assets/prd-template.md