Browse Source

Merge branch 'master' of http://git.12345lm.cn/Fengwo/hotline

Dun.Jason 1 năm trước cách đây
mục cha
commit
1fbe78d3c7
31 tập tin đã thay đổi với 417 bổ sung192 xóa
  1. 21 1
      src/Hotline.Api/Controllers/DataSharing/EnterpriseController.cs
  2. 12 6
      src/Hotline.Api/Controllers/DataSharing/ProvinceController.cs
  3. 37 23
      src/Hotline.Api/Controllers/OrderController.cs
  4. 23 3
      src/Hotline.Api/Controllers/QualityController.cs
  5. 4 2
      src/Hotline.Api/Controllers/TestController.cs
  6. 1 3
      src/Hotline.Api/Controllers/WorkflowController.cs
  7. 37 18
      src/Hotline.Api/Realtimes/HotlineHub.cs
  8. 5 0
      src/Hotline.Api/Realtimes/RealtimeMethods.cs
  9. 8 10
      src/Hotline.Api/Realtimes/RealtimeService.cs
  10. 1 1
      src/Hotline.Api/config/appsettings.json
  11. 43 37
      src/Hotline.Application/Bigscreen/BigscreenDataShowRefreshService.cs
  12. 7 1
      src/Hotline.Application/FlowEngine/IWorkflowApplication.cs
  13. 19 6
      src/Hotline.Application/FlowEngine/WorkflowApplication.cs
  14. 38 18
      src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs
  15. 12 2
      src/Hotline.Application/Handlers/FlowEngine/WorkflowPreviousHandler.cs
  16. 23 0
      src/Hotline.Application/Handlers/Order/AddOrderTracesAsyncNotifyHandler.cs
  17. 23 0
      src/Hotline.Application/Handlers/Order/CancelOrderAsyncNotifyHandler.cs
  18. 1 1
      src/Hotline.Application/Handlers/Order/DelayProvinceResultNotifyHandler.cs
  19. 4 2
      src/Hotline.Application/Handlers/Order/OrderResultNotifyHandler.cs
  20. 1 1
      src/Hotline.Application/Handlers/Order/ScreenProvinceResultNotifyHandler.cs
  21. 1 1
      src/Hotline.Application/Orders/IOrderApplication.cs
  22. 2 3
      src/Hotline.Application/Orders/OrderApplication.cs
  23. 12 1
      src/Hotline.Share/Dtos/Order/OrderVisitDto.cs
  24. 4 1
      src/Hotline/DataSharing/Province/Notifications/DelayProvinceResultNotify.cs
  25. 5 1
      src/Hotline/DataSharing/Province/Notifications/OrderResultNotify.cs
  26. 4 1
      src/Hotline/DataSharing/Province/Notifications/ScreenProvinceResultNotify.cs
  27. 4 9
      src/Hotline/DataSharing/Province/Services/IProvinceService.cs
  28. 45 31
      src/Hotline/DataSharing/Province/Services/ProvinceService.cs
  29. 9 9
      src/Hotline/Orders/Order.cs
  30. 5 0
      src/Hotline/Orders/OrderVisit.cs
  31. 6 0
      src/Hotline/Realtimes/IRealtimeService.cs

+ 21 - 1
src/Hotline.Api/Controllers/DataSharing/EnterpriseController.cs

@@ -1,9 +1,12 @@
 using DotNetCore.CAP;
 using Hotline.DataSharing;
 using Hotline.DataSharing.Enterprise;
+using Hotline.DataSharing.Order;
+using Hotline.DataSharing.Province.Notifications;
 using Hotline.Share.Dtos.DataSharing;
 using Hotline.Share.Dtos.DataSharing.Enterprise.Receive;
 using MapsterMapper;
+using MediatR;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using Sharing.Share.Dtos.DataSharing.Enterprise;
@@ -20,17 +23,25 @@ namespace Hotline.Api.Controllers.DataSharing
         private readonly IMapper _mapper;
         private readonly IRepository<DsReceiveWriteResult> _receiveWriteResultRepository;
         private readonly EnterpriseClient _enterpriseClient;
+        private readonly IMediator _mediator;
+        private readonly IRepository<DsOrder> _dataOrderRepository;
 
         /// <summary>
         /// 
         /// </summary>
         /// <param name="mapper"></param>
         /// <param name="receiveWriteResultRepository"></param>
-        public EnterpriseController(IMapper mapper, IRepository<DsReceiveWriteResult> receiveWriteResultRepository, EnterpriseClient enterpriseClient)
+        /// <param name="enterpriseClient"></param>
+        /// <param name="mediator"></param>
+        /// <param name="dataOrderRepository"></param>
+        public EnterpriseController(IMapper mapper, IRepository<DsReceiveWriteResult> receiveWriteResultRepository, EnterpriseClient enterpriseClient,
+         IMediator mediator, IRepository<DsOrder> dataOrderRepository)
         {
             _mapper = mapper;
             _receiveWriteResultRepository = receiveWriteResultRepository;
             _enterpriseClient = enterpriseClient;
+            _mediator = mediator;
+            _dataOrderRepository = dataOrderRepository;
         }
 
         /// <summary>
