Переглянути джерело

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

田爽 11 місяців тому
батько
коміт
17a9ffb488

+ 87 - 6
src/Hotline.Api/Controllers/EnforcementOrderController.cs

@@ -13,10 +13,12 @@ using Hotline.Share.Enums.Order;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
 using SqlSugar;
+using StackExchange.Redis;
 using XF.Domain.Authentications;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
+using Order = Hotline.Orders.Order;
 
 namespace Hotline.Api.Controllers
 {
@@ -30,6 +32,7 @@ namespace Hotline.Api.Controllers
         private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
         private readonly IRepository<SystemOrganize> _systemOrganizeRepository;
         private readonly ISessionContext _sessionContext;
+        private readonly IOrderRepository _orderRepository;
 
         /// <summary>
         /// 
@@ -37,11 +40,12 @@ namespace Hotline.Api.Controllers
         /// <param name="enforcementOrdersRepository"></param>
         /// <param name="judicialComplaintsEventTypeRepository"></param>
         /// <param name="enforcementHotspotRepository"></param>
-        /// <param name="mapper"></param> 
+        /// <param name="mapper"></param>
         /// <param name="workflowApplication"></param>
         /// <param name="sysDicDataCacheManager"></param>
         /// <param name="systemOrganizeRepository"></param>
         /// <param name="sessionContext"></param>
+        /// <param name="orderRepository"></param>
         public EnforcementOrderController(IRepository<EnforcementOrders> enforcementOrdersRepository,
          IRepository<JudicialComplaintsEventType> judicialComplaintsEventTypeRepository,
          IRepository<EnforcementHotspot> enforcementHotspotRepository,
@@ -49,7 +53,8 @@ namespace Hotline.Api.Controllers
          IWorkflowApplication workflowApplication,
          ISystemDicDataCacheManager sysDicDataCacheManager,
          IRepository<SystemOrganize> systemOrganizeRepository,
-         ISessionContext sessionContext)
+         ISessionContext sessionContext,
+         IOrderRepository orderRepository)
         {
             _enforcementOrdersRepository = enforcementOrdersRepository;
             _judicialComplaintsEventTypeRepository = judicialComplaintsEventTypeRepository;
@@ -59,6 +64,7 @@ namespace Hotline.Api.Controllers
             _sysDicDataCacheManager = sysDicDataCacheManager;
             _systemOrganizeRepository = systemOrganizeRepository;
             _sessionContext = sessionContext;
+            _orderRepository = orderRepository;
         }
 
         /// <summary>
@@ -69,9 +75,12 @@ namespace Hotline.Api.Controllers
         [HttpGet("getorderlist")]
         public async Task<PagedDto<EnforcementOrderListDto>> GetOrderList([FromQuery] QueryEnforcementOrderDto dto)
         {
+            var areaCode = _sessionContext.OrgAreaCode ?? "511500";
+
             var (total, items) = await _enforcementOrdersRepository.Queryable()
            .Includes(x => x.Order)
            .Where(d => d.Order.Id != null)
+           .WhereIF(areaCode != "511500", d => d.Order.AreaCode.StartsWith(areaCode))
            .WhereIF(dto.IsEnforcementOrder.HasValue, d => d.IsEnforcementOrder == dto.IsEnforcementOrder)//是否行政执法类
            .WhereIF(dto.IsPassTheBuckOrder.HasValue, d => d.IsPassTheBuckOrder == dto.IsPassTheBuckOrder)//是否推诿
            .WhereIF(dto.IsTheClueTrue.HasValue, d => d.IsTheClueTrue == dto.IsTheClueTrue)//线索是否属实
@@ -240,7 +249,7 @@ namespace Hotline.Api.Controllers
              .LeftJoin<EnforcementOrders>((x, o) => o.EventTypeSpliceName != null && (x.EventTypeName == o.EventTypeSpliceName || o.EventTypeSpliceName.Contains(x.EventTypeName)))
             .LeftJoin<Order>((x, o, p) => p.Id == o.Id)
             .Where((x, o, p) => p.StartTime >= StartDate && p.StartTime <= EndDate)
-            .WhereIF(!string.IsNullOrEmpty(AreaCode), (x, o, p) => p.AreaCode == AreaCode)
+            .WhereIF(!string.IsNullOrEmpty(AreaCode), (x, o, p) => p.AreaCode.StartsWith(AreaCode))
              .Where((x, o, p) => x.ParentId == Id)
              .GroupBy((x, o, p) => new { x.Id, x.EventTypeName })
              .Select((x, o, p) => new
@@ -293,7 +302,7 @@ namespace Hotline.Api.Controllers
             .Where(d => d.Order.Id != null)
             .Where(d => d.Order.StartTime >= dto.StartDate && d.Order.StartTime <= dto.EndDate && d.EventTypeId != null)
             .WhereIF(!string.IsNullOrEmpty(dto.EventTypeId), d => d.EventTypeId.StartsWith(dto.EventTypeId))
-            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.Order.AreaCode == dto.AreaCode)
+            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.Order.AreaCode.StartsWith(dto.AreaCode))
               .OrderByDescending(d => d.CreationTime)
            .ToPagedListAsync(dto, HttpContext.RequestAborted);
 
