Selaa lähdekoodia

省重办和省回访增加分布式锁

tangjiang 1 viikko sitten
vanhempi
commit
32a1f75191

+ 142 - 133
src/Hotline.Application/OrderApp/OrderApplication.cs

@@ -1,8 +1,4 @@
-using DocumentFormat.OpenXml.Drawing.Diagrams;
-using DocumentFormat.OpenXml.Office.CustomUI;
-using DocumentFormat.OpenXml.Office2010.CustomUI;
-using DocumentFormat.OpenXml.Spreadsheet;
-using DotNetCore.CAP;
+using DotNetCore.CAP;
 using FluentValidation;
 using Hotline.Application.FlowEngine;
 using Hotline.Application.OrderApp.OrderVisitApp;
@@ -37,7 +33,6 @@ using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.Order.Publish;
 using Hotline.Share.Dtos.Push;
 using Hotline.Share.Dtos.Settings;
-using Hotline.Share.Dtos.Users;
 using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Enums.Push;
@@ -54,17 +49,15 @@ using Hotline.Validators.FlowEngine;
 using Mapster;
 using MapsterMapper;
 using MediatR;
-using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Options;
-using NPOI.SS.Formula.Functions;
 using PanGu;
 using SqlSugar;
 using System.Data;
 using System.Dynamic;
-using System.Threading;
 using XF.Domain.Authentications;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
+using XF.Domain.Locks;
 using XF.Domain.Repository;
 using WordInfo = PanGu.WordInfo;
 
@@ -72,6 +65,7 @@ namespace Hotline.Application.OrderApp;
 
 public class OrderApplication : IOrderApplication, IScopeDependency
 {
+    #region 注入
     private readonly IOrderSnapshotRepository _orderSnapshotRepository;
     private readonly IMediator _mediator;
     private readonly IRepository<TranspondCityRawData> _transpondCityRawDataRepository;
@@ -83,8 +77,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     private readonly IWorkflowDomainService _workflowDomainService;
     private readonly ISessionContext _sessionContext;
     private readonly IOrderRepository _orderRepository;
-
-    //private readonly ITimeLimitDomainService _timeLimitDomainService;
     private readonly IMapper _mapper;
     private readonly ISystemSettingCacheManager _systemSettingCacheManager;
     private readonly IRepository<OrderWord> _orderWrodRepository;
@@ -127,6 +119,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     private readonly IRepository<OrderVisitDetailCopy> _orderVisitDetailCopyRepository;
     private readonly IRepository<OrderDelayAutomatic> _orderDelayAutomaticRepository;
     private readonly IRepository<Hotline.Orders.ObservationPiece> _observationPieceRepository;
+    private readonly IDistributedLock _distributedLock;
 
     public OrderApplication(
         IOrderDomainService orderDomainService,
@@ -182,9 +175,9 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         IRepository<Role> roleRepository,
         IRepository<OrderVisitDetailCopy> orderVisitDetailCopyRepository,
         IRepository<OrderDelayAutomatic> orderDelayAutomaticRepository,
-        IRepository<Hotline.Orders.ObservationPiece> observationPieceRepository
-,
-        IOrderSnapshotRepository orderSnapshotRepository)
+        IRepository<Hotline.Orders.ObservationPiece> observationPieceRepository,
+        IOrderSnapshotRepository orderSnapshotRepository,
+        IDistributedLock distributedLock)
     {
         _orderDomainService = orderDomainService;
         _workflowDomainService = workflowDomainService;
@@ -240,7 +233,9 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         _orderDelayAutomaticRepository = orderDelayAutomaticRepository;
         _observationPieceRepository = observationPieceRepository;
         _orderSnapshotRepository = orderSnapshotRepository;
+        _distributedLock = distributedLock;
     }
+    #endregion
 
     /// <summary>
     /// 更新工单办理期满时间(延期调用,其他不调用)
@@ -1780,7 +1775,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 await _orderSnapshotRepository.Queryable().Where(m => m.Id == item.OrderId)
                     .Select(m => m.IndustryName)
                     .FirstAsync()
-                    .Then(name => 
+                    .Then(name =>
                     {
                         if (name.Trim() == "电气焊作业申报") code = "1012";
                     });
@@ -2121,7 +2116,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
 
         query = query
             .Includes(x => x.OrderSupervises.OrderByDescending(d => d.CreationTime).Take(2).ToList())
-            .Includes(x => x.OrderVisits.Where(q=>q.VisitState == EVisitState.Visited).Take(1).ToList(), d => d.OrderVisitDetails.Where(c => c.VisitTarget == EVisitTarget.Org).Take(1).ToList());
+            .Includes(x => x.OrderVisits.Where(q => q.VisitState == EVisitState.Visited).Take(1).ToList(), d => d.OrderVisitDetails.Where(c => c.VisitTarget == EVisitTarget.Org).Take(1).ToList());
 
         return query;
     }