@@ -78,6 +89,15 @@ namespace Hotline.Api.Controllers.DataSharing
             var id = await _receiveWriteResultRepository.AddAsync(data, HttpContext.RequestAborted);
             if (!string.IsNullOrEmpty(id))
             {
+                string FinishType = "";
+                if (dto.ReplyResultType == 2)
+                    FinishType = "0";
+                else if (dto.ReplyResultType == 1)
+                    FinishType = "1";
+
+                var order = await _dataOrderRepository.GetAsync(p => p.OrderNo == dto.ReplyCode, HttpContext.RequestAborted);
+                if (order != null)
+                    await _mediator.Send(new OrderResultNotify { OrderId = order.OrderId, FinishType = FinishType, Opinion = dto.ReplyContent }, HttpContext.RequestAborted);
                 //向业务系统推送消息
                 // await _capPublisher.PublishAsync("", _mapper.Map<DataWriteResultDto>(dto), cancellationToken: HttpContext.RequestAborted);
                 //这里往业务系统推送数据

+ 12 - 6
src/Hotline.Api/Controllers/DataSharing/ProvinceController.cs

@@ -237,8 +237,9 @@ namespace Hotline.Api.Controllers.DataSharing
             var id = await InitReceiveProvinceData(dto.CaseSerial, dto.CliengGuid, "send_supervise_info", System.Text.Json.JsonSerializer.Serialize(dto));
             if (!string.IsNullOrEmpty(id))
             {
+                var listFiles = await GetFileData(dto.CliengGuid, dto.CaseSerial, "督办工单派发");
                 //向业务系统推送消息
-                await _mediator.Send(new ProvinceOrderSuperviseNotify { ProvinceOrderSuperviseDto = _mapper.Map<ProvinceOrderSuperviseDto>(dto) }, HttpContext.RequestAborted);
+                await _mediator.Send(new ProvinceOrderSuperviseNotify { ProvinceOrderSuperviseDto = _mapper.Map<ProvinceOrderSuperviseDto>(dto), Files = listFiles }, HttpContext.RequestAborted);
                 return OpenResponse.Ok(Reponse.Success("您已成功提交数据!"));
 
             }
@@ -305,7 +306,8 @@ namespace Hotline.Api.Controllers.DataSharing
 
             if (!string.IsNullOrEmpty(id))
             {
-                await _mediator.Send(new ScreenProvinceResultNotify { ProvinceScreenResult = _mapper.Map<ProvinceScreenResult>(dto) }, HttpContext.RequestAborted);
+                var listFiles = await GetFileData(dto.CliengGuid, dto.CaseSerial, "工单甄别结果");
+                await _mediator.Send(new ScreenProvinceResultNotify { ProvinceScreenResult = _mapper.Map<ProvinceScreenResult>(dto), Files = listFiles }, HttpContext.RequestAborted);
 
                 return OpenResponse.Ok(Reponse.Success("您已成功提交数据!"));
             }
@@ -338,8 +340,9 @@ namespace Hotline.Api.Controllers.DataSharing
 
             if (!string.IsNullOrEmpty(id))
             {
+                var listFiles = await GetFileData(dto.CliengGuid, dto.CaseSerial, "工单延期审核结果");
                 //向业务系统推送消息
-                await _mediator.Send(new DelayProvinceResultNotify { IsPass = dto.AuditResult == "1", Opinion = dto.AuditOpinion, No = dto.CaseSerial }, HttpContext.RequestAborted);
+                await _mediator.Send(new DelayProvinceResultNotify { IsPass = dto.AuditResult == "1", Opinion = dto.AuditOpinion, No = dto.CaseSerial, Files = listFiles }, HttpContext.RequestAborted);
                 return OpenResponse.Ok(Reponse.Success("您已成功提交数据!"));
             }
             else
@@ -404,7 +407,7 @@ namespace Hotline.Api.Controllers.DataSharing
 
             if (!string.IsNullOrEmpty(id))
             {
-              var data=  await _dataOrderRepository.GetAsync(p => p.ProvinceNo == dto.CaseSerial, HttpContext.RequestAborted);
+                var data = await _dataOrderRepository.GetAsync(p => p.ProvinceNo == dto.CaseSerial, HttpContext.RequestAborted);
                 if (data != null)
                     await _mediator.Send(new CancelOrderAsyncNotify { Opinion = dto.RevokeReasion, OrderId = data.OrderId });
                 //向业务系统推送消息
@@ -513,7 +516,10 @@ namespace Hotline.Api.Controllers.DataSharing
                     //将工单的办理状态改为办理完成,终止拉取办理信息
                     tempData.IsEnd = true;
                     await _sendCaseInfoRepository.UpdateAsync(tempData, HttpContext.RequestAborted);
+
+                    await _mediator.Send(new OrderResultNotify { OrderId = tempData.OrderID, FinishType = dto.FinishType, Opinion = dto.FdBack }, HttpContext.RequestAborted);
                 }
+
                 //向业务系统推送消息
                 //await _capPublisher.PublishAsync(Sharing.Share.Mq.EventNames.SharingOrderReultSend, _mapper.Map<ReultSendDto>(dto), cancellationToken: HttpContext.RequestAborted);
                 return OpenResponse.Ok(Reponse.Success("您已成功提交数据!"));
@@ -750,11 +756,11 @@ namespace Hotline.Api.Controllers.DataSharing
                             break;
                         case "screen_case_result_receive":
                             listFiles = await InitFileData(listData, "工单甄别结果");
-                            await _mediator.Send(new ScreenProvinceResultNotify { ProvinceScreenResult = new() { CaseSerial = tmpCaseMaterialInfo.CaseSerial } }, HttpContext.RequestAborted);
+                            await _mediator.Send(new ScreenProvinceResultNotify { ProvinceScreenResult = new() { CaseSerial = tmpCaseMaterialInfo.CaseSerial }, Files = listFiles }, HttpContext.RequestAborted);
                             break;
                         case "delay_case_result_receive":
                             listFiles = await InitFileData(listData, "工单延期审核结果");
-                            await _mediator.Send(new DelayProvinceResultNotify { No = tmpCaseMaterialInfo.CaseSerial }, HttpContext.RequestAborted);
+                            await _mediator.Send(new DelayProvinceResultNotify { No = tmpCaseMaterialInfo.CaseSerial, Files = listFiles }, HttpContext.RequestAborted);
                             break;
                         case "supply_case_info_receive":
                             listFiles = await InitFileData(listData, "工单补充");

+ 37 - 23
src/Hotline.Api/Controllers/OrderController.cs

@@ -85,9 +85,10 @@ public class OrderController : BaseController
     private readonly IRepository<OrderSpecial> _orderSpecialRepository;
     private readonly IRepository<WorkflowTrace> _workflowTraceRepository;
     private readonly IRepository<TrCallRecord> _trCallRecordRepository;
+    private readonly ILogger<OrderController> _logger;
 
 
-	public OrderController(
+    public OrderController(
         IOrderDomainService orderDomainService,
         IOrderRepository orderRepository,
         IWorkflowApplication workflowApplication,
@@ -128,9 +129,8 @@ public class OrderController : BaseController
         IRepository<OrderSendBack> orderSendBackRepository,
         IRepository<OrderSpecial> orderSpecialRepository,
         IRepository<WorkflowTrace> workflowTraceRepository,
-		IRepository<TrCallRecord> trCallRecordRepository
-
-	)
+		IRepository<TrCallRecord> trCallRecordRepository,
+        ILogger<OrderController> logger)
     {
         _orderDomainService = orderDomainService;
         _orderRepository = orderRepository;
@@ -173,8 +173,8 @@ public class OrderController : BaseController
         _orderSpecialRepository = orderSpecialRepository;
         _workflowTraceRepository = workflowTraceRepository;
         _trCallRecordRepository = trCallRecordRepository;
-
-	}
+        _logger = logger;
+    }
 
     #region 工单发布
 
@@ -597,19 +597,26 @@ public class OrderController : BaseController
                 //        FirstSatisfactionCode = visit.Order.FirstVisitResultCode!,
                 //        ClientGuid = ""
                 //    });
-                await _provinceService.SubmitVisitInfo(new PublishVisitDto()
+                try
                 {
-                    Order = orderDto,
-                    No = visit.No,
-                    VisitType = visit.VisitType,
-                    VisitName = visit.CreatorName,
-                    VisitTime = visit.VisitTime,
-                    VisitRemark = first.VisitContent,
-                    AreaCode = visit.Order.AreaCode!,
-                    SubjectResultSatifyCode = first.OrgProcessingResults.Key,
-                    FirstSatisfactionCode = visit.Order.FirstVisitResultCode!,
-                    ClientGuid = ""
-                }, HttpContext.RequestAborted);
+                    await _provinceService.SubmitVisitInfo(new PublishVisitDto()
+                    {
+                        Order = orderDto,
+                        No = visit.No,
+                        VisitType = visit.VisitType,
+                        VisitName = visit.CreatorName,
+                        VisitTime = visit.VisitTime,
+                        VisitRemark = first.VisitContent,
+                        AreaCode = visit.Order.AreaCode!,
+                        SubjectResultSatifyCode = first.OrgProcessingResults.Key,
+                        FirstSatisfactionCode = visit.Order.FirstVisitResultCode!,
+                        ClientGuid = ""
+                    }, HttpContext.RequestAborted);
+                }
+                catch (Exception e)
+                {
+                    _logger.LogError("_provinceService.SubmitVisitInfo throw exception: {ex}", e.Message);
+                }
             }
             if (first != null)
             {
@@ -1384,12 +1391,19 @@ public class OrderController : BaseController
                     //    Supervise = superviseDto,
                     //    ClientGuid = ""
                     //});
-                    await _provinceService.SendSuperviseProcessInfo(new PublishSuperviseDto()
+                    try
                     {
-                        Order = orderDto,
-                        Supervise = superviseDto,
-                        ClientGuid = ""
-                    }, HttpContext.RequestAborted);
+                        await _provinceService.SendSuperviseProcessInfo(new PublishSuperviseDto()
+                        {
+                            Order = orderDto,
+                            Supervise = superviseDto,
+                            ClientGuid = ""
+                        }, HttpContext.RequestAborted);
+                    }
+                    catch (Exception e)
+                    {
+                        _logger.LogError("_provinceService.SendSuperviseProcessInfo throw exception: {ex}", e.Message);
+                    }
                 }
             }
         }

