Browse Source

Merge branch 'test' of http://110.188.24.182:10023/Fengwo/hotline into test

Dun.Jason 3 months ago
parent
commit
359eddbaf8
51 changed files with 1288 additions and 539 deletions
  1. 2 2
      src/Hotline.Api/Controllers/ExportData/ExportDataController.cs
  2. 19 10
      src/Hotline.Api/Controllers/KnowledgeCommonController.cs
  3. 4 9
      src/Hotline.Api/Controllers/KnowledgeController.cs
  4. 137 97
      src/Hotline.Api/Controllers/OrderController.cs
  5. 1 1
      src/Hotline.Api/Controllers/QualityController.cs
  6. 2 14
      src/Hotline.Api/Controllers/Snapshot/SnapshotBulletinController.cs
  7. 12 2
      src/Hotline.Api/Controllers/Snapshot/SnapshotController.cs
  8. 6 6
      src/Hotline.Api/Controllers/SysController.cs
  9. 144 193
      src/Hotline.Api/Controllers/TestController.cs
  10. 517 3
      src/Hotline.Api/Controllers/WebPortalController.cs
  11. 27 27
      src/Hotline.Api/Middleware/HeaderMiddleware.cs
  12. 1 10
      src/Hotline.Api/StartupExtensions.cs
  13. 3 2
      src/Hotline.Api/config/appsettings.Development.json
  14. 2 2
      src/Hotline.Application.Contracts/Validators/Order/AddOrderDtoValidator.cs
  15. 2 1
      src/Hotline.Application.Tests/Controller/SnapshotControllerTest.cs
  16. 17 4
      src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs
  17. 2 2
      src/Hotline.Application/Jobs/XingTangCallsSyncJob.cs
  18. 2 2
      src/Hotline.Application/Jobs/XingTangTelOperationSyncJob.cs
  19. 21 7
      src/Hotline.Application/Knowledge/KnowApplication.cs
  20. 74 72
      src/Hotline.Application/Orders/OrderApplication.cs
  21. 1 1
      src/Hotline.Application/Quality/QualityApplication.cs
  22. 4 1
      src/Hotline.Application/Snapshot/ISnapshotBulletinApplication.cs
  23. 5 2
      src/Hotline.Application/Snapshot/Notifications/SnapshotHandler.cs
  24. 23 1
      src/Hotline.Application/Snapshot/SnapshotBulletinApplication.cs
  25. 2 0
      src/Hotline.Application/Snapshot/SnapshotOrderApplication.cs
  26. 7 3
      src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs
  27. 5 0
      src/Hotline.Repository.SqlSugar/Snapshot/OrderSnapshotRepository.cs
  28. 5 0
      src/Hotline.Share/Dtos/Bi/BiOrderDto.cs
  29. 18 7
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  30. 69 0
      src/Hotline.Share/Dtos/Order/OrderFlowDto.cs
  31. 16 0
      src/Hotline.Share/Dtos/Order/OrderRelationTagDto.cs
  32. 10 0
      src/Hotline.Share/Dtos/Order/OrderVisitDto.cs
  33. 1 1
      src/Hotline.Share/Dtos/Snapshot/OrderDto.cs
  34. 28 1
      src/Hotline.Share/Dtos/WebPortal/ArticleDetailsDto.cs
  35. 14 0
      src/Hotline.Share/Dtos/WebPortal/WaitVisitListDataDto.cs
  36. 1 1
      src/Hotline.Share/Dtos/WebPortal/WebFlowAcceptDto.cs
  37. 0 29
      src/Hotline.Share/Enums/Snapshot/EJobType.cs
  38. 1 1
      src/Hotline.Share/Hotline.Share.csproj
  39. 6 1
      src/Hotline.Share/Requests/PagedKeywordRequest.cs
  40. 1 1
      src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs
  41. 0 1
      src/Hotline/KnowledgeBase/Knowledge.cs
  42. 1 0
      src/Hotline/KnowledgeBase/KnowledgeDomainService.cs
  43. 6 0
      src/Hotline/KnowledgeBase/KnowledgePV.cs
  44. 4 1
      src/Hotline/KnowledgeBase/KnowledgeType.cs
  45. 24 12
      src/Hotline/Orders/Order.cs
  46. 2 4
      src/Hotline/Orders/OrderDomainService.cs
  47. 24 0
      src/Hotline/Orders/OrderRelationTag.cs
  48. 2 2
      src/Hotline/SeedData/SystemDicDataSeedData.cs
  49. 7 0
      src/Hotline/Snapshot/Interfaces/IOrderSnapshotRepository.cs
  50. 6 1
      src/Hotline/Snapshot/OrderSnapshot.cs
  51. 0 2
      src/XingTang.Sdk/XingtangCall.cs

+ 2 - 2
src/Hotline.Api/Controllers/ExportData/ExportDataController.cs

@@ -18,7 +18,7 @@ namespace Hotline.Api.Controllers.ExportData;
 ///        比如: RedPackController.GetRedPackList 就会去查找 RedPackApplication.GetRedPackList 方法
 ///     3. 通过反射调用对应的方法
 ///     4. ApplicationService 的方法返回的必须是 ISugarQueryable
-///     5. ApplicationService 中方法的Description 属性会作为导出的文件名
+///     5. ApplicationService 中方法的ExportExcel属性会作为导出的文件名
 /// </summary>
 [ApiController]
 [Route("{*path:regex(.*export_excel$)}")]
@@ -40,7 +40,7 @@ public class ExportDataController : BaseController
     /// 动态导出数据
     /// </summary>
     /// <returns></returns>
-    [HttpPost]
+    [HttpPost, HttpGet]
     public async Task<FileStreamResult> HandleExportPost()
     {
         var fullPath = HttpContext.Request.Path.Value;

+ 19 - 10
src/Hotline.Api/Controllers/KnowledgeCommonController.cs

@@ -3,6 +3,7 @@ using Hotline.Permissions;
 using Hotline.Settings;
 using Hotline.Settings.Hotspots;
 using Hotline.Share.Dtos.Knowledge;
+using Hotline.Share.Enums.KnowledgeBase;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
 using SqlSugar;
@@ -137,22 +138,30 @@ namespace Hotline.Api.Controllers
         /// <summary>
         /// 知识分类- 获取层级分类
         /// </summary>
-        /// <param name="IsEnable">不传查询所有</param>
-        /// <returns></returns>
         [HttpGet("treelist")]
-        public async Task<List<KnowledgeTypeDto>> GetTreeList(bool? IsEnable, string? Attribution)
+        public async Task<List<KnowledgeTypeDto>> GetTreeList(bool? isEnable, string? attribution, EKnowledgeStatus? status)
         {
-            var query = _knowledgeTypeRepository.Queryable();
-            if (!_sessionContext.OrgIsCenter)
+            var isCenter = _sessionContext.OrgIsCenter;
+            var query = _knowledgeTypeRepository.Queryable()
+                .WhereIF(isEnable.HasValue, x => x.IsEnable == isEnable);
+            if (!isCenter)
                 query.Where(x => x.Orgs.Any(s => s.Id == _sessionContext.RequiredOrgId));
-            return await query.WhereIF(IsEnable.HasValue, x => x.IsEnable == IsEnable)
+            return await query
                  .Select(x => new KnowledgeTypeDto()
                  {
                      Id = x.Id.SelectAll(),
-                     KnowledgeNum = SqlFunc.Subqueryable<KnowledgeRelationType>().LeftJoin<Knowledge>((kr, k) => kr.KnowledgeId == k.Id)
-                         .Where((kr, k) => kr.KnowledgeTypeSpliceName.StartsWith(x.SpliceName))
-                         .WhereIF(!string.IsNullOrEmpty(Attribution), (kr, k) => k.Attribution == Attribution).DistinctCount(kr => kr.KnowledgeId)
-
+                     //KnowledgeNum = SqlFunc.Subqueryable<KnowledgeRelationType>()
+                     //    .LeftJoin<Knowledge>((kr, k) => kr.KnowledgeId == k.Id)
+                     //    .Where((kr, k) => kr.KnowledgeTypeSpliceName.StartsWith(x.SpliceName))
+                     //    .WhereIF(!string.IsNullOrEmpty(attribution) && !isCenter, (kr, k) => k.Attribution == attribution)
+                     //    .DistinctCount(kr => kr.KnowledgeId),
+                     KnowledgeNum = SqlFunc.Subqueryable<Knowledge>()
+                         .InnerJoin<KnowledgeRelationType>((k, krt) => k.Id == krt.KnowledgeId)
+                         .InnerJoin<KnowledgeType>((k, krt, t) => krt.KnowledgeTypeId == t.Id)
+                         .Where((k, krt, t) => t.SpliceName.StartsWith(x.SpliceName))
+                         .WhereIF(!string.IsNullOrEmpty(attribution) && !isCenter, (k, krt, t) => k.Attribution == attribution)
+                         .WhereIF(status != null, k => k.Status == status)
+                         .DistinctCount(k => k.Id)
                  })
                  .OrderBy(x => x.Sort)
                  .ToTreeAsync(it => it.children, it => it.ParentId, null, it => it.Id);

+ 4 - 9
src/Hotline.Api/Controllers/KnowledgeController.cs

@@ -33,21 +33,14 @@ using Microsoft.AspNetCore.Mvc;
 using SqlSugar;
 using System.Text;
 using Hotline.Configurations;
-using Hotline.Share.Requests;
 using Microsoft.Extensions.Options;
 using XF.Domain.Authentications;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
-using System.Threading;
 using Hotline.Caching.Interfaces;
-using Hotline.Import;
-using Hotline.Caching.Services;
-using Hotline.Share.Enums.Order;
 using MiniExcelLibs;
-using DocumentFormat.OpenXml.Wordprocessing;
 using Hotline.Pdf;
-using Microsoft.AspNetCore.Authorization;
 
 namespace Hotline.Api.Controllers
 {
@@ -1008,7 +1001,7 @@ namespace Hotline.Api.Controllers
             var inputLevelOneTypes = items.Select(d => d.KnowledgeTypeLevelOne)
                 .Distinct().ToList();
             var levelOneTypes = await _knowledgeTypeRepository.Queryable()
-                .Where(d => d.IsEnable && d.ParentId == null)
+                .Where(d => d.IsEnable && string.IsNullOrEmpty(d.ParentId))
                 .ToListAsync(HttpContext.RequestAborted);
             var existLevelOneNames = levelOneTypes.Select(d => d.Name);
             var notExists = inputLevelOneTypes.Except(existLevelOneNames).ToList();
@@ -1942,7 +1935,7 @@ namespace Hotline.Api.Controllers
             var approves = await _knowledgeApproRepository.Queryable()
                 .Includes(d => d.Approver)
                 .Where(d => d.KnowledgeId == knowledgeId)
-                .OrderBy(d => d.CreationTime)
+                .OrderByDescending(d => d.CreationTime)
                 .ToListAsync(HttpContext.RequestAborted);
 
             return _mapper.Map<IReadOnlyList<KnowledgeApproveDto>>(approves);
@@ -1960,6 +1953,8 @@ namespace Hotline.Api.Controllers
 
             var approves = await _knowledgeApproRepository.Queryable()
                 .Includes(d => d.Knowledge, x => x.KnowledgeTypes)
+                .Includes(d => d.Knowledge, x => x.User)
+                .Includes(d => d.Knowledge, x => x.SourceOrganize)
                 .Where(d => request.ApproveIds.Contains(d.Id) && d.KnowledgeApproveStatus == EKnowledgeApproveStatus.Unhandle)
                 .ToListAsync(HttpContext.RequestAborted);
 

+ 137 - 97
src/Hotline.Api/Controllers/OrderController.cs

@@ -6,6 +6,7 @@ using Hotline.Application.ExportExcel;
 using Hotline.Application.FlowEngine;
 using Hotline.Application.Orders;
 using Hotline.Application.Quality;
+using Hotline.Application.Snapshot;
 using Hotline.Application.Systems;
 using Hotline.Authentications;
 using Hotline.Caching.Interfaces;
@@ -40,7 +41,9 @@ using Hotline.Share.Dtos.Order.Detail;
 using Hotline.Share.Dtos.Order.Handle;
 using Hotline.Share.Dtos.Order.Migration;
 using Hotline.Share.Dtos.Order.Publish;
+using Hotline.Share.Dtos.Org;
 using Hotline.Share.Dtos.Settings;
+using Hotline.Share.Dtos.Snapshot;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
@@ -49,6 +52,8 @@ using Hotline.Share.Enums.Settings;
 using Hotline.Share.Mq;
 using Hotline.Share.Requests;
 using Hotline.Share.Tools;
+using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using Hotline.Tools;
 using Hotline.Users;
 using Hotline.YbEnterprise.Sdk;
@@ -68,20 +73,6 @@ using XF.Domain.Entities;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
-using Hotline.Application.Contracts.Validators.FlowEngine;
-using Hotline.Authentications;
-using Hotline.Share.Dtos.CallCenter;
-using Hotline.Share.Mq;
-using Hotline.CallCenter.Calls;
-using Hotline.FlowEngine.Notifications;
-using Hotline.Share.Dtos.Order.Detail;
-using Hotline.Share.Dtos.File;
-using Hotline.Share.Dtos.Org;
-using Hotline.Snapshot.Interfaces;
-using Hotline.Snapshot.Notifications;
-using Hotline.Snapshot;
-using Hotline.Application.Snapshot;
-using Hotline.Share.Dtos.Snapshot;
 using OrderDto = Hotline.Share.Dtos.Order.OrderDto;
 
 namespace Hotline.Api.Controllers;
@@ -161,6 +152,7 @@ public class OrderController : BaseController
     private readonly IOrderSnapshotRepository _orderSnapshotRepository;
     private readonly IOrderSnapshotApplication _orderSnapshotApplication;
     private readonly IIndustryRepository _industryRepository;
+    private readonly IRepository<SystemDicData> _sysDicDataRepository;
 
     public OrderController(
         IOrderDomainService orderDomainService,
@@ -231,7 +223,8 @@ public class OrderController : BaseController
         ISystemLogApplication systemLogApplication,
         IOrderSnapshotRepository orderSnapshotRepository,
         IIndustryRepository industryRepository,
-        IOrderSnapshotApplication orderSnapshotApplication)
+        IOrderSnapshotApplication orderSnapshotApplication,
+         IRepository<SystemDicData> sysDicDataRepository)
     {
         _orderDomainService = orderDomainService;
         _orderRepository = orderRepository;
@@ -302,6 +295,7 @@ public class OrderController : BaseController
         _orderSnapshotRepository = orderSnapshotRepository;
         _industryRepository = industryRepository;
         _orderSnapshotApplication = orderSnapshotApplication;
+        _sysDicDataRepository = sysDicDataRepository;
     }
 
     #endregion
@@ -380,6 +374,7 @@ public class OrderController : BaseController
     public async Task<PagedDto<PublishDto>> PublishOrderList([FromQuery] QueryOrderPublishDto dto)
     {
         var (total, items) = await _orderRepository.Queryable()
+            .Includes(d => d.OrderTags)
             //.Includes(d => d.OrderPublish)
             .Where(x => x.Status == EOrderStatus.Filed)
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword!))
@@ -388,7 +383,8 @@ public class OrderController : BaseController
             //.WhereIF(dto.PubState == EPubState.Pub, d => d.Status >= EOrderStatus.Published)
             //.WhereIF(dto.PubState == EPubState.NoPub, d => d.Status == EOrderStatus.Filed)
             .WhereIF(!string.IsNullOrEmpty(dto.Channel), d => d.SourceChannelCode == dto.Channel)
-            .WhereIF(!string.IsNullOrEmpty(dto.OrderTag), d => d.OrderTagCode == dto.OrderTag!) //工单标签
+            //.WhereIF(!string.IsNullOrEmpty(dto.OrderTag), d => d.OrderTagCode == dto.OrderTag!) //工单标签
+            .WhereIF(!string.IsNullOrEmpty(dto.OrderTag), d => d.OrderTags.Any(ot => ot.DicDataValue == dto.OrderTag)) //工单标签
             .WhereIF(!string.IsNullOrEmpty(dto.CenterToOrgHandlerName), d => d.CenterToOrgHandlerName == dto.CenterToOrgHandlerName!) //派单人
             .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName == dto.NameOrNo! || d.AcceptorStaffNo == dto.NameOrNo!) //受理人/坐席
             .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门(综合查询模糊)
@@ -976,8 +972,8 @@ public class OrderController : BaseController
         var users = await _userRepository.Queryable()
             .Includes(d => d.Organization)
             .Includes(d => d.Roles)
-            .WhereIF(!_appOptions.Value.IsZiGong, d => d.Roles.Any(x => roles.Contains(x.Name)))
-            .WhereIF(_appOptions.Value.IsZiGong, d => d.OrgId == OrgSeedData.CenterId)
+            .WhereIF(!_appOptions.Value.IsZiGong && !_appOptions.Value.IsLuZhou, d => d.Roles.Any(x => roles.Contains(x.Name)))
+            .WhereIF(_appOptions.Value.IsZiGong || _appOptions.Value.IsLuZhou, d => d.OrgId == OrgSeedData.CenterId)
             .ToListAsync(HttpContext.RequestAborted);
         return users.Select(d => new OrderMigrationHandler
         {
@@ -1176,10 +1172,10 @@ public class OrderController : BaseController
         //    x => x.OrderId == orderVisit.OrderId && x.AgainState == EAgainState.DoAgain, HttpContext.RequestAborted);
         var voiceEvaluate = EnumExts.GetDescriptions<EVoiceEvaluate>();
         var seatEvaluate = EnumExts.GetDescriptions<ESeatEvaluate>();
-        if (_appOptions.Value.IsZiGong==true)
+        if (_appOptions.Value.IsZiGong == true)
         {
             voiceEvaluate = EnumExtensions.GetEnumKeyValueList<EVoiceEvaluate>();
-            seatEvaluate=EnumExtensions.GetEnumKeyValueList<ESeatEvaluate>();
+            seatEvaluate = EnumExtensions.GetEnumKeyValueList<ESeatEvaluate>();
         }
         var visitSatisfaction = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitSatisfaction);
         var visitManner = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitManner);
