WorkflowController.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. using Hotline.Application.FlowEngine;
  2. using Hotline.FlowEngine.Definitions;
  3. using Hotline.FlowEngine.Workflows;
  4. using Hotline.Identity.Roles;
  5. using Hotline.Permissions;
  6. using Hotline.Repository.SqlSugar.Extensions;
  7. using Hotline.Settings;
  8. using Hotline.Share.Dtos;
  9. using Hotline.Share.Dtos.FlowEngine;
  10. using Hotline.Share.Enums.FlowEngine;
  11. using Hotline.Users;
  12. using MapsterMapper;
  13. using Microsoft.AspNetCore.Mvc;
  14. using SqlSugar;
  15. using Hotline.FlowEngine.WorkflowModules;
  16. using Microsoft.AspNetCore.Authorization;
  17. using XF.Domain.Authentications;
  18. using XF.Domain.Exceptions;
  19. using XF.Domain.Extensions;
  20. using XF.Utility.EnumExtensions;
  21. using XF.Domain.Repository;
  22. using Hotline.Share.Dtos.FlowEngine.Workflow;
  23. namespace Hotline.Api.Controllers;
  24. /// <summary>
  25. /// 工作流管理
  26. /// </summary>
  27. public class WorkflowController : BaseController
  28. {
  29. private readonly IDefinitionDomainService _definitionDomainService;
  30. private readonly IRepository<WorkflowDefinition> _definitionRepository;
  31. private readonly IWorkflowApplication _workflowApplication;
  32. private readonly IWorkflowDomainService _workflowDomainService;
  33. private readonly IWorkflowRepository _workflowRepository;
  34. private readonly IRepository<User> _userRepository;
  35. private readonly ISystemOrganizeRepository _organizeRepository;
  36. private readonly IRepository<Role> _roleRepository;
  37. private readonly ISystemDomainService _systemDomainService;
  38. private readonly IWfModuleDomainService _wfModuleDomainService;
  39. private readonly IRepository<WorkflowModule> _wfModuleRepository;
  40. private readonly ISessionContext _sessionContext;
  41. private IRepository<WorkflowTrace> _workflowTraceRepository;
  42. private readonly IMapper _mapper;
  43. public WorkflowController(
  44. IDefinitionDomainService definitionDomainService,
  45. IRepository<WorkflowDefinition> definitionRepository,
  46. IWorkflowApplication workflowApplication,
  47. IWorkflowDomainService workflowDomainService,
  48. IWorkflowRepository workflowRepository,
  49. IRepository<User> userRepository,
  50. ISystemOrganizeRepository organizeRepository,
  51. IRepository<Role> roleRepository,
  52. ISystemDomainService systemDomainService,
  53. IWfModuleDomainService wfModuleDomainService,
  54. IRepository<WorkflowModule> wfModuleRepository,
  55. ISessionContext sessionContext,
  56. IRepository<WorkflowTrace> workflowTraceRepository,
  57. IMapper mapper
  58. )
  59. {
  60. _definitionDomainService = definitionDomainService;
  61. _definitionRepository = definitionRepository;
  62. _workflowApplication = workflowApplication;
  63. _workflowDomainService = workflowDomainService;
  64. _workflowRepository = workflowRepository;
  65. _userRepository = userRepository;
  66. _organizeRepository = organizeRepository;
  67. _roleRepository = roleRepository;
  68. _systemDomainService = systemDomainService;
  69. _wfModuleDomainService = wfModuleDomainService;
  70. _wfModuleRepository = wfModuleRepository;
  71. _sessionContext = sessionContext;
  72. _mapper = mapper;
  73. _workflowTraceRepository = workflowTraceRepository;
  74. }
  75. /// <summary>
  76. /// 分页查询最新版本号的模板
  77. /// </summary>
  78. /// <param name="dto"></param>
  79. /// <returns></returns>
  80. [HttpGet("definition/latest")]
  81. public async Task<PagedDto<DefinitionDto>> QueryDefinitionLatest([FromQuery] QueryDefinitionDto dto)
  82. {
  83. var query2 = await _definitionRepository.Queryable()
  84. .WhereIF(dto.Status.HasValue, d => d.Status == dto.Status)
  85. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Code.Contains(dto.Keyword) || d.Name.Contains(dto.Keyword))
  86. .Select(d => new { i = SqlFunc.RowNumber($"{d.Version} desc", d.Code), d })
  87. .MergeTable()
  88. .Where(d => d.i == 1)
  89. .ToListAsync();
  90. var items = query2.Select(d => d.d).ToList();
  91. return new PagedDto<DefinitionDto>(query2.Count, _mapper.Map<IReadOnlyList<DefinitionDto>>(items));
  92. }
  93. /// <summary>
  94. /// 分页查询流程模板
  95. /// </summary>
  96. /// <param name="dto"></param>
  97. /// <returns></returns>
  98. [Permission(EPermission.FlowDefinitionQuery)]
  99. [HttpGet("definition")]
  100. public async Task<PagedDto<DefinitionDto>> QueryDefinitions([FromQuery] QueryDefinitionDto dto)
  101. {
  102. #region old version:只查询草稿、禁用以及已启用模板的最新版本
  103. ////todo 数据量大需重构
  104. //var query1 = await _definitionRepository.Queryable()
  105. // .Where(d => d.Status == EDefinitionStatus.Temporary)
  106. // .ToListAsync();
  107. //var query2 = await _definitionRepository.Queryable()
  108. // .Where(d => d.Status != EDefinitionStatus.Temporary)
  109. // .Select(d => new { i = SqlFunc.RowNumber($"{d.Version} desc", d.Code), d })
  110. // .MergeTable()
  111. // .Where(d => d.i == 1)
  112. // .ToListAsync();
  113. //var query = query1.Union(query2.Select(d => d.d));
  114. //var total = query.Count();
  115. //var items = query
  116. // .OrderBy(d => d.Status)
  117. // .ThenByDescending(d => d.CreationTime)
  118. // .Skip(dto.Skip())
  119. // .Take(dto.PageSize)
  120. // .ToList();
  121. #endregion
  122. var (total, items) = await _definitionRepository.Queryable()
  123. .WhereIF(dto.Status.HasValue, d => d.Status == dto.Status)
  124. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Code.Contains(dto.Keyword!) || d.Name.Contains(dto.Keyword!))
  125. .OrderBy(d => d.Status)
  126. .OrderBy(d => d.Code)
  127. .OrderByDescending(d => d.Version)
  128. .ToPagedListAsync(dto, HttpContext.RequestAborted);
  129. return new PagedDto<DefinitionDto>(total, _mapper.Map<IReadOnlyList<DefinitionDto>>(items));
  130. }
  131. /// <summary>
  132. /// 查询流程模板
  133. /// </summary>
  134. /// <param name="id"></param>
  135. /// <returns></returns>
  136. [Permission(EPermission.GetFlow)]
  137. [HttpGet("definition/{id}")]
  138. public async Task<DefinitionDto> GetDefinition(string id)
  139. {
  140. var definition = await _definitionRepository.GetAsync(id, HttpContext.RequestAborted);
  141. if (definition == null) return new();
  142. return _mapper.Map<DefinitionDto>(definition);
  143. }
  144. /// <summary>
  145. /// 新增流程模板草稿
  146. /// </summary>
  147. /// <param name="dto"></param>
  148. /// <returns></returns>
  149. [Permission(EPermission.FlowDefinitionAdd)]
  150. [HttpPost("definition")]
  151. public async Task<string> AddDefinition([FromBody] AddDefinitionDto dto)
  152. {
  153. return await _definitionDomainService.AddAsync(dto, HttpContext.RequestAborted);
  154. }
  155. /// <summary>
  156. /// 更新流程模板草稿
  157. /// </summary>
  158. /// <param name="dto"></param>
  159. /// <returns></returns>
  160. [Permission(EPermission.FlowDefinitionUpdate)]
  161. [HttpPut("definition")]
  162. public async Task UpdateDefinition([FromBody] UpdateDefinitionDto dto)
  163. {
  164. var definition = await _definitionRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  165. if (definition == null)
  166. throw UserFriendlyException.SameMessage("无效模板编号");
  167. if (definition.Status == EDefinitionStatus.Temporary)
  168. {
  169. _mapper.Map(dto, definition);
  170. await _definitionRepository.UpdateAsync(definition, HttpContext.RequestAborted);
  171. }
  172. else
  173. {
  174. var newDefinition = _mapper.Map<WorkflowDefinition>(dto);
  175. await _definitionRepository.AddAsync(newDefinition, HttpContext.RequestAborted);
  176. }
  177. }
  178. /// <summary>
  179. /// 删除草稿
  180. /// </summary>
  181. /// <param name="id"></param>
  182. /// <returns></returns>
  183. /// <exception cref="UserFriendlyException"></exception>
  184. [Permission(EPermission.FlowDefinitionRemove)]
  185. [HttpDelete("definition/{id}")]
  186. public async Task RemoveDefinition(string id)
  187. {
  188. var definition = await _definitionRepository.GetAsync(id, HttpContext.RequestAborted);
  189. if (definition == null) return;
  190. if (definition.Status != EDefinitionStatus.Temporary)
  191. throw new UserFriendlyException("已发布模板不能删除");
  192. await _definitionRepository.RemoveAsync(id, false, HttpContext.RequestAborted);
  193. }
  194. /// <summary>
  195. /// 发布(列表操作)
  196. /// </summary>
  197. /// <returns></returns>
  198. [Permission(EPermission.FlowDefinitionPublish)]
  199. [HttpPost("definition/{id}/publish")]
  200. public async Task Publish(string id)
  201. {
  202. await _definitionDomainService.PublishAsync(id, HttpContext.RequestAborted);
  203. }
  204. /// <summary>
  205. /// 发布(保存并发布)
  206. /// </summary>
  207. /// <returns></returns>
  208. [Obsolete]
  209. [Permission(EPermission.FlowDefinitionPublish)]
  210. [HttpPost("definition/publish")]
  211. public async Task Publish([FromBody] AddDefinitionDto dto)
  212. {
  213. await _definitionDomainService.PublishAsync(dto, HttpContext.RequestAborted);
  214. }
  215. /// <summary>
  216. /// 分页查询流程
  217. /// </summary>
  218. /// <param name="dto"></param>
  219. /// <returns></returns>
  220. [Permission(EPermission.FlowQuery)]
  221. [HttpGet]
  222. public async Task<PagedDto<WorkflowDto>> QueryPaged([FromQuery] QueryWorkflowPagedDto dto)
  223. {
  224. var (total, items) = await _workflowRepository.Queryable()
  225. .WhereIF(!string.IsNullOrEmpty(dto.ModuleCode), d => d.ModuleCode == dto.ModuleCode)
  226. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Id.Contains(dto.Keyword!) || d.Title.Contains(dto.Keyword!))
  227. .OrderByDescending(d => d.CreationTime)
  228. .ToPagedListAsync(dto, HttpContext.RequestAborted);
  229. return new PagedDto<WorkflowDto>(total, _mapper.Map<IReadOnlyList<WorkflowDto>>(items));
  230. }
  231. /// <summary>
  232. /// 查询流程办理下一步可选节点
  233. /// </summary>
  234. [HttpGet("{workflowId}/nextsteps")]
  235. public async Task<NextStepsDto> GetNextStepDefine(string workflowId)
  236. {
  237. //var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, true, true,
  238. // cancellationToken: HttpContext.RequestAborted);
  239. //var current = _workflowDomainService.FindCurrentStep(workflow);
  240. //var nextStepDefines = workflow.WorkflowDefinition.FindStepDefines(current.StepBox.NextSteps.Select(d => d.Code));
  241. //if (current.StepBox.PathPolicy is not EPathPolicy.None && current.StepBox.NextSteps.Count > 1)
  242. // _workflowDomainService.NextStepDefineFilter(current.StepBox.PathPolicy, nextStepDefines);
  243. //return new DefinedStepDto
  244. //{
  245. // DefinitionId = workflow.DefinitionId,
  246. // Steps = _mapper.Map<IReadOnlyList<StepBasicDto>>(nextStepDefines),//nextStepDefines.Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).ToList(),
  247. // ExpiredTime = workflow.ExpiredTime,
  248. // Components = current.StepBox.Components,
  249. //};
  250. return await _workflowApplication.GetNextStepsAsync(workflowId, HttpContext.RequestAborted);
  251. }
  252. ///// <summary>
  253. ///// 查询流程下一节点待选配置
  254. ///// </summary>
  255. //[HttpGet("step-options")]
  256. //public async Task<NextStepOptionDto> GetNextStepOptions([FromQuery] QueryNextStepOptionDto dto)
  257. //{
  258. // var definition = await _definitionRepository.GetAsync(dto.DefineId, HttpContext.RequestAborted);
  259. // if (definition == null)
  260. // throw new UserFriendlyException("无效DefineId");
  261. // var defineStep = definition.FindStepDefine(dto.Code);
  262. // if (defineStep is null)
  263. // throw UserFriendlyException.SameMessage("未查询到对应节点配置");
  264. // return await _workflowApplication.GetNextStepOptionsAsync(defineStep, HttpContext.RequestAborted);
  265. //}
  266. /// <summary>
  267. /// 办理节点
  268. /// </summary>
  269. [Permission(EPermission.FlowNext)]
  270. [HttpPost("next")]
  271. public async Task Next([FromBody] NextWorkflowDto dto)
  272. {
  273. await _workflowApplication.NextAsync(dto, HttpContext.RequestAborted);
  274. }
  275. /// <summary>
  276. /// 退回(返回前一节点)
  277. /// </summary>
  278. [Permission(EPermission.FlowPrevious)]
  279. [HttpPost("previous")]
  280. public async Task Previous([FromBody] PreviousWorkflowDto dto)
  281. {
  282. var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true,
  283. cancellationToken: HttpContext.RequestAborted);
  284. await _workflowDomainService.PreviousAsync(workflow, dto, HttpContext.RequestAborted);
  285. }
  286. /// <summary>
  287. /// 获取撤回可选节点
  288. /// </summary>
  289. /// <param name="workflowId"></param>
  290. /// <returns></returns>
  291. [Permission(EPermission.FlowRecall)]
  292. [HttpGet("{workflowId}/recall")]
  293. public async Task<NextStepsDto> GetRecallSteps(string workflowId)
  294. {
  295. return await _workflowApplication.GetRecallStepsAsync(workflowId, HttpContext.RequestAborted);
  296. }
  297. /// <summary>
  298. /// 撤回至任意节点
  299. /// </summary>
  300. /// <param name="dto"></param>
  301. /// <returns></returns>
  302. [Permission(EPermission.FlowRecall)]
  303. [HttpPost("recall")]
  304. public async Task Recall([FromBody] RecallDto dto)
  305. {
  306. await _workflowApplication.RecallAsync(dto, HttpContext.RequestAborted);
  307. }
  308. /// <summary>
  309. /// 获取跳转可选节点
  310. /// </summary>
  311. /// <param name="workflowId"></param>
  312. /// <returns></returns>
  313. [HttpGet("{workflowId}/jump")]
  314. public async Task<NextStepsDto> GetJumpSteps(string workflowId)
  315. {
  316. return await _workflowApplication.GetJumpStepsAsync(workflowId, HttpContext.RequestAborted);
  317. }
  318. /// <summary>
  319. /// 跳转至任意节点
  320. /// </summary>
  321. /// <param name="dto"></param>
  322. /// <returns></returns>
  323. [Permission(EPermission.FlowJump)]
  324. [HttpPost("jump")]
  325. public async Task Jump([FromBody] RecallDto dto)
  326. {
  327. await _workflowApplication.JumpAsync(dto, HttpContext.RequestAborted);
  328. }
  329. /// <summary>
  330. /// 获取重办可选节点
  331. /// </summary>
  332. /// <param name="workflowId"></param>
  333. /// <returns></returns>
  334. [HttpGet("{workflowId}/redo")]
  335. public async Task<NextStepsDto> GetRedoSteps(string workflowId)
  336. {
  337. return await _workflowApplication.GetRedoStepsAsync(workflowId, HttpContext.RequestAborted);
  338. }
  339. /// <summary>
  340. /// 终止流程
  341. /// </summary>
  342. [Permission(EPermission.FlowTerminate)]
  343. [HttpPost("terminate")]
  344. public async Task Terminate([FromBody] TerminateDto dto)
  345. {
  346. await _workflowDomainService.TerminateAsync(dto, HttpContext.RequestAborted);
  347. }
  348. /// <summary>
  349. /// 撤销流程
  350. /// </summary>
  351. [HttpPost("cancel")]
  352. public async Task Cancel([FromBody] CancelDto dto)
  353. {
  354. await _workflowDomainService.CancelAsync(dto, HttpContext.RequestAborted);
  355. }
  356. /// <summary>
  357. /// 补充
  358. /// </summary>
  359. /// <param name="dto"></param>
  360. /// <returns></returns>
  361. [Permission(EPermission.FlowSupplement)]
  362. [HttpPost("supplement")]
  363. public async Task Supplement([FromBody] SupplementDto dto)
  364. {
  365. var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId);
  366. await _workflowDomainService.SupplementAsync(workflow, dto, HttpContext.RequestAborted);
  367. }
  368. /// <summary>
  369. /// 查询办理类型参数
  370. /// </summary>
  371. [HttpGet("handlerclassify/{handlerType}")]
  372. public async Task<List<KeyValuePair<string, string>>> GetHandlerClassifies(EHandlerType handlerType)
  373. {
  374. switch (handlerType)
  375. {
  376. case EHandlerType.Role:
  377. var roles = await _roleRepository.QueryAsync();
  378. return roles.Select(d => new KeyValuePair<string, string>(d.Name, d.DisplayName)).ToList();
  379. case EHandlerType.OrgLevel:
  380. var orgs1 = await _systemDomainService.QueryOrgLevelStringOptionsAsync(HttpContext.RequestAborted);
  381. return orgs1.ToList();
  382. case EHandlerType.OrgType:
  383. return EnumExts.GetDescriptions<EOrgType>().Select(d => new KeyValuePair<string, string>(d.Key.ToString(), d.Value)).ToList();
  384. case EHandlerType.AssignedOrg:
  385. var orgs = await _organizeRepository.GetOrgJson();
  386. return orgs.Select(d => new KeyValuePair<string, string>(d.Id, d.Name)).ToList();
  387. case EHandlerType.AssignedUser:
  388. default:
  389. throw new ArgumentOutOfRangeException(nameof(handlerType), handlerType, null);
  390. }
  391. }
  392. /// <summary>
  393. /// 查询流程流转记录
  394. /// </summary>
  395. /// <param name="workflowId"></param>
  396. /// <returns></returns>
  397. [HttpGet("{workflowId}/traces")]
  398. public async Task<WorkflowDto> GetWorkflowTraces(string workflowId)
  399. {
  400. var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, cancellationToken: HttpContext.RequestAborted);
  401. workflow.Traces = await _workflowTraceRepository.Queryable()
  402. .Where(d => d.WorkflowId == workflow.Id && !string.IsNullOrEmpty(d.AcceptorId))
  403. .OrderBy(d => d.CreationTime)
  404. .ToTreeAsync(d => d.Traces, d => d.ParentId, null);
  405. return _mapper.Map<WorkflowDto>(workflow);
  406. }
  407. /// <summary>
  408. /// 查询被督办/催办部门
  409. /// </summary>
  410. /// <param name="workflowId"></param>
  411. /// <returns></returns>
  412. [HttpGet("{workflowId}/urge")]
  413. public async Task<IReadOnlyList<Kv>> GetUrgeOrgs(string workflowId)
  414. {
  415. /*
  416. * 非会签:当前部门上至一级部门
  417. * 中心会签:一级部门下至所有当前办理部门(遍历所有会签分支)
  418. */
  419. //var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withSteps: true, cancellationToken: HttpContext.RequestAborted);
  420. //var steps = workflow.Steps.Where(d => d.StepType is not EStepType.Start and not EStepType.End).ToList();
  421. //if (workflow.CounterSignType is ECounterSignType.Center)
  422. //{
  423. // var steps = workflow.Steps.Where(d=> d.StepType is not EStepType.Start and not EStepType.End)
  424. // .SelectMany(d=>d.Handlers)
  425. // .ToList();
  426. //}
  427. //else
  428. //{
  429. //}
  430. //
  431. var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withSteps: true, cancellationToken: HttpContext.RequestAborted);
  432. var stepBoxes = workflow.Steps.Where(d => d.StepType != EStepType.Start && d.StepType != EStepType.End).ToList();
  433. var steps = stepBoxes.SelectMany(d => d.Steps);
  434. var orgs = new List<Kv>();
  435. foreach (var step in steps)
  436. {
  437. var orgCode = step.HandlerOrgId ?? step.AcceptorOrgId;
  438. var orgName = step.HandlerOrgName ?? step.AcceptorOrgName;
  439. if (string.IsNullOrEmpty(orgCode))
  440. {
  441. switch (step.HandlerType)
  442. {
  443. case EHandlerType.Role:
  444. case EHandlerType.AssignedUser:
  445. //todo
  446. var users = await _userRepository.Queryable()
  447. .Includes(d => d.Organization)
  448. .Where(d => step.Handlers.Select(x => x.Key).Contains(d.Id))
  449. .ToListAsync(HttpContext.RequestAborted);
  450. orgs.AddRange(users.Select(d => new Kv(d.OrgId, d.Organization.Name)));
  451. break;
  452. case EHandlerType.OrgLevel:
  453. case EHandlerType.OrgType:
  454. case EHandlerType.AssignedOrg:
  455. orgs.AddRange(step.Handlers);
  456. break;
  457. default:
  458. throw new ArgumentOutOfRangeException();
  459. }
  460. }
  461. else
  462. {
  463. orgs.Add(new Kv(orgCode, orgName));
  464. }
  465. }
  466. return orgs.DistinctBy(d => d.Key).ToList();
  467. }
  468. [HttpGet("base-data")]
  469. public async Task<dynamic> BaseData()
  470. {
  471. var levels = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  472. var orgs = levels.Select(d => new KeyValuePair<string, string>(d.ToString(), $"{d.ToChinese()}级部门办理")).ToList();
  473. var center = new KeyValuePair<string, string>("0", "中心办理");
  474. var centerIsTop = new List<KeyValuePair<string, string>> { center };
  475. centerIsTop.AddRange(orgs);
  476. return new
  477. {
  478. ModuleOptions = WorkflowModuleConsts.AllModules.Select(d => new KeyValuePair<string, string>(d.Code, d.Name)),
  479. HandlerTypeOptions = EnumExts.GetDescriptions<EHandlerType>(),
  480. BusinessTypeOptions = EnumExts.GetDescriptions<EBusinessType>(),
  481. StepPropertiesOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.WorkflowStepComponent, HttpContext.RequestAborted),
  482. //PathPolicyOptions = EnumExts.GetDescriptions<EPathPolicy>(),
  483. ExecuteModeOptions = EnumExts.GetDescriptions<EExecuteMode>(),
  484. InstanceModeOptions = EnumExts.GetDescriptions<EInstanceMode>(),
  485. StepTypeOptions = EnumExts.GetDescriptions<EStepType>().Where(d => d.Key != 1 && d.Key != 2),
  486. DynamicPolicyOptions = EnumExts.GetDescriptions<EDynamicPolicy>()
  487. .Select(d => new
  488. {
  489. Key = d.Key,
  490. Value = d.Value,
  491. Items = d.Key == 0 || d.Key == 2 ? centerIsTop : orgs
  492. }),//todo thk
  493. };
  494. }
  495. /// <summary>
  496. /// 持久化新增工作流业务
  497. /// </summary>
  498. /// <returns></returns>
  499. [AllowAnonymous]
  500. [HttpGet("wfmodule/persistence")]
  501. public async Task PersistenceWfModule()
  502. {
  503. await _wfModuleDomainService.PersistenceModulesAsync(HttpContext.RequestAborted);
  504. }
  505. /// <summary>
  506. /// 查询所有工作流模块
  507. /// </summary>
  508. /// <returns></returns>
  509. [HttpGet("wfmodules")]
  510. public async Task<IReadOnlyList<WorkflowModule>> QueryWfModules()
  511. {
  512. return await _wfModuleRepository.Queryable()
  513. .Includes(d => d.Definition)
  514. .ToListAsync();
  515. }
  516. /// <summary>
  517. /// 为工作流业务匹配或取消流程模板
  518. /// </summary>
  519. /// <param name="dto"></param>
  520. /// <returns></returns>
  521. [HttpPut("wfmodule/match")]
  522. public async Task MatchDefinition([FromBody] MatchDefinitionDto dto)
  523. {
  524. if (string.IsNullOrEmpty(dto.DefinitionId))
  525. {
  526. //取消当前已配置模板
  527. await _wfModuleDomainService.MatchDefinitionAsync(dto, HttpContext.RequestAborted);
  528. }
  529. else
  530. {
  531. var definition = await _definitionRepository.GetAsync(dto.DefinitionId);
  532. if (definition == null)
  533. throw UserFriendlyException.SameMessage("无效模板编号");
  534. if (definition.Status != EDefinitionStatus.Enable)
  535. throw UserFriendlyException.SameMessage("该模板未发布");
  536. await _wfModuleDomainService.MatchDefinitionAsync(dto, HttpContext.RequestAborted);
  537. }
  538. }
  539. }