+ 23 - 3
src/Hotline.Api/Controllers/QualityController.cs

@@ -17,6 +17,7 @@ using Hotline.Share.Enums.Order;
 using XF.Utility.EnumExtensions;
 using System.Xml.Linq;
 using System.Threading;
+using Hotline.CallCenter.Calls;
 
 namespace Hotline.Api.Controllers
 {
@@ -31,6 +32,7 @@ namespace Hotline.Api.Controllers
 		private readonly IRepository<QualityTemplateDetail> _qualiteyTemplateDetail;
 		private readonly IRepository<QualityProhibited> _qualiteyProhibited;
 		private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
+		private readonly IRepository<TrCallRecord> _trCallRecordRepository;
 
 		public QualityController(
 			ISessionContext sessionContext,
@@ -41,7 +43,8 @@ namespace Hotline.Api.Controllers
 			IRepository<QualityTemplate> qualityTemplate,
 			IRepository<QualityTemplateDetail> qualiteyTemplateDetail,
 			IRepository<QualityProhibited> qualiteyProhibited,
-			ISystemDicDataCacheManager systemDicDataCacheManager
+			ISystemDicDataCacheManager systemDicDataCacheManager,
+			IRepository<TrCallRecord> trCallRecordRepository
 		)
 		{
 			_sessionContext = sessionContext;
@@ -53,6 +56,7 @@ namespace Hotline.Api.Controllers
 			_qualiteyTemplateDetail = qualiteyTemplateDetail;
 			_qualiteyProhibited = qualiteyProhibited;
 			_systemDicDataCacheManager = systemDicDataCacheManager;
+			_trCallRecordRepository = trCallRecordRepository;
 		}
 		#region 质检管理
 		/// <summary>
@@ -99,6 +103,8 @@ namespace Hotline.Api.Controllers
 				.WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!))
 				.WhereIF(dto.State.HasValue, d => d.State == dto.State)
 				.WhereIF(dto.Source.HasValue, d => d.Source == dto.Source)
+				.WhereIF(dto.Source.HasValue && dto.Source == EQualitySource.Accepted, x=> !string.IsNullOrEmpty(x.Order.CallId))
+				.WhereIF(dto.Source.HasValue && dto.Source == EQualitySource.Visit, x => !string.IsNullOrEmpty(x.Visit.CallId))
 				.WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
 				.WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
 				.OrderByDescending(x => x.CreationTime)
@@ -112,11 +118,25 @@ namespace Hotline.Api.Controllers
 		/// <param name="id"></param>
 		/// <returns></returns>
 		[HttpGet("{id}")]
-		public async Task<Quality.Quality> Entity(string id)
+		public async Task<QualityDto> Entity(string id)
 		{
-			return await _qualitey.Queryable()
+			var quality =	await _qualitey.Queryable()
+				.Includes(x => x.Order)
+				.Includes(x => x.Visit)
+				.Includes(x => x.Visit, e => e.Employee)
 				.Includes(x => x.QualityDetails)
 				.FirstAsync(x => x.Id == id);
+			var qualityDto = _mapper.Map<QualityDto>(quality);
+			if (qualityDto.Order != null) {
+				var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Order.CallId).FirstAsync();
+				if (call != null) qualityDto.Order.RecordingFileUrl = call.RecordingFileUrl;
+			}
+			if (qualityDto.Visit != null)
+			{
+				var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Visit.CallId).FirstAsync();
+				if (call != null) qualityDto.Visit.RecordingFileUrl = call.RecordingFileUrl;
+			}
+			return qualityDto;
 		}
 		#endregion
 

+ 4 - 2
src/Hotline.Api/Controllers/TestController.cs

@@ -1,9 +1,11 @@
 using Hotline.CallCenter.BlackLists;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Ivrs;
+using Hotline.DataSharing.Province.Notifications;
 using Hotline.FlowEngine.WorkflowModules;
 using Hotline.Identity.Roles;
 using Hotline.Orders;
+using Hotline.Orders.Notifications;
 using Hotline.Realtimes;
 using Hotline.Repository.SqlSugar;
 using Hotline.Repository.SqlSugar.Ts;
@@ -110,9 +112,9 @@ public class TestController : BaseController
     }
 
     [HttpGet("testo")]
-    public Task<OpenResponse> TestOrigin()
+    public async Task<OpenResponse> TestOrigin()
     {
-        return Task.FromResult(OpenResponse.Ok(DateTime.Today.ToString()));
+        return OpenResponse.Ok(DateTime.Today.ToString());
     }
 
     [HttpGet("time")]

+ 1 - 3
src/Hotline.Api/Controllers/WorkflowController.cs

@@ -324,9 +324,7 @@ public class WorkflowController : BaseController
     [HttpPost("previous")]
     public async Task Previous([FromBody] PreviousWorkflowDto dto)
     {
-        var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true,
-            cancellationToken: HttpContext.RequestAborted);
-        await _workflowDomainService.PreviousAsync(workflow, dto, HttpContext.RequestAborted);
+        await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
     }
 
     /// <summary>

+ 37 - 18
src/Hotline.Api/Realtimes/HotlineHub.cs

@@ -34,25 +34,29 @@ namespace Hotline.Api.Realtimes
         /// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that represents the asynchronous connect.</returns>
         public override async Task OnConnectedAsync()
         {
-            var userId = _sessionContext.RequiredUserId;
-            //todo 检查是否exists , t:说明可能是断线重连,1.set cache 2.依据缓存加入group f: 1.set cache
-            //await SetConnectionAsync(new RealtimeConnection(userId, Context.ConnectionId), Context.ConnectionAborted);
-            var connection = await _cacheConnection.GetAsync(userId, Context.ConnectionAborted);
-            if (connection == null)
-            {
-                await SetConnectionAsync(new RealtimeConnection(userId, Context.ConnectionId), Context.ConnectionAborted);
-            }
-            else
+            var userId = _sessionContext.UserId;
+            if (!string.IsNullOrEmpty(userId))
             {
-                connection.ConnectionId = Context.ConnectionId;
-                await SetConnectionAsync(connection, Context.ConnectionAborted);
-
-                if (connection.GroupNames.Any())
+                //todo 检查是否exists , t:说明可能是断线重连,1.set cache 2.依据缓存加入group f: 1.set cache
+                //await SetConnectionAsync(new RealtimeConnection(userId, Context.ConnectionId), Context.ConnectionAborted);
+                var connection = await _cacheConnection.GetAsync(userId, Context.ConnectionAborted);
+                if (connection == null)
                 {
-                    foreach (var groupName in connection.GroupNames)
+                    await SetConnectionAsync(new RealtimeConnection(userId, Context.ConnectionId), Context.ConnectionAborted);
+                }
+                else
+                {
+                    connection.ConnectionId = Context.ConnectionId;
+                    await SetConnectionAsync(connection, Context.ConnectionAborted);
+
+                    if (connection.GroupNames.Any())
                     {
-                        await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
-                        await Clients.Group(groupName).SendAsync("Send", $"{Context.ConnectionId} has joined the group {groupName}.");
+                        foreach (var groupName in connection.GroupNames)
+                        {
+                            await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
+                            await Clients.Group(groupName)
+                                .SendAsync("Send", $"{Context.ConnectionId} has joined the group {groupName}.");
+                        }
                     }
                 }
             }
@@ -98,10 +102,17 @@ namespace Hotline.Api.Realtimes
             await Clients.Group(dto.GroupName).SendAsync("Send", $"{Context.ConnectionId} has joined the group {dto.GroupName}.");
         }
 
