feat(workflow): 添加业务编号生成器并集成到工作流引擎

- 新增 BusinessNoGenerator 类用于生成 YYYYMM + 4位序列号格式的业务编号
- 添加 BusinessNoSequence 实体类用于存储业务编号序列记录
- 在 WorkflowEngineApp 中注入 BusinessNoGenerator 依赖
- 修改工作流发起逻辑,移除手动传入业务编号改为自动生成
- 集成业务编号生成功能在流程实例创建过程中自动分配编号
- 添加批量生成业务编号的功能支持
- 重构工作流相关文件目录结构到 workflow 命名空间下
main
陈伟 2026-02-05 14:21:04 +08:00
parent 84f06b463f
commit d46ee3a002
3 changed files with 136 additions and 29 deletions

View File

@ -0,0 +1,123 @@
using DocumentFormat.OpenXml.Wordprocessing;
using SqlSugar;
namespace OpenAuth.App.workflow;
/// <summary>
/// 业务编号生成器
/// 格式YYYYMM + 4位序列号 (如2024120001)
/// </summary>
public class BusinessNoGenerator
{
private readonly ISqlSugarClient _sqlSugar;
private static readonly object _lockObject = new object();
public BusinessNoGenerator(ISqlSugarClient sqlSugar)
{
_sqlSugar = sqlSugar;
}
/// <summary>
/// 生成业务编号
/// </summary>
/// <param name="prefix">业务前缀(可选)</param>
/// <returns>业务编号</returns>
public string GenerateBusinessNo(string prefix = "")
{
lock (_lockObject)
{
var currentDate = DateTime.Now;
var yearMonth = currentDate.ToString("yyyyMM");
// 查询当天最大序列号
var todayPrefix = $"{prefix}{yearMonth}";
var maxSequence = _sqlSugar.Queryable<BusinessNoSequence>()
.Where(s => s.DatePrefix == todayPrefix)
.OrderByDescending(s => s.SequenceNumber)
.Select(s => s.SequenceNumber)
.First();
// 计算新的序列号
var newSequence = maxSequence + 1;
// 更新序列号记录
var sequenceRecord = new BusinessNoSequence
{
DatePrefix = todayPrefix,
SequenceNumber = newSequence,
LastUpdateTime = DateTime.Now
};
// 如果记录不存在则插入,否则更新
var existingRecord = _sqlSugar.Queryable<BusinessNoSequence>()
.Where(s => s.DatePrefix == todayPrefix)
.First();
if (existingRecord == null)
{
_sqlSugar.Insertable(sequenceRecord).ExecuteCommand();
}
else
{
_sqlSugar.Updateable<BusinessNoSequence>()
.SetColumns(s => new BusinessNoSequence
{
SequenceNumber = newSequence,
LastUpdateTime = DateTime.Now
})
.Where(s => s.DatePrefix == todayPrefix)
.ExecuteCommand();
}
// 格式化返回业务编号
return $"{todayPrefix}{newSequence:D4}";
}
}
/// <summary>
/// 批量生成业务编号
/// </summary>
/// <param name="count">生成数量</param>
/// <param name="prefix">业务前缀</param>
/// <returns>业务编号列表</returns>
public List<string> GenerateBatchBusinessNo(int count, string prefix = "")
{
var businessNos = new List<string>();
lock (_lockObject)
{
for (int i = 0; i < count; i++)
{
businessNos.Add(GenerateBusinessNo(prefix));
}
}
return businessNos;
}
}
/// <summary>
/// 业务编号序列记录表
/// </summary>
[SugarTable("zy_business_no_sequence")]
public class BusinessNoSequence
{
/// <summary>
/// 日期前缀 (YYYYMM格式)
/// </summary>
[SugarColumn(ColumnName = "dateprefix")]
public string DatePrefix { get; set; }
/// <summary>
/// 当前序列号
/// </summary>
[SugarColumn(ColumnName = "sequencenumber")]
public int SequenceNumber { get; set; }
/// <summary>
/// 最后更新时间
/// </summary>
[SugarColumn(ColumnName = "lastupdatetime")]
public DateTime LastUpdateTime { get; set; }
}

View File

@ -7,29 +7,7 @@ using OpenAuth.Repository.Domain.workflow;
using OpenAuth.WebApi.Controllers.ServerController;
using SqlSugar;
namespace workflow;
using Microsoft.AspNetCore.Http;
using OpenAuth.App.BaseApp.Base;
using OpenAuth.App.Interface;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Http;
using OpenAuth.App.BaseApp.Base;
using OpenAuth.App.Interface;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Domain.workflow;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace OpenAuth.App.workflow;
/// <summary>
/// 完整工作流引擎适配区县→执法监督科→5个审核科会签→汇总归档/退回)
@ -39,6 +17,8 @@ public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext
{
private readonly ISqlSugarClient _sqlSugar;
private readonly BusinessNoGenerator _businessNoGenerator;
// 配置5个审核科角色ID需与sys_role表对应自行修改为实际值
private readonly List<long> _auditDeptRoleIds = new()
{
@ -53,9 +33,10 @@ public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext
private const long _supervisionDeptRoleId = 6;
public WorkflowEngineApp(ISugarUnitOfWork<SugarDbContext> unitWork, ISimpleClient<SysCategoryType> repository,
IAuth auth) : base(unitWork, repository, auth)
IAuth auth,BusinessNoGenerator businessNoGenerator) : base(unitWork, repository, auth)
{
_sqlSugar = Repository.AsSugarClient();
_businessNoGenerator = businessNoGenerator;
}
#region 一、核心业务:流程发起/处理
@ -70,8 +51,8 @@ public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext
public long InitiateFlow(long userId, string userName, InitiateFlowRequestDto requestDto)
{
// 参数校验
if (string.IsNullOrEmpty(requestDto.FlowCode) || string.IsNullOrEmpty(requestDto.BusinessNo))
throw new Exception("流程编码和业务编号不能为空");
/*if (string.IsNullOrEmpty(requestDto.FlowCode) || string.IsNullOrEmpty(requestDto.BusinessNo))
throw new Exception("流程编码和业务编号不能为空");*/
if (userId <= 0 || string.IsNullOrEmpty(userName))
throw new Exception("发起人ID和姓名不能为空");
var instanceId = 0L;
@ -93,7 +74,11 @@ public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext
.First();
if (startNode == null)
throw new Exception("流程开始节点【区县提交】不存在,请配置节点");
var currentDate = DateTime.Now;
var yearMonth = currentDate.ToString("yyyyMM");
var prefix = "wfjszl";
var businessNo = _businessNoGenerator.GenerateBusinessNo(prefix);
requestDto.BusinessNo = businessNo;
// 步骤3插入流程实例返回自增主键
var flowInstance = new ZyFlowInstance
{
@ -107,7 +92,6 @@ public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext
CreateTime = DateTime.Now
};
instanceId = _sqlSugar.Insertable(flowInstance).ExecuteReturnIdentity();
// 步骤4插入开始节点工作项直接标记为已完成
var startWorkitem = new ZyFlowWorkitem
{

View File

@ -1,8 +1,8 @@
using Microsoft.AspNetCore.Mvc;
using OpenAuth.App.Interface;
using OpenAuth.App.workflow;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Domain.workflow;
using workflow;
namespace OpenAuth.WebApi.Controllers.ServerController;