@@ -1993,7 +1989,7 @@ public class OrderController : BaseController
             if (_appOptions.Value.IsZiGong)
             {
                 count = await _orderDelayRepository.CountAsync(x =>
-                    x.OrderId == delaydto.OrderId &&  x.ApplyOrgCode == _sessionContext.RequiredOrgId &&
+                    x.OrderId == delaydto.OrderId && x.ApplyOrgCode == _sessionContext.RequiredOrgId &&
                     (x.DelayState == EDelayState.Pass || x.DelayState == EDelayState.NoPass));
             }
 
@@ -2073,97 +2069,108 @@ public class OrderController : BaseController
         }
     }
 
-	/// <summary>
-	/// 批量审批延期
-	/// </summary>
-	[HttpPost("delay/batch_audit")]
-	[LogFilter("批量审批延期")]
-	public async Task<string> BatchAuditDelay([FromBody] BatchDelayNextFlowDto dto) {
-		var result = new StringBuilder();
-		var fail = 0;
-		var success = 0;
-		foreach (var item in dto.DelayId)
-		{
-			try
-			{
+    /// <summary>
+    /// 批量审批延期
+    /// </summary>
+    [HttpPost("delay/batch_audit")]
+    [LogFilter("批量审批延期")]
+    public async Task<string> BatchAuditDelay([FromBody] BatchDelayNextFlowDto dto)
+    {
+        var result = new StringBuilder();
+        var fail = 0;
+        var success = 0;
+        foreach (var item in dto.DelayId)
+        {
+            try
+            {
                 var workflow = dto.NextWorkflow;
+				if (workflow.NextHandlers.Any() && workflow.NextHandlers.Count() == 1)
+				{
+					var handler = workflow.NextHandlers.FirstOrDefault();
+					if (string.IsNullOrEmpty(handler.UserId))
+					{
+						workflow.NextHandlers = new List<FlowStepHandler>();
+					}
+				}
 				var delay = await _orderDelayRepository.Queryable().Includes(x=>x.Order).Where(x=>x.Id == item).FirstAsync(HttpContext.RequestAborted);
 				workflow.WorkflowId = delay.WorkflowId;
 				var workflowEntuty = await _workflowDomainService.GetWorkflowAsync(workflow.WorkflowId, withDefine: true, withSteps: true,cancellationToken: HttpContext.RequestAborted);
 				var currentStep =
 					workflowEntuty.Steps.FirstOrDefault(d => d.Status == EWorkflowStepStatus.WaitForAccept || d.Status == EWorkflowStepStatus.WaitForHandle);
 
-				NextStepsWithOpinionDto<NextStepOption> next = null;
+                NextStepsWithOpinionDto<NextStepOption> next = null;
 
-				try
-				{
-					next = await _workflowApplication.GetNextStepsAsync(delay.WorkflowId, HttpContext.RequestAborted);
-				}
-				catch (UserFriendlyException e)
-				{
-					if (e.Message.Contains("未找到对应节点"))
-					{
-						result.Append("无权审核:" + delay.No);
-						fail++;
-					}
-					else
-					{
-						throw;
-					}
-				}
-				if (next == null) continue;
+                try
+                {
+                    next = await _workflowApplication.GetNextStepsAsync(delay.WorkflowId, HttpContext.RequestAborted);
+                }
+                catch (UserFriendlyException e)
+                {
+                    if (e.Message.Contains("未找到对应节点"))
+                    {
+                        result.Append("无权审核:" + delay.No);
+                        fail++;
+                    }
+                    else
+                    {
+                        throw;
+                    }
+                }
+                if (next == null) continue;
 
-				if (!delay.Order.IsProvince)
-				{
-					if (next.Steps.Any(x => x.Value == "省审批"))
-					{
-						next.Steps.Remove(next.Steps.First(x => x.Value == "省审批"));
-					}
-				}
+                if (!delay.Order.IsProvince)
+                {
+                    if (next.Steps.Any(x => x.Value == "省审批"))
+                    {
+                        next.Steps.Remove(next.Steps.First(x => x.Value == "省审批"));
+                    }
+                }
 
-				if (!_sessionContext.OrgIsCenter && currentStep.Name != "中心初审")
-				{
-					if (next.Steps.Any(x => x.Value == "中心终审"))
-					{
-						next.Steps.Remove(next.Steps.First(x => x.Value == "中心终审"));
-					}
-				}
+                if (!_sessionContext.OrgIsCenter && currentStep.Name != "中心初审")
+                {
+                    if (next.Steps.Any(x => x.Value == "中心终审"))
+                    {
+                        next.Steps.Remove(next.Steps.First(x => x.Value == "中心终审"));
+                    }
+                }
 
-				var isBatch = next.Steps.Where(x => x.Value == workflow.NextStepName).Any();
+                var isBatch = next.Steps.Where(x => x.Value == workflow.NextStepName).Any();
                 if (isBatch)
                 {
-					var step = next.Steps.Where(x => x.Value == workflow.NextStepName).FirstOrDefault();
-					workflow.NextStepCode = step.Key;
-					workflow.NextStepName = step.Value;
-				}
-                else {
-					result.Append("无权审核:" + delay.No);
-					fail++;
+                    var step = next.Steps.Where(x => x.Value == workflow.NextStepName).FirstOrDefault();
+                    workflow.NextStepCode = step.Key;
+                    workflow.NextStepName = step.Value;
+                }
+                else
+                {
+                    result.Append("无权审核:" + delay.No);
+                    fail++;
                     continue;
-				}
+                }
 
-				workflow.StepId = next.StepId;
+                workflow.StepId = next.StepId;
                 workflow.ReviewResult = dto.IsPass ? EReviewResult.Approval : EReviewResult.Failed;
 
-				if (workflow.ReviewResult == EReviewResult.Approval) {
-					await _workflowDomainService.NextAsync(_sessionContext, workflow,cancellationToken: HttpContext.RequestAborted);
-				}
-				else
-				{
-					var reject = workflow.Adapt<RejectDto>();
-					await _workflowApplication.RejectAsync(reject, HttpContext.RequestAborted);
-				}
-				success++;
-			}
-			catch (UserFriendlyException e)
-			{
-				result.Append(e.Message);
-				fail++;
-			}
-		}
-		return $"总共: {dto.DelayId.Length}, 成功: {success}, 失败: {fail}, 失败原因: {result.ToString()}";
+                if (workflow.ReviewResult == EReviewResult.Approval)
+                {
+                    await _workflowDomainService.NextAsync(_sessionContext, workflow, cancellationToken: HttpContext.RequestAborted);
+                }
+                else
+                {
+                    var reject = workflow.Adapt<RejectDto>();
+                    await _workflowApplication.RejectAsync(reject, HttpContext.RequestAborted);
+                }
+                success++;
+            }
+            catch (UserFriendlyException e)
+            {
+                result.Append(e.Message);
+                fail++;
+            }
+        }
+        return $"总共: {dto.DelayId.Length}, 成功: {success}, 失败: {fail}, 失败原因: {result.ToString()}";
 
-	}
+    }
 
     /// <summary>
     ///  延期查询流程办理下一步可选节点
@@ -3406,6 +3413,7 @@ public class OrderController : BaseController
             .Includes(d => d.OrderPublish)
             .Includes(d => d.OrderPushTypes)
             .Includes(d => d.OrderComplements)
+            .Includes(d => d.OrderTags)
             //.Includes(d => d.OrderScreens)
             .Includes(d => d.OrderVisits.Where(x => x.VisitState == EVisitState.Visited).ToList(), x => x.OrderVisitDetails)
             .Includes(d => d.OrderVisits.Where(x => x.VisitState == EVisitState.Visited).ToList(), x => x.Employee)
@@ -3738,6 +3746,21 @@ public class OrderController : BaseController
             order.PushType = string.Join(",", pushTypes);
         }
 
+        if (dto.Tags != null && dto.Tags.Any())
+        {
+            var orderTags = new List<SystemDicData>();
+            foreach (var item in dto.Tags)
+            {
+                orderTags.Add(new SystemDicData() { Id = item });
+            }
+            order.OrderTags = orderTags;
+            var dicData = await _sysDicDataRepository.Queryable().Where(p => dto.Tags.Contains(p.Id)).Select(p => p.DicDataValue).ToListAsync();
+            if (dicData != null && dicData.Any())
+            {
+                order.OrderTagCode = String.Join(", ", dicData);
+            }
+        }
+
         await _orderDomainService.AddAsync(order, true, HttpContext.RequestAborted);
 
         if (_systemSettingCacheManager.Snapshot && dto.IndustryId.NotNullOrEmpty() && dto.IndustryName.NotNullOrEmpty())
@@ -3770,6 +3793,8 @@ public class OrderController : BaseController
             await _repeatableEventDetailRepository.AddRangeAsync(repeatables, HttpContext.RequestAborted);
         }
 
+
+
         //工单ID跟通话记录相关联
         //var callRecord = await _trCallRecordRepository.GetAsync(p => p.CallAccept == order.CallId, HttpContext.RequestAborted);//由CallAccept改为OtherAccept
         //var callRecord = await _trCallRecordRepository.GetAsync(p => p.OtherAccept == order.CallId && string.IsNullOrEmpty(p.OtherAccept) == false, HttpContext.RequestAborted);
@@ -3972,6 +3997,21 @@ public class OrderController : BaseController
             var pushTypes = dto.OrderPushTypes.Select(x => x.PushType);
             order.PushType = string.Join(",", pushTypes);
         }
+        if (dto.Tags != null && dto.Tags.Any())
+        {
+            var orderTags = new List<SystemDicData>();
+            foreach (var item in dto.Tags)
+            {
+                orderTags.Add(new SystemDicData() { Id = item });
+            }
+            order.OrderTags = orderTags;
+            var dicData = await _sysDicDataRepository.Queryable().Where(p => dto.Tags.Contains(p.Id)).Select(p => p.DicDataValue).ToListAsync();
+            if (dicData != null && dicData.Any())
+            {
+                order.OrderTagCode = String.Join(", ", dicData);
+            }
+        }
+        else order.OrderTagCode = string.Empty;
 
         //处理工单的期满时间
         //首先是工单编辑页面提交的、流程已经开启、工单未归档的工单才能修改期满时间
@@ -4003,7 +4043,7 @@ public class OrderController : BaseController
             }
         }
 
-        await _orderRepository.UpdateNav(order, new UpdateNavRootOptions { IgnoreColumns = ["CallId"] }).Include(d => d.OrderExtension).ExecuteCommandAsync();
+        await _orderRepository.UpdateNav(order, new UpdateNavRootOptions { IgnoreColumns = ["CallId"] }).Include(d => d.OrderExtension).Include(d => d.OrderTags).ExecuteCommandAsync();
 
         //订阅此事件的内部处理工单数据只能更新各自业务的字段,不能全部更新
         //修改工单其他处理事件  (受理短信)
@@ -4222,7 +4262,7 @@ public class OrderController : BaseController
                     continue;
                 }
                 throw;
-            }            
+            }
             var stepInfo = nextSteps.Steps.FirstOrDefault(m => m.BusinessType == EBusinessType.Send);
             if (stepInfo == null)
             {
@@ -4314,7 +4354,7 @@ public class OrderController : BaseController
                 orderHandleFlowDto.CrossSteps = orderHandleFlowDto.CrossSteps.OrderBy(d => d.Sort).ToList();
                 var stepCount = orderHandleFlowDto.CrossSteps.Count;
                 var unhandleSteps = new List<WorkflowStep> { startStep };
-                for (int i = 0;i < stepCount;i++)
+                for (int i = 0; i < stepCount; i++)
                 {
                     var crossStep = orderHandleFlowDto.CrossSteps[i];
                     var tempSteps = new List<WorkflowStep>();

+ 1 - 1
src/Hotline.Api/Controllers/QualityController.cs

@@ -680,7 +680,7 @@ namespace Hotline.Api.Controllers
             else {
 				var notStarted = await _qualityTransferRecordsRepository.Queryable().Where(x => x.IsFinished == false && x.TransferState == EQualityTransferState.NotStarted).OrderBy(x => x.TransferTime).FirstAsync();
 				await _qualityTransferRecordsRepository.Updateable().SetColumns(x => new QualityTransferRecords { TransferState = EQualityTransferState.Translating , TransferTime = DateTime.Now }).Where(x => x.Id == notStarted.Id).ExecuteCommandAsync();
-				await _qualityApplication.Transfer_XT(notStarted.QualityId, HttpContext.RequestAborted);
+				Task.Run(async () => await _qualityApplication.Transfer_XT(notStarted.QualityId, HttpContext.RequestAborted));
 			}
 		}
 

+ 2 - 14
src/Hotline.Api/Controllers/Snapshot/SnapshotBulletinController.cs

@@ -43,20 +43,8 @@ public class SnapshotBulletinController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpGet("bulletin/query")]
-    public async Task<PagedDto<SnapshotBulletinItemsOutDto>> QueryBulletinList([FromQuery] SnapshotBulletinItemsInDto dto)
-    {
-        var query = _bulletinRepository.Queryable()
-            .Includes(x => x.ExaminMan)
-            .WhereIF(!string.IsNullOrEmpty(dto.SnapshotBulletinTypeName), d => d.SnapshotBulletinTypeName.Contains(dto.SnapshotBulletinTypeName))
-            .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title))
-            .WhereIF(dto.BeginCreationTime.HasValue, d => d.BulletinTime >= dto.BeginCreationTime)
-            .WhereIF(dto.EndCreationTime.HasValue, d => d.BulletinTime <= dto.EndCreationTime)
-            .WhereIF(dto.State.HasValue, d => d.BulletinState == dto.State)
-            .OrderByDescending(d => d.CreationTime)
-            .Select<SnapshotBulletinItemsOutDto>();
-        return (await query
-            .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted)).ToPaged();
-    }
+    public async Task<PagedDto<SnapshotBulletinItemsOutDto>> QueryBulletinItems([FromQuery] SnapshotBulletinItemsInDto dto)
+        => (await _bulletinApplication.QueryBulletinItems(dto).ToPagedListAsync(dto)).ToPaged();
 
     /// <summary>
     /// 公告详情(内部)

+ 12 - 2
src/Hotline.Api/Controllers/Snapshot/SnapshotController.cs

@@ -50,8 +50,9 @@ public class SnapshotController : BaseController
     private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
     private readonly ISessionContext _sessionContext;
     private readonly IThirdAccountRepository _thirdAccountRepository;
+    private readonly ILogger<SnapshotController> _logger;
 
-    public SnapshotController(IRepository<Order> orderRepository, ISnapshotApplication snapshotApplication, ISystemAreaDomainService systemAreaDomainService, IIndustryRepository industryRepository, IOrderDomainService orderDomainService, IFileRepository fileRepository, IOrderSnapshotRepository orderSnapshotRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISessionContext sessionContext, IThirdAccountRepository thirdAccountRepository)
+    public SnapshotController(IRepository<Order> orderRepository, ISnapshotApplication snapshotApplication, ISystemAreaDomainService systemAreaDomainService, IIndustryRepository industryRepository, IOrderDomainService orderDomainService, IFileRepository fileRepository, IOrderSnapshotRepository orderSnapshotRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISessionContext sessionContext, IThirdAccountRepository thirdAccountRepository, ILogger<SnapshotController> logger)
     {
         _orderRepository = orderRepository;
         _snapshotApplication = snapshotApplication;
@@ -63,6 +64,7 @@ public class SnapshotController : BaseController
         _systemDicDataCacheManager = systemDicDataCacheManager;
         _sessionContext = sessionContext;
         _thirdAccountRepository = thirdAccountRepository;
+        _logger = logger;
     }
 
     /// <summary>
@@ -119,6 +121,14 @@ public class SnapshotController : BaseController
         orderSnapshot.IndustryId = dto.IndustryId;
         orderSnapshot.IndustryName = industry.Name;
         orderSnapshot.CompanyName = dto.CompanyName;
+        try
+        {
+            orderSnapshot.JobTypeName = _systemDicDataCacheManager.JobType.FirstOrDefault(m => m.DicDataValue == dto.JobType.ToString())?.DicDataName;
+        }
+        catch (Exception e)
+        {
+            _logger.LogError(e, $"添加随手拍工单, 获取JobTypeName异常. '{dto.JobType}'");
+        }
         if (dto.StartWorkTime.NotNullOrEmpty()) orderSnapshot.StartWorkTime = dto.StartWorkTime.ObjToDate();
         if (dto.EndWorkTime.NotNullOrEmpty()) orderSnapshot.EndWorkTime = dto.EndWorkTime.ObjToDate();
         if (dto.Name.NotNullOrEmpty())
@@ -389,7 +399,7 @@ public class SnapshotController : BaseController
                 EventType = 0,
                 WorkAddress = order.Address,
                 CreatedTime = order.CreationTime,
