KnowledgeDomainService.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. using DotNetCore.CAP;
  2. using Hotline.Caching.Interfaces;
  3. using Hotline.FlowEngine;
  4. using Hotline.FlowEngine.WorkflowModules;
  5. using Hotline.FlowEngine.Workflows;
  6. using Hotline.Settings;
  7. using Hotline.Share.Dtos.Knowledge;
  8. using Hotline.Share.Enums.KnowledgeBase;
  9. using Hotline.Share.Mq;
  10. using MapsterMapper;
  11. using SqlSugar;
  12. using XF.Domain.Dependency;
  13. using XF.Domain.Entities;
  14. using XF.Domain.Exceptions;
  15. using XF.Domain.Repository;
  16. namespace Hotline.KnowledgeBase
  17. {
  18. public class KnowledgeDomainService : IKnowledgeDomainService, IScopeDependency
  19. {
  20. private readonly IKnowledgeRepository _knowledgeRepository;
  21. private readonly IMapper _mapper;
  22. private readonly IRepository<KnowledgePv> _knowledgePVRepository;
  23. private readonly IKnowledgeWorkFlowRepository _knowledgeWorkFlowRepository;
  24. private readonly ICapPublisher _capPublisher;
  25. private readonly ISystemSettingCacheManager _systemSettingCacheManager;
  26. private readonly IRepository<KnowledgeRelationType> _relationTypeRepository;
  27. private readonly IRepository<KnowledgeType> _knowledgeTypeRepository;
  28. /// <summary>
  29. ///
  30. /// </summary>
  31. /// <param name="knowledgeRepository"></param>
  32. /// <param name="mapper"></param>
  33. /// <param name="knowledgePVRepository"></param>
  34. /// <param name="knowledgeWorkFlowRepository"></param>
  35. /// <param name="capPublisher"></param>
  36. /// <param name="systemSettingCacheManager"></param>
  37. /// <param name="relationTypeRepository"></param>
  38. /// <param name="knowledgeTypeRepository"></param>
  39. public KnowledgeDomainService(IKnowledgeRepository knowledgeRepository,
  40. IMapper mapper,
  41. IRepository<KnowledgePv> knowledgePVRepository,
  42. IKnowledgeWorkFlowRepository knowledgeWorkFlowRepository,
  43. ICapPublisher capPublisher, ISystemSettingCacheManager systemSettingCacheManager,
  44. IRepository<KnowledgeRelationType> relationTypeRepository,
  45. IRepository<KnowledgeType> knowledgeTypeRepository
  46. )
  47. {
  48. _knowledgeRepository = knowledgeRepository;
  49. _mapper = mapper;
  50. _knowledgePVRepository = knowledgePVRepository;
  51. _knowledgeWorkFlowRepository = knowledgeWorkFlowRepository;
  52. _capPublisher = capPublisher;
  53. _systemSettingCacheManager = systemSettingCacheManager;
  54. _relationTypeRepository = relationTypeRepository;
  55. _knowledgeTypeRepository = knowledgeTypeRepository;
  56. }
  57. /// <summary>
  58. /// 知识库-查询详情-增加浏览量
  59. /// </summary>
  60. /// <param name="Id"></param>
  61. /// <returns></returns>
  62. public async Task<Knowledge> KnowledgeInfo(string Id, CancellationToken cancellationToken)
  63. {
  64. var know = await _knowledgeRepository.Queryable(false, false, false)
  65. .Includes(x => x.Workflow, d => d.Steps)
  66. .Includes(x => x.SourceOrganize)
  67. .Includes(x => x.KnowledgeType).FirstAsync(p => p.Id == Id);
  68. if (know is null)
  69. throw UserFriendlyException.SameMessage("知识查询失败!");
  70. return know;
  71. }
  72. /// <summary>
  73. /// 浏览记录写入
  74. /// </summary>
  75. /// <param name="know"></param>
  76. /// <param name="cancellationToken"></param>
  77. /// <returns></returns>
  78. public async Task KnowledgePvIncreaseAsync(Knowledge know, CancellationToken cancellationToken)
  79. {
  80. //写入浏览记录
  81. KnowledgePv knowledgePv = new()
  82. {
  83. CreationTime = DateTime.Now,
  84. KnowledgeCode = know.Code
  85. };
  86. //浏览记录写入
  87. await _knowledgePVRepository.AddAsync(knowledgePv, cancellationToken);
  88. //修改浏览量
  89. know.PageView++;
  90. //修改点击量
  91. await _knowledgeRepository.UpdateAsync(know, cancellationToken);
  92. }
  93. /// <summary>
  94. /// 知识审批主表
  95. /// </summary>
  96. /// <param name="knowId">知识Id</param>
  97. /// <param name="eKnowledgeApplyType">申请类型</param>
  98. /// <param name="cancellationToken"></param>
  99. /// <returns></returns>
  100. public async Task<string> AddWorkFlowAsync(string knowId, EKnowledgeApplyType eKnowledgeApplyType, CancellationToken cancellationToken)
  101. {
  102. KnowledgeWorkFlow workFlow = new()
  103. {
  104. KnowledgeId = knowId,
  105. WorkflowModuleStatus = eKnowledgeApplyType,
  106. WorkFlowApplyStatus = EKnowledgeWorkFlowStatus.Auditing,
  107. };
  108. return await _knowledgeWorkFlowRepository.AddAsync(workFlow, cancellationToken);
  109. }
  110. /// <summary>
  111. /// 修改流程ID
  112. /// </summary>
  113. public async Task UpdateWorkFlowId(string workflowExternalId, string workflowId, List<HandlerGroupItem> handlerUsers, List<HandlerGroupItem> handlerOrgs,
  114. List<string> flowedUserIds, List<string> flowedOrgIds, CancellationToken cancellationToken)
  115. {
  116. if (string.IsNullOrEmpty(workflowExternalId))
  117. throw UserFriendlyException.SameMessage("无效知识编号");
  118. var knowledgeFlow =
  119. await _knowledgeWorkFlowRepository.Queryable().Where(x => x.KnowledgeId == workflowExternalId).FirstAsync(cancellationToken);
  120. if (knowledgeFlow == null)
  121. throw new UserFriendlyException($"无效知识编号, knowledgeFlowId: {workflowExternalId}", "无效知识编号");
  122. knowledgeFlow.WorkflowId = workflowId;
  123. knowledgeFlow.Flowed(flowedUserIds, flowedOrgIds, handlerUsers, handlerOrgs);
  124. await _knowledgeWorkFlowRepository.UpdateAsync(knowledgeFlow, cancellationToken);
  125. var knowledge = await _knowledgeRepository.Queryable().Where(x => x.Id == workflowExternalId).FirstAsync(cancellationToken);
  126. if (knowledge == null)
  127. throw new UserFriendlyException($"无效知识编号, knowledgeId: {workflowExternalId}", "无效知识编号");
  128. knowledge.WorkflowId = workflowId;
  129. knowledge.Status = EKnowledgeStatus.Auditing;
  130. knowledge.Flowed(flowedUserIds, flowedOrgIds, handlerUsers, handlerOrgs);
  131. await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  132. }
  133. /// <summary>
  134. /// 修改指派人
  135. /// </summary>
  136. /// <param name="assignInfo"></param>
  137. /// <param name="knowledgeFlowId"></param>
  138. /// <param name="cancellationToken"></param>
  139. /// <returns></returns>
  140. public async Task UpdateWorkAssign(FlowAssignInfo assignInfo, string? knowledgeFlowId, CancellationToken cancellationToken)
  141. {
  142. //知识流程表
  143. var knowledgeFlow =
  144. await _knowledgeWorkFlowRepository.GetAsync(knowledgeFlowId, cancellationToken);
  145. if (knowledgeFlow == null)
  146. throw new UserFriendlyException($"无效知识编号, knowledgeFlowId: {knowledgeFlowId}", "指派失败");
  147. knowledgeFlow.Assign(assignInfo.FlowAssignType, assignInfo.GetHandlerIds());
  148. await _knowledgeWorkFlowRepository.UpdateAsync(knowledgeFlow, cancellationToken);
  149. //知识主表
  150. var knowledge = await _knowledgeRepository.GetAsync(p => p.WorkflowId == knowledgeFlow.WorkflowId, cancellationToken);
  151. if (knowledge != null)
  152. {
  153. knowledge.Assign(assignInfo.FlowAssignType, assignInfo.GetHandlerIds());
  154. await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  155. }
  156. }
  157. /// <summary>
  158. /// 知识库-新增
  159. /// </summary>
  160. /// <param name="dto"></param>
  161. /// <returns></returns>
  162. public async Task<string> KnowledgeAdd(AddKnowledgeDto dto, CancellationToken cancellationToken)
  163. {
  164. var kn = _mapper.Map<Knowledge>(dto);
  165. //Code为空,从新生成Code
  166. if (string.IsNullOrEmpty(kn.Code))
  167. kn.Code = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds).ToString();
  168. kn.Status = EKnowledgeStatus.Auditing;
  169. return await _knowledgeRepository.AddAsync(kn, cancellationToken);
  170. }
  171. /// <summary>
  172. /// 知识库-修改
  173. /// </summary>
  174. /// <param name="dto"></param>
  175. /// <returns></returns>
  176. public async Task<string> KnowledgeUpdate(UpdateKnowledgeDto dto, CancellationToken cancellationToken)
  177. {
  178. //知识修改逻辑
  179. //如果可以修改,此条数据不动,重新写入一条新数据,知识编号不变,版本号+1,审批通过以后在数据交换
  180. var know = await _knowledgeRepository.GetAsync(dto.Id, cancellationToken);
  181. if (know is null || know.IsDeleted)
  182. throw UserFriendlyException.SameMessage("无效知识");
  183. //审批中数据不能处理
  184. if (know.Status == EKnowledgeStatus.Auditing)
  185. throw UserFriendlyException.SameMessage("审批中数据不能修改");
  186. var knowledge = _mapper.Map<Knowledge>(dto);
  187. knowledge.Code = know.Code;
  188. knowledge.PageView = know.PageView;
  189. knowledge.Status = EKnowledgeStatus.Auditing;
  190. knowledge.Id = null;
  191. knowledge.Version = 0;
  192. return await _knowledgeRepository.AddAsync(knowledge, cancellationToken);
  193. }
  194. /// <summary>
  195. /// 流程终止,处理知识状态
  196. /// </summary>
  197. /// <param name="workflow"></param>
  198. /// <param name="cancellationToken"></param>
  199. /// <returns></returns>
  200. /// <exception cref="UserFriendlyException"></exception>
  201. public async Task TerminateWorkKnowledge(Workflow workflow, CancellationToken cancellationToken)
  202. {
  203. //根据审批主表知识ID查询当前知识
  204. var knowledge = await _knowledgeRepository.GetAsync(p => p.Id == workflow.ExternalId, cancellationToken);
  205. if (knowledge == null)
  206. throw new UserFriendlyException($"知识查询失败");
  207. //修改主表审批状态 根据流程ID查询审批主表
  208. var workFlow = await _knowledgeWorkFlowRepository.GetAsync(p => p.KnowledgeId == workflow.ExternalId, cancellationToken);
  209. if (workFlow == null)
  210. throw new UserFriendlyException($"知识查询失败, workflowId: {workflow.ExternalId}", "无效流程编号");
  211. //修改业务数据状态
  212. workFlow.WorkFlowApplyStatus = EKnowledgeWorkFlowStatus.Revoke;
  213. workFlow.ActualOpinion = workflow.ActualOpinion;
  214. await _knowledgeWorkFlowRepository.UpdateAsync(workFlow, cancellationToken);
  215. //现有知识状态更改为已撤回
  216. knowledge.Status = EKnowledgeStatus.Revert;
  217. await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  218. //switch (workFlow.WorkflowModuleStatus)
  219. // {
  220. // case EKnowledgeApplyType.Add:
  221. // //将知识保存为草稿
  222. // knowledge.Status = EKnowledgeStatus.Drafts;
  223. // await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  224. // break;
  225. // default:
  226. // //现有知识状态更改为已撤回
  227. // knowledge.Status = EKnowledgeStatus.Revert;
  228. // await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  229. // break;
  230. //}
  231. }
  232. /// <summary>
  233. /// 流程审批完成,处理知识状态
  234. /// </summary>
  235. /// <param name="workflow"></param>
  236. /// <param name="cancellationToken"></param>
  237. /// <returns></returns>
  238. /// <exception cref="UserFriendlyException"></exception>
  239. public async Task EndWorkKnowledge(Workflow workflow, CancellationToken cancellationToken)
  240. {
  241. //修改主表审批状态 根据流程ID查询审批主表
  242. var workFlow = await _knowledgeWorkFlowRepository.GetAsync(p => p.KnowledgeId == workflow.ExternalId, cancellationToken);
  243. if (workFlow == null)
  244. throw new UserFriendlyException($"知识查询失败, workflowId: {workflow.ExternalId}", "无效流程编号");
  245. //根据审批主表知识ID查询当前知识
  246. // var knowledge = await _knowledgeRepository.GetAsync(p => p.Id == workFlow.KnowledgeId, cancellationToken);
  247. workFlow.HandleTime = DateTime.Now;
  248. workFlow.WorkFlowApplyStatus = EKnowledgeWorkFlowStatus.Success;
  249. workFlow.ActualOpinion = workflow.ActualOpinion;
  250. await _knowledgeWorkFlowRepository.UpdateAsync(workFlow, cancellationToken);
  251. var knowledge = await _knowledgeRepository.Queryable(false, false, false)
  252. .Includes(it => it.SystemOrganize)
  253. .Includes(it => it.HotspotType)
  254. .Includes(it => it.User)
  255. .Where(p => p.Id == workflow.ExternalId)
  256. .FirstAsync();
  257. if (knowledge == null)
  258. throw new UserFriendlyException($"知识查询失败");
  259. string isSendType = "";//推送类别:新增0,修改1,删除2
  260. switch (workflow.ModuleCode)
  261. {
  262. case WorkflowModuleConsts.KnowledgeAdd://新增
  263. case WorkflowModuleConsts.KnowledgeUpdate://修改
  264. //根据Code查询是否有历史数据
  265. var oldKnowledge = await _knowledgeRepository
  266. .Queryable()
  267. .Where(p => p.Code == knowledge.Code && (p.Status == EKnowledgeStatus.OnShelf || p.Status == EKnowledgeStatus.OffShelf)
  268. && p.IsDeleted == false && p.Id != knowledge.Id)
  269. .OrderByDescending(p => p.Version)
  270. .Take(1)
  271. .FirstAsync();
  272. if (!knowledge.Renewaln.Value)
  273. {
  274. isSendType = "0";
  275. }
  276. else
  277. {
  278. isSendType = "1";
  279. }
  280. //修改知识状态为已上架
  281. knowledge.Status = EKnowledgeStatus.OnShelf;
  282. knowledge.OnShelfTime = System.DateTime.Now;
  283. await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  284. break;
  285. case WorkflowModuleConsts.KnowledgeDelete://删除
  286. //知识先下架,在删除
  287. knowledge.Status = EKnowledgeStatus.OffShelf;
  288. knowledge.OffShelfTime = System.DateTime.Now;
  289. knowledge.WorkflowId = workflow.Id;
  290. await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  291. //删除知识
  292. await _knowledgeRepository.RemoveAsync(p => p.Code == knowledge.Code, true, cancellationToken);
  293. isSendType = "2";
  294. break;
  295. }
  296. #region 数据推送
  297. var pushKnowledge = _mapper.Map<KnowledgeSendDto>(knowledge);
  298. pushKnowledge.CategoryCode = "01";
  299. pushKnowledge.CategoryName = "公共服务";
  300. //高效办成一件事配置
  301. var cancelPublishOrderEnabled = _systemSettingCacheManager.GetSetting(SettingConstants.EfficientlyAccomplish)?.SettingValue[0];
  302. //获取到配置,执行下面
  303. if (!string.IsNullOrEmpty(cancelPublishOrderEnabled))
  304. {
  305. var isEfficientlyAccomplish = false;
  306. //根据知识ID查询所有的知识分类
  307. var typeList = await _relationTypeRepository.Queryable().Where(p => p.KnowledgeId == knowledge.Id).ToListAsync(cancellationToken);
  308. if (typeList != null && typeList.Any())
  309. {
  310. //遍历知识分类
  311. foreach (var item in typeList)
  312. {
  313. //查询知识分类是否满足高效办成一件事
  314. if (await _knowledgeTypeRepository.AnyAsync(p => p.Id == item.KnowledgeTypeId && p.SpliceName.StartsWith(cancelPublishOrderEnabled), cancellationToken))
  315. {
  316. //满足,跳出遍历
  317. isEfficientlyAccomplish = true;
  318. break;
  319. }
  320. }
  321. }
  322. //是高效,处理默认值
  323. if (isEfficientlyAccomplish)
  324. {
  325. pushKnowledge.CategoryCode = "25";
  326. pushKnowledge.CategoryName = "高效办成一件事";
  327. }
  328. }
  329. //推送
  330. if (isSendType == "0") //新增知识推送
  331. await _capPublisher.PublishAsync(EventNames.HotlineKnowledgeAdd, pushKnowledge, cancellationToken: cancellationToken);
  332. else if (isSendType == "1") //修改知识推送
  333. await _capPublisher.PublishAsync(EventNames.HotlineKnowledgeUpdate, pushKnowledge, cancellationToken: cancellationToken);
  334. else if (isSendType == "2") //删除知识推送
  335. await _capPublisher.PublishAsync(EventNames.HotlineKnowledgeRemove, pushKnowledge, cancellationToken: cancellationToken);
  336. #endregion
  337. }
  338. }
  339. }