@@ -5621,135 +5616,149 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         }
         else
         {
-            _mapper.Map(dto, order);
-            if (files != null && files.Any())
-                order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
-            else
-                order.FileJson = new List<Share.Dtos.File.FileJson>();
-            //order.ReTransactNum++;
-            if (order.ProvinceReTransactNum.HasValue)
-                order.ProvinceReTransactNum = order.ProvinceReTransactNum + 1;
-            else
-                order.ProvinceReTransactNum = 1;
-
-            if (order.IsSecret == true)
-            {
-                order.FocusOnEventsName = "保密";
-                order.FocusOnEvents = "99";
-            }
-            //await _orderRepository.UpdateAsync(order, cancellationToken);
-
-            if (orderExtension is not null)
-            {
-                orderExtension.Id = order.Id;
-                if (dto.OrderExtension != null)
-                    _mapper.Map(dto.OrderExtension, orderExtension);
-                await _orderDomainService.UpdateExtensionAsync(orderExtension, cancellationToken);
-            }
-
-            //计算order 期满时间
-            ExpiredTimeWithConfig expiredTimeConfig;
-            if (_appOptions.Value.IsZiGong)
-            {
-                expiredTimeConfig = await _expireTime.CalcExpiredTime(DateTime.Now, DateTime.Now, EFlowDirection.CenterToCenter,
-                    order.Adapt<OrderTimeClacInfo>());
-            }
-            else
-            {
-                //期满时间
-                //expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg, order.AcceptTypeCode);
-                expiredTimeConfig =
-                    await _expireTime.CalcExpiredTime(DateTime.Now, DateTime.Now, EFlowDirection.CenterToOrg, order.Adapt<OrderTimeClacInfo>());
-            }
+            //分布式锁执行锁定
+            var distributedLockKey = $"provinceordervisit_{order.Id}";
+            if (await _distributedLock.AcquireAsync(distributedLockKey, TimeSpan.FromMinutes(3), cancellationToken))
+            {
+                //锁定成功,执行正常业务
+                _mapper.Map(dto, order);
+                if (files != null && files.Any())
+                    order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
+                else
+                    order.FileJson = new List<Share.Dtos.File.FileJson>();
+                //order.ReTransactNum++;
+                if (order.ProvinceReTransactNum.HasValue)
+                    order.ProvinceReTransactNum = order.ProvinceReTransactNum + 1;
+                else
+                    order.ProvinceReTransactNum = 1;
 
-            _mapper.Map(expiredTimeConfig, order);
-            //await _orderRepository.UpdateAsync(order, cancellationToken);
-
-            //特提(撤回至发起)
-            if (!string.IsNullOrEmpty(order.WorkflowId))
-            {
-                // FlowStepHandler? handler = null;
-                // if (_appOptions.Value.IsZiGong)
-                // {
-                //     // 平均派单
-                //     var averageSendOrder = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.AverageSendOrder).SettingValue[0]);
-                //     if (averageSendOrder)
-                //     {
-                //         handler = await _orderDomainService.AverageOrder(cancellationToken);
-                //     }
-                // }
-                //
-                // StepAssignInfo? stepAssignInfo = null;
-                // if (handler is not null)
-                // {
-                //     stepAssignInfo = _mapper.Map<StepAssignInfo>(handler);
-                //     stepAssignInfo.FlowAssignType = EFlowAssignType.User;
-                // }
-                //
-                // var reverseFlowStepAssignInfo = stepAssignInfo is null
-                //     ? new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStep)
-                //     : new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStepUser, stepAssignInfo);
-                //await _workflowDomainService.RecallToStartStepAsync(order.WorkflowId, "省工单重派", current, order.Status >= EOrderStatus.Filed, cancellationToken);
-
-                var flowAssignType = _appOptions.Value.IsYiBin
-                    ? EFlowAssignType.User
-                    : EFlowAssignType.Role;
-
-                var (isPaiDan, workflow) = await _workflowDomainService.RecallToCenterFirstToSendAsync(order.WorkflowId, "省工单重派",
-                    order.Status >= EOrderStatus.Filed, order.ExpiredTime, EHandleMode.Redo, flowAssignType, cancellationToken);
-
-                order.FileEmpty();
-
-                order.CurrentStepName = workflow.CurrentStepName;
-                order.CurrentStepCode = workflow.CurrentStepCode;
-                order.CurrentStepId = workflow.CurrentStepId;
-                order.CurrentStepCreateTime = workflow.CurrentStepCreateTime;
-                order.CurrentHandleTime = workflow.CurrentHandleTime;
-                order.CurrentHandlerId = workflow.CurrentHandlerId;
-                order.CurrentHandlerName = workflow.CurrentHandlerName;
-                order.CurrentHandleOrgName = workflow.CurrentHandleOrgName;
-                order.CurrentHandleOrgId = workflow.CurrentHandleOrgId;
-                order.CurrentHandleOrgLevel = workflow.CurrentHandleOrgLevel;
-                order.CurrentHandleOrgAreaCode = workflow.CurrentHandleOrgAreaCode;
-                order.CurrentHandleOrgAreaName = workflow.CurrentHandleOrgAreaName;
-
-                order.Status = EOrderStatus.WaitForAccept;
-                if (isPaiDan)
+                if (order.IsSecret == true)
                 {
-                    order.Status = EOrderStatus.Special;
+                    order.FocusOnEventsName = "保密";
+                    order.FocusOnEvents = "99";
                 }
-                //await _orderRepository.Updateable().SetColumns(o => new Order { Status = status }).Where(o => o.Id == order.Id).ExecuteCommandAsync(cancellationToken);
+                //await _orderRepository.UpdateAsync(order, cancellationToken);
 
-                //处理回访和发布信息
+                if (orderExtension is not null)
+                {
+                    orderExtension.Id = order.Id;
+                    if (dto.OrderExtension != null)
+                        _mapper.Map(dto.OrderExtension, orderExtension);
+                    await _orderDomainService.UpdateExtensionAsync(orderExtension, cancellationToken);
+                }
 
-                var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == order.Id);
-                if (publish != null)
+                //计算order 期满时间
+                ExpiredTimeWithConfig expiredTimeConfig;
+                if (_appOptions.Value.IsZiGong)
                 {
-                    var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
-                    publishHistory.OrderPublishId = publish.Id;
-                    publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
-                    publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
-                    publishHistory.ArrangeContentAfter = publish.ArrangeContent;
-                    publishHistory.ArrangeContentBefor = publish.ArrangeContent;
-                    publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
-                    publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
-                    await _orderPublishHistoryRepository.AddAsync(publishHistory, cancellationToken);
-                    await _orderPublishRepository.RemoveAsync(publish, false, cancellationToken);
+                    expiredTimeConfig = await _expireTime.CalcExpiredTime(DateTime.Now, DateTime.Now, EFlowDirection.CenterToCenter,
+                        order.Adapt<OrderTimeClacInfo>());
+                }
+                else
+                {
+                    //期满时间
+                    //expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg, order.AcceptTypeCode);
+                    expiredTimeConfig =
+                        await _expireTime.CalcExpiredTime(DateTime.Now, DateTime.Now, EFlowDirection.CenterToOrg, order.Adapt<OrderTimeClacInfo>());
                 }
 
-                var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == order.Id && x.VisitState != EVisitState.None);
-                if (visit != null)
+                _mapper.Map(expiredTimeConfig, order);
+                //await _orderRepository.UpdateAsync(order, cancellationToken);
+
+                //特提(撤回至发起)
+                if (!string.IsNullOrEmpty(order.WorkflowId))
                 {
-                    visit.VisitState = EVisitState.None;
-                    await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
+                    // FlowStepHandler? handler = null;
+                    // if (_appOptions.Value.IsZiGong)
+                    // {
+                    //     // 平均派单
+                    //     var averageSendOrder = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.AverageSendOrder).SettingValue[0]);
+                    //     if (averageSendOrder)
+                    //     {
+                    //         handler = await _orderDomainService.AverageOrder(cancellationToken);
+                    //     }
+                    // }
+                    //
+                    // StepAssignInfo? stepAssignInfo = null;
+                    // if (handler is not null)
+                    // {
+                    //     stepAssignInfo = _mapper.Map<StepAssignInfo>(handler);
+                    //     stepAssignInfo.FlowAssignType = EFlowAssignType.User;
+                    // }
+                    //
+                    // var reverseFlowStepAssignInfo = stepAssignInfo is null
+                    //     ? new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStep)
+                    //     : new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStepUser, stepAssignInfo);
+                    //await _workflowDomainService.RecallToStartStepAsync(order.WorkflowId, "省工单重派", current, order.Status >= EOrderStatus.Filed, cancellationToken);
+
+                    var flowAssignType = _appOptions.Value.IsYiBin
+                        ? EFlowAssignType.User
+                        : EFlowAssignType.Role;
+
+                    var (isPaiDan, workflow) = await _workflowDomainService.RecallToCenterFirstToSendAsync(order.WorkflowId, "省工单重派",
+                        order.Status >= EOrderStatus.Filed, order.ExpiredTime, EHandleMode.Redo, flowAssignType, cancellationToken);
+
+                    order.FileEmpty();
+
+                    order.CurrentStepName = workflow.CurrentStepName;
+                    order.CurrentStepCode = workflow.CurrentStepCode;
+                    order.CurrentStepId = workflow.CurrentStepId;
+                    order.CurrentStepCreateTime = workflow.CurrentStepCreateTime;
+                    order.CurrentHandleTime = workflow.CurrentHandleTime;
+                    order.CurrentHandlerId = workflow.CurrentHandlerId;
+                    order.CurrentHandlerName = workflow.CurrentHandlerName;
+                    order.CurrentHandleOrgName = workflow.CurrentHandleOrgName;
+                    order.CurrentHandleOrgId = workflow.CurrentHandleOrgId;
+                    order.CurrentHandleOrgLevel = workflow.CurrentHandleOrgLevel;
+                    order.CurrentHandleOrgAreaCode = workflow.CurrentHandleOrgAreaCode;
+                    order.CurrentHandleOrgAreaName = workflow.CurrentHandleOrgAreaName;
+
+                    order.Status = EOrderStatus.WaitForAccept;
+                    if (isPaiDan)
+                    {
+                        order.Status = EOrderStatus.Special;
+                    }
+                    //await _orderRepository.Updateable().SetColumns(o => new Order { Status = status }).Where(o => o.Id == order.Id).ExecuteCommandAsync(cancellationToken);
+
+                    //处理回访和发布信息
+
+                    var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == order.Id);
+                    if (publish != null)
+                    {
+                        var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
+                        publishHistory.OrderPublishId = publish.Id;
+                        publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
+                        publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
+                        publishHistory.ArrangeContentAfter = publish.ArrangeContent;
+                        publishHistory.ArrangeContentBefor = publish.ArrangeContent;
+                        publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
+                        publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
+                        await _orderPublishHistoryRepository.AddAsync(publishHistory, cancellationToken);
+                        await _orderPublishRepository.RemoveAsync(publish, false, cancellationToken);
+                    }
+
+                    var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == order.Id && x.VisitState != EVisitState.None);
+                    if (visit != null)
+                    {
+                        visit.VisitState = EVisitState.None;
+                        await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
+                    }
                 }