+        public async Task JoinGroupUnauthAsync(JoinGroupDto dto)
+        {
+            CheckIfConnected();
+            await Groups.AddToGroupAsync(Context.ConnectionId, dto.GroupName);
+            await Clients.Group(dto.GroupName).SendAsync("Send", $"{Context.ConnectionId} has joined the group {dto.GroupName}.");
+        }
+
         public async Task LeaveGroupAsync(JoinGroupDto dto)
         {
             CheckIfConnected();
-            
+
             var userId = _sessionContext.RequiredUserId;
             var connection = await GetConnectionAsync(userId, Context.ConnectionAborted);
             if (connection is null)
@@ -121,6 +132,13 @@ namespace Hotline.Api.Realtimes
             //    Context.Abort();
         }
 
+        public async Task LeaveGroupUnauthAsync(JoinGroupDto dto)
+        {
+            CheckIfConnected();
+            await Groups.RemoveFromGroupAsync(Context.ConnectionId, dto.GroupName);
+            await Clients.Group(dto.GroupName).SendAsync("Send", $"{Context.ConnectionId} has left the group {dto.GroupName}.");
+        }
+
         #region private
 
         private void CheckIfConnected()
@@ -138,6 +156,7 @@ namespace Hotline.Api.Realtimes
         {
             return _cacheConnection.SetAsync(connection.UserId, connection, TimeSpan.FromDays(7), cancellationToken);
         }
+
         #endregion
     }
-}
+}

+ 5 - 0
src/Hotline.Api/Realtimes/RealtimeMethods.cs

@@ -44,6 +44,11 @@
 
         #endregion
 
+        #region 大屏-数据展示
+
+        public static string BsDataShow = "BsDataShow";
+
+        #endregion
     }
 }
     

+ 8 - 10
src/Hotline.Api/Realtimes/RealtimeService.cs

@@ -138,7 +138,7 @@ public class RealtimeService : IRealtimeService, IScopeDependency
         if (record.CircularType == Share.Enums.Article.ECircularType.Person)
         {
             //个人
-            await SendMsgToUserAsync(record.UserId, RealtimeMethods.CircularRecord,
+            await SendToUserAsync(record.UserId, RealtimeMethods.CircularRecord,
                 new CircularRecoordDto() { CircularType = Share.Enums.Article.ECircularType.Person, Count = record.RecordCount },
                 cancellationToken);
         }
@@ -150,7 +150,7 @@ public class RealtimeService : IRealtimeService, IScopeDependency
             {
                 try
                 {
-                    await SendMsgToUserAsync(user.Id, RealtimeMethods.CircularRecord,
+                    await SendToUserAsync(user.Id, RealtimeMethods.CircularRecord,
                         new CircularRecoordDto()
                             { CircularType = Share.Enums.Article.ECircularType.Org, Count = record.RecordCount },
                         cancellationToken);
@@ -164,12 +164,10 @@ public class RealtimeService : IRealtimeService, IScopeDependency
 
     #endregion
 
-    #region 通用
+    #region 大屏.数据展示
 
-    //public int GetGroupMemberCount(string groupName)
-    //{
-    //    _hubContext.Clients.Group(groupName)
-    //}
+    public Task BsDataShowChangedAsync(object obj, CancellationToken cancellationToken) =>
+        SendToGroupAsync(RealtimeGroupNames.BigScreenDataShow, RealtimeMethods.BsDataShow, obj, cancellationToken);
 
     #endregion
 
@@ -195,14 +193,14 @@ public class RealtimeService : IRealtimeService, IScopeDependency
             throw UserFriendlyException.SameMessage($"该用户不属于分组:{groupName}");
     }
 
-    private async Task SendMsgToUserAsync(string userId, string msg, object? value, CancellationToken cancellationToken)
+    private async Task SendToUserAsync(string userId, string msg, object? value, CancellationToken cancellationToken)
     {
         var connection = await _realtimeCacheManager.GetConnectionAsync(userId, cancellationToken);
         await _hubContext.Clients.Client(connection.ConnectionId).SendAsync(msg, value, cancellationToken);
     }
 
-    private Task SendMsgToGroupAsync(string groupName, string msg, object? value, CancellationToken cancellationToken) => 
-        _hubContext.Clients.Group(groupName).SendAsync(msg, value, cancellationToken);
+    private Task SendToGroupAsync(string groupName, string method, object? value, CancellationToken cancellationToken) =>
+        _hubContext.Clients.Group(groupName).SendAsync(method, value, cancellationToken);
 
     #endregion
 }

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

@@ -56,7 +56,7 @@
       "Issuer": "hotline_server",
       "Audience": "hotline",
       "Scope": "hotline_api",
-      "Expired": 86400 //seceonds
+      "Expired": 3600 //seceonds
     }
   },
   "DatabaseConfiguration": {

+ 43 - 37
src/Hotline.Application/Bigscreen/BigscreenDataShowRefreshService.cs

@@ -1,42 +1,48 @@
-//using System;
-//using System.Collections.Generic;
-//using System.Linq;
-//using System.Text;
-//using System.Threading.Tasks;
-//using Hotline.Realtimes;
-//using Microsoft.Extensions.DependencyInjection;
-//using Microsoft.Extensions.Hosting;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Hotline.Realtimes;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
 
-//namespace Hotline.Application.Bigscreen
-//{
-//    public class BigscreenDataShowRefreshService : BackgroundService
-//    {
-//        private readonly IServiceScopeFactory _serviceScopeFactory;
+namespace Hotline.Application.Bigscreen
+{
+    public class BigscreenDataShowRefreshService : BackgroundService
+    {
+        private readonly IServiceScopeFactory _serviceScopeFactory;
 
-//        public BigscreenDataShowRefreshService(IServiceScopeFactory serviceScopeFactory)
-//        {
-//            _serviceScopeFactory = serviceScopeFactory;
-//        }
+        public BigscreenDataShowRefreshService(IServiceScopeFactory serviceScopeFactory)
+        {
+            _serviceScopeFactory = serviceScopeFactory;
+        }
 
-//        /// <summary>
-//        /// This method is called when the <see cref="T:Microsoft.Extensions.Hosting.IHostedService" /> starts. The implementation should return a task that represents
-//        /// the lifetime of the long running operation(s) being performed.
-//        /// </summary>
-//        /// <param name="stoppingToken">Triggered when <see cref="M:Microsoft.Extensions.Hosting.IHostedService.StopAsync(System.Threading.CancellationToken)" /> is called.</param>
-//        /// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that represents the long running operations.</returns>
-//        /// <remarks>See <see href="https://docs.microsoft.com/dotnet/core/extensions/workers">Worker Services in .NET</see> for implementation guidelines.</remarks>
-//        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
-//        {
-//            using var scope = _serviceScopeFactory.CreateScope();
-//            var realtimeService = scope.ServiceProvider.GetService<IRealtimeService>();
+        /// <summary>
+        /// This method is called when the <see cref="T:Microsoft.Extensions.Hosting.IHostedService" /> starts. The implementation should return a task that represents
+        /// the lifetime of the long running operation(s) being performed.
+        /// </summary>
+        /// <param name="stoppingToken">Triggered when <see cref="M:Microsoft.Extensions.Hosting.IHostedService.StopAsync(System.Threading.CancellationToken)" /> is called.</param>
+        /// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that represents the long running operations.</returns>
+        /// <remarks>See <see href="https://docs.microsoft.com/dotnet/core/extensions/workers">Worker Services in .NET</see> for implementation guidelines.</remarks>
+        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+        {
+            using var scope = _serviceScopeFactory.CreateScope();
+            var realtimeService = scope.ServiceProvider.GetRequiredService<IRealtimeService>();
 
-//            while (!stoppingToken.IsCancellationRequested)
-//            {
-//                //todo
-                
+            while (!stoppingToken.IsCancellationRequested)
+            {
+                //todo
+                var data = new {
+                    Name = "John",
+                    Age = 20,
+                };
 
-//                await Task.Delay(30000, stoppingToken);
-//            }
-//        }
-//    }
-//}
+                await realtimeService.BsDataShowChangedAsync(data, stoppingToken);
+
+                await Task.Delay(30000, stoppingToken);
+            }
+        }
+    }
+}

+ 7 - 1
src/Hotline.Application/FlowEngine/IWorkflowApplication.cs

@@ -1,6 +1,7 @@
 using Hotline.FlowEngine.Definitions;
 using Hotline.Orders;
 using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.File;
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.FlowEngine.Definition;
 using Hotline.Share.Dtos.Settings;
@@ -20,6 +21,11 @@ namespace Hotline.Application.FlowEngine
         /// 流转至下一节点(节点办理)
         /// </summary>
         Task NextAsync(NextWorkflowDto dto, CancellationToken cancellationToken);
+        
+        /// <summary>
+        /// 退回(返回前一节点)
+        /// </summary>
+        Task PreviousAsync(PreviousWorkflowDto dto, CancellationToken cancellationToken);
 
         /// <summary>
         /// 撤回至任意节点
@@ -39,7 +45,7 @@ namespace Hotline.Application.FlowEngine
         /// <summary>
         /// 跳转至结束节点(无视流程模板配置直接跳至结束节点)
         /// </summary>
-        Task JumpToEndAsync(string workflowId, string opinion, EReviewResult? reviewResult = EReviewResult.Unknown,
+        Task JumpToEndAsync(string workflowId, string opinion,List<FileDto> file, EReviewResult? reviewResult = EReviewResult.Unknown,
             CancellationToken cancellationToken = default);
 
         /// <summary>

+ 19 - 6
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -28,6 +28,7 @@ using XF.Domain.Exceptions;
 using XF.Domain.Extensions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
+using Hotline.Share.Dtos.File;
 
 namespace Hotline.Application.FlowEngine;
 
@@ -242,6 +243,16 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             cancellationToken);
     }
 
