FastAPI 后端实战:企业审核功能设计(审核记录 + 状态流转)
FastAPI 后端实战企业审核功能设计审核记录 状态流转记录今天在招聘类项目仿 BOSS 直聘后端写的「企业审核」功能。技术栈FastAPI Tortoise ORM MySQL Redis 阿里云 OSS。只讲后端不展开前端。一、需求与约定企业提交认证资料后需要后台进行审核通过 / 驳回并且要能查看完整的审核历史时间线展示同时审核状态要驱动账号能否登录。核心约定审核结果用整数枚举0提交申请 /1通过 /2驳回审核记录采用**追加append-only**方式每次操作都新增一条而不是覆盖这样完整历史不会丢账号是否通过审核以最新的那条审核记录为准而不是单独在别处维护一个状态位二、数据模型新增一张「企业审核表」挂在企业主表t_enterprise下面用enterprise_id关联# app/models/enterprise.pyclassEnterpriseReview(Model):企业审核表idfields.IntField(pkTrue,description主键ID)review_resultfields.IntField(nullTrue,description审核结果(1:通过,2:驳回))review_reasonfields.CharField(max_length512,nullTrue,description拒绝原因)remarkfields.TextField(nullTrue,description备注说明)audit_timefields.DatetimeField(nullTrue,description审核时间)audit_userfields.CharField(max_length100,nullTrue,description审核人)enterprise_idfields.IntField(nullTrue,description企业ID)classMeta:tablet_enterprise_reviewtable_description企业审核表对应迁移文件migrations/models/6_20260728193745_update.py里建表CREATE TABLE IF NOT EXISTS t_enterprise_review(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT主键ID,review_result INT COMMENT审核结果(1:通过,2:驳回),review_reason VARCHAR(512)COMMENT拒绝原因,remark LONGTEXT COMMENT备注说明,audit_time DATETIME(6)COMMENT审核时间,audit_user VARCHAR(100)COMMENT审核人,enterprise_id INT COMMENT企业ID)CHARACTER SET utf8mb4 COMMENT企业审核表;注意enterprise_id是可空的IntField而非硬外键——审核记录本质是「日志」用松散关联比强外键更省心删企业时也不会被外键约束卡住。三、校验模型入参模型只收审核需要的信息不收企业资料本身资料在提交环节已经存过了# app/schemas/enterprise.pyclassEnterpriseReviewCreateRequest(BaseModel):review_result:intField(...,description审核结果(0:提交申请,1:通过,2:驳回))review_reason:str|NoneField(None,description拒绝原因)remark:str|NoneField(None,description备注说明)audit_user:str|NoneField(None,description审核人)enterprise_id:intField(...,description企业ID)review_reason/remark/audit_user都允许为空audit_user在管理端没登录态时由后端默认填充见下review_reason只有在驳回时才需要。四、审核接口与核心逻辑两个接口一个是审核操作一个是查历史# app/apis/enterprise_api.pyenterprise_router.post(/review,summary企业审核,description企业审核)asyncdefenterprise_review(enterpriseReviewCreateRequest:EnterpriseReviewCreateRequest):awaitEnterpriseService.enterprise_review(enterpriseReviewCreateRequest)return{code:1,message:审核完成}enterprise_router.get(/review_records,summary查询企业审核记录)asyncdefselect_enterprise_review_records(enterprise_id:intQuery(...,title企业ID,description企业ID)):resawaitEnterpriseService.get_review_records(enterprise_id)return{code:1,message:查询成功,data:res}4.1 审核操作追加记录 通过时改主表状态# app/services/enterprise_service.pystaticmethodasyncdefenterprise_review(enterpriseReviewCreateRequest:EnterpriseReviewCreateRequest):enterprise_identerpriseReviewCreateRequest.enterprise_id audit_userenterpriseReviewCreateRequest.audit_useror平台管理员# 每次审核操作都追加一条审核记录审核历史便于前端展示历史审核记录awaitEnterpriseReview.create(enterprise_identerprise_id,review_resultenterpriseReviewCreateRequest.review_result,review_reasonenterpriseReviewCreateRequest.review_reason,remarkenterpriseReviewCreateRequest.remark,audit_useraudit_user,audit_timenow(),)ifenterpriseReviewCreateRequest.review_result1:enterpriseawaitEnterprise.get_or_none(identerprise_id)ifenterprise:enterprise.account_statusAccountStatus.NORMALawaitenterprise.save()# TODO 发送短信(手机号)或者邮件(邮箱)给 用户这里有两个设计点追加而非覆盖不管通过还是驳回都EnterpriseReview.create一条新记录。这样提交 → 驳回 → 重新提交 → 通过的完整流转在表里都查得到前端做时间线直接读这张表就行。通过才改主表状态只有review_result 1才把企业主表的account_status从PENDING_AUDIT改成NORMAL。驳回时不改主表状态——因为后续可能重新提交、再审核状态最终由「最新审核记录」决定见第五节登录校验。4.2 查询历史按 id 正序直接给前端时间线staticmethodasyncdefget_review_records(enterprise_id:int):查询企业的审核记录历史按时间正序供前端历史审核记录时间线展示recordsawaitEnterpriseReview.filter(enterprise_identerprise_id).order_by(id)result[]forrinrecords:result.append({id:r.id,enterprise_id:r.enterprise_id,review_result:r.review_result,review_reason:r.review_reason,remark:r.remark,audit_user:r.audit_user,audit_time:r.audit_time,})returnresultorder_by(id)保证时间正序前端拿到就是天然的「提交 → 审核1 → 审核2…」时间线不需要再排序。五、两个联动点审核功能不是孤立的提交认证和登录都要和它挂钩。5.1 提交认证时写第一条审核记录企业提交认证资料saveEnterpriseInfo时在事务里先写一条review_result0的「提交申请」记录保证审核历史从提交那一刻就完整# 写入第一条审核记录企业提交认证申请awaitEnterpriseReview.create(enterprise_identerprise.id,review_result0,review_reasonNone,remark企业提交认证申请,audit_user企业,audit_timenow(),)5.2 登录门槛以「最新审核记录」为准企业登录时不查主表状态位而是取该企业最新一条审核记录判断# 取最新一条审核记录判断是否已通过审核enterprise_reviewawaitEnterpriseReview.filter(enterprise_identerprise_id).order_by(-id).first()ifenterprise_reviewisNoneorenterprise_review.review_result!1:# 审核通过raiseException(账号未审核通过)用order_by(-id).first()拿最新记录而不是维护一个独立的「当前状态」字段。好处是审核被驳回后再重新提交、再通过的流转都能正确反映——状态始终由最后一条记录说了算不会出现「主表已改但历史对不上」的不一致。六、小结今天企业审核这块后端落地了三样东西模型 迁移t_enterprise_review审核记录表enterprise_id松散关联。审核接口 服务POST /enterprise/review追加审核记录、通过时把主表账号状态置为正常GET /enterprise/review_records按 id 正序返回历史供时间线展示。两处联动提交认证写「提交申请」首条记录登录以最新审核记录判定是否放行。整套设计的关键就一句话审核历史用 append-only 记录表承载业务状态能否登录由最新一条记录派生既保留完整审计轨迹又避免了多处状态位不同步的坑。希望对做审核 / 审批类功能的同学有一点参考价值。

