
# 【实战分析】从界面反推数据库设计：以金华人才网站为例

## 前言

最近在学习系统架构与数据库设计，为了检验学习成果，我选取了 **金华人才网 (jhrcsc.com)** 及其关联的 **大学生欢迎中心** 网站作为案例。通过浏览其核心业务界面（找工作、找人才、企业招聘、资讯公告等），我尝试反推了其后端数据库的表结构设计，并总结了关键的业务实现逻辑与潜在的优化方案。

以下是我的分析总结记录。

---

## 一、 核心数据库架构设计

一个成熟的招聘系统通常由 **用户权限**、**企业/职位**、**简历中心**、**内容管理(CMS)** 四大模块构成。

### 1. 用户与权限模块 (User & Auth)
这是系统的入口，最大的难点在于如何处理“个人求职者”与“企业HR”的身份区分。

*   **表名：`sys_user` (用户主表)**
    *   `uid` (PK): 用户唯一标识。
    *   `username` / `mobile`: 登录账号/手机号。
    *   `password`: 加密后的密码 (推荐 Bcrypt)。
    *   `user_type`: 用户类型 (1=个人, 2=企业)。
    *   `last_login_time`: 最后登录时间（用于判断活跃度）。
    *   **设计思考**：为了扩展性，建议配合 RBAC 模型，增加 `sys_role` 和 `sys_user_role` 表，允许一个账号切换不同身份。

### 2. 企业与职位模块 (Enterprise & Jobs)
对应网站的“找企业”和“找工作”界面。

*   **表名：`company_profile` (企业信息表)**
    *   `id` (PK): 企业ID。
    *   `uid`: 关联的用户ID。
    *   `company_name`: 企业全称。
    *   `logo_url`: Logo图片存储路径 (建议存相对路径或CDN地址)。
    *   `industry_id`: 行业字典ID (如：交通/物流)。
    *   `nature_id`: 性质字典ID (如：国企、民营)。
    *   `scale_id`: 规模字典ID (如：20-99人)。
    *   `is_famous`: 是否名企 (用于首页推荐排序)。

*   **表名：`company_jobs` (职位发布表)**
    *   `id` (PK): 职位ID。
    *   `company_id`: 关联企业ID。
    *   `job_name`: 职位名称 (如：市场营销)。
    *   `salary_min` / `salary_max`: 薪资范围 (存储数值，单位元)。
    *   `is_negotiable`: 是否面议 (Boolean)。
    *   `edu_req` / `exp_req`: 学历与经验要求的字典ID。
    *   `city_id` / `district_id`: 工作地区ID。
    *   `refresh_time`: 刷新时间 (决定列表页排序权重)。
    *   `status`: 状态 (1=招聘中, 0=已下架)。

### 3. 简历中心模块 (Resume)
对应网站的“找人才”界面，核心在于隐私保护与多维度展示。

*   **表名：`resume_base` (简历基本信息)**
    *   `id` (PK): 简历ID。
    *   `uid`: 关联求职者ID。
    *   `realname`: 真实姓名。
    *   `gender`: 性别。
    *   `birth_year`: 出生年份 (界面显示年龄通常由年份动态计算)。
    *   `privacy_level`: 隐私设置 (完全公开/仅投递可见/保密)。

*   **表名：`resume_edu` / `resume_work` (经历附表)**
    *   设计为 **一对多** 关系。
    *   `resume_id`: 外键。
    *   `school_name` / `company_name`: 学校或公司名。
    *   `start_time` / `end_time`: 起止时间。
    *   `description`: 经历描述。

### 4. 运营与内容模块 (Operation & CMS)
对应“看资讯”、“招聘会”界面。

*   **表名：`cms_article` (资讯文章)**
    *   `title`: 标题。
    *   `cat_id`: 分类ID (政策、公告、指导)。
    *   `content`: 富文本内容 (HTML)。
    *   `publish_time`: 发布时间。

*   **表名：`job_fair` (招聘会)**
    *   `title`: 招聘会主题。
    *   `start_time` / `end_time`: 举办时间范围。
    *   `poster_url`: 海报图片。
    *   `address`: 举办地点。

*   **表名：`sys_dict` (通用数据字典)**
    *   **作用**：这是系统中最重要的辅助表，用于存储“行业”、“学历”、“薪资范围”等下拉选项，减少数据冗余。
    *   字段：`dict_code` (如 edu_level), `dict_value` (1), `dict_label` (本科)。

---

## 二、 关键业务逻辑实现

在分析界面交互时，我总结了以下几个有趣的逻辑实现方式：

### 1. 简历隐私脱敏 (Masking)
在“找人才”列表页，求职者姓名显示为“季**”。
*   **实现逻辑**：前端不应接收完整姓名。后端 API 在输出 JSON 前进行处理：
    ```php
    // 伪代码示例
    if (!$user->is_paid_enterprise) {
        $resume['name'] = mb_substr($resume['realname'], 0, 1) . "**";
        $resume['mobile'] = "******";
    }
    ```

### 2. 招聘会状态判断
界面显示“进行中”或“已结束”。
*   **实现逻辑**：通常不在数据库存状态字段，而是运行时计算：
    *   `Now < start_time` -> **未开始**
    *   `Now > end_time` -> **已结束**
    *   `Otherwise` -> **进行中**

### 3. 薪资的存储与展示
界面显示“6.7-12k/月”或“面议”。
*   **实现逻辑**：
    *   **存储**：数据库存精确数值 `salary_min=6700`, `salary_max=12000`。
    *   **展示**：若 `is_negotiable=1` 则直接显示“面议”；否则除以1000拼接字符串。这种方式既支持范围搜索（WHERE salary > 5000），又支持前端灵活展示。

### 4. 登录分流
如何实现个人和企业在同一个入口登录？
*   **方案**：后端接口统一，通过前端 Tab 页传参（`type=person` 或 `type=company`）。登录成功后，根据数据库 `user_type` 字段，后端返回不同的重定向 URL（`/person/dashboard` 或 `/company/dashboard`）。

---

## 三、 思考：现有架构的潜在优化点

作为学习者，如果让我来重构这个系统，我会考虑以下技术升级：

1.  **搜索性能优化 (Elasticsearch)**
    *   目前的 SQL `LIKE '%关键词%'` 查询在数据量大时效率极低。
    *   **改进**：引入 Elasticsearch，将职位和简历数据同步索引，实现毫秒级全文检索、拼写纠错和高亮显示。

2.  **图片存储 (OSS + CDN)**
    *   网站包含大量 Logo 和海报。
    *   **改进**：不应将图片二进制存入数据库或仅存本地服务器路径。应上传至阿里云 OSS / 七牛云，数据库只存 URL，配合 CDN 加速加载。

3.  **安全性加强**
    *   招聘网站数据价值高，极易被爬虫抓取。
    *   **改进**：接口增加 **Rate Limiting (频率限制)**；简历联系方式查看需增加 **积分扣除** 逻辑；关键接口增加 **Signature 签名校验**。

## 总结

通过对 `jhrcsc.com` 的逆向分析，我深刻体会到：**界面是数据的投影**。看似简单的网页，背后需要严密的数据库范式设计和复杂的业务逻辑支撑。这次分析不仅帮我复习了 SQL 表设计，也让我对业务系统的全链路交互有了更清晰的认识。