@@ -408,13 +417,14 @@ namespace Hotline.Api.Controllers
         public async Task<object> GetRegionalClassificationStatisticsAsync(DateTime StartDate, DateTime EndDate)
         {
             EndDate = EndDate.AddDays(1).AddSeconds(-1);
-
+            var areaCode = _sessionContext.OrgAreaCode ?? "511500";
             var list = await _enforcementOrdersRepository.Queryable()
                .Includes(x => x.Order)
                .Where(x => x.Order.Id != null)
                .Where(x => x.Order.StartTime >= StartDate && x.Order.StartTime <= EndDate)
                .LeftJoin<SystemArea>((x, o) => x.Order.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) == o.Id)
                .Where((x, o) => x.Order.Status >= EOrderStatus.Filed)
+               .WhereIF(areaCode != "511500", (x, o) => x.Order.AreaCode.StartsWith(areaCode))
                .GroupBy((x, o) => new
                {
                    AreaCode = x.Order.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
@@ -449,7 +459,7 @@ namespace Hotline.Api.Controllers
             .Includes(x => x.Order)
             .Where(d => d.Order.Id != null)
             .Where(d => d.Order.StartTime >= dto.StartDate && d.Order.StartTime <= dto.EndDate)
-            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.Order.AreaCode == dto.AreaCode)
+            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.Order.AreaCode.StartsWith(dto.AreaCode))
             .WhereIF(dto.TheClueIsTrue == true, d => d.IsTheClueTrue == true)
             .WhereIF(dto.TheClueIsNotTrue == true, d => d.IsTheClueTrue == false)
             .WhereIF(dto.EnforcementOrder == true, d => d.IsEnforcementOrder == true)
@@ -667,5 +677,76 @@ namespace Hotline.Api.Controllers
             return new PagedDto<EnforcementOrgSatisfactionOrderListDto>(total, _mapper.Map<IReadOnlyList<EnforcementOrgSatisfactionOrderListDto>>(items));
 
         }
+
+        /// <summary>
+        /// 处理司法历史工单数据
+        /// </summary>
+        /// <param name="Year"></param>
+        /// <param name="Month"></param>
+        /// <returns></returns>
+        [HttpGet("add_enforcement_old_order")]
+        public async Task AddEnforcementOldOrder(int Year, int Month)
+        {
+            DateTime StartDate = DateTime.Parse(Year + "-" + Month + "-01 00:00:00");
+            DateTime EndDate = StartDate.AddMonths(1).AddSeconds(-1);
+
+            var list = await _orderRepository.Queryable()
+                .Where(p => p.CreationTime >= StartDate && p.CreationTime <= EndDate && p.Status >= EOrderStatus.Filed && p.AcceptTypeCode != "10")
+                .Select(p => new EnforcementOldOrder()
+                {
+                    Id = p.Id,
+                    No = p.No,
+                    HotspotId = p.HotspotId,
+                    HandleTime = p.ActualHandleTime,
+                    OrgLevelOneCode = p.OrgLevelOneCode,
+                    ActualHandleOrgCode = p.ActualHandleOrgCode
+                })
+                .ToListAsync();
+
+            if (list != null && list.Count > 0)
+            {
+                //查询指定热点数据
+                var hotList = await _enforcementHotspotRepository.Queryable().ToListAsync();
+
+                //查询指定部门数据
+                var JudicialManagementOrg = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.JudicialManagementOrg).ToList();
+
+                foreach (var item in list)
+                {
+                    bool isAdd = false;
+
+                    //如果是特定热点写入数据
+                    if (hotList.Exists(p => p.Id == item.HotspotId))
+                        isAdd = true;
+
+                    if (!string.IsNullOrEmpty(item.OrgLevelOneCode))
+                    {
+                        //如果是特定部门办理写入数据
+                        if (JudicialManagementOrg.Exists(p => p.DicDataValue.Trim() == item.OrgLevelOneCode))
+                            isAdd = true;
+                    }
+
+                    if (isAdd)
+                    {
+                        //是否存在此工单
+                        if (!await _enforcementOrdersRepository.AnyAsync(p => p.Id == item.Id, HttpContext.RequestAborted))
+                        {
+                            //  不存在写入
+                            EnforcementOrders enforcementOrders = new()
+                            {
+                                Id = item.Id,
+                                OrderNo = item.No,
+                                IsEnforcementOrder = false,
+                                IsTheClueTrue = null,
+                                IsPassTheBuckOrder = false,
+                                CreationTime = item.HandleTime != null ? item.HandleTime.Value : DateTime.Now
+                            };
+                            await _enforcementOrdersRepository.AddAsync(enforcementOrders, HttpContext.RequestAborted);
+
+                        }
+                    }
+                }
+            }
+        }
     }
 }