相关新闻

Python虚拟环境全解析:Conda与Venv对比及实战指南

Python虚拟环境全解析:Conda与Venv对比及实战指南

1. 项目概述:为什么我们需要虚拟环境?如果你刚开始学Python,或者已经写了几个脚本,可能觉得直接pip install把包装到系统里就完事了。但很快你就会遇到第一个大麻烦:项目A需要Django 3.2,而项目B需要Django…

2026/7/29 2:58:24阅读更多 →
第1章:Python 术语全景与解释器工作原理

第1章:Python 术语全景与解释器工作原理

1. 项目背景 业务场景 食光集市技术团队刚刚度过第三轮融资后的第一个双十一。订单量从日均500单飙升到3万单,系统虽然没有挂,但技术负责人老张发现一个尴尬的问题:团队里七个开发人员,每个人对Python的理解深度参差不齐。有人以…

2026/7/29 2:58:24阅读更多 →
从零制作Arduino二进制时钟:硬件选型、电路设计与编程实战

从零制作Arduino二进制时钟:硬件选型、电路设计与编程实战

1. 从“看不懂”到“看得懂”:二进制时钟的魅力与挑战最近在整理工作室的旧物时,翻出了一个多年前用Arduino和LED灯珠搭的“小玩意儿”——一个手工制作的二进制时钟。它静静地躺在角落,六个LED排成两列,幽幽地闪着光。我把它重新…

