using Hotline.Application.FlowEngine; using Hotline.Application.Knowledge; using Hotline.FlowEngine.Definitions; using Hotline.FlowEngine.Workflows; using Hotline.KnowledgeBase; using Hotline.KnowledgeBase.Notifies; using Hotline.Permissions; using Hotline.Repository.SqlSugar.Extensions; using Hotline.Settings; using Hotline.Settings.Hotspots; using Hotline.Share.Dtos; using Hotline.Share.Dtos.FlowEngine; using Hotline.Share.Dtos.Knowledge; using Hotline.Share.Enums.KnowledgeBase; using Hotline.Share.Enums.Order; using Hotline.Users; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Mvc; using SqlSugar; using XF.Domain.Authentications; using XF.Domain.Exceptions; using XF.Utility.EnumExtensions; namespace Hotline.Api.Controllers { /// /// /// public class KnowledgeController : BaseController { #region 注入 private readonly IKnowledgeRepository _knowledgeRepository; private readonly IKnowledgeTempRepository _knowledgeTempRepository; private readonly ISessionContext _sessionContext; private readonly IKnowledgeDomainService _knowledgeDomainService; private readonly IMapper _mapper; private readonly IKnowApplication _knowApplication; private readonly IMediator _mediator; private readonly IWorkflowApplication _workflowApplication; private readonly IKnowledgeWorkFlowRepository _knowledgeWorkFlowRepository; private readonly IWorkflowDomainService _workflowDomainService; private readonly IDefinitionDomainService _definitionDomainService; private readonly IUserRepository _userRepository; private readonly IKnowledgeTypeRepository _knowledgeTypeRepository; private readonly IHotspotTypeRepository _hotspotTypeRepository; /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public KnowledgeController(IKnowledgeRepository knowledgeRepository, IKnowledgeTempRepository knowledgeTempRepository, ISessionContext sessionContext, IKnowledgeDomainService knowledgeDomainService, IMapper mapper, IKnowApplication knowApplication, IMediator mediator, IWorkflowApplication workflowApplication, IKnowledgeWorkFlowRepository knowledgeWorkFlowRepository, IWorkflowDomainService workflowDomainService , IDefinitionDomainService definitionDomainService, IUserRepository userRepository, IKnowledgeTypeRepository knowledgeTypeRepository, IHotspotTypeRepository hotspotTypeRepository) { _knowledgeRepository = knowledgeRepository; _knowledgeTempRepository = knowledgeTempRepository; _sessionContext = sessionContext; _knowledgeDomainService = knowledgeDomainService; _mapper = mapper; _knowApplication = knowApplication; _mediator = mediator; _workflowApplication = workflowApplication; _knowledgeWorkFlowRepository = knowledgeWorkFlowRepository; _workflowDomainService = workflowDomainService; _definitionDomainService = definitionDomainService; _userRepository = userRepository; _knowledgeTypeRepository = knowledgeTypeRepository; _hotspotTypeRepository = hotspotTypeRepository; } #endregion #region 草稿箱 /// /// 草稿箱-新增 /// /// /// [Permission(EPermission.KnowledgeDraftsAdd)] [HttpPost("adddrafts")] public async Task AddKnowledgeDrafts([FromBody] AddKnowledgeDto dto) { var kn = _mapper.Map(dto); if (string.IsNullOrEmpty(dto.Code)) kn.Code = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds).ToString(); return await _knowledgeTempRepository.AddAsync(kn, HttpContext.RequestAborted); } /// /// 草稿箱-修改 /// /// /// [Permission(EPermission.KnowledgeDraftsUpdate)] [HttpPut("updatedrafts")] public async Task UpdateKnowledgeDrafts([FromBody] UpdateKnowledgeDto dto) { var kn = _mapper.Map(dto); await _knowledgeTempRepository.UpdateAsync(kn, HttpContext.RequestAborted); } /// /// 草稿箱-查询详情 /// /// /// [HttpGet("draftsinfo/{Id}")] public async Task KnowledgeDraftsInfo(string Id) { var temp = await _knowledgeTempRepository.GetAsync(Id, HttpContext.RequestAborted); if (temp is null) throw UserFriendlyException.SameMessage("知识草稿查询失败!"); var knowledgeInfoDto = _mapper.Map(temp); //分类 var type = await _knowledgeTypeRepository.GetAsync(temp.KnowledgeTypeId, HttpContext.RequestAborted); if (type != null) knowledgeInfoDto.KnowledgeTypeName = type.SpliceName; //热点 var hot = await _hotspotTypeRepository.GetAsync(temp.HotspotId, HttpContext.RequestAborted); if (hot != null) knowledgeInfoDto.HotspotName = hot.HotSpotFullName; return knowledgeInfoDto; } /// /// 草稿箱删除 /// /// /// [Permission(EPermission.KnowledgeDraftsDelete)] [HttpDelete("removedrafts")] public async Task RemoveKnowledgeDrafts(string Id) { if (string.IsNullOrEmpty(Id)) throw UserFriendlyException.SameMessage("Id不能为空!"); await _knowledgeTempRepository.RemoveAsync(p => p.Id == Id, false, HttpContext.RequestAborted); } /// /// 我的草稿箱 /// /// /// [Permission(EPermission.KnowledgeMyDraftsList)] [HttpGet("mydraftslist")] public async Task> MyDraftsList([FromQuery] MyDraftsListPagedDto pagedDto) { var (total, items) = await _knowledgeTempRepository .Queryable() .Includes(it => it.User) .Includes(it => it.KnowledgeType) .Where(p => p.CreatorId == _sessionContext.RequiredUserId) .WhereIF(!string.IsNullOrEmpty(pagedDto.Keyword), d => d.Title.Contains(pagedDto.Keyword!)) .WhereIF(!string.IsNullOrEmpty(pagedDto.KnowledgeTypeId), d => d.KnowledgeTypeId == pagedDto.KnowledgeTypeId) .WhereIF(pagedDto.StartTime != null, d => d.CreationTime >= pagedDto.StartTime) .WhereIF(pagedDto.EndTime != null, d => d.CreationTime <= pagedDto.EndTime) .OrderByDescending(p => p.CreationTime) .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } #endregion #region 知识管理 /// /// 知识库-知识修改-查询详情 /// /// /// [HttpGet("updateinfo/{Id}")] public async Task KnowledgeUpdateInfo(string Id) { var know = await _knowledgeRepository.GetAsync(Id, HttpContext.RequestAborted); if (know is null) throw UserFriendlyException.SameMessage("知识查询失败!"); var knowledgeInfoDto = _mapper.Map(know); //分类 var type = await _knowledgeTypeRepository.GetAsync(know.KnowledgeTypeId, HttpContext.RequestAborted); if (type != null) knowledgeInfoDto.KnowledgeTypeName = type.SpliceName; //热点 var hot = await _hotspotTypeRepository.GetAsync(know.HotspotId, HttpContext.RequestAborted); if (hot != null) knowledgeInfoDto.HotspotName = hot.HotSpotFullName; return knowledgeInfoDto; } /// /// 知识库-查询详情-增加浏览量 /// /// 知识Id /// 默认不增加,false不增加,true增加浏览量 /// [HttpGet("info/{Id}")] public async Task KnowledgeInfo(string Id, bool? IsAddPv) { var knowledge = await _knowledgeDomainService.KnowledgeInfo(Id, HttpContext.RequestAborted); if (knowledge is null) throw UserFriendlyException.SameMessage("知识查询失败!"); //转化 var knowledgeShowInfoDto = _mapper.Map(knowledge); //查询其他 var user = await _userRepository.GetAsync(knowledge.CreatorId, HttpContext.RequestAborted); if (user != null) knowledgeShowInfoDto.CreatorName = user.Name; var type = await _knowledgeTypeRepository.GetAsync(knowledge.KnowledgeTypeId, HttpContext.RequestAborted); if (type != null) knowledgeShowInfoDto.KnowledgeTypeName = type.SpliceName; var hot = await _hotspotTypeRepository.GetAsync(knowledge.HotspotId, HttpContext.RequestAborted); if (hot != null) knowledgeShowInfoDto.HotspotName = hot.HotSpotFullName; if (IsAddPv == true) _mediator.Publish(new GetKnowledgeInfoNotify(knowledge)); return knowledgeShowInfoDto; } /// /// 知识库-新增 /// /// /// [Permission(EPermission.AddKnowledge)] [HttpPost("add")] public async Task AddKnowledge([FromBody] AddKnowledgeDto dto) { //知识处理逻辑 return await _knowledgeDomainService.KnowledgeAdd(dto, HttpContext.RequestAborted); } ///// ///// 知识库-修改 ///// ///// ///// //[Permission(EPermission.KnowledgeUpdate)] //[HttpPut("update")] //public async Task UpdateKnowledge([FromBody] UpdateKnowledgeDto dto) //{ // //知识更新流程业务 // return await _knowledgeDomainService.KnowledgeUpdate(dto, HttpContext.RequestAborted); //} /// /// 知识库-知识下架 /// /// /// [Permission(EPermission.KnowledgeOffShelf)] [HttpPut("offshelf")] public async Task KnowledgeOffShelf(string Id) { var know = await _knowledgeRepository.GetAsync(Id, HttpContext.RequestAborted); if (know != null && know.Status == EKnowledgeStatus.OnShelf) { know.Status = EKnowledgeStatus.OffShelf; know.OnShelfTime = null; know.OffShelfTime = DateTime.Now; await _knowledgeRepository.UpdateAsync(know, HttpContext.RequestAborted); } else throw UserFriendlyException.SameMessage("知识下架失败"); } /// /// 知识库-知识上架 /// /// /// [Permission(EPermission.KnowledgeOnTheShelf)] [HttpPut("ontheshelf")] public async Task KnowledgeOnTheShelf(string Id) { var know = await _knowledgeRepository.GetAsync(Id, HttpContext.RequestAborted); if (know != null && know.Status == EKnowledgeStatus.OffShelf) { know.Status = EKnowledgeStatus.OnShelf; know.OnShelfTime = DateTime.Now; know.OffShelfTime = null; await _knowledgeRepository.UpdateAsync(know, HttpContext.RequestAborted); } else throw UserFriendlyException.SameMessage("知识上架失败"); } /// /// 撤销 /// /// /// [HttpPut("revoke")] public async Task KnowledgeRevoke(string workFlowId) { await _knowledgeDomainService.KnowledgeRevoke(workFlowId, HttpContext.RequestAborted); } /// /// 根据workFlowId,查询审批明细 /// /// /// [HttpGet("getworkflow")] public async Task GetWorkflow(string workFlowId) { return await _workflowDomainService.GetWorkflowAsync(workFlowId, withSteps: true, withSupplements: true, withAssigns: true, cancellationToken: HttpContext.RequestAborted); } /// /// 知识申请-关联知识-获取知识列表 /// /// [HttpGet("getknowledge")] public async Task> GetKnowledge() { var temp = await _knowledgeRepository .Queryable() .LeftJoin((o, sys) => o.CreatorOrgId == sys.Id) .Where((o, sys) => o.IsDeleted == false) //重新构建数据 .Select((o, sys) => new { index = SqlFunc.RowNumber($"{o.Version} desc ", $"{o.Code}"), DepartmentId = sys.Id, Department = sys.OrgName, o.Id, o.Title, o.Status, o.Code }) //将结果合并成一个表 .MergeTable() //取第一条数据 .Where(d => d.index == 1 && d.Status == EKnowledgeStatus.OnShelf) .ToListAsync(); //返回数据 return _mapper.Map>(temp); } #endregion #region 知识列表 /// /// 知识库列表页面枚举值 /// /// [HttpGet("knowledge-status-data")] public async Task KnowledgeStatus() { return EnumExts.GetDescriptions(); } /// /// 知识查询 /// /// /// [Permission(EPermission.KnowledgeAllList)] [HttpGet()] public async Task> GetKnowList([FromQuery] KnowPagedListDto pagedDto) { return await _knowApplication.GetKnowList(pagedDto); } #endregion #region 知识检索 /// /// 知识检索 /// /// /// [Permission(EPermission.KnowledgeRetrieval)] [HttpGet("knowretrieval")] public async Task> KnowRetrieval([FromQuery] KnowledgeRetrievalPagedListDto pagedDto) { //if (string.IsNullOrEmpty(pagedDto.Keyword)) // throw UserFriendlyException.SameMessage("请输入关键字"); RefAsync total = 0; var Keyword = pagedDto.Keyword?.Trim(); var temp = await _knowledgeRepository .Queryable() .Where(p => p.IsDeleted == false) .Select(o => new { index = SqlFunc.RowNumber($"{o.Version} desc ", $"{o.Code}"), o.Id, o.Code, o.Title, o.Summary, o.Content, o.PageView, o.Additions, o.Status }) //将结果合并成一个表 .MergeTable() //取第一条数据 .Where(d => d.index == 1 && d.Status == EKnowledgeStatus.OnShelf) .WhereIF((pagedDto.RetrievalType == null || pagedDto.RetrievalType == EKnowledgeRetrievalType.All) && !string.IsNullOrEmpty(Keyword), d => d.Title.Contains(Keyword) || d.Content.Contains(Keyword))// || d.Additions.Contains(pagedDto.Keyword) .WhereIF(pagedDto.RetrievalType == EKnowledgeRetrievalType.Title && !string.IsNullOrEmpty(Keyword), d => d.Title.Contains(Keyword)) .WhereIF(pagedDto.RetrievalType == EKnowledgeRetrievalType.Content && !string.IsNullOrEmpty(Keyword), d => d.Content.Contains(Keyword)) // .WhereIF(pagedDto.RetrievalType == EKnowledgeRetrievalType.Enclosure, d => d.Additions.Contains(pagedDto.Keyword)) .OrderByDescending(p => p.PageView) .ToPageListAsync(pagedDto.PageIndex, pagedDto.PageSize, total); return new PagedDto(total, _mapper.Map>(temp)); } #endregion #region 我的知识删除列表 /// /// 我的知识删除列表页面枚举值 /// /// [HttpGet("delete-status-data")] public async Task DeleteApplyStatus() { return EnumExts.GetDescriptions(); } /// /// 我的知识删除列表 /// /// /// [HttpGet("deletelist")] [Permission(EPermission.KnowledgeDeleteApply)] public async Task> GetDeleteApplyList([FromQuery] KnowledgeDeletelPagedListDto pagedDto) { var (total, items) = await _knowledgeWorkFlowRepository .Queryable(includeDeleted: true) .Includes(it => it.Knowledge) .Includes(it => it.User) .Includes(it => it.SystemOrganize) .Includes(it => it.Knowledge, it => it.KnowledgeType) .Includes(it => it.Knowledge, it => it.HotspotType) .Includes(it => it.Workflow) .Where(d => d.CreatorId == _sessionContext.RequiredUserId && d.WorkflowModuleStatus == EKnowledgeApplyType.Delete) .WhereIF(pagedDto.EKnowledgeWorkFlowStatus.HasValue, d => d.WorkFlowApplyStatus == pagedDto.EKnowledgeWorkFlowStatus) .WhereIF(pagedDto.StartApplyTime.HasValue, d => d.CreationTime >= pagedDto.StartApplyTime) .WhereIF(pagedDto.EndApplyTime.HasValue, d => d.CreationTime <= pagedDto.EndApplyTime) .WhereIF(!string.IsNullOrEmpty(pagedDto.Keyword), d => d.Knowledge.User.Name.Contains(pagedDto.Keyword!) || d.Knowledge.SystemOrganize.OrgName.Contains(pagedDto.Keyword!) || d.Knowledge.Title.Contains(pagedDto.Keyword!)) .OrderByDescending(p => p.CreationTime) .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } #endregion #region 审核管理 /// /// 审核管理页面枚举值 /// /// [HttpGet("approval-base-data")] public async Task ApprovalBaseData() { var rsp = new { EKnowledgeWorkFlowStatus = EnumExts.GetDescriptions(), EKnowledgeApplyType = new List> { new KeyValuePair(0, "发布知识"), new KeyValuePair(2, "删除知识") } }; return rsp; } /// /// 审核管理 /// /// /// [Permission(EPermission.KnowledgeApprovedAllList)] [HttpGet("approvedlist")] public async Task> ApprovedList([FromQuery] KnowledgeApprovalPagedListDto pagedDto) { var (total, items) = await _knowledgeWorkFlowRepository .Queryable(includeDeleted: true) .Includes(it => it.Knowledge) .Includes(it => it.User) .Includes(it => it.SystemOrganize) .Includes(it => it.Knowledge, it => it.KnowledgeType) .Includes(it => it.Workflow) .WhereIF(pagedDto.EKnowledgeApplyType.HasValue, d => d.WorkflowModuleStatus == pagedDto.EKnowledgeApplyType) .WhereIF(pagedDto.EKnowledgeWorkFlowStatus.HasValue, d => d.WorkFlowApplyStatus == pagedDto.EKnowledgeWorkFlowStatus) .WhereIF(!string.IsNullOrEmpty(pagedDto.Keyword), d => d.Knowledge.User.Name.Contains(pagedDto.Keyword!) || d.Knowledge.SystemOrganize.OrgName.Contains(pagedDto.Keyword!) || d.Knowledge.Title.Contains(pagedDto.Keyword!)) .OrderByDescending(p => p.CreationTime) .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize, HttpContext.RequestAborted); //处理是否可以办理 items.ForEach(d => d.CanHandle = d.Workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgCode)); return new PagedDto(total, _mapper.Map>(items)); } #endregion #region 工单受理,知识库检索 /// /// 获取知识热点词 /// /// [HttpGet("getkeyword")] public async Task> GetKeyWord() { return await _knowledgeDomainService.GetKeyWord(); } /// /// 工单受理知识检索 /// /// /// [HttpGet("knowpopscreen")] public async Task> KnowPopScreen([FromQuery] KnowledgePopScreenPagedListDto pagedDto) { //if (string.IsNullOrEmpty(pagedDto.Keyword)&& string.IsNullOrEmpty(pagedDto.HotspotId)) // throw UserFriendlyException.SameMessage("请选择热点或输入关键字"); RefAsync total = 0; var temp = await _knowledgeRepository .Queryable() .Where(p => p.IsDeleted == false) .Select(o => new { index = SqlFunc.RowNumber($"{o.Version} desc ", $"{o.Code}"), o.Id, o.Code, o.Title, o.Summary, o.Content, o.PageView, o.Keywords, o.HotspotId, o.Status }) //将结果合并成一个表 .MergeTable() //取第一条数据 .Where(d => d.index == 1 && d.Status == EKnowledgeStatus.OnShelf) .WhereIF(!string.IsNullOrEmpty(pagedDto.Keyword), p => p.Title.Contains(pagedDto.Keyword) || p.Keywords.Contains(pagedDto.Keyword)) .WhereIF(!string.IsNullOrEmpty(pagedDto.HotspotId), p => p.HotspotId == pagedDto.HotspotId) .OrderByDescending(p => p.PageView) .ToPageListAsync(pagedDto.PageIndex, pagedDto.PageSize, total); return new PagedDto(total, _mapper.Map>(temp)); } #endregion #region 流程相关 /// /// 新增-开始流程 /// /// 知识id /// 流程开启参数 /// [HttpPost("{id}/add-startflow")] public async Task AddStartFlow(string id, [FromBody] StartWorkflowDto dto) { await StartFlow(id, WorkflowModuleConsts.KnowledgeAdd, EKnowledgeApplyType.Add, dto); } ///// ///// 修改-开始流程 ///// ///// 知识id ///// 流程开启参数 ///// //[HttpPost("{id}/update-startflow")] //public async Task UpdateStartFlow(string id, [FromBody] StartWorkflowDto dto) //{ // await StartFlow(id, WorkflowModuleConsts.KnowledgeUpdate, EKnowledgeApplyType.Update, dto); //} /// /// 删除-开始流程 /// /// 知识id /// 流程开启参数 /// [HttpPost("{id}/remove-startflow")] public async Task RemoveStartFlow(string id, [FromBody] StartWorkflowDto dto) { await StartFlow(id, WorkflowModuleConsts.KnowledgeDelete, EKnowledgeApplyType.Delete, dto); } /// /// 查询知识库办理流程开启参数-新增 /// /// [HttpGet("add-flow-start")] public async Task> GetAddFlowStartOptionsAsync() { return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.KnowledgeAdd, HttpContext.RequestAborted); } ///// ///// 查询知识库办理流程开启参数-修改 ///// ///// //[HttpGet("update-flow-start")] //public async Task> GetUpdateFlowStartOptionsAsync() //{ // return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.KnowledgeUpdate, HttpContext.RequestAborted); //} /// /// 查询知识库办理流程开启参数-删除 /// /// [HttpGet("remove-flow-start")] public async Task> GetRemoveFlowStartOptionsAsync() { return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.KnowledgeDelete, HttpContext.RequestAborted); } #endregion #region 私有方法-开始流程 /// /// 开始流程 /// /// 知识ID /// 知识模板编号 /// 申请类型 /// 流程开启参数 /// private async Task StartFlow(string id, string moduleCode, EKnowledgeApplyType eKnowledgeApplyType, StartWorkflowDto dto) { var knowledge = await _knowledgeRepository.GetAsync(id, HttpContext.RequestAborted); if (knowledge == null) throw UserFriendlyException.SameMessage("无效知识编号"); if (eKnowledgeApplyType == EKnowledgeApplyType.Delete) { if (knowledge.IsDeleted == true) throw UserFriendlyException.SameMessage("知识删除失败"); //验证是否已经发起过知识删除流程 var exists = await _knowledgeWorkFlowRepository.GetAsync(p => p.KnowledgeId == knowledge.Id && p.WorkflowModuleStatus == EKnowledgeApplyType.Delete && (p.WorkFlowApplyStatus == EKnowledgeWorkFlowStatus.Success || p.WorkFlowApplyStatus == EKnowledgeWorkFlowStatus.Auditing)); if (exists != null) throw UserFriendlyException.SameMessage($"该知识已发起过{WorkflowModule.Modules[WorkflowModuleConsts.KnowledgeDelete]}流程"); } if (!string.IsNullOrEmpty(knowledge.WorkflowId) && eKnowledgeApplyType != EKnowledgeApplyType.Delete) throw UserFriendlyException.SameMessage("知识已发起流程"); var definition = await _definitionDomainService.GetLastEnableByModuleCodeAsync( moduleCode, HttpContext.RequestAborted); if (definition is null) throw UserFriendlyException.SameMessage("未配置流程模板"); //知识审批主表 var flowId = await _knowledgeDomainService.AddWorkFlowAsync(id, eKnowledgeApplyType, HttpContext.RequestAborted); dto.DefinitionCode = definition.Code; dto.Title = knowledge.Title; await _workflowApplication.StartWorkflowAsync(dto, flowId, HttpContext.RequestAborted); //if (eKnowledgeApplyType != EKnowledgeApplyType.Delete) // //修改流程ID // await _knowledgeDomainService.UpdateWorkFlowId(id, workflowId, HttpContext.RequestAborted); } #endregion } }