using DotNetCore.CAP;
using Hotline.Api.Filter;
using Hotline.Application.FlowEngine;
using Hotline.Application.Knowledge;
using Hotline.File;
using Hotline.FlowEngine.WorkflowModules;
using Hotline.KnowledgeBase;
using Hotline.KnowledgeBase.Notifies;
using Hotline.Permissions;
using Hotline.Repository.SqlSugar.Extensions;
using Hotline.Repository.SqlSugar.Ts;
using Hotline.Settings;
using Hotline.Settings.Hotspots;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.File;
using Hotline.Share.Dtos.FlowEngine;
using Hotline.Share.Dtos.Knowledge;
using Hotline.Share.Enums.KnowledgeBase;
using Hotline.Share.Mq;
using Hotline.Users;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System.Threading;
using XF.Domain.Authentications;
using XF.Domain.Exceptions;
using XF.Domain.Repository;
using XF.Utility.EnumExtensions;

namespace Hotline.Api.Controllers
{
    public class KnowledgeController : BaseController
    {

        #region 注入
        private readonly IKnowledgeRepository _knowledgeRepository;
        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 IRepository<User> _userRepository;
        private readonly IRepository<KnowledgeType> _knowledgeTypeRepository;
        private readonly IRepository<Hotspot> _hotspotTypeRepository;
        private readonly IRepositoryTextSearch<KnowledgeTs> _repositoryts;
        private readonly IRepository<KnowledgeWord> _knowledgeWrodRepository;
        private readonly IRepository<KnowledgeQuestions> _knowledgeQuestionsRepository;
        private readonly IRepository<KnowledgeCorrection> _knowledgeCorrectionRepository;
        private readonly IRepository<KnowledgeCollect> _knowledgeCollectRepository;
        private readonly ISystemDomainService _systemDomainService;
        private readonly IRepository<KnowledgeComment> _knowledgeCommentRepository;
        private readonly ISystemOrganizeRepository _systemOrganizeRepository;
        private readonly IFileRepository _fileRepository;
        private readonly ICapPublisher _capPublisher;
        private readonly IRepository<KnowledgeRelationType> _knowledgeRelationTypeRepository;


		public KnowledgeController(
           IKnowledgeRepository knowledgeRepository,
           ISessionContext sessionContext,
           IKnowledgeDomainService knowledgeDomainService,
           IMapper mapper,
           IKnowApplication knowApplication,
           IMediator mediator,
           IWorkflowApplication workflowApplication,
           IKnowledgeWorkFlowRepository knowledgeWorkFlowRepository,
           IRepository<User> userRepository,
           IRepository<KnowledgeType> knowledgeTypeRepository,
           IRepository<Hotspot> hotspotTypeRepository,
           IRepositoryTextSearch<KnowledgeTs> repositoryts,
           IRepository<KnowledgeWord> knowledgeWrodRepository,
           IRepository<KnowledgeQuestions> knowledgeQuestionsRepository,
           IRepository<KnowledgeCorrection> knowledgeCorrectionRepository,
           IRepository<KnowledgeCollect> knowledgeCollectRepository,
           ISystemDomainService systemDomainService,
           IRepository<KnowledgeComment> knowledgeCommentRepository,
           ISystemOrganizeRepository systemOrganizeRepository,
           IFileRepository fileRepository,
           ICapPublisher capPublisher,
           IRepository<KnowledgeRelationType> knowledgeRelationTypeRepository
		   )
        {
            _knowledgeRepository = knowledgeRepository;
            _sessionContext = sessionContext;
            _knowledgeDomainService = knowledgeDomainService;
            _mapper = mapper;
            _knowApplication = knowApplication;
            _mediator = mediator;
            _workflowApplication = workflowApplication;
            _knowledgeWorkFlowRepository = knowledgeWorkFlowRepository;
            _userRepository = userRepository;
            _knowledgeTypeRepository = knowledgeTypeRepository;
            _hotspotTypeRepository = hotspotTypeRepository;
            _repositoryts = repositoryts;
            _knowledgeWrodRepository = knowledgeWrodRepository;
            _knowledgeQuestionsRepository = knowledgeQuestionsRepository;
            _knowledgeCorrectionRepository = knowledgeCorrectionRepository;
            _knowledgeCollectRepository = knowledgeCollectRepository;
            _systemDomainService = systemDomainService;
            _knowledgeCommentRepository = knowledgeCommentRepository;
            _systemOrganizeRepository = systemOrganizeRepository;
            _fileRepository = fileRepository;
            _capPublisher = capPublisher;
            _knowledgeRelationTypeRepository = knowledgeRelationTypeRepository;

		}

        #endregion

        #region 知识管理

        /// <summary>
        /// 知识库-新增
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [Permission(EPermission.AddKnowledge)]
        [HttpPost("add")]
        [LogFilter("知识新增")]
        public async Task<string> AddKnowledge([FromBody] AddStartFlowDto dto)
        {
            //var addDto = _mapper.Map<AddKnowledgeDto>(dto.Data);
            var kn = _mapper.Map<Knowledge>(dto.Data);
            kn.SourceOrganizeId = _sessionContext.RequiredOrgId;
			var any = await _knowledgeRepository.Queryable().Where(x => x.Status == EKnowledgeStatus.OnShelf && x.Title == kn.Title).AnyAsync();
            if (any) throw UserFriendlyException.SameMessage("当前知识标题存在重复标题！");

            //Code为空，从新生成Code
            if (string.IsNullOrEmpty(kn.Code))
                kn.Code = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds).ToString();

