WorkflowController.cs 22 KB

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