+    /// <summary>
+    /// 退回(返回前一节点)
+    /// </summary>
+    public async Task PreviousAsync(PreviousWorkflowDto dto, CancellationToken cancellationToken)
+    {
+        var workflow =
+            await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true, cancellationToken: cancellationToken);
+        await _workflowDomainService.PreviousAsync(workflow, dto, cancellationToken);
+    }
+
     /// <summary>
     /// 撤回至任意节点
     /// </summary>
@@ -299,7 +310,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     /// <summary>
     /// 跳转至结束节点(无视流程模板配置直接跳至结束节点)
     /// </summary>
-    public async Task JumpToEndAsync(string workflowId, string opinion, EReviewResult? reviewResult = EReviewResult.Unknown,
+    public async Task JumpToEndAsync(string workflowId, string opinion, List<FileDto> files,
+        EReviewResult? reviewResult = EReviewResult.Unknown,
         CancellationToken cancellationToken = default)
     {
         var workflow =
@@ -311,9 +323,10 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         if (currentStep is null)
             throw new UserFriendlyException("未找到实际办理节点");
 
-        var endTrace = await _workflowDomainService.EndAsync(workflow, new BasicWorkflowDto
+        await _workflowDomainService.EndAsync(workflow, new BasicWorkflowDto
             {
                 Opinion = opinion,
+                Files = files
             }, endStepDefine, currentStep,
             reviewResult, cancellationToken);
     }
@@ -717,7 +730,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         CancellationToken cancellationToken)
     {
         var handlers = new List<Kv>();
-        if (stepDefine.StepType is EStepType.Start or EStepType.End)
+        if (stepDefine.StepType is EStepType.End)
         {
             return new NextStepOption
             {
@@ -742,8 +755,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                 //当前操作人所属部门的下级部门并且属于配置包含角色
                 var roles = await _roleRepository.Queryable()
                     .Includes(
-                        d => d.Accounts.Where(
-                            x => !x.IsDeleted && x.Status == EAccountStatus.Normal).ToList(),
+                        d => d.Accounts.Where(x =>
+                            !x.IsDeleted && x.Status == EAccountStatus.Normal && x.AccountType == EAccountType.Personal).ToList(),
                         x => x.User)
                     .Where(d => stepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Name))
                     .ToListAsync(cancellationToken);
@@ -751,7 +764,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
 
                 //工单办理:除一级部门选择中心汇总(中心会签流程,返回topCountersignStep场景),其余只能选下级部门
                 if (flowType is EFlowType.Handle
-                    && (stepDefine.StepType != EStepType.Summary || stepDefine.BusinessType != EBusinessType.Center))
+                    && (stepDefine.StepType != EStepType.Summary && stepDefine.BusinessType != EBusinessType.Center))
                     users1 = users1.Where(d => d.OrgId.StartsWith(levelOneOrgId));
 
                 handlers = users1.Select(d => new Kv(d.Id, d.Name)).ToList();

+ 38 - 18
src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs

@@ -18,6 +18,7 @@ using Hotline.Share.Mq;
 using MapsterMapper;
 using MediatR;
 using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Logging;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 
@@ -44,6 +45,7 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
     private readonly IRepository<OrderDelay> _orderDelayRepository;
     private readonly IRepository<OrderVisitApply> _orderVisitApplyRepository;
     private readonly IMediator _mediator;
+    private readonly ILogger<WorkflowEndHandler> _logger;
 
     public WorkflowEndHandler(
         IKnowledgeDomainService knowledgeDomainService,
@@ -63,8 +65,8 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
         IRepository<OrderDelay> orderDelayRepository,
         IRepository<OrderVisit> orderVisitRepository,
         IRepository<OrderVisitApply> orderVisitApplyRepository,
-        IMediator mediator
-        )
+        IMediator mediator,
+        ILogger<WorkflowEndHandler> logger)
     {
         _knowledgeDomainService = knowledgeDomainService;
         _orderDomainService = orderDomainService;
@@ -84,6 +86,7 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
         _orderVisitRepository = orderVisitRepository;
         _orderVisitApplyRepository = orderVisitApplyRepository;
         _mediator = mediator;
+        _logger = logger;
     }
 
     /// <summary>Handles a notification</summary>
@@ -124,12 +127,20 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
                 //    Order = _mapper.Map<OrderDto>(order),
                 //    WorkflowTrace = _mapper.Map<WorkflowTraceDto>(notification.Trace)
                 //}, cancellationToken: cancellationToken);
-                await _provinceService.OrderFiled(new OrderFlowDto
+                try
                 {
-                    Order = _mapper.Map<OrderDto>(order),
-                    WorkflowTrace = _mapper.Map<WorkflowTraceDto>(notification.Trace)
-                }, cancellationToken: cancellationToken);
 
+                    await _provinceService.OrderFiled(new OrderFlowDto
+                    {
+                        Order = _mapper.Map<OrderDto>(order),
+                        WorkflowTrace = _mapper.Map<WorkflowTraceDto>(notification.Trace)
+                    }, cancellationToken: cancellationToken);
+
+                }
+                catch (Exception e)
+                {
+                    _logger.LogError("_provinceService.OrderFiled throw exception: {ex}", e.Message);
+                }
                 break;
             case WorkflowModuleConsts.OrderScreen:
                 var screen = await _orderScreenRepository.GetAsync(workflow.ExternalId, cancellationToken);
