123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- using Hotline.File;
- using Hotline.Share.Dtos;
- using Hotline.Share.Dtos.FlowEngine.Definition;
- using Hotline.Share.Dtos.FlowEngine.Workflow;
- using Hotline.Share.Enums.FlowEngine;
- using SqlSugar;
- using XF.Domain.Exceptions;
- namespace Hotline.FlowEngine.Workflows;
- public class WorkflowStep : StepBasicEntity
- {
- /// <summary>
- /// 配置下一步节点 & 谁被选中
- /// </summary>
- [SugarColumn(ColumnDataType = "json", IsJson = true)]
- public List<StepSimple> NextSteps { get; set; } = new();
- /// <summary>
- /// 前一级节点Id,会签汇总节点无此字段(因可能有多个上级来源)
- /// </summary>
- public string? PrevStepId { get; set; }
- public string? PrevStepCode { get; set; }
- /// <summary>
- /// 主办
- /// </summary>
- public bool IsMain { get; set; }
- /// <summary>
- /// 原生节点(区别动态生成)
- /// </summary>
- public bool IsOrigin { get; set; }
- #region 会签
- /// <summary>
- /// 会签id(或外层会签的id)
- /// </summary>
- public string? CountersignId { get; set; }
- /// <summary>
- /// 节点处于会签流程中的位置(区别直接办理会签和会签内非会签节点)
- /// outer属于特殊会签
- /// 最顶层的发起会签节点为none
- /// </summary>
- public ECountersignPosition CountersignPosition { get; set; }
- /// <summary>
- /// 会签直属办理节点
- /// </summary>
- [SugarColumn(ColumnDataType = "json", IsJson = true)]
- public List<CountersignStep>? CountersignSteps { get; set; } = new();
- /// <summary>
- /// 发起的会签是否汇总
- /// </summary>
- public bool IsStartedCountersignEnd { get; set; }
- #region 发起会签节点特有
- /// <summary>
- /// 发起会签生成会签Id(不发起会签节点无此字段)
- /// </summary>
- public string? StartCountersignId { get; set; }
- #endregion
- #region 会签汇总节点特有
- /// <summary>
- /// 是否为会签汇总节点
- /// </summary>
- public bool IsCountersignEndStep { get; set; }
- /// <summary>
- /// 开启会签节点id(会签汇总节点对应会签发起节点id)
- /// </summary>
- public string? CountersignStartStepId { get; set; }
- #endregion
- #endregion
- [Navigate(NavigateType.ManyToOne, nameof(WorkflowId))]
- public Workflow Workflow { get; set; }
- [Navigate(NavigateType.OneToOne, nameof(Id),
- nameof(Workflows.WorkflowTrace.StepId))]
- public WorkflowTrace WorkflowTrace { get; set; }
- [Navigate(NavigateType.OneToMany, nameof(WorkflowStepHandler.WorkflowStepId))]
- public List<WorkflowStepHandler> StepHandlers { get; set; }
- #region Method
- /// <summary>
- /// 是否处于会签流程中(不包含顶层发起会签节点)
- /// </summary>
- public bool IsInCountersign() => CountersignPosition != ECountersignPosition.None;
- ///// <summary>
- ///// 是否发起过会签
- ///// </summary>
- //public bool HasStartedCountersign() => !string.IsNullOrEmpty(StartCountersignId);
- /// <summary>
- /// 接办
- /// </summary>
- public void Accept(string userId, string? userName, string orgId, string? orgName, string? orgAreaCode,
- string? orgAreaName)
- {
- AcceptorId = userId;
- AcceptorName = userName;
- AcceptorOrgId = orgId;
- AcceptorOrgName = orgName;
- AcceptorOrgAreaCode = orgAreaCode;
- AcceptorOrgAreaName = orgAreaName;
- AcceptTime = DateTime.Now;
- Status = EWorkflowStepStatus.WaitForHandle;
- }
- /// <summary>
- /// 节点办理完成
- /// </summary>
- public void Handle(
- string userId, string? userName,
- string orgId, string? orgName,
- string? orgAreaCode, string? orgAreaName,
- bool orgIsCenter, string opinion, string nextStepCode)
- {
- base.Handle(userId, userName, orgId, orgName, orgAreaCode, orgAreaName, orgIsCenter, opinion);
- Status = EWorkflowStepStatus.Handled;
- if (!IsInCountersign()
- && InstanceMode is EInstanceMode.Config
- && StepType is not EStepType.End)
- {
- var step = NextSteps.FirstOrDefault(d => d.Code == nextStepCode);
- if (step != null)
- step.Selected = true;
- }
- }
- /// <summary>
- /// 会签结束
- /// </summary>
- public void CountersignEnd() => IsStartedCountersignEnd = true;
- /// <summary>
- /// 开启会签
- /// </summary>
- public void StartCountersign(string startCountersignId)
- {
- IsStartCountersign = true;
- StartCountersignId = startCountersignId;
- IsStartedCountersignEnd = false;
- }
- //public void CreateCountersignSteps(List<WorkflowStep> nextSteps) =>
- // CountersignSteps = nextSteps
- // .Select(d => new CountersignStep { StepId = d.Id })
- // .ToList();
- /// <summary>
- /// step设置为可接办状态
- /// </summary>
- public void SetAssigned() => Status = EWorkflowStepStatus.WaitForAccept;
- /// <summary>
- /// 依据当前节点获取下一节点会签状态
- /// </summary>
- /// <returns></returns>
- public ECountersignPosition GetNextStepCountersignPosition() =>
- IsStartCountersign
- ? ECountersignPosition.Inner
- : IsInCountersign()
- ? ECountersignPosition.Outer
- : ECountersignPosition.None;
- public bool IsCenter() => BusinessType is EBusinessType.Center or EBusinessType.Send;
- public bool IsOrg() => BusinessType is EBusinessType.Department;
- /// <summary>
- /// 重置节点,只清除办理痕迹(退回场景/依据会签开始节点复制会签汇总节点,将上一级节点重置等待重新办理)
- /// </summary>
- public void Reset()
- {
- HandlerId = null;
- HandlerName = null;
- HandlerOrgId = null;
- HandlerOrgName = null;
- HandlerOrgAreaCode = null;
- HandlerOrgAreaName = null;
- HandleTime = null;
- AcceptorId = null;
- AcceptorName = null;
- AcceptorOrgId = null;
- AcceptorOrgName = null;
- AcceptorOrgAreaCode = null;
- AcceptorOrgAreaName = null;
- AcceptTime = null;
- IsStartCountersign = false;
- NextSteps.ForEach(d => d.Selected = false);
- }
- /// <summary>
- /// 重置办理参数
- /// </summary>
- public void ResetParameters()
- {
- NextHandlers = new();
- NextMainHandler = null;
- NextStepCode = null;
- BackToCountersignEnd = false;
- IsSms = false;
- Opinion = null;
- FileJson = new();
- StepExpiredTime = null;
- }
- ///// <summary>
- ///// 发起会签节点发起的会签是否全都办理完成
- ///// </summary>
- ///// <returns></returns>
- //public bool StartedCountersignHasAllHandled()
- //{
- // //if (!HasStartedCountersign())
- // // throw new UserFriendlyException("该节点未发起会签");
- // //outer属于特殊会签
- // return CountersignSteps.All(d => d.Completed);
- //}
- /// <summary>
- /// 动态实例化节点是否应该终止
- /// </summary>
- /// <returns></returns>
- public bool DynamicShouldTerminal() => !string.IsNullOrEmpty(NextStepCode) && TerminalDynamicMark == NextStepCode;
- /// <summary>
- /// 是否是顶级会签汇总节点
- /// </summary>
- public bool IsTopCountersignEndStep(string? topCountersignStepId)
- {
- if (string.IsNullOrEmpty(topCountersignStepId))
- throw new UserFriendlyException($"无效顶级会签节点编号,wfId: {WorkflowId}");
- return IsCountersignEndStep && CountersignStartStepId == topCountersignStepId;
- }
- public WorkflowStepHandler?
- FindActualHandler(ICollection<string> roles, string? userId = null, string? orgId = null) =>
- StepHandlers.FirstOrDefault(d => d.IsHandler(roles, userId, orgId));
- public WorkflowStepHandler? GetActualHandler() =>
- StepHandlers.FirstOrDefault(d => d.IsActualHandler);
- #endregion
- }
- /*
- 获取开始节点下一步待选节点:
- 是否属于多次实例化配置(dynamic动态实例化配置:结合办理人动态生成待办节点)
- t:无需检查是否到结束标识,所以按配置的重复实例化策略结合当前操作人生成待办节点,如:生成x级部门办理,下一接口再选具体部门
- f:开始节点配置的下一节点集合
- 获取开始节点所选下一步节点的具体参数:
- 是否属于多次实例化配置
- t:所选x级部门返回对应办理对象集合(具体部门)
- f:按模板配置返回办理对象集合
- 获取待办节点下一步待选节点:
- 是否属于多次实例化配置(无需检查definetion,直接找到当前待办节点获取参数(需要的参数冗余至待办节点上))
- t:检查是否到结束标识(检查当前办理节点的办理对象与结束标识(orglevel:int)是否一致)
- t:返回配置的下一节点(看作单次实例化,当前节点已办完)//definitionId,stepCodes,按配置走
- f:按配置的重复实例化策略结合当前操作人,生成如:{x:X级部门办理},{0:中心办理},最高级最多只能到中心,按动态策略走,动态策略枚举
- 是否处于会签中
- t:按会签策略的下一级 + 上一级(isCSEnd会签汇总节点标记),并对上一级选项打上标记,如:{x:X级部门办理},{0:中心办理},按动态策略走,动态策略枚举
- f:按照definition(按配置走)
- 返回当前节点的配置下一步
- 获取下一步的具体参数:
- 检查模式
- 按动态策略:依据当前操作人、动态类型枚举 查询对应待选部门
- 按配置策略:原有实现方案
- start:
- check配置是否允许当前用户发起
- next: (nextStepCode/x, userId[]/orgId[],dto.other)
- check该不该当前用户办(handlers,all不需要check)
- 办理当前节点
- 创建后面节点
- 是否动态实例化
- t:检查是否到结束标识(参数orgId==mark?)
- t:(参数时stepcode)按配置创建
- f:(参数是x级部门)按动态实例化策略创建
- 是否处于会签中
- t: 是否返回上一级汇总 (isCSEnd)
- t: 1.update上一级的会签完成情况[]
- 2.如果会签全完成,创建新的待办汇总节点(IsCountersignSummaryStep = true)?更新发起节点状态?thk
- f: 创建新的下一步节点
- */
|