-            }
 
-            await _orderRepository.UpdateAsync(order, cancellationToken);
-            //await _workflowDomainService.RecallToStartStepAsync(order.WorkflowId, "省工单重派", current, cancellationToken);
+                await _orderRepository.UpdateAsync(order, cancellationToken);
+                //await _workflowDomainService.RecallToStartStepAsync(order.WorkflowId, "省工单重派", current, cancellationToken);
 
-            //删除甄别、延期、二次办理等数据
-            await SpecialNewVerify(order, cancellationToken);
+                //删除甄别、延期、二次办理等数据
+                await SpecialNewVerify(order, cancellationToken);
+
+                //执行完成释放分布式锁
+                await _distributedLock.ReleaseAsync(distributedLockKey, cancellationToken);
+            }
+            else
+            {
+                //锁定失败,调用消息队列,再次执行
+                _capPublisher.PublishDelay(TimeSpan.FromMinutes(2), EventNames.HotlineOrderAddAnonymous, dto);
+            }
         }
 
         return _mapper.Map<AddOrderResponse>(order);

+ 174 - 148
src/Hotline.Application/Subscribers/DatasharingSubscriber.cs

@@ -5,7 +5,6 @@ using Hotline.Application.FlowEngine;
 using Hotline.Application.OrderApp;
 using Hotline.Authentications;
 using Hotline.Caching.Interfaces;