2026/7/29 2:56:24阅读更多 →
从玩具到工程思维:用Boson Kit带孩子理解数字信号与逻辑门

从玩具到工程思维:用Boson Kit带孩子理解数字信号与逻辑门

1. 项目缘起:从“玩具”到“工程思维”的桥梁上次和女儿一起拆开Boson Kit的包装,我们只是简单地按照说明书,把几个模块用线连起来,让蜂鸣器响、让LED灯亮。女儿觉得新奇,但那种感觉更像是“按图索骥”完成一个任务&am…

2026/7/29 4:13:07阅读更多 →
Python子域名探测实战:从基础脚本到智能侦察兵的进阶之路

Python子域名探测实战:从基础脚本到智能侦察兵的进阶之路

1. 从“为什么”开始:子域名探测的实战价值再思考上次我们聊了用Python实现子域名探测的基础方法,主要是基于字典爆破的思路。很多朋友跟着做了一遍,反馈说“工具跑起来了,但感觉差点意思”。这种感觉是对的。一个能跑起来的脚本&…

2026/7/29 4:13:07阅读更多 →
C++与Qt毕业设计实战指南:从选题到部署的完整项目开发

C++与Qt毕业设计实战指南:从选题到部署的完整项目开发

1. 项目概述:为什么选择C与Qt作为毕业设计的黄金搭档?又到了一年一度的毕业季,对于计算机相关专业的同学来说,毕业设计无疑是大学四年学习成果的集中展示,也是敲开理想工作大门的一块重要敲门砖。面对琳琅满目的技术栈…

2026/7/29 4:13:07阅读更多 →
Leetcode 25,148:k个一组翻转链表,排序链表

Leetcode 25,148:k个一组翻转链表,排序链表

1.题目描述题目解答 这道题属于困难题,实现起来较为复杂,但本质上和昨天的两两反转链表是大同小异的。 我们可以先进行单个组内的链表反转,具体可以参考之前的题目。然后将反转好的链表作为结果,返回给前面的链表的尾部。这个具体…

2026/7/29 4:13:07阅读更多 →
使用IOT-Tree消息流节点直接开放RESTful Api支持大屏展示

使用IOT-Tree消息流节点直接开放RESTful Api支持大屏展示

从版本2.0.0开始,IOT-Tree的一些消息流节点可以直接对外开放RESTful Api接口,此机制极大的增强了消息流节点的功能。 比如,你需要通过大屏展示设备运行状态数据时,可以直接使用IOT-Tree的这个功能直接提供后端Api,基本…

2026/7/29 4:13:07阅读更多 →
互动媒体艺术创作:从创意编程到物理交互的完整实现指南

互动媒体艺术创作:从创意编程到物理交互的完整实现指南

1. 项目概述:一场创意与技术的年度交汇每年年底,对于上海纽约大学互动媒体艺术(Interactive Media Arts,简称IMA)专业的学生和老师们来说,最令人期待也最“肝”的盛事,莫过于秋季学期的期末展。…

2026/7/29 4:11:06阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/28 4:06:39阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/28 2:08:06阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/28 1:38:28阅读更多 →
28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“! 在构建复杂的 Agent 系统时,我们经常会遇到这样的场景:Agent 正在执行一个多步骤的任务,比如“下单购买商品”,但执行到一半时,我们…

2026/7/29 0:01:46阅读更多 →
自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

近日,国际专注开放式技术研发的声学品牌Nank南卡,正式官宣实力艺人曾舜晞担任品牌代言人。消息一经发出便轰动全网。为什么耳机品牌不选择流量明星、老牌歌手?而且是选择曾舜晞?让我们一起来探索一下!比起短期的流量&a…

2026/7/29 0:01:46阅读更多 →
【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:01:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/28 20:22:24阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/28 3:17:03阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/28 2:35:58阅读更多 →