+ 7 - 2
src/Hotline.Api/Controllers/IPPbxController.cs

@@ -314,8 +314,13 @@ namespace Hotline.Api.Controllers
             if (work is null)
                 throw UserFriendlyException.SameMessage("分机未签入,不能操作");
 
-            var telAction = new TelActionRecord(work.UserId, work.UserName, work.TelNo, work.QueueId, (EActionType)actionType);
-            await _telActionRecordRepository.AddAsync(telAction, HttpContext.RequestAborted);
+            //判断如果已经存在未结束的该动作就不新增
+            var ishas = await _telActionRecordRepository.AnyAsync(x => x.TelNo == work.TelNo && x.ActionType == (EActionType)actionType && !x.EndTime.HasValue, HttpContext.RequestAborted);
+            if (!ishas)
+            {
+                var telAction = new TelActionRecord(work.UserId, work.UserName, work.TelNo, work.QueueId, (EActionType)actionType);
+                await _telActionRecordRepository.AddAsync(telAction, HttpContext.RequestAborted);
+            }
         }
 
         /// <summary>

+ 69 - 1
src/Hotline.Api/Controllers/TestController.cs

@@ -460,7 +460,75 @@ public class TestController : BaseController
     [HttpPost("t3")]
     public async Task TestExportExcel()
     {
-      
+        var items = await _workflowTraceRepository.Queryable()
+            .Where(d => !SqlFunc.Subqueryable<WorkflowStepHandler>().Where(x => x.WorkflowStepId == d.StepId).Any())
+            .ToListAsync(HttpContext.RequestAborted);
+
+        _logger.LogInformation($"traces.count: {items.Count}");
+        //var items = await _workflowTraceRepository.Queryable()
+        //    .LeftJoin<WorkflowStepHandler>((t, h) => t.StepId == h.WorkflowStepId)
+        //    .Where((t, h) => h == null)
+        //    .Select((t, h) => new { t, h })
+        //    .ToListAsync(HttpContext.RequestAborted);
+
+        var handlerIds = items.Select(d => d)
+            .SelectMany(d => d.Handlers)
+            .Select(d => d.Key)
+            .Distinct()
+            .ToList();
+        var users = await _userRepository.Queryable()
+            .Includes(d => d.Organization)
+            .Where(d => handlerIds.Contains(d.Id))
+            .ToListAsync(HttpContext.RequestAborted);
+        var orgs = await _systemOrganizeRepository.Queryable()
+            .Where(d => handlerIds.Contains(d.Id))
+            .ToListAsync(HttpContext.RequestAborted);
+
+        var handlers = new List<WorkflowStepHandler>();
+        var updateTraces = new List<WorkflowTrace>();
+        foreach (var item in items)
+        {
+            var trace = item;
+            foreach (var traceHandler in trace.Handlers)
+            {
+                if (!trace.FlowAssignType.HasValue)
+                {
+                    trace.FlowAssignType = traceHandler.Key.Length == 36 ? EFlowAssignType.User : EFlowAssignType.Org;
+                    updateTraces.Add(trace);
+                }
+
+                if (trace.FlowAssignType == EFlowAssignType.User)
+                {
+                    var user = users.FirstOrDefault(d => d.Id == traceHandler.Key);
+                    if (user != null)
+                    {
+                        var stepHandler = WorkflowStepHandler.Create(trace.WorkflowId, trace.ExternalId,
+                            trace.FlowAssignType.Value, user.Id, user.Name, user.OrgId, user.Organization.Name);
+                        stepHandler.WorkflowStepId = trace.StepId;
+                        handlers.Add(stepHandler);
+                    }
+                }
+                else
+                {
+                    var org = orgs.FirstOrDefault(d => d.Id == traceHandler.Key);
+                    if (org != null)
+                    {
+                        var stepHandler = WorkflowStepHandler.Create(trace.WorkflowId, trace.ExternalId,
+                            trace.FlowAssignType.Value, orgId: org.Id, orgName: org.Name);
+                        stepHandler.WorkflowStepId = trace.StepId;
+                        handlers.Add(stepHandler);
+                    }
+                }
+            }
+        }
+
+        _logger.LogInformation($"待更新traces: {updateTraces.Count}");
+        if (updateTraces.Any())
+            await _workflowTraceRepository.UpdateRangeAsync(updateTraces, HttpContext.RequestAborted);
+
+        _logger.LogInformation($"待更新traces: {handlers.Count}");
+        if (handlers.Any())
+            await _workflowStepHandleRepository.AddRangeAsync(handlers, HttpContext.RequestAborted);
     }
 
     [HttpGet("rsa")]

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

