KnowledgeDomainService.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. using Hotline.FlowEngine.Workflows;
  2. using Hotline.Settings;
  3. using Hotline.Share.Dtos.Knowledge;
  4. using Hotline.Share.Enums.KnowledgeBase;
  5. using MapsterMapper;
  6. using SqlSugar;
  7. using XF.Domain.Dependency;
  8. using XF.Domain.Exceptions;
  9. namespace Hotline.KnowledgeBase
  10. {
  11. public class KnowledgeDomainService : IKnowledgeDomainService, IScopeDependency
  12. {
  13. private readonly IKnowledgeRepository _knowledgeRepository;
  14. private readonly IKnowledgeTempRepository _knowledgeTempRepository;
  15. private readonly IMapper _mapper;
  16. private readonly IKnowledgePVRepository _knowledgePVRepository;
  17. private readonly IKnowledgeWorkFlowRepository _knowledgeWorkFlowRepository;
  18. private readonly IWorkflowDomainService _workflowDomainService;
  19. private readonly IKnowledgeApplyRepository _knowledgeApplyRepository;
  20. /// <summary>
  21. ///
  22. /// </summary>
  23. /// <param name="knowledgeRepository"></param>
  24. /// <param name="knowledgeTempRepository"></param>
  25. /// <param name="mapper"></param>
  26. /// <param name="knowledgePVRepository"></param>
  27. /// <param name="knowledgeWorkFlowRepository"></param>
  28. /// <param name="workflowDomainService"></param>
  29. public KnowledgeDomainService(IKnowledgeRepository knowledgeRepository, IKnowledgeTempRepository knowledgeTempRepository, IMapper mapper, IKnowledgePVRepository knowledgePVRepository, IKnowledgeWorkFlowRepository knowledgeWorkFlowRepository
  30. , IWorkflowDomainService workflowDomainService, IKnowledgeApplyRepository knowledgeApplyRepository)
  31. {
  32. _knowledgeRepository = knowledgeRepository;
  33. _mapper = mapper;
  34. _knowledgeTempRepository = knowledgeTempRepository;
  35. _knowledgePVRepository = knowledgePVRepository;
  36. _knowledgeWorkFlowRepository = knowledgeWorkFlowRepository;
  37. _workflowDomainService = workflowDomainService;
  38. _knowledgeApplyRepository = knowledgeApplyRepository;
  39. }
  40. /// <summary>
  41. /// 知识库-查询详情-增加浏览量
  42. /// </summary>
  43. /// <param name="Id"></param>
  44. /// <returns></returns>
  45. public async Task<Knowledge> KnowledgeInfo(string Id, CancellationToken cancellationToken)
  46. {
  47. var know = await _knowledgeRepository.GetAsync(Id, cancellationToken);
  48. if (know is null)
  49. throw UserFriendlyException.SameMessage("知识查询失败!");
  50. return know;
  51. }
  52. /// <summary>
  53. /// 浏览记录写入
  54. /// </summary>
  55. /// <param name="know"></param>
  56. /// <param name="cancellationToken"></param>
  57. /// <returns></returns>
  58. public async Task KnowledgePvIncreaseAsync(Knowledge know, CancellationToken cancellationToken)
  59. {
  60. //写入浏览记录
  61. KnowledgePv knowledgePv = new()
  62. {
  63. CreationTime = DateTime.Now,
  64. KnowledgeCode = know.Code
  65. };
  66. //浏览记录写入
  67. await _knowledgePVRepository.AddAsync(knowledgePv, cancellationToken);
  68. //修改浏览量
  69. know.PageView++;
  70. //修改点击量
  71. await _knowledgeRepository.UpdateAsync(know, cancellationToken);
  72. }
  73. /// <summary>
  74. /// 知识审批主表
  75. /// </summary>
  76. /// <param name="knowId">知识Id</param>
  77. /// <param name="workFlowId">流程ID</param>
  78. /// <param name="eKnowledgeApplyType">申请类型</param>
  79. /// <param name="cancellationToken"></param>
  80. /// <returns></returns>
  81. public async Task<string> AddWorkFlow(string knowId, string workFlowId, EKnowledgeApplyType eKnowledgeApplyType, CancellationToken cancellationToken)
  82. {
  83. KnowledgeWorkFlow workFlow = new()
  84. {
  85. KnowledgeId = knowId,
  86. WorkflowModuleStatus = eKnowledgeApplyType,
  87. WorkFlowApplyStatus = EKnowledgeWorkFlowStatus.Auditing,
  88. WorkflowId = workFlowId
  89. };
  90. return await _knowledgeWorkFlowRepository.AddAsync(workFlow, cancellationToken);
  91. }
  92. /// <summary>
  93. /// 修改流程ID
  94. /// </summary>
  95. /// <param name="knowledgeId"></param>
  96. /// <param name="workFlowId"></param>
  97. /// <param name="cancellationToken"></param>
  98. /// <returns></returns>
  99. public async Task UpdateWorkFlowId(string knowledgeId, string workFlowId, CancellationToken cancellationToken)
  100. {
  101. var knowledge = await _knowledgeRepository.GetAsync(knowledgeId, cancellationToken);
  102. knowledge.WorkflowId = workFlowId;
  103. await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  104. }
  105. /// <summary>
  106. /// 知识库-新增
  107. /// </summary>
  108. /// <param name="dto"></param>
  109. /// <returns></returns>
  110. public async Task<string> KnowledgeAdd(AddKnowledgeDto dto, CancellationToken cancellationToken)
  111. {
  112. var kn = _mapper.Map<Knowledge>(dto);
  113. //知识草稿ID如果不为空,则表示是草稿箱的数据
  114. if (!string.IsNullOrEmpty(dto.Code))
  115. {
  116. //移除草稿箱数据
  117. await _knowledgeTempRepository.RemoveAsync(p => p.Code == dto.Code, false, cancellationToken);
  118. }
  119. //如果草稿箱不存在数据,也就是Code为空,从新生成Code
  120. if (string.IsNullOrEmpty(kn.Code))
  121. kn.Code = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds).ToString();
  122. kn.Status = EKnowledgeStatus.Auditing;
  123. var knowledgeId = await _knowledgeRepository.AddAsync(kn, cancellationToken);
  124. if (!string.IsNullOrEmpty(dto.Applies))
  125. {
  126. var apply = await _knowledgeApplyRepository.GetAsync(p => p.Id == dto.Applies, cancellationToken);
  127. if (apply != null)
  128. {
  129. apply.KnowledgeId = knowledgeId;
  130. await _knowledgeApplyRepository.UpdateAsync(apply, cancellationToken);
  131. }
  132. }
  133. return knowledgeId;
  134. }
  135. /// <summary>
  136. /// 知识库-修改
  137. /// </summary>
  138. /// <param name="dto"></param>
  139. /// <returns></returns>
  140. public async Task<string> KnowledgeUpdate(UpdateKnowledgeDto dto, CancellationToken cancellationToken)
  141. {
  142. //知识修改逻辑
  143. //如果可以修改,此条数据不动,重新写入一条新数据,知识编号不变,版本号+1,审批通过以后在数据交换
  144. var know = await _knowledgeRepository.GetAsync(dto.Id, cancellationToken);
  145. if (know is null || know.IsDeleted)
  146. throw UserFriendlyException.SameMessage("无效知识");
  147. //审批中数据不能处理
  148. if (know.Status == EKnowledgeStatus.Auditing)
  149. throw UserFriendlyException.SameMessage("审批中数据不能修改");
  150. var knowledge = _mapper.Map<Knowledge>(dto);
  151. knowledge.Code = know.Code;
  152. knowledge.PageView = know.PageView;
  153. knowledge.Status = EKnowledgeStatus.Auditing;
  154. knowledge.Id = "";
  155. knowledge.Version = 0;
  156. var knowledgeId = await _knowledgeRepository.AddAsync(knowledge, cancellationToken);
  157. if (!string.IsNullOrEmpty(dto.Applies))
  158. {
  159. var apply = await _knowledgeApplyRepository.GetAsync(p => p.Id == dto.Applies, cancellationToken);
  160. if (apply != null)
  161. {
  162. apply.KnowledgeId = knowledgeId;
  163. await _knowledgeApplyRepository.UpdateAsync(apply, cancellationToken);
  164. }
  165. }
  166. //新增一条数据
  167. return knowledgeId;
  168. }
  169. /// <summary>
  170. /// 撤销
  171. /// </summary>
  172. /// <param name="workFlowId"></param>
  173. /// <param name="cancellationToken"></param>
  174. /// <returns></returns>
  175. public async Task KnowledgeRevoke(string workFlowId, CancellationToken cancellationToken)
  176. {
  177. var knowWorkFlow = await _knowledgeWorkFlowRepository.GetAsync(p => p.WorkflowId == workFlowId, cancellationToken);
  178. if (knowWorkFlow is null)
  179. throw UserFriendlyException.SameMessage("无效知识审批");
  180. if (knowWorkFlow.WorkFlowApplyStatus != EKnowledgeWorkFlowStatus.Auditing)
  181. throw UserFriendlyException.SameMessage("只有审批中的知识才能撤回!");
  182. knowWorkFlow.WorkFlowApplyStatus = EKnowledgeWorkFlowStatus.Revoke;
  183. await _knowledgeWorkFlowRepository.UpdateAsync(knowWorkFlow);
  184. switch (knowWorkFlow.WorkflowModuleStatus)
  185. {
  186. case EKnowledgeApplyType.Add:
  187. case EKnowledgeApplyType.Update:
  188. //查询知识
  189. var knowledge = await _knowledgeRepository.GetAsync(p => p.WorkflowId == workFlowId, cancellationToken);
  190. if (knowledge != null)
  191. {
  192. //将知识保存到草稿箱
  193. var tempKnow = _mapper.Map<KnowledgeTemp>(knowledge);
  194. await _knowledgeTempRepository.AddAsync(tempKnow, cancellationToken);
  195. knowledge.Status = EKnowledgeStatus.Revert;
  196. //删除现有知识
  197. await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  198. }
  199. break;
  200. }
  201. //调用终止流程
  202. await _workflowDomainService.TerminateAsync(workFlowId, cancellationToken);
  203. }
  204. /// <summary>
  205. /// 获取关键词
  206. /// </summary>
  207. /// <returns></returns>
  208. public async Task<List<string>> GetKeyWord()
  209. {
  210. var temp = await _knowledgeRepository
  211. .Queryable()
  212. .Where(p => p.IsDeleted == false && p.Status == EKnowledgeStatus.OnShelf)
  213. .Select((p) => new
  214. {
  215. index = SqlFunc.RowNumber($"{p.Version} desc ", $"{p.Code}"),
  216. p.Version,
  217. p.PageView,
  218. p.Keywords
  219. })
  220. //将结果合并成一个表
  221. .MergeTable()
  222. //取第一条数据
  223. .Where(d => d.index == 1 && d.Keywords != null && d.Keywords != "")
  224. //根据点击量在排序
  225. .OrderByDescending(p => p.PageView)
  226. .Take(10)//取前10条
  227. .ToListAsync();
  228. //将数据组装到集合
  229. List<string> strList = new();
  230. temp.ForEach(p =>
  231. {
  232. if (!string.IsNullOrEmpty(p.Keywords))
  233. strList.AddRange(p.Keywords.Split(',').ToList());//添加数据
  234. });
  235. //取10条数据返回
  236. return strList.Distinct().Take(10).ToList();
  237. }
  238. /// <summary>
  239. /// 流程审批完成,处理知识状态
  240. /// </summary>
  241. /// <param name="workflow"></param>
  242. /// <param name="cancellationToken"></param>
  243. /// <returns></returns>
  244. /// <exception cref="UserFriendlyException"></exception>
  245. public async Task EndWorkKnowledge(Workflow workflow, CancellationToken cancellationToken)
  246. {
  247. var knowledge = await _knowledgeRepository.GetAsync(p => p.WorkflowId == workflow.Id, cancellationToken);
  248. if (knowledge == null)
  249. throw new UserFriendlyException($"知识查询失败, workflowId: {workflow.Id}", "无效流程编号");
  250. //修改主表审批状态
  251. var workFlow = await _knowledgeWorkFlowRepository.GetAsync(p => p.WorkflowId == workflow.Id, cancellationToken);
  252. if (workFlow != null)
  253. {
  254. workFlow.HandleTime = DateTime.Now;
  255. workFlow.WorkFlowApplyStatus = EKnowledgeWorkFlowStatus.Success;
  256. await _knowledgeWorkFlowRepository.UpdateAsync(workFlow, cancellationToken);
  257. }
  258. switch (workflow.ModuleCode)
  259. {
  260. case WorkflowModuleConsts.KnowledgeAdd://新增
  261. //修改知识状态为已上架
  262. knowledge.Status = EKnowledgeStatus.OnShelf;
  263. knowledge.OnShelfTime = System.DateTime.Now;
  264. await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  265. break;
  266. case WorkflowModuleConsts.KnowledgeUpdate://修改
  267. //处理知识版本号
  268. //根据Code查询目前使用的版本号,版本号+1
  269. var oldKnowledge = await _knowledgeRepository
  270. .Queryable()
  271. .Where(p => p.Code == knowledge.Code && p.Status != EKnowledgeStatus.Auditing && p.Status != EKnowledgeStatus.Failed && p.IsDeleted == false)
  272. .OrderByDescending(p => p.Version)
  273. .Take(1)
  274. .FirstAsync();
  275. if (oldKnowledge == null)
  276. knowledge.Version = 1;
  277. else
  278. knowledge.Version = oldKnowledge.Version + 1;
  279. //修改知识状态为已上架
  280. knowledge.Status = EKnowledgeStatus.OnShelf;
  281. knowledge.OnShelfTime = System.DateTime.Now;
  282. await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  283. break;
  284. case WorkflowModuleConsts.KnowledgeDelete://删除
  285. //知识先下架,在删除
  286. knowledge.Status = EKnowledgeStatus.OffShelf;
  287. knowledge.OffShelfTime = System.DateTime.Now;
  288. knowledge.WorkflowId = workflow.Id;
  289. await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  290. //删除知识
  291. await _knowledgeRepository.RemoveAsync(p => p.Code == knowledge.Code, true, cancellationToken);
  292. break;
  293. }
  294. }
  295. }
  296. }