@@ -171,19 +182,28 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
                                 //        FirstSatisfactionCode = visit.Order.FirstVisitResultCode!,
                                 //        ClientGuid = ""
                                 //    });
-                                await _provinceService.SubmitOrderScreenSuccess(new PublishVisitDto()
+                                try
+                                {
+
+                                    await _provinceService.SubmitOrderScreenSuccess(new PublishVisitDto()
+                                    {
+                                        Order = _mapper.Map<OrderDto>(visit.Order),
+                                        No = visit.No,
+                                        VisitType = visit.VisitType,
+                                        VisitName = visit.CreatorName,
+                                        VisitTime = visit.VisitTime,
+                                        VisitRemark = visitDe.VisitContent,
+                                        AreaCode = visit.Order.AreaCode!,
+                                        SubjectResultSatifyCode = visitDe.OrgProcessingResults?.Key,
+                                        FirstSatisfactionCode = visit.Order.FirstVisitResultCode!,
+                                        ClientGuid = ""
+                                    }, cancellationToken);
+
+                                }
+                                catch (Exception e)
                                 {
-                                    Order = _mapper.Map<OrderDto>(visit.Order),
-                                    No = visit.No,
-                                    VisitType = visit.VisitType,
-                                    VisitName = visit.CreatorName,
-                                    VisitTime = visit.VisitTime,
-                                    VisitRemark = visitDe.VisitContent,
-                                    AreaCode = visit.Order.AreaCode!,
-                                    SubjectResultSatifyCode = visitDe.OrgProcessingResults?.Key,
-                                    FirstSatisfactionCode = visit.Order.FirstVisitResultCode!,
-                                    ClientGuid = ""
-                                }, cancellationToken);
+                                    _logger.LogError("_provinceService.SubmitOrderScreenSuccess throw exception: {ex}", e.Message);
+                                }
                             }
                         }
                     }

+ 12 - 2
src/Hotline.Application/Handlers/FlowEngine/WorkflowPreviousHandler.cs

@@ -31,6 +31,7 @@ namespace Hotline.Application.Handlers.FlowEngine
         private readonly IProvinceService _provinceService;
         private readonly ICapPublisher _capPublisher;
         private readonly IMapper _mapper;
+        private readonly ILogger<WorkflowPreviousHandler> _logger;
 
         public WorkflowPreviousHandler(
             IOrderDomainService orderDomainService,
@@ -39,7 +40,8 @@ namespace Hotline.Application.Handlers.FlowEngine
             ITimeLimitDomainService timeLimitDomainService,
             IProvinceService provinceService,
             ICapPublisher capPublisher,
-            IMapper mapper)
+            IMapper mapper,
+            ILogger<WorkflowPreviousHandler> logger)
         {
             _orderDomainService = orderDomainService;
             _orderRepository = orderRepository;
@@ -48,6 +50,7 @@ namespace Hotline.Application.Handlers.FlowEngine
             _provinceService = provinceService;
             _capPublisher = capPublisher;
             _mapper = mapper;
+            _logger = logger;
         }
 
         /// <summary>Handles a notification</summary>
@@ -79,7 +82,14 @@ namespace Hotline.Application.Handlers.FlowEngine
 
                         var dto = _mapper.Map<OrderDto>(order);
                         //await _capPublisher.PublishAsync(EventNames.HotlineOrderExpiredTimeUpdate, dto, cancellationToken: cancellationToken);
-                        await _provinceService.HotlineOrderFlowRecalled(dto, cancellationToken);
+                        try
+                        {
+                            await _provinceService.HotlineOrderFlowRecalled(dto, cancellationToken);
+                        }
+                        catch (Exception e)
+                        {
+                            _logger.LogError("_provinceService.HotlineOrderFlowRecalled throw exception: {ex}", e.Message);
+                        }
                     }
 
                     break;

+ 23 - 0
src/Hotline.Application/Handlers/Order/AddOrderTracesAsyncNotifyHandler.cs

@@ -0,0 +1,23 @@
+using Hotline.Application.Orders;
+using Hotline.DataSharing.Province.Notifications;
+using MediatR;
+
+namespace Hotline.Application.Handlers.Order;
+
+public class AddOrderTracesAsyncNotifyHandler:INotificationHandler<AddOrderTracesAsyncNotify>
+{
+    private readonly IOrderApplication _orderApplication;
+
+    public AddOrderTracesAsyncNotifyHandler(IOrderApplication orderApplication)
+    {
+        _orderApplication = orderApplication;
+    }
+    
+    /// <summary>Handles a notification</summary>
+    /// <param name="notification">The notification</param>
+    /// <param name="cancellationToken">Cancellation token</param>
+    public async Task Handle(AddOrderTracesAsyncNotify notification, CancellationToken cancellationToken)
+    {
+        await _orderApplication.AddOrderTracesAsync(notification.OrderId, notification.Traces, cancellationToken);
+    }
+}

+ 23 - 0
src/Hotline.Application/Handlers/Order/CancelOrderAsyncNotifyHandler.cs

@@ -0,0 +1,23 @@
+using Hotline.Application.Orders;
+using Hotline.DataSharing.Province.Notifications;
+using MediatR;
+
+namespace Hotline.Application.Handlers.Order;
+
+public class CancelOrderAsyncNotifyHandler : INotificationHandler<CancelOrderAsyncNotify>
+{
+    private readonly IOrderApplication _orderApplication;
+
+    public CancelOrderAsyncNotifyHandler(IOrderApplication orderApplication)
+    {
+        _orderApplication = orderApplication;
+    }
+    
+    /// <summary>Handles a notification</summary>
+    /// <param name="notification">The notification</param>
+    /// <param name="cancellationToken">Cancellation token</param>
+    public async Task Handle(CancelOrderAsyncNotify notification, CancellationToken cancellationToken)
+    {
+        await _orderApplication.CancelOrderAsync(notification.OrderId, notification.Opinion, cancellationToken);
+    }
+}

+ 1 - 1
src/Hotline.Application/Handlers/Order/DelayProvinceResultNotifyHandler.cs

