Files
student_manage_system/stu_jiuye/就业模块文档.md
T
2026-09-23 10:25:32 +08:00

16 KiB
Raw Blame History

学生就业信息管理系统 —— 就业模块项目文档

一、模块概述

本模块是「学生就业信息管理系统」的核心业务模块,负责管理学生就业状态的全生命周期。围绕就业信息(Employments)、公司信息(Company)、地址信息(Address)三张核心表,并与学生表(students)、班级表(classes)建立外键关联,提供增删改查(CRUD)与统计分析接口。

技术栈:

项 选型
Web 框架 FastAPI
ORM SQLAlchemy 2.x
数据库 MySQL 8.x(驱动 PyMySQL)
数据校验 Pydantic v2
服务启动 Uvicorn

二、目录结构

student\_manage\_system/

├── main.py                # 程序入口:注册全模块路由、建表(\_\_main\_\_ 中执行)

├── databases.py           # 根数据库配置:engine\_all / Base\_all / Session / get\_db

└── stu\_jiuye/             # 就业模块业务包

    ├── main.py            # 路由组装(Shtudent\_Jiuye);独立自测 app

    ├── database.py        # 模块级数据库配置(engine / Base / Session / get\_db)

    ├── model.py           # ORM 模型:Employments / Company / Address

    ├── request.py         # Pydantic 请求体 / 响应体模型

    ├── dao.py             # 数据访问层(纯数据库操作)

    └── CURD\_api.py        # 路由层(API 接口定义)

分层职责:

层 文件 职责
路由层 CURD_api.py 接收 HTTP 请求,参数校验,调用 DAO,返回响应
数据访问层 dao.py 封装 SQLAlchemy 查询与事务,向上提供函数
模型层 model.py 定义表结构与外键关系
校验层 request.py 定义请求体 / 响应体的字段与类型
配置层 database.py 数据库 URL、引擎、Session 工厂

三、数据表设计

1. Employments(就业信息表)

字段 类型 约束 说明
id Integer PK, 自增 主键
stuid Integer FK → students.id 学生 ID
class_id Integer FK → classes.id 班级 ID
company_id Integer FK → Company.id, 可空 就业公司
address_id Integer FK → Address.id, NOT NULL 就业地址
employment_salary Integer 可空 就业薪资
employment_open_time DATE 可空 就业开放时间
offer_recived_time DATE 可空 Offer 下发时间
create_time DateTime default=now 创建时间
update_time DateTime default=now, onupdate=now 更新时间
is_deleted Integer default=0 软删除标记(0 正常 / 1 已删)

2. Company(公司表)

字段 类型 约束 说明
id Integer PK, 自增 主键
employment_company String(50) NOT NULL 公司名称
create_time DateTime default=now 创建时间
update_time DateTime default=now, onupdate=now 更新时间
is_deleted Integer default=0 软删除标记

3. Address(地址表)

字段 类型 约束 说明
id Integer PK, 自增 主键
somewhere String(50) NOT NULL 地址区域,如 "深圳市南山区"
create_time DateTime default=now 创建时间
update_time DateTime default=now, onupdate=now 更新时间
is_deleted Integer default=0 软删除标记

表关系图

students (1) ───< (N) Employments (N) >─── (1) Company

classes  (1) ───< (N)         |  (N) >─── (1) Address
  • 一个学生可有多个就业记录,一条就业记录对应一个学生(通过 stuid 关联学生表)

  • 一条就业记录对应一个公司(company_id)与一个地址(address_id)

  • 通过多表 JOIN 可从就业记录直接获取学生姓名、班级名称、公司名称与地址信息

设计说明:姓名 / 班级不冗余,走 JOIN 获取

与 "在就业表冗余学生姓名" 的方案不同,本模块选择通过 stuid、class_id 外键关联学生表与班级表,查询时动态 JOIN 获取姓名与班级名。代价是查询多一次 JOIN;好处是学生姓名 / 班级变更后无需同步,数据天然一致。

四、API 功能清单(CRUD)

接口定义于 CURD_api.py 的 CURD 路由,由根 ../main.py 以 Shtudent_Jiuye 挂载。

📌 新增(Create)