-                WorkType = snapshot.JobType.ObjToInt(),
+                WorkType = snapshot.JobType.Value,
                 Source = 1,
                 WorkTimeStart = snapshot.StartWorkTime.Value,
                 WorkTimeStop = snapshot.EndWorkTime.Value,

+ 6 - 6
src/Hotline.Api/Controllers/SysController.cs

@@ -587,12 +587,12 @@ namespace Hotline.Api.Controllers
 
         }
 
-        /// <summary>
-        /// 获取日志实体
-        /// </summary>
-        /// <param name="id"></param>
-        /// <returns></returns>
-        [HttpGet("log/{id}")]
+		/// <summary>
+		/// 获取日志实体
+		/// </summary>
+		/// <param name="id"></param>
+		/// <returns></returns>
+		[HttpGet("log/{id}")]
         public async Task<SystemLogDto> ItemEntity(string id)
         {
             var log = await _systemLogRepository.Queryable()

+ 144 - 193
src/Hotline.Api/Controllers/TestController.cs

@@ -79,6 +79,10 @@ using Microsoft.AspNetCore.DataProtection;
 using Hotline.Share.Tools;
 using NETCore.Encrypt;
 using Hotline.Ai.Quality;
+using Hotline.EventBus;
+using Hotline.JudicialManagement.Notifies;
+using Hotline.Snapshot.Notifications;
+using XF.Domain.Entities;
 
 namespace Hotline.Api.Controllers;
 
@@ -1098,199 +1102,6 @@ ICallApplication callApplication,
             "RGDH9951150024082950312",
 "RGDH9951150024080750198",
 "RGDH9951150024083050009",
-"RGDH9951150024083150167",
-"RGDH9951150024083150102",
-"RGDH9951150024083050052",
-"RGDH9951150024080750184",
-"RGDH9951150024083050108",
-"RGDH9951150024083050314",
-"RGDH9951150024083050363",
-"RGDH9951150024083150243",
-"RGDH9951150024082850303",
-"QT9951150024082150023",
-"RGDH9951150024080750185",
-"RGDH9951150024083150065",
-"RGDH9951150024082850032",
-"RGDH9951150024082950295",
-"RGDH9951150024080750189",
-"RGDH9951150024082650189",
-"RGDH9951150024083050008",
-"RGDH9951150024082950036",
-"RGDH9951150024082850341",
-"RGDH9951150024080750215",
-"RGDH9951150024081450005",
-"RGDH9951150024080750212",
-"RGDH9951150024083050137",
-"RGDH9951150024082450124",
-"RGDH9951150024083150188",
-"RGDH9951150024083150083",
-"RGDH9951150024082850082",
-"RGDH9951150024080750174",
-"RGDH9951150024082950371",
-"RGDH9951150024082950114",
-"RGDH9951150024083050339",
-"RGDH9951150024080750217",
-"RGDH9951150024082950040",
-"RGDH9951150024083050031",
-"RGDH9951150024083150267",
-"RGDH9951150024083050064",
-"RGDH9951150024072650086",
-"RGDH9951150024082950360",
-"RGDH9951150024080750195",
-"RGDH9951150024080750210",
-"RGDH9951150024082950250",
-"RGDH9951150024083050145",
-"RGDH9951150024083050356",
-"RGDH9951150024080750194",
-"RGDH9951150024080750173",
-"RGDH9951150024080750213",
-"RGDH9951150024080750218",
-"RGDH9951150024083150271",
-"RGDH9951150024083150134",
-"RGDH9951150024080750179",
-"RGDH9951150024083050140",
-"RGDH9951150024083150262",
-"RGDH9951150024083050119",
-"RGDH9951150024083150177",
-"RGDH9951150024083050146",
-"RGDH9951150024080750223",
-"RGDH9951150024080750221",
-"RGDH9951150024083150130",
-"RGDH9951150024080750209",
-"RGDH9951150024083150237",
-"RGDH9951150024082850095",
-"RGDH9951150024082850223",
-"RGDH9951150024083050077",
-"RGDH9951150024082950118",
-"RGDH9951150024082850056",
-"RGDH9951150024082550177",
-"RGDH9951150024083050358",
-"RGDH9951150024080750193",
-"RGDH9951150024082150011",
-"RGDH9951150024082950167",
-"RGDH9951150024083050201",
-"RGDH9951150024082850048",
-"RGDH9951150024083150161",
-"RGDH9951150024083050300",
-"RGDH9951150024083150016",
-"RGDH9951150024083150101",
-"RGDH9951150024082850207",
-"RGDH9951150024083150144",
-"RGDH9951150024082750300",
-"RGDH9951150024083050230",
-"RGDH9951150024080750211",
-"RGDH9951150024082750379",
-"RGDH9951150024082850252",
-"RGDH9951150024083050204",
-"RGDH9951150024080750176",
-"RGDH9951150024080750190",
-"RGDH9951150024083150027",
-"RGDH9951150024082850308",
-"RGDH9951150024082850070",
-"RGDH9951150024082950068",
-"RGDH9951150024083050002",
-"RGDH9951150024083050130",
-"RGDH9951150024083050060",
-"RGDH9951150024082950282",
-"RGDH9951150024082950320",
-"RGDH9951150024082850312",
-"RGDH9951150024083150040",
-"RGDH9951150024080750202",
-"RGDH9951150024083150216",
-"RGDH9951150024082750156",
-"RGDH9951150024082850224",
-"RGDH9951150024083150238",
-"RGDH9951150024083050327",
-"RGDH9951150024082950090",
-"RGDH9951150024083150131",
-"RGDH9951150024080750187",
-"RGDH9951150024082350072",
-"RGDH9951150024080750177",
-"RGDH9951150024082950010",
-"RGDH9951150024082850263",
-"RGDH9951150024082850087",
-"RGDH9951150024083050234",
-"RGDH9951150024083150098",
-"RGDH9951150024083050166",
-"RGDH9951150024082850339",
-"RGDH9951150024083150157",
-"RGDH9951150024080150214",
-"RGDH9951150024083150149",
-"RGDH9951150024083150264",
-"RGDH9951150024080750200",
-"RGDH9951150024083150116",
-"RGDH9951150024082950188",
-"RGDH9951150024083050148",
-"RGDH9951150024082750338",
-"RGDH9951150024082950268",
-"RGDH9951150024083050337",
-"RGDH9951150024082250263",
-"RGDH9951150024080750196",
-"RGDH9951150024080750192",
-"RGDH9951150024082850272",
-"RGDH9951150024082650290",
-"RGDH9951150024083150117",
-"RGDH9951150024080750207",
-"RGDH9951150024080750201",
-"RGDH9951150024080750188",
-"RGDH9951150024083050011",
-"RGDH9951150024083050067",
-"RGDH9951150024083050193",
-"RGDH9951150024082850242",
-"RGDH9951150024082950121",
-"RGDH9951150024080750222",
-"RGDH9951150024082950280",
-"RGDH9951150024080750205",
-"RGDH9951150024083050334",
-"RGDH9951150024083150235",
-"RGDH9951150024082950156",
-"RGDH9951150024080750220",
-"RGDH9951150024082750209",
-"RGDH9951150024083150046",
-"RGDH9951150024080750214",
-"RGDH9951150024082850116",
-"RGDH9951150024083050082",
-"RGDH9951150024083150118",
-"RGDH9951150024082950338",
-"RGDH9951150024082950359",
-"RGDH9951150024083150156",
-"RGDH9951150024083150072",
-"RGDH9951150024082150001",
-"RGDH9951150024082850186",
-"RGDH9951150024082750377",
-"RGDH9951150024083150166",
-"RGDH9951150024083050255",
-"RGDH9951150024083050190",
-"RGDH9951150024080750175",
-"RGDH9951150024083050184",
-"RGDH9951150024083050021",
-"RGDH9951150024082850317",
-"RGDH9951150024082950146",
-"RGDH9951150024083150172",
-"RGDH9951150024083050354",
-"RGDH9951150024082850305",
-"RGDH9951150024082850351",
-"RGDH9951150024082950340",
-"RGDH9951150024083150273",
-"RGDH9951150024080750208",
-"RGDH9951150024083150053",
-"RGDH9951150024082850291",
-"RGDH9951150024082950104",
-"RGDH9951150024082850247",
-"RGDH9951150024082850320",
-"RGDH9951150024083050285",
-"RGDH9951150024082850011",
-"RGDH9951150024083050174",
-"RGDH9951150024083150212",
-"RGDH9951150024083050323",
-"RGDH9951150024080750224",
-"RGDH9951150024083150244",
-"RGDH9951150024080750199",
-"RGDH9951150024082850269",
-"RGDH9951150024082850053",
-"RGDH9951150024082950342",
-"RGDH9951150024082950046",
-"RGDH9951150024082950194"
         };
         _logger.LogWarning($"推送数据共:{provinceNos.Count}");
 
@@ -1479,4 +1290,144 @@ ICallApplication callApplication,
         var strString = dto.AppId + dto.Timestamp;
         return dto.AppId + EncryptProvider.AESEncrypt(strString, dto.Secret, dto.AppId);
     }
+
+	/// <summary>
+	/// 归档handle错误数据处理
+	/// </summary>
+	/// <returns></returns>
+	[HttpPost("end_order_data_dispose")]
+	[AllowAnonymous]
+	public async Task EndOrderDataDispose([FromBody] string No)
+	{
+		var orderNo = await _orderRepository.Queryable().Where(x => x.No == No).FirstAsync(HttpContext.RequestAborted);
+
+		var workflow = await _workflowRepository.Queryable().Where(x => x.ExternalId == orderNo.Id).FirstAsync(HttpContext.RequestAborted);
+
+		var notification = await _workflowStepRepository.Queryable().Includes(x=>x.Workflow,w=>w.Steps).Where(x => x.ExternalId == orderNo.Id && x.BusinessType == EBusinessType.File && x.StepType == EStepType.End).FirstAsync(HttpContext.RequestAborted);
+		var order = await _orderDomainService.GetOrderAsync(orderNo.Id,
+					   withExtension: true, cancellationToken: HttpContext.RequestAborted);
+		//order.CheckIfFiled();
+		//order.UpdateHandlingStatus(workflow.IsInCountersign);
+		_mapper.Map(workflow, order);
+		var now = DateTime.Now;
+		var handleDuration = order.CenterToOrgTime.HasValue && order.ActualHandleTime.HasValue
+			? // _timeLimitDomainService.CalcWorkTime(
+			await _expireTime.CalcWorkTime(
+				order.CenterToOrgTime.Value,
+			order.ActualHandleTime.Value, order.ProcessType is EProcessType.Zhiban)
+			: 0;
+		var fileDuration = order.CenterToOrgTime.HasValue
+			? //_timeLimitDomainService.CalcWorkTime(
+			await _expireTime.CalcWorkTime(
+				order.CenterToOrgTime.Value,
+				now, order.ProcessType is EProcessType.Zhiban)
+			: 0;
+		var allDuration = order.StartTime.HasValue
+			? // _timeLimitDomainService.CalcWorkTime(
+			await _expireTime.CalcWorkTime(
+				order.StartTime.Value, now,
+			order.ProcessType is EProcessType.Zhiban)
+			: 0;
+		var creationTimeHandleDurationWorkday = order.ActualHandleTime.HasValue
+			? //_timeLimitDomainService.CalcWorkTimeEx(
+			await _expireTime.CalcWorkTimeEx(
+				order.CreationTime, now,
+			order.ProcessType is EProcessType.Zhiban)
+			: 0;
+		var centerToOrgHandleDurationWorkday = order.ActualHandleTime.HasValue && order.CenterToOrgTime.HasValue
+			? //_timeLimitDomainService.CalcWorkTimeEx(
+			await _expireTime.CalcWorkTimeEx(
+				order.CenterToOrgTime.Value, now,
+			order.ProcessType is EProcessType.Zhiban)
+			: 0;
+		creationTimeHandleDurationWorkday = creationTimeHandleDurationWorkday <= 0 ? 10 : creationTimeHandleDurationWorkday;
+		centerToOrgHandleDurationWorkday = centerToOrgHandleDurationWorkday <= 0 ? 10 : centerToOrgHandleDurationWorkday;
+
+		order.File(now, handleDuration, fileDuration, allDuration, creationTimeHandleDurationWorkday, centerToOrgHandleDurationWorkday);
+		order.FileUserId = notification.HandlerId;
+		order.FileUserName = notification.HandlerName;
+		order.FileUserOrgId = notification.HandlerOrgId;
+		order.FileUserOrgName = notification.HandlerOrgName;
+		order.FileOrgIsCenter = notification.HandlerOrgIsCenter;
+		order.FileOpinion = notification.Opinion;
+
+		//记录冗余归档数据
+		if (notification.Workflow.Steps.Any(x => x.BusinessType == Share.Enums.FlowEngine.EBusinessType.Send))
+		{
+			order.FileUserRole = EFileUserType.Dispatch;
+		}
+		else
+		{
+			order.FileUserRole = EFileUserType.Seat;
+		}
+		if (order.ProcessType == EProcessType.Jiaoban)
+		{
+			order.FileUserRole = EFileUserType.Org;
+		}
+
+		//是否已解决
+		order.IsResolved = true;
+
+		await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
+		//var callRecord = await _trCallRecordRepository.GetAsync(p => p.CallAccept == order.CallId, cancellationToken); //由CallAccept改为OtherAccept
+		//var callRecord = await _trCallRecordRepository.GetAsync(p => p.OtherAccept == order.CallId, cancellationToken);
+		//var orderFlowDto = new OrderFlowDto
+		//{
+		//	Order = _mapper.Map<OrderDto>(order),
+		//	WorkflowTrace = _mapper.Map<WorkflowTraceDto>(notification.Trace)
+		//};
+		//// if (callRecord != null)
+		//// {
+		////     orderFlowDto.TrCallRecordDto = _mapper.Map<TrCallDto>(callRecord);
+		//// }
+		//if (order.SourceChannelCode == AppDefaults.SourceChannel.DianHua &&
+		//	!string.IsNullOrEmpty(order.CallId))
+		//{
+		//	if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.TianRun)
+		//	{
+		//		// var callRecord = await _trCallRecordRepository.GetAsync(p => p.OtherAccept == order.CallId, cancellationToken);
+		//		var callRecord = await _callApplication.GetTianrunCallAsync(order.CallId, HttpContext.RequestAborted);
+		//		if (callRecord != null)
+		//		{
+		//			orderFlowDto.TrCallRecordDto = _mapper.Map<TrCallDto>(callRecord);
+		//		}
+		//	}
+		//	else if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XingTang)
+		//	{
+		//		var call = await _callApplication.GetCallAsync(order.CallId, HttpContext.RequestAborted);
+		//		if (call is not null)
+		//		{
+		//			orderFlowDto.TrCallRecordDto = _mapper.Map<TrCallDto>(call);
+
+		//			// 工单开始办理如果获取的通话记录是呼出并且录音文件是空就不推送通话记录
+		//			// 如果 通话记录是呼入, 并且没有录音文件
+		//			if (_systemSettingCacheManager.OrderStartHandlerPushCallIsNull && call.Direction == ECallDirection.Out && call.AudioFile.IsNullOrEmpty())
+		//			{
+		//				orderFlowDto.TrCallRecordDto = null;
+		//			}
+		//		}
+		//	}
+		//}
+
+		//这里需要判断是否是警情退回
+		//orderFlowDto.IsNonPoliceReturn = notification.Dto.External == null ? false : notification.Dto.External.IsPoliceReturn;
+		//await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFiled, orderFlowDto, cancellationToken: HttpContext.RequestAborted);
+		//await _publisher.PublishAsync(new SnapshotOrderFiledNotification(order.Id), PublishStrategy.ParallelWhenAll, HttpContext.RequestAborted);
+		//await _orderDomainService.OrderAutomaticPublishAsync(order, HttpContext.RequestAborted);
+		//try
+		//{
+		//    //写入质检  针对受理之后直接结束的工单
+		//    await _qualityApplication.AddQualityAsync(EQualitySource.Accepted, order.Id, cancellationToken);
+		//}
+		//catch (Exception e)
+		//{
+		//    _logger.LogError($"写入质检异常!orderId: {order.Id}, \r\n{e.Message}");
+		//}
+
+		//司法行政监督管理-工单处理
+		//如果没开启则不处理
+		//var isOpenJudicialManagement = _systemSettingCacheManager.GetSetting(SettingConstants.IsOpenJudicialManagement)?.SettingValue[0];
+		//if (isOpenJudicialManagement == "true")
+		//	await _publisher.PublishAsync(new JudicialManagementOrderNotify(order), PublishStrategy.ParallelWhenAll, HttpContext.RequestAborted);
+	}
 }

+ 517 - 3
src/Hotline.Api/Controllers/WebPortalController.cs

@@ -8,6 +8,7 @@ using Hotline.KnowledgeBase;
 using Hotline.Orders;
 using Hotline.Push.Notifies;
 using Hotline.Repository.SqlSugar.Extensions;
+using Hotline.Repository.SqlSugar.Knowledge;
 using Hotline.Settings;
 using Hotline.Settings.Hotspots;
 using Hotline.Share.Dtos;
@@ -25,6 +26,7 @@ using MediatR;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
+using Senparc.Weixin.WxOpen.AdvancedAPIs.WxApp.WxAppJson;
 using SqlSugar;
 using XF.Domain.Authentications;
 using XF.Domain.Cache;