-using Hotline.Caching.Services;
 using Hotline.CallCenter.Calls;
 using Hotline.Configurations;
 using Hotline.ContingencyManagement;
@@ -19,7 +18,6 @@ using Hotline.Settings.TimeLimitDomain;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.ContingencyManagement;
 using Hotline.Share.Dtos.DataSharing.PusherHotlineDto;
-using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.OrderTranspond;
@@ -28,18 +26,15 @@ using Hotline.Share.Dtos.TrCallCenter;
 using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Mq;
-using Hotline.Validators.FlowEngine;
 using Mapster;
 using MapsterMapper;
 using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Options;
-using Newtonsoft.Json;
 using SqlSugar;
-using XF.Domain.Authentications;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
+using XF.Domain.Locks;
 using XF.Domain.Repository;
 
 namespace Hotline.Application.Subscribers
@@ -49,6 +44,7 @@ namespace Hotline.Application.Subscribers
     /// </summary>
     public class DataSharingSubscriber : ICapSubscribe, ITransientDependency
     {
+        #region 注入
         private readonly IRepository<OrderVisit> _orderVisitRepository;
         private readonly IMapper _mapper;
         private readonly IOrderRepository _orderRepository;
@@ -81,6 +77,7 @@ namespace Hotline.Application.Subscribers
         private readonly ICalcExpireTime _expireTime;
         private readonly ISessionContextManager _sessionContextManager;
         private readonly ILogger<DataSharingSubscriber> _logger;
+        private readonly IDistributedLock _distributedLock;
 
         public DataSharingSubscriber(
             IRepository<OrderVisit> orderVisitRepository,
@@ -114,7 +111,8 @@ namespace Hotline.Application.Subscribers
             ISystemDicDataCacheManager sysDicDataCacheManager,
             ICalcExpireTime expireTime,
             ISessionContextManager sessionContextManager,
-            ILogger<DataSharingSubscriber> logger)
+            ILogger<DataSharingSubscriber> logger,
+            IDistributedLock distributedLock)
         {
             _orderSendBackRepository = orderSendBackRepository;
             _workflowApplication = workflowApplication;
@@ -148,7 +146,9 @@ namespace Hotline.Application.Subscribers
             _expireTime = expireTime;
             _sessionContextManager = sessionContextManager;
             _logger = logger;
+            _distributedLock = distributedLock;
         }
