소스 검색

增加知识库

TANG JIANG 2 년 전
부모
커밋
f7a2505696
45개의 변경된 파일2167개의 추가작업 그리고 214개의 파일을 삭제
  1. 5 5
      src/Hotline.Api/Controllers/HomeController.cs
  2. 365 0
      src/Hotline.Api/Controllers/KnowledgeApplyController.cs
  3. 277 0
      src/Hotline.Api/Controllers/KnowledgeCommonController.cs
  4. 413 0
      src/Hotline.Api/Controllers/KnowledgeController.cs
  5. 1 2
      src/Hotline.Api/Controllers/ReportController.cs
  6. 105 99
      src/Hotline.Api/Controllers/TestController.cs
  7. 49 84
      src/Hotline.Api/Controllers/WorkflowController.cs
  8. 2 0
      src/Hotline.Api/StartupExtensions.cs
  9. 1 1
      src/Hotline.Api/appsettings.Development.json
  10. 1 1
      src/Hotline.Api/appsettings.json
  11. 18 0
      src/Hotline.Application.Contracts/Validators/Knowledge/AddKnowledgeApplyDtoValidator.cs
  12. 17 0
      src/Hotline.Application.Contracts/Validators/Knowledge/AddKnowledgeStandardDtoValidator.cs
  13. 16 0
      src/Hotline.Application.Contracts/Validators/Knowledge/AddKnowledgeTypeValidator.cs
  14. 20 0
      src/Hotline.Application.Contracts/Validators/Knowledge/UpdateKnowledgeApplyDtoValidator.cs
  15. 18 0
      src/Hotline.Application.Contracts/Validators/Knowledge/UpdateKnowledgeStandardDtoValidator.cs
  16. 17 0
      src/Hotline.Application.Contracts/Validators/Knowledge/UpdateKnowledgeTypeValidator.cs
  17. 8 0
      src/Hotline.Application/Dtos/WorkflowDefinitionDto.cs
  18. 1 0
      src/Hotline.Application/Hotline.Application.csproj
  19. 24 1
      src/Hotline.Application/Mappers/MapperConfigs.cs
  20. 67 0
      src/Hotline.Share/Dtos/Knowledge/KnowledgeApplyDto.cs
  21. 57 0
      src/Hotline.Share/Dtos/Knowledge/KnowledgeApplyPageDto.cs
  22. 8 0
      src/Hotline.Share/Dtos/Knowledge/KnowledgeApplyPagedDto.cs
  23. 89 0
      src/Hotline.Share/Dtos/Knowledge/KnowledgeDataDto.cs
  24. 85 0
      src/Hotline.Share/Dtos/Knowledge/KnowledgeDto.cs
  25. 58 0
      src/Hotline.Share/Dtos/Knowledge/KnowledgePagedDto.cs
  26. 29 0
      src/Hotline.Share/Dtos/Knowledge/KnowledgeStandardDto.cs
  27. 70 0
      src/Hotline.Share/Dtos/Knowledge/KnowledgeTypeDto.cs
  28. 35 0
      src/Hotline.Share/Dtos/Knowledge/TreeListDto.cs
  29. 12 0
      src/Hotline/IDeviceEventHandler.cs
  30. 8 0
      src/Hotline/KnowledgeBase/IKnowledgeApplyRepository.cs.cs
  31. 9 0
      src/Hotline/KnowledgeBase/IKnowledgePVRepository.cs
  32. 9 0
      src/Hotline/KnowledgeBase/IKnowledgeRepository.cs
  33. 8 0
      src/Hotline/KnowledgeBase/IKnowledgeStandardRepository.cs
  34. 8 0
      src/Hotline/KnowledgeBase/IKnowledgeTempRepository.cs
  35. 8 0
      src/Hotline/KnowledgeBase/IKnowledgeTypeRepository.cs
  36. 30 0
      src/Hotline/KnowledgeBase/IKnowledgeTypeService.cs
  37. 27 3
      src/Hotline/KnowledgeBase/Knowledge.cs
  38. 21 1
      src/Hotline/KnowledgeBase/KnowledgeApply.cs
  39. 4 1
      src/Hotline/KnowledgeBase/KnowledgePV.cs
  40. 7 0
      src/Hotline/KnowledgeBase/KnowledgeStandard.cs
  41. 1 1
      src/Hotline/KnowledgeBase/KnowledgeTemp.cs
  42. 8 1
      src/Hotline/KnowledgeBase/KnowledgeType.cs
  43. 127 0
      src/Hotline/KnowledgeBase/KnowledgeTypeService.cs
  44. 15 14
      src/Hotline/Orders/Order.cs
  45. 9 0
      src/Hotline/Orders/TempOrder.cs

+ 5 - 5
src/Hotline.Api/Controllers/HomeController.cs

@@ -75,7 +75,7 @@ public class HomeController : BaseController
         db.CodeFirst.InitTables<Blacklist,Call,CallDetail,CallRecord,TelHold>();
         db.CodeFirst.InitTables<Ivr, IvrCategory, Tel, TelGroup, TelRest>();
         db.CodeFirst.InitTables<Knowledge, KnowledgeApply, KnowledgePv, KnowledgeStandard, KnowledgeTemp>();
-        db.CodeFirst.InitTables<KnowledgeType, Orders.Order, OrderTemporary, OrgUser>();
+        db.CodeFirst.InitTables<KnowledgeType, Orders.Order, TempOrder, OrgUser>();
         db.CodeFirst.InitTables<SystemAuthority, SystemButton, SystemDataAuthority, SystemDataTable, SystemMenu>();
         db.CodeFirst.InitTables<SystemOrganize, SystemSetting, SystemSettingGroup, UserFastMenu>();
         db.CodeFirst.InitTables<User, Work>();
@@ -88,12 +88,12 @@ public class HomeController : BaseController
     /// <returns></returns>
     [AllowAnonymous]
     [HttpPost("get-fastmenu")]
-    public async Task<IReadOnlyList<SystemMenu>> GetFastMenuByToken([FromBody] GetFastMenuByTokenDto dto)
+    public async Task<IReadOnlyList<SystemMenu>> GetFastMenuByToken([FromBody]GetFastMenuByTokenDto dto)
     {
         if (!string.IsNullOrEmpty(_sessionContext.UserId))
         {
             var roles = _sessionContext.Roles;
-            return await _systemMenuRepository.GetFastMenu(roles, _sessionContext.UserId, dto.name);
+            return await _systemMenuRepository.GetFastMenu(roles, _sessionContext.UserId,dto.name);
         }
         throw UserFriendlyException.SameMessage("无效登录信息");
     }
@@ -104,7 +104,7 @@ public class HomeController : BaseController
     /// <returns></returns>
     [AllowAnonymous]
     [HttpPost("set-fastmenu")]