            kn.Status = EKnowledgeStatus.Drafts;
            kn.InitId();
            if (dto.Data.Files.Any()) kn.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, kn.Id, "", HttpContext.RequestAborted);
            await _knowledgeRepository.AddAsync(kn, HttpContext.RequestAborted);
            if (dto.Workflow != null && !string.IsNullOrEmpty(kn.Id))
            {
                var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
                startDto.DefinitionModuleCode = WorkflowModuleConsts.KnowledgeAdd;
                startDto.Title = "知识库新增";
                await StartFlow(kn.Id, WorkflowModuleConsts.KnowledgeAdd, EKnowledgeApplyType.Add, startDto);
                var knowledge = await _knowledgeRepository.GetAsync(kn.Id);
                knowledge.Status = EKnowledgeStatus.Auditing;
                await _knowledgeRepository.UpdateAsync(knowledge, HttpContext.RequestAborted);
            }
            if (dto.Data.KnowledgeType.Any())
            {
                List<KnowledgeRelationType> types = _mapper.Map<List<KnowledgeRelationType>>(dto.Data.KnowledgeType);
                types.ForEach(x => x.KnowledgeId = kn.Id);
				await _knowledgeRelationTypeRepository.AddRangeAsync(types, HttpContext.RequestAborted);
			}
            return kn.Id;
        }


        /// <summary>
        /// 知识库-知识下架
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [Permission(EPermission.KnowledgeOffShelf)]
        [HttpPut("offshelf")]
        [LogFilter("知识下架")]
        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);

                var pushKnowledge = _mapper.Map<KnowledgeSendDto>(know);
                pushKnowledge.CategoryCode = "01";
                pushKnowledge.CategoryName = "公共服务";
                //推省上
                await _capPublisher.PublishAsync(EventNames.HotlineKnowledgeRemove, pushKnowledge, cancellationToken: HttpContext.RequestAborted);
            }
            else
                throw UserFriendlyException.SameMessage("知识下架失败");
        }

        /// <summary>
        /// 知识库-知识上架
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [Permission(EPermission.KnowledgeOnTheShelf)]
        [HttpPut("ontheshelf")]
        [LogFilter("知识上架")]
        public async Task KnowledgeOnTheShelf(string Id)
        {
            var know = await _knowledgeRepository.GetAsync(Id, HttpContext.RequestAborted);
            if (know != null && know.Status == EKnowledgeStatus.OffShelf)
            {
                var any = await _knowledgeRepository.Queryable().Where(x => x.Status == EKnowledgeStatus.OnShelf && x.Title == know.Title && x.Id != know.Id).AnyAsync();
                if (any) throw UserFriendlyException.SameMessage("当前知识标题存在重复标题！");
                if (know.ExpiredTime < DateTime.Now) throw UserFriendlyException.SameMessage("知识已过期不能上架！");

                know.Status = EKnowledgeStatus.OnShelf;
                know.OnShelfTime = DateTime.Now;
                know.OffShelfTime = null;
                await _knowledgeRepository.UpdateAsync(know, HttpContext.RequestAborted);
            }
            else
                throw UserFriendlyException.SameMessage("知识上架失败");
        }

        /// <summary>
        /// 知识库-标题
        /// </summary>
        /// <param name="title"></param>
        /// <returns></returns>
        [HttpGet("title")]
        public async Task<bool> KnowledgeTitle([FromQuery] KnowledgeTitleDto dto)
        {
            var count = await _knowledgeRepository.Queryable()
                .WhereIF(!string.IsNullOrEmpty(dto.Id), x => x.Id != dto.Id)
                .Where(x => x.Title == dto.Title && x.Status == EKnowledgeStatus.OnShelf).CountAsync();
            return count > 0;
        }

        /// <summary>
        /// 知识库-修改
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("update")]
        [LogFilter("知识修改")]
        public async Task UpdateKnowledge([FromBody] UpdateStartFlowDto dto)
        {
            var update = _mapper.Map<UpdateKnowledgeDto>(dto.Data);
            var knowledge = await _knowledgeRepository.GetAsync(update.Id);
            if (knowledge == null)
                throw UserFriendlyException.SameMessage("知识库数据错误");
            if ((knowledge.Status == EKnowledgeStatus.OnShelf || knowledge.Status == EKnowledgeStatus.Auditing) && (knowledge.ExpiredTime.HasValue && knowledge.ExpiredTime.Value > DateTime.Now))
                throw UserFriendlyException.SameMessage("知识库数据不可修改");

            var any = await _knowledgeRepository.Queryable().Where(x => x.Status == EKnowledgeStatus.OnShelf && x.Title == update.Title && x.Id != update.Id).AnyAsync();
            if (any) throw UserFriendlyException.SameMessage("当前知识标题存在重复标题！");
            _mapper.Map(dto.Data, knowledge);
            //if (update.Tags.Any()) await _repositoryts.UpdateVectorAsync(update.Id, update.Tags, HttpContext.RequestAborted);

            if (dto.Data.Files.Any()) knowledge.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, knowledge.Id, "", HttpContext.RequestAborted);
            if (dto.Workflow != null) knowledge.Renewaln = update.Status != EKnowledgeStatus.Drafts;
            await _knowledgeRepository.UpdateAsync(knowledge, HttpContext.RequestAborted);
            if (dto.Workflow != null)
            {
                if (update.Status == EKnowledgeStatus.Drafts)
                {
                    var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
                    startDto.DefinitionModuleCode = WorkflowModuleConsts.KnowledgeAdd;
                    startDto.Title = "知识库新增";
                    await StartFlow(update.Id, WorkflowModuleConsts.KnowledgeAdd, EKnowledgeApplyType.Add, startDto);
                }
                else
                {
                    var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
                    startDto.DefinitionModuleCode = WorkflowModuleConsts.KnowledgeUpdate;
                    startDto.Title = "知识库修改";
                    await StartFlow(update.Id, WorkflowModuleConsts.KnowledgeUpdate, EKnowledgeApplyType.Update, startDto);
                }
            }
            if (dto.Data.KnowledgeType.Any())
            {
                await _knowledgeRelationTypeRepository.RemoveAsync(t => t.KnowledgeId == update.Id);
				List<KnowledgeRelationType> types = _mapper.Map<List<KnowledgeRelationType>>(dto.Data.KnowledgeType);
                types.ForEach(x => x.KnowledgeId = update.Id);
				await _knowledgeRelationTypeRepository.AddRangeAsync(types, HttpContext.RequestAborted);
            }
		}

        /// <summary>
        /// 删除知识
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete]
        [LogFilter("删除知识")]
        public async Task Remove([FromBody] DeleteStartFlowDto dto)
        {
            var delete = _mapper.Map<KnowledgeDto>(dto.Data);
            var knowledge = await _knowledgeRepository.GetAsync(delete.Id, HttpContext.RequestAborted);
            if (knowledge == null)
                throw UserFriendlyException.SameMessage("无效知识库数据");
            if (knowledge.Status == EKnowledgeStatus.OnShelf || knowledge.Status == EKnowledgeStatus.Auditing)
                throw UserFriendlyException.SameMessage("知识库数据不可删除");
            if (knowledge.Status == EKnowledgeStatus.Drafts)
            {
                await _knowledgeRepository.RemoveAsync(knowledge, false, HttpContext.RequestAborted);
            }
            else
            {
                var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
                startDto.DefinitionModuleCode = WorkflowModuleConsts.KnowledgeDelete;
                startDto.Title = "知识库删除";
                await StartFlow(delete.Id, WorkflowModuleConsts.KnowledgeDelete, EKnowledgeApplyType.Delete, startDto);
            }
        }

        /// <summary>
        /// 增加搜索量
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("search_num")]
        [LogFilter("知识搜索")]
        public async Task SearchNum([FromBody] KnowledgeSearchNumDto dto)
        {

            var knowledge = await _knowledgeRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (knowledge == null)
                throw UserFriendlyException.SameMessage("无效知识库数据");
            knowledge.SearchNum++;
            await _knowledgeRepository.UpdateAsync(knowledge, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 搜索量列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("search_num/list")]
        public async Task<PagedDto<KnowledgeDto>> SearchNumList([FromQuery] KnowledgeCollectListDto dto)
        {
            var (total, items) = await _knowledgeRepository.Queryable(false, false, false)
                .Where(x => x.Status == EKnowledgeStatus.OnShelf)
                .Where(x => (x.ExpiredTime != null && x.ExpiredTime >= DateTime.Now) || x.ExpiredTime == null)
                .OrderByDescending(x => x.SearchNum)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<KnowledgeDto>(total, _mapper.Map<IReadOnlyList<KnowledgeDto>>(items));
        }

        /// <summary>
        /// 知识库-知识修改-查询详情
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [HttpGet("updateinfo/{Id}")]
        public async Task<KnowledgeInfoDto> KnowledgeUpdateInfo(string Id)
        {
            //var know = await _knowledgeRepository.GetAsync(Id, HttpContext.RequestAborted);
            var know = await _knowledgeDomainService.KnowledgeInfo(Id, HttpContext.RequestAborted);
			if (know is null)
                throw UserFriendlyException.SameMessage("知识查询失败！");

            var knowledgeInfoDto = _mapper.Map<KnowledgeInfoDto>(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;
            //收藏
            var collect = await _knowledgeCollectRepository.GetAsync(x => x.KnowledgeId == Id && x.CreatorId == _sessionContext.UserId);
            if (collect != null)
                knowledgeInfoDto.Collect = _mapper.Map<KnowledgeCollectDto>(collect);

            return knowledgeInfoDto;
        }

        /// <summary>
        /// 知识库-查询详情-增加浏览量
        /// </summary>
        /// <param name="Id">知识Id</param>
        /// <param name="IsAddPv">默认不增加，false不增加，true增加浏览量</param>
        /// <returns></returns>
        [HttpGet("info/{Id}")]
        public async Task<KnowledgeInfoDto> KnowledgeInfo(string Id, bool? IsAddPv)
        {
            var knowledge = await _knowledgeDomainService.KnowledgeInfo(Id, HttpContext.RequestAborted);
            if (knowledge is null)
                throw UserFriendlyException.SameMessage("知识查询失败！");
            if (knowledge.Workflow != null) 
                knowledge.IsCanHandle = knowledge.Workflow.IsCanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles);
            //转化
            var knowledgeShowInfoDto = _mapper.Map<KnowledgeInfoDto>(knowledge);

            //var type = await _knowledgeTypeRepository.GetAsync(knowledge.KnowledgeTypeId, HttpContext.RequestAborted);
            //if (type != null)
            //{
            //	knowledgeShowInfoDto.KnowledgeTypeName = type.SpliceName;
            //	knowledgeShowInfoDto.KnowledgeType = _mapper.Map<KnowledgeTypeDto>(type);
            //}
            var hot = await _hotspotTypeRepository.GetAsync(knowledge.HotspotId, HttpContext.RequestAborted);
            if (hot != null)
                knowledgeShowInfoDto.HotspotName = hot.HotSpotFullName;
            //收藏
            var collect = await _knowledgeCollectRepository.GetAsync(x => x.KnowledgeId == Id && x.CreatorId == _sessionContext.UserId);
            if (collect != null)
                knowledgeShowInfoDto.Collect = _mapper.Map<KnowledgeCollectDto>(collect);
            //关联知识
            var knowledges = await _knowledgeRepository.Queryable().In(x => x.Id, knowledge.Knowledges).Where(x => x.Status == EKnowledgeStatus.OnShelf && ((x.ExpiredTime != null && x.ExpiredTime >= DateTime.Now) || x.ExpiredTime == null)).ToListAsync();
            if (knowledges.Any())
                knowledgeShowInfoDto.KnowledgeDtos = _mapper.Map<List<KnowledgeDto>>(knowledges);
            //关键词
            var knowledgeWords = await _knowledgeWrodRepository.Queryable().In(x => x.Id, knowledge.Keywords).ToListAsync();
            if (knowledgeWords.Any())
                knowledgeShowInfoDto.KeywordsDto = _mapper.Map<List<KnowledgeWordDto>>(knowledgeWords);

            var files = await _fileRepository.Queryable().Where(x => x.Key == knowledge.Id).ToListAsync();
            if (files.Any()) knowledgeShowInfoDto.Files = _mapper.Map<List<FileDto>>(files);

            if (IsAddPv == true)
                _mediator.Publish(new GetKnowledgeInfoNotify(knowledge));
            return knowledgeShowInfoDto;
        }

        /// <summary>
        /// 知识申请-关联知识-获取知识列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("getknowledge")]
        public async Task<IReadOnlyList<KnowledgeCreateBMDataDto>> GetKnowledge()
        {
            var temp = await _knowledgeRepository
               .Queryable()
               .LeftJoin<SystemOrganize>((o, sys) => o.CreatorOrgId == sys.Id)
               //重新构建数据
               .Select((o, sys) => new
               {
                   index = SqlFunc.RowNumber($"{o.Version} desc ", $"{o.Code}"),
                   DepartmentId = sys.Id,
                   Department = sys.Name,
                   o.Id,
                   o.Title,
                   o.Status,
                   o.Code,
                   o.IsDeleted,
                   o.ExpiredTime
               })
           //将结果合并成一个表
           .MergeTable()
           //取第一条数据
           .Where(x => x.IsDeleted == false)
           .Where(x => (x.ExpiredTime != null && x.ExpiredTime >= DateTime.Now) || x.ExpiredTime == null)
           .Where(d => d.index == 1 && d.Status == EKnowledgeStatus.OnShelf)
          .ToListAsync();
            //返回数据
            return _mapper.Map<IReadOnlyList<KnowledgeCreateBMDataDto>>(temp);

        }

        /// <summary>
        /// 我的草稿箱
        /// </summary>
        /// <param name="pagedDto"></param>
        /// <returns></returns>
        [HttpGet("mydraftslist")]
        public async Task<PagedDto<KnowledgeDataDto>> MyDraftsList([FromQuery] MyDraftsListPagedDto pagedDto)
        {
            var (total, items) = await _knowledgeRepository
             .Queryable()
             .Includes(it => it.User)
             .Where(p => p.CreatorId == _sessionContext.RequiredUserId && p.Status == EKnowledgeStatus.Drafts)
             .WhereIF(!string.IsNullOrEmpty(pagedDto.Keyword), d => d.Title.Contains(pagedDto.Keyword!))
             .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<KnowledgeDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeDataDto>>(items));
        }

        /// <summary>
        /// 知识库列表页面枚举值
        /// </summary>
        /// <returns></returns>
        [HttpGet("knowledge-status-data")]
        public async Task<object> KnowledgeStatus()
        {
            return new List<KeyValuePair<int, string>>
            {
                new KeyValuePair<int, string>(1, "审核中"),
                new KeyValuePair<int, string>(3, "已上架"),
                new KeyValuePair<int, string>(4, "已下架"),
                new KeyValuePair<int, string>(5, "审核不通过")
            };
        }

        /// <summary>
        /// 知识查询
        /// </summary>
        /// <param name="pagedDto"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<PagedDto<KnowledgeDataDto>> GetKnowList([FromQuery] KnowPagedListDto pagedDto)
        {
            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 aa = _knowledgeRepository.Queryable().OrderByDescending(d => d.CreationTime).ToSql();
            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)
                //.Includes(x=>x.KnowledgeRelationTypes,t=> t.)
                .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 => SqlFunc.JsonLike(x.KnowledgeType, typeSpliceName))
				.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, HttpContext.RequestAborted);
            //temp.ForEach(x => x.IsCanHandle = x.Workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId));
            //返回数据
            return new PagedDto<KnowledgeDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeDataDto>>(temp));
        }

        /// <summary>
        /// 知识检索
        /// </summary>
        /// <param name="pagedDto"></param>
        /// <returns></returns>
        [HttpGet("knowretrieval")]
        public async Task<PagedDto<KnowledgeRetrievalDataDto>> KnowRetrieval([FromQuery] KnowledgeRetrievalPagedListDto pagedDto)
        {
            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 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(pagedDto.RetrievalType == EKnowledgeRetrievalType.All && !string.IsNullOrEmpty(pagedDto.Keyword), d => d.Title.Contains(pagedDto.Keyword!) || d.Content.Contains(pagedDto.Keyword!))// || d.Additions.Contains(pagedDto.Keyword)
                .WhereIF(pagedDto.RetrievalType == EKnowledgeRetrievalType.Title && !string.IsNullOrEmpty(pagedDto.Keyword), d => d.Title.Contains(pagedDto.Keyword!))
                .WhereIF(pagedDto.RetrievalType == EKnowledgeRetrievalType.Content && !string.IsNullOrEmpty(pagedDto.Keyword), d => d.Content.Contains(pagedDto.Keyword!))
                .WhereIF(pagedDto.RetrievalType == EKnowledgeRetrievalType.Summary && !string.IsNullOrEmpty(pagedDto.Keyword), d => d.Summary != null && d.Summary.Contains(pagedDto.Keyword!))
				//.WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => SqlFunc.JsonLike(x.KnowledgeType, typeSpliceName))
				.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.HotspotName), x => x.HotspotType.HotSpotFullName.EndsWith(pagedDto.HotspotName!))
                .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateOrgId), x => x.CreatorOrgId != null && x.CreatorOrgId.EndsWith(pagedDto.CreateOrgId!))
                .WhereIF(!string.IsNullOrEmpty(pagedDto.Attribution), x => x.Attribution == pagedDto.Attribution!);
            switch (pagedDto.Sort)
            {
                case "2":
                    sugar = sugar.OrderByDescending(p => p.Score);
                    break;
                case "3":
                    sugar = sugar.OrderByDescending(p => p.CreationTime);
                    break;
                default:
                    sugar = sugar.OrderByDescending(p => p.PageView);
                    break;
            }
            var (total, temp) = await sugar.ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize);
            return new PagedDto<KnowledgeRetrievalDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeRetrievalDataDto>>(temp));
        }

        /// <summary>
        /// 获取知识审批信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("audit_log")]
        public async Task<PagedDto<KnowledgeWorkFlowDto>> KnowRetrieval([FromQuery] AuditLogListPagedDto pagedDto)
        {
            var (total, temp) = await _knowledgeWorkFlowRepository
                .Queryable()
                .Includes(x => x.User)
                .Includes(x => x.SystemOrganize)
                .Includes(x => x.Workflow)
                .Where(x => x.KnowledgeId == pagedDto.id)
                .Where(x => x.IsDeleted == false)
                .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize);
            return new PagedDto<KnowledgeWorkFlowDto>(total, _mapper.Map<IReadOnlyList<KnowledgeWorkFlowDto>>(temp));
        }
        /// <summary>
        /// 知识查重
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost("finding_duplicate")]

        public async Task<bool> FindingDuplicate([FromBody] KnowledgeFindingDuplicateDto dto)
        {
            var any = await _knowledgeRepository.Queryable().Where(x => x.Status == EKnowledgeStatus.Auditing || x.Status >= EKnowledgeStatus.OnShelf)
                .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Title.Equals(dto.Title))
                .WhereIF(!string.IsNullOrEmpty(dto.Summary), x => x.Summary.Equals(dto.Summary))
                .WhereIF(!string.IsNullOrEmpty(dto.Content), x => x.Content.Equals(dto.Content))
                .WhereIF(!string.IsNullOrEmpty(dto.Id),x=> x.Id !=  dto.Id)
                .AnyAsync();
            return any;
        }

        #endregion

        #region 我的知识删除列表
        /// <summary>
        /// 我的知识删除列表页面枚举值
        /// </summary>
        /// <returns></returns>
        [HttpGet("delete-status-data")]
        public async Task<object> DeleteApplyStatus()
        {
            return EnumExts.GetDescriptions<EKnowledgeWorkFlowStatus>();
        }

        /// <summary>
        /// 我的知识删除列表
        /// </summary>
        /// <param name="pagedDto"></param>
        /// <returns></returns>
        [HttpGet("deletelist")]
        public async Task<PagedDto<KnowledgeDeleteApplyDataDto>> 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 && d.WorkflowId != null)
               .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.Name.Contains(pagedDto.Keyword!)
               || d.Knowledge.Title.Contains(pagedDto.Keyword!))

               .OrderByDescending(p => p.CreationTime)
               .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize, HttpContext.RequestAborted);

            return new PagedDto<KnowledgeDeleteApplyDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeDeleteApplyDataDto>>(items));
        }

        /// <summary>
        /// 审核管理页面枚举值
        /// </summary>
        /// <returns></returns>
        [HttpGet("approval-base-data")]
        public async Task<object> ApprovalBaseData()
        {
            return new
            {
                EKnowledgeWorkFlowStatus = EnumExts.GetDescriptions<EKnowledgeWorkFlowStatus>(),
                EKnowledgeApplyType = EnumExts.GetDescriptions<EKnowledgeApplyType>()
            };
        }

        /// <summary>
        /// 审核管理
        /// </summary>
        /// <param name="pagedDto"></param>
        /// <returns></returns>
        [HttpGet("approvedlist")]
        public async Task<PagedDto<KnowledgeApprovalDataDto>> 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.Workflow, d=>d.Steps)
                .Where(it => it.WorkflowId != null)
                .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.Name.Contains(pagedDto.Keyword!)
                || d.Knowledge.Title.Contains(pagedDto.Keyword!))

                .OrderByDescending(p => p.CreationTime)
                .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize, HttpContext.RequestAborted);

            foreach (var item in items)
            {
                if (item.Workflow != null)
                    //item.CanHandle = item.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
                    item.CanHandle = item.Workflow.IsCanHandle(
                        _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles);

            }
            //处理是否可以办理
            //items.ForEach(d => d.CanHandle = d.Workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgCode));

            return new PagedDto<KnowledgeApprovalDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeApprovalDataDto>>(items));
        }

        /// <summary>
        /// 工单受理知识检索
        /// </summary>
        /// <param name="pagedDto"></param>
        /// <returns></returns>
        [HttpGet("knowpopscreen")]
        public async Task<PagedDto<KnowledgeRetrievalDataDto>> KnowPopScreen([FromQuery] KnowledgePopScreenPagedListDto pagedDto)
        {
            var orgid = string.Empty;
            if (pagedDto.RetrievalType == EKnowledgeRetrievalType.Org && !string.IsNullOrEmpty(pagedDto.Keyword))
            {
                var organize = await _systemOrganizeRepository.GetAsync(x => x.Name == pagedDto.Keyword);
                orgid = organize?.Id;
            }
            var (total, temp) = await _knowledgeRepository.Queryable()
                .Includes(x => x.SourceOrganize)
               .Where(d => d.Status == EKnowledgeStatus.OnShelf)
               .WhereIF(pagedDto.RetrievalType == EKnowledgeRetrievalType.Title && !string.IsNullOrEmpty(pagedDto.Keyword), d => d.Title.Contains(pagedDto.Keyword!))
               .WhereIF(pagedDto.RetrievalType == EKnowledgeRetrievalType.Content && !string.IsNullOrEmpty(pagedDto.Keyword), d => d.Content.Contains(pagedDto.Keyword!))
               .WhereIF(!string.IsNullOrEmpty(orgid) && pagedDto.RetrievalType == EKnowledgeRetrievalType.Org, x => x.CreatorOrgId.EndsWith(orgid!))
               .WhereIF(!string.IsNullOrEmpty(pagedDto.HotspotId), p => p.HotspotId == pagedDto.HotspotId)
               .OrderByDescending(p => p.CreationTime)
               .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize);
            return new PagedDto<KnowledgeRetrievalDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeRetrievalDataDto>>(temp));
        }

        ///// <summary>
        ///// 新增-开始流程
        ///// </summary>
        ///// <param name="id">知识id</param>
        ///// <param name="dto">流程开启参数</param>
        ///// <returns></returns>
        //[Permission(EPermission.AddKnowledge)]
        //[HttpPost("{id}/add-startflow")]
        //public async Task AddStartFlow(string id, [FromBody] StartWorkflowDto dto)
        //{
        //	await StartFlow(id, WorkflowModuleConsts.KnowledgeAdd, EKnowledgeApplyType.Add, dto);
        //}

        ///// <summary>
        ///// 删除-开始流程
        ///// </summary>
        ///// <param name="id">知识id</param>
        ///// <param name="dto">流程开启参数</param>
        ///// <returns></returns>
        //[Permission(EPermission.KnowledgeDelete)]
        //[HttpPost("{id}/remove-startflow")]
        //public async Task RemoveStartFlow(string id, [FromBody] StartWorkflowDto dto)
        //{
        //	await StartFlow(id, WorkflowModuleConsts.KnowledgeDelete, EKnowledgeApplyType.Delete, dto);
        //}

        /// <summary>
        /// 查询知识库办理流程开启参数-新增
        /// </summary>
        /// <returns></returns>
        //[Permission(EPermission.AddKnowledge)]
        [HttpGet("add-flow-start")]
        public async Task<NextStepsDto> GetAddFlowStartOptionsAsync()
        {
            return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.KnowledgeAdd,
                HttpContext.RequestAborted);
        }

        /// <summary>
        /// 查询知识库办理流程开启参数-新增
        /// </summary>
        /// <returns></returns>
        //[Permission(EPermission.AddKnowledge)]
        [HttpGet("update-flow-start")]
        public async Task<NextStepsDto> GetUpdateFlowStartOptionsAsync()
        {
            return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.KnowledgeUpdate,
                HttpContext.RequestAborted);
        }

        /// <summary>
        /// 查询知识库办理流程开启参数-删除
        /// </summary>
        /// <returns></returns>
        //[Permission(EPermission.KnowledgeDelete)]
        [HttpGet("remove-flow-start")]
        public async Task<NextStepsDto> GetRemoveFlowStartOptionsAsync()
        {
            return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.KnowledgeDelete,
                HttpContext.RequestAborted);
        }

        /// <summary>
        /// 开始流程
        /// </summary>
        /// <param name="id">知识ID</param>
        /// <param name="moduleCode">知识模板编号</param>
        /// <param name="eKnowledgeApplyType">申请类型</param>
        /// <param name="dto">流程开启参数</param>
        /// <returns></returns>
        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) && p.WorkflowId != null);
                //if (exists != null)
                //	throw UserFriendlyException.SameMessage($"该知识已发起过{WorkflowModuleConsts.KnowledgeDelete}流程");//todo
            }

            //知识审批主表
            var flowId = await _knowledgeDomainService.AddWorkFlowAsync(id, eKnowledgeApplyType, HttpContext.RequestAborted);

            dto.DefinitionModuleCode = moduleCode;
            dto.Title = knowledge.Title;
            await _workflowApplication.StartWorkflowAsync(dto, _sessionContext, flowId, cancellationToken: HttpContext.RequestAborted);
        }
        #endregion

        #region 知识库词库
        /// <summary>
        /// 新增知识库词库
        /// </summary>
        /// <param name="dtos"></param>
        /// <returns></returns>
        [Permission(EPermission.AddKnowledgeWord)]
        [HttpPost("knowledge_word")]
        [LogFilter("新增知识库词库")]
        public async Task Add([FromBody] KnowledgeWordAddDto dto)
        {
            var word = _mapper.Map<KnowledgeWord>(dto);
            await _knowledgeWrodRepository.AddAsync(word, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 删除知识库词库
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [Permission(EPermission.DeleteKnowledgeWord)]
        [HttpDelete("knowledge_word")]
        [LogFilter("删除知识库词库")]
        public async Task Delete([FromBody] KnowledgeWordDeleteDto dto)
        {
            await _knowledgeRepository.RemoveKnowledgeWrodBatchAsync(dto.Ids, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 更新知识库词库
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [Permission(EPermission.UpdateKnowledgeWord)]
        [HttpPut("knowledge_word")]
        [LogFilter("更新知识库词库")]
        public async Task Update([FromBody] KnowledgeWordUpdateDto dto)
        {
            var word = await _knowledgeWrodRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (word is null)
                throw UserFriendlyException.SameMessage("无效知识库词库");
            _mapper.Map(dto, word);
            word.LastModificationName = _sessionContext.UserName;
            await _knowledgeWrodRepository.UpdateAsync(word, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 获取知识库词库列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("knowledge_word/list")]
        public async Task<PagedDto<KnowledgeWordDto>> List([FromQuery] KnowledgeWordListDto dto)
        {
            var (total, items) = await _knowledgeWrodRepository.Queryable()
                .WhereIF(!string.IsNullOrEmpty(dto.Tag), x => x.Tag == dto.Tag!)
                .WhereIF(!string.IsNullOrEmpty(dto.Classify), x => x.Classify == dto.Classify!)
                .WhereIF(!string.IsNullOrEmpty(dto.Synonym), x => x.Synonym != null && x.Synonym.Contains(dto.Synonym!))
                .OrderByDescending(x => x.CreationTime)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<KnowledgeWordDto>(total, _mapper.Map<IReadOnlyList<KnowledgeWordDto>>(items));
        }

        /// <summary>
        /// 获取知识库词库
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("knowledge_word/{id}")]
        public async Task<KnowledgeWord> WordEntity(string id)
        {
            return await _knowledgeWrodRepository.Queryable()
                .FirstAsync(x => x.Id == id);
        }

        /// <summary>
        /// 获取知识库词库基本信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("knowledge_word/base")]
        public async Task<object> Base()
        {
            var rsp = new
            {
                KnowledgeWordClassify = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.KnowledgeWordClassify),
            };
            return rsp;
        }
        #endregion

        #region 知识纠错
        /// <summary>
        /// 新增知识纠错
        /// </summary>
        /// <param name="dtos"></param>
        /// <returns></returns>
        //[Permission(EPermission.AddKnowledgeCorrection)]
        [HttpPost("knowledge_correction")]
        [LogFilter("新增知识纠错")]
        public async Task Add([FromBody] KnowledgeCorrectionAddDto dto)
        {
            var correction = _mapper.Map<KnowledgeCorrection>(dto);
            await _knowledgeCorrectionRepository.AddAsync(correction, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 删除知识纠错
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        //[Permission(EPermission.DeleteKnowledgeCorrection)]
        //[HttpDelete("knowledge_correction")]
        //public async Task Delete([FromBody] KnowledgeCorrectionDeleteDto dto)
        //{
        //	await _knowledgeCorrectionRepository.RemoveAsync(x => x.Id == dto.Id);
        //}

        /// <summary>
        /// 更新知识纠错
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        //[Permission(EPermission.UpdateKnowledgeCorrection)]
        //[HttpPut("knowledge_correction")]
        //public async Task Update([FromBody] KnowledgeCorrectionUpdateDto dto)
        //{
        //	var correction = await _knowledgeCorrectionRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
        //	if (correction is null)
        //		throw UserFriendlyException.SameMessage("无效知识纠错");
        //	_mapper.Map(dto, correction);
        //	await _knowledgeCorrectionRepository.UpdateAsync(correction, HttpContext.RequestAborted);
        //}

        /// <summary>
        /// 答复知识纠错
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [Permission(EPermission.ReplyKnowledgeCorrection)]
        [HttpPut("knowledge_correction/Reply")]
        [LogFilter("答复知识纠错")]
        public async Task Reply([FromBody] KnowledgeCorrectionUpdateDto dto)
        {
            var correction = await _knowledgeCorrectionRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (correction is null)
                throw UserFriendlyException.SameMessage("无效知识纠错");
            _mapper.Map(dto, correction);
            correction.ReplyTime = DateTime.Now;
            correction.ReplyUserName = _sessionContext.UserName;
            correction.State = ECorrectionState.AlreadyAnswered;
            await _knowledgeCorrectionRepository.UpdateAsync(correction, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 获取知识纠错列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [Permission(EPermission.KnowledgeCorrectionList)]
        [HttpGet("knowledge_correction/list")]
        public async Task<PagedDto<KnowledgeCorrectionDto>> List([FromQuery] KnowledgeCorrectionListDto dto)
        {
            var typeSpliceName = string.Empty;
            if (!string.IsNullOrEmpty(dto.KnowledgeTypeId))
            {
                var type = await _knowledgeTypeRepository.GetAsync(x => x.Id == dto.KnowledgeTypeId);
                typeSpliceName = type?.SpliceName;
            }
            var (total, items) = await _knowledgeCorrectionRepository.Queryable()
                .Includes(x => x.Knowledge)
                //.WhereIF(!string.IsNullOrEmpty(dto.KnowledgeTypeId), x => x.Knowledge.KnowledgeTypeId == dto.KnowledgeTypeId!)
                .WhereIF(!string.IsNullOrEmpty(dto.CreatorName), x => x.CreatorName == dto.CreatorName!)
				 //.WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => SqlFunc.JsonLike(x.Knowledge.KnowledgeType, typeSpliceName))
				 .WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => x.Knowledge.KnowledgeType.Any(t=>t.KnowledgeTypeSpliceName.EndsWith(typeSpliceName)))
				.Where(x => !string.IsNullOrEmpty(x.Knowledge.Id))
                .OrderByDescending(x => x.CreationTime)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<KnowledgeCorrectionDto>(total, _mapper.Map<IReadOnlyList<KnowledgeCorrectionDto>>(items));
        }

        /// <summary>
        /// 获取知识库纠错
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        //[Permission(EPermission.KnowledgeCorrectionEntity)]
        [HttpGet("knowledge_correction/{id}")]
        public async Task<KnowledgeCorrection> CorrectionEntity(string id)
        {
            return await _knowledgeCorrectionRepository.Queryable()
                .Includes(x => x.Knowledge)
                .FirstAsync(x => x.Id == id);
        }
        #endregion

        #region 知识提问
        /// <summary>
        /// 新增知识提问
        /// </summary>
        /// <param name="dtos"></param>
        /// <returns></returns>
        //[Permission(EPermission.AddKnowledgeQuestions)]
        [HttpPost("knowledge_questions")]
        [LogFilter("新增知识提问")]
        public async Task Add([FromBody] KnowledgeQuestionsAddDto dto)
        {
            var questions = _mapper.Map<KnowledgeQuestions>(dto);
            await _knowledgeQuestionsRepository.AddAsync(questions, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 删除知识提问
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        //[Permission(EPermission.DeleteKnowledgeQuestions)]
        //[HttpDelete("knowledge_questions")]
        //public async Task Delete([FromBody] KnowledgeQuestionsDeleteDto dto)
        //{
        //	await _knowledgeQuestionsRepository.RemoveAsync(x => x.Id == dto.Id);
        //}

        /// <summary>
        /// 更新知识提问
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        //[Permission(EPermission.UpdateKnowledgeQuestions)]
        //[HttpPut("knowledge_questions")]
        //public async Task Update([FromBody] KnowledgeQuestionsUpdateDto dto)
        //{
        //	var questions = await _knowledgeQuestionsRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
        //	if (questions is null)
        //		throw UserFriendlyException.SameMessage("无效知识提问");
        //	_mapper.Map(dto, questions);
        //	await _knowledgeQuestionsRepository.UpdateAsync(questions, HttpContext.RequestAborted);
        //}

        /// <summary>
        /// 答复知识提问
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [Permission(EPermission.ReplyKnowledgeQuestions)]
        [HttpPut("knowledge_questions/Reply")]
        [LogFilter("答复知识提问")]
        public async Task Reply([FromBody] KnowledgeQuestionsUpdateDto dto)
        {
            var questions = await _knowledgeQuestionsRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (questions is null)
                throw UserFriendlyException.SameMessage("无效知识提问");
            _mapper.Map(dto, questions);
            questions.ReplyTime = DateTime.Now;
            questions.ReplyUserName = _sessionContext.UserName;
            questions.State = ECorrectionState.AlreadyAnswered;
            await _knowledgeQuestionsRepository.UpdateAsync(questions, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 获取知识提问列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [Permission(EPermission.KnowledgeQuestionsList)]
        [HttpGet("knowledge_questions/list")]
        public async Task<PagedDto<KnowledgeQuestionsDto>> List([FromQuery] KnowledgeQuestionsListDto dto)
        {
            var typeSpliceName = string.Empty;
            if (!string.IsNullOrEmpty(dto.KnowledgeTypeId))
            {
                var type = await _knowledgeTypeRepository.GetAsync(x => x.Id == dto.KnowledgeTypeId);
                typeSpliceName = type?.SpliceName;
            }
            var (total, items) = await _knowledgeQuestionsRepository.Queryable()
                .Includes(x => x.Knowledge)
			   //.WhereIF(!string.IsNullOrEmpty(dto.KnowledgeTypeId), x => x.Knowledge.KnowledgeTypeId == dto.KnowledgeTypeId!)
			   //.WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => SqlFunc.JsonLike(x.Knowledge.KnowledgeType, typeSpliceName))
			   .WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => x.Knowledge.KnowledgeType.Any(t=>t.KnowledgeTypeSpliceName.EndsWith(typeSpliceName)))
				.WhereIF(!string.IsNullOrEmpty(dto.CreatorName), x => x.CreatorName == dto.CreatorName!)
                .Where(x => !string.IsNullOrEmpty(x.Knowledge.Id))
                .OrderByDescending(x => x.CreationTime)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<KnowledgeQuestionsDto>(total, _mapper.Map<IReadOnlyList<KnowledgeQuestionsDto>>(items));
        }

        /// <summary>
        /// 获取知识提问
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        //[Permission(EPermission.KnowledgeQuestionsEntity)]
        [HttpGet("knowledge_questions/{id}")]
        public async Task<KnowledgeQuestions> QuestionsEntity(string id)
        {
            return await _knowledgeQuestionsRepository.Queryable()
                .Includes(x => x.Knowledge)
                .FirstAsync(x => x.Id == id);
        }

        #endregion

        #region 知识收藏
        /// <summary>
        /// 知识收藏列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [Permission(EPermission.KnowledgeCollectList)]
        [HttpGet("knowledge_collect/list")]
        public async Task<PagedDto<KnowledgeCollectDto>> List([FromQuery] KnowledgeCollectListDto dto)
        {
            var (total, items) = await _knowledgeCollectRepository.Queryable()
                .Includes(x => x.Knowledge)
                .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Knowledge.Title.Contains(dto.Keyword!) || (x.Knowledge.Summary != null && x.Knowledge.Summary.Contains(dto.Keyword!)))
                .Where(x => x.CreatorId == _sessionContext.UserId)
                .Where(x => !string.IsNullOrEmpty(x.Knowledge.Id))
                .Where(x => x.Collect!.Value)
                .OrderByDescending(x => x.CreationTime)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<KnowledgeCollectDto>(total, _mapper.Map<IReadOnlyList<KnowledgeCollectDto>>(items));
        }

        /// <summary>
        /// 新增知识收藏
        /// </summary>
        /// <param name="dtos"></param>
        /// <returns></returns>
        //[Permission(EPermission.AddKnowledgeCollect)]
        [HttpPost("knowledge_collect")]
        [LogFilter("知识收藏")]
        public async Task Add([FromBody] KnowledgeCollectAddDto dto)
        {
            var collect = await _knowledgeCollectRepository.GetAsync(x => x.KnowledgeId == dto.KnowledgeId && x.CreatorId == _sessionContext.UserId);
            if (collect != null)
            {
                collect.Collect = dto.Collect;
                await _knowledgeCollectRepository.UpdateAsync(collect, HttpContext.RequestAborted);
            }
            else
            {
                var collectNew = _mapper.Map<KnowledgeCollect>(dto);
                await _knowledgeCollectRepository.AddAsync(collectNew, HttpContext.RequestAborted);
            }
        }

        /// <summary>
        /// 知识评分
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        //[Permission(EPermission.AddKnowledgeScore)]
        [HttpDelete("knowledge_score")]
        [LogFilter("知识评分")]
        public async Task Delete([FromBody] KnowledgeCollectAddDto dto)
        {
            var collect = await _knowledgeCollectRepository.GetAsync(x => x.KnowledgeId == dto.KnowledgeId && x.CreatorId == _sessionContext.UserId);
            if (collect != null)
            {
                if (collect.Score > 0)
                    throw UserFriendlyException.SameMessage("当前知识已经评分");
                collect.Score = dto.Score;
                await _knowledgeCollectRepository.UpdateAsync(collect, HttpContext.RequestAborted);
            }
            else
            {
                var questions = _mapper.Map<KnowledgeCollect>(dto);
                await _knowledgeCollectRepository.AddAsync(questions, HttpContext.RequestAborted);
            }
            //计算总分
            var sugar = _knowledgeCollectRepository.Queryable().Where(x => x.KnowledgeId == dto.KnowledgeId);
            var count = await sugar.CountAsync();
            var collects = await sugar.SumAsync(x => x.Score);
            var score = collects / count;
            var knowledge = await _knowledgeRepository.GetAsync(x => x.Id == dto.KnowledgeId);
            if (knowledge != null)
            {
                knowledge.Score = decimal.Round(score.Value, 1);
                await _knowledgeRepository.UpdateAsync(knowledge, HttpContext.RequestAborted);
            }
        }
        #endregion

        #region 知识评论

        /// <summary>
        /// 新增知识评论
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("knowledge_comment")]
        public async Task Add([FromBody] KnowledgeCommentAddDto dto)
        {
            var model = _mapper.Map<KnowledgeComment>(dto);
            await _knowledgeCommentRepository.AddAsync(model, HttpContext.RequestAborted);
            if (!string.IsNullOrEmpty(dto.ReplyId))
            {
                var comment = await _knowledgeCommentRepository.GetAsync(dto.ReplyId);
                if (comment != null)
                {
                    comment.ReplyNum++;
                    await _knowledgeCommentRepository.UpdateAsync(comment, HttpContext.RequestAborted);
                }
            }
        }

        /// <summary>
        /// 删除知识评论
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpDelete("knowledge_comment")]
        public async Task Delete([FromBody] KnowledgeCommentDeleteDto dto)
        {
            var comment = await _knowledgeCommentRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (comment is null)
                throw UserFriendlyException.SameMessage("无效评论");
            if (comment.CreatorId != _sessionContext.UserId)
                throw UserFriendlyException.SameMessage("只有评论者可以删除当前评论");
            await _knowledgeCommentRepository.RemoveAsync(x => x.Id == dto.Id);
        }

        /// <summary>
        /// 修改知识评论
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("knowledge_comment")]
        public async Task Update([FromBody] KnowledgeCommentUpdateDto dto)
        {
            var comment = await _knowledgeCommentRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (comment is null)
                throw UserFriendlyException.SameMessage("无效评论");
            _mapper.Map(dto, comment);
            await _knowledgeCommentRepository.UpdateAsync(comment, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 知识评论列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("knowledge_comment/list")]
        public async Task<List<KnowledgeCommentDto>> List([FromQuery] KnowledgeCommentListDto dto)
        {
            var comments = await _knowledgeCommentRepository.Queryable()
                .WhereIF(!string.IsNullOrEmpty(dto.KnowledgeId), x => x.KnowledgeId == dto.KnowledgeId)
                .WhereIF(!string.IsNullOrEmpty(dto.ReplyId), x => x.ReplyId == dto.ReplyId)
                .WhereIF(dto.All.HasValue && dto.All == false, x => x.CreatorId == _sessionContext.UserId)
                .OrderByDescending(x => x.CreationTime)
                .ToListAsync();
            return new List<KnowledgeCommentDto>(_mapper.Map<IReadOnlyList<KnowledgeCommentDto>>(comments));
        }
        #endregion
    }
}
