identificationOfCultivatedL.../OpenAuth.App/WorkflowEngineApp.cs

451 lines
17 KiB
C#
Raw Normal View History

2026-02-04 20:40:22 +08:00
using Microsoft.AspNetCore.Http;
using OpenAuth.App.BaseApp.Base;
using OpenAuth.App.Interface;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
2026-02-04 21:43:24 +08:00
using OpenAuth.Repository.Domain.workflow;
2026-02-04 20:40:22 +08:00
using SqlSugar;
namespace workflow;
2026-02-04 21:06:45 +08:00
public class WorkflowEngineApp : SqlSugarBaseApp<IllegalConstructionAssessment, SugarDbContext>
2026-02-04 20:40:22 +08:00
{
private readonly ISqlSugarClient _sqlSugar;
2026-02-04 21:43:24 +08:00
private readonly IAuth _auth; // 修正:私有字段命名为 _auth与注入一致
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
// 构造函数:注入 IAuth 赋值给 _auth
public WorkflowEngineApp(ISugarUnitOfWork<SugarDbContext> unitWork,
ISimpleClient<IllegalConstructionAssessment> repository,
2026-02-04 20:40:22 +08:00
IAuth auth) : base(unitWork, repository, auth)
{
_sqlSugar = Repository.AsSugarClient();
2026-02-04 21:43:24 +08:00
_auth = auth; // 赋值:将注入的 auth 赋值给私有字段 _auth
2026-02-04 20:40:22 +08:00
}
2026-02-04 21:43:24 +08:00
#region 私有辅助方法(不变)
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
private void ValidatePageParam(PageQueryInput pageInput)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
pageInput.PageIndex = pageInput.PageIndex < 1 ? 1 : pageInput.PageIndex;
pageInput.PageSize = pageInput.PageSize < 1 ? 10 : pageInput.PageSize;
pageInput.PageSize = pageInput.PageSize > 100 ? 100 : pageInput.PageSize;
}
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
private string GenerateBusinessNumber() => Guid.NewGuid().ToString("N").ToLower();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
private string GenerateFormId() => Guid.NewGuid().ToString("N");
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
private PageQueryOutput<FlowQueryResult> WrapPageResult(PageQueryInput pageInput, long totalCount,
List<FlowQueryResult> dataList)
{
return new PageQueryOutput<FlowQueryResult>
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
PageIndex = pageInput.PageIndex,
PageSize = pageInput.PageSize,
TotalCount = totalCount,
TotalPages = (int)Math.Ceiling((double)totalCount / pageInput.PageSize),
DataList = dataList
};
2026-02-04 20:40:22 +08:00
}
#endregion
2026-02-04 21:43:24 +08:00
#region 按角色ID查询用户名不变已适配 First 写法)
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
public string GetUserNameByRoleId(long roleId)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
if (roleId <= 0) return string.Empty;
2026-02-04 20:40:22 +08:00
try
{
2026-02-04 21:43:24 +08:00
var sql = @"select u.*
from sys_user u
left join sys_userrole r on u.""id"" = r.""user_id""
where r.""role_id"" = @RoleId";
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var hasData = _sqlSugar.SqlQueryable<SysUser>(sql)
.AddParameters(new { RoleId = roleId })
.Any();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
if (!hasData) return string.Empty;
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var user = _sqlSugar.SqlQueryable<SysUser>(sql)
.AddParameters(new { RoleId = roleId })
2026-02-04 20:40:22 +08:00
.First();
2026-02-04 21:43:24 +08:00
return user?.Name ?? string.Empty;
2026-02-04 20:40:22 +08:00
}
catch (Exception ex)
{
2026-02-04 21:43:24 +08:00
Console.WriteLine($"查询用户姓名失败:{ex.Message}");
return string.Empty;
2026-02-04 20:40:22 +08:00
}
}
#endregion
2026-02-04 21:43:24 +08:00
#region 流程核心业务修正SetColumns 实体初始化写法 + _auth 调用)
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
public long InitiateAssessmentFlow(long userId, string userName, InitiateAssessmentFlowRequest request)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
if (string.IsNullOrEmpty(request.FlowCode) || string.IsNullOrEmpty(request.Title))
throw new ArgumentException("流程编码和表单标题不能为空");
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var businessNumber = string.IsNullOrEmpty(request.BusinessNumber)
? GenerateBusinessNumber()
: request.BusinessNumber;
var formId = GenerateFormId();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var hasTemplate = _sqlSugar.Queryable<FlowTemplate>()
.Where(t => t.FlowCode == request.FlowCode && t.IsEnabled)
.Any();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
if (!hasTemplate)
throw new Exception($"流程模板 {request.FlowCode} 不存在或未启用");
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var flowTemplate = _sqlSugar.Queryable<FlowTemplate>()
.Where(t => t.FlowCode == request.FlowCode && t.IsEnabled)
.First();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
long instanceId = 0;
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
try
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
UnitWork.Db.Ado.BeginTran();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var assessmentForm = new IllegalConstructionAssessment
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
Id = formId,
Title = request.Title,
BusinessNumber = businessNumber,
Type = request.Type,
Attachments = request.Attachments,
AcceptanceTime = request.AcceptanceTime ?? DateTime.Now,
ReceiveTime = request.ReceiveTime,
Status = request.Status ?? "Submitted",
CreateTime = DateTime.Now,
CreateUser = userName,
Remark = request.Remark
};
Repository.Insert(assessmentForm);
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var flowInstance = new FlowInstance
{
TemplateId = flowTemplate.TemplateId,
BusinessNo = businessNumber,
FlowStatus = assessmentForm.Status,
InitiatorId = userId,
InitiatorName = userName,
CreateTime = DateTime.Now
};
instanceId = _sqlSugar.Insertable(flowInstance).ExecuteReturnIdentity();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var flowWorkitem = new FlowWorkitem
{
InstanceId = instanceId,
BusinessNo = businessNumber,
HandlerId = userId,
HandlerName = userName,
NodeName = "发起节点",
WorkitemStatus = "ToDo",
CreateTime = DateTime.Now
};
_sqlSugar.Insertable(flowWorkitem).ExecuteCommand();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
UnitWork.Db.Ado.CommitTran();
}
catch (Exception ex)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
UnitWork.Db.Ado.RollbackTran();
throw new Exception($"发起流程失败:{ex.Message}");
2026-02-04 20:40:22 +08:00
}
2026-02-04 21:43:24 +08:00
return instanceId;
2026-02-04 20:40:22 +08:00
}
2026-02-04 21:43:24 +08:00
public AssessmentFlowUnionResult? QueryAssessmentFlowByBusinessNo(string businessNumber)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
if (string.IsNullOrEmpty(businessNumber))
throw new ArgumentException("业务编号不能为空");
var hasData = _sqlSugar
.Queryable<IllegalConstructionAssessment, FlowInstance, FlowTemplate, FlowWorkitem>((a, fi, ft, fw) =>
new JoinQueryInfos(
JoinType.Inner, a.BusinessNumber == fi.BusinessNo,
JoinType.Inner, fi.TemplateId == ft.TemplateId,
JoinType.Inner, fi.InstanceId == fw.InstanceId && fw.WorkitemStatus == "ToDo"))
.Where((a, fi, ft, fw) => a.BusinessNumber == businessNumber)
.Any();
if (!hasData) return null;
return _sqlSugar
.Queryable<IllegalConstructionAssessment, FlowInstance, FlowTemplate, FlowWorkitem>((a, fi, ft, fw) =>
new JoinQueryInfos(
JoinType.Inner, a.BusinessNumber == fi.BusinessNo,
JoinType.Inner, fi.TemplateId == ft.TemplateId,
JoinType.Inner, fi.InstanceId == fw.InstanceId && fw.WorkitemStatus == "ToDo"))
.Where((a, fi, ft, fw) => a.BusinessNumber == businessNumber)
.Select((a, fi, ft, fw) => new AssessmentFlowUnionResult
{
FormId = a.Id,
Title = a.Title,
BusinessNumber = a.BusinessNumber,
Type = a.Type,
Attachments = a.Attachments,
AcceptanceTime = a.AcceptanceTime,
FlowInstanceId = fi.InstanceId,
FlowName = ft.FlowName,
CurrentNodeName = fw.NodeName,
FlowStatus = fi.FlowStatus,
InitiatorName = fi.InitiatorName,
FlowCreateTime = fi.CreateTime,
FlowFinishTime = fi.FinishTime
})
2026-02-04 20:40:22 +08:00
.First();
}
2026-02-04 21:43:24 +08:00
public bool UpdateAssessmentForm(IllegalConstructionAssessment form, long userId)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
if (form == null || string.IsNullOrEmpty(form.Id))
throw new ArgumentException("表单数据无效");
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
// 修正:调用 _auth私有字段不再是 Auth
var currentUser = _auth.GetCurrentUser()?.User;
if (currentUser == null)
throw new Exception("未获取到当前登录用户");
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
try
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
UnitWork.Db.Ado.BeginTran();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
form.UpdateTime = DateTime.Now;
form.UpdateUser = currentUser.Name;
//Repository.AsUpdateable(newProject).IgnoreNullColumns().ExecuteCommandAsync();
var updateCount = Repository.AsUpdateable(form).IgnoreColumns().ExecuteCommand();
if (!string.IsNullOrEmpty(form.Status))
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
// 修正SetColumns 改为 实体初始化写法
_sqlSugar.Updateable<FlowInstance>()
.SetColumns(fi => new FlowInstance()
{
FlowStatus = form.Status,
FinishTime = form.Status == "Completed" ? DateTime.Now : (DateTime?)null
})
.Where(fi => fi.BusinessNo == form.BusinessNumber)
.ExecuteCommand();
2026-02-04 20:40:22 +08:00
}
2026-02-04 21:43:24 +08:00
UnitWork.Db.Ado.CommitTran();
return updateCount > 0;
}
catch (Exception ex)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
UnitWork.Db.Ado.RollbackTran();
throw new Exception($"更新表单失败:{ex.Message}");
}
2026-02-04 20:40:22 +08:00
}
2026-02-04 21:43:24 +08:00
public PageQueryOutput<AssessmentFlowUnionResult> QueryAllAssessmentForms(PageQueryInput pageInput)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
ValidatePageParam(pageInput);
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var query =
_sqlSugar.Queryable<IllegalConstructionAssessment, FlowInstance, FlowTemplate, FlowWorkitem>((a, fi, ft,
fw) => new JoinQueryInfos(
JoinType.Inner, a.BusinessNumber == fi.BusinessNo,
JoinType.Inner, fi.TemplateId == ft.TemplateId,
JoinType.Inner, fi.InstanceId == fw.InstanceId));
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
if (!string.IsNullOrEmpty(pageInput.Status))
query = query.Where((a, fi, ft, fw) => a.Status == pageInput.Status);
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var queryProjection = query.Select((a, fi, ft, fw) => new AssessmentFlowUnionResult
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
FormId = a.Id,
Title = a.Title,
BusinessNumber = a.BusinessNumber,
Type = a.Type,
Attachments = a.Attachments,
AcceptanceTime = a.AcceptanceTime,
FlowInstanceId = fi.InstanceId,
FlowName = ft.FlowName,
CurrentNodeName = fw.NodeName,
FlowStatus = fi.FlowStatus,
InitiatorName = fi.InitiatorName,
FlowCreateTime = fi.CreateTime,
FlowFinishTime = fi.FinishTime
});
long totalCount = queryProjection.Count();
var dataList = queryProjection
.Skip((pageInput.PageIndex - 1) * pageInput.PageSize)
.Take(pageInput.PageSize)
.ToList();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
return new PageQueryOutput<AssessmentFlowUnionResult>
{
PageIndex = pageInput.PageIndex,
PageSize = pageInput.PageSize,
TotalCount = totalCount,
TotalPages = (int)Math.Ceiling((double)totalCount / pageInput.PageSize),
DataList = dataList
};
}
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
#endregion
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
#region 待办/已办/拟办查询(不变)
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
public PageQueryOutput<FlowQueryResult> QueryMyDraft(long userId, PageQueryInput pageInput)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
ValidatePageParam(pageInput);
var query = _sqlSugar.Queryable<FlowWorkitem, FlowInstance, FlowTemplate>((fw, fi, ft) => new JoinQueryInfos(
JoinType.Inner, fw.InstanceId == fi.InstanceId,
JoinType.Inner, fi.TemplateId == ft.TemplateId))
.Where((fw, fi, ft) => fw.HandlerId == userId && fw.WorkitemStatus == "Draft")
.Select((fw, fi, ft) => new FlowQueryResult
{
InstanceId = fi.InstanceId,
BusinessNo = fi.BusinessNo,
FlowName = ft.FlowName,
FlowStatus = fi.FlowStatus,
NodeName = fw.NodeName,
InitiatorName = fi.InitiatorName,
CreateTime = fi.CreateTime,
FinishTime = fi.FinishTime
});
return WrapPageResult(pageInput, query.Count(),
query.Skip((pageInput.PageIndex - 1) * pageInput.PageSize).Take(pageInput.PageSize).ToList());
2026-02-04 20:40:22 +08:00
}
2026-02-04 21:43:24 +08:00
public PageQueryOutput<FlowQueryResult> QueryMyToDo(long userId, PageQueryInput pageInput)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
ValidatePageParam(pageInput);
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var query = _sqlSugar.Queryable<FlowWorkitem, FlowInstance, FlowTemplate>((fw, fi, ft) => new JoinQueryInfos(
JoinType.Inner, fw.InstanceId == fi.InstanceId,
JoinType.Inner, fi.TemplateId == ft.TemplateId))
.Where((fw, fi, ft) => fw.HandlerId == userId && fw.WorkitemStatus == "ToDo")
.Select((fw, fi, ft) => new FlowQueryResult
{
InstanceId = fi.InstanceId,
BusinessNo = fi.BusinessNo,
FlowName = ft.FlowName,
FlowStatus = fi.FlowStatus,
NodeName = fw.NodeName,
InitiatorName = fi.InitiatorName,
CreateTime = fi.CreateTime,
FinishTime = fi.FinishTime
});
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
return WrapPageResult(pageInput, query.Count(),
query.Skip((pageInput.PageIndex - 1) * pageInput.PageSize).Take(pageInput.PageSize).ToList());
}
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
public PageQueryOutput<FlowQueryResult> QueryMyDone(long userId, PageQueryInput pageInput)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
ValidatePageParam(pageInput);
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var query = _sqlSugar.Queryable<FlowWorkitem, FlowInstance, FlowTemplate>((fw, fi, ft) => new JoinQueryInfos(
JoinType.Inner, fw.InstanceId == fi.InstanceId,
JoinType.Inner, fi.TemplateId == ft.TemplateId))
.Where((fw, fi, ft) => fw.HandlerId == userId && fw.WorkitemStatus == "Done")
.Select((fw, fi, ft) => new FlowQueryResult
{
InstanceId = fi.InstanceId,
BusinessNo = fi.BusinessNo,
FlowName = ft.FlowName,
FlowStatus = fi.FlowStatus,
NodeName = fw.NodeName,
InitiatorName = fi.InitiatorName,
CreateTime = fi.CreateTime,
FinishTime = fi.FinishTime
});
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
return WrapPageResult(pageInput, query.Count(),
query.Skip((pageInput.PageIndex - 1) * pageInput.PageSize).Take(pageInput.PageSize).ToList());
}
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
#endregion
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
#region 待办项处理核心修正SetColumns 实体初始化 + _auth 调用)
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
public bool ClaimDraftWorkitem(long workitemId, long userId, string userName)
{
if (workitemId <= 0 || userId <= 0) return false;
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
// 修正SetColumns 改为 实体初始化写法(批量赋值)
var updateCount = _sqlSugar.Updateable<FlowWorkitem>()
.SetColumns(fw => new FlowWorkitem()
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
WorkitemStatus = "ToDo",
HandlerId = userId,
HandlerName = userName
})
.Where(fw => fw.WorkitemId == workitemId && fw.WorkitemStatus == "Draft")
.ExecuteCommand();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
return updateCount > 0;
2026-02-04 20:40:22 +08:00
}
2026-02-04 21:43:24 +08:00
public bool HandleWorkitem(long userId, string userName, HandleWorkitemRequest request)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
if (request == null || request.WorkitemId <= 0 || string.IsNullOrEmpty(request.HandleResult))
throw new ArgumentException("处理参数无效");
2026-02-04 20:40:22 +08:00
try
{
2026-02-04 21:43:24 +08:00
UnitWork.Db.Ado.BeginTran();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
// 修正SetColumns 实体初始化写法
var updateCount = _sqlSugar.Updateable<FlowWorkitem>()
.SetColumns(fw => new FlowWorkitem()
{
WorkitemStatus = "Done",
HandleTime = DateTime.Now
})
.Where(fw => fw.WorkitemId == request.WorkitemId && fw.HandlerId == userId)
.ExecuteCommand();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var hasWorkitem = _sqlSugar.Queryable<FlowWorkitem>()
.Where(fw => fw.WorkitemId == request.WorkitemId)
.Any();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
if (!hasWorkitem)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
UnitWork.Db.Ado.RollbackTran();
return false;
}
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var workitem = _sqlSugar.Queryable<FlowWorkitem>()
.Where(fw => fw.WorkitemId == request.WorkitemId)
.First();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
var flowStatus = request.HandleResult.Equals("Pass", StringComparison.OrdinalIgnoreCase)
? "Auditing"
: "Rejected";
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
// 修正SetColumns 实体初始化写法
_sqlSugar.Updateable<FlowInstance>()
.SetColumns(fi => new FlowInstance()
{
FlowStatus = flowStatus
})
.Where(fi => fi.InstanceId == workitem.InstanceId)
.ExecuteCommand();
2026-02-04 20:40:22 +08:00
2026-02-04 21:43:24 +08:00
UnitWork.Db.Ado.CommitTran();
return updateCount > 0;
}
catch (Exception ex)
2026-02-04 20:40:22 +08:00
{
2026-02-04 21:43:24 +08:00
UnitWork.Db.Ado.RollbackTran();
throw new Exception($"处理待办失败:{ex.Message}");
2026-02-04 20:40:22 +08:00
}
}
#endregion
}