@@ -45,7 +45,7 @@ namespace Hotline.Application.Handlers.Order
 
             if (dto.IsPass)
             {
-                await _workflowApplication.JumpToEndAsync(orderDelay.WorkflowId, dto.Opinion, EReviewResult.Approval,
+                await _workflowApplication.JumpToEndAsync(orderDelay.WorkflowId, dto.Opinion, notification.Files,EReviewResult.Approval,
                     cancellationToken);
             }
             else

+ 4 - 2
src/Hotline.Application/Handlers/Order/OrderResultNotifyHandler.cs

@@ -2,6 +2,7 @@
 using Hotline.DataSharing.Province.Notifications;
 using Hotline.File;
 using Hotline.Orders;
+using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.Order;
 using MapsterMapper;
@@ -29,10 +30,11 @@ namespace Hotline.Application.Handlers.Order
             {
 				if ("0".Equals(request.FinishType))
 				{
-					//todo  等_workflowApplication 新加一个退回上一个节点的方法
+					await _workflowApplication.PreviousAsync(
+						new PreviousWorkflowDto { WorkflowId = order.WorkflowId, Opinion = request.Opinion, Files = request.Files }, cancellationToken: cancellationToken);
 				}
 				else if ("1".Equals(request.FinishType)) {
-					await _workflowApplication.JumpToEndAsync(order.WorkflowId, request.Opinion, cancellationToken: cancellationToken);
+					await _workflowApplication.JumpToEndAsync(order.WorkflowId, request.Opinion, request.Files, cancellationToken: cancellationToken);
 				}
 			}
         }

+ 1 - 1
src/Hotline.Application/Handlers/Order/ScreenProvinceResultNotifyHandler.cs

@@ -47,7 +47,7 @@ namespace Hotline.Application.Handlers.Order
             var pass = "1".Equals(dto.AuditResult);
             if (pass)
             {
-                await _workflowApplication.JumpToEndAsync(orderScreen.WorkflowId, dto.AuditOpinion, EReviewResult.Approval,
+                await _workflowApplication.JumpToEndAsync(orderScreen.WorkflowId, dto.AuditOpinion, notification.Files,EReviewResult.Approval,
                     cancellationToken);
             }
             else

+ 1 - 1
src/Hotline.Application/Orders/IOrderApplication.cs

@@ -19,7 +19,7 @@ namespace Hotline.Application.Orders
         /// 1.更新工单 2.更新流程 3.推送省平台
         /// </summary>
         /// <returns></returns>
-        Task DelayOrderHandleExpiredTimeAsync(Order order, ETimeType timeType, int timeCount, bool publishToProvince = true);
+        Task DelayOrderExpiredTimeAsync(Order order, ETimeType timeType, int timeCount, bool publishToProvince = true);
 
         /// <summary>
         /// 新增工单办理流程记录

+ 2 - 3
src/Hotline.Application/Orders/OrderApplication.cs

@@ -41,7 +41,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// 1.更新工单 2.更新流程 3.推送省平台
     /// </summary>
     /// <returns></returns>
-    public async Task DelayOrderHandleExpiredTimeAsync(Order order, ETimeType timeType, int timeCount,
+    public async Task DelayOrderExpiredTimeAsync(Order order, ETimeType timeType, int timeCount,
         bool publishToProvince = true)
     {
         var expiredTime = _timeLimitDomainService.CalcEndTime(order.ExpiredTime.Value, timeType, timeCount, false);
@@ -51,8 +51,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <summary>
     /// 新增工单办理流程记录
     /// </summary>
-    public async Task AddOrderTracesAsync(string orderId, ICollection<WorkflowTraceDto> traces,
-        CancellationToken cancellationToken)
+    public async Task AddOrderTracesAsync(string orderId, ICollection<WorkflowTraceDto> traces, CancellationToken cancellationToken)
     {
         var order = await _orderRepository.GetAsync(orderId, cancellationToken);
         if (order is null)

+ 12 - 1
src/Hotline.Share/Dtos/Order/OrderVisitDto.cs

@@ -293,7 +293,18 @@ namespace Hotline.Share.Dtos.Order
         /// 回访明细
         /// </summary>
         public List<OrderVisitDetailDto> OrderVisitDetails { get; set; }
-    }
+
+
+        /// <summary>
+        /// 可直接访问的通话录音地址
+        /// </summary>
+        public string? RecordingFileUrl { get; set; }
+
+        /// <summary>
+        /// 渠道为电话时,此字段存在
+        /// </summary>
+        public string? CallId { get; set; }
+	}
 
     public class OrderVisitDetailDto
     {

+ 4 - 1
src/Hotline/DataSharing/Province/Notifications/DelayProvinceResultNotify.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Hotline.Share.Dtos.File;
 using MediatR;
 
 namespace Hotline.DataSharing.Province.Notifications
@@ -26,5 +27,7 @@ namespace Hotline.DataSharing.Province.Notifications
         /// 办理意见
         /// </summary>
         public string Opinion { get; set; }
-    }
+
+        public List<FileDto> Files { get; set; }
+	}
 }

+ 5 - 1
src/Hotline/DataSharing/Province/Notifications/OrderResultNotify.cs

@@ -1,4 +1,5 @@
-using MediatR;
+using Hotline.Share.Dtos.File;
+using MediatR;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -7,6 +8,7 @@ using System.Threading.Tasks;
 
 namespace Hotline.DataSharing.Province.Notifications
 {
+	// 不接受补附件
 	public class OrderResultNotify : INotification
 	{
 		public string OrderId { get; set; }
@@ -14,5 +16,7 @@ namespace Hotline.DataSharing.Province.Notifications
 		public string Opinion { get; set; }
 
 		public string FinishType { get; set; }
+
+		public List<FileDto> Files { get; set; }
 	}
 }

+ 4 - 1
src/Hotline/DataSharing/Province/Notifications/ScreenProvinceResultNotify.cs

@@ -1,4 +1,5 @@
-using Hotline.Share.Dtos.Order;
+using Hotline.Share.Dtos.File;
+using Hotline.Share.Dtos.Order;
 using MediatR;
 
 namespace Hotline.DataSharing.Province.Notifications;
@@ -9,4 +10,6 @@ namespace Hotline.DataSharing.Province.Notifications;
 public class ScreenProvinceResultNotify : INotification
 {
     public ProvinceScreenResult ProvinceScreenResult { get; set; }
+
+    public List<FileDto> Files { get; set; }
 }

+ 4 - 9
src/Hotline/DataSharing/Province/Services/IProvinceService.cs

@@ -139,11 +139,12 @@ namespace Hotline.DataSharing.Province.Services
         Task SupplyCaseInfoSend(SupplyCaseInfoSendInfo dto, CancellationToken cancellationToken);
 
         /// <summary>
-        /// 服务工单撤单
+        /// 撤单--已对接
         /// </summary>
         /// <param name="dto"></param>
+        /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task SendRevokeCaseInfo(RevokeCaseInfoInfo dto, CancellationToken cancellationToken);
+        Task RevokeOrder(PublishSpecialDto dto, CancellationToken cancellationToken);
 
         /// <summary>
         /// 服务工单催单--已对接
@@ -187,12 +188,6 @@ namespace Hotline.DataSharing.Province.Services
         Task SendRealTimeStatus(SendRealTimeStatusInfo dto, CancellationToken cancellationToken);
         #endregion
 
-        /// <summary>
-        /// 撤单
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <param name="cancellationToken"></param>
-        /// <returns></returns>
-        Task RevokeOrder(PublishSpecialDto dto, CancellationToken cancellationToken);
+
     }
 }

+ 45 - 31
src/Hotline/DataSharing/Province/Services/ProvinceService.cs

@@ -776,29 +776,53 @@ namespace Hotline.DataSharing.Province.Services
         }
 
         /// <summary>
-        /// 服务工单撤单
+        /// 撤单
         /// </summary>
         /// <param name="dto"></param>