@@ -15,6 +15,7 @@
     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.9" />
     <PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="7.0.14" />
     <PackageReference Include="MiniExcel" Version="1.31.3" />
+    <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
     <PackageReference Include="Serilog.Sinks.Grafana.Loki" Version="8.1.0" />
     <PackageReference Include="Serilog.Sinks.MongoDB" Version="5.3.1" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />

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

@@ -3,7 +3,8 @@
     "Using": [
       "Serilog.Enrichers.Span",
       "Serilog.Sinks.Console",
-      "Serilog.Sinks.Grafana.Loki"
+      "Serilog.Sinks.Grafana.Loki",
+      "Serilog.Sinks.File"
     ],
     "MinimumLevel": {
       "Default": "Information",
@@ -41,7 +42,7 @@
             "fwhl"
           ]
         }
-      }
+      },
       //{
       //  "Name": "Exeptionless",
       //  "Args": {

+ 12 - 0
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -1062,6 +1062,18 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                 return dto.NextHandlers.Select(d => WorkflowStepHandler.Create(workflow.Id, workflow.ExternalId,
                     assignType, orgId: d.Key, orgName: d.Value)).ToList();
             case EFlowAssignType.User:
+                if (!dto.NextHandlers.Any() && dto.HandlerType is EHandlerType.Role)
+                {
+                    var stepOption = await GetConfigStepAsync(EFlowType.Handle, nextStepDefine, cancellationToken);
+                    var uIds = stepOption.Items.Select(d => d.Key).ToList();
+                    var users1 = await _userRepository.Queryable()
+                        .Includes(d => d.Organization)
+                        .Where(d => uIds.Contains(d.Id))
+                        .ToListAsync(cancellationToken);
+                    return users1.Select(d => WorkflowStepHandler.Create(workflow.Id, workflow.ExternalId,
+                            assignType, d.Id, d.Name, d.OrgId, d.Organization.Name))
+                        .ToList();
+                }
                 var userIds = dto.NextHandlers.Select(d => d.Key).ToList();
                 var users = await _userRepository.Queryable()
                     .Includes(d => d.Organization)

+ 1 - 1
src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs

@@ -199,7 +199,7 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
                 //司法行政监督管理-工单处理
                 await _enforcementApplication.AddEnforcementOrderAsync(order, cancellationToken);
                 //推诿工单
-                await _enforcementApplication.AddPassTheBuckOrderAsync(order, _sessionContext.OrgId, _sessionContext.OrgName, cancellationToken);
+               // await _enforcementApplication.AddPassTheBuckOrderAsync(order, _sessionContext.OrgId, _sessionContext.OrgName, cancellationToken);
                 break;
             case WorkflowModuleConsts.OrderScreen:
                 var screen = await _orderScreenRepository.GetAsync(workflow.ExternalId, cancellationToken);

+ 5 - 3
src/Hotline.Application/Handlers/FlowEngine/WorkflowNextHandler.cs

@@ -143,10 +143,12 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
 
                 //    expiredTimeChanged = true;
                 //}