@@ -35,6 +37,8 @@ namespace Hotline.Api.Controllers
 {
     public class WebPortalController : BaseController
     {
+        #region 注入
+
         private readonly IMapper _mapper;
         private readonly IMediator _mediator;
         private readonly IRepository<Bulletin> _bulletinRepository;
@@ -58,6 +62,7 @@ namespace Hotline.Api.Controllers
         private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
         private readonly ITypedCache<string> _getVailData;
         private readonly IRepository<KnowledgeWord> _knowledgeWordRepository;
+        private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
 
         public WebPortalController(IMapper mapper,
             IMediator mediator,
@@ -81,7 +86,8 @@ namespace Hotline.Api.Controllers
             ISystemDicDataCacheManager systemDicDataCacheManager,
             IOptionsSnapshot<AppConfiguration> appOptions,
             ITypedCache<string> getVailData,
-            IRepository<KnowledgeWord> knowledgeWordRepository
+            IRepository<KnowledgeWord> knowledgeWordRepository,
+            ISystemDicDataCacheManager sysDicDataCacheManager
             )
         {
             _mapper = mapper;
@@ -107,8 +113,11 @@ namespace Hotline.Api.Controllers
             _appOptions = appOptions;
             _getVailData = getVailData;
             _knowledgeWordRepository = knowledgeWordRepository;
+            _sysDicDataCacheManager = sysDicDataCacheManager;
         }
 
+        #endregion
+
         #region 通知
         /// <summary>
         /// 获取列表
@@ -1046,8 +1055,8 @@ namespace Hotline.Api.Controllers
                     data.Source = ESource.APP;
                     break;
                 case "3":
-                    data.SourceChannel = "微信";
-                    data.SourceChannelCode = "WX";
+                    data.SourceChannel = "微信小程序";
+                    data.SourceChannelCode = "XCX";
                     data.Source = ESource.WeChat;
                     break;
                 case "9"://宜宾人社专用
@@ -1308,6 +1317,8 @@ namespace Hotline.Api.Controllers
         }
         #endregion
 
+        #region 知识库
+
         /// <summary>
         /// 获取知识库分类
         /// </summary>
@@ -1402,6 +1413,10 @@ namespace Hotline.Api.Controllers
             return OpenResponse.Ok(WebPortalDeResponse<IReadOnlyList<KnowledgeInfoDto>>.Success(dataDto));
         }
 
+        #endregion
+
+        #region 查询受理类型
+
         /// <summary>
         /// 查询受理类型----受理量
         /// </summary>
@@ -1506,6 +1521,10 @@ namespace Hotline.Api.Controllers
             return OpenResponse.Ok(WebPortalDeResponse<IReadOnlyList<OrderFormCount>>.Success(formFileCount));
         }
 
+        #endregion
+
+        #region 缓存值
+
         /// <summary>
         /// 缓存值
         /// </summary>
@@ -1547,5 +1566,500 @@ namespace Hotline.Api.Controllers
 
             return OpenResponse.Ok(WebPortalDeResponse<string>.Success("-1"));
         }
+
+        #endregion
+
+        #region 通知-宜宾
+
+        /// <summary>
+        /// 获取列表
+        /// </summary>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpPost("getarticlelist_yibin")]
+        public async Task<OpenResponse> GetArticleListYiBin([FromBody] QueryArticleListDto dto)
+        {
+            if (string.IsNullOrEmpty(dto.PushRanges))
+                dto.PushRanges = "2";
+
+            RefAsync<int> total = 0;
+            var items1 = _bulletinRepository.Queryable()
+                .Where(p => p.LoseEfficacyTime >= DateTime.Now)
+                .Where(p => p.IsArrive == true)
+                .Where(p => SqlFunc.JsonListObjectAny(p.PushRanges, "Key", dto.PushRanges))
+                .Where(p => p.BulletinTypeId == dto.NoticeType)
+                .WhereIF(!string.IsNullOrEmpty(dto.Condition), p => p.Title.Contains(dto.Condition))
+                .Select(it => new ArticleListDto
+                {
+                    Page = 0,
+                    NoticeID = it.Id,
+                    //NoticeContent = it.Content,
+                    NoticeTypeName = it.BulletinTypeName,
+                    NoticeTitle = it.Title,
+                    NoticeBMName = it.SourceOrgName,
+                    NoticeCreateDate = it.CreationTime,
+                    VideoUrl = "",
+                    WNLT_FullCode = ""
+                });
+
+            List<ArticleListDto> items = new List<ArticleListDto>();
+            if (dto.NoticeType == "6")
+            {
+                //知识库
+                var items2 = _knowledgeRepository.Queryable()
+                    .Where(k => k.IsPublic == true)
+                    .Where(k => k.Status == EKnowledgeStatus.OnShelf)
+                    .Where(k => k.Attribution == "部门知识库")
+                    .Select(it => new ArticleListDto
+                    {
+                        Page = 0,
+                        NoticeID = it.Id,
+                        //NoticeContent = it.Content,
+                        NoticeTypeName = "知识库",
+                        NoticeTitle = it.Title,
+                        NoticeBMName = it.CreatorOrgName,
+                        NoticeCreateDate = it.CreationTime,
+                        VideoUrl = "",
+                        WNLT_FullCode = ""
+                    });
+
+                items = await _orderRepository.UnionAll(items1, items2)
+                  .Select(x => new ArticleListDto
+                  {
+                      Page = SqlFunc.RowNumber($"{x.NoticeCreateDate} desc "),
+                      NoticeID = x.NoticeID,
+                      //NoticeContent = x.NoticeContent,
+                      NoticeTypeName = x.NoticeTypeName,
+                      NoticeTitle = x.NoticeTitle,
+                      NoticeBMName = x.NoticeBMName,
+                      NoticeCreateDate = x.NoticeCreateDate,
+                      VideoUrl = x.VideoUrl,
+                      WNLT_FullCode = x.WNLT_FullCode
+                  })
+                  .OrderByDescending(p => p.NoticeCreateDate)
+                  .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
+            }
+            else
+            {
+                items = await items1
+                  .OrderByDescending(p => p.NoticeCreateDate)
+                  .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
+
+            }
+
+            //计算总页数
+            int nPageCount = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(total) / dto.PageSize));
+            ArticleListDataDto dataDto = new()
+            {
+                PageCount = nPageCount,
+                Total = total,
+                data = _mapper.Map<IReadOnlyList<ArticleListDto>>(items)
+            };
+
+            return OpenResponse.Ok(WebPortalDeResponse<ArticleListDataDto>.Success(dataDto));
+        }
+
+        /// <summary>
+        /// 获取详情,修改阅读次数
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpPost("getarticledetails_yibin")]
+        public async Task<OpenResponse> GetArticleDetailsYiBin([FromBody] ArticleIdDto dto)
+        {
+            ArticleDetailsDto detailsDto = null;
+            if (dto.TypeName == "知识库")
+            {
+                var data = await _knowledgeRepository.GetAsync(p => p.Id == dto.Id, HttpContext.RequestAborted);
+                if (data != null)
+                {
+                    data.PageView = data.PageView++;
+                    await _knowledgeRepository.UpdateAsync(data, HttpContext.RequestAborted);
+                    detailsDto = new()
+                    {
+                        NoticeID = data.Id,
+                        NoticeTypeName = "知识库",
+                        NoticeTitle = data.Title,
+                        NoticeBMName = data.CreatorOrgName,
+                        NoticeCreateDate = data.CreationTime,
+                        NoticeRCount = data.PageView,
+                        WNED_VideoUrl = "",
+                        NoticeContent = data.Content
+                    };
+                    if (data != null && !string.IsNullOrEmpty(data.Content))
+                        data.Content = _bulletinApplication.GetSiteUrls(data.Content);
+                }
+                else
+                    detailsDto = new();
+            }
+            else
+            {
+                var data = await _bulletinRepository.GetAsync(p => p.Id == dto.Id, HttpContext.RequestAborted);
+                if (data != null)
+                {
+                    data.ReadedNum = data.ReadedNum++;
+                    await _bulletinRepository.UpdateAsync(data, HttpContext.RequestAborted);
+                    detailsDto = new()
+                    {
+                        NoticeID = data.Id,
+                        NoticeTypeName = data.BulletinTypeName,
+                        NoticeTitle = data.Title,
+                        NoticeBMName = data.SourceOrgName,
+                        NoticeCreateDate = data.CreationTime,
+                        NoticeRCount = data.ReadedNum,
+                        WNED_VideoUrl = "",
+                        NoticeContent = data.Content
+                    };
+                    if (data != null && !string.IsNullOrEmpty(data.Content))
+                        data.Content = _bulletinApplication.GetSiteUrls(data.Content);
+                }
+                else
+                    detailsDto = new();
+            }
+
+            List<ArticleDetailsDto> dataDto = new() { detailsDto };
+            return OpenResponse.Ok(WebPortalDeResponse<IReadOnlyList<ArticleDetailsDto>>.Success(dataDto));
+        }
+
+        /// <summary>
+        /// 上一条和下一条
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpPost("getpreviousandnext_yibin")]
+        public async Task<OpenResponse> GetPreviousAndNextYiBin([FromBody] ArticlePreviousAndNextDto dto)
+        {
+            if (string.IsNullOrEmpty(dto.PushRanges))
+                dto.PushRanges = "2";
+
+            var sugar = _bulletinRepository.Queryable()
+                .Where(p => p.LoseEfficacyTime >= DateTime.Now)
+                .Where(p => p.IsArrive == true)
+                .Where(p => SqlFunc.JsonListObjectAny(p.PushRanges, "Key", dto.PushRanges));
+
+            if (dto.FullSearch == "1")//全文搜索
+            {
+                if (_appOptions.Value.IsYiBin)
+                {
+                    sugar.Where(p => p.BulletinTypeId == "1" || p.BulletinTypeId == "5" || p.BulletinTypeId == "6" || p.BulletinTypeId == "7" || p.BulletinTypeId == "3" || p.BulletinTypeId == "4")
+                    .WhereIF(!string.IsNullOrEmpty(dto.Condition), p => p.Content.Contains(dto.Condition) || p.Title.Contains(dto.Condition));
+                }
+                if (_appOptions.Value.IsZiGong)
+                {
+                    sugar.Where(p => p.BulletinTypeId == "5013" || p.BulletinTypeId == "5016" || p.BulletinTypeId == "5011" || p.BulletinTypeId == "5015" || p.BulletinTypeId == "5017")
+                    .WhereIF(!string.IsNullOrEmpty(dto.Condition), p => p.Content.Contains(dto.Condition) || p.Title.Contains(dto.Condition));
+                }
+            }
+            else//指定分类
+            {
+                sugar.WhereIF(!string.IsNullOrEmpty(dto.Condition), p => p.Title.Contains(dto.Condition))
+                    .Where(p => p.BulletinTypeId == dto.NoticeTypeId);
+            }
+
+            var items1 = sugar.Select(it => new ArticleDetailDataDto
+            {
+                Page = SqlFunc.RowNumber($"{it.CreationTime} desc "),// SqlFunc.MappingColumn(default(int), "  row_number()  over( order by 'NoticeCreateDate'  ) "),
+                NoticeID = it.Id,
+                NoticeTitle = it.Title,
+                NoticeTypeName = it.BulletinTypeName,
+                NoticeCreateDate = it.CreationTime
+            });
+
+            List<ArticleDetailDataDto> list = new List<ArticleDetailDataDto>();
+            if (dto.NoticeTypeId == "6")
+            {
+                //知识库
+                var items2 = _knowledgeRepository.Queryable()
+                    .Where(k => k.IsPublic == true)
+                    .Where(k => k.Status == EKnowledgeStatus.OnShelf)
+                    .Where(k => k.Attribution == "部门知识库")
+                    .WhereIF(!string.IsNullOrEmpty(dto.Condition), k => k.Content.Contains(dto.Condition) || k.Title.Contains(dto.Condition))
+                    .Select(it => new ArticleDetailDataDto
+                    {
+                        Page = 0,
+                        NoticeID = it.Id,
+                        NoticeTitle = it.Title,
+                        NoticeTypeName = "知识库",
+                        NoticeCreateDate = it.CreationTime
+                    });
+
+                list = await _orderRepository.UnionAll(items1, items2)
+                    .Select(x => new ArticleDetailDataDto
+                    {
+                        Page = SqlFunc.RowNumber($"{x.NoticeCreateDate} desc "),
+                        NoticeID = x.NoticeID,
+                        NoticeTitle = x.NoticeTitle,
+                        NoticeTypeName = x.NoticeTypeName,
+                        NoticeCreateDate = x.NoticeCreateDate
+                    })
+                    .OrderByDescending(x => x.NoticeCreateDate)
+                    .ToListAsync();
+            }
+            else
+            {
+                list = await items1.OrderByDescending(x => x.NoticeCreateDate).ToListAsync();
+            }
+
+            //数据为空返回空数据
+            if (list == null || list.Count == 0)
+                return OpenResponse.Ok(WebPortalDeResponse<List<ArticlePreviousAndNextDataDto>>.Success(null));
+            else
+            {
+                var temp = list.Find(p => p.NoticeID == dto.ID);
+                if (temp != null)
+                {
+                    List<ArticlePreviousAndNextDataDto> returnDto = new();
+                    //上一条
+                    var pTemp = list.Find(p => p.Page == temp.Page - 1);
+                    if (pTemp != null)
+
+                        returnDto.Add(new()
+                        {
+                            NoticeID = pTemp.NoticeID,
+                            NoticeTitle = pTemp.NoticeTitle,
+                            NoticeTypeName = pTemp.NoticeTypeName,
+                            pntype = "p"
+                        });
+
+                    //下一条
+                    var nTemp = list.Find(p => p.Page == temp.Page + 1);
+                    if (nTemp != null)
+                        returnDto.Add(new()
+                        {
+                            NoticeID = nTemp.NoticeID,
+                            NoticeTitle = nTemp.NoticeTitle,
+                            NoticeTypeName = nTemp.NoticeTypeName,
+                            pntype = "n"
+                        });
+                    return OpenResponse.Ok(WebPortalDeResponse<List<ArticlePreviousAndNextDataDto>>.Success(returnDto));
+                }
+                else
+                    return OpenResponse.Ok(WebPortalDeResponse<List<ArticlePreviousAndNextDataDto>>.Success(null));
+            }
+        }
+
+        /// <summary>
+        /// 全文检索
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpPost("getfulltextsearchlist_yibin")]
+        public async Task<OpenResponse> GetFullTextSearchList_YiBin([FromBody] QueryArticleListDto dto)
+        {
+            if (string.IsNullOrEmpty(dto.PushRanges))
+                dto.PushRanges = "2";
+
+            if (string.IsNullOrEmpty(dto.Condition))
+                return OpenResponse.Ok(WebPortalDeResponse<FullTextSearchListDataDto>.Success(null));
+
+            RefAsync<int> total = 0;
+            var items1 = _bulletinRepository.Queryable()
+                 .Where(p => p.LoseEfficacyTime >= DateTime.Now)
+                 .Where(p => p.IsArrive == true)
+                 .Where(p => SqlFunc.JsonListObjectAny(p.PushRanges, "Key", dto.PushRanges))
+                 .WhereIF(_appOptions.Value.IsYiBin, p => p.BulletinTypeId == "1" || p.BulletinTypeId == "5" || p.BulletinTypeId == "6" || p.BulletinTypeId == "7" || p.BulletinTypeId == "3" || p.BulletinTypeId == "4")
+                 .WhereIF(_appOptions.Value.IsZiGong, p => p.BulletinTypeId == "5013" || p.BulletinTypeId == "5016" || p.BulletinTypeId == "5011" || p.BulletinTypeId == "5015" || p.BulletinTypeId == "5017")
+                 .WhereIF(!string.IsNullOrEmpty(dto.Condition), p => p.Title.Contains(dto.Condition))
+                 .OrderByDescending(p => p.CreationTime)
+                 .Select(it => new FullTextSearchListDto
+                 {
+                     Page = 0,
+                     NoticeID = it.Id,
+                     //Content = it.Content,
+                     NoticeTypeID = it.BulletinTypeId,
+                     NoticeTypeName = it.BulletinTypeName,
+                     NoticeTitle = it.Title,
+                     NoticeBMName = it.SourceOrgName,
+                     NoticeCreateDate = it.CreationTime.ToString("yyyy-MM-dd HH:mm:ss"),
+                     TypeCode = ""
+                 });
+
+            List<FullTextSearchListDto> items = new List<FullTextSearchListDto>();
+            if (dto.NoticeType == "6")
+            {
+                //知识库
+                var items2 = _knowledgeRepository.Queryable()
+                    .Where(k => k.IsPublic == true)
+                    .Where(k => k.Status == EKnowledgeStatus.OnShelf)
+                    .Where(k => k.Attribution == "部门知识库")
+                    .WhereIF(!string.IsNullOrEmpty(dto.Condition), k => k.Content.Contains(dto.Condition) || k.Title.Contains(dto.Condition))
+                    .Select(it => new FullTextSearchListDto
+                    {
+                        Page = 0,
+                        NoticeID = it.Id,
+                        //NoticeContent = it.Content,
+                        NoticeTypeID = "6",
+                        NoticeTypeName = "知识库",
+                        NoticeTitle = it.Title,
+                        NoticeBMName = it.CreatorOrgName,
+                        NoticeCreateDate = it.CreationTime.ToString("yyyy-MM-dd HH:mm:ss"),
+                        TypeCode = ""
+                    });
+
+                items = await _orderRepository.UnionAll(items1, items2)
+                  .Select(x => new FullTextSearchListDto
+                  {
+                      Page = SqlFunc.RowNumber($"{x.NoticeCreateDate} desc "),
+                      NoticeID = x.NoticeID,
+                      //NoticeContent = it.Content,
+                      NoticeTypeID = x.NoticeTypeID,
+                      NoticeTypeName = x.NoticeTypeName,
+                      NoticeTitle = x.NoticeTitle,
+                      NoticeBMName = x.NoticeBMName,
+                      NoticeCreateDate = x.NoticeCreateDate,
+                      TypeCode = ""
+                  })
+                  .OrderByDescending(p => p.NoticeCreateDate)
+                  .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
+            }
+            else
+            {
+                items = await items1
+                  .OrderByDescending(p => p.NoticeCreateDate)
+                  .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
+            }
+
+            //计算总页数
+            int nPageCount = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(total) / dto.PageSize));
+            FullTextSearchListDataDto dataDto = new()
+            {
+                PageCount = nPageCount,
+                data = _mapper.Map<IReadOnlyList<FullTextSearchListDto>>(items)
+            };
+            return OpenResponse.Ok(WebPortalDeResponse<FullTextSearchListDataDto>.Success(dataDto));
+        }
+
+        #endregion
+
+        #region 办件-宜宾
+
+        /// <summary>
+        /// 办件摘编详情
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpPost("getorderdetailbyid_yibin")]
+        public async Task<object> GetOrderDetailByIdYiBin([FromBody] ArticleIdDto dto)
+        {
+            var data = await _orderRepository.GetAsync(p => p.Id == dto.Id, HttpContext.RequestAborted);
+
+            var orderDetail = _mapper.Map<OrderDetail>(data);
+            if (data != null)
+            {
+                //如果是省工单或者是省政民互动的工单,市民不能进行评价
+                if (data.IsProvince == true || data.SourceChannelCode == "ZMHD")
+                    orderDetail.IsProvinceOrder = "1";
+                else
+                    orderDetail.IsProvinceOrder = "0";
+
+                //获取发布的数据
+                var orderPublish = await _orderPublishRepository.GetAsync(p => p.OrderId == data.Id, HttpContext.RequestAborted);
+                if (orderPublish != null)
+                {
+                    orderDetail.PubFlag = "1";
+                    orderDetail.FlowTitle = orderPublish.ArrangeTitle;
+                    orderDetail.FlowContent = orderPublish.ArrangeContent;
+                    orderDetail.FlowResult = orderPublish.ArrangeOpinion;
+                    if (orderPublish.PublishState)
+                        orderDetail.FlowPubFlagName = "公开";
+                }
+
+                //能否进行评价
+                var orderVisit = await _orderVisitRepository.GetAsync(p => p.OrderId == data.Id && p.VisitState != EVisitState.None, HttpContext.RequestAborted);
+                if (orderVisit == null)
+                    orderDetail.VisitType = "0";
+                else
+                {
+                    orderDetail.VisitType = orderVisit.VisitState switch
+                    {
+                        EVisitState.WaitForVisit => "1",
+                        EVisitState.Visited => "2",
+                        EVisitState.Visiting or EVisitState.NoSatisfiedWaitForVisit or EVisitState.None => "0",
+                        _ => "0",
+                    };
+                }
+            }
+            //List<OrderDetail> dataDto = new() { orderDetail };
+            //return OpenResponse.Ok(WebPortalDeResponse<IReadOnlyList<OrderDetail>>.Success(dataDto));
+
+            var dissatisfiedReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.DissatisfiedReason);
+
+            return new
+            {
+                OrderDetail = orderDetail,
+                DissatisfiedReason = dissatisfiedReason
+            };
+        }
+
+        #endregion
+
+        #region 评价-宜宾
+
+        /// <summary>
+        /// 评价内容
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpPost("receivevisitdata_yibin")]
+        public async Task<OpenResponse> ReceiveVisitData_YiBin([FromBody] OrderVisitListDataDto dto)
+        {
+            if (dto == null || dto.VistListDtos == null || dto.VistListDtos.Count == 0)
+                return OpenResponse.Ok(WebPortalDeResponse<string>.Failed("评价数据不能为空!"));
+
+            var dataOrder = await _orderVisitRepository.GetAsync(p => p.OrderId == dto.OrderId && p.VisitState != EVisitState.None, HttpContext.RequestAborted);
+            if (dataOrder == null)
+                return OpenResponse.Ok(WebPortalDeResponse<string>.Failed("工单已经评价!"));
+
+            //组装数据
+            OrderVisitWebDto visitWebDto = new()
+            {
+                VisitType = Hotline.Share.Enums.Order.EVisitType.WebVisit,
+                VisitTime = DateTime.Now
+            };
+
+            List<OrderVisitDetailWebDto> orderVisitDetails = new();
+
+            #region 部门评价
+            //部门评价
+            //遍历数据
+            foreach (var item in dto.VistListDtos)
+            {
+                Hotline.Share.Dtos.Kv kv = item.SatisfactionCode switch
+                {
+                    "5" => new Hotline.Share.Dtos.Kv { Key = "5", Value = "非常满意" },
+                    "4" => new Hotline.Share.Dtos.Kv { Key = "4", Value = "满意" },
+                    "2" => new Hotline.Share.Dtos.Kv { Key = "2", Value = "不满意" },
+                    _ => new Hotline.Share.Dtos.Kv { Key = "7", Value = "不做评价" },
+                };
+                //组装回访数据
+                visitWebDto.Id = item.VisitId;
+                OrderVisitDetailWebDto detailDto = new()
+                {
+                    Id = item.Id,
+                    VisitTarget = Hotline.Share.Enums.Order.EVisitTarget.Org,
+                    OrgProcessingResults = kv,
+                    OrgNoSatisfiedReason = item.OrgNoSatisfiedReason,
+                    OrgHandledAttitude = kv,
+                    VisitContent = item.VisitContent,
+                    IsContact = item.IsContact,
+                    Volved = item.Volved
+                };
+                orderVisitDetails.Add(detailDto);
+            }
+            #endregion
+
+            visitWebDto.OrderVisitDetailDto = orderVisitDetails;
+
+            //推送数据
+            await _orderApplication.OrderVisitWeb(visitWebDto, HttpContext.RequestAborted);
+            return OpenResponse.Ok(WebPortalDeResponse<string>.Success("1"));
+        }
+
+        #endregion
     }
 }

