using Hotline.Application.Tools; using Hotline.KnowledgeBase; using Hotline.Repository.SqlSugar.Extensions; using Hotline.Settings; using Hotline.Settings.Hotspots; using Hotline.Share.Dtos; using Hotline.Share.Dtos.Knowledge; using Hotline.Share.Enums.Article; using Hotline.Share.Enums.KnowledgeBase; using Hotline.Share.Tools; using Hotline.Users; using Mapster; using MapsterMapper; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Org.BouncyCastle.Utilities.IO; using PanGu; using SqlSugar; using XF.Domain.Authentications; using XF.Domain.Dependency; using XF.Domain.Exceptions; using XF.Domain.Repository; namespace Hotline.Application.Knowledge { public class KnowApplication : IKnowApplication, IScopeDependency { private readonly IKnowledgeRepository _knowledgeRepository; private readonly IRepository _knowledgePvepository; private readonly IRepository _hotspotTypeRepository; private readonly IRepository _knowledgeTypeRepository; private readonly IRepository _knowledgeApplyRepository; private readonly IRepository _knowledgeWordRepository; private readonly IRepository _knowledgeHotWordRepository; private readonly ISessionContext _sessionContext; private readonly IMapper _mapper; /// /// /// /// /// /// /// /// public KnowApplication(IKnowledgeRepository knowledgeRepository, IRepository knowledgeApplyRepository, ISessionContext sessionContext, IMapper mapper, IRepository knowledgeTypeRepository, IRepository hotspotTypeRepository, IRepository knowledgeWordRepository, IRepository knowledgePvepository, IRepository knowledgeHotWordRepository) { _knowledgeRepository = knowledgeRepository; _knowledgeApplyRepository = knowledgeApplyRepository; _sessionContext = sessionContext; _mapper = mapper; _knowledgeTypeRepository = knowledgeTypeRepository; _hotspotTypeRepository = hotspotTypeRepository; _knowledgeWordRepository = knowledgeWordRepository; _knowledgePvepository = knowledgePvepository; _knowledgeHotWordRepository = knowledgeHotWordRepository; } /// /// 知识库查询 /// /// /// public async Task<(int, IList)> GetKnowList(KnowPagedListDto pagedDto, CancellationToken cancellationToken) { var typeSpliceName = string.Empty; var hotspotHotSpotFullName = string.Empty; if (!string.IsNullOrEmpty(pagedDto.KnowledgeTypeId)) { var type = await _knowledgeTypeRepository.GetAsync(x => x.Id == pagedDto.KnowledgeTypeId); typeSpliceName = type?.SpliceName; } if (!string.IsNullOrEmpty(pagedDto.HotspotId)) { var hotspot = await _hotspotTypeRepository.GetAsync(x => x.Id == pagedDto.HotspotId); hotspotHotSpotFullName = hotspot?.HotSpotFullName; } var (total, temp) = await _knowledgeRepository.Queryable(false, false, false) .Includes(x => x.User) .Includes(x => x.SystemOrganize) .Includes(x => x.SourceOrganize) .Includes(x => x.HotspotType) .Includes(x => x.Workflow) .Includes(x => x.KnowledgeType) .Where(x => x.IsDeleted == false) .Where(x => x.KnowledgeType.Any(t => t.KnowledgeType.KnowledgeTypeOrgs.Any(to => to.OrgId == _sessionContext.RequiredOrgId) || t.KnowledgeType.KnowledgeTypeOrgs.Any() == false)) .Where(x => (x.Status == EKnowledgeStatus.Drafts && x.CreatorId == _sessionContext.UserId) || (x.Status != EKnowledgeStatus.Drafts)) .WhereIF(!string.IsNullOrEmpty(pagedDto.Title), x => x.Title.Contains(pagedDto.Title!)) .WhereIF(!string.IsNullOrEmpty(pagedDto.Keyword), x => x.Title.Contains(pagedDto.Keyword!) || x.CreatorName.Contains(pagedDto.Keyword!) || x.CreatorOrgName.Contains(pagedDto.Keyword!) || x.SourceOrganize.Name.Contains(pagedDto.Keyword!)) .WhereIF(pagedDto.Status.HasValue && pagedDto.Status != EKnowledgeStatus.OffShelf, x => x.Status == pagedDto.Status && ((x.ExpiredTime != null && x.ExpiredTime > DateTime.Now) || x.ExpiredTime == null)) .WhereIF(pagedDto.Status.HasValue && pagedDto.Status == EKnowledgeStatus.OffShelf, x => x.Status == pagedDto.Status || (x.ExpiredTime != null && x.ExpiredTime < DateTime.Now && x.Status != EKnowledgeStatus.Drafts)) .WhereIF(pagedDto.IsPublic.HasValue, x => x.IsPublic == pagedDto.IsPublic) .WhereIF(!string.IsNullOrEmpty(pagedDto.Summary), x => x.Summary != null && x.Summary.Contains(pagedDto.Summary!)) .WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => x.KnowledgeType.Any(t => t.KnowledgeTypeSpliceName.EndsWith(typeSpliceName))) .WhereIF(!string.IsNullOrEmpty(hotspotHotSpotFullName), x => x.HotspotType.HotSpotFullName.EndsWith(hotspotHotSpotFullName!)) .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateOrgId), x => x.SourceOrganizeId != null && x.SourceOrganizeId.EndsWith(pagedDto.CreateOrgId!)) .WhereIF(!string.IsNullOrEmpty(pagedDto.ModuleCode), x => x.Workflow.ModuleCode == pagedDto.ModuleCode) .OrderByDescending(d => d.CreationTime) .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize, cancellationToken); //返回数据 return (total, _mapper.Map>(temp)); } /// /// 知识申请查询 /// /// /// /// public async Task> GetApplyList(KnowledgeApplyPagedDto pagedDto, CancellationToken cancellationToken) { var (total, items) = await _knowledgeApplyRepository .Queryable() .Includes(it => it.User) .Includes(it => it.SystemOrganize) .Where(d => d.CreatorId == _sessionContext.RequiredUserId) .WhereIF(pagedDto.Status.HasValue, d => d.Status == pagedDto.Status) .WhereIF(pagedDto.ApplyType.HasValue, d => d.KnowledgeApplyType == pagedDto.ApplyType) .WhereIF(!string.IsNullOrEmpty(pagedDto.IsOvertime) && pagedDto.IsOvertime == "0", d => d.IsOvertime == true) .WhereIF(!string.IsNullOrEmpty(pagedDto.IsOvertime) && pagedDto.IsOvertime == "1", d => d.IsOvertime == false) .WhereIF(pagedDto.StartTime.HasValue, d => d.CreationTime >= pagedDto.StartTime) .WhereIF(pagedDto.EndTime.HasValue, d => d.CreationTime <= pagedDto.EndTime) .OrderByDescending(p => p.CreationTime) .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize, cancellationToken); return new PagedDto(total, _mapper.Map>(items)); } /// /// 申请处理查询 /// /// /// /// public async Task> GetApplyHandleList(KnowledgeHandlePagedDto pagedDto, CancellationToken cancellationToken) { var (total, items) = await _knowledgeApplyRepository .Queryable() .Includes(it => it.User) .Includes(it => it.SystemOrganize) .Where(p => p.DepartmentId == _sessionContext.RequiredOrgId) .WhereIF(pagedDto.Status.HasValue, d => d.Status == pagedDto.Status) .WhereIF(!string.IsNullOrEmpty(pagedDto.Keyword), d => d.User.Name.Contains(pagedDto.Keyword!) || d.SystemOrganize.Name.Contains(pagedDto.Keyword!)) .WhereIF(pagedDto.ApplyType.HasValue, d => d.KnowledgeApplyType == pagedDto.ApplyType) .WhereIF(!string.IsNullOrEmpty(pagedDto.IsOvertime) && pagedDto.IsOvertime == "0", d => d.IsOvertime == true) .WhereIF(!string.IsNullOrEmpty(pagedDto.IsOvertime) && pagedDto.IsOvertime == "1", d => d.IsOvertime == false) .WhereIF(pagedDto.StartTime.HasValue && pagedDto.Status != EKnowledgeApplyStatus.Failed && pagedDto.Status != EKnowledgeApplyStatus.Succeed, d => d.CreationTime >= pagedDto.StartTime) .WhereIF(pagedDto.EndTime.HasValue && pagedDto.Status != EKnowledgeApplyStatus.Failed && pagedDto.Status != EKnowledgeApplyStatus.Succeed, d => d.CreationTime <= pagedDto.EndTime) .WhereIF(pagedDto.StartTime.HasValue && pagedDto.Status == EKnowledgeApplyStatus.Failed, d => d.ReturnTime >= pagedDto.StartTime) .WhereIF(pagedDto.EndTime.HasValue && pagedDto.Status == EKnowledgeApplyStatus.Failed, d => d.ReturnTime <= pagedDto.EndTime) .WhereIF(pagedDto.StartTime.HasValue && pagedDto.Status == EKnowledgeApplyStatus.Succeed, d => d.HandleTime >= pagedDto.StartTime) .WhereIF(pagedDto.EndTime.HasValue && pagedDto.Status == EKnowledgeApplyStatus.Succeed, d => d.HandleTime <= pagedDto.EndTime) .OrderByDescending(p => p.CreationTime) .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize, cancellationToken); return new PagedDto(total, _mapper.Map>(items)); } public async Task> KnowledgeInfoListExportAsync(KnowledgeInfoExportInDto dto, CancellationToken cancellationToken) { var streamList = new Dictionary(); var knowList = await _knowledgeRepository.Queryable() .Where(m => dto.Ids.Contains(m.Id)) .Select(m => new { m.Title, m.Content }) .ToListAsync(cancellationToken); foreach (var item in knowList) { Stream stream = item.Content.HtmlToStream(dto.FileType); streamList.Add(item.Title + dto.FileType.GetFileExtension(), stream); } return streamList; } public async Task> TitleParticiple(string title) { var keywords = new List(); var splitWords = new Segment().DoSegment(title); for (int i = 0;i < splitWords.Count;i++) { var word = splitWords.ElementAt(i); if (word is not { WordType: WordType.SimplifiedChinese, Word.Length: > 1 }) continue; var tag = splitWords.ElementAt(i).Word; var entity = await _knowledgeWordRepository.Queryable().Where(m => m.Tag == tag).FirstAsync(); if (entity is not null) { keywords.Add(new KnowledgeWordOutDto(entity.Id, entity.Tag)); continue; } var wordEntity = new KnowledgeWord { Tag = tag, Classify = "普通标签", Remark = "系统自动从知识标题分词", Synonym = "", IsEnable = 1 }; var keyId = await _knowledgeWordRepository.AddAsync(wordEntity); keywords.Add(new KnowledgeWordOutDto(keyId, tag)); } return keywords; } public async Task<(int, IList)> GetPageViewListAsync(PageViewInDto dto, CancellationToken requestAborted = default) { var query = _knowledgePvepository.Queryable(includeDeleted: true) .LeftJoin((p, k) => p.KnowledgeCode == k.Code) .LeftJoin((p, k, r) => r.KnowledgeId == k.Id) .WhereIF(dto.Title.NotNullOrEmpty(), (p, k, r) => k.Title.Contains(dto.Title)) .WhereIF(dto.CreatorName.NotNullOrEmpty(), (p, k, r) => p.CreatorName.Contains(dto.CreatorName)) .WhereIF(dto.KnowledgeTypeId.NotNullOrEmpty(), (p, k, r) => r.KnowledgeTypeId == dto.KnowledgeTypeId) .WhereIF(dto.StartTime.HasValue && dto.EndTime.HasValue, (p, k, r) => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime) .OrderByDescending((p, k, r) => p.CreationTime); if (_sessionContext.OrgIsCenter == false) query = query.Where((p, k, r) => p.CreatorOrgId.StartsWith(_sessionContext.OrgId)); return await query.Select().ToPagedListAsync(dto.PageIndex, dto.PageSize, requestAborted); } public async Task<(int total, IList items)> GetKnowledgeHotWordListAsync(KnowledgeHotWordInDto dto, CancellationToken requestAborted) { var query = _knowledgeHotWordRepository.Queryable() .WhereIF(dto.IsEnable != null, m => m.IsEnable == dto.IsEnable) .WhereIF(dto.KeyWord.NotNullOrEmpty(), m => m.KeyWord.Contains(dto.KeyWord)) .WhereIF(dto.Type != null, m => m.Type == dto.Type) // .WhereIF(dto.StartTime.HasValue && dto.EndTime.HasValue, m => m.CreationTime >= dto.StartTime && m.CreationTime <= dto.EndTime) ; if (dto.SortField.NotNullOrEmpty()) query = query.OrderByPropertyName(dto.SortField, (OrderByType)dto.OrderByType); else { query = query.OrderByDescending(m => m.Sort); query = query.OrderByDescending(m => m.CreationTime); } return await query.Select().ToPagedListAsync(dto.PageIndex, dto.PageSize, requestAborted); } public async Task UpdateKnowledgeHotWordAsync(UpdateKnowledgeHotWordInDto dto, CancellationToken requestAborted) { var entity = await _knowledgeHotWordRepository.GetAsync(dto.Id) ?? throw UserFriendlyException.SameMessage("数据不存在"); dto.Adapt(entity); await _knowledgeHotWordRepository.UpdateAsync(entity); } public async Task AddKnowledgeHotWordAsync(AddKnowledgeHotWordInDto dto, CancellationToken requestAborted) { var isExist = await _knowledgeHotWordRepository.Queryable() .Where(m => m.KeyWord == dto.KeyWord).AnyAsync(); if (isExist) throw UserFriendlyException.SameMessage("热词已存在"); var entity = dto.Adapt(); await _knowledgeHotWordRepository.AddAsync(entity, requestAborted); } public async Task<(int, List)> KnowRetrievalAsync(KnowledgeRetrievalPagedListDto dto) { var typeSpliceName = string.Empty; var hotspotHotSpotFullName = string.Empty; if (!string.IsNullOrEmpty(dto.KnowledgeTypeId)) { var type = await _knowledgeTypeRepository.GetAsync(x => x.Id == dto.KnowledgeTypeId); typeSpliceName = type?.SpliceName; } if (!string.IsNullOrEmpty(dto.HotspotId)) { var hotspot = await _hotspotTypeRepository.GetAsync(x => x.Id == dto.HotspotId); hotspotHotSpotFullName = hotspot?.HotSpotFullName; } var sugar = _knowledgeRepository .Queryable(false, false, false) .Includes(x => x.User) .Includes(x => x.SystemOrganize) .Includes(x => x.HotspotType) .Where(x => x.IsDeleted == false) .Where(x => x.Status == EKnowledgeStatus.OnShelf) .Where(x => x.KnowledgeType.Any(t => t.KnowledgeType.KnowledgeTypeOrgs.Any(to => to.OrgId == _sessionContext.RequiredOrgId) || t.KnowledgeType.KnowledgeTypeOrgs.Any() == false)) .WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => x.KnowledgeType.Any(t => t.KnowledgeTypeSpliceName.EndsWith(typeSpliceName))) .WhereIF(!string.IsNullOrEmpty(hotspotHotSpotFullName), x => x.HotspotType.HotSpotFullName.EndsWith(hotspotHotSpotFullName!)) .WhereIF(!string.IsNullOrEmpty(dto.HotspotName), x => x.HotspotType.HotSpotFullName.EndsWith(dto.HotspotName!)) .WhereIF(!string.IsNullOrEmpty(dto.CreateOrgId), x => x.CreatorOrgId != null && x.CreatorOrgId.EndsWith(dto.CreateOrgId!)) .WhereIF(!string.IsNullOrEmpty(dto.Attribution), x => x.Attribution == dto.Attribution!); if (dto.Keyword.NotNullOrEmpty()) { var keywords = dto.Keyword!.SplitKeywords(); var exp = Expressionable.Create(); foreach (var keyword in keywords) { if (dto.RetrievalType == EKnowledgeRetrievalType.All) exp.Or(x => x.Title.Contains(keyword) || x.Content.Contains(keyword)); if (dto.RetrievalType == EKnowledgeRetrievalType.Title) exp.Or(x => x.Title.Contains(keyword)); if (dto.RetrievalType == EKnowledgeRetrievalType.Content) exp.Or(x => x.Content.Contains(keyword)); if (dto.RetrievalType == EKnowledgeRetrievalType.Summary) exp.Or(x => x.Summary != null && x.Summary.Contains(keyword)); if (dto.RetrievalType == EKnowledgeRetrievalType.KeyWord) { var keywordEntity = await _knowledgeWordRepository.GetAsync(m => m.Tag == keyword && m.IsEnable == 0); if (keywordEntity is null) continue; exp.Or(x => SqlFunc.JsonArrayAny(x.Keywords, keywordEntity.Id)); } } sugar = sugar.Where(exp.ToExpression()); } if (dto.Content.NotNullOrEmpty()) { var keywords = dto.Content!.GetSegment(); var exp = Expressionable.Create(); _knowledgeWordRepository.Queryable() .Where(m => keywords.Contains(m.Tag) && m.IsEnable == 0) .Select(m => m.Id) .ToList() .ForEach(m => exp.Or(x => SqlFunc.JsonArrayAny(x.Keywords, m)) ); sugar = sugar.Where(exp.ToExpression()); } switch (dto.Sort) { case "2": sugar = sugar.OrderByDescending(p => p.CollectCount); break; case "3": sugar = sugar.OrderByDescending(p => p.CreationTime); break; default: sugar = sugar.OrderByDescending(p => p.PageView); break; } return await sugar.Select().ToPagedListAsync(dto.PageIndex, dto.PageSize); } } }