+        #endregion
 
         /// <summary>
         /// 接收工单退回结果
@@ -613,165 +613,181 @@ namespace Hotline.Application.Subscribers
         [CapSubscribe(Hotline.Share.Mq.EventNames.SharingOrderEvlResult)]
         public async Task OrderVisitProvince(ProvinceOrderVisitDto dto, CancellationToken cancellationToken)
         {
-            var orderVisit = await _orderVisitRepository.Queryable()
-                .Includes(x => x.Order)
-                .Includes(x => x.OrderVisitDetails)
-                .Where(x => x.Order.ReceiveProvinceNo == dto.ProvinceNo &&
-                            x.VisitState == Share.Enums.Order.EVisitState.WaitForVisit).FirstAsync(cancellationToken);
-
-            if (orderVisit != null)
+            var order = await _orderRepository.Queryable().Where(x => x.ReceiveProvinceNo == dto.ProvinceNo).FirstAsync();
+            if (order == null)
+                return;
+            var distributedLockKey = $"provinceordervisit_{order.Id}";
+            //分布式锁,如果锁成功,则执行
+            if (await _distributedLock.AcquireAsync(distributedLockKey, TimeSpan.FromMinutes(3), cancellationToken))
             {
-                //处理评价结果
-                var processingResult = dto.OrgProcessingResults;
-                Kv orgProcessingResults = null;
-                if (!string.IsNullOrEmpty(processingResult))
+                //处理原始的回访逻辑
+                var orderVisit = await _orderVisitRepository.Queryable()
+                    .Includes(x => x.Order)
+                    .Includes(x => x.OrderVisitDetails)
+                    .Where(x => x.Order.ReceiveProvinceNo == dto.ProvinceNo &&
+                                x.VisitState == Share.Enums.Order.EVisitState.WaitForVisit).FirstAsync(cancellationToken);
+
+                if (orderVisit != null)
                 {
-                    var dicData = await _systemDicDataRepository.GetAsync(x => x.DicTypeCode == SysDicTypeConsts.VisitSatisfaction &&
-                                                                               x.DicDataValue == processingResult, cancellationToken);
-                    if (dicData != null)
-                    {
-                        orgProcessingResults = new Kv();
-                        orgProcessingResults.Key = dicData.DicDataValue;
-                        orgProcessingResults.Value = dicData.DicDataName;
-                    }
-
-                    if (orgProcessingResults != null)
+                    //处理评价结果
+                    var processingResult = dto.OrgProcessingResults;
+                    Kv orgProcessingResults = null;
+                    if (!string.IsNullOrEmpty(processingResult))
                     {
-                        //主表
-                        orderVisit.VisitState = Share.Enums.Order.EVisitState.Visited;
-                        orderVisit.VisitTime = dto.VisitTime;
-                        orderVisit.VisitType = dto.VisitType;
-                        orderVisit.IsCanHandle = orgProcessingResults.Key == "2";
-                        orderVisit.IsCanAiVisit = false;
-                        orderVisit.NowEvaluate = orgProcessingResults;
-                        if (_appOptions.Value.IsZiGong)
+                        var dicData = await _systemDicDataRepository.GetAsync(x => x.DicTypeCode == SysDicTypeConsts.VisitSatisfaction &&
+                                                                                   x.DicDataValue == processingResult, cancellationToken);
+                        if (dicData != null)
                         {
-                            orderVisit.EmployeeId = _systemSettingCacheManager.DefaultVisitEmployeeId;
+                            orgProcessingResults = new Kv();
+                            orgProcessingResults.Key = dicData.DicDataValue;
+                            orgProcessingResults.Value = dicData.DicDataName;
                         }
 
-                        await _orderVisitRepository.UpdateAsync(orderVisit, cancellationToken);
-                        //子表
-                        for (int i = 0; i < orderVisit.OrderVisitDetails.Count; i++)
+                        if (orgProcessingResults != null)
                         {
-                            if (orderVisit.OrderVisitDetails[i].VisitTarget == EVisitTarget.Seat)
+                            //主表
+                            orderVisit.VisitState = Share.Enums.Order.EVisitState.Visited;
+                            orderVisit.VisitTime = dto.VisitTime;
+                            orderVisit.VisitType = dto.VisitType;
+                            orderVisit.IsCanHandle = orgProcessingResults.Key == "2";
+                            orderVisit.IsCanAiVisit = false;
+                            orderVisit.NowEvaluate = orgProcessingResults;
+                            if (_appOptions.Value.IsZiGong)
                             {
-                                orderVisit.OrderVisitDetails[i].VoiceEvaluate = (EVoiceEvaluate)int.Parse(orgProcessingResults.Key);
-                                orderVisit.OrderVisitDetails[i].SeatEvaluate = (ESeatEvaluate)int.Parse(orgProcessingResults.Key);
+                                orderVisit.EmployeeId = _systemSettingCacheManager.DefaultVisitEmployeeId;
                             }
-                            else
+
+                            await _orderVisitRepository.UpdateAsync(orderVisit, cancellationToken);
+                            //子表
+                            for (int i = 0; i < orderVisit.OrderVisitDetails.Count; i++)
                             {
-                                orderVisit.OrderVisitDetails[i].OrgProcessingResults = orgProcessingResults;
+                                if (orderVisit.OrderVisitDetails[i].VisitTarget == EVisitTarget.Seat)
+                                {
+                                    orderVisit.OrderVisitDetails[i].VoiceEvaluate = (EVoiceEvaluate)int.Parse(orgProcessingResults.Key);
+                                    orderVisit.OrderVisitDetails[i].SeatEvaluate = (ESeatEvaluate)int.Parse(orgProcessingResults.Key);
+                                }
+                                else
+                                {
+                                    orderVisit.OrderVisitDetails[i].OrgProcessingResults = orgProcessingResults;
+                                }
+
+                                orderVisit.OrderVisitDetails[i].VisitContent = dto.VisitContent;
+                                orderVisit.OrderVisitDetails[i].ScreenByEndTime = await _orderDomainService.GetScreenByEndTime();
                             }
 
-                            orderVisit.OrderVisitDetails[i].VisitContent = dto.VisitContent;
-							orderVisit.OrderVisitDetails[i].ScreenByEndTime = await _orderDomainService.GetScreenByEndTime();
-						}
-
-                        await _orderVisitedDetailRepository.UpdateRangeAsync(orderVisit.OrderVisitDetails, cancellationToken);
-                        //工单
-                        orderVisit.Order.Visited(orgProcessingResults.Key, orgProcessingResults.Value);
-                        await _orderRepository.UpdateAsync(orderVisit.Order);
-
-                        ////处理网站通知差评数据
-                        //if (orderVisit.Order.Source == ESource.Hotline && orderVisit.OrderVisitDetails.Any(x => x.OrgHandledAttitude?.Key == "1" || x.OrgHandledAttitude?.Key == "2" || x.OrgProcessingResults?.Key == "1" || x.OrgProcessingResults?.Key == "2"))
-                        //{
-                        //    //包含不满意数据,重新生成新的回访
-                        //    var newOrderVisit = _mapper.Map<OrderVisit>(orderVisit);
-                        //    newOrderVisit.InitId();
-                        //    newOrderVisit.VisitState = EVisitState.NoSatisfiedWaitForVisit;
-                        //    newOrderVisit.VisitTime = null;
-                        //    newOrderVisit.IsCanHandle = false;
-                        //    newOrderVisit.IsCanAiVisit = false;
-                        //    newOrderVisit.AiVisitCount = 0;
-                        //    await _orderVisitRepository.AddAsync(newOrderVisit, cancellationToken);
-                        //    var list = _mapper.Map<List<OrderVisitDetail>>(orderVisit.OrderVisitDetails);
-                        //    list.ForEach(x =>
-                        //    {
-                        //        x.VisitId = newOrderVisit.Id;
-                        //        x.VoiceEvaluate = null;
-                        //        x.VoiceEvaluate = null;
-                        //        x.OrgHandledAttitude = null;
-                        //        x.OrgNoSatisfiedReason = null;
-                        //        x.OrgProcessingResults = null;
-                        //        x.VisitContent = "";
-                        //    });
-                        //    await _orderVisitedDetailRepository.AddRangeAsync(list, cancellationToken);
-                        //}
+                            await _orderVisitedDetailRepository.UpdateRangeAsync(orderVisit.OrderVisitDetails, cancellationToken);
+                            //工单
+                            orderVisit.Order.Visited(orgProcessingResults.Key, orgProcessingResults.Value);
+                            await _orderRepository.UpdateAsync(orderVisit.Order);
+
+                            ////处理网站通知差评数据
+                            //if (orderVisit.Order.Source == ESource.Hotline && orderVisit.OrderVisitDetails.Any(x => x.OrgHandledAttitude?.Key == "1" || x.OrgHandledAttitude?.Key == "2" || x.OrgProcessingResults?.Key == "1" || x.OrgProcessingResults?.Key == "2"))
+                            //{
+                            //    //包含不满意数据,重新生成新的回访
+                            //    var newOrderVisit = _mapper.Map<OrderVisit>(orderVisit);
+                            //    newOrderVisit.InitId();
+                            //    newOrderVisit.VisitState = EVisitState.NoSatisfiedWaitForVisit;
+                            //    newOrderVisit.VisitTime = null;
+                            //    newOrderVisit.IsCanHandle = false;
+                            //    newOrderVisit.IsCanAiVisit = false;
+                            //    newOrderVisit.AiVisitCount = 0;
+                            //    await _orderVisitRepository.AddAsync(newOrderVisit, cancellationToken);
+                            //    var list = _mapper.Map<List<OrderVisitDetail>>(orderVisit.OrderVisitDetails);
+                            //    list.ForEach(x =>
+                            //    {
+                            //        x.VisitId = newOrderVisit.Id;
+                            //        x.VoiceEvaluate = null;
+                            //        x.VoiceEvaluate = null;
+                            //        x.OrgHandledAttitude = null;
+                            //        x.OrgNoSatisfiedReason = null;
+                            //        x.OrgProcessingResults = null;
+                            //        x.VisitContent = "";
+                            //    });
+                            //    await _orderVisitedDetailRepository.AddRangeAsync(list, cancellationToken);
+                            //}
+                        }
                     }
                 }
-            }
-            else
-            {
-                //处理省下行回访
-                var order = await _orderRepository.Queryable().Where(x => x.ReceiveProvinceNo == dto.ProvinceNo).FirstAsync();
-                if (order != null && order.Status <= EOrderStatus.Filed)
+                else
                 {
-                    //判断是否有发布数据
-                    var orderPublish = await _orderPublishRepository.Queryable()
-                        .Includes(x => x.Order).Where(x => x.Order.ReceiveProvinceNo == dto.ProvinceNo).FirstAsync(cancellationToken);
-                    if (orderPublish == null)
+                    //处理省下行回访
+                    //  var order = await _orderRepository.Queryable().Where(x => x.ReceiveProvinceNo == dto.ProvinceNo).FirstAsync();
+                    if (order != null && order.Status <= EOrderStatus.Filed)
                     {
-                        orderPublish = new OrderPublish();
-                        orderPublish.OrderId = order.Id;
-                        orderPublish.No = order.No;
-                        orderPublish.PublishState = false;
-                        orderPublish.ArrangeTitle = order.Title;
-                        orderPublish.ArrangeContent = order.Content;
-                        orderPublish.ArrangeOpinion = order.FileOpinion;
-                        orderPublish.ProPublishState = false;
-                        orderPublish.FeedBackPhone = order.Contact;
-                        orderPublish.CreatorName = order.CenterToOrgHandlerId;
-                        await _orderPublishRepository.AddAsync(orderPublish);
-                        order.Publish(orderPublish.PublishState);
-                    }
+                        //判断是否有发布数据
+                        var orderPublish = await _orderPublishRepository.Queryable()
+                            .Includes(x => x.Order).Where(x => x.Order.ReceiveProvinceNo == dto.ProvinceNo).FirstAsync(cancellationToken);
+                        if (orderPublish == null)
+                        {
+                            orderPublish = new OrderPublish();
+                            orderPublish.OrderId = order.Id;
+                            orderPublish.No = order.No;
+                            orderPublish.PublishState = false;
+                            orderPublish.ArrangeTitle = order.Title;
+                            orderPublish.ArrangeContent = order.Content;
+                            orderPublish.ArrangeOpinion = order.FileOpinion;
+                            orderPublish.ProPublishState = false;
+                            orderPublish.FeedBackPhone = order.Contact;
+                            orderPublish.CreatorName = order.CenterToOrgHandlerId;
+                            await _orderPublishRepository.AddAsync(orderPublish);
+                            order.Publish(orderPublish.PublishState);
+                        }
 
-                    orderVisit = new OrderVisit();
-                    orderVisit.No = order.No;
-                    orderVisit.OrderId = order.Id;
-                    orderVisit.PublishTime = DateTime.Now;
-                    orderVisit.IsCanHandle = true;
-                    orderVisit.EmployeeId = order.CenterToOrgHandlerId;
-                    orderVisit.VisitState = EVisitState.None;
-                    orderVisit.VisitTime = dto.VisitTime;
-                    orderVisit.VisitType = dto.VisitType;
-                    orderVisit.IsCanAiVisit = false;
-                    var VisitSatisfaction = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitSatisfaction)
-                        .Where(x => x.DicDataValue == dto.OrgProcessingResults).Select(m => new Kv { Key = m.DicDataValue, Value = m.DicDataName })
-                        .FirstOrDefault();
-                    var satisfy = VisitSatisfaction;
-                    orderVisit.NowEvaluate = satisfy;
-                    string visitId = await _orderVisitRepository.AddAsync(orderVisit);
-
-                    //新增回访信息
-                    var visitedDetail = new List<OrderVisitDetail>();
-
-                    //新增坐席回访
-                    var seatDetail = new OrderVisitDetail();
-                    seatDetail.VisitId = visitId;
-                    seatDetail.VisitTarget = EVisitTarget.Seat;
-                    seatDetail.VoiceEvaluate = EVoiceEvaluate.Satisfied;
-                    seatDetail.SeatEvaluate = ESeatEvaluate.Satisfied;
-                    visitedDetail.Add(seatDetail);
-
-                    //新增部门回访
-                    var orgDetail = new OrderVisitDetail();
-                    orgDetail.VisitId = visitId;
-                    orgDetail.VisitOrgCode = order.ActualHandleOrgCode;
-                    orgDetail.VisitOrgName = order.ActualHandleOrgName;
-                    orgDetail.VisitTarget = EVisitTarget.Org;
-					orgDetail.ScreenByEndTime = await _orderDomainService.GetScreenByEndTime();
-
-					orgDetail.OrgProcessingResults = satisfy;
-
-                    visitedDetail.Add(orgDetail);
-                    //TODO 自贡办件态度
-
-
-                    await _orderVisitedDetailRepository.AddRangeAsync(visitedDetail, cancellationToken);
-                    //order.Visited(satisfy.Key, satisfy.Value);
-                    //order.Status = EOrderStatus.Visited;
-                    //await _orderRepository.UpdateAsync(order, cancellationToken);
+                        orderVisit = new OrderVisit();
+                        orderVisit.No = order.No;
+                        orderVisit.OrderId = order.Id;
+                        orderVisit.PublishTime = DateTime.Now;
+                        orderVisit.IsCanHandle = true;
+                        orderVisit.EmployeeId = order.CenterToOrgHandlerId;
+                        orderVisit.VisitState = EVisitState.None;
+                        orderVisit.VisitTime = dto.VisitTime;
+                        orderVisit.VisitType = dto.VisitType;
+                        orderVisit.IsCanAiVisit = false;
+                        var VisitSatisfaction = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitSatisfaction)
+                            .Where(x => x.DicDataValue == dto.OrgProcessingResults).Select(m => new Kv { Key = m.DicDataValue, Value = m.DicDataName })
+                            .FirstOrDefault();
+                        var satisfy = VisitSatisfaction;
+                        orderVisit.NowEvaluate = satisfy;
+                        string visitId = await _orderVisitRepository.AddAsync(orderVisit);
+
+                        //新增回访信息
+                        var visitedDetail = new List<OrderVisitDetail>();
+
+                        //新增坐席回访
+                        var seatDetail = new OrderVisitDetail();
+                        seatDetail.VisitId = visitId;
+                        seatDetail.VisitTarget = EVisitTarget.Seat;
+                        seatDetail.VoiceEvaluate = EVoiceEvaluate.Satisfied;
+                        seatDetail.SeatEvaluate = ESeatEvaluate.Satisfied;
+                        visitedDetail.Add(seatDetail);
+
+                        //新增部门回访
+                        var orgDetail = new OrderVisitDetail();
+                        orgDetail.VisitId = visitId;
+                        orgDetail.VisitOrgCode = order.ActualHandleOrgCode;
+                        orgDetail.VisitOrgName = order.ActualHandleOrgName;
+                        orgDetail.VisitTarget = EVisitTarget.Org;
+                        orgDetail.ScreenByEndTime = await _orderDomainService.GetScreenByEndTime();
+
+                        orgDetail.OrgProcessingResults = satisfy;
+
+                        visitedDetail.Add(orgDetail);
+                        //TODO 自贡办件态度
+
+
+                        await _orderVisitedDetailRepository.AddRangeAsync(visitedDetail, cancellationToken);
+                        //order.Visited(satisfy.Key, satisfy.Value);
+                        //order.Status = EOrderStatus.Visited;
+                        //await _orderRepository.UpdateAsync(order, cancellationToken);
+                    }
                 }
