基于 FastAPI + Vue3 实现 BOSS 直聘风格企业招聘平台(企业端全栈实战)
本文记录我将一个课程项目中的企业端功能,从零迁移并落地到自研后端
fastApi(FastAPI + Tortoise ORM)与前端boss_ui(Vue3)的完整过程。涵盖企业列表、详情、审核、短信验证码登录、入驻认证等 6 大核心功能,以及前后端分层架构设计思路。
一、背景与功能概览
在企业招聘平台中,"企业端"与"管理端"是两个最核心的角色。企业要能入驻平台、展示工商信息、发布职位;平台方则要对企业的资质进行审核,保证信息真实。
本次实现围绕企业端 6 大功能展开:
技术栈:后端FastAPI + Tortoise ORM(异步)+ python-jose JWT + Pydantic v2 + Aerich;前端Vue3<script setup>+ Vite + Element Plus + Vue Router4 + Axios。前后端均遵循API Router → Service → ORM Model三层架构。
二、数据库设计:一张主表 + 三张扩展表
企业信息具有"主信息 + 工商详情 + 资质材料 + 审核记录"的天然分层结构。我把原本单表的设计拆成 4 张表,既符合范式,也方便按场景查询:
t_enterprise:企业主表(名称、账号状态、认证类型、提交时间等)
t_enterprise_info:工商详情(统一社会信用代码、法人、注册资本、行业、规模、经营范围)
t_enterprise_qualification:资质材料(联系人 + 营业执照/身份证图片 URL)
t_enterprise_review:审核记录(结果、原因、审核人、时间)
并定义了 7 个枚举统一管理状态:AccountStatus(0 正常/1 待审核/2 封禁)、AuthType、RegisterStatus、CompanyScale、FinancingStage、AuditType等。用IntEnumField存库,保证可读性与扩展性。
三、Service 层:核心业务逻辑
Service 层是本次实现的重头戏,把跨表事务、权限校验、外部调用都收敛在这里。
1. 入驻保存(事务 + 文件上传)
save_enterprise_info在in_transaction()中一次性写入 3 张表,并把营业执照、法人身份证正反面三张图片上传到 OSS,任一环节失败整体回滚:
2. 完整详情(4 表联合)
get_enterprise_full_detail通过get_or_none关联查询三张扩展表,并把行业 ID 解析为行业名称、规模枚举解析为中文名,前端拿到的就是"开箱即用"的数据。
3. 审核(通过即激活)
enterprise_review不仅写审核记录,还会在review_result == 1时自动把企业account_status改为正常、同步旧status字段——审核通过即可登录,形成闭环。
4. 短信验证码登录
企业端不使用密码,而是"手机号 + 验证码":
send_login_sms_code:校验手机号已在资质表注册 → 生成 6 位随机码 → 写入 Redis(boss-api:enterprise-login:sms:{mobile},5 分钟过期)。
enterprise_login:遍历该手机号对应的企业,要求审核已通过,再比对 Redis 中的验证码,正确则用create_tokens签发 JWT。
四、前端实现:管理端 + 企业端
前端采用 monorepo 结构,boss-manage-ui(管理端)与boss-company-ui(企业端)共享 Axios 封装与 Element Plus 组件库,通过 Vite proxy 把/api转发到127.0.0.1:8000。
管理端:认证审核
CertificationList.vue由原本的 mock 数据改为真实接口:调用getEnterpriseList({account_status:1})拉取待审列表,从enterprise_info取法人、行业名,用AUDIT_TYPE_MAP映射审核类型,并支持批量通过;CertificationAudit.vue在挂载时通过getEnterpriseFullDetail(id)填充公司信息、资质材料、营业执照预览,审核时提交reviewEnterprise({enterprise_id, review_result})。
企业端:登录 + 入驻 + 主页
Login.vue:默认切换为"验证码登录",sendCode调enterpriseSendCode、onSubmit调enterpriseLogin,登录成功后把companyToken、companyUserInfo(含 enterpriseId)写入 localStorage。
Certification.vue:提交认证时构建FormData,以multipart/form-data上传三证图片,行业选项来自/resume/industry/position,枚举字段统一用 int 存储。
CompanyProfile.vue:fetchProfile读取 localStorage 中的 enterpriseId,调enterpriseFullDetail填充公司名称、行业、规模、简介等,并支持更新简介/邮箱/官网。
两个项目均通过vite build验证,构建产物清理后无残留。
五、技术要点小结
- 分层清晰:路由只做参数解析与鉴权,业务逻辑全部下沉到 Service,模型只管数据。复用性与可测性都更好。
- 事务保证一致性:入驻涉及 3 张表 + OSS 上传,用
in_transaction兜底,避免"主表有、详情表没"的脏数据。
- 审核即激活:把"审核通过 → 账号可用"做成原子操作,省去额外的状态机。
- 无密码登录:企业账号用手机号 + 短信验证码,规避明文密码风险,也更符合 B 端"联系人才是账号"的现实。
- 枚举驱动:状态/类型一律走枚举,前后端用统一的中文映射表,减少魔法数字。
六、总结
本文完整呈现了一个企业招聘平台"企业端"从数据建模、后端服务到前端页面的全栈落地过程。核心是把"入驻 → 审核 → 登录"这条主线用事务、JWT、Redis 三种机制串起来,既保证安全,也让管理端与企业端的协作闭环顺滑。后续可继续补充短信服务商对接、企业信息变更审核、以及新增职位发布等模块。