2026-05-09 20:29:11 +08:00
|
|
|
|
# 大作业·工程结构设计
|
|
|
|
|
|
|
|
|
|
|
|
> 基于《思维导图》与《大作业项目要求》,前端技术栈统一采用 **React + Vite**,后端为 Go(Gin + gRPC)。
|
|
|
|
|
|
|
|
|
|
|
|
## 一、仓库根目录结构(`final_homework/`)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
final_homework/
|
|
|
|
|
|
├── hr-frontend/ # HR管理端前端(React + Vite)
|
|
|
|
|
|
├── user-frontend/ # 候选人用户端前端(React + Vite)
|
|
|
|
|
|
├── web-gin-service/ # Gin Web网关服务
|
|
|
|
|
|
├── logic-grpc-service/ # gRPC核心业务服务
|
2026-05-10 21:47:14 +08:00
|
|
|
|
├── proto/ # Protobuf 定义
|
|
|
|
|
|
│ └── v1/
|
|
|
|
|
|
│ ├── auth.proto # 认证相关
|
|
|
|
|
|
│ ├── job.proto # 岗位相关
|
|
|
|
|
|
│ ├── application.proto # 投递相关
|
|
|
|
|
|
│ ├── profile.proto # 候选人档案
|
|
|
|
|
|
│ ├── resume.proto # 简历/OSS上传
|
|
|
|
|
|
│ └── chat.proto # AI对话
|
|
|
|
|
|
├── api.md # 前后端接口说明文档
|
|
|
|
|
|
├── db.md # 数据库设计文档
|
2026-05-09 20:29:11 +08:00
|
|
|
|
├── README.md # 启动部署指南 + 项目亮点
|
|
|
|
|
|
└── answer.md # 拓展设计方案(OpenClaw/Hermes集成思路)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 二、HR管理端前端(`hr-frontend/`)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
hr-frontend/
|
|
|
|
|
|
├── index.html
|
|
|
|
|
|
├── package.json
|
|
|
|
|
|
├── vite.config.ts # Vite 配置,配置代理到 web-gin-service
|
|
|
|
|
|
├── tsconfig.json
|
|
|
|
|
|
├── .env # 前端环境变量(API_BASE_URL 等,不进 Git)
|
|
|
|
|
|
├── .gitignore
|
|
|
|
|
|
├── public/
|
|
|
|
|
|
│ └── favicon.ico
|
|
|
|
|
|
├── src/
|
|
|
|
|
|
│ ├── main.tsx # 入口文件
|
|
|
|
|
|
│ ├── App.tsx # 路由入口 + 权限守卫
|
|
|
|
|
|
│ ├── vite-env.d.ts
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── styles/ # 全局样式
|
|
|
|
|
|
│ │ ├── global.css
|
|
|
|
|
|
│ │ └── variables.css
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── router/ # 路由配置
|
|
|
|
|
|
│ │ └── index.tsx # 独立路由页面:/hr/*
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── api/ # Axios 请求封装
|
|
|
|
|
|
│ │ ├── client.ts # axios 实例 + baseURL / interceptor
|
|
|
|
|
|
│ │ ├── auth.ts # 登录/注册接口
|
|
|
|
|
|
│ │ ├── job.ts # 岗位 CRUD 接口
|
|
|
|
|
|
│ │ ├── application.ts # 投递列表接口
|
|
|
|
|
|
│ │ ├── profile.ts # 候选人档案接口
|
|
|
|
|
|
│ │ ├── resume.ts # 简历信息接口
|
|
|
|
|
|
│ │ └── chat.ts # AI对话接口
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── stores/ # 状态管理(useState + Context 即可)
|
|
|
|
|
|
│ │ ├── AuthContext.tsx # 登录态 + JWT Token 上下文
|
|
|
|
|
|
│ │ └── ChatContext.tsx # AI对话消息历史上下文
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── pages/ # 页面组件
|
|
|
|
|
|
│ │ ├── LoginPage.tsx # HR登录页
|
|
|
|
|
|
│ │ ├── RegisterPage.tsx # HR注册页
|
|
|
|
|
|
│ │ └── dashboard/ # 后台主页面(登录后可见)
|
|
|
|
|
|
│ │ ├── DashboardLayout.tsx # 布局框架(侧边栏 + 顶栏)
|
|
|
|
|
|
│ │ ├── HomePage.tsx # 工作台概览
|
|
|
|
|
|
│ │ ├── JobListPage.tsx # 岗位列表(分页、搜索)
|
|
|
|
|
|
│ │ ├── JobEditPage.tsx # 新建/编辑岗位表单
|
|
|
|
|
|
│ │ ├── CandidatePage.tsx # 岗位下候选人列表(含投递状态)
|
|
|
|
|
|
│ │ ├── ProfileViewPage.tsx # 候选人结构化档案详情页
|
|
|
|
|
|
│ │ └── ChatPage.tsx # AI智能对话窗口(常驻)
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── components/ # 公共组件
|
|
|
|
|
|
│ │ ├── Layout/
|
|
|
|
|
|
│ │ │ ├── Sidebar.tsx # 左侧导航栏
|
|
|
|
|
|
│ │ │ └── Header.tsx # 顶部栏(显示当前HR头像/退出)
|
|
|
|
|
|
│ │ ├── Common/
|
|
|
|
|
|
│ │ │ ├── LoadingSpinner.tsx
|
|
|
|
|
|
│ │ │ ├── EmptyState.tsx
|
|
|
|
|
|
│ │ │ └── PageHeader.tsx
|
|
|
|
|
|
│ │ └── UI/ # 基础 UI 组件(可用 Ant Design / Shadcn)
|
|
|
|
|
|
│ │ ├── Table.tsx
|
|
|
|
|
|
│ │ ├── Form.tsx
|
|
|
|
|
|
│ │ ├── Modal.tsx
|
|
|
|
|
|
│ │ └── Tag.tsx
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── types/ # TypeScript 类型定义
|
|
|
|
|
|
│ │ ├── auth.ts
|
|
|
|
|
|
│ │ ├── job.ts
|
|
|
|
|
|
│ │ ├── application.ts
|
|
|
|
|
|
│ │ ├── profile.ts
|
|
|
|
|
|
│ │ ├── resume.ts
|
|
|
|
|
|
│ │ └── chat.ts
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ └── utils/ # 工具函数
|
|
|
|
|
|
│ ├── request.ts # 通用请求拦截(自动带 Token)
|
|
|
|
|
|
│ └── format.ts # 日期/数字格式化工具
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### HR端关键路由
|
|
|
|
|
|
|
|
|
|
|
|
| 路径 | 页面 | 说明 | 鉴权 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `/hr/login` | 登录页 | HR账号密码登录 | 访客可访问 |
|
|
|
|
|
|
| `/hr/register` | 注册页 | HR账号注册 | 访客可访问 |
|
|
|
|
|
|
| `/hr/dashboard` | 工作台 | 数据概览 | 必须JWT有效 |
|
|
|
|
|
|
| `/hr/dashboard/jobs` | 岗位列表 | 本人发布的岗位 | 必须JWT有效 |
|
|
|
|
|
|
| `/hr/dashboard/jobs/create` | 新建岗位 | 表单页 | 必须JWT有效 |
|
|
|
|
|
|
| `/hr/dashboard/jobs/:id/edit` | 编辑岗位 | 回显+修改 | 必须是创建者 |
|
|
|
|
|
|
| `/hr/dashboard/candidates` | 候选人列表 | 岗位下投递者 | 必须JWT有效 |
|
|
|
|
|
|
| `/hr/dashboard/candidates/:id/profile` | 档案详情 | 结构化资料 | 必须JWT有效 |
|
|
|
|
|
|
| `/hr/dashboard/chat` | AI对话 | 智能问答窗口 | 必须JWT有效 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 三、候选人用户端前端(`user-frontend/`)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
user-frontend/
|
|
|
|
|
|
├── index.html
|
|
|
|
|
|
├── package.json
|
|
|
|
|
|
├── vite.config.ts
|
|
|
|
|
|
├── tsconfig.json
|
|
|
|
|
|
├── .env
|
|
|
|
|
|
├── .gitignore
|
|
|
|
|
|
├── public/
|
|
|
|
|
|
│ └── favicon.ico
|
|
|
|
|
|
├── src/
|
|
|
|
|
|
│ ├── main.tsx
|
|
|
|
|
|
│ ├── App.tsx # 路由入口 + 游客/已登录态切换
|
|
|
|
|
|
│ ├── vite-env.d.ts
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── styles/
|
|
|
|
|
|
│ │ ├── global.css
|
|
|
|
|
|
│ │ └── variables.css
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── router/
|
|
|
|
|
|
│ │ └── index.tsx # 独立路由页面:/user/*
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── api/ # Axios 请求封装(同hr-frontend模式)
|
|
|
|
|
|
│ │ ├── client.ts
|
|
|
|
|
|
│ │ ├── auth.ts
|
|
|
|
|
|
│ │ ├── job.ts
|
|
|
|
|
|
│ │ ├── profile.ts
|
|
|
|
|
|
│ │ ├── resume.ts
|
|
|
|
|
|
│ │ └── application.ts
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── stores/
|
|
|
|
|
|
│ │ └── AuthContext.tsx # 登录态 + Token 上下文
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── pages/
|
|
|
|
|
|
│ │ ├── HomePage.tsx # 首页:公开岗位列表(游客可见)
|
|
|
|
|
|
│ │ ├── LoginPage.tsx # 候选人登录页
|
|
|
|
|
|
│ │ ├── RegisterPage.tsx # 候选人注册页(强校验)
|
|
|
|
|
|
│ │ ├── JobDetailPage.tsx # 岗位详情(含投递按钮)
|
|
|
|
|
|
│ │ ├── SetupProfilePage.tsx # 引导完善档案
|
|
|
|
|
|
│ │ ├── ResumeUploadPage.tsx # 简历上传页(OSS签名URL直传)
|
|
|
|
|
|
│ │ └── ApplicationPage.tsx # 我的投递记录
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── components/
|
|
|
|
|
|
│ │ ├── Layout/
|
|
|
|
|
|
│ │ │ ├── Navbar.tsx # 顶栏导航(游客/已登录不同UI)
|
|
|
|
|
|
│ │ │ └── Footer.tsx
|
|
|
|
|
|
│ │ ├── JobCard.tsx # 岗位卡片组件(复用)
|
|
|
|
|
|
│ │ ├── JobList.tsx # 岗位列表组件
|
|
|
|
|
|
│ │ ├── UploadProgress.tsx # 简历上传进度条
|
|
|
|
|
|
│ │ ├── WarningModal.tsx # 拦截弹窗(未完善资料/无简历)
|
|
|
|
|
|
│ │ └── Common/
|
|
|
|
|
|
│ │ ├── EmptyState.tsx
|
|
|
|
|
|
│ │ └── LoadingSpinner.tsx
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── types/
|
|
|
|
|
|
│ │ ├── auth.ts
|
|
|
|
|
|
│ │ ├── job.ts
|
|
|
|
|
|
│ │ ├── profile.ts
|
|
|
|
|
|
│ │ ├── resume.ts
|
|
|
|
|
|
│ │ └── application.ts
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ └── utils/
|
|
|
|
|
|
│ ├── request.ts
|
|
|
|
|
|
│ └── format.ts
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 候选人端关键路由
|
|
|
|
|
|
|
|
|
|
|
|
| 路径 | 页面 | 说明 | 鉴权 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `/user/` | 首页 | 公开岗位列表 | 免登录 |
|
|
|
|
|
|
| `/user/login` | 登录页 | 候选人登录 | 访客可访问 |
|
|
|
|
|
|
| `/user/register` | 注册页 | 候选人注册(强校验) | 访客可访问 |
|
|
|
|
|
|
| `/user/job/:id` | 岗位详情 | 查看岗位 + 投递 | 投递需登录 |
|
|
|
|
|
|
| `/user/profile/setup` | 完善档案 | 必填字段表单 | 必须登录 |
|
|
|
|
|
|
| `/user/resume/upload` | 简历上传 | OSS签名URL直传 | 必须登录 |
|
|
|
|
|
|
| `/user/applications` | 我的投递 | 投递记录列表 | 必须登录 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 四、Web 网关服务(`web-gin-service/`)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
web-gin-service/
|
|
|
|
|
|
├── go.mod
|
|
|
|
|
|
├── go.sum
|
|
|
|
|
|
├── main.go # 服务入口,初始化 Gin Router + gRPC dial
|
|
|
|
|
|
├── config/
|
|
|
|
|
|
│ ├── config.go # 配置加载(Viper / env)
|
|
|
|
|
|
│ └── .env.example # 环境变量模板
|
|
|
|
|
|
├── internal/
|
|
|
|
|
|
│ ├── handler/ # HTTP Handler(仅做参数解析 + gRPC调用转发)
|
|
|
|
|
|
│ │ ├── auth_handler.go # POST /api/auth/login, /api/auth/register
|
|
|
|
|
|
│ │ ├── job_handler.go # POST/GET/PUT/DELETE /api/jobs
|
|
|
|
|
|
│ │ ├── application_handler.go
|
|
|
|
|
|
│ │ ├── profile_handler.go
|
|
|
|
|
|
│ │ ├── resume_handler.go # POST /api/resume/upload → 调gRPC取签名URL
|
|
|
|
|
|
│ │ └── chat_handler.go # POST /api/chat/messages
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── middleware/ # 中间件
|
|
|
|
|
|
│ │ ├── cors.go # 全局跨域处理
|
|
|
|
|
|
│ │ ├── jwt_auth.go # JWT 统一鉴权(角色校验)
|
|
|
|
|
|
│ │ └── validate.go # 请求参数合法性校验
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── transport/ # gRPC 客户端(连接 logic-grpc-service)
|
|
|
|
|
|
│ │ ├── grpc_client.go # 统一 gRPC client 池
|
|
|
|
|
|
│ │ └── codec.go # proto message ↔ HTTP JSON 转换
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ └── router/ # 路由注册
|
|
|
|
|
|
│ └── router.go # gin.Engine 路由绑定
|
|
|
|
|
|
├── proto/ # 引用的 proto 文件只读拷贝
|
|
|
|
|
|
│ └── gen/
|
|
|
|
|
|
│ └── v1/
|
|
|
|
|
|
└── README.md # Web服务自述
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Web端 API 路由清单
|
|
|
|
|
|
|
|
|
|
|
|
| 方法 | 路径 | 说明 | 鉴权 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| POST | `/api/auth/login` | 登录,返回 JWT | 无 |
|
|
|
|
|
|
| POST | `/api/auth/register` | 注册 | 无 |
|
|
|
|
|
|
| GET | `/api/jobs` | 岗位列表(分页) | 无 |
|
|
|
|
|
|
| GET | `/api/jobs/:id` | 岗位详情 | 无 |
|
|
|
|
|
|
| POST | `/api/jobs` | 发布岗位 | HR |
|
|
|
|
|
|
| PUT | `/api/jobs/:id` | 编辑岗位 | HR(本人) |
|
|
|
|
|
|
| DELETE | `/api/jobs/:id` | 下架岗位 | HR(本人) |
|
|
|
|
|
|
| GET | `/api/jobs/:id/applications` | 岗位下候选人列表 | HR |
|
|
|
|
|
|
| GET | `/api/profile/:userId` | 查看候选人档案 | HR |
|
|
|
|
|
|
| POST | `/api/resume/upload` | 获取OSS签名URL | 候选人 |
|
|
|
|
|
|
| POST | `/api/profile` | 更新个人档案 | 候选人 |
|
|
|
|
|
|
| POST | `/api/applications` | 投递简历 | 候选人 |
|
|
|
|
|
|
| POST | `/api/chat/messages` | AI对话发送 | HR |
|
|
|
|
|
|
| GET | `/api/chat/history` | 加载对话历史 | HR |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 五、Logic 核心业务服务(`logic-grpc-service/`)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
logic-grpc-service/
|
|
|
|
|
|
├── go.mod
|
|
|
|
|
|
├── go.sum
|
|
|
|
|
|
├── main.go # 服务入口,注册 gRPC Server
|
|
|
|
|
|
├── config/
|
|
|
|
|
|
│ ├── config.go
|
|
|
|
|
|
│ └── .env.example
|
|
|
|
|
|
├── internal/
|
|
|
|
|
|
│ ├── server/ # gRPC Server 实现
|
|
|
|
|
|
│ │ ├── auth_service.go # 用户注册/登录/鉴权
|
|
|
|
|
|
│ │ ├── job_service.go # 岗位 CRUD(含创建者权限校验)
|
|
|
|
|
|
│ │ ├── application_service.go # 投递逻辑
|
|
|
|
|
|
│ │ ├── profile_service.go # 候选人档案增改查
|
|
|
|
|
|
│ │ ├── resume_service.go # OSS签名URL生成
|
|
|
|
|
|
│ │ └── chat_service.go # AI对话 + 历史持久化
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── model/ # 数据模型(ORM struct)
|
|
|
|
|
|
│ │ ├── user.go
|
|
|
|
|
|
│ │ ├── job.go
|
|
|
|
|
|
│ │ ├── application.go
|
|
|
|
|
|
│ │ ├── profile.go
|
|
|
|
|
|
│ │ └── chat_record.go
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── repository/ # 数据访问层(MySQL操作)
|
|
|
|
|
|
│ │ ├── user_repo.go
|
|
|
|
|
|
│ │ ├── job_repo.go
|
|
|
|
|
|
│ │ ├── application_repo.go
|
|
|
|
|
|
│ │ ├── profile_repo.go
|
|
|
|
|
|
│ │ ├── resume_repo.go
|
|
|
|
|
|
│ │ └── chat_record_repo.go
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── oss/ # OSS客户端封装
|
|
|
|
|
|
│ │ ├── client.go # MinIO / 阿里云 OSS SDK 初始化
|
|
|
|
|
|
│ │ └── signer.go # 签名URL生成 + 文件头白名单校验
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── ai/ # Eino AI 封装
|
|
|
|
|
|
│ │ ├── engine.go # Eino Chat 引擎初始化
|
|
|
|
|
|
│ │ ├── prompt.go # 提示词模板 + 业务上下文拼接
|
|
|
|
|
|
│ │ └── query_parser.go # 自然语言意图解析 → SQL查询条件
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├── jwt/ # JWT 工具
|
|
|
|
|
|
│ │ └── jwt.go # 签发 + 验证 + 角色提取
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ └── converter/ # DTO 转换
|
|
|
|
|
|
│ └── proto_converter.go # proto message ↔ model struct
|
|
|
|
|
|
├── proto/
|
|
|
|
|
|
│ └── gen/
|
|
|
|
|
|
│ └── v1/
|
|
|
|
|
|
└── README.md
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-05-10 21:47:14 +08:00
|
|
|
|
## 六、Protobuf 定义(`proto/v1/`)
|
2026-05-09 20:29:11 +08:00
|
|
|
|
|
2026-05-10 21:47:14 +08:00
|
|
|
|
所有 proto 文件统一放在 `proto/v1/`,供 `web-gin-service` 和 `logic-grpc-service` 共同引用。
|
2026-05-09 20:29:11 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
2026-05-10 21:47:14 +08:00
|
|
|
|
proto/v1/
|
2026-05-09 20:29:11 +08:00
|
|
|
|
├── common.proto # 公共定义(Response code/msg, Pagination)
|
|
|
|
|
|
├── auth.proto # AuthService: Login, Register, VerifyToken
|
|
|
|
|
|
├── job.proto # JobService: CreateJob, UpdateJob, ListJobs, DeleteJob
|
|
|
|
|
|
├── application.proto # ApplicationService: SubmitApplication, ListApplications
|
|
|
|
|
|
├── profile.proto # ProfileService: GetProfile, UpdateProfile
|
|
|
|
|
|
├── resume.proto # ResumeService: GenOssSign, GetResumeInfo
|
|
|
|
|
|
└── chat.proto # ChatService: SendChat, GetHistory
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 七、数据流总览
|
|
|
|
|
|
|
|
|
|
|
|
### 7.1 核心架构调用链
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
flowchart LR
|
|
|
|
|
|
subgraph FE ["前端层(React + Vite)"]
|
|
|
|
|
|
HR["HR管理端<br/>hr-frontend"]
|
|
|
|
|
|
User["候选人用户端<br/>user-frontend"]
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
subgraph GW ["Web网关层(Gin)<br/>web-gin-service"]
|
|
|
|
|
|
RH["Auth Handler"]
|
|
|
|
|
|
JH["Job Handler"]
|
|
|
|
|
|
AH["Application Handler"]
|
|
|
|
|
|
PH["Profile Handler"]
|
|
|
|
|
|
RRH["Resume Handler"]
|
|
|
|
|
|
CH["Chat Handler"]
|
|
|
|
|
|
JWT["JWT 鉴权中间件"]
|
|
|
|
|
|
CORS["CORS 中间件"]
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
subgraph RPC ["Logic业务层(gRPC)<br/>logic-grpc-service"]
|
|
|
|
|
|
US["AuthService"]
|
|
|
|
|
|
JS["JobService"]
|
|
|
|
|
|
AS["ApplicationService"]
|
|
|
|
|
|
PS["ProfileService"]
|
|
|
|
|
|
RSS["ResumeService"]
|
|
|
|
|
|
CS["ChatService"]
|
|
|
|
|
|
JWT_L["JWT 验证"]
|
|
|
|
|
|
DB["MySQL Repository"]
|
|
|
|
|
|
OSS_S["OSS Signer"]
|
|
|
|
|
|
AI["Eino Chat Engine"]
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
subgraph Storage ["存储 & 外部服务"]
|
|
|
|
|
|
M[(MySQL)]
|
|
|
|
|
|
O[私有 OSS Bucket]
|
|
|
|
|
|
LLM[大语言模型]
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
%% HR 请求链路
|
|
|
|
|
|
HR -->|"HTTP /api/*"| CORS
|
|
|
|
|
|
CORS --> JWT
|
|
|
|
|
|
JWT --> RH
|
|
|
|
|
|
JWT --> JH
|
|
|
|
|
|
JWT --> CH
|
|
|
|
|
|
|
|
|
|
|
|
%% 候选人 请求链路
|
|
|
|
|
|
User -->|"HTTP /api/*"| CORS
|
|
|
|
|
|
|
|
|
|
|
|
%% gRPC 跨服务调用
|
|
|
|
|
|
RH -->|"gRPC Login/RPC"| US
|
|
|
|
|
|
JH -->|"gRPC Job CRUD"| JS
|
|
|
|
|
|
CH -->|"gRPC SendChat/History"| CS
|
|
|
|
|
|
RRH -->|"gRPC GenOssSign"| RSS
|
|
|
|
|
|
|
|
|
|
|
|
%% Handler 转发候选人请求
|
|
|
|
|
|
JWT --> RRH
|
|
|
|
|
|
JWT --> PH
|
|
|
|
|
|
JWT --> AH
|
|
|
|
|
|
|
|
|
|
|
|
PH -->|"gRPC Get/UpdateProfile"| PS
|
|
|
|
|
|
AH -->|"gRPC SubmitApplication"| AS
|
|
|
|
|
|
|
|
|
|
|
|
%% Backend → Storage
|
|
|
|
|
|
US --> M
|
|
|
|
|
|
JS --> M
|
|
|
|
|
|
AS --> M
|
|
|
|
|
|
PS --> M
|
|
|
|
|
|
DB --> M
|
|
|
|
|
|
CS --> DB
|
|
|
|
|
|
RSS --> O
|
|
|
|
|
|
CS --> AI
|
|
|
|
|
|
AI --> LLM
|
|
|
|
|
|
|
|
|
|
|
|
classDef frontNode fill:#e3f2fd,stroke:#1565c0;
|
|
|
|
|
|
classDef gwNode fill:#fff3e0,stroke:#e65100;
|
|
|
|
|
|
classDef logicNode fill:#e8f5e9,stroke:#2e7d32;
|
|
|
|
|
|
classDef storeNode fill:#fce4ec,stroke:#c62828;
|
|
|
|
|
|
|
|
|
|
|
|
class HR,User frontNode;
|
|
|
|
|
|
class CORS,RH,JH,AH,PH,RRH,CH gwNode;
|
|
|
|
|
|
class US,JS,AS,PS,RSS,CS,JWT_L,DB,OSS_S,AI logicNode;
|
|
|
|
|
|
class M,O,LLM storeNode;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 7.2 简历直传流程(签名 URL 方案)
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant C as CandidateFrontend
|
|
|
|
|
|
participant W as Web-Gin
|
|
|
|
|
|
participant R as ResumeService (gRPC)
|
|
|
|
|
|
participant S as Storage (Private OSS)
|
|
|
|
|
|
|
|
|
|
|
|
Note over C,S: 第一阶段:获取上传凭证
|
|
|
|
|
|
|
|
|
|
|
|
C->>W: POST /api/resume/upload<br/>(PDF/DOC/DOCX 文件元信息)
|
|
|
|
|
|
W->>W: JWT校验 + 后缀白名单校验
|
|
|
|
|
|
W->>R: gRPC GenOssSign(key, extension)
|
|
|
|
|
|
R->>R: 校验文件头 Magic Number
|
|
|
|
|
|
R-->>W: {UploadURL, DownloadURL, Expiry}
|
|
|
|
|
|
W-->>C: 返回签名URL信息
|
|
|
|
|
|
|
|
|
|
|
|
Note over C,S: 第二阶段:客户端直传 OSS(服务端零缓存)
|
|
|
|
|
|
|
|
|
|
|
|
C->>S: PUT 直接上传到 OSS Bucket
|
|
|
|
|
|
S-->>C: 200 OK,上传完成
|
|
|
|
|
|
|
|
|
|
|
|
Note over C,W: 第三阶段:记录简历链接到数据库
|
|
|
|
|
|
|
|
|
|
|
|
C->>W: POST /api/profile/save-resume<br/>(fileKey)
|
|
|
|
|
|
W->>R: gRPC SaveResume(fileKey)
|
|
|
|
|
|
R->>R: 持久化 fileKey 到 MySQL
|
|
|
|
|
|
R-->>W: 操作成功
|
|
|
|
|
|
W-->>C: 保存成功
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 7.3 AI 对话数据流
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant H as HR Frontend
|
|
|
|
|
|
participant W as Web-Gin
|
|
|
|
|
|
participant C as ChatService (gRPC)
|
|
|
|
|
|
participant Q as Query Parser
|
|
|
|
|
|
participant M as MySQL
|
|
|
|
|
|
participant P as Prompt Builder
|
|
|
|
|
|
participant E as Eino Chat
|
|
|
|
|
|
participant L as Large Language Model
|
|
|
|
|
|
participant DB as ChatRecordRepo
|
|
|
|
|
|
|
|
|
|
|
|
Note over H,M: Step 1 — 发起提问
|
|
|
|
|
|
|
|
|
|
|
|
H->>W: POST /api/chat/messages {question}
|
|
|
|
|
|
W->>C: gRPC SendChat(hrId, question)
|
|
|
|
|
|
|
|
|
|
|
|
Note over C,Q: Step 2 — 意图解析 + 数据查询
|
|
|
|
|
|
|
|
|
|
|
|
C->>Q: 解析自然语言意图
|
|
|
|
|
|
Q->>M: 执行业务SQL查询
|
|
|
|
|
|
M-->>Q: 真实统计数据
|
|
|
|
|
|
|
|
|
|
|
|
Note over C,P: Step 3 — 上下文拼接 + 推送模型
|
|
|
|
|
|
|
|
|
|
|
|
Q-->>C: 结构化数据
|
|
|
|
|
|
C->>P: 拼接 Prompt = 模板 + 业务数据 + 原始问题
|
|
|
|
|
|
P-->>C: 完整Prompt
|
|
|
|
|
|
C->>E: Eino.Chat.Send(context, messages)
|
|
|
|
|
|
E->>L: HTTP 请求至大模型
|
|
|
|
|
|
L-->>E: 生成回答
|
|
|
|
|
|
E-->>C: 自然语言回答
|
|
|
|
|
|
|
|
|
|
|
|
Note over C,DB: Step 4 — 持久化 + 返回
|
|
|
|
|
|
|
|
|
|
|
|
C->>DB: INSERT chat_record(hr_id, question, reply)
|
|
|
|
|
|
DB-->>C: 写入成功
|
|
|
|
|
|
C-->>W: gRPC Response {reply, records[]}
|
|
|
|
|
|
W-->>H: 渲染AI回复 + 历史消息列表
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 7.4 模块依赖关系图
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
graph TB
|
|
|
|
|
|
subgraph HRFE ["hr-frontend (React + Vite)"]
|
|
|
|
|
|
Routes["路由 /hr/*"]
|
|
|
|
|
|
AuthCtx["AuthContext (JWT)"]
|
|
|
|
|
|
ChatCtx["ChatContext (对话状态)"]
|
|
|
|
|
|
API["Axios API 层"]
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
subgraph UFE ["user-frontend (React + Vite)"]
|
|
|
|
|
|
URoutes["路由 /user/*"]
|
|
|
|
|
|
UAuthCtx["AuthContext (JWT)"]
|
|
|
|
|
|
UAPI["Axios API 层"]
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
subgraph GWI ["web-gin-service (Go)"]
|
|
|
|
|
|
Router["Router"]
|
|
|
|
|
|
Middleware["Middleware: CORS + JWT + Validate"]
|
|
|
|
|
|
Handlers["Handlers: auth / job / resume / chat ..."]
|
|
|
|
|
|
GrpcClient["gRPC Client → Logic"]
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
subgraph LO ["logic-grpc-service (Go)"]
|
|
|
|
|
|
GrpcServer["gRPC Server"]
|
|
|
|
|
|
Services["Services: auth / job / application / profile / resume / chat"]
|
|
|
|
|
|
Repos["Repositories → MySQL"]
|
|
|
|
|
|
OSSMod["OSS Client → Private OSS"]
|
|
|
|
|
|
AIMod["Eino Engine → LLM"]
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
subgraph DATA ["数据 & 存储"]
|
|
|
|
|
|
MySQL[(MySQL)]
|
|
|
|
|
|
OSS["私有 OSS"]
|
|
|
|
|
|
LLM["大语言模型 API"]
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
HRFE -->|HTTP JSON| GWI
|
|
|
|
|
|
UFE -->|HTTP JSON| GWI
|
|
|
|
|
|
GWI -->|gRPC| LO
|
|
|
|
|
|
LO --> MySQL
|
|
|
|
|
|
LO --> OSS
|
|
|
|
|
|
LO --> LLM
|
|
|
|
|
|
|
|
|
|
|
|
classDef fe fill:#e3f2fd,stroke:#1565c0;
|
|
|
|
|
|
classDef gw fill:#fff3e0,stroke:#e65100;
|
|
|
|
|
|
classDef logic fill:#e8f5e9,stroke:#2e7d32;
|
|
|
|
|
|
classDef data fill:#fce4ec,stroke:#c62828;
|
|
|
|
|
|
class HRFE,UFE fe;
|
|
|
|
|
|
class GWI gw;
|
|
|
|
|
|
class LO logic;
|
|
|
|
|
|
class DATA data;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 八、开发建议
|
|
|
|
|
|
|
|
|
|
|
|
1. **前后端各自独立运行**:每个 `frontend/` 用 `npm run dev` 启动 Vite 开发服务器,通过 `vite.config.ts` 中的 `server.proxy` 将 `/api/*` 代理到 `localhost:8080`(Web-Gin)。
|
2026-05-10 21:47:14 +08:00
|
|
|
|
2. **Proto 先行**:先写好 `proto/v1/` 下的所有 `.proto` 文件,再各自 `protoc` 生成代码,避免来回改接口。
|
2026-05-09 20:29:11 +08:00
|
|
|
|
3. **前端共享模式**:HR端和用户端都遵循「API层 → Store层 → 页面层」三层分离,可抽取公共的 Axios client 和类型定义作为参考。
|
|
|
|
|
|
4. **环境变量隔离**:两个前端的 `.env`、后端的 `.env` 全部加 `.gitignore`,使用 `.env.example` 作为模板提交。
|