CaseApplication.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. using Hotline.Settings.Hotspots;
  2. using Hotline.Share.Dtos.Knowledge;
  3. using Hotline.Share.Dtos.Caselibrary;
  4. using Hotline.Share.Enums.Caselibrary;
  5. using MapsterMapper;
  6. using XF.Domain.Authentications;
  7. using XF.Domain.Dependency;
  8. using XF.Domain.Exceptions;
  9. using XF.Domain.Repository;
  10. using Hotline.Repository.SqlSugar.Extensions;
  11. using Hotline.SeedData;
  12. using Hotline.File;
  13. using Hotline.Application.Bulletin;
  14. using Hotline.Share.Tools;
  15. using Hotline.Application.Tools;
  16. using SqlSugar;
  17. using Hotline.CaseLibrary;
  18. using Hotline.Orders;
  19. using Hotline.KnowledgeBase;
  20. using Hotline.Share.Enums.Planlibrary;
  21. using System.Numerics;
  22. using Hotline.Share.Dtos.Planlibrary;
  23. namespace Hotline.Application.Caselibrary
  24. {
  25. /// <summary>
  26. /// 案例库处理
  27. /// </summary>
  28. public class CaseApplication : ICaseApplication, IScopeDependency
  29. {
  30. #region 注册
  31. private readonly IRepository<CaseList> _caseListRepository; //案例库列表
  32. private readonly IRepository<CaseRelationType> _caseRelationTypeRepository; //案例库关联类型
  33. private readonly IRepository<CaseType> _caseTypeRepository; //案例库分类管理
  34. private readonly IRepository<CaseTypeOrg> _caseTypeOrgRepository; //案例库分类关联机构
  35. private readonly IRepository<CaseCollect> _caseCollectRepository; //案例库收藏评分
  36. private readonly IRepository<Order> _orderRepository; //工单
  37. private readonly IRepository<Hotline.KnowledgeBase.Knowledge> _knowledgeRepository; //知识库
  38. private readonly ISessionContext _sessionContext;
  39. private readonly IMapper _mapper;
  40. private readonly IRepository<Hotspot> _hotspotTypeRepository;
  41. private readonly IFileRepository _fileRepository;
  42. private readonly IBulletinApplication _bulletinApplication;
  43. public CaseApplication(
  44. IRepository<CaseList> caseListRepository,
  45. IRepository<CaseRelationType> caseRelationTypeRepository,
  46. IRepository<CaseType> caseTypeRepository,
  47. IRepository<CaseTypeOrg> caseTypeOrgRepository,
  48. IRepository<CaseCollect> caseCollectRepository,
  49. IRepository<Order> orderRepository,
  50. IRepository<Hotline.KnowledgeBase.Knowledge> knowledgeRepository,
  51. ISessionContext sessionContext,
  52. IMapper mapper,
  53. IRepository<Hotspot> hotspotTypeRepository,
  54. IFileRepository fileRepository,
  55. IBulletinApplication bulletinApplication)
  56. {
  57. _caseListRepository = caseListRepository;
  58. _caseRelationTypeRepository = caseRelationTypeRepository;
  59. _caseTypeRepository = caseTypeRepository;
  60. _caseTypeOrgRepository = caseTypeOrgRepository;
  61. _caseCollectRepository = caseCollectRepository;
  62. _orderRepository = orderRepository;
  63. _knowledgeRepository = knowledgeRepository;
  64. _sessionContext = sessionContext;
  65. _mapper = mapper;
  66. _hotspotTypeRepository = hotspotTypeRepository;
  67. _fileRepository = fileRepository;
  68. _bulletinApplication = bulletinApplication;
  69. }
  70. #endregion
  71. #region 案例库类型管理
  72. #region 案例库类型 - 新增
  73. /// <summary>
  74. /// 案例库类型 - 新增
  75. /// </summary>
  76. /// <param name="dto"></param>
  77. /// <param name="cancellationToken"></param>
  78. /// <returns></returns>
  79. public async Task<string> AddTypeAsync(AddCaseTypeDto dto, CancellationToken cancellationToken)
  80. {
  81. var sandard = await _caseTypeRepository.GetAsync(p => p.ParentId == dto.ParentId && p.Name == dto.Name && p.IsDeleted == false, cancellationToken);
  82. if (sandard is not null)
  83. throw UserFriendlyException.SameMessage("当前层级已存在相同名称的分类!");
  84. var type = _mapper.Map<CaseType>(dto);
  85. type.InitId();
  86. type.IsEnable = true;
  87. //获取分类名称全称
  88. string FullName = await GetFullName(type.ParentId);
  89. //处理全称,如果为第一级直接用全称,否则获取全称后拼接名称
  90. type.SpliceName = string.IsNullOrEmpty(FullName) ? dto.Name : FullName + "-" + dto.Name;
  91. var id = await _caseTypeRepository.AddAsync(type, cancellationToken);
  92. if (dto.TypeOrgDtos != null && dto.TypeOrgDtos.Any())
  93. {
  94. List<CaseTypeOrg> orgs = _mapper.Map<List<CaseTypeOrg>>(dto.TypeOrgDtos);
  95. orgs.ForEach(x => x.TypeId = type.Id);
  96. await _caseTypeOrgRepository.AddRangeAsync(orgs, cancellationToken);
  97. }
  98. return id;
  99. }
  100. #endregion
  101. #region 案例库类型 - 编辑
  102. /// <summary>
  103. /// 案例库类型 - 编辑
  104. /// </summary>
  105. /// <param name="dto"></param>
  106. /// <param name="cancellationToken"></param>
  107. /// <returns></returns>
  108. public async Task UpdateTypeAsync(UpdateCaseTypeDto dto, CancellationToken cancellationToken)
  109. {
  110. //查询原有数据
  111. var type = await _caseTypeRepository.GetAsync(dto.Id, cancellationToken);
  112. if (type is null)
  113. throw UserFriendlyException.SameMessage("编辑失败!");
  114. bool result = type.Name != dto.Name || type.ParentId != dto.ParentId;
  115. //是否更改分类名称或者层级
  116. //转换
  117. _mapper.Map(dto, type);
  118. //如果更改了名称或者修改了层级,则修改全称,未更改不修改
  119. if (result)
  120. {
  121. string FullName = await GetFullName(type.ParentId);//获取分类名称全称
  122. type.SpliceName = string.IsNullOrEmpty(FullName) ? dto.Name : FullName + "-" + dto.Name;//处理全称,如果为第一级直接用全称,否则获取全称后拼接名称
  123. }
  124. //修改数据
  125. await _caseTypeRepository.UpdateAsync(type, cancellationToken);
  126. //如果修改了名称,对应修改子分类全称
  127. if (result)
  128. await UpdateChildNode(type.Id);
  129. // 修改关联机构
  130. await _caseTypeOrgRepository.RemoveAsync(x => x.TypeId == type.Id, false, cancellationToken);
  131. if (dto.TypeOrgDtos != null && dto.TypeOrgDtos.Any())
  132. {
  133. List<CaseTypeOrg> orgs = _mapper.Map<List<CaseTypeOrg>>(dto.TypeOrgDtos);
  134. orgs.ForEach(x => x.TypeId = type.Id);
  135. await _caseTypeOrgRepository.AddRangeAsync(orgs, cancellationToken);
  136. }
  137. }
  138. #endregion
  139. #region 案例库类型 - 删除
  140. /// <summary>
  141. /// 案例库类型 - 删除
  142. /// </summary>
  143. /// <param name="Id"></param>
  144. /// <param name="cancellationToken"></param>
  145. /// <returns></returns>
  146. public async Task RemoveTypeAsync(string Id, CancellationToken cancellationToken)
  147. {
  148. //查询数据是否存在
  149. var sandard = await _caseTypeRepository.GetAsync(p => p.Id == Id && p.IsDeleted == false, cancellationToken);
  150. if (sandard is null)
  151. throw UserFriendlyException.SameMessage("分类不存在!");
  152. //查询是否有子级分类
  153. var checkChild = await _caseTypeRepository.CountAsync(p => p.ParentId == Id && p.IsDeleted == false, cancellationToken);
  154. if (checkChild > 0)
  155. throw UserFriendlyException.SameMessage("存在子级分类!");
  156. //查询是否有案例分类
  157. var checkKnowledge = await _caseListRepository.CountAsync(p => p.CaseTypes.Any(t => t.CaseId == Id), cancellationToken);
  158. if (checkKnowledge > 0)
  159. throw UserFriendlyException.SameMessage("分类存在案例!");
  160. //删除操作
  161. await _caseTypeRepository.RemoveAsync(sandard, true, cancellationToken);
  162. }
  163. #endregion
  164. #endregion
  165. #region 案例库管理
  166. #region 案例库 - 列表
  167. /// <summary>
  168. /// 案例库 - 列表
  169. /// </summary>
  170. /// <param name="pagedDto"></param>
  171. /// <returns></returns>
  172. public async Task<(int, IList<CaseDataDto>)> QueryAllCaseListAsync(CaseListDto pagedDto, CancellationToken cancellationToken)
  173. {
  174. var typeSpliceName = string.Empty;
  175. if (!string.IsNullOrEmpty(pagedDto.CaseTypeID))
  176. {
  177. var type = await _caseTypeRepository.GetAsync(x => x.Id == pagedDto.CaseTypeID);
  178. typeSpliceName = type?.SpliceName;
  179. }
  180. //单表分页
  181. var (total, temp) = await _caseListRepository.Queryable()
  182. .Includes(x => x.CaseTypes)
  183. .Includes(x => x.ExaminMan)
  184. .Includes(x => x.Order)
  185. .Includes(x => x.Knowledge)
  186. .Where(x => x.IsDeleted == false)
  187. .WhereIF(pagedDto.IsPopular.HasValue, x => x.IsPopular == pagedDto.IsPopular)
  188. .WhereIF(OrgSeedData.CenterId != pagedDto.CreateOrgId && !string.IsNullOrEmpty(pagedDto.CreateOrgId), x => x.CreatorOrgId != null && x.CreatorOrgId.StartsWith(pagedDto.CreateOrgId!))
  189. .WhereIF(!string.IsNullOrEmpty(pagedDto.Title) &&
  190. string.IsNullOrEmpty(pagedDto.Keywords) &&
  191. string.IsNullOrEmpty(pagedDto.Abstract), x => x.Title.Contains(pagedDto.Title!))
  192. .WhereIF(string.IsNullOrEmpty(pagedDto.Title) &&
  193. !string.IsNullOrEmpty(pagedDto.Keywords) &&
  194. string.IsNullOrEmpty(pagedDto.Abstract), x => x.Keywords.Contains(pagedDto.Keywords!))
  195. .WhereIF(string.IsNullOrEmpty(pagedDto.Title) &&
  196. string.IsNullOrEmpty(pagedDto.Keywords) &&
  197. !string.IsNullOrEmpty(pagedDto.Abstract), x => x.Abstract.Contains(pagedDto.Abstract!))
  198. .WhereIF(!string.IsNullOrEmpty(pagedDto.Title) &&
  199. !string.IsNullOrEmpty(pagedDto.Keywords) &&
  200. !string.IsNullOrEmpty(pagedDto.Abstract)
  201. , x => x.Title.Contains(pagedDto.Title!) ||
  202. x.Keywords!.Contains(pagedDto.Keywords!) ||
  203. x.Abstract!.Contains(pagedDto.Abstract!))
  204. .WhereIF(pagedDto.Status.HasValue && pagedDto.Status == ECaseStatus.OnShelf, x => x.Status == ECaseStatus.OnShelf)
  205. .WhereIF(pagedDto.Status.HasValue && pagedDto.Status == ECaseStatus.OffShelf, x => x.Status == ECaseStatus.OffShelf)
  206. .WhereIF(pagedDto.Status.HasValue && pagedDto.Status == ECaseStatus.Auditing, x => x.Status == ECaseStatus.Auditing)
  207. .WhereIF(pagedDto.Status.HasValue && pagedDto.Status == ECaseStatus.NewDrafts, x =>
  208. (x.Status == ECaseStatus.Drafts && x.CreatorId == _sessionContext.UserId) ||
  209. (x.Status == ECaseStatus.Revert && x.CreatorId == _sessionContext.UserId) ||
  210. (x.Status == ECaseStatus.NewDrafts && x.CreatorId == _sessionContext.UserId))
  211. .WhereIF(pagedDto.Status.HasValue && pagedDto.Status == ECaseStatus.All, x => (x.Status == ECaseStatus.OnShelf ||
  212. x.Status == ECaseStatus.OffShelf ||
  213. x.Status == ECaseStatus.Auditing) ||
  214. (x.Status == ECaseStatus.Drafts && x.CreatorId == _sessionContext.UserId) ||
  215. (x.Status == ECaseStatus.Revert && x.CreatorId == _sessionContext.UserId) ||
  216. (x.Status == ECaseStatus.NewDrafts && x.CreatorId == _sessionContext.UserId))
  217. .WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => x.CaseTypes.Any(t => t.CaseTypeSpliceName.StartsWith(typeSpliceName)))
  218. .WhereIF(pagedDto.CreationTimeStart.HasValue, x => x.CreationTime >= pagedDto.CreationTimeStart)
  219. .WhereIF(pagedDto.CreationTimeEnd.HasValue, x => x.CreationTime <= pagedDto.CreationTimeEnd)
  220. .WhereIF(pagedDto.OnShelfTimeStart.HasValue, x => x.OnShelfTime >= pagedDto.OnShelfTimeStart)
  221. .WhereIF(pagedDto.OnShelfTimeEnd.HasValue, x => x.OnShelfTime <= pagedDto.OnShelfTimeEnd)
  222. .WhereIF(pagedDto.OffShelfTimeStart.HasValue, x => x.OffShelfTime >= pagedDto.OffShelfTimeStart)
  223. .WhereIF(pagedDto.OffShelfTimeEnd.HasValue, x => x.OffShelfTime <= pagedDto.OffShelfTimeEnd)
  224. .WhereIF(pagedDto.UpdateTimeStart.HasValue, x => x.UpdateTime >= pagedDto.UpdateTimeStart)
  225. .WhereIF(pagedDto.UpdateTimeEnd.HasValue, x => x.UpdateTime <= pagedDto.UpdateTimeEnd)
  226. .WhereIF(pagedDto.ExaminTimeStart.HasValue, x => x.ExaminTime >= pagedDto.ExaminTimeStart)
  227. .WhereIF(pagedDto.ExaminTimeEnd.HasValue, x => x.ExaminTime <= pagedDto.ExaminTimeEnd)
  228. .OrderByIF(string.IsNullOrEmpty(pagedDto.SortField), x => x.CreationTime, OrderByType.Desc)
  229. .OrderByIF(pagedDto is { SortField: "pageView" }, x => x.PageView, OrderByType.Desc) //阅读量
  230. .OrderByIF(pagedDto is { SortField: "score" }, x => x.Score, OrderByType.Desc) //评分
  231. .OrderByIF(pagedDto is { SortField: "creationTime" }, x => x.CreationTime, OrderByType.Desc) //创建时间
  232. //.Select(x => new CaseDataDto
  233. //{
  234. // Id = x.Id.SelectAll(),
  235. // OrderTitle = x.Order.Title,
  236. // KnowledgeTitle = x.Knowledge.Title
  237. //})
  238. .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize, cancellationToken);
  239. return (total, _mapper.Map<IList<CaseDataDto>>(temp));
  240. //return (total, temp);
  241. }
  242. #endregion
  243. #region 案例库 - 新增
  244. /// <summary>
  245. /// 新增
  246. /// </summary>
  247. /// <param name="dto"></param>
  248. /// <param name="cancellationToken"></param>
  249. /// <returns></returns>
  250. public async Task<string> AddCaseAsync(AddCaseListDto dto, CancellationToken cancellationToken)
  251. {
  252. var pList = _mapper.Map<CaseList>(dto);
  253. var any = await _caseListRepository.Queryable().Where(x => x.Status == ECaseStatus.OnShelf && x.Title == dto.Title).AnyAsync();
  254. if (any)
  255. throw UserFriendlyException.SameMessage("当前案例标题存在重复标题!");
  256. pList.InitId();
  257. if (dto.Files != null && dto.Files.Count > 0)
  258. pList.FileJson = await _fileRepository.AddFileAsync(dto.Files, pList.Id, "", cancellationToken);
  259. await _caseListRepository.AddAsync(pList, cancellationToken);
  260. if (dto.CaseTypes.Any())
  261. {
  262. List<CaseRelationType> types = _mapper.Map<List<CaseRelationType>>(dto.CaseTypes);
  263. types.ForEach(x => x.CaseId = pList.Id);
  264. await _caseRelationTypeRepository.AddRangeAsync(types, cancellationToken);
  265. }
  266. return pList.Id;
  267. }
  268. #endregion
  269. #region 案例库 - 修改
  270. /// <summary>
  271. /// 修改
  272. /// </summary>
  273. /// <param name="dto"></param>
  274. /// <param name="cancellationToken"></param>
  275. /// <returns></returns>
  276. public async Task UpdateCaseAsync(UpdateCaseListDto dto, CancellationToken cancellationToken)
  277. {
  278. var Case = await _caseListRepository.GetAsync(dto.Id);
  279. if (Case == null)
  280. throw UserFriendlyException.SameMessage("案例库查询失败");
  281. if ((Case.Status == ECaseStatus.OnShelf || Case.Status == ECaseStatus.Auditing) && (Case.ExpiredTime.HasValue && Case.ExpiredTime.Value > DateTime.Now))
  282. throw UserFriendlyException.SameMessage("案例库数据不可修改");
  283. var any = await _caseListRepository.Queryable().Where(x => x.Status == ECaseStatus.OnShelf && x.Title == dto.Title && x.Id != dto.Id).AnyAsync();
  284. if (any)
  285. throw UserFriendlyException.SameMessage("当前案例标题存在重复标题!");
  286. if (dto.ApplyStatus == ECaseApplyStatus.Delete)
  287. {
  288. Case.Status = (ECaseStatus)dto.Status;
  289. Case.ApplyStatus = (ECaseApplyStatus)dto.ApplyStatus;
  290. Case.Id = dto.Id;
  291. Case.ApplyReason = dto.ApplyReason;
  292. }
  293. else
  294. {
  295. _mapper.Map(dto, Case);
  296. if (dto.Files != null && dto.Files.Count > 0)
  297. Case.FileJson = await _fileRepository.AddFileAsync(dto.Files, Case.Id, "", cancellationToken);
  298. else
  299. Case.FileJson = new List<Share.Dtos.File.FileJson>();
  300. }
  301. await _caseListRepository.UpdateNullAsync(Case, cancellationToken);
  302. if (dto.ApplyStatus != ECaseApplyStatus.Delete)
  303. {
  304. if (dto.CaseTypes.Any())
  305. {
  306. var anyRelationTypes = await _caseRelationTypeRepository.Queryable().Where(x => x.CaseId == Case.Id).ToListAsync();
  307. if (anyRelationTypes.Any())
  308. await _caseRelationTypeRepository.RemoveRangeAsync(anyRelationTypes);
  309. List<CaseRelationType> types = _mapper.Map<List<CaseRelationType>>(dto.CaseTypes);
  310. types.ForEach(x => x.CaseId = dto.Id);
  311. await _caseRelationTypeRepository.AddRangeAsync(types, cancellationToken);
  312. }
  313. }
  314. }
  315. #endregion
  316. #region 案例库 - 删除
  317. /// <summary>
  318. /// 删除
  319. /// </summary>
  320. /// <param name="dto"></param>
  321. /// <param name="cancellationToken"></param>
  322. /// <returns></returns>
  323. public async Task RemoveCaseAsync(UpdateCaseListDto dto, CancellationToken cancellationToken)
  324. {
  325. var Case = await _caseListRepository.GetAsync(dto.Id);
  326. if (Case == null)
  327. throw UserFriendlyException.SameMessage("案例库查询失败");
  328. _mapper.Map(dto, Case);
  329. Case.IsDeleted = true;
  330. await _caseListRepository.UpdateNullAsync(Case, cancellationToken);
  331. }
  332. #endregion
  333. #region 案例库 - 审核
  334. /// <summary>
  335. /// 审核
  336. /// </summary>
  337. /// <param name="dto"></param>
  338. /// <param name="cancellationToken"></param>
  339. /// <returns></returns>
  340. public async Task AuditCaseAsync(UpdateCaseListDto dto, CancellationToken cancellationToken)
  341. {
  342. var Case = await _caseListRepository.GetAsync(dto.Id);
  343. if (Case == null)
  344. throw UserFriendlyException.SameMessage("案例库查询失败");
  345. Case.Status = (ECaseStatus)dto.Status!;
  346. Case.ApplyStatus = (ECaseApplyStatus)dto.ApplyStatus!;
  347. Case.ExaminTime = dto.ExaminTime;
  348. Case.ExaminManId = dto.ExaminManId;
  349. Case.ExaminOrganizeId = dto.ExaminOrganizeId;
  350. Case.ExaminOpinion = dto.ExaminOpinion;
  351. Case.UpdateTime = dto.UpdateTime;
  352. Case.OnShelfTime = dto.OnShelfTime;
  353. Case.OffShelfTime = dto.OffShelfTime;
  354. if (Case.ApplyStatus == ECaseApplyStatus.Delete)
  355. {
  356. Case.IsDeleted = true;
  357. }
  358. await _caseListRepository.UpdateNullAsync(Case, cancellationToken);
  359. }
  360. #endregion
  361. #region 案例库 - 详情
  362. /// <summary>
  363. /// 详情
  364. /// </summary>
  365. /// <param name="Id"></param>
  366. /// <param name="IsAddPv">默认不增加,false不增加,true增加浏览量</param>
  367. /// <returns></returns>
  368. public async Task<CaseInfoDto> GetCaseAsync(string Id, bool? IsAddPv, CancellationToken cancellationToken)
  369. {
  370. var Case = await _caseListRepository.Queryable()
  371. .Includes(x => x.CaseTypes)
  372. .Includes(x => x.Order)
  373. .Includes(x => x.Knowledge)
  374. .Where(x => x.Id == Id).FirstAsync();
  375. if (Case == null)
  376. throw UserFriendlyException.SameMessage("案例库查询失败");
  377. ;
  378. //转化
  379. var caseInfoDto = _mapper.Map<CaseInfoDto>(Case);
  380. if (Case != null)
  381. {
  382. if (!string.IsNullOrEmpty(Case.Abstract))
  383. caseInfoDto.Abstract = _bulletinApplication.GetSiteUrls(Case.Abstract);
  384. if (!string.IsNullOrEmpty(Case.Describe))
  385. caseInfoDto.Describe = _bulletinApplication.GetSiteUrls(Case.Describe);
  386. if (!string.IsNullOrEmpty(Case.Result))
  387. caseInfoDto.Result = _bulletinApplication.GetSiteUrls(Case.Result);
  388. if (!string.IsNullOrEmpty(Case.Reason))
  389. caseInfoDto.Reason = _bulletinApplication.GetSiteUrls(Case.Reason);
  390. }
  391. // 分类
  392. //var relationType = await _caseRelationTypeRepository.QueryAsync(x => x.CaseId == Id && x.CreatorId == _sessionContext.UserId);
  393. //if (relationType != null)
  394. //{
  395. // caseInfoDto.CaseTypes = _mapper.Map<List<CaseRelationTypeDto>>(relationType);
  396. //}
  397. // 收藏
  398. var collect = await _caseCollectRepository.GetAsync(x => x.CaseId == Id && x.CreatorId == _sessionContext.UserId);
  399. if (collect != null)
  400. caseInfoDto.Collect = _mapper.Map<CaseCollectDto>(collect);
  401. // 附件
  402. if (caseInfoDto.FileJson != null && caseInfoDto.FileJson.Any())
  403. {
  404. var ids = caseInfoDto.FileJson.Select(x => x.Id).ToList();
  405. caseInfoDto.Files = await _fileRepository.GetFilesAsync(ids, cancellationToken);
  406. }
  407. // 更新浏览量
  408. if (IsAddPv == true)
  409. {
  410. //修改浏览量
  411. Case.PageView++;
  412. //修改点击量
  413. await _caseListRepository.UpdateAsync(Case, cancellationToken);
  414. }
  415. return caseInfoDto;
  416. }
  417. #endregion
  418. #region 案例库 - 批量导出
  419. /// <summary>
  420. /// 案例库 - 批量导出
  421. /// </summary>
  422. /// <param name="dto"></param>
  423. /// <param name="cancellationToken"></param>
  424. /// <returns></returns>
  425. public async Task<Dictionary<string, Stream>> CaseInfoListExportAsync(CaseInfoExportDto dto, CancellationToken cancellationToken)
  426. {
  427. var streamList = new Dictionary<string, Stream>();
  428. var knowList = await _caseListRepository.Queryable()
  429. .Where(m => dto.Ids.Contains(m.Id))
  430. .Select(m => new { m.Title, m.Result })
  431. .ToListAsync(cancellationToken);
  432. var tasks = knowList.Select(async item =>
  433. {
  434. var stream = await Task.Run(() => item.Result.HtmlToStream(dto.FileType), cancellationToken);
  435. return new KeyValuePair<string, Stream>(
  436. item.Title + dto.FileType.GetFileExtension(),
  437. stream
  438. );
  439. });
  440. var results = await Task.WhenAll(tasks);
  441. foreach (var kvp in results)
  442. {
  443. if (!streamList.ContainsKey(kvp.Key))
  444. {
  445. streamList.Add(kvp.Key, kvp.Value);
  446. }
  447. }
  448. return streamList;
  449. }
  450. #endregion
  451. #endregion
  452. #region 私有方法
  453. #region 查询所有子级
  454. /// <summary>
  455. /// 查询所有子级
  456. /// </summary>
  457. /// <param name="treeDatas">分类数据</param>
  458. /// <param name="ID">需要查询哪级下面的分类</param>
  459. /// <param name="checkId">选中的数据ID</param>
  460. /// <returns></returns>
  461. private List<TreeListDto> GetChildren(List<CaseType> treeDatas, string ID, string? checkId)
  462. {
  463. List<TreeListDto> nodeList = new();
  464. //根据ID查询子级
  465. var children = treeDatas.Where(q => q.ParentId == ID);
  466. foreach (var dr in children)
  467. {
  468. //组装数据
  469. TreeListDto node = new()
  470. {
  471. name = dr.Name,
  472. ParentID = dr.ParentId,
  473. value = dr.Id,
  474. IsEnable = dr.IsEnable
  475. };
  476. //是否选中
  477. if (!string.IsNullOrEmpty(checkId) && checkId != Guid.Empty.ToString() && checkId == dr.Id)
  478. node.selected = true;
  479. //子级数据赋值
  480. node.children = GetChildren(treeDatas, node.value, checkId);
  481. //添加数据
  482. nodeList.Add(node);
  483. }
  484. return nodeList;
  485. }
  486. #endregion
  487. #region 获取全称
  488. /// <summary>
  489. /// 获取全称
  490. /// </summary>
  491. /// <param name="Id"></param>
  492. /// <returns></returns>
  493. private async Task<string> GetFullName(string? Id)
  494. {
  495. //获取全部父级名称
  496. var list = await GetParentNode(Id);
  497. //倒叙
  498. list.Reverse();
  499. //拆分
  500. return string.Join("-", list.ToArray());
  501. }
  502. /// <summary>
  503. /// 查询父级名称
  504. /// </summary>
  505. /// <param name="Id"></param>
  506. /// <returns></returns>
  507. private async Task<List<string>> GetParentNode(string? Id)
  508. {
  509. List<string> list = new();
  510. //查询父级数据
  511. var type = await _caseTypeRepository.GetAsync(p => p.Id == Id);
  512. if (type != null)
  513. {
  514. //添加名称
  515. list.Add(type.Name);
  516. list.AddRange(await GetParentNode(type.ParentId));
  517. }
  518. return list;
  519. }
  520. #endregion
  521. #region 修改子级分类全称
  522. /// <summary>
  523. /// 修改子级分类全称
  524. /// </summary>
  525. /// <param name="Id"></param>
  526. /// <returns></returns>
  527. private async Task UpdateChildNode(string Id)
  528. {
  529. //查询子分类
  530. var list = await GetChildNode(Id);
  531. if (list is not null && list.Count > 0)
  532. {
  533. foreach (var item in list)
  534. {
  535. //获取全称
  536. string FullName = await GetFullName(item.ParentId);
  537. item.SpliceName = string.IsNullOrEmpty(FullName) ? item.Name : FullName + "-" + item.Name;
  538. //修改全称
  539. await _caseTypeRepository.UpdateAsync(item);
  540. }
  541. }
  542. }
  543. /// <summary>
  544. /// 查询子级节点数据
  545. /// </summary>
  546. /// <param name="Id"></param>
  547. /// <returns></returns>
  548. private async Task<List<CaseType>> GetChildNode(string Id)
  549. {
  550. List<CaseType> list = new();
  551. //查询数据
  552. var typelist = await _caseTypeRepository.QueryAsync(p => p.ParentId == Id);
  553. if (typelist != null)
  554. {
  555. //处理数据
  556. foreach (var item in typelist)
  557. {
  558. list.Add(item);
  559. list.AddRange(await GetChildNode(item.Id));
  560. }
  561. }
  562. return list;
  563. }
  564. #endregion
  565. #endregion
  566. }
  567. }