-    public async Task SetFastMenu([FromBody] SetFastMenuDto dto)
+    public async Task SetFastMenu([FromBody]SetFastMenuDto dto)
     {
         if (!string.IsNullOrEmpty(_sessionContext.UserId))
         {
@@ -125,7 +125,7 @@ public class HomeController : BaseController
         {
             throw UserFriendlyException.SameMessage("无效登录信息");
         }
-
+        
     }
 
     /// <summary>

+ 365 - 0
src/Hotline.Api/Controllers/KnowledgeApplyController.cs

@@ -0,0 +1,365 @@
+using Hotline.KnowledgeBase;
+using Hotline.Repository.SqlSugar;
+using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.Knowledge;
+using Hotline.Share.Enums.KnowledgeBase;
+using MapsterMapper;
+using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
+using XF.Domain.Exceptions;
+
+namespace Hotline.Api.Controllers
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class KnowledgeApplyController : BaseController
+    {
+        private readonly IKnowledgeRepository _knowledgeRepository;
+        private readonly IKnowledgeApplyRepository _knowledgeApplyRepository;
+        private readonly IMapper _mapper;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="knowledgeRepository"></param>
+        /// <param name="knowledgeApplyRepository"></param>
+        /// <param name="mapper"></param>
+        public KnowledgeApplyController(IKnowledgeRepository knowledgeRepository, IKnowledgeApplyRepository knowledgeApplyRepository,
+            IMapper mapper)
+        {
+            _knowledgeRepository = knowledgeRepository;
+            _knowledgeApplyRepository = knowledgeApplyRepository;
+            _mapper = mapper;
+        }
+
+        /// <summary>
+        /// 知识申请-发起申请
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("apply-add")]
+        public async Task<string> ApplyAdd([FromBody] KnowledgeApplyDto dto)
+        {
+            var ka = _mapper.Map<KnowledgeApply>(dto);
+            ka.CreationTime = DateTime.Now;
+            ka.Status = EKnowledgeApplyStatus.Handling;
+            return await _knowledgeApplyRepository.AddAsync(ka);
+        }
+
+        /// <summary>
+        /// 知识申请-修改申请
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("apply-update")]
+        public async Task UpdateAdd([FromBody] UpdateKnowledgeApplyDto dto)
+        {
+            var ka = _mapper.Map<KnowledgeApply>(dto);
+            await _knowledgeApplyRepository.UpdateAsync(ka);
+        }
+
+        /// <summary>
+        ///知识申请-信息办理
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpPost("apply-handle")]
+        public async Task ApplyHandle(string Id)
+        {
+            //查询申请信息
+            var handle = await _knowledgeApplyRepository.GetAsync(Id);
+
+            if (handle is null)
+                throw UserFriendlyException.SameMessage("办理失败");
+            handle.Status = EKnowledgeApplyStatus.Succeed;
+            //修改办理信息
+            await _knowledgeApplyRepository.UpdateAsync(handle);
+        }
+
+        /// <summary>
+        ///知识申请- 撤销操作
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpPost("apply-handle/{Id}")]
+        public async Task ApplyRevoke(string Id)
+        {
+            var handle = await _knowledgeApplyRepository.GetAsync(Id);
+            if (handle is null)
+                throw UserFriendlyException.SameMessage("申请信息撤销失败");
+            handle.Status = EKnowledgeApplyStatus.Revert;
+            await _knowledgeApplyRepository.UpdateAsync(handle);
+        }
+
+        /// <summary>
+        /// 知识申请-退回操作
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpPost("apply-return")]
+        public async Task ApplyReturn(string Id)
+        {
+            //查询申请信息
+            var handle = await _knowledgeApplyRepository.GetAsync(Id);
+            if (handle is null)
+                throw UserFriendlyException.SameMessage("退回失败");
+            handle.Status = EKnowledgeApplyStatus.Failed;
+            await _knowledgeApplyRepository.UpdateAsync(handle);
+        }
+
+        /// <summary>
+        /// 知识申请-查询详情
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpGet("apply-info")]
+        public async Task<DataKnowledgeApplyDto> ApplyInfo(string Id)
+        {
+            var handle = await _knowledgeApplyRepository.GetAsync(Id);
+            if (handle is null)
+                throw UserFriendlyException.SameMessage("申请信息查询失败");
+            DataKnowledgeApplyDto dataKnowledgeApplyDto = new();
+            _mapper.Map(handle, dataKnowledgeApplyDto);
+
+            var knowledge = await _knowledgeRepository.GetAsync(p => p.Applies.Contains(Id));
+            if (knowledge != null)
+            {
+                dataKnowledgeApplyDto.KBID = knowledge.Id;
+                dataKnowledgeApplyDto.KBTitle = knowledge.Title;
+            }
+
+            return dataKnowledgeApplyDto;
+        }
+
+        #region 我的知识申请
+        /// <summary>
+        /// 我的知识申请--全部
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost("apply-allapply")]
+        public async Task<PagedDto<KnowledgeApply>> AllApply([FromQuery] KnowledgeApplyPagedDto dto)
+        {
+            var (total, items) = await _knowledgeApplyRepository
+                  .Queryable(false)
+                  .Includes(it => it.User)
+                  .Includes(it => it.SystemOrganize)
+                  .Where(d => d.CreateUserId == dto.CreateUserId)
+                  .WhereIF(!string.IsNullOrEmpty(dto.ApplyType), d => d.KnowledgeApplyType.ToString() == dto.ApplyType)
+                  .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "0", d => d.ExpiredTime < DateTime.Now)
+                  .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "1", d => d.ExpiredTime >= DateTime.Now)
+                  .WhereIF(dto.StartTime != null, d => d.CreationTime >= dto.StartTime)
+                  .WhereIF(dto.EndTime != null, d => d.CreationTime <= dto.EndTime)
+                  .OrderByDescending(p => p.CreationTime)
+                  .ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+            return new PagedDto<KnowledgeApply>(total, _mapper.Map<IReadOnlyList<KnowledgeApply>>(items));
+        }
+
+        /// <summary>
+        /// 我的知识申请--处理中
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("apply-processingapply")]
+        public async Task<PagedDto<KnowledgeApply>> ProcessingApply([FromQuery] KnowledgeApplyPagedDto dto)
+        {
+            var (total, items) = await _knowledgeApplyRepository
+               .Queryable(false)
+               .Includes(it => it.User)
+               .Includes(it => it.SystemOrganize)
+               .Where(d => d.CreateUserId == dto.CreateUserId && d.Status == EKnowledgeApplyStatus.Handling)
+               .WhereIF(!string.IsNullOrEmpty(dto.ApplyType), d => d.KnowledgeApplyType.ToString() == dto.ApplyType)
+               .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "0", d => d.ExpiredTime < DateTime.Now)
+               .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "1", d => d.ExpiredTime >= DateTime.Now)
+               .WhereIF(dto.StartTime != null, d => d.CreationTime >= dto.StartTime)
+               .WhereIF(dto.EndTime != null, d => d.CreationTime <= dto.EndTime)
+               .OrderByDescending(p => p.CreationTime)
+               .ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+            return new PagedDto<KnowledgeApply>(total, _mapper.Map<IReadOnlyList<KnowledgeApply>>(items));
+        }
+
+        /// <summary>
+        /// 我的知识申请--已完成
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("apply-endapply")]
+        public async Task<PagedDto<KnowledgeApply>> EndApply([FromQuery] KnowledgeApplyPagedDto dto)
+        {
+            var (total, items) = await _knowledgeApplyRepository
+              .Queryable(false)
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Where(d => d.CreateUserId == dto.CreateUserId && d.Status == EKnowledgeApplyStatus.Succeed)
+              .WhereIF(!string.IsNullOrEmpty(dto.ApplyType), d => d.KnowledgeApplyType.ToString() == dto.ApplyType)
+              .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "0", d => d.ExpiredTime < DateTime.Now)
+              .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "1", d => d.ExpiredTime >= DateTime.Now)
+              .WhereIF(dto.StartTime != null, d => d.CreationTime >= dto.StartTime)
+              .WhereIF(dto.EndTime != null, d => d.CreationTime <= dto.EndTime)
+              .OrderByDescending(p => p.CreationTime)
+              .ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+            return new PagedDto<KnowledgeApply>(total, _mapper.Map<IReadOnlyList<KnowledgeApply>>(items));
+        }
+
+        /// <summary>
+        /// 我的知识申请--退回
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("apply-returnapply")]
+        public async Task<PagedDto<KnowledgeApply>> ReturnApply([FromQuery] KnowledgeApplyPagedDto dto)
+        {
+            var (total, items) = await _knowledgeApplyRepository
+              .Queryable(false)
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Where(d => d.CreateUserId == dto.CreateUserId && d.Status == EKnowledgeApplyStatus.Failed)
+              .WhereIF(!string.IsNullOrEmpty(dto.ApplyType), d => d.KnowledgeApplyType.ToString() == dto.ApplyType)
+              .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "0", d => d.ExpiredTime < DateTime.Now)
+              .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "1", d => d.ExpiredTime >= DateTime.Now)
+              .WhereIF(dto.StartTime != null, d => d.CreationTime >= dto.StartTime)
+              .WhereIF(dto.EndTime != null, d => d.CreationTime <= dto.EndTime)
+              .OrderByDescending(p => p.CreationTime)
+              .ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+            return new PagedDto<KnowledgeApply>(total, _mapper.Map<IReadOnlyList<KnowledgeApply>>(items));
+        }
+
+        /// <summary>
+        /// 我的知识申请--已撤销
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("apply-revokeapply")]
+        public async Task<PagedDto<KnowledgeApply>> RevokeApply([FromQuery] KnowledgeApplyPagedDto dto)
+        {
+            var (total, items) = await _knowledgeApplyRepository
+              .Queryable(false)
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Where(d => d.CreateUserId == dto.CreateUserId && d.Status == EKnowledgeApplyStatus.Revert)
+              .WhereIF(!string.IsNullOrEmpty(dto.ApplyType), d => d.KnowledgeApplyType.ToString() == dto.ApplyType)
+              .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "0", d => d.ExpiredTime < DateTime.Now)
+              .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "1", d => d.ExpiredTime >= DateTime.Now)
+              .WhereIF(dto.StartTime != null, d => d.CreationTime >= dto.StartTime)
+              .WhereIF(dto.EndTime != null, d => d.CreationTime <= dto.EndTime)
+              .OrderByDescending(p => p.CreationTime)
+              .ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+            return new PagedDto<KnowledgeApply>(total, _mapper.Map<IReadOnlyList<KnowledgeApply>>(items));
+        }
+        #endregion
+
+        #region 知识申请处理查询
+        /// <summary>
+        /// 申请处理--全部
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost("apply-allhandle")]
+        public async Task<PagedDto<KnowledgeApplyPageDto>> AllHandle([FromQuery] KnowledgeHandlePagedDto dto)
+        {
+            var (total, items) = await _knowledgeApplyRepository
+                 .Queryable(false)
+                 .Includes(it => it.User)
+                 .Includes(it => it.SystemOrganize)
+                 .Where(p => p.DepartmentCode == dto.DepartmentCode)
+                 .WhereIF(!string.IsNullOrEmpty(dto.CreateUserName), d => d.User.Name.Contains(dto.CreateUserName!))
+                 .WhereIF(!string.IsNullOrEmpty(dto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(dto.CreateBMName!))
+                 .WhereIF(!string.IsNullOrEmpty(dto.ApplyType), d => d.KnowledgeApplyType.ToString() == dto.ApplyType)
+                 .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "0", d => d.ExpiredTime < DateTime.Now)
+                 .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "1", d => d.ExpiredTime >= DateTime.Now)
+                 .WhereIF(dto.StartTime != null, d => d.CreationTime >= dto.StartTime)
+                 .WhereIF(dto.EndTime != null, d => d.CreationTime <= dto.EndTime)
+                 .OrderByDescending(p => p.CreationTime)
+                 .ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+            return new PagedDto<KnowledgeApplyPageDto>(total, _mapper.Map<IReadOnlyList<KnowledgeApplyPageDto>>(items));
+        }
+
+        /// <summary>
+        /// 申请处理--处理中
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("apply-processinghandle")]
+        public async Task<PagedDto<KnowledgeApplyPageDto>> ProcessingHandle([FromQuery] KnowledgeHandlePagedDto dto)
+        {
+            var (total, items) = await _knowledgeApplyRepository
+                .Queryable(false)
+                .Includes(it => it.User)
+                .Includes(it => it.SystemOrganize)
+                .Where(p => p.DepartmentCode == dto.DepartmentCode)
+                .Where(p => p.Status == EKnowledgeApplyStatus.Handling)
+                .WhereIF(!string.IsNullOrEmpty(dto.CreateUserName), d => d.User.Name.Contains(dto.CreateUserName!))
+                .WhereIF(!string.IsNullOrEmpty(dto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(dto.CreateBMName!))
+                .WhereIF(!string.IsNullOrEmpty(dto.ApplyType), d => d.KnowledgeApplyType.ToString() == dto.ApplyType)
+                .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "0", d => d.ExpiredTime < DateTime.Now)
+                .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "1", d => d.ExpiredTime >= DateTime.Now)
+                .WhereIF(dto.StartTime != null, d => d.CreationTime >= dto.StartTime)
+                .WhereIF(dto.EndTime != null, d => d.CreationTime <= dto.EndTime)
+                .OrderByDescending(p => p.CreationTime)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+            return new PagedDto<KnowledgeApplyPageDto>(total, _mapper.Map<IReadOnlyList<KnowledgeApplyPageDto>>(items));
+        }
+
+        /// <summary>
+        /// 申请处理--已完成
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("apply-endhandle")]
+        public async Task<PagedDto<KnowledgeApplyPageDto>> EndHandle([FromQuery] KnowledgeHandlePagedDto dto)
+        {
+            var (total, items) = await _knowledgeApplyRepository
+               .Queryable(false)
+               .Includes(it => it.User)
+               .Includes(it => it.SystemOrganize)
+               .Where(p => p.DepartmentCode == dto.DepartmentCode)
+               .Where(p => p.Status == EKnowledgeApplyStatus.Succeed)
+               .WhereIF(!string.IsNullOrEmpty(dto.CreateUserName), d => d.User.Name.Contains(dto.CreateUserName!))
+               .WhereIF(!string.IsNullOrEmpty(dto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(dto.CreateBMName!))
+               .WhereIF(!string.IsNullOrEmpty(dto.ApplyType), d => d.KnowledgeApplyType.ToString() == dto.ApplyType)
+               .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "0", d => d.ExpiredTime < DateTime.Now)
+               .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "1", d => d.ExpiredTime >= DateTime.Now)
+               .WhereIF(dto.StartTime != null, d => d.CreationTime >= dto.StartTime)
+               .WhereIF(dto.EndTime != null, d => d.CreationTime <= dto.EndTime)
+               .OrderByDescending(p => p.CreationTime)
+               .ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+            return new PagedDto<KnowledgeApplyPageDto>(total, _mapper.Map<IReadOnlyList<KnowledgeApplyPageDto>>(items));
+        }
+
+        /// <summary>
+        /// 申请处理--退回
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("apply-returnhandle")]
+        public async Task<PagedDto<KnowledgeApplyPageDto>> ReturnHandle([FromQuery] KnowledgeHandlePagedDto dto)
+        {
+            var (total, items) = await _knowledgeApplyRepository
+               .Queryable(false)
+               .Includes(it => it.User)
+               .Includes(it => it.SystemOrganize)
+               .Where(p => p.DepartmentCode == dto.DepartmentCode)
+               .Where(p => p.Status == EKnowledgeApplyStatus.Failed)
+               .WhereIF(!string.IsNullOrEmpty(dto.CreateUserName), d => d.User.Name.Contains(dto.CreateUserName!))
+               .WhereIF(!string.IsNullOrEmpty(dto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(dto.CreateBMName!))
+               .WhereIF(!string.IsNullOrEmpty(dto.ApplyType), d => d.KnowledgeApplyType.ToString() == dto.ApplyType)
+               .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "0", d => d.ExpiredTime < DateTime.Now)
+               .WhereIF(!string.IsNullOrEmpty(dto.IsOvertime) && dto.IsOvertime == "1", d => d.ExpiredTime >= DateTime.Now)
+               .WhereIF(dto.StartTime != null, d => d.CreationTime >= dto.StartTime)
+               .WhereIF(dto.EndTime != null, d => d.CreationTime <= dto.EndTime)
+               .OrderByDescending(p => p.CreationTime)
+               .ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+            return new PagedDto<KnowledgeApplyPageDto>(total, _mapper.Map<IReadOnlyList<KnowledgeApplyPageDto>>(items));
+
+        }
+        #endregion
+    }
+}

+ 277 - 0
src/Hotline.Api/Controllers/KnowledgeCommonController.cs