方法 路径 功能 请求体
POST /emp/company/address 新增地址区域 AddRequest
POST /emp/company 新增公司 CompRequest
POST /emp 新增学生就业信息 PostRequest

注意:由于外键依赖,建议按 Address → Company → Employments 的顺序添加。

📌 查询(Read)

方法 路径 功能 查询参数
GET /emp 多条件查询就业信息 sname、class_id、employment_company、min_salary、max_salary、somewhere、employment_open_start、employment_open_end、offer_recived_start、offer_recived_end(全部可选,均不传则查询全部)

就业薪资 Top5、就业时长、平均就业时长等统计接口已迁移至统计分析模块(StatCalc):

/statcalc/top

、

/statcalc/job

、

/statcalc/avgjob

。

📌 更新(Update)

方法 路径 功能 参数
PUT /emp?id=X 修改就业信息 Query:id;Body:PostRequest(支持部分字段更新)

📌 删除(Delete)

方法 路径 功能 参数
DELETE /emp/{id} 软删除就业信息 Path:id

删除说明:本模块采用软删除(is_deleted = 1),数据不会从物理表中移除,便于审计与恢复。

五、核心流程示例

查询流程(GET /emp)

前端 → CURD\_api.get\_stuinfo()

&#x20;      ↓ 收集 10 个可选查询条件

&#x20;      ↓ 调用 get\_emp\_dao()

&#x20;      ↓ DAO 五表 OUTER JOIN:Employments + Students + ClassInfo + Company + Address

&#x20;      ↓ 动态拼接 filter(姓名/班级/公司/薪资范围/地址/时间范围)

&#x20;      ↓ 统一过滤 is\_deleted = 0

&#x20;      ↓ 返回 list\[dict](含学生姓名、班级名称、公司、区域、薪资、时间)

&#x20;      ↓ 结果为空 → 404「名单不存在」

添加流程(POST /emp)

前端 → CURD\_api.add\_stuinfo()

&#x20;      ↓ p.model\_dump() 转 dict

&#x20;      ↓ add\_employment\_dao()

&#x20;      ↓ o.pop('id' / 'create\_time' / 'update\_time' / 'is\_deleted') 去掉自增主键与自动字段

&#x20;      ↓ Employments(\*\*o) 实例化

&#x20;      ↓ db.add → db.commit → db.refresh

&#x20;      ↓ 失败 → db.rollback → 返回 500

更新流程(PUT /emp?id=X)

前端 → CURD\_api.updata\_stuinfo()

&#x20;      ↓ 请求体排除未传字段(exclude\_unset)

&#x20;      ↓ 为空 → 400「没有需要更新的字段」

&#x20;      ↓ update\_emp\_dao() 按 id 执行 update

&#x20;      ↓ 影响 0 行 → 404「未找到对应记录」

删除流程(DELETE /emp/{id})

前端 → CURD\_api.delete\_stuinfo()

&#x20;      ↓ delete\_emp\_dao() 按 id 执行 UPDATE is\_deleted = 1(软删除)

&#x20;      ↓ 影响 0 行 → 500「没有删除」

六、项目亮点

  1. 清晰的分层架构

    路由(CURD_api.py)、数据访问(dao.py)、模型(model.py)、校验(request.py)各司其职,便于单元测试与维护。

  2. 全链路软删除

    Employments、Company、Address 三张表均有 is_deleted 字段,删除统一走 UPDATE is_deleted = 1,数据可追溯、可恢复;查询时统一过滤 is_deleted == 0。

  3. 动态多条件组合查询

    get_emp_dao 使用链式 filter 动态拼接查询条件,任一条件为空自动跳过,一个接口覆盖 10 种查询维度(姓名 / 班级 / 公司 / 薪资区间 / 地址 / 开放时间区间 / Offer 时间区间)。

  4. 统一时间戳审计

    所有表均带 create_time / update_time,onupdate=datetime.now 让修改自动记录时间,为审计、报表提供数据基础。

  5. 请求体与响应体分离

    request.py 为每类资源定义独立请求体(PostRequest / CompRequest / AddRequest)与响应体(EmpResponse / CompResponse / AddResponse),前端契约清晰,Swagger 自动生成接口文档。

  6. 多表 JOIN 关联查询

    就业记录与学生、班级、公司、地址四张表通过外键关联,一次查询即可返回完整就业信息,无需前端二次请求。

  7. 外键约束保证数据完整性

    stuid /class_id/company_id /address_id 全部建立外键,杜绝 "就业记录指向不存在学生 / 公司" 的脏数据。