-				await _orderRepository.UpdateAsync(order, cancellationToken);
+                await _orderRepository.UpdateAsync(order, cancellationToken);
 
                 //司法行政监督管理-推诿工单
-                await _enforcementApplication.AddPassTheBuckOrderAsync(order, _sessionContext.RequiredOrgId, _sessionContext.OrgName, cancellationToken);
+                if (notification.Trace.StepType != EStepType.Summary && notification.Trace.StepType != EStepType.End && !notification.Trace.IsCountersignEndStep)
+                    await _enforcementApplication.AddPassTheBuckOrderAsync(order, _sessionContext.RequiredOrgId, _sessionContext.OrgName, cancellationToken);
+
                 try
                 {
                     if (notification.Dto.IsSms)
@@ -213,7 +215,7 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
                     HandlerOrgLevel = notification.HandlerOrgId.CalcOrgLevel()
                 }, cancellationToken: cancellationToken);
 
-             
+
                 break;
             case WorkflowModuleConsts.KnowledgeAdd:
             case WorkflowModuleConsts.KnowledgeUpdate:

+ 24 - 2
src/Hotline.Application/Handlers/FlowEngine/WorkflowRecallHandler.cs

@@ -1,4 +1,5 @@
 using DotNetCore.CAP;
+using Hotline.Caching.Interfaces;
 using Hotline.FlowEngine.Notifications;
 using Hotline.FlowEngine.WorkflowModules;
 using Hotline.FlowEngine.Workflows;
@@ -10,6 +11,7 @@ using Hotline.Share.Enums.Order;
 using MapsterMapper;
 using MediatR;
 using Microsoft.Extensions.Logging;
+using XF.Domain.Constants;
 
 namespace Hotline.Application.Handlers.FlowEngine;
 
@@ -19,6 +21,7 @@ public class WorkflowRecallHandler : INotificationHandler<RecallNotify>
     private readonly IOrderRepository _orderRepository;
     private readonly IWorkflowDomainService _workflowDomainService;
     private readonly ITimeLimitDomainService _timeLimitDomainService;
+    private readonly ISystemSettingCacheManager _systemSettingCacheManager;
     private readonly ICapPublisher _capPublisher;
     private readonly IMapper _mapper;
     private readonly ILogger<WorkflowRecallHandler> _logger;
@@ -28,6 +31,7 @@ public class WorkflowRecallHandler : INotificationHandler<RecallNotify>
         IOrderRepository orderRepository,
         IWorkflowDomainService workflowDomainService,
         ITimeLimitDomainService timeLimitDomainService,
+        ISystemSettingCacheManager systemSettingCacheManager,
         ICapPublisher capPublisher,
         IMapper mapper,
         ILogger<WorkflowRecallHandler> logger)
@@ -36,6 +40,7 @@ public class WorkflowRecallHandler : INotificationHandler<RecallNotify>
         _orderRepository = orderRepository;
         _workflowDomainService = workflowDomainService;
         _timeLimitDomainService = timeLimitDomainService;
+        _systemSettingCacheManager = systemSettingCacheManager;
         _capPublisher = capPublisher;
         _mapper = mapper;
         _logger = logger;
@@ -57,11 +62,28 @@ public class WorkflowRecallHandler : INotificationHandler<RecallNotify>
                 _mapper.Map(workflow, order);
                 if (notification.TargetStep.StepType is EStepType.Start)
                 {
+                    if (!bool.TryParse(
+                            _systemSettingCacheManager.GetSetting(SettingConstants.IsRecallToSeatDesignated)?.SettingValue[0],
+                            out var isRecallToSeatDesignated))
+                        isRecallToSeatDesignated = false;
+                    //var isRecallToSeatDesignated = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.IsRecallToSeatDesignated).SettingValue[0]);
                     order.Status = EOrderStatus.SpecialToUnAccept;
-                    order.BackToUnsign();
+                    if (isRecallToSeatDesignated)
+                    {
+                        if (data.HandlerType is EHandlerType.Role or EHandlerType.AssignedUser)
+                        {
+                            var handler = data.NextHandlers.First();
+                            order.SignerId = handler.Key;
+                            order.SignerName = handler.Value;
+                        }
+                    }
+                    else
+                    {
+                        order.BackToUnsign();
+                    }
                 }
                 await _orderRepository.UpdateAsync(order, false, cancellationToken);