@@ -0,0 +1,277 @@
+using Hotline.KnowledgeBase;
+using Hotline.Share.Dtos.Knowledge;
+using MapsterMapper;
+using Microsoft.AspNetCore.Mvc;
+using XF.Domain.Exceptions;
+
+namespace Hotline.Api.Controllers
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class KnowledgeCommonController : BaseController
+    {
+        private readonly IKnowledgeTypeRepository _knowledgeTypeRepository;
+        private readonly IKnowledgeRepository _knowledgeRepository;
+        private readonly IKnowledgeTypeService _knowledgeTypeService;
+        private readonly IKnowledgeStandardRepository _knowledgeStandardRepository;
+        private readonly IMapper _mapper;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="knowledgeRepository"></param>
+        /// <param name="knowledgeTypeRepository"></param>
+        /// <param name="knowledgeTypeService"></param>
+        /// <param name="knowledgeStandardRepository"></param>
+        /// <param name="mapper"></param>
+        public KnowledgeCommonController(IKnowledgeRepository knowledgeRepository, IKnowledgeTypeRepository knowledgeTypeRepository, IKnowledgeTypeService knowledgeTypeService,
+            IKnowledgeStandardRepository knowledgeStandardRepository,
+            IMapper mapper)
+        {
+            _knowledgeRepository = knowledgeRepository;
+            _knowledgeTypeRepository = knowledgeTypeRepository;
+            _knowledgeTypeService = knowledgeTypeService;
+            _knowledgeStandardRepository = knowledgeStandardRepository;
+            _mapper = mapper;
+        }
+
+        #region 知识分类
+
+        /// <summary>
+        ///知识分类- 新增
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("type-add")]
+        public async Task<string> TypeAdd([FromBody] AddKnowledgeTypeDto dto)
+        {
+            var type = _mapper.Map<KnowledgeType>(dto);
+            type.CreationTime = DateTime.Now;
+            type.IsEnable = true;
+            string FullName = await _knowledgeTypeService.GetFullName(type.ParentId);
+            type.SpliceName = string.IsNullOrEmpty(FullName) ? dto.Name : FullName + "-" + dto.Name;
+            return await _knowledgeTypeRepository.AddAsync(type);
+        }
+
+        /// <summary>
+        ///知识分类- 编辑
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("type-update")]
+        public async Task TypeUpdate([FromBody] UpdateKnowledgeTypeDto dto)
+        {
+            //查询原有数据
+            var type = await _knowledgeTypeRepository.GetAsync(dto.Id);
+            if (type is null)
+                throw UserFriendlyException.SameMessage("编辑失败!");
+
+            bool result = false;
+            //是否更改分类名称
+            if (type.Name != dto.Name)
+                result = true;
+            //转换
+            _mapper.Map(dto, type);
+            //如果更改了名称,则修改全程,为更改不修改
+            if (result)
+            {
+                string FullName = await _knowledgeTypeService.GetFullName(type.ParentId);
+                type.SpliceName = string.IsNullOrEmpty(FullName) ? dto.Name : FullName + "-" + dto.Name;
+            }
+            //修改数据
+            await _knowledgeTypeRepository.UpdateAsync(type);
+            //如果修改了名称,对应修改子分类全称
+            if (result)
+                await _knowledgeTypeService.UpdateChildNode(type.Id);
+        }
+
+        /// <summary>
+        /// 知识分类-新增、编辑初始化
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <param name="ParentId"></param>
+        /// <returns></returns>
+        [HttpGet("type-init")]
+        public async Task<KnowledgeTypeDto> TypeInit(string Id, string ParentId)
+        {
+            KnowledgeTypeDto knowledgeTypeDto = new();
+            if (!string.IsNullOrEmpty(Id))
+            {
+                var type = await _knowledgeTypeRepository.GetAsync(p => p.Id == Id);
+                _mapper.Map(type, knowledgeTypeDto);
+            }
+            var list = await _knowledgeTypeRepository.QueryAsync(p => p.IsEnable == true);
+            if (!string.IsNullOrEmpty(ParentId) && ParentId != Guid.Empty.ToString())
+            {
+                knowledgeTypeDto.TreeLists = _knowledgeTypeService.GetChildren(list, Guid.Empty.ToString(), ParentId);
+            }
+            else
+            {
+                knowledgeTypeDto.TreeLists = _knowledgeTypeService.GetChildren(list, Guid.Empty.ToString(), "");
+            }
+            return knowledgeTypeDto;
+        }
+
+        /// <summary>
+        /// 知识分类-查询详情
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpGet("type-info")]
+        public async Task<KnowledgeType> TypeInfo(string Id)
+        {
+            var types = await _knowledgeTypeRepository.GetAsync(Id);
+            if (types is null)
+                throw UserFriendlyException.SameMessage("查询失败!");
+            return types;
+        }
+
+        /// <summary>
+        /// 知识分类-删除
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpDelete("type-delete")]
+        public async Task TypeDelete(string Id)
+        {
+            //查询数据是否存在
+            var sandard = await _knowledgeTypeRepository.GetAsync(Id);
+            if (sandard is null)
+                throw UserFriendlyException.SameMessage("分类不存在!");
+
+            //查询是否有子级分类
+
+            var checkChild = await _knowledgeTypeRepository.CountAsync(p => p.ParentId == Id);
+            if (checkChild > 0)
+                throw UserFriendlyException.SameMessage("存在子级分类!");
+
+            //查询是否有知识分类
+            var checkKnowledge = await _knowledgeRepository.CountAsync(p => p.KnowledgeTypeId == Id);
+            if (checkKnowledge > 0)
+                throw UserFriendlyException.SameMessage("分类存在知识!");
+
+            //删除操作
+            await _knowledgeTypeRepository.RemoveAsync(sandard, true);
+
+        }
+
+        /// <summary>
+        /// 知识分类-启用、禁用切换
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpGet("type-changestate")]
+        public async Task TypeChangeState(string Id)
+        {
+            //查询数据是否存在
+            var type = await _knowledgeTypeRepository.GetAsync(Id);
+            if (type is null)
+                throw UserFriendlyException.SameMessage("分类不存在!");
+            if (type.IsEnable)//禁用
+            {
+                //查询是否有子级,如果有子级启用,则不能禁用
+                var checkChild = await _knowledgeTypeRepository.CountAsync(p => p.ParentId == Id && p.IsEnable == true);
+                if (checkChild > 0)
+                    throw UserFriendlyException.SameMessage("请先禁用子级分类!");
+                type.IsEnable = false;
+            }
+            else //启用
+            {
+                //查询上级是否是启用状态,如果是禁用状态不能修改
+                var CheckParent = await _knowledgeTypeRepository.GetAsync(type.ParentId);
+                if (CheckParent is null)
+                    throw UserFriendlyException.SameMessage("分类启用失败!");
+                if (!CheckParent.IsEnable)
+                    throw UserFriendlyException.SameMessage("请先启用父级分类!");
+
+                //将状态修改为启用
+                type.IsEnable = true;
+            }
+            await _knowledgeTypeRepository.UpdateAsync(type);
+        }
+
+        /// <summary>
+        ///知识分类- 获取层级分类
+        /// </summary>
+        /// <param name="IsAll">如果为true查询全部分类,包括禁用的;如果false查询启用的分类</param>
+        /// <returns></returns>
+        [HttpPost("type-treelist")]
+        public async Task<List<TreeListDto>> GetTreeList(bool IsAll)
+        {
+            List<KnowledgeType> typeList;
+            if (IsAll)//查询全部
+            {
+                typeList = await _knowledgeTypeRepository.QueryAsync();
+            }
+            else//查询启用的
+            {
+                typeList = await _knowledgeTypeRepository.QueryAsync(p => p.IsEnable == true);
+            }
+
+            return _knowledgeTypeService.GetChildren(typeList, Guid.Empty.ToString(), "");
+        }
+
+        #endregion
+
+        #region 编写规范
+        /// <summary>
+        /// 编写规范-查询详情
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpGet("standard-info")]
+        public async Task<KnowledgeStandard> StandardInfo(string Id)
+        {
+            if (string.IsNullOrEmpty(Id))
+                throw UserFriendlyException.SameMessage("ID不能为空!");
+
+            var sandard = await _knowledgeStandardRepository.GetAsync(Id);
+            if (sandard is null)
+                throw UserFriendlyException.SameMessage("编写规范查询失败!");
+            return sandard;
+        }
+
+        /// <summary>
+        /// 编写规范-删除
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpDelete("standard-delete")]
+        public async Task StandardDelete(string Id)
+        {
+            if (string.IsNullOrEmpty(Id))
+                throw UserFriendlyException.SameMessage("ID不能为空!");
+            //删除操作
+            await _knowledgeStandardRepository.RemoveAsync(Id);
+
+        }
+
+        /// <summary>
+        /// 编写规范-新增
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("standard-add")]
+        public async Task StandardAdd([FromBody] AddKnowledgeStandardDto dto)
+        {
+            var sandard = _mapper.Map<KnowledgeStandard>(dto);
+            sandard.CreationTime = DateTime.Now;
+            await _knowledgeStandardRepository.AddAsync(sandard);
+        }
+
+        /// <summary>
+        /// 编写规范-编辑
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("standard-update")]
+        public async Task StandardUpdate([FromBody] UpdateKnowledgeStandardDto dto)
+        {
+            var sandard = _mapper.Map<KnowledgeStandard>(dto);
+            await _knowledgeStandardRepository.UpdateAsync(sandard);
+        }
+        #endregion
+
+    }
+}

+ 413 - 0
src/Hotline.Api/Controllers/KnowledgeController.cs