七、待添加的新功能 与 已知问题

🎯 短期(可快速落地)

功能 说明 涉及改动
分页查询 /emp 支持 page /page_size,返回 total 与 items dao.py 加 .offset ().limit (),request.py 加分页请求体
薪资区间校验 确保 min_salary <= max_salary request.py 加 @model_validator
数据去重 同一学生同一公司只保留一条有效就业记录 add_employment_dao 前置查询 + 唯一约束
级联删除 删公司 / 地址时同步软删其下就业记录 dao.py 加级联更新逻辑
外键存在性校验 新增时校验 stuid /company_id/address_id 真实存在,给出明确错误 dao.py 前置查询

🚀 中期(需要设计)

功能 说明
批量导入 支持 Excel/CSV 批量导入就业信息
数据导出 查询结果一键导出为 Excel
JWT 鉴权 管理员 / 普通用户角色分离,保护写接口
操作日志 记录每一次增删改操作的操作人与时间
Alembic 迁移 用 Alembic 管理表结构变更,告别手动 DROP TABLE

🌟 长期(数据价值)

功能 说明
就业数据看板 按班级 / 公司 / 薪资维度统计,前端可视化
薪资分布分析 直方图、分位数、同比环比
就业率追踪 结合学生表计算班级 / 专业就业率
缓存层 Redis 缓存 Top5、统计类接口
异步任务 Celery 处理导入 / 导出等耗时任务

⚠️ 当前已知问题(开发中待修复)

问题 位置 影响 建议修复
查询结果按 5 变量解包 3 元组 dao.py get_emp_dao 查到数据即 ValueError 崩溃 select 补齐 5 列,或解包变量与列数一致
空日期直接 strftime dao.py 返回段 时间为空时 AttributeError 判空后再格式化
删除 0 行返回 500 CURD_api.py delete_stuinfo 状态码语义错误 改 404
查询空结果返回 404 CURD_api.py get_stuinfo 正常空结果被当异常 改 200 + 空列表 + totals
更新未过滤已删除记录 dao.py update_emp_dao 可修改已软删数据 filter 加 is_deleted == 0
SQL 全量打印 database.py echo=True 开发噪音 / 性能损耗 生产环境关闭
命名不统一 Shtudent_Jiuye / updata_stuinfo / offer_recived_time 可读性差 统一规范命名

八、运行方式

\# 1. 安装依赖

pip install fastapi uvicorn sqlalchemy pymysql pydantic python-dotenv

\# 2. 配置数据库(项目根目录 .env 中 DB\_USER / DB\_PASSWORD / DB\_HOST / DB\_PORT / DB\_NAME)

\# 3. 启动服务(根入口,含全模块)

python main.py

\# 或

uvicorn main:app --host 127.0.0.1 --port 59000 --reload

\# 4. 单独调试就业模块

uvicorn stu\_jiuye.main:app --host 127.0.0.1 --port 12395 --reload

\# 5. 访问 Swagger 文档

http://127.0.0.1:59000/docs

九、注意事项

  1. 表结构变更需删表重建:Base.metadata.create_all(engine) 只建不改,模型加字段后需 DROP TABLE 或引入 Alembic。

  2. 建表时机:当前建表逻辑在根 ../main.py 的 __main__ 块中执行;直接用 uvicorn main:app 启动时不会建表,全新环境需先执行一次 python main.py(或后续将建表移入 FastAPI lifespan)。

  3. 添加顺序有外键依赖:先建学生 / 班级 / 公司 / 地址,再添加就业记录;Employments 的 stuid /class_id/company_id /address_id 均受外键约束。

  4. 软删除后查询自动过滤:get_emp_dao 已统一过滤 is_deleted == 0,被删除的记录不会再出现在列表里。

  5. 删除接口用 Path 参数:DELETE /emp/{id},不要写成 /emp?id=X。

  6. echo=True 仅限开发:生产环境请关掉,避免刷屏与性能损耗。