+ 27 - 27
src/Hotline.Api/Middleware/HeaderMiddleware.cs

@@ -1,34 +1,34 @@
-using Microsoft.AspNetCore.Mvc;
+//using Microsoft.AspNetCore.Mvc;
 
-namespace Hotline.Api.Middleware;
+//namespace Hotline.Api.Middleware;
 
-/// <summary>
-/// 为特定的返回结果添加 头部信息 的中间件
-/// </summary>
-public class HeaderMiddleware
-{
-    private readonly RequestDelegate _next;
+///// <summary>
+///// 为特定的返回结果添加 头部信息 的中间件
+///// </summary>
+//public class HeaderMiddleware
+//{
+//    private readonly RequestDelegate _next;
 
-    public HeaderMiddleware(RequestDelegate next)
-    {
-        _next = next;
-    }
+//    public HeaderMiddleware(RequestDelegate next)
+//    {
+//        _next = next;
+//    }
 
-    public async Task InvokeAsync(HttpContext context)
-    {
-        var originalBodyStream = context.Response.Body;
-        using var responseBody = new MemoryStream();
-        context.Response.Body = responseBody;
+//    public async Task InvokeAsync(HttpContext context)
+//    {
+//        var originalBodyStream = context.Response.Body;
+//        using var responseBody = new MemoryStream();
+//        context.Response.Body = responseBody;
 
-        await _next(context);
+//        await _next(context);
 
-        // 为返回类型是 FileStreamResult 的请求添加 头部信息
-        if (context.Response.StatusCode == 200 && context.Response is FileStreamResult)
-        {
-            context.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
-        }
+//        // 为返回类型是 FileStreamResult 的请求添加 头部信息
+//        if (context.Response.StatusCode == 200 && context.Response is FileStreamResult)
+//        {
+//            context.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
+//        }
 
-        context.Response.Body.Seek(0, SeekOrigin.Begin);
-        await responseBody.CopyToAsync(originalBodyStream);
-    }
-}
+//        context.Response.Body.Seek(0, SeekOrigin.Begin);
+//        await responseBody.CopyToAsync(originalBodyStream);
+//    }
+//}

+ 1 - 10
src/Hotline.Api/StartupExtensions.cs

@@ -1,5 +1,4 @@
-using System.IO.Compression;
-using System.Reflection;
+using System.Reflection;
 using FluentValidation;
 using FluentValidation.AspNetCore;
 using Hotline.Api.Realtimes;
@@ -26,26 +25,18 @@ using Hotline.Application.CallCenter.Calls;
 using Hotline.Application.CallCenter;
 using Hotline.Authentications;
 using Hotline.CallCenter.Calls;
-using Swashbuckle.AspNetCore.SwaggerUI;
 using Hotline.Configurations;
 using Hotline.DI;
-using Hotline.Share.Tools;
 using Hotline.Settings.TimeLimitDomain.ExpireTimeSupplier;
-using Hotline.Api.Middleware;
 using XF.Domain.Authentications;
 using Hotline.XingTang;
-using Hotline.Logger;
 using HotPot.Mvc.Filters;
-using Microsoft.AspNetCore.ResponseCompression;
 using Hotline.WeChat;
 using Hotline.Snapshot.Interfaces;
 using TianQue.Sdk;
-using Hotline.Application.Snapshot;
 using Hotline.Orders;
 using XF.Domain.Repository.Events;
 using Hotline.Orders.DatabaseEventHandler;
-using Hotline.Snapshot;
-using Hotline.WeChat;
 using Hotline.Ai.XingTang;
 using Hotline.Pdf;
 

+ 3 - 2
src/Hotline.Api/config/appsettings.Development.json

@@ -62,8 +62,9 @@
       "Ip": "222.213.23.229"
     },
     "XingTang": {
-      //"DbConnectionString": "server=123.56.10.71;Database=callcenter_db;Uid=root;Pwd=Lhw1981!(*!"
-      "DbConnectionString": "server=110.188.24.182;Database=callcenter_xingtang;Uid=dev;Pwd=fengwo11!!"
+        //"DbConnectionString": "server=123.56.10.71;Database=callcenter_db;Uid=root;Pwd=Lhw1981!(*!"
+        "DbConnectionString": "server=110.188.24.182;Database=callcenter_xingtang;Uid=dev;Pwd=fengwo11!!"
+        //"DbConnectionString": "PORT=50143;server=110.188.24.182;Database=callcenter_db;Uid=dev;Pwd=fengwo123!@#;"
     }
   },
   "ConnectionStrings": {

+ 2 - 2
src/Hotline.Application.Contracts/Validators/Order/AddOrderDtoValidator.cs

@@ -102,9 +102,9 @@ public class AddOrderDtoValidator : AbstractValidator<AddOrderDto>
         #endregion
 
         #region 投诉对象信息
-        RuleFor(d => d.OrderExtension.EnterpriseName).MaxLengthWithChineseChar(80).When(d => d.OrderExtension != null).WithMessage("企业名称最多80字符");
+        RuleFor(d => d.OrderExtension.EnterpriseName).MaxLengthWithChineseChar(50).When(d => d.OrderExtension != null).WithMessage("企业名称最多50字符");
         RuleFor(d => d.OrderExtension.UnifiedSocialCreditCode).MaxLengthWithChineseChar(30).When(d => d.OrderExtension != null).WithMessage("统一社会信用代码最多30字符");
-        RuleFor(d => d.OrderExtension.RegisterAddress).MaxLengthWithChineseChar(400).When(d => d.OrderExtension != null).WithMessage("企业注册地址最多400字符");
+        RuleFor(d => d.OrderExtension.RegisterAddress).MaxLengthWithChineseChar(50).When(d => d.OrderExtension != null).WithMessage("企业注册地址最多50字符");
         RuleFor(d => d.OrderExtension.RegisterNumber).MaxLengthWithChineseChar(50).When(d => d.OrderExtension != null).WithMessage("注册号最多50字符");
         RuleFor(d => d.OrderExtension.EnterpriseContact).MaxLengthWithChineseChar(70).When(d => d.OrderExtension != null).WithMessage("联系人最多70字符");
         RuleFor(d => d.OrderExtension.MarketTypeCode).MaxLengthWithChineseChar(64).When(d => d.OrderExtension != null).WithMessage("市场主体类型代码最多64字符");

+ 2 - 1
src/Hotline.Application.Tests/Controller/SnapshotControllerTest.cs

@@ -70,7 +70,7 @@ public class SnapshotControllerTest : TestBase
         inDto.County = "沿滩区";
         inDto.Description = "单元测试添加的时间描述";
         inDto.IsSecret = false;
-        //inDto.JobType = 
+        inDto.JobType = 1;
         foreach (var item in inDto.Files)
         {
             item.FileName = DateTime.Now.ToShortTimeString() + "文件.doc";
@@ -85,5 +85,6 @@ public class SnapshotControllerTest : TestBase
         orderEntity.Content.ShouldNotBeNullOrEmpty();
         var orderSnapshotEntity = await _orderSnapshotRepository.GetAsync(order.Id);
         orderSnapshotEntity.ShouldNotBeNull();
+        orderSnapshotEntity.JobType.ShouldBe(inDto.JobType);
     }
 }

+ 17 - 4
src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs

@@ -50,7 +50,7 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
     private readonly ICalcExpireTime _expireTime;
     private readonly IRepository<OrderTerminate> _orderTerminateRepository;
 
-	public WorkflowEndHandler(
+    public WorkflowEndHandler(
         IMapper mapper,
         IKnowledgeDomainService knowledgeDomainService,
         IOrderDomainService orderDomainService,
@@ -106,8 +106,8 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
                 case WorkflowModuleConsts.KnowledgeUpdate://修改知识库
                 case WorkflowModuleConsts.KnowledgeDelete://删除知识库
                 case WorkflowModuleConsts.KnowledgeOffshelf: //下架知识库
-					//var knowledgeWork = await _knowledgeWorkFlowRepository.Queryable().Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);
-					var knowledge = await _knowledgeRepository.Queryable().Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);
+                                                             //var knowledgeWork = await _knowledgeWorkFlowRepository.Queryable().Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);
+                    var knowledge = await _knowledgeRepository.Queryable().Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);
                     knowledge.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
                     await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
                     if (isReviewPass)
@@ -230,8 +230,21 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
 
                     //这里需要判断是否是警情退回
                     orderFlowDto.IsNonPoliceReturn = notification.Dto.External == null ? false : notification.Dto.External.IsPoliceReturn;
+
+                    //如果是泸州,这里需要查询是否有工单延期
+                    if (_appOptions.Value.IsLuZhou)
+                    {
+                        var orderDelay = await _orderDelayRepository.Queryable().Where(p => p.OrderId == order.Id && p.DelayState == EDelayState.Pass)
+                                .OrderByDescending(p => p.ApplyDelayTime)
+                                .FirstAsync();
+                        orderFlowDto.OrderSearchDelay = _mapper.Map<OrderSearchDelayDto>(orderDelay);
+                    }
+
                     await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFiled, orderFlowDto, cancellationToken: cancellationToken);
-                    await _publisher.PublishAsync(new SnapshotOrderFiledNotification(order.Id), PublishStrategy.ParallelWhenAll, cancellationToken);
+                    if (_systemSettingCacheManager.Snapshot)
+                    {
+                        await _publisher.PublishAsync(new SnapshotOrderFiledNotification(order.Id), PublishStrategy.ParallelWhenAll, cancellationToken);
+                    }
                     await _orderDomainService.OrderAutomaticPublishAsync(order, cancellationToken);
                     //try
                     //{

+ 2 - 2
src/Hotline.Application/Jobs/XingTangCallsSyncJob.cs

@@ -82,7 +82,7 @@ namespace Hotline.Application.Jobs
             if (!occupyCalls.Any()) return;
             try
             {
-                if (occupyCalls.Any(m => m.Customerid.IsNullOrEmpty() == true))
+                if (occupyCalls.Any(m => m.CustomerId.IsNullOrEmpty() == true))
                 {
                     var calls = _mapper.Map<List<CallNative>>(occupyCalls);
                     //填充user信息
@@ -142,7 +142,7 @@ namespace Hotline.Application.Jobs
                     {
                         var call = occupyCall.Adapt<CallNative>();
                         call.Id = await GetCallIdAsync(call.CallNo, context.CancellationToken);
-                        var userSplit = occupyCall.Customerid.Split(':');
+                        var userSplit = occupyCall.CustomerId.Split(':');
                         call.UserId = userSplit[0];
                         call.UserName = userSplit[1];
 

+ 2 - 2
src/Hotline.Application/Jobs/XingTangTelOperationSyncJob.cs

@@ -90,7 +90,7 @@ namespace Hotline.Application.Jobs
 
                     }
                     await _telOperationRepository.AddRangeAsync(operations, context.CancellationToken);
-                    _logger.LogInformation($"旧方法同步分机操作记录成功,数量:{operations.Count}");
+                    //_logger.LogInformation($"旧方法同步分机操作记录成功,数量:{operations.Count}");
                 }
                 else
                 {
@@ -108,7 +108,7 @@ namespace Hotline.Application.Jobs
                         operations.Add(operation);
                     }
                     await _telOperationRepository.AddRangeAsync(operations, context.CancellationToken);
-                    _logger.LogInformation($"新方法同步分机操作记录成功,数量:{operations.Count}");
+                    //_logger.LogInformation($"新方法同步分机操作记录成功,数量:{operations.Count}");
                 }
             }
             catch (Exception e)