@@ -0,0 +1,413 @@
+using Hotline.KnowledgeBase;
+using Hotline.Repository.SqlSugar;
+using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.Knowledge;
+using Hotline.Share.Enums.KnowledgeBase;
+using Identity.Shared.Dtos;
+using MapsterMapper;
+using Microsoft.AspNetCore.Mvc;
+using XF.Domain.Exceptions;
+
+namespace Hotline.Api.Controllers
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class KnowledgeController : BaseController
+    {
+        private readonly IKnowledgeRepository _knowledgeRepository;
+        private readonly IKnowledgeTempRepository _knowledgeTempRepository;
+        private readonly IKnowledgePVRepository _knowledgePVRepository;
+        private readonly IMapper _mapper;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="knowledgeRepository"></param>
+        /// <param name="knowledgeTempRepository"></param>
+        /// <param name="knowledgePVRepository"></param>
+        /// <param name="mapper"></param>
+        public KnowledgeController(IKnowledgeRepository knowledgeRepository, IKnowledgeTempRepository knowledgeTempRepository, IKnowledgePVRepository knowledgePVRepository, IMapper mapper)
+        {
+            _knowledgeRepository = knowledgeRepository;
+            _knowledgeTempRepository = knowledgeTempRepository;
+            _knowledgePVRepository = knowledgePVRepository;
+            _mapper = mapper;
+        }
+
+        /// <summary>
+        /// 草稿箱-新增
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledgetemp-add")]
+        public async Task<string> KnowledgeTempAdd([FromBody] KnowledgeDto dto)
+        {
+            var kn = _mapper.Map<KnowledgeTemp>(dto);
+            kn.Code = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds).ToString();
+            kn.PageView = 0;
+            kn.CreationTime = DateTime.Now;
+            return await _knowledgeTempRepository.AddAsync(kn);
+        }
+
+        /// <summary>
+        /// 草稿箱-修改
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledgetemp-update")]
+        public async Task KnowledgeTempUpdate([FromBody] UpdateKnowledgeDto dto)
+        {
+            var kn = _mapper.Map<KnowledgeTemp>(dto);
+            await _knowledgeTempRepository.UpdateAsync(kn);
+        }
+
+        /// <summary>
+        /// 草稿箱-查询详情
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpGet("knowledgetemp-info")]
+        public async Task<KnowledgeTemp> KnowledgeTempInfo(string Id)
+        {
+            var temp = await _knowledgeTempRepository.GetAsync(Id);
+            if (temp is null)
+                throw UserFriendlyException.SameMessage("知识草稿查询失败!");
+            return temp;
+        }
+
+        /// <summary>
+        /// 知识库-知识修改-查询详情
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpGet("knowledge-updateinfo")]
+        public async Task<Knowledge> KnowledgeUpdateInfo(string Id)
+        {
+            var know = await _knowledgeRepository.GetAsync(Id);
+            if (know is null)
+                throw UserFriendlyException.SameMessage("知识查询失败!");
+            return know;
+        }
+
+        /// <summary>
+        /// 知识库-查询详情
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpGet("knowledge-info")]
+        public async Task<Knowledge> KnowledgeInfo(string Id)
+        {
+            var know = await _knowledgeRepository.GetAsync(Id);
+            if (know is null)
+                throw UserFriendlyException.SameMessage("知识查询失败!");
+            //写入浏览记录
+            KnowledgePv knowledgePV = new()
+            {
+                CreationTime = DateTime.Now,
+                KnowledgeId = know.Id
+            };
+            await _knowledgePVRepository.AddAsync(knowledgePV);
+            return know;
+        }
+
+        /// <summary>
+        /// 知识库-新增
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-add")]
+        public async Task<string> KnowledgeAdd([FromBody] AddKnowledgeDto dto)
+        {
+            var kn = _mapper.Map<Knowledge>(dto);
+            if (string.IsNullOrEmpty(kn.Code))
+                kn.Code = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds).ToString();
+            kn.PageView = 0;
+            kn.CreationTime = DateTime.Now;
+            kn.Status = EKnowledgeStatus.Auditing;
+            return await _knowledgeRepository.AddAsync(kn);
+        }
+
+        /// <summary>
+        /// 知识库-修改
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-update")]
+        public async Task KnowledgeUpdate([FromBody] UpdateKnowledgeDto dto)
+        {
+            var know = await _knowledgeRepository.GetAsync(dto.Id);
+            if (know is null || know.IsDeleted)
+                throw UserFriendlyException.SameMessage("无效知识编号");
+            _mapper.Map(dto, know);
+            await _knowledgeRepository.UpdateAsync(know);
+        }
+
+        #region 知识列表
+        /// <summary>
+        /// 我的草稿箱
+        /// </summary>
+        /// <param name="pagedDto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-mydraftslist")]
+        public async Task<PagedDto<KnowledgeDataDto>> MyDraftsList([FromBody] MyDraftsListPagedDto pagedDto)
+        {
+            var (total, items) = await _knowledgeTempRepository
+             .Queryable()
+             .Includes(it => it.User)
+             .Includes(it => it.KnowledgeType)
+             .Where(p => p.CreateUserId == pagedDto.CreateUserId)
+             .WhereIF(!string.IsNullOrEmpty(pagedDto.Title), d => d.Title.Contains(pagedDto.Title!))
+             .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);
+
+            return new PagedDto<KnowledgeDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeDataDto>>(items));
+        }
+
+        /// <summary>
+        /// 全部知识
+        /// </summary>
+        /// <param name="pagedDto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-alllist")]
+        public async Task<PagedDto<KnowledgeDataDto>> AllList([FromBody] KnowledgePagedListDto pagedDto)
+        {
+            var (total, items) = await _knowledgeRepository
+              .Queryable()
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Includes(it => it.KnowledgeType)
+              .Where(p => p.IsDeleted == false)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateUserName), d => d.User.Name.Contains(pagedDto.CreateUserName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(pagedDto.CreateBMName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.Title), d => d.Title.Contains(pagedDto.Title!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.KnowledgeTypeId), d => d.KnowledgeTypeId == pagedDto.KnowledgeTypeId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.HotspotId), d => d.HotspotId == pagedDto.HotspotId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMCode), d => d.AutoOrgCode == pagedDto.CreateBMCode)
+              .WhereIF(pagedDto.StartTime != null, d => d.OnShelfTime >= pagedDto.StartTime)
+              .WhereIF(pagedDto.EndTime != null, d => d.OnShelfTime <= pagedDto.EndTime)
+              .OrderByDescending(p => p.CreationTime)
+              .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize);
+
+            return new PagedDto<KnowledgeDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeDataDto>>(items));
+        }
+
+        /// <summary>
+        /// 已上架
+        /// </summary>
+        /// <param name="pagedDto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-ontheshelf")]
+        public async Task<PagedDto<KnowledgeDataDto>> OnTheShelf([FromBody] KnowledgePagedListDto pagedDto)
+        {
+            var (total, items) = await _knowledgeRepository
+              .Queryable()
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Includes(it => it.KnowledgeType)
+              .Where(p => p.IsOnShelf == true && p.Status == EKnowledgeStatus.Succeed && p.IsDeleted == false)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateUserName), d => d.User.Name.Contains(pagedDto.CreateUserName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(pagedDto.CreateBMName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.Title), d => d.Title.Contains(pagedDto.Title!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.KnowledgeTypeId), d => d.KnowledgeTypeId == pagedDto.KnowledgeTypeId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.HotspotId), d => d.HotspotId == pagedDto.HotspotId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMCode), d => d.AutoOrgCode == pagedDto.CreateBMCode)
+              .WhereIF(pagedDto.StartTime != null, d => d.OnShelfTime >= pagedDto.StartTime)
+              .WhereIF(pagedDto.EndTime != null, d => d.OnShelfTime <= pagedDto.EndTime)
+              .OrderByDescending(p => p.CreationTime)
+              .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize);
+
+            return new PagedDto<KnowledgeDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeDataDto>>(items));
+        }
+
+        /// <summary>
+        /// 已下架
+        /// </summary>
+        /// <param name="pagedDto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-offshelf")]
+        public async Task<PagedDto<KnowledgeDataDto>> OffShelf([FromBody] KnowledgePagedListDto pagedDto)
+        {
+            var (total, items) = await _knowledgeRepository
+              .Queryable()
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Includes(it => it.KnowledgeType)
+              .Where(p => p.IsOnShelf == false && p.Status == EKnowledgeStatus.Succeed && p.IsDeleted == false)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateUserName), d => d.User.Name.Contains(pagedDto.CreateUserName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(pagedDto.CreateBMName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.Title), d => d.Title.Contains(pagedDto.Title!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.KnowledgeTypeId), d => d.KnowledgeTypeId == pagedDto.KnowledgeTypeId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.HotspotId), d => d.HotspotId == pagedDto.HotspotId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMCode), d => d.AutoOrgCode == pagedDto.CreateBMCode)
+              .WhereIF(pagedDto.StartTime != null, d => d.OffShelfTime >= pagedDto.StartTime)
+              .WhereIF(pagedDto.EndTime != null, d => d.OffShelfTime <= pagedDto.EndTime)
+              .OrderByDescending(p => p.CreationTime)
+              .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize);
+
+            return new PagedDto<KnowledgeDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeDataDto>>(items));
+        }
+
+        /// <summary>
+        /// 审批中
+        /// </summary>
+        /// <param name="pagedDto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-underapproval")]
+        public async Task<PagedDto<KnowledgeDataDto>> UnderApproval([FromBody] KnowledgePagedListDto pagedDto)
+        {
+            var (total, items) = await _knowledgeRepository
+              .Queryable()
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Includes(it => it.KnowledgeType)
+              .Where(p => p.Status == EKnowledgeStatus.Auditing && p.IsDeleted == false)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateUserName), d => d.User.Name.Contains(pagedDto.CreateUserName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(pagedDto.CreateBMName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.Title), d => d.Title.Contains(pagedDto.Title!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.KnowledgeTypeId), d => d.KnowledgeTypeId == pagedDto.KnowledgeTypeId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.HotspotId), d => d.HotspotId == pagedDto.HotspotId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMCode), d => d.AutoOrgCode == pagedDto.CreateBMCode)
+              .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);
+
+            return new PagedDto<KnowledgeDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeDataDto>>(items));
+        }
+
+        /// <summary>
+        /// 审批完成
+        /// </summary>
+        /// <param name="pagedDto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-approved")]
+        public async Task<PagedDto<KnowledgeDataDto>> Approved([FromBody] KnowledgePagedListDto pagedDto)
+        {
+            var (total, items) = await _knowledgeRepository
+              .Queryable()
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Includes(it => it.KnowledgeType)
+              .Where(p => p.Status == EKnowledgeStatus.Succeed && p.IsDeleted == false)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateUserName), d => d.User.Name.Contains(pagedDto.CreateUserName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(pagedDto.CreateBMName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.Title), d => d.Title.Contains(pagedDto.Title!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.KnowledgeTypeId), d => d.KnowledgeTypeId == pagedDto.KnowledgeTypeId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.HotspotId), d => d.HotspotId == pagedDto.HotspotId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMCode), d => d.AutoOrgCode == pagedDto.CreateBMCode)
+              .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);
+
+            return new PagedDto<KnowledgeDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeDataDto>>(items));
+        }
+
+        /// <summary>
+        /// 审批不通过
+        /// </summary>
+        /// <param name="pagedDto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-approvalfailed")]
+        public async Task<PagedDto<KnowledgeDataDto>> ApprovalFailed([FromBody] KnowledgePagedListDto pagedDto)
+        {
+            var (total, items) = await _knowledgeRepository
+              .Queryable()
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Includes(it => it.KnowledgeType)
+              .Where(p => p.Status == EKnowledgeStatus.Failed && p.IsDeleted == false)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateUserName), d => d.User.Name.Contains(pagedDto.CreateUserName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(pagedDto.CreateBMName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.Title), d => d.Title.Contains(pagedDto.Title!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.KnowledgeTypeId), d => d.KnowledgeTypeId == pagedDto.KnowledgeTypeId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.HotspotId), d => d.HotspotId == pagedDto.HotspotId)
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMCode), d => d.AutoOrgCode == pagedDto.CreateBMCode)
+              .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);
+
+            return new PagedDto<KnowledgeDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeDataDto>>(items));
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 待审核
+        /// </summary>
+        /// <param name="pagedDto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-tobereviewed")]
+        public async Task<PagedDto<KnowledgeApprovalDataDto>> ToBeReviewed([FromBody] KnowledgeApprovalPagedListDto pagedDto)
+        {
+            var (total, items) = await _knowledgeRepository
+              .Queryable()
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Includes(it => it.KnowledgeType)
+              .Where(p => p.IsDeleted == false&&p.Status== EKnowledgeStatus.Auditing&&p.AssignUserIds.Contains(pagedDto.UserId!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateUserName), d => d.User.Name.Contains(pagedDto.CreateUserName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(pagedDto.CreateBMName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.Title), d => d.Title.Contains(pagedDto.Title!))
+
+              .OrderByDescending(p => p.CreationTime)
+              .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize);
+
+            return new PagedDto<KnowledgeApprovalDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeApprovalDataDto>>(items));
+        }
+
+        /// <summary>
+        /// 审核通过
+        /// </summary>
+        /// <param name="pagedDto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-approvedlist")]
+        public async Task<PagedDto<KnowledgeApprovalDataDto>> ApprovedList([FromBody] KnowledgeApprovalPagedListDto pagedDto)
+        {
+            var (total, items) = await _knowledgeRepository
+              .Queryable()
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Includes(it => it.KnowledgeType)
+              .Where(p => p.IsDeleted == false && p.Status == EKnowledgeStatus.Succeed && p.AssignUserIds.Contains(pagedDto.UserId!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateUserName), d => d.User.Name.Contains(pagedDto.CreateUserName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(pagedDto.CreateBMName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.Title), d => d.Title.Contains(pagedDto.Title!))
+
+              .OrderByDescending(p => p.CreationTime)
+              .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize);
+
+            return new PagedDto<KnowledgeApprovalDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeApprovalDataDto>>(items));
+        }
+
+        /// <summary>
+        /// 审核不通过
+        /// </summary>
+        /// <param name="pagedDto"></param>
+        /// <returns></returns>
+        [HttpPost("knowledge-approvedfailedlist")]
+        public async Task<PagedDto<KnowledgeApprovalDataDto>> ApprovedFailedList([FromBody] KnowledgeApprovalPagedListDto pagedDto)
+        {
+            var (total, items) = await _knowledgeRepository
+              .Queryable()
+              .Includes(it => it.User)
+              .Includes(it => it.SystemOrganize)
+              .Includes(it => it.KnowledgeType)
+              .Where(p => p.IsDeleted == false && p.Status == EKnowledgeStatus.Failed && p.AssignUserIds.Contains(pagedDto.UserId!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateUserName), d => d.User.Name.Contains(pagedDto.CreateUserName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.CreateBMName), d => d.SystemOrganize.OrgName.Contains(pagedDto.CreateBMName!))
+              .WhereIF(!string.IsNullOrEmpty(pagedDto.Title), d => d.Title.Contains(pagedDto.Title!))
+
+              .OrderByDescending(p => p.CreationTime)
+              .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize);
+
+            return new PagedDto<KnowledgeApprovalDataDto>(total, _mapper.Map<IReadOnlyList<KnowledgeApprovalDataDto>>(items));
+        }
+
+    }
+}

+ 1 - 2
src/Hotline.Api/Controllers/ReportController.cs

@@ -1,5 +1,4 @@
-using Hotline.CallCenter;
-using Hotline.CallCenter.Devices;
+using Hotline.CallCenter.Devices;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
 

+ 105 - 99
src/Hotline.Api/Controllers/TestController.cs

@@ -1,10 +1,12 @@
-using Dapr;
+using Conductor.Client;
+using Conductor.Domain.Models;
+using Dapr;
 using Hotline.CallCenter.BlackLists;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Ivrs;
-using Hotline.FlowEngine.Definitions;
 using Hotline.Realtimes;
 using Hotline.Repository.SqlSugar;
+using Hotline.Settings;
 using Hotline.Share.Dtos.Realtime;
 using Hotline.Users;
 using Microsoft.AspNetCore.Authorization;
@@ -18,68 +20,71 @@ using XF.Domain.Cache;
 using XF.Domain.Entities;
 using XF.Domain.Exceptions;
 
