2026-02-06 16:33:57 +08:00
|
|
|
|
using Microsoft.AspNetCore.Http;
|
2026-02-04 20:40:22 +08:00
|
|
|
|
using OpenAuth.App.BaseApp.Base;
|
2026-02-07 16:55:10 +08:00
|
|
|
|
using OpenAuth.App.FormScheme.FormHelpers;
|
2026-02-04 20:40:22 +08:00
|
|
|
|
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;
|
|
|
|
|
|
|
2026-02-05 14:21:04 +08:00
|
|
|
|
namespace OpenAuth.App.workflow;
|
2026-02-05 09:08:32 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 完整工作流引擎(适配:区县→执法监督科→5个审核科会签→汇总归档/退回)
|
2026-02-05 09:51:56 +08:00
|
|
|
|
/// 包含:流程发起/处理 + 拟办/待办/已办/未办结/已完成/全部事项查询
|
2026-02-05 09:08:32 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext>
|
2026-02-04 20:40:22 +08:00
|
|
|
|
{
|
|
|
|
|
|
private readonly ISqlSugarClient _sqlSugar;
|
|
|
|
|
|
|
2026-02-05 14:21:04 +08:00
|
|
|
|
private readonly BusinessNoGenerator _businessNoGenerator;
|
|
|
|
|
|
|
2026-02-08 10:36:08 +08:00
|
|
|
|
private readonly string prefix = "wfjszl";
|
|
|
|
|
|
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
public WorkflowEngineApp(ISugarUnitOfWork<SugarDbContext> unitWork, ISimpleClient<SysCategoryType> repository,
|
2026-02-05 14:41:27 +08:00
|
|
|
|
IAuth auth, BusinessNoGenerator businessNoGenerator) : base(unitWork, repository, auth)
|
2026-02-04 20:40:22 +08:00
|
|
|
|
{
|
2026-02-05 09:08:32 +08:00
|
|
|
|
_sqlSugar = Repository.AsSugarClient();
|
2026-02-05 14:21:04 +08:00
|
|
|
|
_businessNoGenerator = businessNoGenerator;
|
2026-02-04 21:43:24 +08:00
|
|
|
|
}
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:51:56 +08:00
|
|
|
|
#region 一、核心业务:流程发起/处理
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:51:56 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 发起流程(区县提交→流转至执法监督科)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="userId">发起人ID</param>
|
|
|
|
|
|
/// <param name="userName">发起人姓名</param>
|
|
|
|
|
|
/// <param name="requestDto">发起流程请求参数</param>
|
|
|
|
|
|
/// <returns>流程实例ID</returns>
|
|
|
|
|
|
public long InitiateFlow(long userId, string userName, InitiateFlowRequestDto requestDto)
|
2026-02-04 21:43:24 +08:00
|
|
|
|
{
|
2026-02-08 12:29:33 +08:00
|
|
|
|
var org = _auth.GetCurrentUser().Orgs.First();
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 参数校验
|
2026-02-05 14:21:04 +08:00
|
|
|
|
/*if (string.IsNullOrEmpty(requestDto.FlowCode) || string.IsNullOrEmpty(requestDto.BusinessNo))
|
|
|
|
|
|
throw new Exception("流程编码和业务编号不能为空");*/
|
2026-02-07 10:44:13 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
if (userId <= 0 || string.IsNullOrEmpty(userName))
|
|
|
|
|
|
throw new Exception("发起人ID和姓名不能为空");
|
|
|
|
|
|
var instanceId = 0L;
|
2026-02-04 20:40:22 +08:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 步骤1:查询启用的流程模板(违法建设认定流程)
|
|
|
|
|
|
var template = _sqlSugar.Queryable<ZyFlowTemplate>()
|
2026-02-05 09:51:56 +08:00
|
|
|
|
.Where(t => t.FlowCode == requestDto.FlowCode && t.IsEnabled == true)
|
2026-02-04 20:40:22 +08:00
|
|
|
|
.First();
|
2026-02-05 09:08:32 +08:00
|
|
|
|
if (template == null)
|
2026-02-05 09:51:56 +08:00
|
|
|
|
throw new Exception($"流程模板【{requestDto.FlowCode}】不存在或未启用");
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
var startNode = _sqlSugar.Queryable<ZyFlowNode>()
|
2026-02-11 14:20:46 +08:00
|
|
|
|
.Where(n => n.TemplateId == template.TemplateId && n.NodeType == "Start")
|
2026-02-05 09:08:32 +08:00
|
|
|
|
.First();
|
|
|
|
|
|
if (startNode == null)
|
|
|
|
|
|
throw new Exception("流程开始节点【区县提交】不存在,请配置节点");
|
2026-02-06 15:27:16 +08:00
|
|
|
|
|
2026-02-07 08:44:58 +08:00
|
|
|
|
// 是否存在拟办数据
|
2026-02-07 13:05:41 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(requestDto.BusinessNo) && _sqlSugar
|
2026-02-07 16:55:10 +08:00
|
|
|
|
.Queryable<IllegalConstructionAssessment>()
|
|
|
|
|
|
.Any(a => a.BusinessNumber == requestDto.BusinessNo))
|
2026-02-05 11:07:28 +08:00
|
|
|
|
{
|
2026-02-07 10:44:13 +08:00
|
|
|
|
// 开启事务(基于UnitWork,保障数据一致性)
|
|
|
|
|
|
UnitWork.Db.Ado.BeginTran();
|
2026-02-07 11:23:04 +08:00
|
|
|
|
// 关于直接提交拟办,并提交,并未保存的处理
|
2026-02-09 10:53:22 +08:00
|
|
|
|
var illegal = _sqlSugar.Queryable<IllegalConstructionAssessment>()
|
|
|
|
|
|
.Where(a => a.Id == requestDto.BusinessNo).First();
|
|
|
|
|
|
|
|
|
|
|
|
illegal.UpdateTime = DateTime.Now;
|
|
|
|
|
|
illegal.Status = "Submitted";
|
|
|
|
|
|
|
2026-02-07 11:23:04 +08:00
|
|
|
|
// 字段是否有更新
|
2026-02-07 10:44:13 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(requestDto.Title))
|
|
|
|
|
|
{
|
2026-02-09 10:53:22 +08:00
|
|
|
|
illegal.Title = requestDto.Title;
|
2026-02-07 10:44:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-07 16:55:10 +08:00
|
|
|
|
|
|
|
|
|
|
if (!requestDto.Attachments.IsEmpty())
|
2026-02-07 10:44:13 +08:00
|
|
|
|
{
|
2026-02-07 16:55:10 +08:00
|
|
|
|
var attachmentPaths = string.Join(",", requestDto.Attachments);
|
2026-02-09 10:53:22 +08:00
|
|
|
|
illegal.Attachments = attachmentPaths;
|
2026-02-07 10:44:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (requestDto.Type != null)
|
|
|
|
|
|
{
|
2026-02-09 10:53:22 +08:00
|
|
|
|
illegal.Type = requestDto.Type;
|
2026-02-07 10:44:13 +08:00
|
|
|
|
}
|
2026-02-07 11:23:04 +08:00
|
|
|
|
|
2026-02-06 16:33:57 +08:00
|
|
|
|
// 方案1:明确指定要更新的列,避免主键冲突
|
2026-02-09 10:53:22 +08:00
|
|
|
|
_sqlSugar.Updateable(illegal)
|
2026-02-27 10:31:55 +08:00
|
|
|
|
.IgnoreColumns(ignoreAllNullColumns: true, ignoreAllDefaultValue: true).ExecuteCommand();
|
2026-02-06 16:47:31 +08:00
|
|
|
|
|
2026-02-06 16:33:57 +08:00
|
|
|
|
// 或者方案2:使用 Where 条件更新
|
|
|
|
|
|
// _sqlSugar.Updateable<IllegalConstructionAssessment>()
|
|
|
|
|
|
// .SetColumns(it => new { it.UpdateTime = DateTime.Now, it.Status = "Submitted" })
|
|
|
|
|
|
// .Where(it => it.Id == requestDto.BusinessNo)
|
|
|
|
|
|
// .ExecuteCommand();
|
2026-02-06 15:27:16 +08:00
|
|
|
|
var flowInstance = _sqlSugar.Queryable<ZyFlowInstance>()
|
|
|
|
|
|
.Where(a => a.BusinessNo == requestDto.BusinessNo).First();
|
|
|
|
|
|
instanceId = flowInstance.InstanceId;
|
2026-02-09 10:53:22 +08:00
|
|
|
|
flowInstance.InstanceId = instanceId;
|
|
|
|
|
|
flowInstance.Status = "Submitted";
|
2026-02-27 10:31:55 +08:00
|
|
|
|
_sqlSugar.Updateable(flowInstance)
|
|
|
|
|
|
.IgnoreColumns(ignoreAllNullColumns: true, ignoreAllDefaultValue: true).ExecuteCommand();
|
2026-02-11 14:20:46 +08:00
|
|
|
|
// 需要查驳回和草稿
|
2026-02-06 15:27:16 +08:00
|
|
|
|
var flowWorkItem = _sqlSugar.Queryable<ZyFlowWorkitem>()
|
|
|
|
|
|
.Where(a => a.InstanceId == instanceId
|
2026-02-11 15:16:23 +08:00
|
|
|
|
//&& a.NodeId == startNode.NodeId
|
|
|
|
|
|
&& (a.Status == "Draft" || a.Status == "ToDo")).First();
|
2026-02-06 15:27:16 +08:00
|
|
|
|
if (flowWorkItem == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception("流程工作项不存在");
|
|
|
|
|
|
}
|
2026-02-27 10:31:55 +08:00
|
|
|
|
|
2026-02-09 10:53:22 +08:00
|
|
|
|
flowWorkItem.WorkitemId = flowWorkItem.WorkitemId;
|
|
|
|
|
|
flowWorkItem.Status = "Done";
|
|
|
|
|
|
flowWorkItem.HandleTime = DateTime.Now;
|
|
|
|
|
|
flowWorkItem.Comment = "区县提交";
|
|
|
|
|
|
flowWorkItem.OrgId = org.Id;
|
|
|
|
|
|
flowWorkItem.OrgName = org.Name;
|
2026-02-27 10:31:55 +08:00
|
|
|
|
|
|
|
|
|
|
_sqlSugar.Updateable(flowWorkItem)
|
|
|
|
|
|
.IgnoreColumns(ignoreAllNullColumns: true, ignoreAllDefaultValue: true).ExecuteCommand();
|
2026-02-05 11:07:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-02-07 10:44:13 +08:00
|
|
|
|
// 取号
|
|
|
|
|
|
var businessNo = _businessNoGenerator.GenerateBusinessNo(prefix);
|
2026-02-07 16:55:10 +08:00
|
|
|
|
|
2026-02-07 13:05:41 +08:00
|
|
|
|
requestDto.BusinessNo = businessNo;
|
2026-02-07 10:44:13 +08:00
|
|
|
|
// 开启事务(基于UnitWork,保障数据一致性)
|
|
|
|
|
|
UnitWork.Db.Ado.BeginTran();
|
2026-02-06 15:27:16 +08:00
|
|
|
|
var illegal = new IllegalConstructionAssessment()
|
|
|
|
|
|
{
|
|
|
|
|
|
Id = requestDto.BusinessNo,
|
|
|
|
|
|
Title = requestDto.Title,
|
2026-02-07 13:10:19 +08:00
|
|
|
|
BusinessNumber = requestDto.BusinessNo,
|
|
|
|
|
|
Type = requestDto.Type,
|
2026-02-06 15:27:16 +08:00
|
|
|
|
CreateTime = DateTime.Now,
|
|
|
|
|
|
CreateUser = userName,
|
|
|
|
|
|
UpdateTime = DateTime.Now,
|
|
|
|
|
|
};
|
2026-02-07 16:55:10 +08:00
|
|
|
|
if (!requestDto.Attachments.IsEmpty())
|
|
|
|
|
|
{
|
|
|
|
|
|
var attachmentPaths = string.Join(",", requestDto.Attachments);
|
|
|
|
|
|
illegal.Attachments = attachmentPaths;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-05 11:07:28 +08:00
|
|
|
|
_sqlSugar.Insertable(illegal).ExecuteCommand();
|
2026-02-06 15:27:16 +08:00
|
|
|
|
|
|
|
|
|
|
// 步骤2:查询流程开始节点(区县提交)
|
2026-02-06 17:02:55 +08:00
|
|
|
|
|
2026-02-06 15:27:16 +08:00
|
|
|
|
// 步骤3:插入流程实例,返回自增主键
|
|
|
|
|
|
var flowInstance = new ZyFlowInstance
|
|
|
|
|
|
{
|
|
|
|
|
|
TemplateId = template.TemplateId,
|
|
|
|
|
|
FlowCode = template.FlowCode,
|
|
|
|
|
|
BusinessNo = requestDto.BusinessNo,
|
|
|
|
|
|
Status = "Submitted", // 已提交
|
|
|
|
|
|
CurrentNodeId = startNode.NodeId,
|
|
|
|
|
|
InitiatorId = userId,
|
|
|
|
|
|
InitiatorName = userName,
|
|
|
|
|
|
CreateTime = DateTime.Now
|
|
|
|
|
|
};
|
|
|
|
|
|
instanceId = _sqlSugar.Insertable(flowInstance).ExecuteReturnIdentity();
|
|
|
|
|
|
// 步骤4:插入开始节点工作项(直接标记为已完成)
|
|
|
|
|
|
// 开始节点无ToDo
|
|
|
|
|
|
var startWorkitem = new ZyFlowWorkitem
|
|
|
|
|
|
{
|
|
|
|
|
|
InstanceId = instanceId,
|
|
|
|
|
|
NodeId = startNode.NodeId,
|
|
|
|
|
|
NodeName = startNode.NodeName,
|
|
|
|
|
|
HandlerId = userId,
|
|
|
|
|
|
HandlerName = userName,
|
|
|
|
|
|
Status = "Done", // 已完成
|
|
|
|
|
|
ReceiveTime = DateTime.Now,
|
|
|
|
|
|
HandleTime = DateTime.Now,
|
2026-02-08 15:05:41 +08:00
|
|
|
|
Comment = "提交材料",
|
2026-02-08 12:29:33 +08:00
|
|
|
|
OrgId = org.Id,
|
|
|
|
|
|
OrgName = org.Name
|
2026-02-06 15:27:16 +08:00
|
|
|
|
};
|
|
|
|
|
|
_sqlSugar.Insertable(startWorkitem).ExecuteCommand();
|
|
|
|
|
|
|
|
|
|
|
|
// 步骤5:保存流程变量(标题、附件路径等)
|
|
|
|
|
|
//var attachmentPaths = SaveAttachments(requestDto.Attachments);
|
2026-02-05 11:07:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-07 11:35:59 +08:00
|
|
|
|
// 避免驳回提交数据影响
|
|
|
|
|
|
_sqlSugar.Deleteable<ZyFlowVariable>().Where(a => a.InstanceId == instanceId).ExecuteCommand();
|
2026-02-06 15:27:16 +08:00
|
|
|
|
var flowVariables = new List<ZyFlowVariable>
|
|
|
|
|
|
{
|
|
|
|
|
|
new() { InstanceId = instanceId, VarKey = "Title", VarValue = requestDto.Title },
|
2026-02-07 16:55:10 +08:00
|
|
|
|
|
2026-02-06 15:27:16 +08:00
|
|
|
|
new()
|
|
|
|
|
|
{
|
|
|
|
|
|
InstanceId = instanceId, VarKey = "SubmitTime",
|
|
|
|
|
|
VarValue = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
|
|
|
|
|
|
},
|
2026-02-07 10:44:13 +08:00
|
|
|
|
new() { InstanceId = instanceId, VarKey = "Type", VarValue = requestDto.Type.ToString() },
|
2026-02-06 15:27:16 +08:00
|
|
|
|
};
|
2026-02-07 16:55:10 +08:00
|
|
|
|
if (!requestDto.Attachments.IsEmpty())
|
|
|
|
|
|
{
|
|
|
|
|
|
var attachmentPaths = string.Join(",", requestDto.Attachments);
|
|
|
|
|
|
var x = new ZyFlowVariable()
|
|
|
|
|
|
{ InstanceId = instanceId, VarKey = "AttachmentPaths", VarValue = attachmentPaths };
|
|
|
|
|
|
flowVariables.Add(x);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-06 15:27:16 +08:00
|
|
|
|
_sqlSugar.Insertable(flowVariables).ExecuteCommand();
|
|
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 步骤6:核心流转:从区县提交节点流转至执法监督科节点
|
|
|
|
|
|
FlowToNextNode(instanceId, startNode, userId, userName, "区县提交完成,流转至执法监督科");
|
|
|
|
|
|
|
|
|
|
|
|
// 提交事务
|
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-05 09:08:32 +08:00
|
|
|
|
// 回滚事务
|
2026-02-04 21:43:24 +08:00
|
|
|
|
UnitWork.Db.Ado.RollbackTran();
|
2026-02-05 09:08:32 +08:00
|
|
|
|
throw new Exception($"发起流程失败:{ex.Message}", ex);
|
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-05 09:51:56 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 处理工作项(执法监督科转发/审核科会签/汇总处理)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="userId">处理人ID</param>
|
|
|
|
|
|
/// <param name="userName">处理人姓名</param>
|
|
|
|
|
|
/// <param name="requestDto">处理工作项请求参数</param>
|
|
|
|
|
|
/// <returns>处理结果(成功/失败)</returns>
|
|
|
|
|
|
public bool HandleWorkitem(long userId, string userName, HandleWorkitemRequestDto requestDto)
|
2026-02-05 09:08:32 +08:00
|
|
|
|
{
|
2026-02-08 12:32:58 +08:00
|
|
|
|
var orgs = _auth.GetCurrentUser().Orgs.First();
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 参数校验
|
2026-02-05 09:51:56 +08:00
|
|
|
|
if (requestDto.WorkitemId <= 0)
|
2026-02-05 09:08:32 +08:00
|
|
|
|
throw new Exception("工作项ID无效");
|
|
|
|
|
|
if (userId <= 0 || string.IsNullOrEmpty(userName))
|
|
|
|
|
|
throw new Exception("处理人ID和姓名不能为空");
|
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-05 09:08:32 +08:00
|
|
|
|
// 开启事务
|
2026-02-04 21:43:24 +08:00
|
|
|
|
UnitWork.Db.Ado.BeginTran();
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 步骤1:查询待处理的工作项(仅待办状态可处理)
|
|
|
|
|
|
var workitem = _sqlSugar.Queryable<ZyFlowWorkitem>()
|
2026-02-05 09:51:56 +08:00
|
|
|
|
.Where(w => w.WorkitemId == requestDto.WorkitemId && w.Status == "ToDo")
|
2026-02-05 09:08:32 +08:00
|
|
|
|
.First();
|
|
|
|
|
|
if (workitem == null)
|
|
|
|
|
|
throw new Exception("工作项不存在、已处理或状态异常");
|
|
|
|
|
|
|
|
|
|
|
|
// 步骤2:查询关联的流程实例和当前节点
|
|
|
|
|
|
var flowInstance = _sqlSugar.Queryable<ZyFlowInstance>()
|
|
|
|
|
|
.Where(i => i.InstanceId == workitem.InstanceId)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
var currentNode = _sqlSugar.Queryable<ZyFlowNode>()
|
|
|
|
|
|
.Where(n => n.NodeId == workitem.NodeId)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
if (flowInstance == null || currentNode == null)
|
|
|
|
|
|
throw new Exception("流程实例或流程节点不存在");
|
|
|
|
|
|
|
2026-02-06 08:39:04 +08:00
|
|
|
|
// 步骤3:更新当前工作项为已完成
|
|
|
|
|
|
workitem.Status = "Done";
|
|
|
|
|
|
workitem.HandleTime = DateTime.Now;
|
2026-02-07 17:08:31 +08:00
|
|
|
|
workitem.HandlerId = userId;
|
|
|
|
|
|
workitem.HandlerName = userName;
|
2026-02-10 09:57:03 +08:00
|
|
|
|
// 当前处理人的部门 一个人只有一个部门, 一个角色不一定只有一个部门
|
2026-02-08 12:32:58 +08:00
|
|
|
|
workitem.OrgId = orgs.Id;
|
|
|
|
|
|
workitem.OrgName = orgs.Name;
|
2026-02-10 09:57:03 +08:00
|
|
|
|
// 默认Pass
|
2026-02-08 15:05:41 +08:00
|
|
|
|
workitem.AuditResult = string.IsNullOrEmpty(requestDto.AuditResult) ? "Pass" : requestDto.AuditResult;
|
|
|
|
|
|
var comment = requestDto.Comment;
|
2026-02-08 16:17:12 +08:00
|
|
|
|
_sqlSugar.Updateable(workitem).ExecuteCommand();
|
2026-02-06 08:39:04 +08:00
|
|
|
|
// 生成下一节点数据
|
|
|
|
|
|
// 步骤4:按节点类型分支处理核心逻辑
|
|
|
|
|
|
switch (currentNode.NodeType)
|
2026-02-05 16:25:17 +08:00
|
|
|
|
{
|
2026-02-11 14:20:46 +08:00
|
|
|
|
// 普通节点:执法监督科转发
|
|
|
|
|
|
case "Common" or "End":
|
|
|
|
|
|
if (currentNode.NodeType == "End" && !flowInstance.Status.Equals("Rejected"))
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception("");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
comment = currentNode.NodeType.Equals("Common") ? "下发到审核科室" : "材料提交";
|
2026-02-08 12:29:33 +08:00
|
|
|
|
FlowToNextNode(flowInstance.InstanceId,
|
|
|
|
|
|
currentNode, userId, userName, workitem.Comment, requestDto);
|
2026-02-06 08:39:04 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case "Parallel":
|
2026-02-08 15:09:38 +08:00
|
|
|
|
if (requestDto.AuditResult == "Pass")
|
|
|
|
|
|
{
|
|
|
|
|
|
comment = "审核通过";
|
|
|
|
|
|
}
|
2026-02-08 16:02:42 +08:00
|
|
|
|
|
2026-02-06 08:39:04 +08:00
|
|
|
|
ProcessParallelAudit(flowInstance.InstanceId, currentNode.NodeId, userId, userName, requestDto);
|
2026-02-07 18:08:27 +08:00
|
|
|
|
/*var nextNodeId = long.Parse(currentNode.NextNodeIds.Split(',')[0]);
|
2026-02-06 10:43:57 +08:00
|
|
|
|
var hasNextWorkItem = _sqlSugar.Queryable<ZyFlowWorkitem>()
|
2026-02-06 11:38:31 +08:00
|
|
|
|
.Where(w => w.InstanceId == flowInstance.InstanceId
|
|
|
|
|
|
&& w.Status == "ToDo"
|
|
|
|
|
|
&& w.NodeId == nextNodeId).First();
|
|
|
|
|
|
if (hasNextWorkItem != null)
|
2026-02-06 10:43:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
var nextNode = _sqlSugar.Queryable<ZyFlowNode>()
|
|
|
|
|
|
.Where(a => a.NodeId == nextNodeId).First();
|
2026-02-06 11:38:31 +08:00
|
|
|
|
// 更新脚本节点
|
|
|
|
|
|
var scriptNodeWorkItem = new ZyFlowWorkitem()
|
|
|
|
|
|
{
|
|
|
|
|
|
WorkitemId = hasNextWorkItem.WorkitemId,
|
|
|
|
|
|
Status = "Done"
|
|
|
|
|
|
};
|
2026-02-07 15:42:27 +08:00
|
|
|
|
//_sqlSugar.Updateable(scriptNodeWorkItem).ExecuteCommand();
|
|
|
|
|
|
_sqlSugar.Updateable<ZyFlowWorkitem>()
|
|
|
|
|
|
.SetColumns(t => new ZyFlowWorkitem() { Status = "Done" })
|
|
|
|
|
|
.Where(t => t.WorkitemId == hasNextWorkItem.WorkitemId).ExecuteCommand();
|
2026-02-07 12:19:21 +08:00
|
|
|
|
// 判断是归档还是驳回
|
2026-02-06 10:43:57 +08:00
|
|
|
|
ProcessSummaryNode(flowInstance, nextNode, userId, userName);
|
2026-02-07 18:08:27 +08:00
|
|
|
|
}*/
|
2026-02-06 16:33:57 +08:00
|
|
|
|
|
2026-02-06 08:39:04 +08:00
|
|
|
|
break;
|
|
|
|
|
|
// 分支节点:汇总(归档/退回区县)
|
|
|
|
|
|
case "Branch" when currentNode.NodeName == "汇总判断":
|
2026-02-08 15:05:41 +08:00
|
|
|
|
if (requestDto.AuditResult == "Pass")
|
|
|
|
|
|
{
|
2026-02-09 14:09:54 +08:00
|
|
|
|
comment = "归档";
|
2026-02-08 15:05:41 +08:00
|
|
|
|
}
|
2026-02-27 10:31:55 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
comment = "审核未通过,请区县修改补充材料";
|
|
|
|
|
|
}
|
2026-02-09 14:39:35 +08:00
|
|
|
|
|
2026-02-08 10:07:02 +08:00
|
|
|
|
ProcessSummaryNode(flowInstance, currentNode, userId, userName, requestDto);
|
2026-02-06 08:39:04 +08:00
|
|
|
|
break;
|
|
|
|
|
|
|
2026-02-11 14:20:46 +08:00
|
|
|
|
// 驳回结束
|
|
|
|
|
|
//case "End":
|
|
|
|
|
|
//FlowToNextNode(flowInstance.InstanceId,currentNode, userId, userName, workitem.Comment, requestDto);
|
|
|
|
|
|
// CompleteFlowInstance(flowInstance);
|
|
|
|
|
|
// break;
|
2026-02-04 20:40:22 +08:00
|
|
|
|
}
|
2026-02-06 08:39:04 +08:00
|
|
|
|
|
2026-02-08 15:05:41 +08:00
|
|
|
|
workitem.Comment = comment;
|
|
|
|
|
|
_sqlSugar.Updateable(workitem).ExecuteCommand();
|
2026-02-06 08:39:04 +08:00
|
|
|
|
// 提交事务
|
|
|
|
|
|
UnitWork.Db.Ado.CommitTran();
|
|
|
|
|
|
return true;
|
2026-02-04 21:43:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
2026-02-04 20:40:22 +08:00
|
|
|
|
{
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 回滚事务
|
2026-02-04 21:43:24 +08:00
|
|
|
|
UnitWork.Db.Ado.RollbackTran();
|
2026-02-05 09:08:32 +08:00
|
|
|
|
throw new Exception($"处理工作项失败:{ex.Message}", ex);
|
2026-02-04 21:43:24 +08:00
|
|
|
|
}
|
2026-02-04 20:40:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
#endregion
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:51:56 +08:00
|
|
|
|
#region 二、完整查询:拟办/待办/已办/未办结/已完成/全部事项
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 我的拟办(未认领/待分配给当前用户的事项)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="userId">当前用户ID</param>
|
|
|
|
|
|
/// <param name="pageQueryDto">分页参数</param>
|
|
|
|
|
|
/// <returns>分页结果</returns>
|
|
|
|
|
|
public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyDraft(long userId, PageQueryRequestDto pageQueryDto)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 参数初始化
|
|
|
|
|
|
if (userId <= 0)
|
|
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>();
|
2026-02-07 13:05:41 +08:00
|
|
|
|
pageQueryDto ??= new PageQueryRequestDto();
|
2026-02-05 13:37:02 +08:00
|
|
|
|
var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
|
|
|
|
|
|
var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;
|
2026-02-05 16:25:17 +08:00
|
|
|
|
|
2026-02-07 11:23:04 +08:00
|
|
|
|
// 一个实例,工作项中只有一个拟办,不用去重
|
2026-02-05 10:54:15 +08:00
|
|
|
|
// 拟办不应该是针对个人的吗?
|
2026-02-05 09:51:56 +08:00
|
|
|
|
// 拟办逻辑:工作项状态为"Draft"(拟办)、对应角色匹配当前用户、未分配具体处理人
|
|
|
|
|
|
var draftQuery = _sqlSugar
|
2026-02-05 11:07:28 +08:00
|
|
|
|
.Queryable<IllegalConstructionAssessment>()
|
2026-02-07 11:23:04 +08:00
|
|
|
|
.LeftJoin<ZyFlowInstance>((t, i)
|
2026-02-07 13:10:19 +08:00
|
|
|
|
=> t.BusinessNumber == i.BusinessNo)
|
2026-02-07 11:23:04 +08:00
|
|
|
|
.LeftJoin<ZyFlowNode>((t, i, n)
|
|
|
|
|
|
=> i.CurrentNodeId == n.NodeId)
|
|
|
|
|
|
.LeftJoin<ZyFlowWorkitem>((t, i, n, w)
|
|
|
|
|
|
=> i.InstanceId == w.InstanceId)
|
2026-02-08 17:02:33 +08:00
|
|
|
|
.WhereIF(!string.IsNullOrEmpty(pageQueryDto.key), (t, i, n, w)
|
|
|
|
|
|
=> t.BusinessNumber.Contains(pageQueryDto.key))
|
2026-02-07 11:23:04 +08:00
|
|
|
|
.Where((t, i, n, w) =>
|
|
|
|
|
|
w.Status == "Draft" && i.InitiatorId == userId)
|
2026-02-10 08:51:36 +08:00
|
|
|
|
.OrderByDescending((t, i, n, w) =>
|
2026-02-10 14:35:29 +08:00
|
|
|
|
t.CreateTime)
|
|
|
|
|
|
.Select((t, i, n, w)
|
|
|
|
|
|
=> new FlowQuerySingleResultDto
|
|
|
|
|
|
{
|
|
|
|
|
|
workitemId = w.WorkitemId,
|
|
|
|
|
|
InstanceId = i.InstanceId,
|
|
|
|
|
|
NodeName = n.NodeName,
|
|
|
|
|
|
Status = i.Status, // 工作项状态
|
|
|
|
|
|
WorkStatus = w.Status,
|
|
|
|
|
|
BusinessNo = t.BusinessNumber,
|
|
|
|
|
|
Title = t.Title,
|
|
|
|
|
|
Type = t.Type,
|
|
|
|
|
|
CreateTime = t.CreateTime,
|
|
|
|
|
|
HandleTime = w.HandleTime,
|
|
|
|
|
|
InitiatorName = t.CreateUser //发起人姓名
|
|
|
|
|
|
});
|
2026-02-11 14:20:46 +08:00
|
|
|
|
// 节点 角色 = > 回显状态
|
2026-02-05 09:51:56 +08:00
|
|
|
|
// 分页查询
|
|
|
|
|
|
var totalCount = draftQuery.Count();
|
2026-02-06 16:33:57 +08:00
|
|
|
|
var dataList = draftQuery
|
2026-02-05 09:51:56 +08:00
|
|
|
|
.Skip((pageIndex - 1) * pageSize)
|
|
|
|
|
|
.Take(pageSize)
|
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>
|
|
|
|
|
|
{
|
2026-02-05 13:37:02 +08:00
|
|
|
|
Page = pageIndex,
|
|
|
|
|
|
Limit = pageSize,
|
|
|
|
|
|
Total = totalCount,
|
2026-02-05 09:51:56 +08:00
|
|
|
|
TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
|
2026-02-05 13:37:02 +08:00
|
|
|
|
Items = dataList
|
2026-02-05 09:51:56 +08:00
|
|
|
|
};
|
|
|
|
|
|
}
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
/// <summary>
|
2026-02-05 09:51:56 +08:00
|
|
|
|
/// 我的待办(已分配给当前用户、待处理的事项)
|
2026-02-11 14:20:46 +08:00
|
|
|
|
/// 针对个人,每个流程实例只有一个待办
|
2026-02-05 09:08:32 +08:00
|
|
|
|
/// </summary>
|
2026-02-05 09:51:56 +08:00
|
|
|
|
/// <param name="userId">当前用户ID</param>
|
|
|
|
|
|
/// <param name="pageQueryDto">分页参数</param>
|
|
|
|
|
|
/// <returns>分页结果</returns>
|
|
|
|
|
|
public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyToDo(long userId, PageQueryRequestDto pageQueryDto)
|
2026-02-05 09:08:32 +08:00
|
|
|
|
{
|
2026-02-08 13:51:54 +08:00
|
|
|
|
var orgs = _auth.GetCurrentUser().Orgs.Select(a => a.Id).ToList();
|
2026-02-05 09:51:56 +08:00
|
|
|
|
// 参数初始化
|
2026-02-05 09:08:32 +08:00
|
|
|
|
if (userId <= 0)
|
2026-02-05 09:51:56 +08:00
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>();
|
2026-02-10 09:57:03 +08:00
|
|
|
|
pageQueryDto ??= new PageQueryRequestDto();
|
2026-02-05 13:37:02 +08:00
|
|
|
|
var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
|
|
|
|
|
|
var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;
|
2026-02-07 09:25:57 +08:00
|
|
|
|
|
|
|
|
|
|
// 当是区县用户时: 没有ToDo 只有拟办 及已办
|
|
|
|
|
|
// 当时监督科用户时:工作项状态ToDo 且用户角色能处理的节点 且 handler_id == null
|
|
|
|
|
|
// 当时审核科用户时:handler_id 必须等于用户id
|
2026-02-10 09:57:03 +08:00
|
|
|
|
// 现添加部门限制 主要针对审核角色存在多个部门用户的情况
|
2026-02-05 11:32:29 +08:00
|
|
|
|
var nodeIdList = _sqlSugar.Queryable<ZyFlowNode>()
|
|
|
|
|
|
// 核心:In(主表字段, 子查询Lambda表达式)
|
|
|
|
|
|
.In(
|
|
|
|
|
|
zy => zy.RoleId, // 主表 zy_flow_node 的 role_id 字段
|
|
|
|
|
|
// 子查询:从 sys_userrole 中查询 UserId=2 的 RoleId
|
|
|
|
|
|
_sqlSugar.Queryable<SysUserRole>()
|
|
|
|
|
|
.Where(ur => ur.UserId == userId) // 条件:UserId=2(注意:这里直接用数值,避免字符串拼接)
|
|
|
|
|
|
.Select(ur => ur.RoleId) // 子查询只返回 RoleId 字段
|
|
|
|
|
|
)
|
|
|
|
|
|
// 主查询只返回 node_id 字段(提升查询性能,避免查询全表字段)
|
|
|
|
|
|
.Select(zy => zy.NodeId)
|
|
|
|
|
|
// 执行查询,返回 List<long> 结果
|
|
|
|
|
|
.ToList();
|
2026-02-07 09:25:57 +08:00
|
|
|
|
|
2026-02-05 11:32:29 +08:00
|
|
|
|
var toDoQuery = _sqlSugar
|
|
|
|
|
|
.Queryable<ZyFlowWorkitem>()
|
|
|
|
|
|
.LeftJoin<ZyFlowNode>((w, n) => w.NodeId == n.NodeId)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
.LeftJoin<ZyFlowInstance>((w, n, i)
|
|
|
|
|
|
=> w.InstanceId == i.InstanceId)
|
|
|
|
|
|
.LeftJoin<IllegalConstructionAssessment>((w, n, i, t)
|
2026-02-07 13:10:19 +08:00
|
|
|
|
=> i.BusinessNo == t.BusinessNumber)
|
2026-02-08 17:02:33 +08:00
|
|
|
|
.WhereIF(!string.IsNullOrEmpty(pageQueryDto.key), (w, n, i, t)
|
|
|
|
|
|
=> t.BusinessNumber.Contains(pageQueryDto.key))
|
2026-02-07 09:25:57 +08:00
|
|
|
|
.Where((w, n, i, t)
|
|
|
|
|
|
=> nodeIdList.Contains(w.NodeId) && w.Status == "ToDo")
|
2026-02-08 13:51:54 +08:00
|
|
|
|
.Where((w, n, i, t) => orgs.Contains(w.OrgId))
|
2026-02-07 09:25:57 +08:00
|
|
|
|
.Where((w, n, i, t)
|
|
|
|
|
|
=> w.HandlerId == null || w.HandlerId == userId)
|
2026-02-10 08:56:44 +08:00
|
|
|
|
.OrderByDescending((w, n, i, t) =>
|
2026-02-10 14:35:29 +08:00
|
|
|
|
t.CreateTime)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
.Select((w, n, i, t)
|
|
|
|
|
|
=> new FlowQuerySingleResultDto
|
|
|
|
|
|
{
|
|
|
|
|
|
workitemId = w.WorkitemId,
|
|
|
|
|
|
InstanceId = i.InstanceId,
|
2026-02-07 13:10:19 +08:00
|
|
|
|
BusinessNo = t.BusinessNumber,
|
2026-02-07 09:25:57 +08:00
|
|
|
|
Title = t.Title,
|
|
|
|
|
|
Type = t.Type,
|
|
|
|
|
|
NodeName = n.NodeName,
|
2026-02-10 11:18:22 +08:00
|
|
|
|
//Status = SqlFunc.IIF(i.Status == "Rejected", "Rejected", w.Status),
|
|
|
|
|
|
Status = i.Status,
|
|
|
|
|
|
WorkStatus = w.Status,
|
2026-02-07 09:25:57 +08:00
|
|
|
|
CreateTime = i.CreateTime,
|
2026-02-08 10:41:45 +08:00
|
|
|
|
InitiatorName = i.InitiatorName,
|
|
|
|
|
|
NodeType = n.NodeType
|
2026-02-07 09:25:57 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-02-05 09:51:56 +08:00
|
|
|
|
// 分页查询
|
|
|
|
|
|
var totalCount = toDoQuery.Count();
|
2026-02-07 09:25:57 +08:00
|
|
|
|
var toDoWorkItems = toDoQuery
|
2026-02-05 09:51:56 +08:00
|
|
|
|
.Skip((pageIndex - 1) * pageSize)
|
|
|
|
|
|
.Take(pageSize)
|
2026-02-04 21:43:24 +08:00
|
|
|
|
.ToList();
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-04 21:43:24 +08:00
|
|
|
|
|
2026-02-05 09:51:56 +08:00
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>
|
|
|
|
|
|
{
|
2026-02-05 13:37:02 +08:00
|
|
|
|
Page = pageIndex,
|
|
|
|
|
|
Limit = pageSize,
|
|
|
|
|
|
Total = totalCount,
|
2026-02-05 09:51:56 +08:00
|
|
|
|
TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
|
2026-02-07 09:25:57 +08:00
|
|
|
|
Items = toDoWorkItems
|
2026-02-05 09:51:56 +08:00
|
|
|
|
};
|
2026-02-04 20:40:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
/// <summary>
|
2026-02-05 09:51:56 +08:00
|
|
|
|
/// 我的已办(当前用户已处理完成的事项)
|
2026-02-05 09:08:32 +08:00
|
|
|
|
/// </summary>
|
2026-02-05 09:51:56 +08:00
|
|
|
|
/// <param name="userId">当前用户ID</param>
|
|
|
|
|
|
/// <param name="pageQueryDto">分页参数</param>
|
|
|
|
|
|
/// <returns>分页结果</returns>
|
|
|
|
|
|
public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyDone(long userId, PageQueryRequestDto pageQueryDto)
|
2026-02-04 20:40:22 +08:00
|
|
|
|
{
|
2026-02-05 09:51:56 +08:00
|
|
|
|
// 参数初始化
|
2026-02-05 09:08:32 +08:00
|
|
|
|
if (userId <= 0)
|
2026-02-05 09:51:56 +08:00
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>();
|
2026-02-10 09:57:03 +08:00
|
|
|
|
pageQueryDto ??= new PageQueryRequestDto();
|
2026-02-05 13:37:02 +08:00
|
|
|
|
var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
|
|
|
|
|
|
var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;
|
2026-02-05 09:08:32 +08:00
|
|
|
|
|
2026-02-05 09:51:56 +08:00
|
|
|
|
// 已办逻辑:工作项状态为"Done"、处理人ID为当前用户(去重流程实例)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
var doneInstanceIds = _sqlSugar
|
|
|
|
|
|
.Queryable<ZyFlowWorkitem>()
|
|
|
|
|
|
.LeftJoin<ZyFlowNode>((w, n) => w.NodeId == n.NodeId)
|
|
|
|
|
|
.LeftJoin<ZyFlowInstance>((w, n, i)
|
|
|
|
|
|
=> w.InstanceId == i.InstanceId)
|
|
|
|
|
|
.LeftJoin<IllegalConstructionAssessment>((w, n, i, t)
|
2026-02-07 13:10:19 +08:00
|
|
|
|
=> i.BusinessNo == t.BusinessNumber)
|
2026-02-08 17:02:33 +08:00
|
|
|
|
.WhereIF(!string.IsNullOrEmpty(pageQueryDto.key), (w, n, i, t)
|
|
|
|
|
|
=> t.BusinessNumber.Contains(pageQueryDto.key))
|
2026-02-07 09:25:57 +08:00
|
|
|
|
.Where((w, n, i, t)
|
2026-02-10 09:57:03 +08:00
|
|
|
|
=> w.Status == "Done" && w.HandlerId == userId)
|
2026-02-10 08:56:44 +08:00
|
|
|
|
.OrderByDescending((w, n, i, t) =>
|
2026-02-10 14:35:29 +08:00
|
|
|
|
t.CreateTime)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
.Select((w, n, i, t)
|
|
|
|
|
|
=> new FlowQuerySingleResultDto
|
|
|
|
|
|
{
|
|
|
|
|
|
workitemId = w.WorkitemId,
|
|
|
|
|
|
InstanceId = i.InstanceId,
|
2026-02-07 13:10:19 +08:00
|
|
|
|
BusinessNo = t.BusinessNumber,
|
2026-02-07 09:25:57 +08:00
|
|
|
|
Title = t.Title,
|
|
|
|
|
|
Type = t.Type,
|
|
|
|
|
|
NodeName = n.NodeName,
|
2026-02-10 11:18:22 +08:00
|
|
|
|
Status = i.Status,
|
|
|
|
|
|
WorkStatus = w.Status,
|
2026-02-07 09:25:57 +08:00
|
|
|
|
CreateTime = i.CreateTime,
|
|
|
|
|
|
InitiatorName = i.InitiatorName
|
|
|
|
|
|
});
|
2026-02-05 09:51:56 +08:00
|
|
|
|
// 分页处理实例ID
|
2026-02-07 09:25:57 +08:00
|
|
|
|
var dataList = doneInstanceIds
|
2026-02-05 09:51:56 +08:00
|
|
|
|
.Skip((pageIndex - 1) * pageSize)
|
|
|
|
|
|
.Take(pageSize)
|
|
|
|
|
|
.ToList();
|
2026-02-07 09:25:57 +08:00
|
|
|
|
var totalCount = doneInstanceIds.Count();
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:51:56 +08:00
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>
|
|
|
|
|
|
{
|
2026-02-05 13:37:02 +08:00
|
|
|
|
Page = pageIndex,
|
|
|
|
|
|
Limit = pageSize,
|
|
|
|
|
|
Total = totalCount,
|
2026-02-05 09:51:56 +08:00
|
|
|
|
TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
|
2026-02-05 13:37:02 +08:00
|
|
|
|
Items = dataList
|
2026-02-05 09:51:56 +08:00
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 我的未办结(当前用户参与过、流程尚未完成的事项)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="userId">当前用户ID</param>
|
|
|
|
|
|
/// <param name="pageQueryDto">分页参数</param>
|
|
|
|
|
|
/// <returns>分页结果</returns>
|
|
|
|
|
|
public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyUnfinished(long userId, PageQueryRequestDto pageQueryDto)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 参数初始化
|
|
|
|
|
|
if (userId <= 0)
|
|
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>();
|
|
|
|
|
|
pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
|
2026-02-05 13:37:02 +08:00
|
|
|
|
var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
|
|
|
|
|
|
var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;
|
2026-02-05 09:51:56 +08:00
|
|
|
|
|
2026-02-11 16:53:27 +08:00
|
|
|
|
var maxWorkitemSubQuery = _sqlSugar.Queryable<ZyFlowWorkitem>()
|
|
|
|
|
|
.GroupBy(w => w.InstanceId)
|
|
|
|
|
|
.GroupBy(w => w.HandlerId)
|
|
|
|
|
|
.Select(w => new
|
|
|
|
|
|
{
|
|
|
|
|
|
w.InstanceId,
|
|
|
|
|
|
MaxWorkitemId = SqlFunc.AggregateMax(w.WorkitemId)
|
|
|
|
|
|
});
|
2026-02-05 09:51:56 +08:00
|
|
|
|
// 未办结逻辑:
|
|
|
|
|
|
// 1. 当前用户参与过(处理过/待处理)
|
|
|
|
|
|
// 2. 流程状态不是"Completed"(未完成)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
// Draft(拟办)、Submitted(已提交)、Forwarded(已转发)、Auditing(审核中)、Summarized(已汇总)、Completed(已完成)、Rejected(已驳回)
|
|
|
|
|
|
var doneInstanceIds = _sqlSugar
|
|
|
|
|
|
.Queryable<ZyFlowWorkitem>()
|
2026-02-11 16:53:27 +08:00
|
|
|
|
.InnerJoin(maxWorkitemSubQuery,
|
|
|
|
|
|
(w, sub)
|
|
|
|
|
|
=> w.InstanceId == sub.InstanceId
|
|
|
|
|
|
&& w.WorkitemId == sub.MaxWorkitemId)
|
|
|
|
|
|
// 原有多表关联逻辑(顺序
|
|
|
|
|
|
.LeftJoin<ZyFlowNode>((w, sub, n) => w.NodeId == n.NodeId)
|
|
|
|
|
|
.LeftJoin<ZyFlowInstance>((w, sub, n, i)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
=> w.InstanceId == i.InstanceId)
|
2026-02-11 16:53:27 +08:00
|
|
|
|
.LeftJoin<IllegalConstructionAssessment>((w, sub, n, i, t)
|
2026-02-07 13:10:19 +08:00
|
|
|
|
=> i.BusinessNo == t.BusinessNumber)
|
2026-02-11 16:53:27 +08:00
|
|
|
|
.WhereIF(!string.IsNullOrEmpty(pageQueryDto.key), (w, sub, n, i, t)
|
2026-02-08 17:02:33 +08:00
|
|
|
|
=> t.BusinessNumber.Contains(pageQueryDto.key))
|
2026-02-11 16:53:27 +08:00
|
|
|
|
.Where((w, sub, n, i, t)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
=> w.Status == "Done" && i.Status != "Completed")
|
2026-02-11 16:53:27 +08:00
|
|
|
|
.Where((w, sub, n, i, t)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
=> w.HandlerId == userId)
|
2026-02-11 16:53:27 +08:00
|
|
|
|
.OrderByDescending((w, sub, n, i, t)
|
|
|
|
|
|
=> t.CreateTime)
|
|
|
|
|
|
.Select((w, sub, n, i, t)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
=> new FlowQuerySingleResultDto
|
|
|
|
|
|
{
|
|
|
|
|
|
workitemId = w.WorkitemId,
|
|
|
|
|
|
InstanceId = i.InstanceId,
|
2026-02-07 13:10:19 +08:00
|
|
|
|
BusinessNo = t.BusinessNumber,
|
2026-02-07 09:25:57 +08:00
|
|
|
|
Title = t.Title,
|
|
|
|
|
|
Type = t.Type,
|
|
|
|
|
|
NodeName = n.NodeName,
|
|
|
|
|
|
Status = i.Status,
|
2026-02-10 11:18:22 +08:00
|
|
|
|
WorkStatus = w.Status,
|
2026-02-07 09:25:57 +08:00
|
|
|
|
CreateTime = i.CreateTime,
|
|
|
|
|
|
InitiatorName = i.InitiatorName
|
|
|
|
|
|
});
|
2026-02-05 09:51:56 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 分页处理实例ID
|
2026-02-07 09:25:57 +08:00
|
|
|
|
var pagedInstanceIds = doneInstanceIds
|
2026-02-05 09:51:56 +08:00
|
|
|
|
.Skip((pageIndex - 1) * pageSize)
|
|
|
|
|
|
.Take(pageSize)
|
|
|
|
|
|
.ToList();
|
2026-02-07 09:25:57 +08:00
|
|
|
|
var totalCount = doneInstanceIds.Count();
|
2026-02-05 09:51:56 +08:00
|
|
|
|
|
|
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>
|
|
|
|
|
|
{
|
2026-02-05 13:37:02 +08:00
|
|
|
|
Page = pageIndex,
|
|
|
|
|
|
Limit = pageSize,
|
|
|
|
|
|
Total = totalCount,
|
2026-02-05 09:51:56 +08:00
|
|
|
|
TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
|
2026-02-07 09:25:57 +08:00
|
|
|
|
Items = pagedInstanceIds
|
2026-02-05 09:51:56 +08:00
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 我的已完成(当前用户参与过、流程已归档完成的事项)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="userId">当前用户ID</param>
|
|
|
|
|
|
/// <param name="pageQueryDto">分页参数</param>
|
|
|
|
|
|
/// <returns>分页结果</returns>
|
|
|
|
|
|
public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyCompleted(long userId, PageQueryRequestDto pageQueryDto)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 参数初始化
|
|
|
|
|
|
if (userId <= 0)
|
|
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>();
|
|
|
|
|
|
pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
|
2026-02-05 13:37:02 +08:00
|
|
|
|
var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
|
|
|
|
|
|
var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;
|
2026-02-05 09:51:56 +08:00
|
|
|
|
|
2026-02-11 17:02:44 +08:00
|
|
|
|
var maxWorkitemSubQuery = _sqlSugar.Queryable<ZyFlowWorkitem>()
|
|
|
|
|
|
.GroupBy(w => w.InstanceId)
|
|
|
|
|
|
.GroupBy(w => w.HandlerId)
|
|
|
|
|
|
.Select(w => new
|
|
|
|
|
|
{
|
|
|
|
|
|
w.InstanceId,
|
|
|
|
|
|
MaxWorkitemId = SqlFunc.AggregateMax(w.WorkitemId)
|
|
|
|
|
|
});
|
2026-02-05 09:51:56 +08:00
|
|
|
|
// 已完成逻辑:
|
2026-02-07 09:25:57 +08:00
|
|
|
|
// 1. 当前用户参与过
|
2026-02-05 09:51:56 +08:00
|
|
|
|
// 2. 流程状态是"Completed"(已完成)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
var completedInstanceIds = _sqlSugar
|
|
|
|
|
|
.Queryable<ZyFlowWorkitem>()
|
2026-02-11 17:02:44 +08:00
|
|
|
|
.InnerJoin(maxWorkitemSubQuery,
|
|
|
|
|
|
(w, sub)
|
|
|
|
|
|
=> w.InstanceId == sub.InstanceId
|
|
|
|
|
|
&& w.WorkitemId == sub.MaxWorkitemId)
|
|
|
|
|
|
.LeftJoin<ZyFlowNode>((w, sub, n) => w.NodeId == n.NodeId)
|
|
|
|
|
|
.LeftJoin<ZyFlowInstance>((w, sub, n, i)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
=> w.InstanceId == i.InstanceId)
|
2026-02-11 17:02:44 +08:00
|
|
|
|
.LeftJoin<IllegalConstructionAssessment>((w, sub, n, i, t)
|
2026-02-07 13:10:19 +08:00
|
|
|
|
=> i.BusinessNo == t.BusinessNumber)
|
2026-02-11 17:02:44 +08:00
|
|
|
|
.WhereIF(!string.IsNullOrEmpty(pageQueryDto.key), (w, sub, n, i, t)
|
2026-02-08 17:02:33 +08:00
|
|
|
|
=> t.BusinessNumber.Contains(pageQueryDto.key))
|
2026-02-11 17:02:44 +08:00
|
|
|
|
.Where((w, sub, n, i, t)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
=> w.Status == "Done" && i.Status == "Completed")
|
2026-02-11 17:02:44 +08:00
|
|
|
|
.Where((w, sub, n, i, t)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
=> w.HandlerId == userId)
|
2026-02-11 17:02:44 +08:00
|
|
|
|
.OrderByDescending((w, sub, n, i, t) =>
|
2026-02-10 14:35:29 +08:00
|
|
|
|
t.CreateTime)
|
2026-02-11 17:02:44 +08:00
|
|
|
|
.Select((w, sub, n, i, t)
|
2026-02-07 09:25:57 +08:00
|
|
|
|
=> new FlowQuerySingleResultDto
|
|
|
|
|
|
{
|
|
|
|
|
|
workitemId = w.WorkitemId,
|
|
|
|
|
|
InstanceId = i.InstanceId,
|
2026-02-07 13:10:19 +08:00
|
|
|
|
BusinessNo = t.BusinessNumber,
|
2026-02-07 09:25:57 +08:00
|
|
|
|
Title = t.Title,
|
|
|
|
|
|
Type = t.Type,
|
2026-02-10 09:57:03 +08:00
|
|
|
|
NodeName = n.NodeName ?? "流程结束",
|
2026-02-07 09:25:57 +08:00
|
|
|
|
Status = i.Status,
|
2026-02-10 11:18:22 +08:00
|
|
|
|
WorkStatus = w.Status,
|
2026-02-07 09:25:57 +08:00
|
|
|
|
CreateTime = i.CreateTime,
|
|
|
|
|
|
InitiatorName = i.InitiatorName
|
|
|
|
|
|
});
|
2026-02-05 09:51:56 +08:00
|
|
|
|
|
|
|
|
|
|
// 分页处理实例ID
|
2026-02-07 09:25:57 +08:00
|
|
|
|
var dataList = completedInstanceIds
|
2026-02-05 09:51:56 +08:00
|
|
|
|
.Skip((pageIndex - 1) * pageSize)
|
|
|
|
|
|
.Take(pageSize)
|
|
|
|
|
|
.ToList();
|
2026-02-07 09:25:57 +08:00
|
|
|
|
var totalCount = completedInstanceIds.Count();
|
2026-02-05 09:51:56 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>
|
|
|
|
|
|
{
|
2026-02-05 13:37:02 +08:00
|
|
|
|
Page = pageIndex,
|
|
|
|
|
|
Limit = pageSize,
|
|
|
|
|
|
Total = totalCount,
|
2026-02-05 09:51:56 +08:00
|
|
|
|
TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
|
2026-02-05 13:37:02 +08:00
|
|
|
|
Items = dataList
|
2026-02-05 09:51:56 +08:00
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-02-26 16:41:12 +08:00
|
|
|
|
/// 我的全部事项(待办+已办+未办结+已完成,去重整合)
|
2026-02-05 09:51:56 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="userId">当前用户ID</param>
|
|
|
|
|
|
/// <param name="pageQueryDto">分页参数</param>
|
|
|
|
|
|
/// <returns>分页结果</returns>
|
|
|
|
|
|
public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyAllItems(long userId, PageQueryRequestDto pageQueryDto)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 参数初始化
|
|
|
|
|
|
if (userId <= 0)
|
|
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>();
|
|
|
|
|
|
pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
|
2026-02-05 13:37:02 +08:00
|
|
|
|
var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
|
|
|
|
|
|
var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;
|
2026-02-05 09:51:56 +08:00
|
|
|
|
|
2026-02-09 14:39:35 +08:00
|
|
|
|
var orgIds = _auth.GetCurrentUser().Orgs.Select(o => o.Id).ToList();
|
2026-02-26 16:41:12 +08:00
|
|
|
|
// 发起人 InitiatorId 要经手的 角色绑定的节点 handler_id = null 或者 已经手的(handler_id = user )
|
2026-02-05 15:09:41 +08:00
|
|
|
|
var nodeIdList = _sqlSugar.Queryable<ZyFlowNode>()
|
|
|
|
|
|
// 核心:In(主表字段, 子查询Lambda表达式)
|
|
|
|
|
|
.In(
|
|
|
|
|
|
zy => zy.RoleId, // 主表 zy_flow_node 的 role_id 字段
|
|
|
|
|
|
// 子查询:从 sys_userrole 中查询 UserId=2 的 RoleId
|
|
|
|
|
|
_sqlSugar.Queryable<SysUserRole>()
|
|
|
|
|
|
.Where(ur => ur.UserId == userId) // 条件:UserId=2(注意:这里直接用数值,避免字符串拼接)
|
|
|
|
|
|
.Select(ur => ur.RoleId) // 子查询只返回 RoleId 字段
|
|
|
|
|
|
)
|
|
|
|
|
|
// 主查询只返回 node_id 字段(提升查询性能,避免查询全表字段)
|
|
|
|
|
|
.Select(zy => zy.NodeId)
|
|
|
|
|
|
// 执行查询,返回 List<long> 结果
|
|
|
|
|
|
.ToList();
|
2026-02-06 15:03:34 +08:00
|
|
|
|
var allQuery = _sqlSugar.Queryable<IllegalConstructionAssessment, ZyFlowInstance, ZyFlowNode>((t, i, n) =>
|
|
|
|
|
|
new JoinQueryInfos(
|
2026-02-06 14:51:40 +08:00
|
|
|
|
// 第一个左联:t(违建表) LEFT JOIN i(流程实例表) ON 业务编号匹配
|
2026-02-07 13:10:19 +08:00
|
|
|
|
JoinType.Left, t.BusinessNumber == i.BusinessNo,
|
2026-02-06 14:51:40 +08:00
|
|
|
|
// 第二个左联:i(流程实例表) LEFT JOIN n(流程节点表) ON 当前节点ID匹配
|
|
|
|
|
|
JoinType.Left, i.CurrentNodeId == n.NodeId
|
|
|
|
|
|
))
|
2026-02-10 15:56:51 +08:00
|
|
|
|
.Where((t, i, n) => i.Status != "Draft")
|
2026-02-06 14:51:40 +08:00
|
|
|
|
.Where((t, i, n) =>
|
2026-02-09 15:17:45 +08:00
|
|
|
|
i.InitiatorId == userId //区县
|
2026-02-06 14:51:40 +08:00
|
|
|
|
|| SqlFunc.Exists(
|
|
|
|
|
|
SqlFunc.Subqueryable<ZyFlowWorkitem>()
|
|
|
|
|
|
.GroupBy(w => w.InstanceId)
|
|
|
|
|
|
// 子查询过滤条件:仅修改Contains + 加nodeIdList非空判断
|
2026-02-09 14:39:35 +08:00
|
|
|
|
.Where(w => w.HandlerId == userId
|
|
|
|
|
|
|| w.HandlerId == null
|
|
|
|
|
|
&& w.Status == "ToDo"
|
|
|
|
|
|
&& SqlFunc.ContainsArray(nodeIdList, w.NodeId)
|
|
|
|
|
|
&& orgIds.Contains(w.OrgId))
|
2026-02-06 14:51:40 +08:00
|
|
|
|
// 主查询与子查询的实例ID关联(原有逻辑,不变)
|
|
|
|
|
|
.Where(w => w.InstanceId == i.InstanceId)
|
|
|
|
|
|
.Select(w => w.InstanceId)
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
2026-02-08 17:02:33 +08:00
|
|
|
|
.WhereIF(!string.IsNullOrEmpty(pageQueryDto.key), (t, i, n)
|
|
|
|
|
|
=> t.BusinessNumber.Contains(pageQueryDto.key))
|
2026-02-10 08:56:44 +08:00
|
|
|
|
.OrderByDescending((t, i, n) =>
|
2026-02-10 14:35:29 +08:00
|
|
|
|
t.CreateTime)
|
2026-02-06 14:51:40 +08:00
|
|
|
|
// 你的指定Select:完全按FlowQuerySingleResultDto赋值,保留原空值处理逻辑
|
|
|
|
|
|
.Select((t, i, n) => new FlowQuerySingleResultDto
|
|
|
|
|
|
{
|
|
|
|
|
|
InstanceId = i.InstanceId,
|
|
|
|
|
|
BusinessNo = i.BusinessNo,
|
|
|
|
|
|
Title = t.Title,
|
|
|
|
|
|
Type = t.Type, // 保留原空值默认转0的处理
|
|
|
|
|
|
NodeName = n.NodeName, // 左联可能为null,Dto中若需默认值可加??"未知节点"
|
2026-02-10 16:42:33 +08:00
|
|
|
|
NodeType = n.NodeType,
|
2026-02-06 14:51:40 +08:00
|
|
|
|
Status = i.Status,
|
|
|
|
|
|
CreateTime = i.CreateTime,
|
|
|
|
|
|
InitiatorName = i.InitiatorName
|
|
|
|
|
|
});
|
2026-02-05 15:09:41 +08:00
|
|
|
|
var totalCount = allQuery.Count();
|
2026-02-06 14:51:40 +08:00
|
|
|
|
var dataList = allQuery
|
2026-02-05 09:51:56 +08:00
|
|
|
|
.Skip((pageIndex - 1) * pageSize)
|
|
|
|
|
|
.Take(pageSize)
|
|
|
|
|
|
.ToList();
|
|
|
|
|
|
return new PageQueryResultDto<FlowQuerySingleResultDto>
|
|
|
|
|
|
{
|
2026-02-05 13:37:02 +08:00
|
|
|
|
Page = pageIndex,
|
|
|
|
|
|
Limit = pageSize,
|
|
|
|
|
|
Total = totalCount,
|
2026-02-05 09:51:56 +08:00
|
|
|
|
TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
|
2026-02-05 13:37:02 +08:00
|
|
|
|
Items = dataList
|
2026-02-05 09:51:56 +08:00
|
|
|
|
};
|
2026-02-04 21:43:24 +08:00
|
|
|
|
}
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2026-02-05 09:51:56 +08:00
|
|
|
|
#region 三、内部核心辅助方法(仅内部调用,不对外暴露)
|
2026-02-05 09:08:32 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 流程节点流转核心方法
|
|
|
|
|
|
/// </summary>
|
2026-02-08 12:29:33 +08:00
|
|
|
|
private void FlowToNextNode(long instanceId,
|
|
|
|
|
|
ZyFlowNode currentNode, long userId,
|
|
|
|
|
|
string userName, string comment, HandleWorkitemRequestDto requestDto = null)
|
2026-02-04 20:40:22 +08:00
|
|
|
|
{
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 解析下一节点IDs
|
|
|
|
|
|
var nextNodeIds = currentNode.NextNodeIds?.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
|
|
|
|
|
.Select(long.Parse)
|
|
|
|
|
|
.ToList() ?? new List<long>();
|
|
|
|
|
|
if (!nextNodeIds.Any())
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// 查询流程实例
|
|
|
|
|
|
var flowInstance = _sqlSugar.Queryable<ZyFlowInstance>()
|
|
|
|
|
|
.Where(i => i.InstanceId == instanceId)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
if (flowInstance == null)
|
|
|
|
|
|
throw new Exception("流程实例不存在");
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 遍历处理每个下一节点
|
|
|
|
|
|
foreach (var nextNodeId in nextNodeIds)
|
|
|
|
|
|
{
|
|
|
|
|
|
var nextNode = _sqlSugar.Queryable<ZyFlowNode>()
|
|
|
|
|
|
.Where(n => n.NodeId == nextNodeId)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
if (nextNode == null)
|
|
|
|
|
|
continue;
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 更新流程实例当前节点和状态
|
|
|
|
|
|
flowInstance.CurrentNodeId = nextNode.NodeId;
|
2026-02-10 11:11:44 +08:00
|
|
|
|
// 流程状态更新
|
2026-02-11 14:20:46 +08:00
|
|
|
|
// 区县提交之后 Submitted -> Forwarded -> 转发之后 Auditing -> 审核之后 Summarized -> 汇总判断之后 Completed
|
|
|
|
|
|
// 区县提交之后 Submitted -> Forwarded -> 转发之后 Auditing -> 审核之后 Summarized-> 汇总判断之后 Rejected
|
|
|
|
|
|
// 驳回之后 Rejected -> 转发之后 Auditing -> 审核之后 Summarized 。。。
|
2026-02-05 09:08:32 +08:00
|
|
|
|
flowInstance.Status = GetFlowStatusByNodeType(nextNode.NodeType);
|
2026-02-27 10:31:55 +08:00
|
|
|
|
_sqlSugar.Updateable(flowInstance).IgnoreColumns(ignoreAllNullColumns: true, ignoreAllDefaultValue: true)
|
|
|
|
|
|
.ExecuteCommand();
|
2026-02-11 14:20:46 +08:00
|
|
|
|
// 为选择的每个审核科创建工作项
|
2026-02-05 09:08:32 +08:00
|
|
|
|
if (nextNode.NodeType == "Parallel")
|
|
|
|
|
|
{
|
2026-02-08 12:29:33 +08:00
|
|
|
|
CreateAuditDeptWorkitem(instanceId, nextNode, requestDto?.OrgIds);
|
2026-02-05 09:08:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
// 普通节点/分支节点:创建单个工作项
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-02-08 13:59:07 +08:00
|
|
|
|
var roleId = nextNode.RoleId;
|
|
|
|
|
|
var dept = _sqlSugar
|
|
|
|
|
|
.Queryable<SysOrg>()
|
|
|
|
|
|
.LeftJoin<SysUserOrg>((o, uo)
|
|
|
|
|
|
=> o.Id == uo.OrgId)
|
|
|
|
|
|
.LeftJoin<SysUserRole>((o, uo, ur)
|
|
|
|
|
|
=> uo.UserId == ur.UserId)
|
|
|
|
|
|
.Where((o, uo, ur) => ur.RoleId == roleId)
|
|
|
|
|
|
.First();
|
2026-02-08 09:56:25 +08:00
|
|
|
|
//var userInfo = GetRoleFirstUserInfo(nextNode.RoleId);
|
|
|
|
|
|
// 执法监督科角色可能存在多个用户,不指定处理人
|
2026-02-05 09:08:32 +08:00
|
|
|
|
var nextWorkitem = new ZyFlowWorkitem
|
|
|
|
|
|
{
|
|
|
|
|
|
InstanceId = instanceId,
|
|
|
|
|
|
NodeId = nextNode.NodeId,
|
|
|
|
|
|
NodeName = nextNode.NodeName,
|
2026-02-08 09:56:25 +08:00
|
|
|
|
//HandlerId = userInfo.userId,
|
|
|
|
|
|
//HandlerName = userInfo.userName,
|
2026-02-05 09:08:32 +08:00
|
|
|
|
Status = "ToDo",
|
|
|
|
|
|
ReceiveTime = DateTime.Now,
|
2026-02-08 13:59:07 +08:00
|
|
|
|
Comment = comment,
|
|
|
|
|
|
OrgId = dept.Id,
|
|
|
|
|
|
OrgName = dept.Name
|
2026-02-05 09:08:32 +08:00
|
|
|
|
};
|
|
|
|
|
|
_sqlSugar.Insertable(nextWorkitem).ExecuteCommand();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-04 21:43:24 +08:00
|
|
|
|
}
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 处理并行会签(保存结果+判断是否全部完成)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void ProcessParallelAudit(long instanceId, long nodeId, long userId, string userName,
|
2026-02-05 09:51:56 +08:00
|
|
|
|
HandleWorkitemRequestDto requestDto)
|
2026-02-05 09:08:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 校验会签结果
|
2026-02-05 09:51:56 +08:00
|
|
|
|
if (string.IsNullOrEmpty(requestDto.AuditResult))
|
2026-02-05 09:08:32 +08:00
|
|
|
|
throw new Exception("会签需选择审核结果(Pass/Reject)");
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 步骤1:获取当前用户所属科室名称
|
|
|
|
|
|
var deptName = GetUserDeptName(userId);
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 步骤2:保存会签记录
|
|
|
|
|
|
var parallelAudit = new ZyFlowParallelAudit
|
|
|
|
|
|
{
|
|
|
|
|
|
InstanceId = instanceId,
|
|
|
|
|
|
NodeId = nodeId,
|
|
|
|
|
|
DeptName = deptName,
|
2026-02-05 09:51:56 +08:00
|
|
|
|
AuditResult = requestDto.AuditResult,
|
|
|
|
|
|
AuditComment = requestDto.Comment,
|
2026-02-05 09:08:32 +08:00
|
|
|
|
AuditorId = userId,
|
|
|
|
|
|
AuditorName = userName,
|
|
|
|
|
|
AuditTime = DateTime.Now
|
|
|
|
|
|
};
|
|
|
|
|
|
_sqlSugar.Insertable(parallelAudit).ExecuteCommand();
|
|
|
|
|
|
|
|
|
|
|
|
// 步骤3:判断是否所有审核科都已完成会签
|
2026-02-06 10:43:57 +08:00
|
|
|
|
if (IsAllAuditCompleted(instanceId, nodeId))
|
2026-02-05 09:08:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 步骤4:流转至汇总节点
|
|
|
|
|
|
var parallelNode = _sqlSugar.Queryable<ZyFlowNode>()
|
|
|
|
|
|
.Where(n => n.NodeId == nodeId && n.NodeType == "Parallel")
|
|
|
|
|
|
.First();
|
|
|
|
|
|
FlowToNextNode(instanceId, parallelNode, userId, userName, "所有审核科会签完成,流转至汇总节点");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-11 15:16:23 +08:00
|
|
|
|
|
2026-02-06 10:43:57 +08:00
|
|
|
|
private bool IsAllAuditCompleted(long instanceId, long nodeId)
|
2026-02-06 08:39:04 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 有一个 Pending
|
2026-02-06 10:43:57 +08:00
|
|
|
|
var auditsCount = _sqlSugar.Queryable<ZyFlowWorkitem>()
|
|
|
|
|
|
.Any(a => a.InstanceId == instanceId && a.NodeId == nodeId && a.Status == "ToDo");
|
|
|
|
|
|
return !auditsCount;
|
2026-02-06 08:39:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 处理汇总节点(归档/退回区县)
|
|
|
|
|
|
/// </summary>
|
2026-02-07 18:17:58 +08:00
|
|
|
|
private void ProcessSummaryNode(ZyFlowInstance flowInstance, ZyFlowNode summaryNode, long userId, string userName,
|
2026-02-08 10:07:02 +08:00
|
|
|
|
HandleWorkitemRequestDto requestDto)
|
2026-02-04 21:43:24 +08:00
|
|
|
|
{
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 步骤1:判断是否全部审核通过
|
2026-02-07 18:08:27 +08:00
|
|
|
|
/*var hasReject = _sqlSugar.Queryable<ZyFlowParallelAudit>()
|
2026-02-05 09:08:32 +08:00
|
|
|
|
.Where(a => a.InstanceId == flowInstance.InstanceId)
|
2026-02-06 10:43:57 +08:00
|
|
|
|
.Any(a => a.AuditResult == "Reject");
|
2026-02-07 18:08:27 +08:00
|
|
|
|
var isAllPass = !hasReject;*/
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 步骤2:解析汇总节点下一节点(归档/退回)
|
|
|
|
|
|
var nextNodeIds = summaryNode.NextNodeIds?.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
|
|
|
|
|
.Select(long.Parse)
|
|
|
|
|
|
.ToList() ?? new List<long>();
|
|
|
|
|
|
if (nextNodeIds.Count < 2)
|
|
|
|
|
|
throw new Exception("汇总节点需配置2个后续节点(归档/退回区县)");
|
2026-02-08 10:07:02 +08:00
|
|
|
|
var isAllPass = requestDto.AuditResult == "Pass";
|
2026-02-05 09:51:56 +08:00
|
|
|
|
// 步骤3:确定目标节点(通过→归档[下标0],不通过→退回区县[下标1])
|
|
|
|
|
|
var targetNodeId = isAllPass ? nextNodeIds[0] : nextNodeIds[1];
|
2026-02-05 09:08:32 +08:00
|
|
|
|
var targetNode = _sqlSugar.Queryable<ZyFlowNode>()
|
|
|
|
|
|
.Where(n => n.NodeId == targetNodeId)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
if (targetNode == null)
|
2026-02-05 09:51:56 +08:00
|
|
|
|
throw new Exception($"汇总节点目标节点【{(isAllPass ? "归档" : "退回区县")}】不存在");
|
2026-02-09 16:38:16 +08:00
|
|
|
|
|
2026-02-09 16:53:49 +08:00
|
|
|
|
|
2026-02-10 08:33:20 +08:00
|
|
|
|
// todo 关于同一角色存在于多个部门问题
|
|
|
|
|
|
// todo 一个是区县,一个是审核部门
|
2026-02-09 16:53:49 +08:00
|
|
|
|
// 步骤4:创建目标节点工作项 驳回 or 归档
|
2026-02-05 09:08:32 +08:00
|
|
|
|
var summaryWorkitem = new ZyFlowWorkitem
|
|
|
|
|
|
{
|
|
|
|
|
|
InstanceId = flowInstance.InstanceId,
|
|
|
|
|
|
NodeId = targetNode.NodeId,
|
|
|
|
|
|
NodeName = targetNode.NodeName,
|
2026-02-09 16:38:16 +08:00
|
|
|
|
HandlerId = isAllPass ? userId : null,
|
|
|
|
|
|
HandlerName = isAllPass ? userName : null,
|
2026-02-08 16:38:21 +08:00
|
|
|
|
Status = isAllPass ? "Done" : "ToDo",
|
2026-02-05 09:08:32 +08:00
|
|
|
|
ReceiveTime = DateTime.Now,
|
2026-02-07 18:08:27 +08:00
|
|
|
|
HandleTime = DateTime.Now,
|
2026-02-09 14:09:54 +08:00
|
|
|
|
Comment = isAllPass
|
2026-02-09 16:38:16 +08:00
|
|
|
|
? "归档完成"
|
|
|
|
|
|
: (string.IsNullOrEmpty(requestDto.Comment) ? "审核不通过,退回区县修改补充材料" : requestDto.Comment)
|
2026-02-05 09:08:32 +08:00
|
|
|
|
};
|
2026-02-09 16:53:49 +08:00
|
|
|
|
// 如果是驳回节点,需要退回原部门
|
|
|
|
|
|
if (!isAllPass)
|
2026-02-09 14:01:29 +08:00
|
|
|
|
{
|
2026-02-09 16:53:49 +08:00
|
|
|
|
var startWorkItem = _sqlSugar
|
|
|
|
|
|
.Queryable<ZyFlowWorkitem>()
|
|
|
|
|
|
.Where(w => w.InstanceId == flowInstance.InstanceId)
|
|
|
|
|
|
.OrderBy(w => w.WorkitemId).First();
|
2026-02-11 15:16:23 +08:00
|
|
|
|
// 区县角色用户有多个,为了不数据混乱,需要填充HandlerId和HandlerName
|
2026-02-26 16:41:12 +08:00
|
|
|
|
summaryWorkitem.HandlerId = flowInstance.InitiatorId;
|
2026-02-09 16:53:49 +08:00
|
|
|
|
summaryWorkitem.HandlerName = flowInstance.InitiatorName;
|
|
|
|
|
|
summaryWorkitem.OrgId = startWorkItem.OrgId;
|
|
|
|
|
|
summaryWorkitem.OrgName = startWorkItem.OrgName;
|
2026-02-09 14:01:29 +08:00
|
|
|
|
}
|
2026-02-10 08:33:20 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-02-10 08:51:36 +08:00
|
|
|
|
// 获取目标角色的部门名称
|
|
|
|
|
|
var roleId = targetNode.RoleId;
|
|
|
|
|
|
var dept = _sqlSugar
|
|
|
|
|
|
.Queryable<SysOrg>()
|
|
|
|
|
|
.LeftJoin<SysUserOrg>((o, uo)
|
|
|
|
|
|
=> o.Id == uo.OrgId)
|
|
|
|
|
|
.LeftJoin<SysUserRole>((o, uo, ur)
|
|
|
|
|
|
=> uo.UserId == ur.UserId)
|
|
|
|
|
|
.Where((o, uo, ur) => ur.RoleId == roleId)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
summaryWorkitem.OrgId = dept.Id;
|
|
|
|
|
|
summaryWorkitem.OrgName = dept.Name;
|
2026-02-10 08:33:20 +08:00
|
|
|
|
}
|
2026-02-09 14:09:54 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
_sqlSugar.Insertable(summaryWorkitem).ExecuteCommand();
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 步骤5:更新流程实例最终状态
|
|
|
|
|
|
flowInstance.CurrentNodeId = targetNode.NodeId;
|
|
|
|
|
|
flowInstance.Status = isAllPass ? "Completed" : "Rejected";
|
|
|
|
|
|
flowInstance.FinishTime = isAllPass ? DateTime.Now : null;
|
|
|
|
|
|
_sqlSugar.Updateable(flowInstance).ExecuteCommand();
|
2026-02-07 12:42:27 +08:00
|
|
|
|
|
|
|
|
|
|
// 表单状态更新
|
|
|
|
|
|
var illegalConstructionAssessmentUpdate = new IllegalConstructionAssessment()
|
|
|
|
|
|
{
|
|
|
|
|
|
Id = flowInstance.BusinessNo,
|
|
|
|
|
|
Status = isAllPass ? "Completed" : "Rejected"
|
|
|
|
|
|
};
|
2026-02-07 15:12:36 +08:00
|
|
|
|
//_sqlSugar.Updateable(illegalConstructionAssessmentUpdate).IgnoreNullColumns().ExecuteCommand();
|
|
|
|
|
|
_sqlSugar.Updateable<IllegalConstructionAssessment>()
|
|
|
|
|
|
.SetColumns(t => new IllegalConstructionAssessment() { Status = isAllPass ? "Completed" : "Rejected" })
|
|
|
|
|
|
.Where(t => t.Id == flowInstance.BusinessNo).ExecuteCommand();
|
2026-02-04 20:40:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 完成流程实例(结束节点)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void CompleteFlowInstance(ZyFlowInstance flowInstance)
|
|
|
|
|
|
{
|
|
|
|
|
|
flowInstance.Status = "Completed";
|
|
|
|
|
|
flowInstance.FinishTime = DateTime.Now;
|
|
|
|
|
|
_sqlSugar.Updateable(flowInstance).ExecuteCommand();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 为审核科创建工作项
|
|
|
|
|
|
/// </summary>
|
2026-02-08 12:29:33 +08:00
|
|
|
|
private void CreateAuditDeptWorkitem(long instanceId, ZyFlowNode parallelNode, List<long> orgIds)
|
2026-02-04 20:40:22 +08:00
|
|
|
|
{
|
2026-02-08 12:29:33 +08:00
|
|
|
|
var orgs = _sqlSugar.Queryable<SysOrg>()
|
|
|
|
|
|
.Where(a => orgIds.Contains(a.Id)).ToList();
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 获取科室用户信息
|
2026-02-08 12:29:33 +08:00
|
|
|
|
/*var userInfos = _sqlSugar
|
2026-02-06 10:25:19 +08:00
|
|
|
|
.Queryable<SysUser>()
|
|
|
|
|
|
.LeftJoin<SysUserRole>((u, ur) => u.Id == ur.UserId)
|
|
|
|
|
|
.LeftJoin<SysUserOrg>((u, ur, uo) => u.Id == uo.UserId)
|
|
|
|
|
|
.LeftJoin<SysOrg>((u, ur, uo, o) => uo.OrgId == o.Id)
|
|
|
|
|
|
.Where((u, ur, uo, o) => ur.RoleId == parallelNode.RoleId)
|
|
|
|
|
|
.Select((u, ur, uo, o) => new
|
|
|
|
|
|
{
|
|
|
|
|
|
userName = u.Name,
|
|
|
|
|
|
userId = u.Id,
|
|
|
|
|
|
deptName = o.Name
|
|
|
|
|
|
})
|
2026-02-08 12:29:33 +08:00
|
|
|
|
.ToList();*/
|
|
|
|
|
|
foreach (var org in orgs)
|
2026-02-04 20:40:22 +08:00
|
|
|
|
{
|
2026-02-06 10:25:19 +08:00
|
|
|
|
// 创建工作项
|
|
|
|
|
|
var workitem = new ZyFlowWorkitem
|
|
|
|
|
|
{
|
|
|
|
|
|
InstanceId = instanceId,
|
|
|
|
|
|
NodeId = parallelNode.NodeId,
|
2026-02-08 12:29:33 +08:00
|
|
|
|
NodeName = $"{parallelNode.NodeName}",
|
2026-02-06 10:25:19 +08:00
|
|
|
|
Status = "ToDo",
|
|
|
|
|
|
ReceiveTime = DateTime.Now,
|
2026-02-08 12:29:33 +08:00
|
|
|
|
Comment = "请完成违法建设认定相关审核工作",
|
|
|
|
|
|
OrgId = org.Id,
|
|
|
|
|
|
OrgName = org.Name
|
2026-02-06 10:25:19 +08:00
|
|
|
|
};
|
|
|
|
|
|
_sqlSugar.Insertable(workitem).ExecuteCommand();
|
|
|
|
|
|
}
|
2026-02-05 09:08:32 +08:00
|
|
|
|
}
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 保存附件并返回路径
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private string SaveAttachments(List<IFormFile> attachments)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (attachments == null || !attachments.Any())
|
|
|
|
|
|
return string.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
// 定义附件存储目录
|
2026-02-05 09:55:29 +08:00
|
|
|
|
var uploadDir = Path
|
|
|
|
|
|
.Combine(AppContext.BaseDirectory, "Attachments/FlowAttachments");
|
2026-02-05 09:08:32 +08:00
|
|
|
|
if (!Directory.Exists(uploadDir))
|
|
|
|
|
|
Directory.CreateDirectory(uploadDir);
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
var attachmentPaths = new List<string>();
|
|
|
|
|
|
foreach (var file in attachments)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (file.Length <= 0)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
// 生成唯一文件名
|
|
|
|
|
|
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
|
|
|
|
|
|
var filePath = Path.Combine(uploadDir, fileName);
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 保存文件
|
|
|
|
|
|
using (var stream = new FileStream(filePath, FileMode.Create))
|
2026-02-04 20:40:22 +08:00
|
|
|
|
{
|
2026-02-05 09:08:32 +08:00
|
|
|
|
file.CopyTo(stream);
|
2026-02-04 21:43:24 +08:00
|
|
|
|
}
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
// 保存相对路径(用于前端访问)
|
|
|
|
|
|
attachmentPaths.Add($"/Attachments/FlowAttachments/{fileName}");
|
|
|
|
|
|
}
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
return string.Join(",", attachmentPaths);
|
|
|
|
|
|
}
|
2026-02-04 20:40:22 +08:00
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据节点类型获取流程状态
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private string GetFlowStatusByNodeType(string nodeType)
|
|
|
|
|
|
{
|
2026-02-10 15:18:24 +08:00
|
|
|
|
//执法监督科转发 Common
|
|
|
|
|
|
//审核科审核 Parallel
|
|
|
|
|
|
//汇总判断 Branch
|
|
|
|
|
|
//流程归档 End
|
|
|
|
|
|
//退回区县修改 End
|
2026-02-05 09:08:32 +08:00
|
|
|
|
return nodeType switch
|
2026-02-04 20:40:22 +08:00
|
|
|
|
{
|
2026-02-10 16:42:33 +08:00
|
|
|
|
/*"Common" => "Submitted", // 转发
|
|
|
|
|
|
"Parallel" => "Forwarded", // 审核
|
|
|
|
|
|
"Branch" => "Auditing", // 汇总
|
|
|
|
|
|
"End" => "Completed", // 已完成
|
|
|
|
|
|
_ => "Submitted" // 已提交(这个状态只要一瞬间,前端不可见)*/
|
2026-02-10 15:18:24 +08:00
|
|
|
|
"Common" => "Forwarded", // 将要转发
|
|
|
|
|
|
"Parallel" => "Auditing", // 将要审核
|
|
|
|
|
|
"Branch" => "Summarized", // 将要汇总
|
2026-02-05 09:08:32 +08:00
|
|
|
|
"End" => "Completed", // 已完成
|
2026-02-10 15:18:24 +08:00
|
|
|
|
_ => "Submitted" // 已提交(这个状态只要一瞬间,前端不可见)
|
2026-02-05 09:08:32 +08:00
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取用户所属科室名称
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private string GetUserDeptName(long userId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var deptName = _sqlSugar.Queryable<SysUserOrg, SysOrg>((uo, o) => new JoinQueryInfos(
|
|
|
|
|
|
JoinType.Inner, uo.OrgId == o.Id))
|
|
|
|
|
|
.Where((uo, o) => uo.UserId == userId)
|
|
|
|
|
|
.Select((uo, o) => o.Name)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
|
|
|
|
|
|
return deptName ?? "未知科室";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取角色下第一个用户的完整信息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private (long userId, string userName, string deptName) GetRoleFirstUserInfo(long roleId)
|
|
|
|
|
|
{
|
2026-02-05 09:51:56 +08:00
|
|
|
|
var userInfo = _sqlSugar
|
2026-02-06 09:10:12 +08:00
|
|
|
|
.Queryable<SysUserRole, SysUser, SysUserOrg, SysOrg>((ur, u, uo, o)
|
|
|
|
|
|
=> new JoinQueryInfos(
|
|
|
|
|
|
JoinType.Inner, ur.UserId == u.Id && u.Id == uo.UserId && uo.OrgId == o.Id))
|
|
|
|
|
|
.Where((ur, u, uo, o) => ur.RoleId == roleId)
|
|
|
|
|
|
.Select((ur, u, uo, o) => new
|
2026-02-05 09:51:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
UserId = u.Id,
|
|
|
|
|
|
UserName = u.Name,
|
2026-02-06 09:10:12 +08:00
|
|
|
|
DeptName = o.Name
|
2026-02-05 09:51:56 +08:00
|
|
|
|
})
|
2026-02-05 09:08:32 +08:00
|
|
|
|
.First();
|
|
|
|
|
|
|
2026-02-05 09:51:56 +08:00
|
|
|
|
if (userInfo == null)
|
|
|
|
|
|
return (0, string.Empty, string.Empty);
|
|
|
|
|
|
|
2026-02-05 09:08:32 +08:00
|
|
|
|
return (userInfo.UserId, userInfo.UserName ?? string.Empty, userInfo.DeptName ?? string.Empty);
|
2026-02-04 20:40:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
2026-02-05 10:54:15 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 保存拟办
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="requestDto"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
2026-02-06 16:47:31 +08:00
|
|
|
|
public bool SaveDraft(InitiateFlowRequestDto requestDto)
|
2026-02-05 10:54:15 +08:00
|
|
|
|
{
|
2026-02-06 15:03:34 +08:00
|
|
|
|
try
|
2026-02-05 10:54:15 +08:00
|
|
|
|
{
|
2026-02-07 09:52:38 +08:00
|
|
|
|
if (string.IsNullOrEmpty(requestDto.BusinessNo))
|
2026-02-06 15:03:34 +08:00
|
|
|
|
{
|
2026-02-08 10:36:08 +08:00
|
|
|
|
var businessNo = _businessNoGenerator.GenerateBusinessNo(prefix);
|
2026-02-07 09:52:38 +08:00
|
|
|
|
UnitWork.Db.Ado.BeginTran();
|
|
|
|
|
|
var user = _auth.GetCurrentUser().User;
|
|
|
|
|
|
var illegalConstructionAssessment = new IllegalConstructionAssessment
|
|
|
|
|
|
{
|
|
|
|
|
|
Id = businessNo,
|
|
|
|
|
|
Title = requestDto.Title,
|
2026-02-07 13:10:19 +08:00
|
|
|
|
BusinessNumber = businessNo,
|
2026-02-07 09:52:38 +08:00
|
|
|
|
AcceptanceTime = DateTime.Now,
|
|
|
|
|
|
Status = "Draft",
|
2026-02-07 10:44:13 +08:00
|
|
|
|
Type = requestDto.Type,
|
2026-02-07 09:52:38 +08:00
|
|
|
|
CreateTime = DateTime.Now,
|
|
|
|
|
|
CreateUser = user.Name,
|
|
|
|
|
|
UpdateTime = DateTime.Now,
|
|
|
|
|
|
CreateUserId = user.Id
|
|
|
|
|
|
};
|
2026-02-07 16:55:10 +08:00
|
|
|
|
if (!requestDto.Attachments.IsEmpty())
|
|
|
|
|
|
{
|
|
|
|
|
|
var attachmentPaths = string.Join(",", requestDto.Attachments);
|
|
|
|
|
|
illegalConstructionAssessment.Attachments = attachmentPaths;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-07 09:52:38 +08:00
|
|
|
|
_sqlSugar.Insertable(illegalConstructionAssessment).ExecuteCommand();
|
2026-02-06 16:47:31 +08:00
|
|
|
|
|
2026-02-07 09:52:38 +08:00
|
|
|
|
var template = _sqlSugar.Queryable<ZyFlowTemplate>()
|
|
|
|
|
|
.Where(t => t.FlowCode == requestDto.FlowCode && t.IsEnabled == true)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
if (template == null)
|
|
|
|
|
|
throw new Exception($"流程模板【{requestDto.FlowCode}】不存在或未启用");
|
2026-02-06 15:03:34 +08:00
|
|
|
|
|
2026-02-07 09:52:38 +08:00
|
|
|
|
// 步骤2:查询流程开始节点(区县提交)
|
|
|
|
|
|
var startNode = _sqlSugar.Queryable<ZyFlowNode>()
|
|
|
|
|
|
.Where(n => n.TemplateId == template.TemplateId && n.NodeType == "Start" && n.NodeName == "区县提交")
|
|
|
|
|
|
.First();
|
|
|
|
|
|
if (startNode == null)
|
|
|
|
|
|
throw new Exception("流程开始节点【区县提交】不存在,请配置节点");
|
|
|
|
|
|
var flowInstance = new ZyFlowInstance
|
|
|
|
|
|
{
|
|
|
|
|
|
TemplateId = template.TemplateId,
|
|
|
|
|
|
FlowCode = template.FlowCode,
|
|
|
|
|
|
BusinessNo = businessNo,
|
|
|
|
|
|
Status = "Draft", // 已提交
|
|
|
|
|
|
CurrentNodeId = startNode.NodeId,
|
|
|
|
|
|
InitiatorId = user.Id,
|
|
|
|
|
|
InitiatorName = user.Name,
|
|
|
|
|
|
CreateTime = DateTime.Now
|
|
|
|
|
|
};
|
|
|
|
|
|
var instanceId = _sqlSugar.Insertable(flowInstance).ExecuteReturnIdentity();
|
|
|
|
|
|
// 步骤4:插入开始节点工作项(直接标记为已完成)
|
|
|
|
|
|
// 开始节点无ToDo
|
|
|
|
|
|
var startWorkitem = new ZyFlowWorkitem
|
|
|
|
|
|
{
|
|
|
|
|
|
InstanceId = instanceId,
|
|
|
|
|
|
NodeId = startNode.NodeId,
|
|
|
|
|
|
NodeName = startNode.NodeName,
|
|
|
|
|
|
HandlerId = user.Id,
|
|
|
|
|
|
HandlerName = user.Name,
|
|
|
|
|
|
Status = "Draft", // 已完成
|
|
|
|
|
|
ReceiveTime = DateTime.Now,
|
|
|
|
|
|
HandleTime = DateTime.Now,
|
2026-02-08 15:05:41 +08:00
|
|
|
|
Comment = "提交材料"
|
2026-02-07 09:52:38 +08:00
|
|
|
|
};
|
|
|
|
|
|
_sqlSugar.Insertable(startWorkitem).ExecuteCommand();
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
2026-02-06 15:03:34 +08:00
|
|
|
|
{
|
2026-02-07 09:52:38 +08:00
|
|
|
|
UnitWork.Db.Ado.BeginTran();
|
|
|
|
|
|
var illegalConstructionAssessment = _sqlSugar.Queryable<IllegalConstructionAssessment>()
|
|
|
|
|
|
.Where(i => i.Id == requestDto.BusinessNo)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
if (illegalConstructionAssessment == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception($"该拟办不存在");
|
|
|
|
|
|
}
|
2026-02-06 16:47:31 +08:00
|
|
|
|
|
2026-02-09 11:16:34 +08:00
|
|
|
|
illegalConstructionAssessment.Title = requestDto.Title;
|
|
|
|
|
|
illegalConstructionAssessment.AcceptanceTime = DateTime.Now;
|
|
|
|
|
|
//Status = "Draft",
|
|
|
|
|
|
illegalConstructionAssessment.Type = requestDto.Type;
|
|
|
|
|
|
illegalConstructionAssessment.UpdateTime = DateTime.Now;
|
|
|
|
|
|
|
2026-02-07 16:55:10 +08:00
|
|
|
|
if (!requestDto.Attachments.IsEmpty())
|
2026-02-07 09:52:38 +08:00
|
|
|
|
{
|
2026-02-07 16:55:10 +08:00
|
|
|
|
var attachmentPaths = string.Join(",", requestDto.Attachments);
|
|
|
|
|
|
illegalConstructionAssessment.Attachments = attachmentPaths;
|
2026-02-07 09:52:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-27 10:31:55 +08:00
|
|
|
|
_sqlSugar.Updateable(illegalConstructionAssessment)
|
|
|
|
|
|
.IgnoreColumns(ignoreAllNullColumns: true, ignoreAllDefaultValue: true).ExecuteCommand();
|
2026-02-07 09:52:38 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2026-02-06 15:03:34 +08:00
|
|
|
|
}
|
2026-02-06 16:47:31 +08:00
|
|
|
|
catch (Exception ex)
|
2026-02-06 15:03:34 +08:00
|
|
|
|
{
|
|
|
|
|
|
UnitWork.Db.Ado.RollbackTran();
|
2026-02-06 16:47:31 +08:00
|
|
|
|
throw;
|
|
|
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
UnitWork.Db.Ado.CommitTran();
|
2026-02-06 15:03:34 +08:00
|
|
|
|
}
|
2026-02-05 10:54:15 +08:00
|
|
|
|
}
|
2026-02-06 10:59:54 +08:00
|
|
|
|
|
|
|
|
|
|
public dynamic Detail(string businessNo)
|
|
|
|
|
|
{
|
2026-02-07 18:17:58 +08:00
|
|
|
|
var instance = _sqlSugar
|
|
|
|
|
|
.Queryable<ZyFlowInstance>()
|
|
|
|
|
|
.Where(i => i.BusinessNo == businessNo)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
if (instance == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception($"流程实例不存在");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var workItems = _sqlSugar
|
|
|
|
|
|
.Queryable<ZyFlowWorkitem>()
|
2026-02-27 10:31:55 +08:00
|
|
|
|
.LeftJoin<ZyFlowNode>((w, n) => w.NodeId == n.NodeId)
|
2026-02-08 14:43:39 +08:00
|
|
|
|
.Where(w => w.InstanceId == instance.InstanceId && w.Status == "Done")
|
2026-02-07 18:17:58 +08:00
|
|
|
|
.OrderByDescending(w => w.WorkitemId)
|
2026-02-27 10:31:55 +08:00
|
|
|
|
.Select((w, n) => new
|
2026-02-07 18:29:44 +08:00
|
|
|
|
ZyFlowWorkitem
|
|
|
|
|
|
{
|
|
|
|
|
|
WorkitemId = w.WorkitemId,
|
|
|
|
|
|
Comment = w.Comment,
|
2026-02-27 10:31:55 +08:00
|
|
|
|
AuditComment = w.Comment, // 并行节点审核意见
|
|
|
|
|
|
AuditResult = w.AuditResult,
|
2026-02-07 18:29:44 +08:00
|
|
|
|
Status = w.Status,
|
|
|
|
|
|
ReceiveTime = w.ReceiveTime,
|
|
|
|
|
|
HandleTime = w.HandleTime,
|
|
|
|
|
|
HandlerName = w.HandlerName,
|
2026-02-08 09:59:32 +08:00
|
|
|
|
HandlerId = w.HandlerId,
|
2026-02-08 09:56:25 +08:00
|
|
|
|
NodeName = w.NodeName,
|
2026-02-08 14:44:53 +08:00
|
|
|
|
NodeType = n.NodeType,
|
|
|
|
|
|
OrgName = w.OrgName
|
2026-02-07 18:29:44 +08:00
|
|
|
|
})
|
2026-02-07 18:17:58 +08:00
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
|
|
var illegalConstructionAssessment = _sqlSugar
|
2026-02-06 10:59:54 +08:00
|
|
|
|
.Queryable<IllegalConstructionAssessment>()
|
2026-02-10 15:18:24 +08:00
|
|
|
|
.LeftJoin<ZyFlowInstance>((t, i) => t.BusinessNumber == i.BusinessNo)
|
2026-02-10 15:56:51 +08:00
|
|
|
|
.Where((t, i) => t.Id == businessNo)
|
2026-02-10 15:18:24 +08:00
|
|
|
|
.Select((t, i) => new IllegalConstructionAssessment()
|
|
|
|
|
|
{
|
|
|
|
|
|
Id = t.Id,
|
|
|
|
|
|
Title = t.Title,
|
|
|
|
|
|
BusinessNumber = t.BusinessNumber,
|
|
|
|
|
|
Attachments = t.Attachments,
|
|
|
|
|
|
AcceptanceTime = t.AcceptanceTime,
|
|
|
|
|
|
ReceiveTime = t.ReceiveTime,
|
|
|
|
|
|
Type = t.Type,
|
|
|
|
|
|
CreateTime = t.CreateTime,
|
|
|
|
|
|
CreateUser = t.CreateUser,
|
|
|
|
|
|
UpdateTime = t.UpdateTime,
|
|
|
|
|
|
CreateUserId = t.CreateUserId,
|
|
|
|
|
|
UpdateUser = t.UpdateUser,
|
|
|
|
|
|
Status = i.Status,
|
|
|
|
|
|
Remark = t.Remark
|
|
|
|
|
|
})
|
2026-02-06 10:59:54 +08:00
|
|
|
|
.First();
|
2026-02-07 18:17:58 +08:00
|
|
|
|
illegalConstructionAssessment.Workitems = workItems;
|
|
|
|
|
|
return illegalConstructionAssessment;
|
2026-02-06 10:59:54 +08:00
|
|
|
|
}
|
2026-02-08 08:53:38 +08:00
|
|
|
|
|
|
|
|
|
|
public dynamic GetUserInfoWithDept(long workitemId)
|
|
|
|
|
|
{
|
|
|
|
|
|
// todo 查询下一节点绑定的角色,获取角色下所有用户及部门信息
|
|
|
|
|
|
var workitem = _sqlSugar
|
|
|
|
|
|
.Queryable<ZyFlowWorkitem>()
|
|
|
|
|
|
.Where(w => w.WorkitemId == workitemId)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
if (workitem == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception($"工作项不存在");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var node = _sqlSugar
|
|
|
|
|
|
.Queryable<ZyFlowNode>()
|
|
|
|
|
|
.Where(n => n.NodeId == workitem.NodeId)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
var nodeStr = node.NextNodeIds;
|
|
|
|
|
|
var firstNode = long.Parse(nodeStr.Split(",")[0]);
|
|
|
|
|
|
var nextNode = _sqlSugar
|
|
|
|
|
|
.Queryable<ZyFlowNode>()
|
|
|
|
|
|
.Where(n => n.NodeId == firstNode)
|
|
|
|
|
|
.First();
|
|
|
|
|
|
var roleId = nextNode.RoleId;
|
|
|
|
|
|
// var (userId, userName, deptName) = GetRoleFirstUserInfo(roleId);
|
|
|
|
|
|
var usrInfo = _sqlSugar
|
|
|
|
|
|
.Queryable<SysUser>()
|
|
|
|
|
|
.LeftJoin<SysUserRole>((u, ur) => u.Id == ur.UserId)
|
|
|
|
|
|
.LeftJoin<SysUserOrg>((u, ur, uo) => u.Id == uo.UserId)
|
|
|
|
|
|
.LeftJoin<SysOrg>((u, ur, uo, o) => uo.OrgId == o.Id)
|
|
|
|
|
|
.Where((u, ur, uo, o) => ur.RoleId == roleId)
|
|
|
|
|
|
.Select((u, ur, uo, o) => new
|
|
|
|
|
|
{
|
2026-02-08 09:03:59 +08:00
|
|
|
|
UserId = u.Id,
|
2026-02-08 08:53:38 +08:00
|
|
|
|
UserName = u.Name,
|
|
|
|
|
|
Dept = o.Name
|
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
return usrInfo;
|
|
|
|
|
|
}
|
2026-02-08 11:53:44 +08:00
|
|
|
|
|
|
|
|
|
|
public dynamic ListSupervisionOrg()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 监督
|
|
|
|
|
|
// 取得roleId // 取得角色下的用户及部门信息,部门信息去重
|
|
|
|
|
|
var orgs = _sqlSugar
|
|
|
|
|
|
.Queryable<SysOrg>()
|
|
|
|
|
|
.LeftJoin<SysUserOrg>((o, uo) => o.Id == uo.OrgId)
|
|
|
|
|
|
.LeftJoin<SysUserRole>((o, uo, ur) => uo.UserId == ur.UserId)
|
|
|
|
|
|
.LeftJoin<SysRole>((o, uo, ur, r) => ur.RoleId == r.Id)
|
2026-02-08 13:40:59 +08:00
|
|
|
|
.Where((o, uo, ur, r) => r.Id == 770508474880069L)
|
2026-02-09 15:17:45 +08:00
|
|
|
|
.GroupBy((o, uo, ur, r) => o.Id)
|
2026-02-08 12:01:57 +08:00
|
|
|
|
.Select((o, uo, ur, r) => new
|
2026-02-08 11:53:44 +08:00
|
|
|
|
{
|
2026-02-08 12:01:57 +08:00
|
|
|
|
o.Name,
|
|
|
|
|
|
o.Id
|
2026-02-08 11:53:44 +08:00
|
|
|
|
})
|
|
|
|
|
|
.ToList();
|
|
|
|
|
|
return orgs;
|
|
|
|
|
|
}
|
2026-02-04 20:40:22 +08:00
|
|
|
|
}
|