+ 21 - 7
src/Hotline.Application/Knowledge/KnowApplication.cs

@@ -1,6 +1,8 @@
-using Hotline.Application.Tools;
+using DocumentFormat.OpenXml.EMMA;
+using Hotline.Application.Tools;
 using Hotline.Configurations;
 using Hotline.KnowledgeBase;
+using Hotline.Pdf;
 using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Settings;
 using Hotline.Settings.Hotspots;
@@ -34,6 +36,7 @@ namespace Hotline.Application.Knowledge
         private readonly IRepository<KnowledgeApply> _knowledgeApplyRepository;
         private readonly IRepository<KnowledgeWord> _knowledgeWordRepository;
         private readonly IRepository<KnowledgeHotWord> _knowledgeHotWordRepository;
+        private readonly IPdfManager _pdfManager;
         private readonly ISessionContext _sessionContext;
         private readonly IMapper _mapper;
         private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
@@ -46,7 +49,11 @@ namespace Hotline.Application.Knowledge
         /// <param name="sessionContext"></param>
         /// <param name="knowledgeDomainService"></param>
         /// <param name="mapper"></param>
-        public KnowApplication(IKnowledgeRepository knowledgeRepository, IOptionsSnapshot<AppConfiguration> appOptions, IRepository<KnowledgeApply> knowledgeApplyRepository, ISessionContext sessionContext, IMapper mapper, IRepository<KnowledgeType> knowledgeTypeRepository, IRepository<Hotspot> hotspotTypeRepository, IRepository<KnowledgeWord> knowledgeWordRepository, IRepository<KnowledgePv> knowledgePvepository, IRepository<KnowledgeHotWord> knowledgeHotWordRepository)
+        public KnowApplication(IKnowledgeRepository knowledgeRepository, IOptionsSnapshot<AppConfiguration> appOptions,
+            IRepository<KnowledgeApply> knowledgeApplyRepository, ISessionContext sessionContext, IMapper mapper,
+            IRepository<KnowledgeType> knowledgeTypeRepository, IRepository<Hotspot> hotspotTypeRepository,
+            IRepository<KnowledgeWord> knowledgeWordRepository, IRepository<KnowledgePv> knowledgePvepository,
+            IRepository<KnowledgeHotWord> knowledgeHotWordRepository, IPdfManager pdfManager)
         {
             _knowledgeRepository = knowledgeRepository;
             _knowledgeApplyRepository = knowledgeApplyRepository;
@@ -57,6 +64,7 @@ namespace Hotline.Application.Knowledge
             _knowledgeWordRepository = knowledgeWordRepository;
             _knowledgePvepository = knowledgePvepository;
             _knowledgeHotWordRepository = knowledgeHotWordRepository;
+            _pdfManager = pdfManager;
             _appOptions = appOptions;
 
         }
@@ -287,7 +295,7 @@ namespace Hotline.Application.Knowledge
 
             var tasks = knowList.Select(async item =>
             {
-                var stream = await Task.Run(() => item.Content.HtmlToStream(dto.FileType), cancellationToken);
+                var stream = await Task.Run(() => item.Content.HtmlToStream(dto.FileType, item.Title, _pdfManager), cancellationToken);
                 return new KeyValuePair<string, Stream>(
                     item.Title + dto.FileType.GetFileExtension(),
                     stream
@@ -419,16 +427,22 @@ namespace Hotline.Application.Knowledge
                 dto.Attribution = "部门知识库";
             }
 
-            var sugar = _knowledgeRepository
-                .Queryable(false, false, false)
+            var query = _knowledgeRepository.Queryable(false, false, false);
+
+            if (!_sessionContext.OrgIsCenter)
+                query.Where(x => x.KnowledgeTypes.Any(t => t.Orgs.Any(to => to.Id == _sessionContext.RequiredOrgId)));
+
+            var sugar = query
                 .Includes(x => x.User)
                 .Includes(x => x.SystemOrganize)
                 .Includes(x => x.HotspotType)
                 .Includes(x => x.KnowledgeType)
                 .Where(x => x.IsDeleted == false)
                 .Where(x => x.Status == EKnowledgeStatus.OnShelf)
-                .Where(x => x.KnowledgeType.Any(t => t.KnowledgeType.KnowledgeTypeOrgs.Any(to => to.OrgId == _sessionContext.RequiredOrgId) || t.KnowledgeType.KnowledgeTypeOrgs.Any() == false))
-                .WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => x.KnowledgeType.Any(t => t.KnowledgeTypeSpliceName.StartsWith(typeSpliceName)))
+                //.Where(x => x.KnowledgeType.Any(t => t.KnowledgeType.KnowledgeTypeOrgs.Any(to => to.OrgId == _sessionContext.RequiredOrgId)
+                //                                     || t.KnowledgeType.KnowledgeTypeOrgs.Any() == false))
+                //.WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => x.KnowledgeType.Any(t => t.KnowledgeTypeSpliceName.StartsWith(typeSpliceName)))
+                .WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => x.KnowledgeTypes.Any(t => t.SpliceName.StartsWith(typeSpliceName)))
                 .WhereIF(!string.IsNullOrEmpty(hotspotHotSpotFullName), x => x.HotspotType.HotSpotFullName.EndsWith(hotspotHotSpotFullName!))
                 .WhereIF(!string.IsNullOrEmpty(dto.HotspotName), x => x.HotspotType.HotSpotFullName.EndsWith(dto.HotspotName!))
                 .WhereIF(!string.IsNullOrEmpty(dto.CreateOrgId), x => x.CreatorOrgId != null && x.CreatorOrgId.EndsWith(dto.CreateOrgId!))

+ 74 - 72
src/Hotline.Application/Orders/OrderApplication.cs

@@ -327,73 +327,73 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<Order> GetAboutToExpireAsync(AboutToExpireListDto dto)
     {
-        DateTime? dateTime = DateTime.Now;
-        var IsCenter = _sessionContextProvider.SessionContext.OrgIsCenter;
-        int orgLevel = _sessionContextProvider.SessionContext.OrgLevel;
-        var orgCode = _sessionContextProvider.SessionContext.OrgId;
-        var query = _orderRepository.Queryable();
-        if (IsCenter == true)
-            query = _orderRepository.Queryable(canView: !IsCenter);
-        return query
-            .Includes(d => d.OrderDelays)
-            .WhereIF(orgLevel == 3, d => SqlFunc.Subqueryable<WorkflowStep>()
-                .Where(step => step.ExternalId == d.Id && step.Status != EWorkflowStepStatus.Handled &&
-                               ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) &&
-                                 step.HandlerId == _sessionContextProvider.SessionContext.RequiredUserId) ||
-                                (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) &&
-                                 step.HandlerOrgId == _sessionContextProvider.SessionContext.RequiredOrgId) ||
-                                (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) &&
-                                 _sessionContextProvider.SessionContext.Roles.Contains(step.RoleId))))
-                .Any())
-             .WhereIF(orgLevel == 2 || orgLevel == 1, d => SqlFunc.Subqueryable<WorkflowStep>()
-                .Where(step => step.ExternalId == d.Id &&
-                               step.Status != EWorkflowStepStatus.Handled &&
-                               (!string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId.StartsWith(orgCode)))
-                .Any())
-            .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince)
-            .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No!))
-            .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title!))
-            .WhereIF(dto.Delay.HasValue && dto.Delay == 1, d => d.OrderDelays.Any() == true)
-            .WhereIF(dto.Delay.HasValue && dto.Delay == 2, d => d.OrderDelays.Any() == false)
-            .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始
-            .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束
-            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.AcceptTypeCode == dto.AcceptType) //受理类型
-            .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.FromPhone.Contains(dto.FromPhone)) //来电号码
-            .WhereIF(!string.IsNullOrEmpty(dto.HotspotName), d => d.HotspotSpliceName != null && d.HotspotSpliceName.Contains(dto.HotspotName))
-            .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始
-            .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) //超期时间结束
-            .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门
-                                                                                                                                   //&& stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value
-                                                                                                                                   //.Where(d => d.ExpiredTime != null &&
-                                                                                                                                   //         d.Status != EOrderStatus.Filed && d.Status != EOrderStatus.Published && d.Status != EOrderStatus.Visited && stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value)
-            .Where(d => d.Status < EOrderStatus.Filed && dateTime > d.NearlyExpiredTime && dateTime < d.ExpiredTime)
-            .OrderByIF(dto is { SortField: "no", SortRule: 0 }, x => x.No, OrderByType.Asc) //工单编号升序
-            .OrderByIF(dto is { SortField: "no", SortRule: 1 }, x => x.No, OrderByType.Desc) //工单编号降序
-            .OrderByIF(dto is { SortField: "isProvinceText", SortRule: 0 }, x => x.IsProvince, OrderByType.Asc)//是否省工单升序
-            .OrderByIF(dto is { SortField: "isProvinceText", SortRule: 1 }, x => x.IsProvince, OrderByType.Desc)//是否省工单降序
-            .OrderByIF(dto is { SortField: "currentStepName", SortRule: 0 }, x => x.CurrentStepName, OrderByType.Asc)//当前节点升序
-            .OrderByIF(dto is { SortField: "currentStepName", SortRule: 1 }, x => x.CurrentStepName, OrderByType.Desc)//当前节点降序
-            .OrderByIF(dto is { SortField: "delayText", SortRule: 0 }, x => x.OrderDelays.Count, OrderByType.Asc) //是否延期升序
-            .OrderByIF(dto is { SortField: "delayText", SortRule: 1 }, x => x.OrderDelays.Count, OrderByType.Desc) //是否延期升序
-            .OrderByIF(dto is { SortField: "statusText", SortRule: 0 }, x => x.Status, OrderByType.Asc) //工单状态升序
-            .OrderByIF(dto is { SortField: "statusText", SortRule: 1 }, x => x.Status, OrderByType.Desc) //工单状态升序
-            .OrderByIF(dto is { SortField: "startTime", SortRule: 0 }, x => x.StartTime, OrderByType.Asc) //受理时间升序
-            .OrderByIF(dto is { SortField: "startTime", SortRule: 1 }, x => x.StartTime, OrderByType.Desc) //受理时间降序
-            .OrderByIF(dto is { SortField: "expiredTime", SortRule: 0 }, x => x.ExpiredTime, OrderByType.Asc) //期满时间升序
-            .OrderByIF(dto is { SortField: "expiredTime", SortRule: 1 }, x => x.ExpiredTime, OrderByType.Desc) //期满时间降序
-            .OrderByIF(dto is { SortField: "actualHandleOrgName", SortRule: 0 }, x => x.ActualHandleOrgName, OrderByType.Asc)// 接办部门升序
-            .OrderByIF(dto is { SortField: "actualHandleOrgName", SortRule: 1 }, x => x.ActualHandleOrgName, OrderByType.Desc)// 接办部门降序
-            .OrderByIF(dto is { SortField: "acceptType", SortRule: 0 }, x => x.AcceptTypeCode, OrderByType.Asc) //受理类型升序
-            .OrderByIF(dto is { SortField: "acceptType", SortRule: 1 }, x => x.AcceptTypeCode, OrderByType.Desc) //受理类型降序
-            .OrderByIF(dto is { SortField: "counterSignTypeText", SortRule: 0 }, x => x.CounterSignType, OrderByType.Asc) //是否会签升序
-            .OrderByIF(dto is { SortField: "counterSignTypeText", SortRule: 1 }, x => x.CounterSignType, OrderByType.Desc) //是否会签降序
-            .OrderByIF(dto is { SortField: "orgLevelOneName", SortRule: 0 }, x => x.OrgLevelOneName, OrderByType.Asc) //一级部门升序
-            .OrderByIF(dto is { SortField: "orgLevelOneName", SortRule: 1 }, x => x.OrgLevelOneName, OrderByType.Desc)//一级部门降序
-            .OrderByIF(dto is { SortField: "hotspotName", SortRule: 0 }, x => x.HotspotId, OrderByType.Asc) //热点升序
-            .OrderByIF(dto is { SortField: "hotspotName", SortRule: 1 }, x => x.HotspotId, OrderByType.Desc) //热点降序
-            .OrderByIF(dto is { SortField: "acceptorName", SortRule: 0 }, x => x.AcceptorName, OrderByType.Asc)// 受理人升序
-            .OrderByIF(dto is { SortField: "acceptorName", SortRule: 1 }, x => x.AcceptorName, OrderByType.Desc);// 受理人升序
-    }
+		DateTime? dateTime = DateTime.Now;
+		var IsCenter = _sessionContextProvider.SessionContext.OrgIsCenter;
+		int orgLevel = _sessionContextProvider.SessionContext.OrgLevel;
+		var orgCode = _sessionContextProvider.SessionContext.OrgId;
+		var query = _orderRepository.Queryable();
+		if (IsCenter == true)
+			query = _orderRepository.Queryable(canView: !IsCenter);
+		return query
+			.Includes(d => d.OrderDelays)
+			.WhereIF(orgLevel == 3, d => SqlFunc.Subqueryable<WorkflowStep>()
+				.Where(step => step.ExternalId == d.Id && step.Status != EWorkflowStepStatus.Handled &&
+							   ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) &&
+								 step.HandlerId == _sessionContextProvider.SessionContext.RequiredUserId) ||
+								(step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) &&
+								 step.HandlerOrgId == _sessionContextProvider.SessionContext.RequiredOrgId) ||
+								(step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) &&
+								 _sessionContextProvider.SessionContext.Roles.Contains(step.RoleId))))
+				.Any())
+			 .WhereIF(orgLevel == 2 || orgLevel == 1, d => SqlFunc.Subqueryable<WorkflowStep>()
+				.Where(step => step.ExternalId == d.Id &&
+							   step.Status != EWorkflowStepStatus.Handled &&
+							   (!string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId.StartsWith(orgCode)))
+				.Any())
+			.WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince)
+			.WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No!))
+			.WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title!))
+			.WhereIF(dto.Delay.HasValue && dto.Delay == 1, d => d.OrderDelays.Any() == true)
+			.WhereIF(dto.Delay.HasValue && dto.Delay == 2, d => d.OrderDelays.Any() == false)
+			.WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始
+			.WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束
+			.WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.AcceptTypeCode == dto.AcceptType) //受理类型
+			.WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.FromPhone.Contains(dto.FromPhone)) //来电号码
+			.WhereIF(!string.IsNullOrEmpty(dto.HotspotName), d => d.HotspotSpliceName != null && d.HotspotSpliceName.Contains(dto.HotspotName))
+			.WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始
+			.WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) //超期时间结束
+			.WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门
+																																   //&& stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value
+																																   //.Where(d => d.ExpiredTime != null &&
+																																   //         d.Status != EOrderStatus.Filed && d.Status != EOrderStatus.Published && d.Status != EOrderStatus.Visited && stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value)
+			.Where(d => d.Status < EOrderStatus.Filed && dateTime > d.NearlyExpiredTime && dateTime < d.ExpiredTime)
+			.OrderByIF(dto is { SortField: "no", SortRule: 0 }, x => x.No, OrderByType.Asc) //工单编号升序
+			.OrderByIF(dto is { SortField: "no", SortRule: 1 }, x => x.No, OrderByType.Desc) //工单编号降序
+			.OrderByIF(dto is { SortField: "isProvinceText", SortRule: 0 }, x => x.IsProvince, OrderByType.Asc)//是否省工单升序
+			.OrderByIF(dto is { SortField: "isProvinceText", SortRule: 1 }, x => x.IsProvince, OrderByType.Desc)//是否省工单降序
+			.OrderByIF(dto is { SortField: "currentStepName", SortRule: 0 }, x => x.CurrentStepName, OrderByType.Asc)//当前节点升序
+			.OrderByIF(dto is { SortField: "currentStepName", SortRule: 1 }, x => x.CurrentStepName, OrderByType.Desc)//当前节点降序
+			.OrderByIF(dto is { SortField: "delayText", SortRule: 0 }, x => x.OrderDelays.Count, OrderByType.Asc) //是否延期升序
+			.OrderByIF(dto is { SortField: "delayText", SortRule: 1 }, x => x.OrderDelays.Count, OrderByType.Desc) //是否延期升序
+			.OrderByIF(dto is { SortField: "statusText", SortRule: 0 }, x => x.Status, OrderByType.Asc) //工单状态升序
+			.OrderByIF(dto is { SortField: "statusText", SortRule: 1 }, x => x.Status, OrderByType.Desc) //工单状态升序
+			.OrderByIF(dto is { SortField: "startTime", SortRule: 0 }, x => x.StartTime, OrderByType.Asc) //受理时间升序
+			.OrderByIF(dto is { SortField: "startTime", SortRule: 1 }, x => x.StartTime, OrderByType.Desc) //受理时间降序
+			.OrderByIF(dto is { SortField: "expiredTime", SortRule: 0 }, x => x.ExpiredTime, OrderByType.Asc) //期满时间升序
+			.OrderByIF(dto is { SortField: "expiredTime", SortRule: 1 }, x => x.ExpiredTime, OrderByType.Desc) //期满时间降序
+			.OrderByIF(dto is { SortField: "actualHandleOrgName", SortRule: 0 }, x => x.ActualHandleOrgName, OrderByType.Asc)// 接办部门升序
+			.OrderByIF(dto is { SortField: "actualHandleOrgName", SortRule: 1 }, x => x.ActualHandleOrgName, OrderByType.Desc)// 接办部门降序
+			.OrderByIF(dto is { SortField: "acceptType", SortRule: 0 }, x => x.AcceptTypeCode, OrderByType.Asc) //受理类型升序
+			.OrderByIF(dto is { SortField: "acceptType", SortRule: 1 }, x => x.AcceptTypeCode, OrderByType.Desc) //受理类型降序
+			.OrderByIF(dto is { SortField: "counterSignTypeText", SortRule: 0 }, x => x.CounterSignType, OrderByType.Asc) //是否会签升序
+			.OrderByIF(dto is { SortField: "counterSignTypeText", SortRule: 1 }, x => x.CounterSignType, OrderByType.Desc) //是否会签降序
+			.OrderByIF(dto is { SortField: "orgLevelOneName", SortRule: 0 }, x => x.OrgLevelOneName, OrderByType.Asc) //一级部门升序
+			.OrderByIF(dto is { SortField: "orgLevelOneName", SortRule: 1 }, x => x.OrgLevelOneName, OrderByType.Desc)//一级部门降序
+			.OrderByIF(dto is { SortField: "hotspotName", SortRule: 0 }, x => x.HotspotId, OrderByType.Asc) //热点升序
+			.OrderByIF(dto is { SortField: "hotspotName", SortRule: 1 }, x => x.HotspotId, OrderByType.Desc) //热点降序
+			.OrderByIF(dto is { SortField: "acceptorName", SortRule: 0 }, x => x.AcceptorName, OrderByType.Asc)// 受理人升序
+			.OrderByIF(dto is { SortField: "acceptorName", SortRule: 1 }, x => x.AcceptorName, OrderByType.Desc);// 受理人升序
+	}
 
     /// <summary>
     /// 即将超期列表