-namespace Hotline.Api.Controllers;
-
-/// <summary>
-/// 
-/// </summary>
-public class TestController : BaseController
+namespace Hotline.Api.Controllers
 {
-    private readonly ILogger<TestController> _logger;
-    private readonly IAuthorizeGenerator _authorizeGenerator;
-    private readonly IOptionsSnapshot<DeviceConfigs> _options;
-    private readonly ISessionContext _sessionContext;
-    private readonly IUserRepository _userRepository;
-
-    private readonly ITypedCache<User> _cache;
-    private readonly IRealtimeService _realtimeService;
-    private readonly IBlacklistDomainService _blacklistDomainService;
-    private readonly IIvrDomainService _ivrDomainService;
-    private readonly ISugarUnitOfWork<HotlineDbContext> _uow;
-
-    //private readonly ITypedCache<List<User>> _cache;
-    //private readonly ICacheManager<User> _cache;
-
     /// <summary>
     /// 
     /// </summary>
-    /// <param name="client"></param>
-    /// <param name="logger"></param>
-    /// <param name="authorizeGenerator"></param>
-    /// <param name="options"></param>
-    /// <param name="sessionContext"></param>
-    /// <param name="userRepository"></param>
-    /// <param name="cache"></param>
-    /// <param name="realtimeService"></param>
-    /// <param name="blacklistDomainService"></param>
-    /// <param name="ivrDomainService"></param>
-    public TestController(
-        INewRockClient client,
-        ILogger<TestController> logger,
-        IAuthorizeGenerator authorizeGenerator,
-        IOptionsSnapshot<DeviceConfigs> options,
-        ISessionContext sessionContext,
-        IUserRepository userRepository,
-        //ICacheManager<User> cache
-        //ITypedCache<List<User>> cache
-        ITypedCache<User> cache,
-        IRealtimeService realtimeService,
-        IBlacklistDomainService blacklistDomainService,
-        IIvrDomainService ivrDomainService,
-        ISugarUnitOfWork<HotlineDbContext> uow
-    )
+    public class TestController : BaseController
     {
-        _logger = logger;
-        _authorizeGenerator = authorizeGenerator;
-        _options = options;
-        _sessionContext = sessionContext;
-        _userRepository = userRepository;
-        _cache = cache;
-        _realtimeService = realtimeService;
-        _blacklistDomainService = blacklistDomainService;
-        _ivrDomainService = ivrDomainService;
-        _uow = uow;
-    }
+        private readonly ILogger<TestController> _logger;
+        private readonly IAuthorizeGenerator _authorizeGenerator;
+        private readonly IOptionsSnapshot<DeviceConfigs> _options;
+        private readonly ISessionContext _sessionContext;
+        private readonly IUserRepository _userRepository;
+
+        private readonly ITypedCache<User> _cache;
+        private readonly IRealtimeService _realtimeService;
+        private readonly IBlacklistDomainService _blacklistDomainService;
+        private readonly IIvrDomainService _ivrDomainService;
+        private readonly ISugarUnitOfWork<HotlineDbContext> _uow;
+        private readonly IWorkflowRemotingService _workflowRemotingService;
+
+        //private readonly ITypedCache<List<User>> _cache;
+        //private readonly ICacheManager<User> _cache;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="client"></param>
+        /// <param name="logger"></param>
+        /// <param name="authorizeGenerator"></param>
+        /// <param name="options"></param>
+        /// <param name="sessionContext"></param>
+        /// <param name="userRepository"></param>
+        /// <param name="cache"></param>
+        /// <param name="realtimeService"></param>
+        /// <param name="blacklistDomainService"></param>
+        /// <param name="ivrDomainService"></param>
+        public TestController(
+            INewRockClient client,
+            ILogger<TestController> logger,
+            IAuthorizeGenerator authorizeGenerator,
+            IOptionsSnapshot<DeviceConfigs> options,
+            ISessionContext sessionContext,
+            IUserRepository userRepository,
+            //ICacheManager<User> cache
+            //ITypedCache<List<User>> cache
+            ITypedCache<User> cache,
+            IRealtimeService realtimeService,
+            IBlacklistDomainService blacklistDomainService,
+            IIvrDomainService ivrDomainService,
+            ISugarUnitOfWork<HotlineDbContext> uow,
+            IWorkflowRemotingService workflowRemotingService
+            )
+        {
+            _logger = logger;
+            _authorizeGenerator = authorizeGenerator;
+            _options = options;
+            _sessionContext = sessionContext;
+            _userRepository = userRepository;
+            _cache = cache;
+            _realtimeService = realtimeService;
+            _blacklistDomainService = blacklistDomainService;
+            _ivrDomainService = ivrDomainService;
+            _uow = uow;
+            _workflowRemotingService = workflowRemotingService;
+        }
 
 
         /// <summary>
@@ -112,50 +117,51 @@ public class TestController : BaseController
             await _realtimeService.ByeAsync(_sessionContext.RequiredUserId, new ByeDto() { Id = new Guid().ToString() }, HttpContext.RequestAborted);
         }
 
-    /// <summary>
-    /// 
-    /// </summary>
-    /// <returns></returns>
-    [AllowAnonymous]
-    [HttpGet("t2")]
-    public async Task GetVoiceEndAnswerAsyncTest()
-    {
-        //var answer = await _ivrDomainService.GetVoiceEndAnswerAsync("3", HttpContext.RequestAborted);
-        //Console.WriteLine(answer.Content);
-        throw new UserFriendlyException(2001, "test");
-    }
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("t2")]
+        public async Task GetVoiceEndAnswerAsyncTest()
+        {
+            //var answer = await _ivrDomainService.GetVoiceEndAnswerAsync("3", HttpContext.RequestAborted);
+            //Console.WriteLine(answer.Content);
+            throw new UserFriendlyException(2001, "test");
+        }
 
-    [AllowAnonymous]
-    [HttpGet("wfdefine")]
-    public async Task<IReadOnlyList<Definition>> GetWorkflowDefine()
-    {
-        throw new NotImplementedException();
-    }
+        [AllowAnonymous]
+        [HttpGet("wfdefine")]
+        public async Task<IReadOnlyList<Definition>> GetWorkflowDefine()
+        {
+            var a = await _workflowRemotingService.QueryDefinitionAsync(HttpContext.RequestAborted);
+            return a.Result;
+        }
 
-    [ApiExplorerSettings(IgnoreApi = true)]
-    [AllowAnonymous]
-    [HttpGet("cdb")]
-    public Task CreateTableMultiple()
-    {
-        var db = _uow.Db;
-        db.DbMaintenance.CreateDatabase();
+        
+        [AllowAnonymous]
+        [HttpGet("cdb")]
+        public Task CreateTableMultiple()
+        {
+            var db = _uow.Db;
+            db.DbMaintenance.CreateDatabase();
 
-        var types = typeof(User).Assembly.GetTypes()
-            .Where(d => d.GetInterfaces().Any(x => x == typeof(IEntity)))
-            .Distinct()
-            .ToArray();
+            var types = typeof(User).Assembly.GetTypes()
+                .Where(d => d.GetInterfaces().Any(x => x == typeof(IEntity)))
+                .ToArray();
 
-        db.CodeFirst.InitTables(types);//根据types创建表
+            db.CodeFirst.InitTables(types);//根据types创建表
 
-        return Task.CompletedTask;
-    }
+            return Task.CompletedTask;
+        }
 
-    [AllowAnonymous]
-    [Topic("pubsub", "test")]
-    [HttpPost("t3")]
-    public Task<int> TestDaprPubsub(int data)
-    {
-        _logger.LogDebug("receive dapr event, params: {0}", data);
-        return Task.FromResult(data);
+        [AllowAnonymous]
+        [Topic("pubsub", "test")]
+        [HttpPost("t3")]
+        public Task<int> TestDaprPubsub(int data)
+        {
+            _logger.LogDebug("receive dapr event, params: {0}", data);
+            return Task.FromResult(data);
+        }
     }
-}
+}

+ 49 - 84
src/Hotline.Api/Controllers/WorkflowController.cs

@@ -1,14 +1,10 @@
-using Hotline.FlowEngine.Definitions;
-using Hotline.Repository.SqlSugar;
+using Conductor.Client;
+using Conductor.Domain.Models;
 using Hotline.Share.Dtos;
-using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Workflow;
-using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Requests;
 using MapsterMapper;
-using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
-using SqlSugar;
 using XF.Domain.Exceptions;
 
 namespace Hotline.Api.Controllers;
@@ -18,17 +14,14 @@ namespace Hotline.Api.Controllers;
 /// </summary>
 public class WorkflowController : BaseController
 {
-    private readonly IDefinitionDomainService _definitionDomainService;
-    private readonly IDefinitionRepository _definitionRepository;
+    private readonly IWorkflowRemotingService _workflowRemotingService;
     private readonly IMapper _mapper;
 
     public WorkflowController(
-        IDefinitionDomainService definitionDomainService,
-        IDefinitionRepository definitionRepository,
+        IWorkflowRemotingService workflowRemotingService,
         IMapper mapper)
     {
-        _definitionDomainService = definitionDomainService;
-        _definitionRepository = definitionRepository;
+        _workflowRemotingService = workflowRemotingService;
         _mapper = mapper;
     }
 
@@ -38,19 +31,23 @@ public class WorkflowController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpGet("definition")]
-    public async Task<PagedDto<DefinitionDto>> QueryDefinitions([FromQuery] PagedRequest dto)
+    public async Task<PagedDto<WorkflowDefinitionDto>> QueryDefinitions([FromQuery] PagedRequest dto)
     {
-        var result = await _definitionRepository.Queryable()
-            .Where(d => d.Status == EDefinitionStatus.Temporary)
-            .MergeTable()
-            .Where(d => d.Status != EDefinitionStatus.Temporary)
-            .GroupBy(d => d.Code)
-            .OrderByDescending(d => d.Version)
-            .Take(1)
-            .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+        var presRsp = await _workflowRemotingService.QueryPreDefinitionAsync(HttpContext.RequestAborted);
+        if (!presRsp.IsSuccess)
+            throw new UserFriendlyException(presRsp.Error ?? string.Empty, "流程模板草稿查询失败");
+        var definesRsp = await _workflowRemotingService.QueryDefinitionAsync(HttpContext.RequestAborted);
+        if (!definesRsp.IsSuccess)
+            throw new UserFriendlyException(definesRsp.Error ?? string.Empty, "流程模板查询失败");
+        var dtos = _mapper.Map<List<WorkflowDefinitionDto>>(presRsp.Result);
+        dtos.AddRange(_mapper.Map<List<WorkflowDefinitionDto>>(definesRsp.Result));
+        var items = dtos.OrderByDescending(d => d.IsPreDefinition)
+            .ThenByDescending(d => d.Id)
+            .Skip(dto.Skip())
+            .Take(dto.PageSize)
+            .ToList();
 
-        var items = _mapper.Map<IReadOnlyList<DefinitionDto>>(result.Items);
-        return new PagedDto<DefinitionDto>(result.Total, items);
+        return new PagedDto<WorkflowDefinitionDto>(dtos.Count, items);
     }
 
     /// <summary>
@@ -58,11 +55,13 @@ public class WorkflowController : BaseController
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
-    [HttpPost("definition")]
-    public async Task<string> AddDefinition([FromBody] AddDefinitionDto dto)
+    /// <exception cref="UserFriendlyException"></exception>
+    [HttpPost("predefinition")]
+    public async Task<string> AddPreDefinition([FromBody] PreDefinition dto)
     {
-        var definition = _mapper.Map<Definition>(dto);
-        return await _definitionRepository.AddAsync(definition, HttpContext.RequestAborted);
+        var addPreRsp = await _workflowRemotingService.AddPreDefinitionAsync(dto, HttpContext.RequestAborted);
+        if (!addPreRsp.IsSuccess) throw new UserFriendlyException(addPreRsp.Error ?? string.Empty, "新增流程模板草稿失败");
+        return addPreRsp.Result;
     }
 
     /// <summary>
@@ -70,94 +69,60 @@ public class WorkflowController : BaseController
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
-    [HttpPut("definition")]
-    public async Task UpdateDefinition([FromBody] UpdateDefinitionDto dto)
-    {
-        var definition = await _definitionRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
-        if (definition == null)
-            throw UserFriendlyException.SameMessage("无效模板编号");
-        if (definition.Status == EDefinitionStatus.Temporary)
-        {
-            _mapper.Map(dto, definition);
-            await _definitionRepository.UpdateAsync(definition, HttpContext.RequestAborted);
-        }
-        else
-        {
-            var newDefinition = _mapper.Map<Definition>(definition);
-            _mapper.Map(dto, newDefinition);
-            await _definitionRepository.AddAsync(newDefinition, HttpContext.RequestAborted);
-        }
-    }
-
-    [HttpDelete("definition/{id}")]
-    public async Task RemoveDefinition(string id)
+    /// <exception cref="UserFriendlyException"></exception>
+    [HttpPut("predefinition")]
+    public async Task UpdatePreDefinition([FromBody] PreDefinition dto)
     {
-        var definition = await _definitionRepository.GetAsync(id, HttpContext.RequestAborted);
-        if (definition == null) return;
-        if (definition.Status != EDefinitionStatus.Temporary)
-            throw new UserFriendlyException("已发布模板不能删除");
-        await _definitionRepository.RemoveAsync(id, false, HttpContext.RequestAborted);
+        var updatePreRsp = await _workflowRemotingService.UpdatePreDefinitionAsync(dto, HttpContext.RequestAborted);
+        if (!updatePreRsp.IsSuccess) throw new UserFriendlyException(updatePreRsp.Error ?? string.Empty, "更新流程模板草稿失败");
     }
 
     /// <summary>
     /// 发布(将草稿发布为正式模板)
     /// </summary>
     /// <returns></returns>