-				break;
+                break;
             case WorkflowModuleConsts.KnowledgeAdd:
             case WorkflowModuleConsts.KnowledgeUpdate:
             case WorkflowModuleConsts.KnowledgeDelete:

+ 1 - 1
src/Hotline.Application/JudicialManagement/EnforcementApplication.cs

@@ -157,7 +157,7 @@ namespace Hotline.Application.JudicialManagement
                     if (orderData == null)
                     {
                         //没有工单数据,直接写入
-                        EnforcementOrders enforcementOrders = new EnforcementOrders()
+                        EnforcementOrders enforcementOrders = new()
                         {
                             Id = order.Id,
                             OrderNo = order.No,

+ 34 - 1
src/Hotline.Share/Dtos/JudicialManagement/EnforcementOrderListDto.cs

@@ -204,11 +204,44 @@ namespace Hotline.Share.Dtos.JudicialManagement
         }
     }
 
-    public  class EnforcementOrgSatisfactionOrderListDto: EnforcementOrderListDto
+    public class EnforcementOrgSatisfactionOrderListDto : EnforcementOrderListDto
     {
         /// <summary>
         /// 回访主表ID
         /// </summary>
         public string VisitId { get; set; }
     }
+
+    public class EnforcementOldOrder
+    {
+        /// <summary>
+        /// 工单Id
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 编号
+        /// </summary>
+        public string No { get; set; }
+
+        /// <summary>
+        /// 热点
+        /// </summary>
+        public string HotspotId { get; set; }
+
+        /// <summary>
+        /// 办结时间
+        /// </summary>
+        public DateTime? HandleTime { get; set; }
+
+        /// <summary>
+        /// 办理一级部门名称
+        /// </summary>
+        public string OrgLevelOneCode { get; set; }
+
+        /// <summary>
+        /// 实际办理部门
+        /// </summary>
+        public string ActualHandleOrgCode { get; set; }
+    }
 }

+ 1 - 1
src/Hotline/CallCenter/Calls/TelActionRecord.cs

@@ -65,7 +65,7 @@ namespace Hotline.CallCenter.Calls
         public void EndAction()
         {
             EndTime = DateTime.Now;
-            Duration = Math.Round((EndTime.Value - StartTime).TotalSeconds,2);
+            Duration = (EndTime.Value - StartTime).TotalSeconds;
         }
     }
 }

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

@@ -0,0 +1,24 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Orders
+{
+    /// <summary>
+    /// 外部市民管理
+    /// </summary>
+    public class ExternalCitizens: CreationEntity
+    {
+        public string PhoneNum { get; set; }
+
+        /// <summary>
+		/// 姓名
+		/// </summary>
+		[SugarColumn(ColumnDescription = "姓名")]
+        public string? Name { get; set; }
+    }
+}

+ 15 - 4
src/Hotline/README.md

@@ -31,17 +31,28 @@ master, hotfix, fix, dev, feature, release
 | hotfix | 紧急bug修复分支,拉取自master |
 | fix | 非紧急bug修复分支,拉取自dev |
 | dev | 开发分支,开发环境共有分支,提供前后端对接环境 |
-| feature | 功能开发分支,一般拉取至dev |
+| feature | 功能开发分支 |
 
 #### 分支命名规范
 
 前缀/功能
 
-如:hotfix/AddOrderError  feature/ExportExcel
+如:hotfix/add_order_error  feature/export_excel
 
-#### 代码提交规范
+#### 代码提交建议
 
-add, del, mod, fix, refactor, optimize, style, doc
+fix, refactor(ref), feature(feat), performance(perf), style, docs, test, revert
+
+| 关键词 | 说明 |
+|-----|------|
+| fix | 修复bug |
+| refactor(ref) | 重构 |
+| feature(feat) | 新功能 |
+| performance(perf) | 优化、性能 |
+| style | 代码样式调整 |
+| docs | 文档相关的修改 |
+| test | 测试 |
+| revert | 版本回退 |
 
 #### 代码提交流程
 

+ 5 - 0
src/XF.Domain/Constants/SettingConstants.cs

@@ -222,6 +222,11 @@ namespace XF.Domain.Constants
         /// </summary>
         public const string WebSystemSettingsTheme = "WebSystemSettingsTheme";
 
+        /// <summary>
+        /// 工单特提至坐席是否指派给选择对象
+        /// </summary>
+        public const string IsRecallToSeatDesignated = "IsRecallToSeatDesignated";
+
 
         #region 智能外呼