28 KiB
tags, create time
| tags | create time | ||||||||
|---|---|---|---|---|---|---|---|---|---|
|
2026-05-09 14:30 |
大作业·执行计划 — 双端 gRPC HR 招聘系统
概述
本文档基于《大作业项目要求》《思维导图》《工程结构设计》三份参考资料,梳理出分阶段、可落地的开发执行计划。整体采用 六阶段推进 策略:环境准备 → Proto 先行 → 后端双服务 → 前端一日冲刺 → 联调测试 → 视频录制与提交,每个阶段明确任务清单、前置依赖和验收标准,确保按期完成高质量交付。
[!tip] 如何使用本计划 建议按阶段的顺序推进,不要跳跃。Proto 定义是前后端的"契约",必须先于业务代码完成。每个阶段完成后对照验收清单自检,避免返工。
一、整体时间规划与打勾进度
将整个开发周期拆分为 6 个阶段,各阶段之间存在明确的先后依赖关系。下方是总进度看板,每完成一个阶段就打勾:
gantt
title 大作业开发总时间线
dateFormat YYYY-MM-DD
axisFormat %m-%d
todayMarker stroke-width:3px,stroke:#fb8c00,opacity:0.6
section 阶段一 · 环境就绪 (M0)
Go / Node / MySQL / OSS :done, p1, 2026-05-10, 1d
.gitignore + .env.example :done, p1b, after p1, 30m
section 阶段二 · Proto 先行 (M1)
7 个接口定义文件 :done, p2, 2026-05-11, 1d
protoc 生成 Go 代码 :done, p2b, after p2, 30m
section 阶段三 · 后端双服务 (M2)
3A · MySQL 建表 : p3a, 2026-05-12, 1d
3B · Logic 核心服务 (12项) :milestone, m3b, 2026-05-14, 0d
3C · Web 网关服务 : p3c, after p3a, 2d
section 阶段四 · 前端一日冲刺 (M3)
Foundation 共享基建 : p4a, 2026-05-15, 3h
候选人用户端 (6页) : p4u, after p4a, 4h
HR 管理端 (7页) : p4h, after p4a, 5h
Build 验证 + Commit :milestone,m4z, 2026-05-15, 0d
section 阶段五 · 联调自测 (M4)
全链路跑通 : p5a, 2026-05-16, 1d
专项测试 + Bug 修复 : p5b, 2026-05-17, 1d
section 阶段六 · 录制提交 (M5)
文档完善 : p6a, 2026-05-18, 2d
视频录制 + KDoc 提交 :milestone,m6end, 2026-05-18, 0d
%% 里程碑锚点
milestone M0_环境就绪 :milestone, mk1, 2026-05-10, 0d
milestone M1_Protobuf冻结 :milestone, mk2, 2026-05-11, 0d
milestone M2_后端可运行 :milestone, mk3, 2026-05-14, 0d
milestone M3_双端完成 :milestone, mk4, 2026-05-15, 0d
milestone M4_联调通过 :milestone, mk5, 2026-05-17, 0d
milestone M5_正式提交 :milestone, mk6, 2026-05-18, 0d
| 阶段 | 日期 | 核心交付物 | 里程碑 |
|---|---|---|---|
| Go / Node / MySQL / OSS 就绪 | ✅ M0 | ||
| 阶段二:Proto 接口定义 | 7 个 .proto 文件 + 生成代码 |
⬜ M1 | |
| 阶段三:后端双服务 | 05-12 ~ 05-14 | Logic gRPC + Web Gin 均可独立运行 | ⬜ M2 |
| 阶段四:前端一日冲刺 | 05-15 | hr-frontend + user-frontend 启动 | ⬜ M3 |
| 阶段五:前后端联调 | 05-16 ~ 05-17 | 全链路测试通过 | ⬜ M4 |
| 阶段六:视频录制与提交 | 05-18 | 视频 + 文档全部提交 | ⬜ M5 |
[!tip] 使用说明
- 🟢 绿色条 = 已完成阶段 · 🟡 黄色条 = 当前活跃期 · 🔴 菱形标记 = 里程碑检查点
- 橙色竖线为今日日期标注,直观对比当前所处阶段
- 甘特图下方表格同步映射 M0~M5 里程碑编号,与第九节里程碑总表一一对应
[!question] 如果某个阶段超时了怎么办? 优先级原则:核心功能(gRPC 分层调用、OSS 签名上传、Eino 对话)> 次要功能(分页搜索、数据可视化)。宁可缩减 UI 装饰细节,也要保住验收红线。
二、阶段一:环境与基础建设
[!note] 进度追踪
- T1.1 Go 1.21+ 安装并验证
- T1.2 Node.js 18+ / npm 安装并验证
- T1.3 MySQL 8.0+ 安装 + 数据库实例创建
- T1.4 OSS 平台注册 + 私有 Bucket 创建
- T1.5 Git 仓库初始化 + 目录结构建立
- T1.6
.gitignore+.env.example初始化
📋 展开查看详细任务表
2.1 详细任务清单
| 编号 | 任务 | 耗时估计 | 说明 |
|---|---|---|---|
| T1.1 | 安装并验证 Go 1.21+ | 30min | go version,配置 GOPATH 和 GOMODCACHE |
| T1.2 | 安装并验证 Node.js 18+ / npm | 30min | 后续用于两个前端项目 |
| T1.3 | 安装并验证 MySQL 8.0+ | 30min | 创建数据库实例,记录连接信息 |
| T1.4 | 注册 OSS 平台,创建私有 Bucket | 30min | 关闭匿名访问,关闭公开读权限 |
| T1.5 | 创建 Git 仓库,建立最终目录结构 | 30min | 参照 final_homework/ 规范 |
| T1.6 | 初始化 .gitignore 和 .env.example | 30min | 敏感文件排除:.env、go.sum(可选)、node_modules |
2.2 前置条件
- 无,这是第一个阶段。
2.3 验收标准
go version、node -v、mysql --version均正常输出- OSS Bucket 已创建且为私有(匿名访问已关闭)
- 本地目录结构已按
工程结构.md的顶层树创建出来 .gitignore正确排除了敏感配置文件
# 预期目录骨架
final_homework/
├── hr-frontend/
├── user-frontend/
├── web-gin-service/
├── logic-grpc-service/
└── api/
[!warning] 常见陷阱
- OSS 密钥务必写入 .env 或独立配置文件,不要硬编码到业务代码中。真实业务场景中 key 是绝对禁止提交到仓库的。
- 新建 Git 仓库后立刻添加 .gitignore,避免误提交 .env 文件。
三、阶段二:Proto 接口定义(契约先行)
[!note] 进度追踪
- T2.1
common.proto— 通用响应码、分页参数- T2.2
auth.proto— Login/RPC、Register/RPC、VerifyToken/RPC- T2.3
job.proto— CreateJob/RPC、UpdateJob/RPC、ListJobs/RPC、DeleteJob/RPC- T2.4
application.proto— SubmitApplication/RPC、ListApplications/RPC- T2.5
profile.proto— GetProfile/RPC、UpdateProfile/RPC- T2.6
resume.proto— GenOssSign/RPC、SaveResume/RPC- T2.7
chat.proto— SendChat/RPC、GetHistory/RPC- T2.8 protoc 生成 Go 代码
📋 展开查看详细任务表 + 前置条件
3.1 详细任务清单
| 编号 | 任务 | 前置依赖 | 耗时估计 |
|---|---|---|---|
| T2.1 | 定义 common.proto(通用响应码、分页参数) |
— | 30min |
| T2.2 | 定义 auth.proto(Login/RPC、Register/RPC、VerifyToken/RPC) |
T2.1 | 30min |
| T2.3 | 定义 job.proto(CreateJob/RPC、UpdateJob/RPC、ListJobs/RPC、DeleteJob/RPC) |
T2.1 | 30min |
| T2.4 | 定义 application.proto(SubmitApplication/RPC、ListApplications/RPC) |
T2.1 | 30min |
| T2.5 | 定义 profile.proto(GetProfile/RPC、UpdateProfile/RPC) |
T2.1 | 30min |
| T2.6 | 定义 resume.proto(GenOssSign/RPC、SaveResume/RPC) |
T2.1 | 30min |
| T2.7 | 定义 chat.proto(SendChat/RPC、GetHistory/RPC) |
T2.1 | 30min |
| T2.8 | protoc 生成 Go 代码 | T2.1 ~ T2.7 | 30min |
3.2 前置条件
- 阶段一已完成(T1.1 ~ T1.6)
- protoc 编译器及 go plugin 插件已安装
3.3 验收标准
protoc --go_out=... --go-grpc_out=...在api/proto/v1/下编译通过- 生成的 Go 代码存在于两个服务的
proto/gen/v1/目录 - 所有 RPC 方法签名覆盖项目需求文档中的全部接口
[!tip] Proto 设计最佳实践
- 每个 Service 对应一个 proto 文件,职责单一
- Request 和 Response 消息统一命名规范:
XxxRequest、XxxResponsecommon.proto中的CommonResponse{code, msg, data}作为所有响应的包装壳- 字段使用 tag 编号,从 1 开始递增,预留扩展空间
四、阶段三:后端双服务开发
3.1 子阶段 3A:MySQL 数据库建表
[!note] 进度追踪
- T3A.1 根据 ER 图设计 SQL DDL
- T3A.2 执行建表 + 插入测试种子数据
建表清单(对照 db.md 细化):
| 表名 | 用途 | 关键字段 |
|---|---|---|
users |
用户表 | id, username, password_hash, role, created_at |
jobs |
岗位表 | id, creator_id, title, description, status, created_at |
applications |
投递记录表 | id, job_id, candidate_id, applied_at |
profiles |
候选人档案表 | id, user_id, name, phone, education, school, experience, skills |
resumes |
简历信息表 | id, profile_id, file_key, oss_url, created_at |
chat_records |
AI对话历史表 | id, hr_id, question, ai_reply, created_at |
[!note] 思考题 为什么
creator_id放在 jobs 表中而不是单独的 job_ownership 关联表?因为本系统架构轻量化,HR 仅管理本人发布的岗位,单字段外键足以表达这种一对一的归属关系。
3.2 子阶段 3B:Logic 核心业务服务
[!note] 进度追踪
- T3B.1 gRPC Server 框架 + config 模块
- T3B.2 AuthService(注册/登录/JWT签发)
- T3B.3 JobService(岗位 CRUD + 创建者权限校验)
- T3B.4 ApplicationService(投递逻辑 + 校验拦截)
- T3B.5 ProfileService(候选人档案增改查)
- T3B.6 ResumeService + OSS signer(签名 URL 生成 + 文件头校验)
- T3B.7 ChatService(意图解析 → SQL查询 → Prompt拼接 → Eino推送 → 持久化)
- T3B.8 repository 层数据访问封装(6张表)
- T3B.9 converter 层 proto ↔ model 转换
- T3B.10 JWT 工具模块(签发 + 验证 + 角色提取)
- T3B.11 AI 模块封装(Eino Chat Engine + prompt 模板 + 意图解析器)
- T3B.12 Logic 服务独立启动测试
📋 展开查看 Logic 详细任务表
| 编号 | 任务 | 前置依赖 | 耗时估计 |
|---|---|---|---|
| T3B.1 | 搭建 gRPC Server 框架 + config 模块 | T3A.2 | 1h |
| T3B.2 | 实现 AuthService(注册/登录/JWT签发) | T3B.1 | 2h |
| T3B.3 | 实现 JobService(岗位 CRUD + 创建者权限校验) | T3B.1 | 2h |
| T3B.4 | 实现 ApplicationService(投递逻辑 + 校验拦截) | T3B.1, T3B.3 | 2h |
| T3B.5 | 实现 ProfileService(候选人档案增改查) | T3B.1 | 1.5h |
| T3B.6 | 实现 ResumeService + OSS signer(签名 URL 生成 + 文件头校验) | T3B.1 | 2h |
| T3B.7 | 实现 ChatService(意图解析 → SQL查询 → Prompt拼接 → Eino推送 → 持久化) | T3B.1, T3A.2 | 2.5h |
| T3B.8 | repository 层数据访问封装(6张表) | T3B.1 | 2h |
| T3B.9 | converter 层 proto ↔ model 转换 | T2.8, T3B.8 | 1h |
| T3B.10 | JWT 工具模块(签发 + 验证 + 角色提取) | T3B.1 | 1h |
| T3B.11 | AI 模块封装(Eino Chat Engine + prompt 模板 + 意图解析器) | T3B.1 | 2h |
| T3B.12 | Logic 服务独立启动测试 | T3B.2 ~ T3B.11 | 1h |
Logic 核心流程自查
- 用户注册时密码 bcrypt 加密存储
- 登录成功签发 JWT(包含 userId + role)
- 岗位编辑/下架时校验当前操作用户 == creator_id
- 候选人投递时拦截:未完善资料或无简历 → 返回错误码
- OSS 签名 URL 严格后缀白名单 (.pdf/.doc/.docx) + 文件头 Magic Number 校验
- 简历不经过服务端缓存,客户端直传 OSS
- AI 对话每条问答自动写入 chat_records 表
[!danger] 验收红线 Logic 服务内所有业务逻辑只能通过 gRPC Server 暴露,Web 服务不得通过同工程内部函数直连调用。如果同一个 Go module 里直接 import service 包 = 架构违规。
3.3 子阶段 3C:Web 网关服务
[!note] 进度追踪
- T3C.1 Gin 项目框架 + router 注册
- T3C.2 CORS 中间件(全局跨域处理)
- T3C.3 JWT 鉴权中间件(读取 Token + 角色校验)
- T3C.4 参数合法性校验中间件
- T3C.5 gRPC Client 连接池 + codec JSON 转换
- T3C.6 Auth Handler
- T3C.7 Job Handler
- T3C.8 Application Handler
- T3C.9 Profile Handler
- T3C.10 Resume Handler
- T3C.11 Chat Handler
- T3C.12 Web 服务独立启动测试
📋 展开查看 Web 网关详细任务表
| 编号 | 任务 | 前置依赖 | 耗时估计 |
|---|---|---|---|
| T3C.1 | 搭建 Gin 项目框架 + router 注册 | T3B.12 | 1h |
| T3C.2 | CORS 中间件(全局跨域处理) | T3C.1 | 30min |
| T3C.3 | JWT 鉴权中间件(读取 Token + 角色校验) | T3B.10 | 1h |
| T3C.4 | 参数合法性校验中间件 | T3C.1 | 1h |
| T3C.5 | gRPC Client 连接池 + codec JSON 转换 | T3B.12 | 1.5h |
| T3C.6 | Auth Handler(POST /api/auth/login, register) | T3C.5, T3B.2 | 1h |
| T3C.7 | Job Handler(CRUD 路由映射到 gRPC) | T3C.5, T3B.3 | 1.5h |
| T3C.8 | Application Handler | T3C.5, T3B.4 | 1h |
| T3C.9 | Profile Handler | T3C.5, T3B.5 | 1h |
| T3C.10 | Resume Handler(获取签名 URL 返回给前端) | T3C.5, T3B.6 | 1.5h |
| T3C.11 | Chat Handler(AI 对话转发) | T3C.5, T3B.7 | 1.5h |
| T3C.12 | Web 服务独立启动,用 curl/postman 测试 | T3C.6 ~ T3C.11 | 1h |
Web 端架构自查
- Handler 中没有任何核心业务逻辑——只有参数解析 + gRPC 调用转发
- JWT 中间件在路由注册前挂载,未携带 Token 的请求一律返回 401
- 所有 gRPC 调用都有 context deadline(防止阻塞)
- 错误码统一通过 CommonResponse.code 传递
五、阶段四:前端一日冲刺
[!tip] 技术选型确认 前端统一使用 React + Vite + TypeScript + Axios,UI 组件库推荐 Ant Design(开箱即用、减少造轮子时间)。前端只负责页面渲染和接口请求,所有业务逻辑在后端处理。
4.1 核心策略:共享基础层 + 下午独立填页
两个前端共用了同一套后端 API 契约(api/proto/v1/),因此不需要各自从零搭架子。关键压缩思路:
graph LR
subgraph Foundation["Foundation(共享基础层)"]
A1["hr-frontend 脚手架初始化"] --> A2["user-frontend 脚手架初始化"]
A2 --> A3["双方同步搭建: Router/Axios/AuthContext/布局组件"]
A3 --> A4["Ant Design 主题配置"]
end
subgraph Candidate["候选人用户端(独立完成)"]
B1["公开岗位列表"] --> B2["登录注册"] --> B3["档案表单"] --> B4["OSS直传"] --> B5["投递记录"]
end
subgraph HR["HR 管理端(独立完成)"]
C1["登录注册"] --> C2["岗位CRUD"] --> C3["候选人列表"] --> C4["AI对话窗口"]
end
A4 -.-> B1
A4 -.-> C1
| 模块 | 策略 | 复用收益 |
|---|---|---|
| Foundation | 两个项目同时跑:Vite 初始化 + Router + Axios client + AuthContext + 布局组件 | 每个文件只写一次,两份代码各自 cp -r 起步,省去重复劳动 |
| 候选人 / HR | 各自独立填充页面——候选人端 6 页 / HR 端 7 页,互不干扰 | 后端 API 已完成,前端只对接已有接口 |
4.2 Foundation 搭建
[!note] 进度追踪
- T4.AM.1 hr-frontend 脚手架初始化 (
create-vite)- T4.AM.1b user-frontend 脚手架初始化 (
create-vite)- T4.AM.2 安装依赖 (antd, icons, react-router-dom)
- T4.AM.3 路由配置 + Layout 组件(hr: Sidebar/Header, user: Navbar/Footer)
- T4.AM.4 Axios client 封装(baseURL / interceptor / token 注入)
- T4.AM.5 AuthContext(useContext 管理 JWT,isAuthenticated / role 状态)
- T4.AM.6 Ant Design 全局主题 & 全局 CSS
📋 展开查看详细任务表
| 编号 | 任务 | 耗时 | 说明 |
|---|---|---|---|
| T4.AM.1 | npx create-vite hr-frontend --template react-ts |
5min | 同步创建两个项目 |
| T4.AM.1b | npx create-vite user-frontend --template react-ts |
5min | — |
| T4.AM.2 | 安装依赖 (antd, @ant-design/icons, react-router-dom) |
10min | 两端同步操作 |
| T4.AM.3 | 路由配置 + Layout 组件(hr: Sidebar/Header, user: Navbar/Footer) | 45min | 各自按风格定制 |
| T4.AM.4 | Axios client 封装(baseURL / interceptor / token 注入) | 30min | 模板几乎相同,改 baseURL 即可 |
| T4.AM.5 | AuthContext(useContext 管理 JWT,isAuthenticated / role 状态) | 30min | 两端复制 + 角色名差异 |
| T4.AM.6 | Ant Design 全局主题 & 全局 CSS | 20min | hr 用深色主题, user 用浅色主题 |
AM 成果验证
- 两个
npm run dev均能启动,显示空白布局框架 - 路由切换正常,Axios 请求可发送到
http://localhost:8080/api
[!note] 思考题 为什么 AuthContext 只需要改"角色名"就可以复用?因为前后端的鉴权模型是一致的——都靠 JWT 中的
role字段区分 HR/候选人。这个设计体现了"接口契约驱动开发"的思想:proto 定义了统一的用户身份模型,前端只需消费它。
4.3 候选人用户端
[!note] 进度追踪
- T4.U.1 HomePage — 公开岗位列表(免登录浏览)
- T4.U.2 LoginPage + RegisterPage — 表单 + 提交到
/api/auth/login- T4.U.3 JobDetailPage — 岗位详情 + 条件渲染投递按钮
- T4.U.4 SetupProfilePage — 结构化档案表单
- T4.U.5 ResumeUploadPage — OSS 签名 URL 直传组件
- T4.U.6 ApplicationPage + WarningModal — 投递记录 + 拦截弹窗
📋 展开查看详细任务表
| 编号 | 任务 | 前置依赖 | 耗时 | 页面数 |
|---|---|---|---|---|
| T4.U.1 | HomePage:调用 /api/jobs 展示岗位卡片列表(免登录) |
T4.AM | 40min | 1 |
| T4.U.2 | LoginPage + RegisterPage:表单 + 提交到 /api/auth/login |
T4.AM | 40min | 2 |
| T4.U.3 | JobDetailPage:岗位详情 + 条件渲染投递按钮(已登录 && 有档案 && 有简历) | T4.U.1 | 40min | 1 |
| T4.U.4 | SetupProfilePage:Ant Design Form 表格单(姓名/电话/学历/院校/经历/技能) | T4.AM | 30min | 1 |
| T4.U.5 | ResumeUploadPage:选择文件 → 调 /api/resume/upload 拿签名 URL → 客户端 PUT 到 OSS |
T4.AM, T3C.10 | 50min | 1 |
| T4.U.6 | ApplicationPage + WarningModal:投递记录 + 拦截弹窗 | T4.AM | 30min | 1+1 |
候选人端关键交互逻辑
flowchart TD
A["游客打开 /user/"] --> B["查看岗位列表"]
B --> C["点击投递按钮"]
C --> D{"是否已登录?"}
D -->|"否"| E["跳转 /user/login"]
D -->|"是"| F{"是否完善档案?"}
F -->|"否"| G["提示跳转到 /user/profile/setup"]
F -->|"是"| H{"是否有合规简历?"}
H -->|"否"| I["提示 /user/resume/upload<br/>PDF/DOC/DOCX 格式校验"]
H -->|"是"| J["发送 POST /api/applications"]
J --> K["投递成功 ✅"]
4.4 HR 管理端
[!note] 进度追踪
- T4.H.1 LoginPage + RegisterPage(HR 账号体系)
- T4.H.2 Dashboard/HomePage — 工作台概览
- T4.H.3 JobListPage — 本人岗位列表(分页 + 搜索)
- T4.H.4 JobEditPage — 新建/编辑岗位表单
- T4.H.5 CandidatePage — 岗位下候选人列表
- T4.H.6 ProfileViewPage — 候选人结构化档案只读展示
- T4.H.7 ChatPage — AI 智能对话窗口
📋 展开查看详细任务表
| 编号 | 任务 | 前置依赖 | 耗时 | 页面数 |
|---|---|---|---|---|
| T4.H.1 | LoginPage + RegisterPage(HR 账号体系) | T4.AM | 30min | 2 |
| T4.H.2 | Dashboard/HomePage:工作台概览(数据卡片) | T4.AM | 30min | 1 |
| T4.H.3 | JobListPage:本人岗位列表(Ant Design Table + 分页 + 搜索) | T4.AM | 50min | 1 |
| T4.H.4 | JobEditPage:新建/编辑岗位表单 | T4.AM | 40min | 1 |
| T4.H.5 | CandidatePage:岗位下候选人列表 + 跳转档案详情页 | T4.AM | 50min | 1 |
| T4.H.6 | ProfileViewPage:候选人结构化档案只读展示 | T4.H.5 | 30min | 1 |
| T4.H.7 | ChatPage:AI 智能对话窗口(消息气泡 + 历史加载) | T4.AM, T3C.11 | 80min | 1 |
ChatPage 核心交互时序
sequenceDiagram
participant P as ChatPage
participant S as ChatContext
participant A as Axios
participant W as Web-Gin
Note over P,W: 页面加载时自动拉历史
P->>S: useEffect 触发
S->>A: GET /api/chat/history
A->>W: 带 JWT
W-->>A: 历史消息数组
A-->>S: state.push(...records)
S-->>P: 渲染对话流
Note over P,W: 用户输入新提问
P->>A: POST /api/chat/messages {question}
A->>W: 经 gRPC 转发到 Logic
W-->>A: {reply, records[]}
A-->>S: 追加 AI 回复
S-->>P: 自动滚动到底部
4.5 收尾
[!note] 进度追踪
- T4.Z.1 两端
npm run build验证无编译错误- T4.Z.2 检查 .env 是否正确指向后端地址
- T4.Z.3 git add + commit 本阶段变更
[!warning] 前端权限边界 前端只做视觉展示和跳转控制。真正的权限校验必须发生在后端。例如:即使前端显示了投递按钮,后端也应该再次校验候选人是否满足条件;不应依赖前端隐藏按钮来保护安全。验收时评委可能会故意绕过前端直接调接口测试。
[!tip] 加速技巧速查
- Ant Design 的
Form+Input+Select可以直接粘贴文档示例修改- 岗位列表复用同一个
JobCard组件(候选人端和 HR 端都可以引用)- Axios interceptor 写一次就能用在两个项目中
- 如果某个页面实在写不完,先用
console.log占位,确保核心功能优先上线
六、阶段五:前后端联调与自测
[!note] 进度追踪
- T5.1 全链路跑通:注册 → 登录 → 岗位发布 → 浏览
- T5.2 OSS 签名上传端到端测试(候选人端直传)
- T5.3 AI 对话完整流程测试(提问 → 数据查询 → 回答 → 历史加载)
- T5.4 权限隔离测试(非创建者操作他人岗位应被拒绝)
- T5.5 文件格式拦截测试(上传图片/TXT应为非法)
- T5.6 游客 vs 登录态功能边界测试
- T5.7 Bug 修复与体验优化
6.1 详细任务清单
| 编号 | 任务 | 前置依赖 | 耗时估计 |
|---|---|---|---|
| T5.1 | 全链路跑通:注册 → 登录 → 岗位发布 → 浏览 | T4.Z.3 | 2h |
| T5.2 | OSS 签名上传端到端测试(候选人端直传) | T5.1 | 2h |
| T5.3 | AI 对话完整流程测试(提问 → 数据查询 → 回答 → 历史加载) | T5.1 | 2h |
| T5.4 | 权限隔离测试(非创建者操作他人岗位应被拒绝) | T5.1 | 1h |
| T5.5 | 文件格式拦截测试(上传图片/TXT应为非法) | T5.2 | 1h |
| T5.6 | 游客 vs 登录态功能边界测试 | T5.1 | 1h |
| T5.7 | Bug 修复与体验优化 | T5.1 ~ T5.6 | 2h |
6.2 验收 Checklist
对照以下每一项逐项打勾:
- gRPC 分层:Web 与 Logic 之间全部通过 gRPC 调用,无同工程内部函数调用
- OSS 签名 URL:文件不落地本地,客户端直传 OSS
- Eino 框架:使用了 Eino 封装的 Chat,非裸写 HTTP
- JWT 鉴权:HR 只能管理自己发布的岗位,候选人未完善资料不可投递
- AI 对话持久化:每条问答对入 MySQL,刷新页面自动加载历史上下文
- 双端前端独立运行:hr-frontend 和 user-frontend 各自
npm run dev均可启动 - 四个源码目录完整、三个文档文件齐全
七、阶段六:视频录制与提交
[!note] 进度追踪
- T6.1 撰写 answer.md(拓展设计方案:OpenClaw/Hermes 集成思路)
- T6.2 完善 README.md(启动部署指南 + 项目亮点)
- T6.3 完善 api.md(前后端接口说明)
- T6.4 完善 db.md(数据库设计文档补充)
- T6.5 整理代码仓库(检查 .gitignore、清理临时文件)
- T6.6 录制演示视频(原生实操、口述两大核心技术点)
- T6.7 提交至 KDoc 表单
7.1 详细任务清单
| 编号 | 任务 | 耗时估计 |
|---|---|---|
| T6.1 | 撰写 answer.md(拓展设计方案:OpenClaw/Hermes 集成思路) | 2h |
| T6.2 | 完善 README.md(启动部署指南 + 项目亮点) | 1.5h |
| T6.3 | 完善 api.md(前后端接口说明) | 1.5h |
| T6.4 | 完善 db.md(数据库设计文档补充) | 1h |
| T6.5 | 整理代码仓库(检查 .gitignore、清理临时文件) | 1h |
| T6.6 | 录制演示视频(原生实操、口述两大核心技术点) | 2h |
| T6.7 | 提交至 KDoc 表单 | 30min |
7.2 视频录制脚本大纲
| 时间段 | 内容 | 口述要点 |
|---|---|---|
| 0:00-0:30 | 开场 + 服务启动演示 | "我现在依次启动 Logic 服务和 Web 网关服务..." |
| 0:30-2:00 | 候选人端操作流程 | "候选人浏览岗位、注册、完善档案、上传简历、投递..." |
| 2:00-3:00 | 口述核心技术点①:gRPC 两层架构 | "Web 网关接收 HTTP 请求后,通过 gRPC 远程调用 Logic 服务...这两个是独立进程..." |
| 3:00-4:00 | 口述核心技术点②:OSS 签名 URL | "简历文件先获取签名URL,然后客户端直传 OSS,服务端零缓存..." |
| 4:00-5:30 | HR 管理端操作流程 | "HR 登录、发布岗位、查看候选人、AI 对话..." |
| 5:30-6:30 | AI 对话演示 | "输入自然语言提问,后端查询 MySQL 真实数据,通过 Eino 推送大模型..." |
| 6:30-7:00 | 总结与结尾 | 简要说明个人开发收获和优化方向 |
[!important] 视频硬性要求
- 禁止剪辑拼接:一次录完,保证画面真实
- 全程配语音解说:不能无声黑屏
- 必录两大技术点口述:gRPC 分层调用逻辑、OSS 签名 URL 安全上传下载
- 文件命名:
姓名_学号_全栈大作业.mp4
八、风险识别与应对
| 风险 | 影响范围 | 概率 | 应对措施 |
|---|---|---|---|
| OSS 平台注册审核慢 | 整个项目 | 中 | 提前注册,使用 MinIO 本地替代方案作为兜底 |
| Eino 框架学习成本超预期 | AI 对话模块 | 中 | 官方文档优先,只使用基础 Chat 组件,不做复杂编排 |
| Protobuf 字段频繁变更 | 前后端同步 | 高 | Proto 先行、冻结接口后再写业务代码;做好注释 |
| gRPC 调试困难 | 后端通信 | 中 | 启用 grpcurl 命令行工具进行 RPC 调用调试 |
| 前端样式适配耗时过长 | UI 呈现 | 中 | 使用现成 UI 组件库(Ant Design),不自研 CSS |
| JWT Token 过期处理遗漏 | 用户体验 | 低 | 初期可不实现自动刷新,手动重新登录即可 |
九、里程碑检查点
[!note] 里程碑进度追踪 点击以下复选框标记里程碑完成情况:
- M0 — 环境就绪
- M1 — Proto 冻结
- M2 — 后端可独立运行
- M3 — 双端前端完成
- M4 — 全链路联调通过
- M5 — 视频已录制
- M6 — 正式提交
graph LR
M0["环境就绪<br/>阶段一"] --> M1["Proto 冻结<br/>阶段二"]
M1 --> M2["后端可独立运行<br/>阶段三"]
M2 --> M3["双端前端完成<br/>阶段四"]
M3 --> M4["全链路联调通过<br/>阶段五"]
M4 --> M5["视频已录制<br/>待提交"]
M5 --> M6["正式提交<br/>KDoc表单"]
classDef done fill:#c8e6c9;
classDef current fill:#fff9c4;
classDef future fill:#eceff1;
class M0,M1,M2,M3,M4 done;
class M5 current;
class M6 future;