-    [HttpPost("definition/{id}/publish")]
+    [HttpPost("publish/{id}")]
     public async Task Publish(string id)
     {
-        await _definitionDomainService.PublishAsync(id, HttpContext.RequestAborted);
+        var pubRsp = await _workflowRemotingService.PublishAsync(id, HttpContext.RequestAborted);
+        if (!pubRsp.IsSuccess) throw new UserFriendlyException(pubRsp.Error ?? string.Empty, "发布流程模板失败");
     }
 
     /// <summary>
     /// 发布(将草稿发布为正式模板)
     /// </summary>
     /// <returns></returns>
-    [HttpPost("definition/publish")]
-    public async Task Publish([FromBody] UpdateDefinitionDto dto)
+    [HttpPost("publish")]
+    public async Task Publish([FromBody] PreDefinition dto)
     {
-        var definition = _mapper.Map<Definition>(dto);
-        await _definitionDomainService.PublishAsync(definition, HttpContext.RequestAborted);
+        var pubRsp = await _workflowRemotingService.PublishAsync(dto, HttpContext.RequestAborted);
+        if (!pubRsp.IsSuccess) throw new UserFriendlyException(pubRsp.Error ?? string.Empty, "发布流程模板失败");
     }
 
     /// <summary>
     /// 启用流程模板
     /// </summary>
+    /// <param name="workflowId"></param>
     /// <returns></returns>
     /// <exception cref="UserFriendlyException"></exception>
-    [HttpPost("definition/enable")]
-    public async Task Enable(string id)
+    [HttpPost("enable")]
+    public async Task Enable(string workflowId)
     {
-        var definition = await _definitionRepository.GetAsync(id, HttpContext.RequestAborted);
-        if (definition == null)
-            throw UserFriendlyException.SameMessage("无效模板编号");
-        if (definition.Status == EDefinitionStatus.Temporary)
-            throw UserFriendlyException.SameMessage("草稿需发布才能启用");
-        if (definition.Status == EDefinitionStatus.Disable)
-        {
-            definition.Status = EDefinitionStatus.Enable;
-            await _definitionRepository.UpdateAsync(definition, HttpContext.RequestAborted);
-        }
+        var enableRsp = await _workflowRemotingService.EnableAsync(workflowId, HttpContext.RequestAborted);
+        if (!enableRsp.IsSuccess) throw new UserFriendlyException(enableRsp.Error ?? string.Empty, "启用流程模板失败");
     }
 
     /// <summary>
     /// 禁用流程模板
     /// </summary>
+    /// <param name="workflowId"></param>
     /// <returns></returns>
     /// <exception cref="UserFriendlyException"></exception>
-    [HttpPost("definition/disable")]
-    public async Task Disable(string id)
+    [HttpPost("disable")]
+    public async Task Disable(string workflowId)
     {
-        var definition = await _definitionRepository.GetAsync(id, HttpContext.RequestAborted);
-        if (definition == null)
-            throw UserFriendlyException.SameMessage("无效模板编号");
-        if (definition.Status == EDefinitionStatus.Temporary)
-            throw UserFriendlyException.SameMessage("草稿无法禁用");
-        if (definition.Status == EDefinitionStatus.Enable)
-        {
-            definition.Status = EDefinitionStatus.Disable;
-            await _definitionRepository.UpdateAsync(definition, HttpContext.RequestAborted);
-        }
+        var disableRsp = await _workflowRemotingService.DisableAsync(workflowId, HttpContext.RequestAborted);
+        if (!disableRsp.IsSuccess) throw new UserFriendlyException(disableRsp.Error ?? string.Empty, "禁用流程模板失败");
     }
-
+    
 }

+ 2 - 0
src/Hotline.Api/StartupExtensions.cs

@@ -24,6 +24,7 @@ using Microsoft.OpenApi.Models;
 using Serilog;
 using XF.Domain.Dependency;
 using XF.Domain.Filters;
+using Conductor.Client;
 
 namespace Hotline.Api;
 
@@ -49,6 +50,7 @@ internal static class StartupExtensions
         services
             .BatchInjectServices()
             .AddApplication()
+            .AddWorkflowConductor()
             ;
 
         var identityConfigs = configuration.GetSection(nameof(IdentityConfigs)).Get<IdentityConfigs>();

+ 1 - 1
src/Hotline.Api/appsettings.Development.json

@@ -48,7 +48,7 @@
     "Expired": 86400 //认证过期时间(秒)
   },
   "ConnectionStrings": {
-    "Hotline": "server=db.fengwo.com;Database=hotline;Uid=dev;Pwd=fengwo11!!;SslMode=none;",
+    "Hotline": "server=db.fengwo.com;Database=hotline1;Uid=dev;Pwd=fengwo11!!;SslMode=none;",
     "Redis": "192.168.100.223:6379"
   },
   "Swagger": true,

+ 1 - 1
src/Hotline.Api/appsettings.json

@@ -56,7 +56,7 @@
     "Expired": 86400 //认证过期时间(秒)
   },
   "ConnectionStrings": {
-    "Hotline": "server=192.168.100.121;port=3306;Database=hotline;Uid=dev;Pwd=fengwo11!!;SslMode=none;",
+    "Hotline": "server=db.fengwo.com;Database=hotline;Uid=dev;Pwd=fengwo11!!;SslMode=none;",
     "Redis": "192.168.100.223:6379"
   },
   "Swagger": true,

+ 18 - 0
src/Hotline.Application.Contracts/Validators/Knowledge/AddKnowledgeApplyDtoValidator.cs

@@ -0,0 +1,18 @@
+using FluentValidation;
+using Hotline.Share.Dtos.Knowledge;
+
+namespace Hotline.Application.Contracts.Validators.Knowledge
+{
+    public class AddKnowledgeApplyDtoValidator : AbstractValidator<KnowledgeApplyDto>
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public AddKnowledgeApplyDtoValidator()
+        {
+            RuleFor(d => d.Content).NotEmpty();
+            RuleFor(d => d.DepartmentCode).NotEmpty();
+            RuleFor(d => d.Department).NotEmpty();
+        }
+    }
+}

+ 17 - 0
src/Hotline.Application.Contracts/Validators/Knowledge/AddKnowledgeStandardDtoValidator.cs

@@ -0,0 +1,17 @@
+using FluentValidation;
+using Hotline.Share.Dtos.Knowledge;
+
+namespace Hotline.Application.Contracts.Validators.Knowledge
+{
+    public class AddKnowledgeStandardDtoValidator : AbstractValidator<AddKnowledgeStandardDto>
+    {
+        /// <summary>
+        /// 新增为空验证
+        /// </summary>
+        public AddKnowledgeStandardDtoValidator()
+        {
+            RuleFor(d => d.Title).NotEmpty();
+            RuleFor(d => d.Content).NotEmpty();
+        }
+    }
+}

+ 16 - 0
src/Hotline.Application.Contracts/Validators/Knowledge/AddKnowledgeTypeValidator.cs

@@ -0,0 +1,16 @@
+using FluentValidation;
+using Hotline.Share.Dtos.Knowledge;
+
+namespace Hotline.Application.Contracts.Validators.Knowledge
+{
+    public class AddKnowledgeTypeValidator : AbstractValidator<AddKnowledgeTypeDto>
+    {
+        /// <summary>
+        /// 新增为空验证
+        /// </summary>
+        public AddKnowledgeTypeValidator()
+        {
+            RuleFor(d => d.Name).NotEmpty();
+        }
+    }
+}

+ 20 - 0
src/Hotline.Application.Contracts/Validators/Knowledge/UpdateKnowledgeApplyDtoValidator.cs

@@ -0,0 +1,20 @@
+using FluentValidation;
+using Hotline.Share.Dtos.Knowledge;
+
+namespace Hotline.Application.Contracts.Validators.Knowledge
+{
+    public class UpdateKnowledgeApplyDtoValidator : AbstractValidator<UpdateKnowledgeApplyDto>
+    {
+        /// <summary>
+        /// 修改验证
+        /// </summary>
+        public UpdateKnowledgeApplyDtoValidator()
+        {
+            RuleFor(d => d.Id).NotEmpty();
+            RuleFor(d => d.KnowledgeApplyType).NotEmpty();
+            RuleFor(d => d.Content).NotEmpty();
+            RuleFor(d => d.DepartmentCode).NotEmpty();
+            RuleFor(d => d.Department).NotEmpty();
+        }
+    }
+}

+ 18 - 0
src/Hotline.Application.Contracts/Validators/Knowledge/UpdateKnowledgeStandardDtoValidator.cs

@@ -0,0 +1,18 @@
+using FluentValidation;
+using Hotline.Share.Dtos.Knowledge;
+
+namespace Hotline.Application.Contracts.Validators.Knowledge
+{
+    public class UpdateKnowledgeStandardDtoValidator : AbstractValidator<UpdateKnowledgeStandardDto>
+    {
+        /// <summary>
+        /// 修改为空验证
+        /// </summary>
+        public UpdateKnowledgeStandardDtoValidator()
+        {
+            RuleFor(d => d.Id).NotEmpty();
+            RuleFor(d => d.Title).NotEmpty();
+            RuleFor(d => d.Content).NotEmpty();
+        }
+    }
+}

+ 17 - 0
src/Hotline.Application.Contracts/Validators/Knowledge/UpdateKnowledgeTypeValidator.cs

@@ -0,0 +1,17 @@
+using FluentValidation;
+using Hotline.Share.Dtos.Knowledge;
+
+namespace Hotline.Application.Contracts.Validators.Knowledge
+{
+    public class UpdateKnowledgeTypeValidator : AbstractValidator<UpdateKnowledgeTypeDto>
+    {
+        /// <summary>
+        /// 修改为空验证
+        /// </summary>
+        public UpdateKnowledgeTypeValidator()
+        {
+            RuleFor(d => d.Id).NotEmpty();
+            RuleFor(d => d.Name).NotEmpty();
+        }
+    }
+}

+ 8 - 0
src/Hotline.Application/Dtos/WorkflowDefinitionDto.cs

@@ -0,0 +1,8 @@
+using Conductor.Domain.Models;
+
+namespace Hotline.Application.Dtos;
+
+public class WorkflowDefinitionDto : PreDefinition
+{
+    public bool IsPreDefinition { get; set; }
+}

+ 1 - 0
src/Hotline.Application/Hotline.Application.csproj

@@ -7,6 +7,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="Conductor.Client" Version="1.0.9" />
     <PackageReference Include="Dapr.AspNetCore" Version="1.9.0" />
     <PackageReference Include="Identity.Admin.HttpClient" Version="1.0.20" />
   </ItemGroup>

+ 24 - 1
src/Hotline.Application/Mappers/MapperConfigs.cs

@@ -1,6 +1,10 @@
-using Hotline.CallCenter.BlackLists;
+using Conductor.Domain.Models;
+using Hotline.CallCenter.BlackLists;
+using Hotline.KnowledgeBase;
 using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.Knowledge;
 using Hotline.Share.Dtos.User;
+using Hotline.Share.Dtos.Workflow;
 using Hotline.Users;
 using Mapster;
 
@@ -17,6 +21,25 @@ namespace Hotline.Application.Mappers
             config.NewConfig<AddUserDto, User>()
                 .Map(d => d.Name, x => x.Name ?? x.UserName);
 
+            config.NewConfig<PreDefinition, WorkflowDefinitionDto>()
+                .Map(d => d.IsPreDefinition, x => true);
+
+            config.NewConfig<Definition, WorkflowDefinitionDto>()
+                .Map(d => d.LastModificationTime, x => x.CreationTime);
+
+            config.NewConfig<KnowledgeApply, KnowledgeApplyPageDto>()
+              .Map(d => d.CreationName, x => x.User.Name)
+                .Map(d => d.CreationOrgName, x => x.SystemOrganize.OrgName);
+
+            config.NewConfig<Knowledge, KnowledgeDataDto>()
+              .Map(d => d.CreationName, x => x.User.Name)
+                .Map(d => d.KnowledgeTypeName, x => x.KnowledgeType.SpliceName);
+
+            config.NewConfig<Knowledge, KnowledgeApprovalDataDto>()
+            .Map(d => d.CreationName, x => x.User.Name)
+              .Map(d => d.KnowledgeTypeName, x => x.KnowledgeType.SpliceName)
+                 .Map(d => d.CreateBMName, x => x.SystemOrganize.OrgName);
+
         }
     }
 }

+ 67 - 0
src/Hotline.Share/Dtos/Knowledge/KnowledgeApplyDto.cs