+
+                //执行完成释放分布式锁
+                await _distributedLock.ReleaseAsync(distributedLockKey, cancellationToken);
+            }
+            else
+            {
+                throw new UserFriendlyException($"分布式锁定失败, orderId: {order.Id}");
             }
         }
 
@@ -1313,5 +1329,15 @@ namespace Hotline.Application.Subscribers
                 }
             }
         }
+
+        /// <summary>
+        /// 分布式执行省工单重派业务
+        /// </summary>
+        /// <returns></returns>
+        [CapSubscribe(EventNames.HotlineOrderAddAnonymous)]
+        public async Task HotlineOrderAddAnonymous(AddOrderDto dto, CancellationToken cancellationToken)
+        {
+            await _orderApplication.ReceiveOrderFromExternalAsync(dto, cancellationToken);
+        }
     }
 }

+ 3 - 0
src/Hotline.Share/Dtos/DataSharing/PusherHotlineDto/ProvinceOrderVisitDto.cs

@@ -8,14 +8,17 @@ public class ProvinceOrderVisitDto
     /// 工单编号
     /// </summary>
     public string ProvinceNo { get; set; }
+
     /// <summary>
     /// 回访时间
     /// </summary>
     public DateTime? VisitTime { get; set; }
+
     /// <summary>
     /// 回访方式
     /// </summary>
     public EVisitType? VisitType { get; set; }
+
     /// <summary>
     /// 回访内容
     /// </summary>

+ 5 - 0
src/Hotline.Share/Mq/EventNames.Order.cs

@@ -119,6 +119,11 @@ namespace Hotline.Share.Mq
         /// 处理每天办理完成未及时推送办理结果的数据 
         /// </summary>
         public const string HotlineFiledOrdersRepublish = "hotline.filed.orders.republish";
+
+        /// <summary>
+        /// 分布式执行省工单重派业务
+        /// </summary>
+        public const string HotlineOrderAddAnonymous = "hotline.order.add.anonymous";
         #endregion
 
         #region 内部订阅