using Hotline.Planlibrary;
using Hotline.Settings.Hotspots;
using Hotline.Share.Dtos.Knowledge;
using Hotline.Share.Dtos.Planlibrary;
using Hotline.Share.Enums.Planlibrary;
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.KnowledgeBase;
using Hotline.Repository.SqlSugar.Knowledge;
using Hotline.Share.Enums.KnowledgeBase;
using Microsoft.AspNetCore.Http;
namespace Hotline.Application.Planlibrary
{
///
/// 预案库处理
///
public class PlanApplication : IPlanApplication, IScopeDependency
{
#region 注册
private readonly IRepository _planListRepository; //预案库列表
private readonly IRepository _planRelationTypeRepository; //预案库关联类型
private readonly IRepository _planTypeRepository; //预案库分类管理
private readonly IRepository _planTypeOrgRepository; //预案库分类关联机构
private readonly IRepository _planCollectRepository; //预案库收藏评分
private readonly ISessionContext _sessionContext;
private readonly IMapper _mapper;
private readonly IRepository _hotspotTypeRepository;
private readonly IFileRepository _fileRepository;
private readonly IBulletinApplication _bulletinApplication;
public PlanApplication(
IRepository planListRepository,
IRepository planRelationTypeRepository,
IRepository planTypeRepository,
IRepository planTypeOrgRepository,
ISessionContext sessionContext,
IMapper mapper,
IRepository hotspotTypeRepository,
IFileRepository fileRepository,
IBulletinApplication bulletinApplication,
IRepository planCollectRepository)
{
_planListRepository = planListRepository;
_planRelationTypeRepository = planRelationTypeRepository;
_planTypeRepository = planTypeRepository;
_planTypeOrgRepository = planTypeOrgRepository;
_sessionContext = sessionContext;
_mapper = mapper;
_hotspotTypeRepository = hotspotTypeRepository;
_fileRepository = fileRepository;
_bulletinApplication = bulletinApplication;
_planCollectRepository = planCollectRepository;
}
#endregion
#region 预案库类型管理
#region 预案库类型 - 新增
///
/// 预案库类型 - 新增
///
///
///
///
public async Task AddTypeAsync(AddPlanTypeDto dto, CancellationToken cancellationToken)
{
var sandard = await _planTypeRepository.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 _planTypeRepository.AddAsync(type, cancellationToken);
if (dto.TypeOrgDtos != null && dto.TypeOrgDtos.Any())
{
List orgs = _mapper.Map>(dto.TypeOrgDtos);
orgs.ForEach(x => x.TypeId = type.Id);
await _planTypeOrgRepository.AddRangeAsync(orgs, cancellationToken);
}
return id;
}
#endregion
#region 预案库类型 - 编辑
///
/// 预案库类型 - 编辑
///
///
///
///
public async Task UpdateTypeAsync(UpdatePlanTypeDto dto, CancellationToken cancellationToken)
{
//查询原有数据
var type = await _planTypeRepository.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 _planTypeRepository.UpdateAsync(type, cancellationToken);
//如果修改了名称,对应修改子分类全称
if (result)
await UpdateChildNode(type.Id);
// 修改关联机构
await _planTypeOrgRepository.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 _planTypeOrgRepository.AddRangeAsync(orgs, cancellationToken);
}
}
#endregion
#region 预案库类型 - 删除
///
/// 预案库类型 - 删除
///
///
///
///
public async Task RemoveTypeAsync(string Id, CancellationToken cancellationToken)
{
//查询数据是否存在
var sandard = await _planTypeRepository.GetAsync(p => p.Id == Id && p.IsDeleted == false, cancellationToken);
if (sandard is null)
throw UserFriendlyException.SameMessage("分类不存在!");
//查询是否有子级分类
var checkChild = await _planTypeRepository.CountAsync(p => p.ParentId == Id && p.IsDeleted == false, cancellationToken);
if (checkChild > 0)
throw UserFriendlyException.SameMessage("存在子级分类!");
//查询是否有预案分类
var checkKnowledge = await _planListRepository.CountAsync(p => p.PlanTypes.Any(t => t.PlanId == Id), cancellationToken);
if (checkKnowledge > 0)
throw UserFriendlyException.SameMessage("分类存在预案!");
//删除操作
await _planTypeRepository.RemoveAsync(sandard, true, cancellationToken);
}
#endregion
#endregion
#region 预案库管理
#region 预案库 - 列表
///
/// 预案库 - 列表
///
///
///
public async Task<(int, IList)> QueryAllPlanListAsync(PlanListDto pagedDto, CancellationToken cancellationToken)
{
//if (!_sessionContext.OrgIsCenter)
//{// 部门只能查询【部门预案库】
// pagedDto.Attribution = "部门预案库";
//}
var typeSpliceName = string.Empty;
var hotspotHotSpotFullName = string.Empty;
if (!string.IsNullOrEmpty(pagedDto.PlanTypeID))
{
var type = await _planTypeRepository.GetAsync(x => x.Id == pagedDto.PlanTypeID);
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 _planListRepository.Queryable()
.Includes(x => x.PlanTypes)
.Includes(x => x.HotspotType)
.Includes(x => x.ExaminMan)
.Where(x => x.IsDeleted == false)
.Where(x => (x.Status == EPlanStatus.Drafts && x.CreatorId == _sessionContext.UserId) || (x.Status != EPlanStatus.Drafts))
.WhereIF(OrgSeedData.CenterId != pagedDto.CreateOrgId && !string.IsNullOrEmpty(pagedDto.CreateOrgId), x => x.CreatorOrgId != null && x.CreatorOrgId.StartsWith(pagedDto.CreateOrgId!))
.WhereIF(!string.IsNullOrEmpty(pagedDto.Attribution), x => x.Attribution == pagedDto.Attribution)
.WhereIF(!string.IsNullOrEmpty(pagedDto.Title), x => x.Title.Contains(pagedDto.Title))
.WhereIF(!string.IsNullOrEmpty(pagedDto.Content), x => x.Content.Contains(pagedDto.Content))
.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 != EPlanStatus.OffShelf &&
pagedDto.Status != EPlanStatus.NewDrafts &&
pagedDto.Status != EPlanStatus.All,
x => x.Status == pagedDto.Status && ((x.ExpiredTime != null && x.ExpiredTime > DateTime.Now) || x.ExpiredTime == null))
.WhereIF(pagedDto.Status.HasValue && pagedDto.Status == EPlanStatus.OffShelf, x => x.Status == pagedDto.Status || (x.ExpiredTime != null && x.ExpiredTime < DateTime.Now && x.Status != EPlanStatus.Drafts))
.WhereIF(pagedDto.Status.HasValue && pagedDto.Status == EPlanStatus.NewDrafts, x => x.Status == EPlanStatus.Drafts || x.Status == EPlanStatus.Revert || x.Status == EPlanStatus.NewDrafts)
.WhereIF(pagedDto.IsPublic.HasValue, x => x.IsPublic == pagedDto.IsPublic)
.WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => x.PlanTypes.Any(t => t.PlanTypeSpliceName.StartsWith(typeSpliceName)))
.WhereIF(!string.IsNullOrEmpty(hotspotHotSpotFullName), x => x.HotspotType.HotSpotFullName.EndsWith(hotspotHotSpotFullName!))
.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 AddPlanAsync(AddPlanListDto dto, CancellationToken cancellationToken)
{
var pList = _mapper.Map(dto);
var any = await _planListRepository.Queryable().Where(x => x.Status == EPlanStatus.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 _planListRepository.AddAsync(pList, cancellationToken);
if (dto.PlanTypes.Any())
{
List types = _mapper.Map>(dto.PlanTypes);
types.ForEach(x => x.PlanId = pList.Id);
await _planRelationTypeRepository.AddRangeAsync(types, cancellationToken);
}
return pList.Id;
}
#endregion
#region 预案库 - 修改
///
/// 修改
///
///
///
///
public async Task UpdatePlanAsync(UpdatePlanListDto dto, CancellationToken cancellationToken)
{
var plan = await _planListRepository.GetAsync(dto.Id);
if (plan == null)
throw UserFriendlyException.SameMessage("预案库查询失败");
if ((plan.Status == EPlanStatus.OnShelf || plan.Status == EPlanStatus.Auditing) && (plan.ExpiredTime.HasValue && plan.ExpiredTime.Value > DateTime.Now))
throw UserFriendlyException.SameMessage("预案库数据不可修改");
var any = await _planListRepository.Queryable().Where(x => x.Status == EPlanStatus.OnShelf && x.Title == dto.Title && x.Id != dto.Id).AnyAsync();
if (any)
throw UserFriendlyException.SameMessage("当前预案标题存在重复标题!");
if (dto.ApplyStatus == EPlanApplyStatus.Delete)
{
plan.Status = (EPlanStatus)dto.Status;
plan.ApplyStatus = (EPlanApplyStatus)dto.ApplyStatus;
plan.Id = dto.Id;
plan.ApplyReason = dto.ApplyReason;
}
else
{
_mapper.Map(dto, plan);
plan.HotspotId = dto.HotspotId;
if (dto.Files != null && dto.Files.Count > 0)
plan.FileJson = await _fileRepository.AddFileAsync(dto.Files, plan.Id, "", cancellationToken);
else
plan.FileJson = new List();
}
await _planListRepository.UpdateNullAsync(plan, cancellationToken);
if (dto.ApplyStatus != EPlanApplyStatus.Delete)
{
if (dto.PlanTypes.Any())
{
var anyRelationTypes = await _planRelationTypeRepository.Queryable().Where(x => x.PlanId == plan.Id).ToListAsync();
if (anyRelationTypes.Any())
await _planRelationTypeRepository.RemoveRangeAsync(anyRelationTypes);
List types = _mapper.Map>(dto.PlanTypes);
types.ForEach(x => x.PlanId = dto.Id);
await _planRelationTypeRepository.AddRangeAsync(types, cancellationToken);
}
}
}
#endregion
#region 预案库 - 删除
///
/// 删除
///
///
///
///
public async Task RemovePlanAsync(UpdatePlanListDto dto, CancellationToken cancellationToken)
{
var plan = await _planListRepository.GetAsync(dto.Id);
if (plan == null)
throw UserFriendlyException.SameMessage("预案库查询失败");
_mapper.Map(dto, plan);
plan.IsDeleted = true;
await _planListRepository.UpdateNullAsync(plan, cancellationToken);
}
#endregion
#region 预案库 - 审核
///
/// 审核
///
///
///
///
public async Task AuditPlanAsync(UpdatePlanListDto dto, CancellationToken cancellationToken)
{
var plan = await _planListRepository.GetAsync(dto.Id);
if (plan == null)
throw UserFriendlyException.SameMessage("预案库查询失败");
plan.Status = (EPlanStatus)dto.Status!;
plan.ApplyStatus = (EPlanApplyStatus)dto.ApplyStatus!;
plan.ExaminTime = dto.ExaminTime;
plan.ExaminManId = dto.ExaminManId;
plan.ExaminOrganizeId = dto.ExaminOrganizeId;
plan.ExaminOpinion = dto.ExaminOpinion;
plan.UpdateTime = dto.UpdateTime;
plan.OnShelfTime = dto.OnShelfTime;
plan.OffShelfTime = dto.OffShelfTime;
if (plan.ApplyStatus == EPlanApplyStatus.Delete)
{
plan.IsDeleted = true;
}
await _planListRepository.UpdateNullAsync(plan, cancellationToken);
}
#endregion
#region 预案库 - 详情
///
/// 详情
///
///
/// 默认不增加,false不增加,true增加浏览量
///
public async Task GetPlanAsync(string Id, bool? IsAddPv, CancellationToken cancellationToken)
{
var plan = await _planListRepository.GetAsync(Id);
if (plan == null)
throw UserFriendlyException.SameMessage("预案库查询失败");
;
// 转化
var planInfoDto = _mapper.Map(plan);
// 内容
if (plan != null && !string.IsNullOrEmpty(plan.Content))
planInfoDto.Content = _bulletinApplication.GetSiteUrls(plan.Content);
// 热点
var hot = await _hotspotTypeRepository.GetAsync(plan.HotspotId, cancellationToken);
if (hot != null)
planInfoDto.HotspotName = hot.HotSpotFullName;
// 分类
var relationType = await _planRelationTypeRepository.QueryAsync(x => x.PlanId == Id && x.CreatorId == _sessionContext.UserId);
if (relationType != null)
{
planInfoDto.PlanTypes = _mapper.Map>(relationType);
}
// 收藏
var collect = await _planCollectRepository.GetAsync(x => x.PlanId == Id && x.CreatorId == _sessionContext.UserId);
if (collect != null)
planInfoDto.Collect = _mapper.Map(collect);
// 附件
if (planInfoDto.FileJson != null && planInfoDto.FileJson.Any())
{
var ids = planInfoDto.FileJson.Select(x => x.Id).ToList();
planInfoDto.Files = await _fileRepository.GetFilesAsync(ids, cancellationToken);
}
// 更新浏览量
if (IsAddPv == true)
{
//修改浏览量
plan.PageView++;
//修改点击量
await _planListRepository.UpdateAsync(plan, cancellationToken);
}
return planInfoDto;
}
#endregion
#region 预案库 - 批量导出
///
/// 预案库 - 批量导出
///
///
///
///
public async Task> PlanInfoListExportAsync(PlanInfoExportDto dto, CancellationToken cancellationToken)
{
var streamList = new Dictionary();
var knowList = await _planListRepository.Queryable()
.Where(m => dto.Ids.Contains(m.Id))
.Select(m => new { m.Title, m.Content })
.ToListAsync(cancellationToken);
var tasks = knowList.Select(async item =>
{
var stream = await Task.Run(() => item.Content.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 _planTypeRepository.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 _planTypeRepository.UpdateAsync(item);
}
}
}
///
/// 查询子级节点数据
///
///
///
private async Task> GetChildNode(string Id)
{
List list = new();
//查询数据
var typelist = await _planTypeRepository.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
}
}