@@ -0,0 +1,67 @@
+using Hotline.Share.Enums.KnowledgeBase;
+
+namespace Hotline.Share.Dtos.Knowledge
+{
+    /// <summary>
+    /// 编辑
+    /// </summary>
+    public record UpdateKnowledgeApplyDto : KnowledgeApplyDto
+    {
+        /// <summary>
+        /// ID
+        /// </summary>
+        public string Id { get; set; }
+    }
+
+    /// <summary>
+    /// 新增
+    /// </summary>
+    public record KnowledgeApplyDto
+    {
+        /// <summary>
+        /// 内容
+        /// </summary>
+        public string Content { get; set; }
+
+        /// <summary>
+        /// 申请类型
+        /// </summary>
+        public EKnowledgeApplyType KnowledgeApplyType { get; set; }
+
+        /// <summary>
+        /// 申请处理部门编码
+        /// </summary>
+        public string DepartmentCode { get; set; }
+
+        /// <summary>
+        /// 申请处理部门名称
+        /// </summary>
+        public string Department { get; set; }
+
+        /// <summary>
+        /// 截止时间
+        /// </summary>
+        public DateTime? ExpiredTime { get; set; }
+    }
+
+   /// <summary>
+   /// 知识申请详情
+   /// </summary>
+    public record DataKnowledgeApplyDto: UpdateKnowledgeApplyDto
+    {
+        /// <summary>
+        /// 申请人
+        /// </summary>
+        public string CreationName { get; set; }
+
+        /// <summary>
+        /// 关联知识ID
+        /// </summary>
+        public string KBID { get; set; }
+
+        /// <summary>
+        /// 知识标题
+        /// </summary>
+        public string KBTitle { get; set; }
+    }
+}

+ 57 - 0
src/Hotline.Share/Dtos/Knowledge/KnowledgeApplyPageDto.cs

@@ -0,0 +1,57 @@
+using Hotline.Share.Enums.KnowledgeBase;
+
+namespace Hotline.Share.Dtos.Knowledge
+{
+    public record KnowledgeApplyPageDto
+    {
+        /// <summary>
+        /// ID
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 内容
+        /// </summary>
+        public string Content { get; set; }
+
+        /// <summary>
+        /// 申请类型
+        /// </summary>
+        public EKnowledgeApplyType KnowledgeApplyType { get; set; }
+
+        /// <summary>
+        /// 申请状态
+        /// </summary>
+        public EKnowledgeApplyStatus Status { get; set; }
+
+        /// <summary>
+        /// 申请人
+        /// </summary>
+        public string CreationName { get; set; }
+
+        /// <summary>
+        /// 申请部门名称
+        /// </summary>
+        public string CreationOrgName { get; set; }
+
+        /// <summary>
+        /// 截止时间
+        /// </summary>
+        public DateTime? ExpiredTime { get; set; }
+
+        /// <summary>
+        /// 创建
+        /// </summary>
+        public DateTime? CreationTime { get; set; }
+
+        /// <summary>
+        /// 处理完成时间
+        /// </summary>
+        public DateTime? HandleTime { get; set; }
+
+        /// <summary>
+        /// 退回时间
+        /// </summary>
+        public DateTime? ReturnTime { get; set; }
+    }
+}

+ 8 - 0
src/Hotline.Share/Dtos/Knowledge/KnowledgeApplyPagedDto.cs

@@ -0,0 +1,8 @@
+using Hotline.Share.Requests;
+
+namespace Hotline.Share.Dtos.Knowledge
+{
+    public record KnowledgeApplyPagedDto(string CreateUserId, string? ApplyType, string? IsOvertime, DateTime? StartTime, DateTime? EndTime) : PagedRequest;
+
+    public record KnowledgeHandlePagedDto(string DepartmentCode, string? ApplyType, string? IsOvertime, DateTime? StartTime, DateTime? EndTime, string? CreateUserName, string? CreateBMName) : PagedRequest;
+}

+ 89 - 0
src/Hotline.Share/Dtos/Knowledge/KnowledgeDataDto.cs

@@ -0,0 +1,89 @@
+using Hotline.Share.Enums.KnowledgeBase;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Knowledge
+{
+    public record KnowledgeBaseDataDto
+    {
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 知识分类
+        /// </summary>
+        public string KnowledgeTypeName { get; set; }
+
+        /// <summary>
+        /// 热点
+        /// </summary>
+        public string HotspotName { get; set; }
+
+        /// <summary>
+        /// 申请人
+        /// </summary>
+        public string CreationName { get; set; }
+
+        /// <summary>
+        /// 浏览量
+        /// </summary>
+        public int PageView { get; set; }
+
+        /// <summary>
+        /// 文档状态
+        /// </summary>
+        public EKnowledgeStatus Status { get; set; }
+    }
+
+    /// <summary>
+    /// 知识库
+    /// </summary>
+    public record KnowledgeDataDto : KnowledgeBaseDataDto
+    {
+        /// <summary>
+        /// 是否上架
+        /// </summary>
+        public bool IsOnShelf { get; set; }
+
+        /// <summary>
+        /// 上架时间
+        /// </summary>
+        public DateTime? OnShelfTime { get; set; }
+
+        /// <summary>
+        /// 更新时间
+        /// </summary>
+        public DateTime? LastModificationTime { get; set; }
+
+        /// <summary>
+        /// 下架时间
+        /// </summary>
+        public DateTime? OffShelfTime { get; set; }
+    }
+
+    /// <summary>
+    /// 审核管理
+    /// </summary>
+    public record KnowledgeApprovalDataDto : KnowledgeBaseDataDto
+    {
+        /// <summary>
+        /// 申请部门
+        /// </summary>
+        public string CreateBMName { get; set; }
+
+        /// <summary>
+        /// 审核类型
+        /// </summary>
+        public string AuditType { get; set; }
+
+        /// <summary>
+        /// 时间,未审核的是到达时间,审核完成的是审核时间
+        /// </summary>
+        public DateTime? Time { get; set; }
+    }
+}

+ 85 - 0
src/Hotline.Share/Dtos/Knowledge/KnowledgeDto.cs

@@ -0,0 +1,85 @@
+namespace Hotline.Share.Dtos.Knowledge
+{
+    /// <summary>
+    /// 编辑
+    /// </summary>
+    public record UpdateKnowledgeDto : KnowledgeDto
+    {
+        /// <summary>
+        /// ID
+        /// </summary>
+        public string Id { get; set; }
+    }
+
+    /// <summary>
+    /// 新增知识
+    /// </summary>
+    public record AddKnowledgeDto : KnowledgeDto
+    {
+        /// <summary>
+        /// 知识编号
+        /// </summary>
+        public string Code { get; set; }
+    }
+
+    /// <summary>
+    /// 新增
+    /// </summary>
+    public record KnowledgeDto
+    {
+        /// <summary>
+        /// 知识分类
+        /// </summary>
+        public string KnowledgeTypeId { get; set; }
+
+        /// <summary>
+        /// 热点
+        /// </summary>
+        public string HotspotId { get; set; }
+
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 摘要
+        /// </summary>
+        public string Summary { get; set; }
+
+        /// <summary>
+        /// 内容
+        /// </summary>
+        public string Content { get; set; }
+
+        /// <summary>
+        /// 是否公开
+        /// </summary>
+        public bool IsPublic { get; set; }
+
+        /// <summary>
+        /// 下架时间-到期时间
+        /// </summary>
+        public DateTime? OffShelfTime { get; set; }
+
+        /// <summary>
+        /// 关键词
+        /// </summary>
+        public string Keywords { get; set; }
+
+        /// <summary>
+        /// 附件
+        /// </summary>
+        public List<string> Additions { get; set; }
+
+        /// <summary>
+        /// 关联知识申请
+        /// </summary>
+        public List<string> Applies { get; set; }
+
+        /// <summary>
+        /// 关联知识
+        /// </summary>
+        public List<string> Knowledges { get; set; }
+    }
+}

+ 58 - 0
src/Hotline.Share/Dtos/Knowledge/KnowledgePagedDto.cs

@@ -0,0 +1,58 @@
+using Hotline.Share.Requests;
+
+namespace Hotline.Share.Dtos.Knowledge
+{
+    /// <summary>
+    /// 我的草稿箱
+    /// </summary>
+    /// <param name="CreateUserId"></param>
+    /// <param name="KnowledgeTypeId"></param>
+    /// <param name="StartTime"></param>
+    /// <param name="EndTime"></param>
+    public record KnowledgeBasePagedDto : PagedRequest
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public string? KnowledgeTypeId { get; set; }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public string? Title { get; set; }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public DateTime? StartTime { get; set; }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public DateTime? EndTime { get; set; }
+    }
+
+    /// <summary>
+    /// 草稿箱
+    /// </summary>
+    public record MyDraftsListPagedDto(string? CreateUserId) : KnowledgeBasePagedDto;
+
+    /// <summary>
+    /// 知识库
+    /// </summary>
+    /// <param name="CreateUserName"></param>
+    /// <param name="CreateBMName"></param>
+    /// <param name="CreateBMCode"></param>
+    /// <param name="HotspotId"></param>
+    public record KnowledgePagedListDto(string? CreateUserName, string? CreateBMName, string? CreateBMCode, string? HotspotId) : KnowledgeBasePagedDto;
+
+    /// <summary>
+    /// 审核管理
+    /// </summary>
+    /// <param name="UserId"></param>
+    /// <param name="AuditType"></param>
+    /// <param name="Title"></param>
+    /// <param name="CreateUserName"></param>
+    /// <param name="CreateBMName"></param>
+    public record KnowledgeApprovalPagedListDto(string UserId, string? AuditType, string? Title, string? CreateUserName, string? CreateBMName) : PagedRequest;
+}

+ 29 - 0
src/Hotline.Share/Dtos/Knowledge/KnowledgeStandardDto.cs

@@ -0,0 +1,29 @@
+namespace Hotline.Share.Dtos.Knowledge
+{
+    /// <summary>
+    /// 修改实体
+    /// </summary>
+    public record UpdateKnowledgeStandardDto: AddKnowledgeStandardDto
+    {
+        /// <summary>
+        /// ID
+        /// </summary>
+        public string Id { get; set; }  
+    }
+
+    /// <summary>
+    /// 新增实体
+    /// </summary>
+    public record AddKnowledgeStandardDto
+    {
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 内容
+        /// </summary>
+        public string Content { get; set; }
+    }
+}

+ 70 - 0
src/Hotline.Share/Dtos/Knowledge/KnowledgeTypeDto.cs

@@ -0,0 +1,70 @@
+namespace Hotline.Share.Dtos.Knowledge
+{
+    /// <summary>
+    /// 编辑
+    /// </summary>
+    public record UpdateKnowledgeTypeDto : AddKnowledgeTypeDto
+    {
+        /// <summary>
+        /// ID
+        /// </summary>
+        public string Id { get; set; }
+    }
+
+    /// <summary>
+    ///新增
+    /// </summary>
+    public record AddKnowledgeTypeDto
+    {
+        /// <summary>
+        /// 类型名称
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// 父级ID
+        /// </summary>
+        public string ParentId { get; set; } = Guid.Empty.ToString();
+
+        /// <summary>
+        /// 排序
+        /// </summary>
+        public int Sort { get; set; } = 0;
+    }
+
+    /// <summary>
+    /// 初始化返回数据
+    /// </summary>
+    public record KnowledgeTypeDto
+    {
+        /// <summary>
+        /// ID
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 类型名称
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// 是否启用
+        /// </summary>
+        public bool IsEnable { get; set; }
+
+        /// <summary>
+        /// 排序
+        /// </summary>
+        public int Sort { get; set; }
+
+        /// <summary>
+        /// 父级ID
+        /// </summary>
+        public string ParentId { get; set; }
+
+        /// <summary>
+        /// 树形分类
+        /// </summary>
+        public List<TreeListDto> TreeLists { get; set; } = new();
+    }
+}

+ 35 - 0
src/Hotline.Share/Dtos/Knowledge/TreeListDto.cs

@@ -0,0 +1,35 @@
+namespace Hotline.Share.Dtos.Knowledge
+{
+    public record TreeListDto
+    {
+        /// <summary>
+        ///名称
+        /// </summary>
+        public string name { get; set; }
+
+        /// <summary>
+        /// 值
+        /// </summary>
+        public string value { get; set; }
+
+        /// <summary>
+        /// 父级ID
+        /// </summary>
+        public string ParentID { get; set; }
+
+        /// <summary>
+        /// 子集合
+        /// </summary>
+        public List<TreeListDto> children { get; set; }
+
+        /// <summary>
+        /// 是否选中
+        /// </summary>
+        public bool selected { get; set; } = false;
+
+        /// <summary>
+        /// 是否启用
+        /// </summary>
+        public bool IsEnable { get; set; }
+    }
+}

+ 12 - 0
src/Hotline/IDeviceEventHandler.cs