@@ -739,7 +739,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<Order> GetPublishOrderList(QueryOrderPublishDto dto)
     {
-        var query = _orderRepository.Queryable();
+        var query = _orderRepository.Queryable().Includes(d => d.OrderTags);
         if (_appOptions.Value.IsLuZhou)
             query = query.Includes(d => d.FwCallRecord);
         //.Includes(d => d.OrderPublish)
@@ -750,7 +750,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
               //.WhereIF(dto.PubState == EPubState.Pub, d => d.Status >= EOrderStatus.Published)
               //.WhereIF(dto.PubState == EPubState.NoPub, d => d.Status == EOrderStatus.Filed)
               .WhereIF(!string.IsNullOrEmpty(dto.Channel), d => d.SourceChannelCode == dto.Channel)
-              .WhereIF(!string.IsNullOrEmpty(dto.OrderTag), d => d.OrderTagCode == dto.OrderTag!) //工单标签
+              //.WhereIF(!string.IsNullOrEmpty(dto.OrderTag), d => d.OrderTagCode == dto.OrderTag!) //工单标签
+              .WhereIF(!string.IsNullOrEmpty(dto.OrderTag), d => d.OrderTags.Any(ot => ot.DicDataValue == dto.OrderTag)) //工单标签
               .WhereIF(!string.IsNullOrEmpty(dto.CenterToOrgHandlerName), d => d.CenterToOrgHandlerName.Contains(dto.CenterToOrgHandlerName)) //派单人
               .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName.Contains(dto.NameOrNo) || d.AcceptorStaffNo.Contains(dto.NameOrNo)) //受理人/坐席
               .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门(综合查询模糊)
@@ -1376,7 +1377,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     {
         var isCenter = _sessionContextProvider.SessionContext.OrgIsCenter;
 
-        var query = _orderRepository.Queryable();
+        var query = _orderRepository.Queryable(canView: false);
         if (!isCenter)
         {
             query.Where(d => SqlFunc.Subqueryable<WorkflowStep>()
@@ -1385,7 +1386,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                                step.HandlerOrgId.StartsWith(_sessionContextProvider.SessionContext.RequiredOrgId)).Any());
         }
 
-        query = query.Includes(x => x.OrderScreens);
+        query = query.Includes(d => d.OrderScreens).Includes(d => d.OrderTags);
 
         //if (!_appOptions.Value.IsYiBin)
         //{
@@ -1464,7 +1465,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
          .WhereIF(dto.IsSgin.HasValue && dto.IsSgin == false, d => d.CurrentStepAcceptTime == null)
          .WhereIF(dto.FiledType is FiledType.CenterFiled, d => d.FileOrgIsCenter == true)//d => d.ProcessType == EProcessType.Zhiban
          .WhereIF(dto.FiledType is FiledType.OrgFiled, d => d.FileOrgIsCenter == false)//d => d.ProcessType == EProcessType.Jiaoban
-         .WhereIF(!string.IsNullOrEmpty(dto.OrderTagCode), d => d.OrderTagCode == dto.OrderTagCode)
+                                                                                       //.WhereIF(!string.IsNullOrEmpty(dto.OrderTagCode), d => d.OrderTagCode == dto.OrderTagCode)// 工单标签
+         .WhereIF(!string.IsNullOrEmpty(dto.OrderTagCode), d => d.OrderTags.Any(ot => ot.DicDataValue == dto.OrderTagCode)) //工单标签
          .WhereIF(!string.IsNullOrEmpty(dto.FocusOnEvents), d => SqlFunc.SplitIn(d.FocusOnEvents, dto.FocusOnEvents))
          .OrderByIF(string.IsNullOrEmpty(dto.SortField), d => d.CreationTime, OrderByType.Desc)//默认排序时间为创建时间
          .OrderByIF(dto is { SortField: "no", SortRule: 0 }, d => d.No, OrderByType.Asc) //工单编号升序

+ 1 - 1
src/Hotline.Application/Quality/QualityApplication.cs

@@ -426,7 +426,7 @@ namespace Hotline.Application.Quality
 							if (statement.Count() == 2)
 							{
 								model.Sort = sort;
-								model.Type = statement[0].ToString() == "spk_01" ? EQualityTransferType.Seats : EQualityTransferType.Citizen;
+								model.Type = statement[0].ToString() == "spk_00" ? EQualityTransferType.Seats : EQualityTransferType.Citizen;
 								model.Content = statement[1].ToString();
 								model.ReviseContent = model.Content;
 								if (!string.IsNullOrEmpty(model.Content))

+ 4 - 1
src/Hotline.Application/Snapshot/ISnapshotBulletinApplication.cs

@@ -1,4 +1,6 @@
-using System;
+using Hotline.Share.Dtos.Snapshot;
+using SqlSugar;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -14,4 +16,5 @@ public interface ISnapshotBulletinApplication
     /// <param name="sHtmlText"></param>
     /// <returns></returns>
     string GetSiteUrls(string sHtmlText);
+    ISugarQueryable<SnapshotBulletinItemsOutDto> QueryBulletinItems(SnapshotBulletinItemsInDto dto);
 }

+ 5 - 2
src/Hotline.Application/Snapshot/Notifications/SnapshotHandler.cs

@@ -57,17 +57,20 @@ public class SnapshotHandler : ICapSubscribe, IScopeDependency
 public class SnapshotOrderFiledNotificationHandler : INotificationHandler<SnapshotOrderFiledNotification>
 {
     private readonly ISnapshotApplication _snapshotApplication;
+    private readonly IOrderSnapshotRepository _orderSnapshotRepository;
     private readonly ILogger<SnapshotOrderFiledNotificationHandler> _logger;
-    public SnapshotOrderFiledNotificationHandler(ISnapshotApplication snapshotApplication, ILogger<SnapshotOrderFiledNotificationHandler> logger)
+    public SnapshotOrderFiledNotificationHandler(ISnapshotApplication snapshotApplication, ILogger<SnapshotOrderFiledNotificationHandler> logger, IOrderSnapshotRepository orderSnapshotRepository)
     {
         _snapshotApplication = snapshotApplication;
         _logger = logger;
+        _orderSnapshotRepository = orderSnapshotRepository;
     }
     public async Task Handle(SnapshotOrderFiledNotification notification, CancellationToken cancellationToken)
     {
         try
         {
-            await _snapshotApplication.AddRedPardAsync(notification.OrderId, cancellationToken);
+            if (_orderSnapshotRepository.HasOrder(notification.OrderId))
+                await _snapshotApplication.AddRedPardAsync(notification.OrderId, cancellationToken);
         }
         catch (Exception e)
         {

+ 23 - 1
src/Hotline.Application/Snapshot/SnapshotBulletinApplication.cs

@@ -1,5 +1,10 @@
 using Hotline.Caching.Interfaces;
 using Hotline.Settings;
+using Hotline.Share.Attributes;
+using Hotline.Share.Dtos.Snapshot;
+using Hotline.Snapshot.Interfaces;
+using Microsoft.AspNetCore.Http;
+using SqlSugar;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -13,10 +18,12 @@ public class SnapshotBulletinApplication : ISnapshotBulletinApplication, IScopeD
 {
 
     private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+    private readonly ISnapshotBulletinRepository _bulletinRepository;
 
-    public SnapshotBulletinApplication(ISystemSettingCacheManager systemSettingCacheManager)
+    public SnapshotBulletinApplication(ISystemSettingCacheManager systemSettingCacheManager, ISnapshotBulletinRepository bulletinRepository)
     {
         _systemSettingCacheManager = systemSettingCacheManager;
+        _bulletinRepository = bulletinRepository;
     }
 
     /// <summary>
@@ -65,4 +72,19 @@ public class SnapshotBulletinApplication : ISnapshotBulletinApplication, IScopeD
 
         return sb.ToString();
     }
+
+    [ExportExcel("随手拍公告")]
+    public ISugarQueryable<SnapshotBulletinItemsOutDto> QueryBulletinItems(SnapshotBulletinItemsInDto dto)
+    {
+        var query = _bulletinRepository.Queryable()
+            .Includes(x => x.ExaminMan)
+            .WhereIF(!string.IsNullOrEmpty(dto.SnapshotBulletinTypeName), d => d.SnapshotBulletinTypeName.Contains(dto.SnapshotBulletinTypeName))
+            .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title))
+            .WhereIF(dto.BeginCreationTime.HasValue, d => d.BulletinTime >= dto.BeginCreationTime)
+            .WhereIF(dto.EndCreationTime.HasValue, d => d.BulletinTime <= dto.EndCreationTime)
+            .WhereIF(dto.State.HasValue, d => d.BulletinState == dto.State)
+            .OrderByDescending(d => d.CreationTime)
+            .Select<SnapshotBulletinItemsOutDto>();
+        return query;
+    }
 }

+ 2 - 0
src/Hotline.Application/Snapshot/SnapshotOrderApplication.cs

@@ -356,6 +356,7 @@ public class SnapshotOrderApplication : IOrderSnapshotApplication, IScopeDepende
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
+    [ExportExcel("工单标注日志")]
     public ISugarQueryable<LabelOrderSnapshotLogItemsOutDto> GetLabelOrderSnapshotLogItems(LabelOrderSnapshotLogItemsInDto dto)
     {
         var query = _snapshotLabelLogRepository.Queryable()
@@ -449,6 +450,7 @@ public class SnapshotOrderApplication : IOrderSnapshotApplication, IScopeDepende
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
+    [ExportExcel("工单标注")]
     public ISugarQueryable<LabeledOrderSnapshotItemsOutDto> GetLabeledOrderSnapshotItems(LabeledOrderSnapshotItemsInDto dto)
     {
         var query = _orderSnapshotRepository.Queryable()

+ 7 - 3
src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs

@@ -74,7 +74,7 @@ namespace Hotline.Repository.SqlSugar.Orders
             //弥补AddNav方法没有自动指派到创建人
             order.AssignToCreator(_dataPermissionFilterBuilder.DataPermissionManager);
 
-            await AddNav(order).Include(d => d.OrderExtension).ExecuteCommandAsync();
+            await AddNav(order).Include(d => d.OrderExtension).Include(d => d.OrderTags).ExecuteCommandAsync();
 
             return order.Id;
         }
@@ -1802,7 +1802,7 @@ namespace Hotline.Repository.SqlSugar.Orders
                 //      x => dto.OrgProcessingResults.Contains(SqlFunc.JsonField(x.OrgProcessingResults, "Key")))
                 //.WhereIF(dto.OrgHandledAttitude != null && dto.OrgHandledAttitude.Any(),
                 //     x => dto.OrgHandledAttitude.Contains(SqlFunc.JsonField(x.OrgHandledAttitude, "Key")))
-                .WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults),dto.AttitudeType == EAttitudeType.ProcessingResult ?x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults  :x => SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == dto.OrgProcessingResults)
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults), dto.AttitudeType == EAttitudeType.ProcessingResult ? x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults : x => SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == dto.OrgProcessingResults)
                 .WhereIF(!string.IsNullOrEmpty(dto.VisitUser), x => x.OrderVisit.Employee.Name.Contains(dto.VisitUser))
                 .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.OrderVisit.Order.No == dto.No)
                 .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.OrderVisit.Order.Title.Contains(dto.Title))
@@ -1819,6 +1819,8 @@ namespace Hotline.Repository.SqlSugar.Orders
                 .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true, x => x.OrderVisit.Order.Source == ESource.ProvinceStraight)
                 .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false, x => x.OrderVisit.Order.Source != ESource.ProvinceStraight)
                 .WhereIF(!string.IsNullOrEmpty(dto.ContentRetrieval), x => x.VisitContent.Contains(dto.ContentRetrieval!))
+                .WhereIF(!string.IsNullOrEmpty(dto.LevelOneOrg), x => x.OrderVisit.Order.OrgLevelOneName.Contains(dto.LevelOneOrg))//一级部门名称
+                .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), x => x.OrderVisit.Order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))// 接办部门
                 .Select(x => new OrgVisitDetailListResp()
                 {
                     Id = x.Id,
@@ -1886,6 +1888,7 @@ namespace Hotline.Repository.SqlSugar.Orders
                 .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true, x => x.OrderVisit.Order.Source == ESource.ProvinceStraight)
                 .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false, x => x.OrderVisit.Order.Source != ESource.ProvinceStraight)
                 .WhereIF(!string.IsNullOrEmpty(dto.ContentRetrieval), x => x.VisitContent.Contains(dto.ContentRetrieval!))
+                .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), x => x.OrderVisit.Order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName!))
                 .Select(x => new OrgVisitDetailListResp
                 {
                     Id = x.Id,
@@ -1908,7 +1911,8 @@ namespace Hotline.Repository.SqlSugar.Orders
                     FileOpinion = x.OrderVisit.Order.FileOpinion,
                     FiledTime = x.OrderVisit.Order.FiledTime,
                     VisitOrgName = x.VisitOrgName,
-                    IsProvinceOrder = x.OrderVisit.Order.Source == ESource.ProvinceStraight ? true : false
+                    IsProvinceOrder = x.OrderVisit.Order.Source == ESource.ProvinceStraight ? true : false,
+                    ActualHandleOrgName = x.OrderVisit.Order.ActualHandleOrgName
                 }).MergeTable()
                 .OrderByIF(string.IsNullOrEmpty(dto.SortField), x => x.VisitTime, OrderByType.Desc)
                 .OrderByIF(dto is { SortField: "creationTime", SortRule: 0 }, x => x.CreationTime, OrderByType.Asc) //受理时间升序

+ 5 - 0
src/Hotline.Repository.SqlSugar/Snapshot/OrderSnapshotRepository.cs

@@ -27,6 +27,11 @@ public class OrderSnapshotRepository : BaseRepository<OrderSnapshot>, IOrderSnap
         return await Queryable().Where(m => m.NetworkENumber == appealNumber).FirstAsync();
     }
 
+    public bool HasOrder(string orderId)
+    {
+        return Queryable().Any(m => m.Id == orderId);
+    }
+
     public async Task<OrderSnapshot> UpdateSafetyAsync(string orderId, bool isSafety, string remark)
     {
         OrderSnapshot order = null;

+ 5 - 0
src/Hotline.Share/Dtos/Bi/BiOrderDto.cs

@@ -71,6 +71,11 @@ namespace Hotline.Share.Dtos.Bi
         /// 内容检索(回访内容)
         /// </summary>
         public string? ContentRetrieval { get; set; }
+
+        /// <summary>
+        /// 接办部门
+        /// </summary>
+        public string? ActualHandleOrgName { get; set; }
     }
 
     public record HighFrequencyCallStatisticsRequest : PagedRequest

+ 18 - 7
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -2,6 +2,7 @@
 using Hotline.Share.Dtos.File;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Dtos.Hotspots;
+using Hotline.Share.Dtos.Settings;
 using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Enums.Settings;
@@ -91,10 +92,13 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 工单标签(自贡)
         /// </summary>
-        public string? OrderTag { get; set; }
+        public string? OrderTag => OrderTags != null && OrderTags.Any() ? string.Join(",", OrderTags.Select(x => x.DicDataName)) : string.Empty;
 
+        // public string? OrderTagCode => OrderTags != null && OrderTags.Any() ? string.Join(",", OrderTags.Select(x => x.DicDataValue)) : string.Empty; 
         public string? OrderTagCode { get; set; }
 
+        public List<SystemDicDataOutDto>? OrderTags { get; set; }
+
         #region 流程信息
 
         /// <summary>
