别再硬编码了!用两张表搞定OA多级审批(附加班申请完整SQL与事务处理)

张开发
2026/4/12 17:30:20 15 分钟阅读

分享文章

别再硬编码了!用两张表搞定OA多级审批(附加班申请完整SQL与事务处理)
通用审批引擎设计用两张表实现企业级OA多级审批系统当企业OA系统需要处理数十种不同类型的审批流程时传统为每种表单单独开发审批逻辑的方式会带来巨大的维护成本。本文将介绍一种基于审批主表明细表的通用审批引擎设计方案通过松耦合的架构实现审批流程的复用大幅降低开发复杂度。1. 核心设计理念与表结构1.1 为什么需要通用审批引擎在传统OA系统中每种审批表单如请假、报销、采购等通常都有自己独立的审批流程实现。这种方式会导致代码重复相似的审批逻辑在不同表单中重复实现维护困难审批规则变更需要在多处修改扩展性差新增审批类型需要从头开发通用审批引擎通过将审批流程抽象为独立模块实现与具体业务表单的解耦提供统一的审批处理机制。1.2 核心表结构设计只需两张核心表即可支撑整个审批系统审批主表(AuditFlow)字段名类型描述FlowNoVARCHAR(50)审批编号主键TitleNVARCHAR(50)审批标题BusTypeVARCHAR(20)业务类型标识AddUserNoVARCHAR(50)申请人AddTimeDATETIME申请时间ApproStatusINT审批状态审批明细表(AuditFlowDetail)字段名类型描述IDINT自增主键FlowNoVARCHAR(50)关联审批编号AuditUserNoVARCHAR(50)审批人AuditRemarkNVARCHAR(500)审批意见AuditTimeDATETIME审批时间AuditStatusINT审批状态这种设计的关键在于通过BusType字段区分不同业务类型通过FlowNo关联业务表与审批流程状态字段使用枚举值表示不同审批阶段2. 审批流程的状态机设计2.1 状态定义与流转审批流程本质上是一个状态机核心状态包括待审流程刚创建等待第一级审批审批中部分审批人已通过流程继续通过所有审批人同意驳回任一审批人拒绝撤销申请人主动撤回状态流转规则stateDiagram-v2 [*] -- 待审 待审 -- 审批中: 第一级通过 审批中 -- 审批中: 中间级通过 审批中 -- 通过: 最后一级通过 待审 -- 驳回: 第一级拒绝 审批中 -- 驳回: 任一级拒绝 待审 -- 撤销: 申请人撤回 审批中 -- 撤销: 申请人撤回2.2 多级审批的实现逻辑明细表中的记录顺序决定了审批层级。处理逻辑如下创建审批流程时按审批顺序插入明细记录第一级审批人的状态设为待我审批后续设为审核中当前审批人通过后如果还有下一级将下一级状态改为待我审批如果是最后一级将主表状态改为通过任一审批人拒绝时立即终止流程主表状态改为驳回3. 与业务表的集成方案3.1 松耦合设计模式业务表只需包含FlowNo字段即可接入审批系统CREATE TABLE OverTimeAsk ( FlowNo VARCHAR(50) PRIMARY KEY, AddUserNo VARCHAR(20) NOT NULL, AddTime DATETIME NOT NULL, AskReason NVARCHAR(50) NOT NULL, -- 其他业务字段... FOREIGN KEY (FlowNo) REFERENCES AuditFlow(FlowNo) );集成步骤业务表提交时生成唯一FlowNo向AuditFlow插入主记录BusType设为业务标识向AuditFlowDetail插入审批人记录业务表记录通过FlowNo关联审批流程3.2 事务处理示例以下是一个完整的加班申请提交事务处理SQL示例BEGIN TRANSACTION; DECLARE FlowNo VARCHAR(50) 2023050112300001; DECLARE BusType VARCHAR(20) OverTimeAsk; -- 插入业务表 INSERT INTO OverTimeAsk (FlowNo, AddUserNo, AddTime, AskReason, LeaveTimeFrom, LeaveTimeTo) VALUES (FlowNo, U1001, GETDATE(), 项目紧急上线, 2023-05-01 19:00, 2023-05-01 22:00); -- 插入审批主表 INSERT INTO AuditFlow (FlowNo, Title, BusType, AddUserNo, AddTime, ApproStatus) VALUES (FlowNo, 张XX的加班申请, BusType, U1001, GETDATE(), 1); -- 插入审批明细表三级审批 INSERT INTO AuditFlowDetail (FlowNo, AuditUserNo, AuditStatus) VALUES (FlowNo, U2001, 2), -- 主管待我审批 (FlowNo, U2002, 1), -- 部门经理审核中 (FlowNo, U2003, 1); -- 总监审核中 COMMIT TRANSACTION;注意实际应用中应考虑添加异常处理和事务回滚逻辑。4. 高级功能与优化建议4.1 动态审批人配置可以通过额外表实现审批人的动态配置审批配置表(AuditConfig)字段名类型描述IDINT自增主键BusTypeVARCHAR(20)业务类型DeptNoVARCHAR(20)部门编号RoleNoVARCHAR(20)角色编号AuditLevelINT审批层级获取审批人逻辑-- 根据业务类型和申请人部门获取审批流程 SELECT ac.AuditLevel, ur.UserNo FROM AuditConfig ac JOIN UserRole ur ON ac.RoleNo ur.RoleNo AND ac.DeptNo ur.DeptNo WHERE ac.BusType OverTimeAsk ORDER BY ac.AuditLevel;4.2 性能优化策略索引优化CREATE INDEX IX_AuditFlow_Status ON AuditFlow(ApproStatus); CREATE INDEX IX_AuditFlowDetail_FlowNo ON AuditFlowDetail(FlowNo); CREATE INDEX IX_AuditFlowDetail_UserStatus ON AuditFlowDetail(AuditUserNo, AuditStatus);查询优化分页查询待审批列表使用JOIN替代子查询考虑使用视图简化常用查询缓存策略缓存常用审批配置缓存审批人信息考虑使用Redis缓存进行状态跟踪4.3 扩展性设计审批委托添加委托关系表查询审批人时检查是否有委托审批条件分支根据业务数据动态调整审批流程实现条件审批规则引擎审批超时处理添加超时时间字段定时任务检查超时审批自动升级或提醒5. 实战中的经验分享在实际项目中实现这套方案时有几个关键点值得注意审批编号生成建议使用年月日时分序号的格式如2023050112300001既保证唯一性又带有时间信息。状态同步业务表的状态应与审批主表保持同步可以通过触发器或应用逻辑实现。历史记录考虑添加审批历史表记录完整的审批轨迹便于审计和查询。消息通知审批状态变更时应实时通知相关人可以集成消息队列实现异步通知。测试覆盖特别注意测试边界条件如单级审批流程多级全部通过中间级驳回第一级驳回申请人撤销等场景这套方案已经在多个项目中得到验证最高支持过12级审批流程日均处理超过5000条审批记录表现出良好的稳定性和扩展性。

更多文章