@@ -0,0 +1,12 @@
+using Hotline.CallCenter.Devices;
+
+namespace Hotline
+{
+    /// <summary>
+    /// 处理设备事件
+    /// </summary>
+    public interface IDeviceEventHandler
+    {
+        Task HandleAsync(Stream eventStream, DeviceConfigs deviceConfigs, CancellationToken cancellationToken);
+    }
+}

+ 8 - 0
src/Hotline/KnowledgeBase/IKnowledgeApplyRepository.cs.cs

@@ -0,0 +1,8 @@
+using XF.Domain.Repository;
+
+namespace Hotline.KnowledgeBase
+{
+    public interface IKnowledgeApplyRepository : IRepository<KnowledgeApply>
+    {
+    }
+}

+ 9 - 0
src/Hotline/KnowledgeBase/IKnowledgePVRepository.cs

@@ -0,0 +1,9 @@
+using XF.Domain.Repository;
+
+namespace Hotline.KnowledgeBase
+{
+    public interface IKnowledgePVRepository : IRepository<KnowledgePv>
+    {
+
+    }
+}

+ 9 - 0
src/Hotline/KnowledgeBase/IKnowledgeRepository.cs

@@ -0,0 +1,9 @@
+using XF.Domain.Repository;
+
+namespace Hotline.KnowledgeBase
+{
+    public interface IKnowledgeRepository : IRepository<KnowledgeBase.Knowledge>
+    {
+
+    }
+}

+ 8 - 0
src/Hotline/KnowledgeBase/IKnowledgeStandardRepository.cs

@@ -0,0 +1,8 @@
+using XF.Domain.Repository;
+
+namespace Hotline.KnowledgeBase
+{
+    public interface IKnowledgeStandardRepository : IRepository<KnowledgeStandard>
+    {
+    }
+}

+ 8 - 0
src/Hotline/KnowledgeBase/IKnowledgeTempRepository.cs

@@ -0,0 +1,8 @@
+using XF.Domain.Repository;
+
+namespace Hotline.KnowledgeBase
+{
+    public interface IKnowledgeTempRepository : IRepository<KnowledgeTemp>
+    {
+    }
+}

+ 8 - 0
src/Hotline/KnowledgeBase/IKnowledgeTypeRepository.cs

@@ -0,0 +1,8 @@
+using XF.Domain.Repository;
+
+namespace Hotline.KnowledgeBase
+{
+    public interface IKnowledgeTypeRepository : IRepository<KnowledgeType>
+    {
+    }
+}

+ 30 - 0
src/Hotline/KnowledgeBase/IKnowledgeTypeService.cs

@@ -0,0 +1,30 @@
+using Hotline.Share.Dtos.Knowledge;
+
+namespace Hotline.KnowledgeBase
+{
+    public interface IKnowledgeTypeService
+    {
+        /// <summary>
+        /// 查询所有子级
+        /// </summary>
+        /// <param name="treeDatas"></param>
+        /// <param name="ID"></param>
+        /// <param name="checkId"></param>
+        /// <returns></returns>
+        List<TreeListDto> GetChildren(List<KnowledgeType> treeDatas, string ID, string checkId);
+
+        /// <summary>
+        /// 获取全称
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        Task<string> GetFullName(string Id);
+
+        /// <summary>
+        /// 修改子级分类全称
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        Task UpdateChildNode(string Id);
+    }
+}

+ 27 - 3
src/Hotline/KnowledgeBase/Knowledge.cs

@@ -1,4 +1,6 @@
-using Hotline.Share.Enums.KnowledgeBase;
+using Hotline.Settings;
+using Hotline.Share.Enums.KnowledgeBase;
+using Hotline.Users;
 using SqlSugar;
 using XF.Domain.Repository;
 
@@ -74,6 +76,11 @@ public class Knowledge : FullStateEntity
     /// </summary>
     public string Keywords { get; set; }
 
+    /// <summary>
+    /// 版本号
+    /// </summary>
+    public int Version { get; set; } = 1;
+
     /// <summary>
     /// 附件
     /// </summary>
@@ -83,13 +90,30 @@ public class Knowledge : FullStateEntity
     /// <summary>
     /// 关联知识申请
     /// </summary>
-    [SugarColumn(ColumnDataType = "varchar(2000)", IsJson = true)]
+    [SugarColumn(ColumnDataType = "varchar(1000)", IsJson = true)]
     public List<string> Applies { get; set; }
 
     /// <summary>
     /// 关联知识
     /// </summary>
-    [SugarColumn(ColumnDataType = "varchar(2000)", IsJson = true)]
+    [SugarColumn(ColumnDataType = "varchar(1000)", IsJson = true)]
     public List<string> Knowledges { get; set; }
 
+    /// <summary>
+    /// 分类
+    /// </summary>
+    [Navigate(NavigateType.OneToOne, nameof(KnowledgeTypeId))]//一对一 
+    public KnowledgeType KnowledgeType { get; set; }
+
+    /// <summary>
+    /// 部门
+    /// </summary>
+    [Navigate(NavigateType.OneToOne, nameof(OrgId))]//一对一 
+    public SystemOrganize SystemOrganize { get; set; }
+
+    /// <summary>
+    /// 用户
+    /// </summary>
+    [Navigate(NavigateType.OneToOne, nameof(CreateUserId))]//一对一 
+    public User User { get; set; }
 }

+ 21 - 1
src/Hotline/KnowledgeBase/KnowledgeApply.cs

@@ -1,4 +1,8 @@
-using Hotline.Share.Enums.KnowledgeBase;
+using Hotline.Settings;
+using Hotline.Share.Enums.KnowledgeBase;
+using Hotline.Users;
+using Microsoft.AspNetCore.Authentication;
+using SqlSugar;
 using XF.Domain.Repository;
 
 namespace Hotline.KnowledgeBase;
@@ -8,6 +12,9 @@ namespace Hotline.KnowledgeBase;
 /// </summary>
 public class KnowledgeApply : FullStateEntity
 {
+    /// <summary>
+    /// 内容
+    /// </summary>
     public string Content { get; set; }
 
     /// <summary>
@@ -35,6 +42,19 @@ public class KnowledgeApply : FullStateEntity
     /// </summary>
     public DateTime? ExpiredTime { get; set; }
 
+    /// <summary>
+    /// 
+    /// </summary>
+    [Navigate(NavigateType.OneToOne, nameof(CreateUserId))]//一对一 CreateUserId是KnowledgeApply类里面的
+    public User User { get; set; }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    [Navigate(NavigateType.OneToOne, nameof(OrgId))]//一对一 
+    public SystemOrganize SystemOrganize { get; set; } 
+
+
     ///// <summary>
     ///// 处理完成
     ///// </summary>

+ 4 - 1
src/Hotline/KnowledgeBase/KnowledgePV.cs

@@ -3,9 +3,12 @@
 namespace Hotline.KnowledgeBase;
 
 /// <summary>
-/// PV
+/// PV 浏览记录
 /// </summary>
 public class KnowledgePv : CreationEntity
 {
+    /// <summary>
+    /// 知识ID
+    /// </summary>
     public string KnowledgeId { get; set; }
 }

+ 7 - 0
src/Hotline/KnowledgeBase/KnowledgeStandard.cs

@@ -7,7 +7,14 @@ namespace Hotline.KnowledgeBase
     /// </summary>
     public class KnowledgeStandard : FullStateEntity
     {
+        /// <summary>
+        /// 标题
+        /// </summary>
         public string Title { get; set; }
+
+        /// <summary>
+        /// 内容
+        /// </summary>
         public string Content { get; set; }
     }
 }

+ 1 - 1
src/Hotline/KnowledgeBase/KnowledgeTemp.cs

@@ -1,7 +1,7 @@
 namespace Hotline.KnowledgeBase;
 
 /// <summary>
-/// 草稿
+/// 知识库草稿
 /// </summary>
 public class KnowledgeTemp : Knowledge
 {

+ 8 - 1
src/Hotline/KnowledgeBase/KnowledgeType.cs

@@ -5,7 +5,7 @@ namespace Hotline.KnowledgeBase;
 /// <summary>
 /// 知识分类
 /// </summary>
-public class KnowledgeType : Entity
+public class KnowledgeType : CreationEntity
 {
     /// <summary>
     /// 类型名称
@@ -25,7 +25,14 @@ public class KnowledgeType : Entity
     /// </summary>
     public bool IsEnable { get; set; }
 
+    /// <summary>
+    /// 排序
+    /// </summary>
     public int Sort { get; set; }
 
+    /// <summary>
+    /// 父级ID
+    /// </summary>
     public string ParentId { get; set; }
+
 }

+ 127 - 0
src/Hotline/KnowledgeBase/KnowledgeTypeService.cs

@@ -0,0 +1,127 @@
+using Hotline.Share.Dtos.Knowledge;
+using XF.Domain.Dependency;
+
+namespace Hotline.KnowledgeBase
+{
+    public class KnowledgeTypeService : IKnowledgeTypeService, IScopeDependency
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        private readonly IKnowledgeTypeRepository _knowledgeTypeRepository;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="knowledgeTypeRepository"></param>
+        public KnowledgeTypeService(IKnowledgeTypeRepository knowledgeTypeRepository)
+        {
+            _knowledgeTypeRepository = knowledgeTypeRepository;
+        }
+        /// <summary>
+        /// 查询所有子级
+        /// </summary>
+        /// <param name="treeDatas"></param>
+        /// <param name="ID"></param>
+        /// <param name="checkId"></param>
+        /// <returns></returns>
+        public List<TreeListDto> GetChildren(List<KnowledgeType> treeDatas, string ID, string checkId)
+        {
+            List<TreeListDto> nodeList = new();
+            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 == dr.Id)
+                {
+                    node.selected = true;
+                }
+                node.children = GetChildren(treeDatas, node.value, checkId);
+                nodeList.Add(node);
+            }
+            return nodeList;
+        }
+
+        /// <summary>
+        /// 获取全称
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        public async Task<string> GetFullName(string Id)
+        {
+            //获取全部父级名称
+            var list = await GetParentNode(Id);
+            //倒叙
+            list.Reverse();
+            //拆分
+            return string.Join("-", list.ToArray());
+        }
+
+        /// <summary>
+        /// 修改子级分类全称
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        public 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 _knowledgeTypeRepository.UpdateAsync(item);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 查询父级节点
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        private async Task<List<string>> GetParentNode(string Id)
+        {
+            List<string> list = new();
+            var type = await _knowledgeTypeRepository.GetAsync(p => p.Id == Id);
+            if (type != null)
+            {
+                list.Add(type.Name);
+                list.AddRange(await GetParentNode(type.ParentId));
+            }
+            return list;
+        }
+
+        /// <summary>
+        /// 查询子级节点
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        private async Task<List<KnowledgeType>> GetChildNode(string Id)
+        {
+            List<KnowledgeType> list = new();
+            var typelist = await _knowledgeTypeRepository.QueryAsync(p => p.ParentId == Id);
+            if (typelist != null)
+            {
+                foreach (var item in typelist)
+                {
+                    list.Add(item);
+                    list.AddRange(await GetChildNode(item.Id));
+                }
+
+            }
+            return list;
+        }
+
+    }
+}

+ 15 - 14
src/Hotline/Orders/Order.cs

@@ -1,5 +1,10 @@
-using Hotline.Share.Enums.Order;
-using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Intrinsics.X86;
+using System.Text;
+using System.Threading.Tasks;
+using Hotline.Share.Enums.Order;
 using XF.Domain.Repository;
 
 namespace Hotline.Orders
@@ -96,17 +101,15 @@ namespace Hotline.Orders
         /// </summary>
         public DateTime? IncidentTime { get; set; }
 
-        ///// <summary>
-        ///// 事发地址
-        ///// </summary>
-        //[SugarColumn(ColumnDataType = "varchar(4000)", IsJson = true)]
-        //public Position IncidentPosition { get; set; } = new();
+        /// <summary>
+        /// 事发地址
+        /// </summary>
+        public Position IncidentPosition { get; set; }
 
-        ///// <summary>
-        ///// 附件
-        ///// </summary>
-        //[SugarColumn(ColumnDataType = "varchar(4000)", IsJson = true)]
-        //public List<string> Additions { get; set; } = new();
+        /// <summary>
+        /// 附件
+        /// </summary>
+        public List<string> Additions { get; set; }
 
         #endregion
     }
@@ -131,8 +134,6 @@ namespace Hotline.Orders
         public string City { get; set; }
         public string County { get; set; }
         public string Street { get; set; }
-
-        [SugarColumn(IsIgnore = true)]
         public string Address => $"{Province}{City}{County}{Street}";
     }
 

+ 9 - 0
src/Hotline/Orders/TempOrder.cs

@@ -0,0 +1,9 @@
+namespace Hotline.Orders;
+
+/// <summary>
+/// 工单草稿
+/// </summary>
+public class TempOrder : Order
+{
+
+}