@@ -658,7 +662,7 @@ namespace Hotline.Share.Dtos.Order
         {
             try
             {
-                if (Status >= EOrderStatus.Filed && FiledTime != null)
+                if (Status >= EOrderStatus.Filed && FiledTime != null && ExpiredTime != null)
                 {
                     return Math.Round((ExpiredTime.Value - FiledTime.Value).TotalDays, 1) + "天";
                 }
@@ -1150,12 +1154,13 @@ namespace Hotline.Share.Dtos.Order
 
         public string Title { get; set; }
 
-        /// <summary>
-        /// 工单标签(自贡)
-        /// </summary>
-        public string? OrderTag { get; set; }
+        //      /// <summary>
+        //      /// 工单标签(自贡)
+        //      /// </summary>
+        //      public string? OrderTag => OrderTags != null && OrderTags.Any() ? string.Join(",", OrderTags.Select(x => x.DicDataName)) : string.Empty;
 
-        public string? OrderTagCode { get; set; }
+
+        //public string? OrderTagCode { get; set; }
 
         #region 热点
 
@@ -1432,6 +1437,12 @@ namespace Hotline.Share.Dtos.Order
         ///知识库引用
         /// </summary>
         public List<Kv>? KnowledgeQuote { get; set; }
+
+        /// <summary>
+        /// 工单标签
+        /// </summary>
+        public List<string>? Tags { get; set; }
+
     }
 
     public record CanLinkCallRecordOrderDto : PagedKeywordRequest

+ 69 - 0
src/Hotline.Share/Dtos/Order/OrderFlowDto.cs

@@ -5,6 +5,7 @@ using System.Text;
 using System.Threading.Tasks;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Dtos.TrCallCenter;
+using Hotline.Share.Enums.Settings;
 
 namespace Hotline.Share.Dtos.Order
 {
@@ -39,5 +40,73 @@ namespace Hotline.Share.Dtos.Order
         /// 非警情退回
         /// </summary>
         public bool IsNonPoliceReturn { get; set; }
+
+        /// <summary>
+        /// 是否存在延期申请
+        /// </summary>
+        public OrderSearchDelayDto? OrderSearchDelay { get; set; }
+    }
+
+    public class OrderSearchDelayDto
+    {
+        /// <summary>
+        /// 延期申请Id
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 流程ID
+        /// </summary>
+        public string? WorkflowId { get; set; }
+
+        /// <summary>
+        /// 工单Id
+        /// </summary>
+        public string OrderId { get; set; }
+
+        /// <summary>
+        /// 工单编号(冗余)
+        /// </summary>
+        public string No { get; set; }
+
+        /// <summary>
+        /// 申请部门Code
+        /// </summary>
+        public string ApplyOrgCode { get; set; }
+
+        /// <summary>
+        /// 申请部门名称
+        /// </summary>
+        public string ApplyOrgName { get; set; }
+
+        /// <summary>
+        /// 申请人
+        /// </summary>
+        public string EmployeeId { get; set; }
+
+        /// <summary>
+        /// 申请人名称
+        /// </summary>
+        public string? EmployeeName { get; set; }
+
+        /// <summary>
+        /// 延期申请时限
+        /// </summary>
+        public int DelayNum { get; set; }
+
+        /// <summary>
+        /// 延期申请单位
+        /// </summary>
+        public ETimeType DelayUnit { get; set; }
+
+        /// <summary>
+        /// 延期申请理由
+        /// </summary>
+        public string DelayReason { get; set; }
+
+        /// <summary>
+        /// 延期申请时间
+        /// </summary>
+        public DateTime ApplyDelayTime { get; set; }
     }
 }

+ 16 - 0
src/Hotline.Share/Dtos/Order/OrderRelationTagDto.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Order
+{
+	public class OrderRelationTagDto
+	{
+		/// <summary>
+		/// 标签ID
+		/// </summary>
+		public string Id { get; set; }
+	}
+}

+ 10 - 0
src/Hotline.Share/Dtos/Order/OrderVisitDto.cs

@@ -1124,6 +1124,16 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public string? VisitContent { get; set; }
 
+        /// <summary>
+        /// 部门是否联系
+        /// </summary>
+        public bool? IsContact { get; set; }
+
+        /// <summary>
+        /// 是否解决问题
+        /// </summary>
+        public bool? Volved { get; set; }
+
     }
 
     public class OrderVisitProvinceDto

+ 1 - 1
src/Hotline.Share/Dtos/Snapshot/OrderDto.cs

@@ -108,7 +108,7 @@ public class AddSnapshotOrderInDto : Position
     /// 1: 气割;
     /// 2: 其他;
     /// </summary>
-    public EJobType? JobType { get; set; }
+    public int? JobType { get; set; }
 
     /// <summary>
     /// 经营单位类别

+ 28 - 1
src/Hotline.Share/Dtos/WebPortal/ArticleDetailsDto.cs

@@ -21,6 +21,11 @@ namespace Hotline.Share.Dtos.WebPortal
         /// 公告ID
         /// </summary>
         public string Id { get; set; }
+
+        /// <summary>
+        /// 分类名称
+        /// </summary>
+        public string TypeName { get; set; }
     }
 
     public class ArticleIdByNumDto
@@ -58,7 +63,7 @@ namespace Hotline.Share.Dtos.WebPortal
         /// <summary>
         /// 公告范围,不传默认查询门户网站  0:全部;1:微信小程序;2:门户网站;4:市民APP;8:部门APP
         /// </summary>
-        public string? PushRanges {  get; set; }
+        public string? PushRanges { get; set; }
     }
 
     /// <summary>
@@ -121,6 +126,11 @@ namespace Hotline.Share.Dtos.WebPortal
         /// 公告标题
         /// </summary>
         public string NoticeTitle { get; set; }
+
+        /// <summary>
+        /// 分类
+        /// </summary>
+        public string NoticeTypeName { get; set; }
     }
 
     /// <summary>
@@ -190,6 +200,23 @@ namespace Hotline.Share.Dtos.WebPortal
         public IReadOnlyList<ArticleListDto> data { get; set; }
     }
 
+    public class ArticleDetailDataDto
+    {
+        /// <summary>
+        /// 总条数
+        /// </summary>
+        public int Page { get; set; }
+
+        /// <summary>
+        /// 总页数
+        /// </summary>
+        public string NoticeID { get; set; }
+        public string NoticeTitle { get; set; }
+
+        public string NoticeTypeName { get; set; }
+        public DateTime NoticeCreateDate { get; set; }
+    }
+
     /// <summary>
     /// 公告列表
     /// </summary>

+ 14 - 0
src/Hotline.Share/Dtos/WebPortal/WaitVisitListDataDto.cs

@@ -57,5 +57,19 @@
         /// </summary>
         public string? SatisfactionCode { get; set; }
 
+        /// <summary>
+        /// 部门是否联系
+        /// </summary>
+        public bool? IsContact { get; set; }
+
+        /// <summary>
+        /// 是否解决问题
+        /// </summary>
+        public bool? Volved { get; set; }
+
+        /// <summary>
+        /// 不满意原因
+        /// </summary>
+        public List<Kv>? OrgNoSatisfiedReason { get; set; }
     }
 }

+ 1 - 1
src/Hotline.Share/Dtos/WebPortal/WebFlowAcceptDto.cs

@@ -81,7 +81,7 @@ namespace Hotline.Share.Dtos.WebPortal
         public string Content { get; set; }
 
         /// <summary>
-        /// 来源方式 APP来源为2,微信来源为3,宜宾人社来源9,
+        /// 来源方式 APP来源为2,微信小程序来源为3,宜宾人社来源9,
         /// </summary>
         public string? FromID { get; set; }
 

+ 0 - 29
src/Hotline.Share/Enums/Snapshot/EJobType.cs

@@ -1,29 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Hotline.Share.Enums.Snapshot;
-public enum EJobType
-{
-
-    /// <summary>
-    /// 电焊
-    /// </summary>
-    [Description("电焊")]
-    Electric,
-
-    /// <summary>
-    /// 气割
-    /// </summary>
-    [Description("气割")]
-    Gas,
-
-    /// <summary>
-    /// 其他
-    /// </summary>
-    [Description("其他")]
-    Othoer
-}

+ 1 - 1
src/Hotline.Share/Hotline.Share.csproj

@@ -7,7 +7,7 @@
     <GenerateDocumentationFile>True</GenerateDocumentationFile>
     <NoWarn>$(NoWarn);1591;8618;</NoWarn>
     <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-    <Version>1.0.114</Version>
+    <Version>1.0.118</Version>
   </PropertyGroup>
 
   <ItemGroup>

+ 6 - 1
src/Hotline.Share/Requests/PagedKeywordRequest.cs

@@ -556,6 +556,11 @@ public record OrgVisitDetailListReq : PagedKeywordRequest
     /// </summary>
     public string? LevelOneOrg { get; set; }
 
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string? ActualHandleOrgName { get; set; }
+
     /// <summary>
     /// 部门分类
     /// </summary>
@@ -564,7 +569,7 @@ public record OrgVisitDetailListReq : PagedKeywordRequest
     /// <summary>
     /// 部门办件结果
     /// </summary>
-    public string? OrgProcessingResults { get; set; } 
+    public string? OrgProcessingResults { get; set; }
 
     /// <summary>
     /// 回访人

+ 1 - 1
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -1106,7 +1106,7 @@ namespace Hotline.FlowEngine.Workflows
             if (prevStep == null)
                 throw UserFriendlyException.SameMessage("未查询到前一节点");
 
-            if (prevStep.IsCountersignEndStep)
+            while (prevStep.IsCountersignEndStep)
             {
                 countersignStartStep = workflow.Steps.FirstOrDefault(d => d.Id == prevStep.CountersignStartStepId);
                 prevStep = countersignStartStep ?? throw new UserFriendlyException("未查询到对应会签开始节点");

+ 0 - 1
src/Hotline/KnowledgeBase/Knowledge.cs

@@ -18,7 +18,6 @@ namespace Hotline.KnowledgeBase;
 /// </summary>
 [Description("知识库文档")]
 [SugarIndex("index_knowledge_hotspotId", nameof(Knowledge.HotspotId), OrderByType.Desc)]
-[SugarIndex("index_knowledge_attribution", nameof(Knowledge.Attribution), OrderByType.Desc)]
 [SugarIndex("index_knowledge_creatorOrgId", nameof(Knowledge.CreatorOrgId), OrderByType.Desc)]
 public class Knowledge : WorkflowEntity//   WorkflowEntity  FullStateEntity
 {

+ 1 - 0
src/Hotline/KnowledgeBase/KnowledgeDomainService.cs

@@ -104,6 +104,7 @@ namespace Hotline.KnowledgeBase
             {
                 CreationTime = DateTime.Now,
                 KnowledgeCode = know.Code,
+                KnowledgeId = know.Id,
                 BrowseTime = browseTime
             };
             //浏览记录写入

+ 6 - 0
src/Hotline/KnowledgeBase/KnowledgePV.cs

@@ -8,6 +8,12 @@ namespace Hotline.KnowledgeBase;
 /// </summary>
 public class KnowledgePv : CreationEntity
 {
+    /// <summary>
+    /// 知识Code
+    /// </summary>
+    [SugarColumn(ColumnDescription = "知识Id")]
+    public string? KnowledgeId { get; set; }
+
     /// <summary>
     /// 知识Code
     /// </summary>

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

@@ -50,8 +50,11 @@ public class KnowledgeType : FullStateEntity
     /// 类型关联机构
     /// </summary>
     [Navigate(NavigateType.OneToMany, nameof(KnowledgeTypeOrg.TypeId))]
-    public List<KnowledgeTypeOrg>  KnowledgeTypeOrgs { get; set; }
+    public List<KnowledgeTypeOrg> KnowledgeTypeOrgs { get; set; }
 
     [Navigate(typeof(KnowledgeTypeOrg), nameof(KnowledgeTypeOrg.TypeId), nameof(KnowledgeTypeOrg.OrgId))]
     public List<SystemOrganize> Orgs { get; set; }
+
+    [Navigate(typeof(KnowledgeRelationType), nameof(KnowledgeRelationType.KnowledgeTypeId), nameof(KnowledgeRelationType.KnowledgeId))]
+    public List<Knowledge> Knowledges { get; set; }
 }

+ 24 - 12
src/Hotline/Orders/Order.cs

@@ -16,6 +16,7 @@ using XF.Domain.Exceptions;
 using XF.Domain.Extensions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
+using Hotline.KnowledgeBase;
 
 namespace Hotline.Orders
 {
@@ -172,21 +173,32 @@ namespace Hotline.Orders
         [SugarColumn(ColumnDescription = "标题")]
         public string Title { get; set; }
 
-        /// <summary>
-        /// 工单标签(自贡)
-        /// </summary>
-        [SugarColumn(ColumnDescription = "工单标签")]
-        public string? OrderTag { get; set; }
+		#region 工单标签(自贡)
+		/// <summary>
+		/// 工单标签(自贡)-- 弃用
+		/// </summary>
+		[SugarColumn(ColumnDescription = "工单标签-- 弃用")]
+		public string? OrderTag { get; set; }
 
-        [SugarColumn(ColumnDescription = "工单标签代码")]
-        public string? OrderTagCode { get; set; }
+		[SugarColumn(ColumnDescription = "工单标签代码-- 弃用")]
+		public string? OrderTagCode { get; set; }
 
-        #region 热点
 
-        /// <summary>
-        /// 热点
-        /// </summary>
-        [SugarColumn(ColumnDescription = "热点ID")]
+
+		/// <summary>
+		/// 工单标签
+		/// </summary>
+		[Navigate(typeof(OrderRelationTag), nameof(OrderRelationTag.OrderId), nameof(OrderRelationTag.TagId))]
+		public List<SystemDicData> OrderTags { get; set; }
+
+		#endregion
+
+		#region 热点
+
+		/// <summary>
+		/// 热点
+		/// </summary>
+		[SugarColumn(ColumnDescription = "热点ID")]
         public string? HotspotId { get; set; }
 
         //public string? HotspotCode { get; set; }

+ 2 - 4
src/Hotline/Orders/OrderDomainService.cs

@@ -760,8 +760,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
         return valid;
     }
     #endregion
-
-
+    
     #region 即将超期和超期短信
 
     /// <summary>
@@ -817,8 +816,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
     }
 
     #endregion
-
-
+    
     #region private
 
     private async Task<Order> GetOrderByFlowIdAsync(string workflowId, CancellationToken cancellationToken)

+ 24 - 0
src/Hotline/Orders/OrderRelationTag.cs

@@ -0,0 +1,24 @@
+using Hotline.KnowledgeBase;
+using SqlSugar;
+using System.ComponentModel;
+using XF.Domain.Entities;
+
+namespace Hotline.Orders
+{
+	[Description("工单关联标签")]
+	public class OrderRelationTag : ITable, IEntity
+	{
+
+		/// <summary>
+		/// 工单ID
+		/// </summary>
+		[SugarColumn(IsPrimaryKey = true)]
+		public string OrderId { get; set; }
+
+		/// <summary>
+		/// 标签ID
+		/// </summary>
+		[SugarColumn(IsPrimaryKey = true)]
+		public string TagId { get; set; }
+	}
+}

+ 2 - 2
src/Hotline/SeedData/SystemDicDataSeedData.cs

@@ -120,8 +120,8 @@ public class SystemDicDataSeedData : ISeedData<SystemDicData>
         if (dicTypeCode == SysDicTypeConsts.JobType)
         {
             return [
-                new() { Id = "08dc3c1e-470f-4a7d-8433-3fed9bb59c95", DicDataValue = "dianhan", DicDataName = "电焊"},
-                new() { Id = "08dc3cc4-aa8b-41ad-8807-ba1571e00628", DicDataValue = "qige", DicDataName = "气割"},
+                new() { Id = "08dc3c1e-470f-4a7d-8433-3fed9bb59c95", DicDataValue = "0", DicDataName = "电焊"},
+                new() { Id = "08dc3cc4-aa8b-41ad-8807-ba1571e00628", DicDataValue = "1", DicDataName = "气割"},
                 ];
         }
         if (dicTypeCode == SysDicTypeConsts.BusinessUnitType)

+ 7 - 0
src/Hotline/Snapshot/Interfaces/IOrderSnapshotRepository.cs

@@ -18,4 +18,11 @@ public interface IOrderSnapshotRepository : IRepository<OrderSnapshot>
     Task<OrderSnapshot> GetByNetworkENumberAsync(string appealNumber);
 
     Task<OrderSnapshot> UpdateSafetyAsync(string orderId, bool isSafety, string remark);
+
+    /// <summary>
+    /// 是否有随手拍工单
+    /// </summary>
+    /// <param name="orderId"></param>
+    /// <returns></returns>
+    bool HasOrder(string orderId);
 }

+ 6 - 1
src/Hotline/Snapshot/OrderSnapshot.cs

@@ -45,7 +45,12 @@ public class OrderSnapshot : CreationSoftDeleteEntity
     /// 作业类型
     /// </summary>
     [SugarColumn(ColumnDescription = "作业类型")]
-    public EJobType? JobType { get; set; }
+    public int? JobType { get; set; }
+
+    /// <summary>
+    /// 作业类型
+    /// </summary>
+    public string? JobTypeName { get; set; }
 
     /// <summary>
     /// 经营单位类别

+ 0 - 2
src/XingTang.Sdk/XingtangCall.cs

@@ -127,8 +127,6 @@ public class XingtangCall
     /// </summary>
     public string? OrgCaller { get; set; }
 
-    public string? Customerid { get; set; }
-
     #region 未启用
 
     public int? MutiCall { get; set; }