+        /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task SendRevokeCaseInfo(RevokeCaseInfoInfo dto, CancellationToken cancellationToken)
+        public async Task RevokeOrder(PublishSpecialDto dto, CancellationToken cancellationToken)
         {
-            var data = _mapper.Map<DsRevokeCaseInfo>(dto);
-            data.Direction = "1";
-            data.AreaCode = _channelConfigurationManager.GetConfigurationCityCode().AreaCode;
-            data.CliengGuid = Guid.NewGuid().ToString();
-            //将上报信息写入本地库
-            data.Id = await _revokeCaseInfoRepository.AddAsync(data);
+            //企业服务
+            if (dto.Order.CurrentHandleOrgCode == "001180")
+            {
+                DsDataWorkOrderCancel dsDataWork = new()
+                {
+                    WorkOrderNo = dto.Order.No,
+                    Reason = dto.Special.Reason
+                };
+                await _enterpriseService.EnterpriseCancelPusher(dsDataWork, cancellationToken);
+            }
 
-            //信息上报
-            //往省上派的单需要代用省上接口
+            //省12345
+            if (dto.Order.CurrentHandleOrgCode == "001170")
+            {
+                DsRevokeCaseInfo dsRevoke = new()
+                {
+                    CaseSerial = dto.Order.ProvinceNo,
+                    AreaCode = dto.Order.AreaCode,
+                    RevokeTime = dto.Special.CreationTime,
+                    RevokeName = dto.Special.CreatorName,
+                    RevokeReasion = dto.Special.Reason,
+                    Direction = "1",
+                    CliengGuid = Guid.NewGuid().ToString()
+                };
 
-            await InitPushData("SendRevokeCaseInfo", System.Text.Json.JsonSerializer.Serialize(data), "revoke_case_info", data.Id, 0, cancellationToken);
-            // await _pusherProviderService.SendRevokeCaseInfoPusher(data, cancellationToken);
-            //处理附件
-            await FileData(new List<FileJson>(), dto.CaseSerial, data.CliengGuid, dto.AreaCode, cancellationToken);
+                if (string.IsNullOrEmpty(dto.Special.Cause))
+                    dsRevoke.RevokeType = "other";
+                else if (dto.Special.Cause.Contains("内容错误"))
+                    dsRevoke.RevokeType = "2";
+                else if (dto.Special.Cause == "撤销工单")
+                    dsRevoke.RevokeType = "1";
+                else
+                    dsRevoke.RevokeType = "other";
+
+                //将上报信息写入本地库
+                dsRevoke.Id = await _revokeCaseInfoRepository.AddAsync(dsRevoke);
+                await InitPushData("SendRevokeCaseInfo", System.Text.Json.JsonSerializer.Serialize(dsRevoke), "revoke_case_info", dsRevoke.Id, 0, cancellationToken);
 
-            //如果是派给企业服务的需要调用企业服务的接口
-            await _enterpriseService.EnterpriseCancelPusher(new DsDataWorkOrderCancel(), cancellationToken);
+                await FileData(dto.Special.FileJson, dsRevoke.CaseSerial, dsRevoke.CliengGuid, dsRevoke.AreaCode, cancellationToken);
+            }
         }
 
         /// <summary>
@@ -938,16 +962,6 @@ namespace Hotline.DataSharing.Province.Services
         }
         #endregion
 
-        /// <summary>
-        /// 撤单
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <param name="cancellationToken"></param>
-        /// <returns></returns>
-        public async Task RevokeOrder(PublishSpecialDto dto, CancellationToken cancellationToken)
-        {
-
-        }
 
         ///// <summary>
         ///// 接收发布数据
@@ -1332,25 +1346,25 @@ namespace Hotline.DataSharing.Province.Services
             {
                 foreach (var item in dto.WorkflowTrace.NextHandlers)
                 {
-                    if (!string.IsNullOrEmpty(item.Value))
+                    if (!string.IsNullOrEmpty(item.Key))
                     {
                         //需要判断是否需要往110推送
-                        if (item.Value == "市公安局110")
+                        if (item.Key == "001179")
                             //写入110本地数据库
                             await InitPoliceSendChainAlarmDs(dto.Order, cancellationToken);
 
                         //需要判断是否需要往宜宾等地市州推送数据
-                        if (item.Value == "泸州12345")
+                        if (item.Key == "泸州12345")
                             //市州数据提交
                             await InitCityDataYB(dto.Order, cancellationToken);
 
                         //需要判断是否需要往企业专班提交数据
-                        if (item.Value == "企业服务专班")
+                        if (item.Key == "001180")
                             //企业专班提交数据
                             await InitEnterpriseData(dto.Order, cancellationToken);
 
                         //是否向省上派单
-                        if (item.Value == "省12345平台")
+                        if (item.Key == "001170")
                             await SendCaseInfo(dto.Order, cancellationToken);
                     }
                 }

+ 9 - 9
src/Hotline/Orders/Order.cs

@@ -421,47 +421,47 @@ namespace Hotline.Orders
         public string? CurrentStepName { get; set; }
 
         /// <summary>
-        /// 到达当前节点时间(stepBox创建时间)
+        /// 到达当前节点时间
         /// </summary>
         public DateTime? CurrentStepCreateTime { get; set; }
 
         /// <summary>
-        /// 实际办理节点签收时间
+        /// 当前办理节点签收时间
         /// </summary>
         public DateTime? CurrentHandleStepAcceptTime { get; set; }
 
         /// <summary>
-        /// 实际办理时间
+        /// 当前办理时间
         /// </summary>
         public DateTime? CurrentHandleTime { get; set; }
 
         /// <summary>
-        /// 实际办理人id
+        /// 当前办理人id
         /// </summary>
         public string? CurrentHandlerId { get; set; }
 
         /// <summary>
-        /// 实际办理人名称
+        /// 当前办理人名称
         /// </summary>
         public string? CurrentHandlerName { get; set; }
 
         /// <summary>
-        /// 实际办理部门名称
+        /// 当前办理部门名称
         /// </summary>
         public string? CurrentHandleOrgName { get; set; }
 
         /// <summary>
-        /// 实际办理部门编码
+        /// 当前办理部门编码
         /// </summary>
         public string? CurrentHandleOrgCode { get; set; }
 
         /// <summary>
-        /// 实际办理部门行政区划编码
+        /// 当前办理部门行政区划编码
         /// </summary>
         public string? CurrentHandleOrgAreaCode { get; set; }
 
         /// <summary>
-        /// 实际办理部门行政区划名称
+        /// 当前办理部门行政区划名称
         /// </summary>
         public string? CurrentHandleOrgAreaName { get; set; }
         #endregion

+ 5 - 0
src/Hotline/Orders/OrderVisit.cs

@@ -94,4 +94,9 @@ public class OrderVisit : CreationEntity
     /// </summary>
     public bool IsCanHandle { get; set; }
 
+    /// <summary>
+    /// 渠道为电话时,此字段存在
+    /// </summary>
+    public string? CallId { get; set; }
+
 }

+ 6 - 0
src/Hotline/Realtimes/IRealtimeService.cs

@@ -27,5 +27,11 @@ namespace Hotline.Realtimes
         Task CircularRecoordAsync(string id, CancellationToken cancellationToken);
 
         #endregion
+
+        #region 大屏.数据展示
+
+        Task BsDataShowChangedAsync(object obj, CancellationToken cancellationToken);
+
+        #endregion
     }
 }