using Hotline.Settings.Hotspots;
using Hotline.Share.Dtos.Knowledge;
using Hotline.Share.Dtos.Caselibrary;
using Hotline.Share.Enums.Caselibrary;
using MapsterMapper;
using XF.Domain.Authentications;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using XF.Domain.Repository;
using Hotline.Repository.SqlSugar.Extensions;
using Hotline.SeedData;
using Hotline.File;
using Hotline.Application.Bulletin;
using Hotline.Share.Tools;
using Hotline.Application.Tools;
using SqlSugar;
using Hotline.CaseLibrary;
using Hotline.Orders;
using Hotline.KnowledgeBase;
using Hotline.Share.Enums.Planlibrary;
using System.Numerics;
namespace Hotline.Application.Caselibrary
{
///
/// 案例库处理
///
public class CaseApplication : ICaseApplication, IScopeDependency
{
#region 注册
private readonly IRepository _caseListRepository; //案例库列表
private readonly IRepository _caseRelationTypeRepository; //案例库关联类型
private readonly IRepository _caseTypeRepository; //案例库分类管理
private readonly IRepository _caseTypeOrgRepository; //案例库分类关联机构
private readonly IRepository _caseCollectRepository; //案例库收藏评分
private readonly IRepository _orderRepository; //工单
private readonly IRepository _knowledgeRepository; //知识库
private readonly ISessionContext _sessionContext;
private readonly IMapper _mapper;
private readonly IRepository _hotspotTypeRepository;
private readonly IFileRepository _fileRepository;
private readonly IBulletinApplication _bulletinApplication;
public CaseApplication(
IRepository caseListRepository,
IRepository caseRelationTypeRepository,
IRepository caseTypeRepository,
IRepository caseTypeOrgRepository,
IRepository caseCollectRepository,
IRepository orderRepository,
IRepository knowledgeRepository,
ISessionContext sessionContext,
IMapper mapper,
IRepository hotspotTypeRepository,
IFileRepository fileRepository,
IBulletinApplication bulletinApplication)
{
_caseListRepository = caseListRepository;
_caseRelationTypeRepository = caseRelationTypeRepository;
_caseTypeRepository = caseTypeRepository;
_caseTypeOrgRepository = caseTypeOrgRepository;
_caseCollectRepository = caseCollectRepository;
_orderRepository = orderRepository;
_knowledgeRepository = knowledgeRepository;
_sessionContext = sessionContext;
_mapper = mapper;
_hotspotTypeRepository = hotspotTypeRepository;
_fileRepository = fileRepository;
_bulletinApplication = bulletinApplication;
}
#endregion
#region 案例库类型管理
#region 案例库类型 - 新增
///
/// 案例库类型 - 新增
///
///
///
///
public async Task AddTypeAsync(AddCaseTypeDto dto, CancellationToken cancellationToken)
{
var sandard = await _caseTypeRepository.GetAsync(p => p.ParentId == dto.ParentId && p.Name == dto.Name && p.IsDeleted == false, cancellationToken);
if (sandard is not null)
throw UserFriendlyException.SameMessage("当前层级已存在相同名称的分类!");
var type = _mapper.Map(dto);
type.InitId();
type.IsEnable = true;
//获取分类名称全称
string FullName = await GetFullName(type.ParentId);
//处理全称,如果为第一级直接用全称,否则获取全称后拼接名称
type.SpliceName = string.IsNullOrEmpty(FullName) ? dto.Name : FullName + "-" + dto.Name;
var id = await _caseTypeRepository.AddAsync(type, cancellationToken);
if (dto.TypeOrgDtos != null && dto.TypeOrgDtos.Any())
{
List orgs = _mapper.Map>(dto.TypeOrgDtos);
orgs.ForEach(x => x.TypeId = type.Id);
await _caseTypeOrgRepository.AddRangeAsync(orgs, cancellationToken);
}
return id;
}
#endregion
#region 案例库类型 - 编辑
///
/// 案例库类型 - 编辑
///
///
///
///
public async Task UpdateTypeAsync(UpdateCaseTypeDto dto, CancellationToken cancellationToken)
{
//查询原有数据
var type = await _caseTypeRepository.GetAsync(dto.Id, cancellationToken);
if (type is null)
throw UserFriendlyException.SameMessage("编辑失败!");
bool result = type.Name != dto.Name || type.ParentId != dto.ParentId;
//是否更改分类名称或者层级
//转换
_mapper.Map(dto, type);
//如果更改了名称或者修改了层级,则修改全称,未更改不修改
if (result)
{
string FullName = await GetFullName(type.ParentId);//获取分类名称全称
type.SpliceName = string.IsNullOrEmpty(FullName) ? dto.Name : FullName + "-" + dto.Name;//处理全称,如果为第一级直接用全称,否则获取全称后拼接名称
}
//修改数据
await _caseTypeRepository.UpdateAsync(type, cancellationToken);
//如果修改了名称,对应修改子分类全称
if (result)
await UpdateChildNode(type.Id);
// 修改关联机构
await _caseTypeOrgRepository.RemoveAsync(x => x.TypeId == type.Id, false, cancellationToken);
if (dto.TypeOrgDtos != null && dto.TypeOrgDtos.Any())
{
List orgs = _mapper.Map>(dto.TypeOrgDtos);
orgs.ForEach(x => x.TypeId = type.Id);
await _caseTypeOrgRepository.AddRangeAsync(orgs, cancellationToken);
}
}
#endregion
#region 案例库类型 - 删除
///
/// 案例库类型 - 删除
///
///
///
///
public async Task RemoveTypeAsync(string Id, CancellationToken cancellationToken)
{
//查询数据是否存在
var sandard = await _caseTypeRepository.GetAsync(p => p.Id == Id && p.IsDeleted == false, cancellationToken);
if (sandard is null)
throw UserFriendlyException.SameMessage("分类不存在!");
//查询是否有子级分类
var checkChild = await _caseTypeRepository.CountAsync(p => p.ParentId == Id && p.IsDeleted == false, cancellationToken);
if (checkChild > 0)
throw UserFriendlyException.SameMessage("存在子级分类!");
//查询是否有案例分类
var checkKnowledge = await _caseListRepository.CountAsync(p => p.CaseTypes.Any(t => t.CaseId == Id), cancellationToken);
if (checkKnowledge > 0)
throw UserFriendlyException.SameMessage("分类存在案例!");
//删除操作
await _caseTypeRepository.RemoveAsync(sandard, true, cancellationToken);
}
#endregion
#endregion
#region 案例库管理
#region 案例库 - 列表
///
/// 案例库 - 列表
///
///
///
public async Task<(int, IList)> QueryAllCaseListAsync(CaseListDto pagedDto, CancellationToken cancellationToken)
{
var typeSpliceName = string.Empty;
if (!string.IsNullOrEmpty(pagedDto.CaseTypeID))
{
var type = await _caseTypeRepository.GetAsync(x => x.Id == pagedDto.CaseTypeID);
typeSpliceName = type?.SpliceName;
}
//单表分页
var (total, temp) = await _caseListRepository.Queryable()
.Includes(x => x.CaseTypes)
.Includes(x => x.ExaminMan)
.Where(x => x.IsDeleted == false)
.Where(x => (x.Status == ECaseStatus.Drafts && x.CreatorId == _sessionContext.UserId) || (x.Status != ECaseStatus.Drafts))
.WhereIF(OrgSeedData.CenterId != pagedDto.CreateOrgId && !string.IsNullOrEmpty(pagedDto.CreateOrgId), x => x.CreatorOrgId != null && x.CreatorOrgId.StartsWith(pagedDto.CreateOrgId!))
.WhereIF(!string.IsNullOrEmpty(pagedDto.Title), x => x.Title.Contains(pagedDto.Title))
.WhereIF(!string.IsNullOrEmpty(pagedDto.Abstract), x => x.Abstract.Contains(pagedDto.Abstract))
.WhereIF(!string.IsNullOrEmpty(pagedDto.Describe), x => x.Describe.Contains(pagedDto.Describe))
.WhereIF(!string.IsNullOrEmpty(pagedDto.Result), x => x.Result.Contains(pagedDto.Result))
.WhereIF(!string.IsNullOrEmpty(pagedDto.Reason), x => x.Reason.Contains(pagedDto.Reason))
.WhereIF(!string.IsNullOrEmpty(pagedDto.Keyword), x => x.Title.Contains(pagedDto.Keyword!) ||
x.CreatorName!.Contains(pagedDto.Keyword!) ||
x.CreatorOrgName!.Contains(pagedDto.Keyword!))
.WhereIF(pagedDto.Status.HasValue && pagedDto.Status != ECaseStatus.OffShelf &&
pagedDto.Status != ECaseStatus.NewDrafts &&
pagedDto.Status != ECaseStatus.All,
x => x.Status == pagedDto.Status && ((x.ExpiredTime != null && x.ExpiredTime > DateTime.Now) || x.ExpiredTime == null))
.WhereIF(pagedDto.Status.HasValue && pagedDto.Status == ECaseStatus.OffShelf, x => x.Status == pagedDto.Status || (x.ExpiredTime != null && x.ExpiredTime < DateTime.Now && x.Status != ECaseStatus.Drafts))
.WhereIF(pagedDto.Status.HasValue && pagedDto.Status == ECaseStatus.NewDrafts, x => x.Status == ECaseStatus.Drafts || x.Status == ECaseStatus.Revert || x.Status == ECaseStatus.NewDrafts)
.WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => x.CaseTypes.Any(t => t.CaseTypeSpliceName.StartsWith(typeSpliceName)))
.WhereIF(pagedDto.CreationTimeStart.HasValue, x => x.CreationTime >= pagedDto.CreationTimeStart)
.WhereIF(pagedDto.CreationTimeEnd.HasValue, x => x.CreationTime <= pagedDto.CreationTimeEnd)
.WhereIF(pagedDto.OnShelfTimeStart.HasValue, x => x.OnShelfTime >= pagedDto.OnShelfTimeStart)
.WhereIF(pagedDto.OnShelfTimeEnd.HasValue, x => x.OnShelfTime <= pagedDto.OnShelfTimeEnd)
.WhereIF(pagedDto.OffShelfTimeStart.HasValue, x => x.OffShelfTime >= pagedDto.OffShelfTimeStart)
.WhereIF(pagedDto.OffShelfTimeEnd.HasValue, x => x.OffShelfTime <= pagedDto.OffShelfTimeEnd)
.WhereIF(pagedDto.UpdateTimeStart.HasValue, x => x.UpdateTime >= pagedDto.UpdateTimeStart)
.WhereIF(pagedDto.UpdateTimeEnd.HasValue, x => x.UpdateTime <= pagedDto.UpdateTimeEnd)
.WhereIF(pagedDto.ExaminTimeStart.HasValue, x => x.ExaminTime >= pagedDto.ExaminTimeStart)
.WhereIF(pagedDto.ExaminTimeEnd.HasValue, x => x.ExaminTime <= pagedDto.ExaminTimeEnd)
.OrderByIF(string.IsNullOrEmpty(pagedDto.SortField), x => x.CreationTime, OrderByType.Desc)
.OrderByIF(pagedDto is { SortField: "pageView" }, x => x.PageView, OrderByType.Desc) //阅读量
.OrderByIF(pagedDto is { SortField: "score" }, x => x.Score, OrderByType.Desc) //评分
.OrderByIF(pagedDto is { SortField: "creationTime" }, x => x.CreationTime, OrderByType.Desc) //创建时间
.ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize, cancellationToken);
return (total, _mapper.Map>(temp));
}
#endregion
#region 案例库 - 新增
///
/// 新增
///
///
///
///
public async Task AddCaseAsync(AddCaseListDto dto, CancellationToken cancellationToken)
{
var pList = _mapper.Map(dto);
var any = await _caseListRepository.Queryable().Where(x => x.Status == ECaseStatus.OnShelf && x.Title == dto.Title).AnyAsync();
if (any)
throw UserFriendlyException.SameMessage("当前案例标题存在重复标题!");
if (dto.Files != null && dto.Files.Count > 0)
pList.FileJson = await _fileRepository.AddFileAsync(dto.Files, pList.Id, "", cancellationToken);
await _caseListRepository.AddAsync(pList, cancellationToken);
if (dto.CaseTypes.Any())
{
List types = _mapper.Map>(dto.CaseTypes);
types.ForEach(x => x.CaseId = pList.Id);
await _caseRelationTypeRepository.AddRangeAsync(types, cancellationToken);
}
return pList.Id;
}
#endregion
#region 案例库 - 修改
///
/// 修改
///
///
///
///
public async Task UpdateCaseAsync(UpdateCaseListDto dto, CancellationToken cancellationToken)
{
var Case = await _caseListRepository.GetAsync(dto.Id);
if (Case == null)
throw UserFriendlyException.SameMessage("案例库查询失败");
if ((Case.Status == ECaseStatus.OnShelf || Case.Status == ECaseStatus.Auditing) && (Case.ExpiredTime.HasValue && Case.ExpiredTime.Value > DateTime.Now))
throw UserFriendlyException.SameMessage("案例库数据不可修改");
var any = await _caseListRepository.Queryable().Where(x => x.Status == ECaseStatus.OnShelf && x.Title == dto.Title && x.Id != dto.Id).AnyAsync();
if (any)
throw UserFriendlyException.SameMessage("当前案例标题存在重复标题!");
if (dto.ApplyStatus == ECaseApplyStatus.Delete)
{
Case.Status = (ECaseStatus)dto.Status;
Case.ApplyStatus = (ECaseApplyStatus)dto.ApplyStatus;
Case.Id = dto.Id;
Case.ApplyReason = dto.ApplyReason;
}
else
{
_mapper.Map(dto, Case);
if (dto.Files != null && dto.Files.Count > 0)
Case.FileJson = await _fileRepository.AddFileAsync(dto.Files, Case.Id, "", cancellationToken);
else
Case.FileJson = new List();
}
await _caseListRepository.UpdateNullAsync(Case, cancellationToken);
if (dto.ApplyStatus != ECaseApplyStatus.Delete)
{
if (dto.CaseTypes.Any())
{
var anyRelationTypes = await _caseRelationTypeRepository.Queryable().Where(x => x.CaseId == Case.Id).ToListAsync();
if (anyRelationTypes.Any())
await _caseRelationTypeRepository.RemoveRangeAsync(anyRelationTypes);
List types = _mapper.Map>(dto.CaseTypes);
types.ForEach(x => x.CaseId = dto.Id);
await _caseRelationTypeRepository.AddRangeAsync(types, cancellationToken);
}
}
}
#endregion
#region 案例库 - 删除
///
/// 删除
///
///
///
///
public async Task RemoveCaseAsync(UpdateCaseListDto dto, CancellationToken cancellationToken)
{
var Case = await _caseListRepository.GetAsync(dto.Id);
if (Case == null)
throw UserFriendlyException.SameMessage("案例库查询失败");
_mapper.Map(dto, Case);
Case.IsDeleted = true;
await _caseListRepository.UpdateNullAsync(Case, cancellationToken);
}
#endregion
#region 案例库 - 审核
///
/// 审核
///
///
///
///
public async Task AuditCaseAsync(UpdateCaseListDto dto, CancellationToken cancellationToken)
{
var Case = await _caseListRepository.GetAsync(dto.Id);
if (Case == null)
throw UserFriendlyException.SameMessage("案例库查询失败");
Case.Status = (ECaseStatus)dto.Status!;
Case.ApplyStatus = (ECaseApplyStatus)dto.ApplyStatus!;
Case.ExaminTime = dto.ExaminTime;
Case.ExaminManId = dto.ExaminManId;
Case.ExaminOrganizeId = dto.ExaminOrganizeId;
Case.ExaminOpinion = dto.ExaminOpinion;
Case.UpdateTime = dto.UpdateTime;
Case.OnShelfTime = dto.OnShelfTime;
Case.OffShelfTime = dto.OffShelfTime;
if (Case.ApplyStatus == ECaseApplyStatus.Delete)
{
Case.IsDeleted = true;
}
await _caseListRepository.UpdateNullAsync(Case, cancellationToken);
}
#endregion
#region 案例库 - 详情
///
/// 详情
///
///
/// 默认不增加,false不增加,true增加浏览量
///
public async Task GetCaseAsync(string Id, bool? IsAddPv, CancellationToken cancellationToken)
{
var Case = await _caseListRepository.GetAsync(Id);
if (Case == null)
throw UserFriendlyException.SameMessage("案例库查询失败");
;
//转化
var CaseInfoDto = _mapper.Map(Case);
if (Case != null)
{
if (!string.IsNullOrEmpty(Case.Describe))
CaseInfoDto.Abstract = _bulletinApplication.GetSiteUrls(Case.Abstract);
if (!string.IsNullOrEmpty(Case.Describe))
CaseInfoDto.Describe = _bulletinApplication.GetSiteUrls(Case.Describe);
if (!string.IsNullOrEmpty(Case.Result))
CaseInfoDto.Result = _bulletinApplication.GetSiteUrls(Case.Result);
if (!string.IsNullOrEmpty(Case.Reason))
CaseInfoDto.Reason = _bulletinApplication.GetSiteUrls(Case.Reason);
}
// 分类
var relationType = await _caseRelationTypeRepository.QueryAsync(x => x.CaseId == Id && x.CreatorId == _sessionContext.UserId);
if (relationType != null)
{
CaseInfoDto.CaseTypes = _mapper.Map>(relationType);
}
// 收藏
var collect = await _caseCollectRepository.GetAsync(x => x.CaseId == Id && x.CreatorId == _sessionContext.UserId);
if (collect != null)
CaseInfoDto.Collect = _mapper.Map(collect);
// 工单
var order = await _orderRepository.GetAsync(x => x.Id == CaseInfoDto.OrderId, cancellationToken);
if (order != null)
CaseInfoDto.OrderTitle = order.Title;
// 知识库
var knowledge = await _knowledgeRepository.GetAsync(x => x.Id == CaseInfoDto.KnowledgeId, cancellationToken);
if (knowledge != null)
CaseInfoDto.KnowledgeTitle = knowledge.Title;
// 附件
if (CaseInfoDto.FileJson != null && CaseInfoDto.FileJson.Any())
{
var ids = CaseInfoDto.FileJson.Select(x => x.Id).ToList();
CaseInfoDto.Files = await _fileRepository.GetFilesAsync(ids, cancellationToken);
}
// 更新浏览量
if (IsAddPv == true)
{
//修改浏览量
Case.PageView++;
//修改点击量
await _caseListRepository.UpdateAsync(Case, cancellationToken);
}
return CaseInfoDto;
}
#endregion
#region 案例库 - 批量导出
///
/// 案例库 - 批量导出
///
///
///
///
public async Task> CaseInfoListExportAsync(CaseInfoExportDto dto, CancellationToken cancellationToken)
{
var streamList = new Dictionary();
var knowList = await _caseListRepository.Queryable()
.Where(m => dto.Ids.Contains(m.Id))
.Select(m => new { m.Title, m.Result })
.ToListAsync(cancellationToken);
var tasks = knowList.Select(async item =>
{
var stream = await Task.Run(() => item.Result.HtmlToStream(dto.FileType), cancellationToken);
return new KeyValuePair(
item.Title + dto.FileType.GetFileExtension(),
stream
);
});
var results = await Task.WhenAll(tasks);
foreach (var kvp in results)
{
if (!streamList.ContainsKey(kvp.Key))
{
streamList.Add(kvp.Key, kvp.Value);
}
}
return streamList;
}
#endregion
#endregion
#region 私有方法
#region 查询所有子级
///
/// 查询所有子级
///
/// 分类数据
/// 需要查询哪级下面的分类
/// 选中的数据ID
///
private List GetChildren(List treeDatas, string ID, string? checkId)
{
List nodeList = new();
//根据ID查询子级
var children = treeDatas.Where(q => q.ParentId == ID);
foreach (var dr in children)
{
//组装数据
TreeListDto node = new()
{
name = dr.Name,
ParentID = dr.ParentId,
value = dr.Id,
IsEnable = dr.IsEnable
};
//是否选中
if (!string.IsNullOrEmpty(checkId) && checkId != Guid.Empty.ToString() && checkId == dr.Id)
node.selected = true;
//子级数据赋值
node.children = GetChildren(treeDatas, node.value, checkId);
//添加数据
nodeList.Add(node);
}
return nodeList;
}
#endregion
#region 获取全称
///
/// 获取全称
///
///
///
private async Task GetFullName(string? Id)
{
//获取全部父级名称
var list = await GetParentNode(Id);
//倒叙
list.Reverse();
//拆分
return string.Join("-", list.ToArray());
}
///
/// 查询父级名称
///
///
///
private async Task> GetParentNode(string? Id)
{
List list = new();
//查询父级数据
var type = await _caseTypeRepository.GetAsync(p => p.Id == Id);
if (type != null)
{
//添加名称
list.Add(type.Name);
list.AddRange(await GetParentNode(type.ParentId));
}
return list;
}
#endregion
#region 修改子级分类全称
///
/// 修改子级分类全称
///
///
///
private async Task UpdateChildNode(string Id)
{
//查询子分类
var list = await GetChildNode(Id);
if (list is not null && list.Count > 0)
{
foreach (var item in list)
{
//获取全称
string FullName = await GetFullName(item.ParentId);
item.SpliceName = string.IsNullOrEmpty(FullName) ? item.Name : FullName + "-" + item.Name;
//修改全称
await _caseTypeRepository.UpdateAsync(item);
}
}
}
///
/// 查询子级节点数据
///
///
///
private async Task> GetChildNode(string Id)
{
List list = new();
//查询数据
var typelist = await _caseTypeRepository.QueryAsync(p => p.ParentId == Id);
if (typelist != null)
{
//处理数据
foreach (var item in typelist)
{
list.Add(item);
list.AddRange(await GetChildNode(item.Id));
}
}
return list;
}
#endregion
#endregion
}
}