فهرست منبع

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

田爽 10 ماه پیش
والد
کامیت
d2b9bcd5bb

+ 63 - 192
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -55,6 +55,7 @@ namespace Hotline.Api.Controllers.Bi
         private readonly IOrderReportApplication _orderReportApplication;
         private readonly IRepository<SystemArea> _systemAreaRepository;
         private readonly IRepository<Hotspot> _hotspotRepository;
+        private readonly IRepository<SystemDicData> _systemDicDataRepository;
 
         public BiOrderController(
             IOrderRepository orderRepository,
@@ -80,7 +81,8 @@ namespace Hotline.Api.Controllers.Bi
             ITimeLimitDomainService timeLimitDomainService,
             IOrderReportApplication orderReportApplication,
             IRepository<SystemArea> systemAreaRepository,
-            IRepository<Hotspot> hotspotRepository
+            IRepository<Hotspot> hotspotRepository,
+             IRepository<SystemDicData> systemDicDataRepository
             )
         {
             _orderRepository = orderRepository;
@@ -107,6 +109,7 @@ namespace Hotline.Api.Controllers.Bi
             _orderReportApplication = orderReportApplication;
             _systemAreaRepository = systemAreaRepository;
             _hotspotRepository = hotspotRepository;
+            _systemDicDataRepository = systemDicDataRepository;
         }
 
         /// <summary>
@@ -2926,203 +2929,71 @@ namespace Hotline.Api.Controllers.Bi
         }
 
         /// <summary>
-        /// 
+        /// 受理类型分时统计
         /// </summary>
+        /// <param name="dto"></param>
         /// <returns></returns>
-        [HttpGet("order_temp_st")]
-        public async Task OrderTempSt()
+        [HttpGet("order_acceptance_time")]
+        public async Task<object> OrderAcceptanceTime([FromQuery] TimeSharingPagedKeywordRequest dto)
         {
-            DateTime StartTime = DateTime.Parse("2024-06-01");
-            DateTime EndTime = DateTime.Parse("2024-07-01");
-            _orderRepository.Queryable()
-                .Where(x => x.CreationTime >= StartTime && x.CreationTime <= EndTime)
-                //.Select()
-                ;
-        }
-
-        public class QueryTempDto
+            var item = await _orderRepository.OrderAcceptanceTime(dto);
+
+            var titleData = await _systemDicDataRepository.Queryable()
+                .Where(p => p.DicTypeCode == "AcceptType")
+                .Select(p => new
+                {
+                    Key = p.DicDataValue,
+                    Value = p.DicDataName
+                }).ToListAsync();
+
+            return new { Item = item, TitleData = titleData };
+        }
+
+        /// <summary>
+        /// 受理类型分时统计-导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("order_acceptance_time_export")]
+        public async Task<FileStreamResult> OrderAcceptanceTimeExport([FromBody] TimeSharingPagedKeywordRequest dto)
         {
-            /// <summary>
-            /// 信件状态
-            /// </summary>
-            public EOrderStatus Status { get; set; }
-
-            /// <summary>
-            /// 是否超期
-            /// </summary>
-            public string IsOverTime { get; set; }
-
-            /// <summary>
-            /// 来源
-            /// </summary>
-            public string Source { get; set; }
-
-            /// <summary>
-            /// 转接来源
-            /// </summary>
-            public string TransferPhone { get; set; }
-
-            /// <summary>
-            /// 当前节点
-            /// </summary>
-            public string ActualHandleStepName { get; set; }
-
-            /// <summary>
-            /// 重办次数
-            /// </summary>
-            public int? ReTransactNum { get; set; }
-
-            /// <summary>
-            /// 甄别状态
-            /// </summary>
-            public string? OrderScreenStatus { get; set; }
-
-            /// <summary>
-            /// 受理编号
-            /// </summary>
-            public string? No { get; set; }
-
-            /// <summary>
-            /// 省编号
-            /// </summary>
-            public string? ProvinceNo { get; set; }
-
-            /// <summary>
-            /// 受理时间
-            /// </summary>
-            public string? StartTime { get; set; }
-
-            /// <summary>
-            /// 标题
-            /// </summary>
-            public string Title { get; set; }
-
-            /// <summary>
-            /// 超期时间(期满时间)
-            /// </summary>
-            public string? ExpiredTime { get; set; }
-
-            /// <summary>
-            /// 一级部门
-            /// </summary>
-            public string? OrgLevelOneName { get; set; }
-
-            /// <summary>
-            /// 二级部门
-            /// </summary>
-            public string? OrgLevelTwoName { get; set; }
-
-            /// <summary>
-            /// 受理人部门名称
-            /// </summary>
-            public string? AcceptorOrgName { get; set; }
-
-            /// <summary>
-            /// 归档时间(暂为流程结束时间,因流程结束自动归档)
-            /// </summary>
-            public DateTime? FiledTime { get; set; }
-
-            /// <summary>
-            /// 受理类型
-            /// </summary>
-            public string? AcceptType { get; set; }
-
-            /// <summary>
-            /// 热点类型
-            /// </summary>
-            public string? HotspotName { get; set; }
-
-            /// <summary>
-            /// 热点全称
-            /// </summary>
-            public string? HotspotSpliceName { get; set; }
-
-            /// <summary>
-            /// 区域
-            /// </summary>
-            public string? AreaName { get; set; }
-
-            /// <summary>
-            /// 区域全称
-            /// </summary>
-            public string? FullAddress { get; set; }
-
-            /// <summary>
-            /// 受理人名称
-            /// </summary>
-            public string? AcceptorName { get; set; }
-
-            /// <summary>
-            /// 来电/信人姓名
-            /// </summary>
-            public string? FromName { get; set; }
-
-            /// <summary>
-            /// 联系电话
-            /// </summary>
-            public string? Contact { get; set; }
-
-            /// <summary>
-            /// 来电号码
-            /// </summary>
-            public string? FromPhone { get; set; }
-
-            /// <summary>
-            /// 事发地址
-            /// </summary>
-            public string? Address { get; set; }
-
-            /// <summary>
-            /// 具体对象
-            /// </summary>
-            public string? Obj { get; set; }
-
-            /// <summary>
-            /// 来电/信人身份
-            /// </summary>
-            public EIdentityType? IdentityType { get; set; }
-
-            /// <summary>
-            /// 来电/信人性别
-            /// </summary>
-            public EGender FromGender { get; set; }
-
-            /// <summary>
-            /// 坐席满意度
-            /// </summary>
-            public string? SeatVisitResult { get; set; }
-
-            /// <summary>
-            /// 第一次评价结果
-            /// </summary>
-            public string? FirstVisitResult { get; set; }
-
-            /// <summary>
-            /// 推送分类
-            /// </summary>
-            public string? PushType { get; set; }
-
-            /// <summary>
-            /// 诉求内容
-            /// </summary>
-            public string Content { get; set; }
-
-            /// <summary>
-            /// 实际办理意见
-            /// </summary>
-            public string ActualOpinion { get; set; }
-
-            /// <summary>
-            /// 归档意见
-            /// </summary>
-            public string? FileOpinion { get; set; }
-
-            /// <summary>
-            /// 创建时间
-            /// </summary>
-            public DateTime CreationTime { get; set; }
+            var dataTable = await _orderRepository.OrderAcceptanceTimeExport(dto);
+            var stream = ExcelHelper.CreateStream(dataTable);
+            return ExcelStreamResult(stream, "受理类型分时统计数据");
+        }
 
+        /// <summary>
+        /// 信件来源分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("order_source_time")]
+        public async Task<object> OrderSourceTime([FromQuery] TimeSharingPagedKeywordRequest dto)
+        {
+            var item = await _orderRepository.OrderSourceTime(dto);
+
+            var titleData = await _systemDicDataRepository.Queryable()
+                .Where(p => p.DicTypeCode == "SourceChannel")
+                .Select(p => new
+                {
+                    Key = p.DicDataValue,
+                    Value = p.DicDataName
+                }).ToListAsync();
+
+            return new { Item = item, TitleData = titleData };
+        }
 
+        /// <summary>
+        /// 信件来源分时统计-导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("order_source_time_export")]
+        public async Task<FileStreamResult> OrderSourceTimeExport([FromBody] TimeSharingPagedKeywordRequest dto)
+        {
+            var dataTable = await _orderRepository.OrderSourceTimeExport(dto);
+            var stream = ExcelHelper.CreateStream(dataTable);
+            return ExcelStreamResult(stream, "信件来源分时统计数据");
         }
     }
 

+ 82 - 11
src/Hotline.Api/Controllers/OrderController.cs

@@ -2418,6 +2418,41 @@ public class OrderController : BaseController
         //}
 		if (!string.IsNullOrEmpty(order.WorkflowId))
         {
+            bool canInsteadHandle = false;
+			//班长代办
+			var settingEnable = _systemSettingCacheManager.GetSetting(SettingConstants.ChargeDAffaires);
+            var isEnable = settingEnable != null && settingEnable.SettingValue.Any() ? int.Parse(settingEnable?.SettingValue[0]) : 0;
+			if (isEnable > 0)
+			{
+				var setting = _systemSettingCacheManager.GetSetting(SettingConstants.SeatsMonitor);
+				var settingStr = setting?.SettingValue;
+				var roles = _sessionContext.Roles;
+				foreach (var item in settingStr)
+				{
+                    if (roles != null && roles.Contains(item))
+                    { 
+                        canInsteadHandle = true; 
+                    }else {
+                        canInsteadHandle = false;
+                    };
+				}
+				if (canInsteadHandle)
+				{
+					var unhandleSteps =
+						await _workflowDomainService.GetUnhandleStepsByOthersAsync(order.WorkflowId, HttpContext.RequestAborted);
+					// 会签多节点 不允许班长代办
+					if (unhandleSteps.Count > 1)
+						canInsteadHandle = false;
+					if (isEnable < 3 && unhandleSteps.Count == 1)
+                    {
+                        var type = isEnable - 1;
+						var step = unhandleSteps.FirstOrDefault(d => d.BusinessType == (EBusinessType)type);
+						canInsteadHandle = step != null && !string.IsNullOrEmpty(step.Id);
+						if (canInsteadHandle && step.IsInCountersign())
+							canInsteadHandle = false;
+					}
+				}
+			}
             var result = await _workflowDomainService.GetWorkflowHandlePermissionAsync(
                 order.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles,
                 cancellationToken: HttpContext.RequestAborted);
@@ -2425,12 +2460,14 @@ public class OrderController : BaseController
             dto.CountersignId = result.CountersignId;
             dto.CanHandle = result.CanHandle;
             dto.CanPrevious = result.CanPrevious;
+            dto.CanInsteadHandle = canInsteadHandle;
 
-            await _mediator.Publish(new GetOrderDetailNotify(result.Workflow,
+			await _mediator.Publish(new GetOrderDetailNotify(result.Workflow,
                 _sessionContext.RequiredUserId, _sessionContext.UserName,
                 _sessionContext.RequiredOrgId, _sessionContext.OrgName,
                 _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName));
         }
+       
 
         //var dto = _mapper.Map<OrderDto>(order!);
         //dto.CountersignId = countersignId;
@@ -2500,16 +2537,16 @@ public class OrderController : BaseController
         dto.RepeatableEventDetails = repeatables;
         if (!string.IsNullOrEmpty(dto.WorkflowId))
         {
-			var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true,
-				cancellationToken: HttpContext.RequestAborted);
-            var centerOpinion = workflow.Steps.Where(x => x.HandlerOrgId == OrgSeedData.CenterId).OrderByDescending(x=>x.CreationTime).Select(x=>x.Opinion).First();
-            dto.CenterOpinion = string.IsNullOrEmpty(centerOpinion)? string.Empty: centerOpinion;
-            var sendBack = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == dto.Id).OrderByDescending(x=>x.CreationTime).FirstAsync();
+            var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true,
+                cancellationToken: HttpContext.RequestAborted);
+            var centerOpinion = workflow.Steps.Where(x => x.HandlerOrgId == OrgSeedData.CenterId).OrderByDescending(x => x.CreationTime).Select(x => x.Opinion).First();
+            dto.CenterOpinion = string.IsNullOrEmpty(centerOpinion) ? string.Empty : centerOpinion;
+            var sendBack = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == dto.Id).OrderByDescending(x => x.CreationTime).FirstAsync();
             dto.SendBackOpinion = sendBack is { Id: not null } && !string.IsNullOrEmpty(sendBack.AuditContent) ? sendBack.AuditContent : string.Empty;
-            List<OrderRemarksDto> remarks = workflow.Steps.Where(x=> !string.IsNullOrEmpty(x.Remark)).Select(x => new OrderRemarksDto { Remark = x.Remark, RemarkTime = x.CreationTime, RemarkUser = x.CreatorName }).ToList();
+            List<OrderRemarksDto> remarks = workflow.Steps.Where(x => !string.IsNullOrEmpty(x.Remark)).Select(x => new OrderRemarksDto { Remark = x.Remark, RemarkTime = x.CreationTime, RemarkUser = x.CreatorName }).ToList();
             dto.OrderRemarks = remarks;
-		}
-		return dto;
+        }
+        return dto;
     }
 
     /// <summary>
@@ -2919,9 +2956,43 @@ public class OrderController : BaseController
     }
 
     /// <summary>
-    /// 结束会签
+    /// 查询工单办理下一步可选节点(带推荐部门)
     /// </summary>
-    [HttpPost("endcs")]
+    [HttpGet("nextsteps_commission/{orderId}")]
+    public async Task<NextStepsWithOpinionDto<RecommendStepOption>> GetNextStepsWithRecommendCommission(string orderId)
+    {
+	    var order = await _orderDomainService.GetOrderAsync(orderId, cancellationToken: HttpContext.RequestAborted);
+	    if (string.IsNullOrEmpty(order.WorkflowId))
+		    throw UserFriendlyException.SameMessage("该工单未开启流程");
+	    var unhandleSteps =
+		    await _workflowDomainService.GetUnhandleStepsByOthersAsync(order.WorkflowId, HttpContext.RequestAborted);
+	    if (unhandleSteps.Count > 1)
+		    throw UserFriendlyException.SameMessage("会签工单不允许班长代办");
+	    if (unhandleSteps.Count < 1)
+		    throw UserFriendlyException.SameMessage("未查询到流程信息");
+        var stepOne = unhandleSteps.First();
+        if (stepOne.IsInCountersign())
+	        throw UserFriendlyException.SameMessage("会签工单不允许班长代办");
+		var dto = await _workflowApplication.GetNextStepsAsync(order.WorkflowId, stepOne.Id, HttpContext.RequestAborted);
+	    dto.ExpiredTime = order.ExpiredTime;
+	    var rsp = _mapper.Map<NextStepsWithOpinionDto<RecommendStepOption>>(dto);
+	    foreach (var step in rsp.Steps)
+	    {
+		    if (dto.CurrentStepBusinessType is not EBusinessType.Send ||
+		        step.BusinessType is not EBusinessType.Department) continue;
+		    var org = await _organizeRepository.GetAsync(d => d.AreaCode == order.AreaCode, HttpContext.RequestAborted);
+		    if (org is null) continue;
+		    step.RecommendOrgId = org.Id;
+		    step.RecommendOrgName = org.Name;
+	    }
+
+	    return rsp;
+    }
+
+	/// <summary>
+	/// 结束会签
+	/// </summary>
+	[HttpPost("endcs")]
     public async Task EndCountersign([FromBody] EndCountersignDto dto)
     {
         var workflow = await _workflowDomainService.TerminalCountersignAsync(dto.CountersignId, HttpContext.RequestAborted);

+ 140 - 0
src/Hotline.Api/Controllers/OrderProvinceZmhdController.cs

@@ -0,0 +1,140 @@
+using DotNetCore.CAP;
+using Hotline.Orders;
+using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.Order;
+using Hotline.Share.Enums.Order;
+using MapsterMapper;
+using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
+using StackExchange.Redis;
+using System.Reflection;
+using XF.Domain.Authentications;
+using XF.Domain.Exceptions;
+using XF.Domain.Repository;
+
+namespace Hotline.Api.Controllers
+{
+    public class OrderProvinceZmhdController : BaseController
+    {
+        private readonly ILogger<OrderProvinceZmhdController> _logger;
+        private readonly ISessionContext _sessionContext;
+        private readonly IMapper _mapper;
+        private readonly ICapPublisher _capPublisher;
+        private readonly IOrderRepository _orderRepository;
+        private readonly IRepository<OrderProvinceZmhd> _orderProvinceZmhdRepository;
+
+        public OrderProvinceZmhdController(ILogger<OrderProvinceZmhdController> logger,
+            ISessionContext sessionContext,
+            IMapper mapper,
+            ICapPublisher capPublisher,
+            IOrderRepository orderRepository,
+            IRepository<OrderProvinceZmhd> orderProvinceZmhdRepository)
+        {
+            _logger = logger;
+            _sessionContext = sessionContext;
+            _mapper = mapper;
+            _capPublisher = capPublisher;
+            _orderRepository = orderRepository;
+            _orderProvinceZmhdRepository = orderProvinceZmhdRepository;
+        }
+
+        /// <summary>
+        /// 查询列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("getorderlist")]
+        public async Task<PagedDto<OrderDto>> GetOrderList([FromQuery] OrderProvinceZmhdDto dto)
+        {
+            RefAsync<int> total = 0;
+            var items = await _orderRepository.Queryable()
+                .Where(p => p.SourceChannelCode == "SZMHD" && p.IsProvince == false && p.Status > EOrderStatus.Filed)
+                .WhereIF(!string.IsNullOrEmpty(dto.No), p => p.No == dto.No)
+                .WhereIF(!string.IsNullOrEmpty(dto.ProvinceNo), p => p.ProvinceNo == dto.ProvinceNo)
+                .WhereIF(!string.IsNullOrEmpty(dto.Title), p => p.Title.StartsWith(dto.Title!))
+                .WhereIF(!string.IsNullOrEmpty(dto.AnswerOu), p => p.ActualHandleOrgName == dto.AnswerOu)
+                .WhereIF(!string.IsNullOrEmpty(dto.AuditFirstName), p => p.AuditFirstName == dto.AuditFirstName)
+                .WhereIF(dto.IsProvinceZmhd.HasValue, p => p.IsProvinceZmhd == dto.IsProvinceZmhd)
+                .WhereIF(dto.StartTime.HasValue, d => d.AuditFirstTime >= dto.StartTime) //初审时间开始
+                .WhereIF(dto.EndTime.HasValue, d => d.AuditFirstTime <= dto.EndTime) //初审时间结束
+                .OrderByDescending(d => d.CreationTime)
+                .ToPageListAsync(dto.PageIndex, dto.PageSize, total, HttpContext.RequestAborted);
+
+            return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
+        }
+
+        /// <summary>
+        /// 查询政民互动发布详情
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpGet("getorderprovincezmhdinfo")]
+        public async Task<PublicOrderProvinceZmhdDto> GetOrderProvinceZmhdInfo(string Id)
+        {
+            var info = await _orderProvinceZmhdRepository.GetAsync(p => p.Id == Id, HttpContext.RequestAborted);
+            if (info == null)
+                throw UserFriendlyException.SameMessage("查询失败");
+
+            return _mapper.Map<PublicOrderProvinceZmhdDto>(info);
+        }
+
+        /// <summary>
+        /// 政民互动发布
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("add")]
+        public async Task AddOrderProvinceZmhd([FromBody] AddOrderProvinceZmhdDto dto)
+        {
+            if (string.IsNullOrEmpty(dto.AnswerContent))
+                throw UserFriendlyException.SameMessage("整理结果不能为空!");
+
+            if (string.IsNullOrEmpty(dto.PublicOpinion))
+                throw UserFriendlyException.SameMessage("公开意见不能为空!");
+
+            if (dto.PublicOpinion.Length > 300)
+                throw UserFriendlyException.SameMessage("公开意见不能超过300字符!");
+
+            var order = await _orderRepository.GetAsync(p => p.Id == dto.OrderId, HttpContext.RequestAborted);
+            if (order == null)
+                throw UserFriendlyException.SameMessage("工单查询失败!");
+
+            OrderProvinceZmhd orderProvinceZmhd = new()
+            {
+                No = order.No,
+                ProvinceNo = order.ProvinceNo,
+                OrderId = order.Id,
+                Title = order.Title,
+                AnswerTime = order.ActualHandleTime,
+                AnswerOu = order.ActualHandleOrgName,
+                AnswerContent = dto.AnswerContent,
+                AuditFirstName = _sessionContext.UserName,
+                AuditFirstTime = DateTime.Now,
+                AuditSecondName = _sessionContext.UserName,
+                PublishDate = DateTime.Now,
+                PublicOpinion = dto.PublicOpinion
+            };
+            //查询是否已经发布过
+            var info = await _orderProvinceZmhdRepository.GetAsync(p => p.OrderId == order.Id, HttpContext.RequestAborted);
+            if (info != null)
+                throw UserFriendlyException.SameMessage("此工单已公开!");
+
+            //发布
+            var id = await _orderProvinceZmhdRepository.AddAsync(orderProvinceZmhd, HttpContext.RequestAborted);
+            if (string.IsNullOrEmpty(id))
+                throw UserFriendlyException.SameMessage("公开失败!");
+
+            //修改工单发布数据
+            order.IsProvinceZmhd = true;
+            order.AuditFirstName = _sessionContext.UserName;
+            order.AuditFirstTime = orderProvinceZmhd.AuditFirstTime;
+            order.OrderProvinceZmhdId = orderProvinceZmhd.Id;
+            await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
+
+            //推送数据
+            var publishPublishOrder = _mapper.Map<PublicOrderProvinceZmhdDto>(orderProvinceZmhd);
+            await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderProvinceZmhd, publishPublishOrder);
+        }
+
+    }
+}

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

@@ -16,7 +16,7 @@
     }
   },
   "ConnectionStrings": {
-    "Hotline": "PORT=5432;DATABASE=hotline;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;",
+    "Hotline": "PORT=5432;DATABASE=hotline_dev;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;"
     //"Redis": "110.188.24.182:50179,password=fengwo22@@",
     //"MongoDB": "mongodb://192.168.100.121:27017",
     //"Wex": "server=222.212.82.225;Port=4509;Database=fs_kft;Uid=root;Pwd=Wex@12345;"
@@ -25,7 +25,7 @@
     "Host": "110.188.24.182",
     "Port": 50179,
     "Password": "fengwo123!$!$",
-    "Database": 3
+    "Database": 5
   },
   "Swagger": true,
   "Cors": {

+ 5 - 0
src/Hotline.Application/FlowEngine/IWorkflowApplication.cs

@@ -67,6 +67,11 @@ namespace Hotline.Application.FlowEngine
         /// </summary>
         Task<NextStepsWithOpinionDto<NextStepOption>> GetNextStepsAsync(string workflowId, CancellationToken cancellationToken);
 
+        /// <summary>
+        /// 查询指定节点的下一步待选节点
+        /// </summary>
+        Task<NextStepsWithOpinionDto<NextStepOption>> GetNextStepsAsync(string workflowId, string stepId, CancellationToken cancellationToken);
+
         /// <summary>
         /// 查询撤回可选节点
         /// </summary>

+ 29 - 4
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -30,6 +30,7 @@ using Hotline.Share.Dtos.File;
 using Microsoft.Extensions.Logging;
 using System.Text;
 using System.Diagnostics;
+using NPOI.SS.Formula.Functions;
 
 namespace Hotline.Application.FlowEngine;
 
@@ -218,8 +219,12 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
             withTraces: true, withCountersigns: true, cancellationToken: cancellationToken);
 
-        var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow,
-            current.RequiredUserId, current.RequiredOrgId, current.Roles);
+        //var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow,
+        //    current.RequiredUserId, current.RequiredOrgId, current.Roles);
+        var currentStep = workflow.Steps.FirstOrDefault(d => d.Id == dto.StepId);
+        if (currentStep == null)
+            throw new UserFriendlyException(
+                $"未找到对应节点, workflowId: {dto.WorkflowId}, stepId: {dto.StepId}", "未找到对应节点");
         if (currentStep.Status is EWorkflowStepStatus.Handled)
             throw new UserFriendlyException("该状态不支持继续办理");
 
@@ -457,6 +462,24 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         if (currentStep.StepType is EStepType.End)
             throw new UserFriendlyException("结束节点无需办理");
 
+        return await GetNextStepsAsync(workflow, currentStep, cancellationToken);
+    }
+
+    public async Task<NextStepsWithOpinionDto<NextStepOption>> GetNextStepsAsync(string workflowId, string stepId, CancellationToken cancellationToken)
+    {
+        var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withDefine: true, withSteps: true,
+            cancellationToken: cancellationToken);
+        var currentStep = workflow.Steps.FirstOrDefault(d => d.Id == stepId);
+        if (currentStep == null)
+            throw new UserFriendlyException($"未查询到选择节点, workflowId: {workflowId}, stepId: {stepId}");
+        if (currentStep.StepType is EStepType.End)
+            throw new UserFriendlyException("结束节点无需办理");
+
+        return await GetNextStepsAsync(workflow, currentStep, cancellationToken);
+    }
+
+    private async Task<NextStepsWithOpinionDto<NextStepOption>> GetNextStepsAsync(Workflow workflow, WorkflowStep currentStep, CancellationToken cancellationToken)
+    {
         var dto = new NextStepsWithOpinionDto<NextStepOption>
         {
             CanReject = workflow.IsReviewType() && currentStep.CanReject,
@@ -465,6 +488,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             CurrentStepBusinessType = currentStep.BusinessType,
             TimeTypeOptions = EnumExts.GetDescriptions<ETimeType>().ToList(),
             IsMainHandlerShow = workflow.WorkflowDefinition.IsMainHandlerShow,
+            StepId = currentStep.Id
         };
 
         var currentStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, currentStep.Code);
@@ -485,14 +509,15 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             {
                 // 宜宾需求:会签汇总节点展示会签办理节点办理意见
                 var countersignHandleSteps = workflow.Steps.Where(d =>
-                        d.CountersignId == currentStep.CountersignId &&
-                        d.CountersignPosition is ECountersignPosition.Multi or ECountersignPosition.Single).ToList();
+                    d.CountersignId == currentStep.CountersignId &&
+                    d.CountersignPosition is ECountersignPosition.Multi or ECountersignPosition.Single).ToList();
                 var sb = new StringBuilder();
                 foreach (var countersignHandleStep in countersignHandleSteps)
                 {
                     //sb.AppendLine($"{countersignHandleStep.GetActualHandler()?.GetHandler().Value} : {countersignHandleStep.Opinion}");
                     sb.AppendLine($"{countersignHandleStep.GetHandler().Value} : {countersignHandleStep.Opinion}");
                 }
+
                 dto.Opinion = sb.ToString();
 
                 //当前待办节点为会签汇总节点时:检查是否为顶级会签汇总节点,t:按配置往下走,f:继续往上汇总,不需要重复往下指派

+ 241 - 57
src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs

@@ -258,51 +258,7 @@ namespace Hotline.Repository.SqlSugar.Orders
               })
                .ToPivotTableAsync(p => p.AreaName, p => p.Hour, p => p.Sum(x => x.count));
 
-            //修改列名
-            dt.Columns["Hour"].ColumnName = "时间段";
-            dt.Columns.Remove("Column1");
-
-            //增加小计
-            DataColumn totalColumn = new DataColumn("小计", typeof(decimal));
-            dt.Columns.Add(totalColumn);
-            for (int i = 0; i < dt.Rows.Count; i++)
-            {
-                int sumcount = 0;
-                for (int j = 1; j < dt.Columns.Count - 1; j++)
-                {
-                    sumcount += Convert.ToInt32(dt.Rows[i][j].ToString());
-                }
-                dt.Rows[i][dt.Columns.Count - 1] = sumcount;
-            }
-
-            //增加合计
-            DataRow totalRow = dt.NewRow();
-            totalRow["时间段"] = "合计";
-            for (int i = 1; i < dt.Columns.Count; i++)
-            {
-                int sumcount = 0;
-                for (int j = 0; j < dt.Rows.Count; j++)
-                {
-                    sumcount += Convert.ToInt32(dt.Rows[j][i].ToString());
-                }
-                totalRow[i] = sumcount;
-            }
-            dt.Rows.Add(totalRow);
-
-            //移除列
-            if (dto.AddColumnName.Any())
-            {
-                for (int i = 0; i < dt.Columns.Count; i++)
-                {
-                    var name = dt.Columns[i].ColumnName;
-                    if (!dto.AddColumnName.Contains(name))
-                    {
-                        dt.Columns.Remove(name);
-                        i = 0;
-                    }
-                }
-            }
-            return dt;
+            return InitDatatTable(dt, dto.AddColumnName);
         }
 
         /// <summary>
@@ -406,13 +362,234 @@ namespace Hotline.Repository.SqlSugar.Orders
               })
                .ToPivotTableAsync(p => p.HotSpotName, p => p.Hour, p => p.Sum(x => x.count));
 
+            return InitDatatTable(dt, dto.AddColumnName);
+        }
+
+        /// <summary>
+        /// 受理类型分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<object> OrderAcceptanceTime(TimeSharingPagedKeywordRequest dto)
+        {
+            List<int> dts = new List<int>();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     AcceptTypeCode = p.AcceptTypeCode,
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<SystemDicData>()
+              .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.AcceptTypeCode)
+              .Where((s, p) => s.DicTypeCode == "AcceptType")
+              .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.DicDataValue)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.AcceptTypeCode != null && p.AcceptTypeCode != "", 1, 0)),
+                  DicDataValue = s.DicDataValue,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  DicDataName = s.DicDataName
+              })
+              .MergeTable();
+
+            var list = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+                .OrderBy(x => x.ColumnName)
+               .Select((x, p) => new
+               {
+                   Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                   p.DicDataValue,
+                   p.count
+               })
+                .ToPivotListAsync(p => p.DicDataValue, p => p.Hour, p => p.Sum(x => x.count));
+            return list;
+
+        }
+
+        /// <summary>
+        /// 受理类型分时统计---导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<DataTable> OrderAcceptanceTimeExport(TimeSharingPagedKeywordRequest dto)
+        {
+            List<int> dts = new();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     AcceptTypeCode = p.AcceptTypeCode,
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<SystemDicData>()
+              .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.AcceptTypeCode)
+              .Where((s, p) => s.DicTypeCode == "AcceptType")
+              .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.DicDataValue)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.AcceptTypeCode != null && p.AcceptTypeCode != "", 1, 0)),
+                  DicDataValue = s.DicDataValue,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  DicDataName = s.DicDataName
+              })
+              .MergeTable();
+
+            var dt = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+               .OrderBy(x => x.ColumnName)
+              .Select((x, p) => new
+              {
+                  Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                  p.DicDataName,
+                  p.count
+              })
+               .ToPivotTableAsync(p => p.DicDataName, p => p.Hour, p => p.Sum(x => x.count));
+
+            return InitDatatTable(dt, dto.AddColumnName);
+        }
+
+        /// <summary>
+        /// 信件来源分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<object> OrderSourceTime(TimeSharingPagedKeywordRequest dto)
+        {
+            List<int> dts = new List<int>();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     SourceChannelCode = p.SourceChannelCode,
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<SystemDicData>()
+              .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.SourceChannelCode)
+              .Where((s, p) => s.DicTypeCode == "SourceChannel")
+              .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.DicDataValue)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.SourceChannelCode != null && p.SourceChannelCode != "", 1, 0)),
+                  DicDataValue = s.DicDataValue,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  DicDataName = s.DicDataName
+              })
+              .MergeTable();
+
+            var list = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+                .OrderBy(x => x.ColumnName)
+               .Select((x, p) => new
+               {
+                   Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                   p.DicDataValue,
+                   p.count
+               })
+                .ToPivotListAsync(p => p.DicDataValue, p => p.Hour, p => p.Sum(x => x.count));
+            return list;
+
+        }
+
+        /// <summary>
+        /// 信件来源分时统计---导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<DataTable> OrderSourceTimeExport(TimeSharingPagedKeywordRequest dto)
+        {
+            List<int> dts = new();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     SourceChannelCode = p.SourceChannelCode,
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<SystemDicData>()
+              .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.SourceChannelCode)
+              .Where((s, p) => s.DicTypeCode == "SourceChannel")
+              .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.DicDataValue)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.SourceChannelCode != null && p.SourceChannelCode != "", 1, 0)),
+                  DicDataValue = s.DicDataValue,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  DicDataName = s.DicDataName
+              })
+              .MergeTable();
+
+            var dt = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+               .OrderBy(x => x.ColumnName)
+              .Select((x, p) => new
+              {
+                  Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                  p.DicDataName,
+                  p.count
+              })
+               .ToPivotTableAsync(p => p.DicDataName, p => p.Hour, p => p.Sum(x => x.count));
+            return InitDatatTable(dt, dto.AddColumnName);
+        }
+
+        /// <summary>
+        /// 处理导出数据
+        /// </summary>
+        /// <param name="dt"></param>
+        /// <param name="AddColumnName"></param>
+        /// <returns></returns>
+        public DataTable InitDatatTable(DataTable dt, List<string> AddColumnName)
+        {
             //修改列名
-            dt.Columns["Hour"].ColumnName = "时间段";
-            dt.Columns.Remove("Column1");
+            if (dt.Columns.Contains("Hour"))
+                dt.Columns["Hour"].ColumnName = "时间段";
 
             //增加小计
             DataColumn totalColumn = new DataColumn("小计", typeof(decimal));
             dt.Columns.Add(totalColumn);
+            if (dt.Columns.Contains("Column1"))
+                dt.Columns.Remove("Column1");
+            //计算小计
             for (int i = 0; i < dt.Rows.Count; i++)
             {
                 int sumcount = 0;
@@ -437,20 +614,27 @@ namespace Hotline.Repository.SqlSugar.Orders
             }
             dt.Rows.Add(totalRow);
 
-            //移除列
-            if (dto.AddColumnName.Any())
+            //创建新表
+            DataTable dt2 = new DataTable();
+
+            //添加表头
+            foreach (var item in AddColumnName)
+            {
+                if (dt.Columns.Contains(item))
+                    dt2.Columns.Add(item);
+            }
+
+            //处理数据
+            foreach (DataRow sourceRow in dt.Rows)
             {
-                for (int i = 0; i < dt.Columns.Count; i++)
+                DataRow targetRow = dt2.NewRow();
+                foreach (var item in AddColumnName)
                 {
-                    var name = dt.Columns[i].ColumnName;
-                    if (!dto.AddColumnName.Contains(name))
-                    {
-                        dt.Columns.Remove(name);
-                        i = 0;
-                    }
+                    targetRow[item] = sourceRow[item];
                 }
+                dt2.Rows.Add(targetRow);
             }
-            return dt;
+            return dt2;
         }
 
         public ISugarQueryable<SelectOrderId> OrderListUnionAll(ISugarQueryable<SelectOrderId> t1, ISugarQueryable<SelectOrderId> t2)

+ 5 - 0
src/Hotline.Share/Dtos/FlowEngine/NextStepsDto.cs

@@ -4,6 +4,11 @@ namespace Hotline.Share.Dtos.FlowEngine;
 
 public class NextStepsDto
 {
+    /// <summary>
+    /// 当前办理节点
+    /// </summary>
+    public string StepId { get; set; }
+
     // public IReadOnlyList<NextStepOption> Steps { get; set; }
     public DateTime? ExpiredTime { get; set; }
 

+ 5 - 0
src/Hotline.Share/Dtos/FlowEngine/NextWorkflowDto.cs

@@ -9,6 +9,11 @@ public class NextWorkflowDto : BasicWorkflowDto
 {
     public string WorkflowId { get; set; }
 
+    /// <summary>
+    /// 当前办理节点id
+    /// </summary>
+    public string StepId { get; set; }
+
     ///// <summary>
     ///// 下一节点到期时间(节点期满时间)
     ///// 需求调整

+ 27 - 2
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -355,9 +355,14 @@ namespace Hotline.Share.Dtos.Order
         public bool CanHandle { get; set; }
 
         /// <summary>
-        /// 延期申请数量
+        /// 是否可代办
         /// </summary>
-        public int DelayingCount => OrderDelays?.Count ?? 0;
+        public bool CanInsteadHandle { get; set; }
+
+		/// <summary>
+		/// 延期申请数量
+		/// </summary>
+		public int DelayingCount => OrderDelays?.Count ?? 0;
 
         /// <summary>
         /// 是否紧急
@@ -812,6 +817,26 @@ namespace Hotline.Share.Dtos.Order
         /// 是否紧急
         /// </summary>
         public bool IsUrgent { get; set; }
+
+        /// <summary>
+        /// 是否政民互动公开
+        /// </summary>
+        public bool IsProvinceZmhd { get; set; }
+
+        /// <summary>
+        /// 初审人姓名
+        /// </summary>
+        public string? AuditFirstName { get; set; }
+
+        /// <summary>
+        /// 初审时间
+        /// </summary>
+        public DateTime? AuditFirstTime { get; set; }
+
+        /// <summary>
+        /// 政民互动公开ID
+        /// </summary>
+        public string? OrderProvinceZmhdId { get; set; }
     }
 
     public record CanLinkCallRecordOrderDto : PagedKeywordRequest

+ 135 - 0
src/Hotline.Share/Dtos/Order/OrderProvinceZmhdDto.cs

@@ -0,0 +1,135 @@
+using Hotline.Share.Requests;
+
+namespace Hotline.Share.Dtos.Order
+{
+    /// <summary>
+    /// 政民互动查询
+    /// </summary>
+    public record OrderProvinceZmhdDto : PagedRequest
+    {
+        /// <summary>
+        /// 工单编号
+        /// </summary>
+        public string? No { get; set; }
+
+        /// <summary>
+        /// 省工单编号
+        /// </summary>
+        public string? ProvinceNo { get; set; }
+
+        /// <summary>
+        /// 工单标题
+        /// </summary>
+        public string? Title { get; set; }
+
+        /// <summary>
+        /// 答复部门名称
+        /// </summary>
+        public string? AnswerOu { get; set; }
+
+        /// <summary>
+        /// 初审人姓名
+        /// </summary>
+        public string? AuditFirstName { get; set; }
+
+        /// <summary>
+        /// 审核开始时间
+        /// </summary>
+        public DateTime? StartTime { get; set; }
+        /// <summary>
+        /// 审核结束时间
+        /// </summary>
+        public DateTime? EndTime { get; set; }
+
+        /// <summary>
+        /// 是否政民互动公开
+        /// </summary>
+        public bool? IsProvinceZmhd { get; set; }
+    }
+
+    public class AddOrderProvinceZmhdDto
+    {
+        /// <summary>
+        /// 工单Id
+        /// </summary>
+        public string OrderId { get; set; }
+
+        /// <summary>
+        /// 整理结果
+        /// </summary>
+        public string AnswerContent { get; set; }
+
+        /// <summary>
+        /// 公开意见(长度300)
+        /// </summary>
+        public string? PublicOpinion { get; set; }
+    }
+
+    public class PublicOrderProvinceZmhdDto
+    {
+        /// <summary>
+        /// Id
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 工单编号
+        /// </summary>
+        public string No { get; set; }
+
+        /// <summary>
+        /// 省工单编号
+        /// </summary>
+        public string ProvinceNo { get; set; }
+
+        /// <summary>
+        /// 工单Id
+        /// </summary>
+        public string OrderId { get; set; }
+
+        /// <summary>
+        /// 工单标题
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 部门答复时间
+        /// </summary>
+        public DateTime? AnswerTime { get; set; }
+
+        /// <summary>
+        /// 答复部门名称
+        /// </summary>
+        public string AnswerOu { get; set; }
+
+        /// <summary>
+        /// 答复内容
+        /// </summary>
+        public string AnswerContent { get; set; }
+
+        /// <summary>
+        /// 初审人姓名
+        /// </summary>
+        public string? AuditFirstName { get; set; }
+
+        /// <summary>
+        /// 初审时间
+        /// </summary>
+        public DateTime? AuditFirstTime { get; set; }
+
+        /// <summary>
+        /// 二审人姓名
+        /// </summary>
+        public string? AuditSecondName { get; set; }
+
+        /// <summary>
+        /// 公开时间
+        /// </summary>
+        public DateTime? PublishDate { get; set; }
+
+        /// <summary>
+        /// 公开意见
+        /// </summary>
+        public string? PublicOpinion { get; set; }
+    }
+}

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

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

+ 7 - 2
src/Hotline.Share/Mq/EventNames.Order.cs

@@ -95,6 +95,11 @@ namespace Hotline.Share.Mq
         /// </summary>
         public const string HotlineOrderTranspondCity = "hotline.order.transpond.city";
 
-		#endregion
-	}
+        /// <summary>
+        /// 政民互动公开
+        /// </summary>
+        public const string HotlineOrderProvinceZmhd = "hotline.order.province.zmhd";
+
+        #endregion
+    }
 }

+ 6 - 0
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -262,5 +262,11 @@ namespace Hotline.FlowEngine.Workflows
         /// 流程被签收至某个用户(更新流转对象,办理对象,节点办理对象以及stepHandlers)
         /// </summary>
         Task<Workflow> SignToSomebodyAsync(string workflowId, string userId, string username, string orgId, string orgName, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// 非节点办理人员查询待办节点
+        /// </summary>
+        /// <returns></returns>
+        Task<ICollection<WorkflowStep>> GetUnhandleStepsByOthersAsync(string workflowId, CancellationToken cancellationToken);
     }
 }

+ 11 - 0
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -946,6 +946,17 @@ namespace Hotline.FlowEngine.Workflows
             return workflow;
         }
 
+        /// <summary>
+        /// 非节点办理人员查询待办节点
+        /// </summary>
+        /// <returns></returns>
+        public async Task<ICollection<WorkflowStep>> GetUnhandleStepsByOthersAsync(string workflowId, CancellationToken cancellationToken)
+        {
+            return await _workflowStepRepository.Queryable()
+                .Where(d => d.WorkflowId == workflowId && d.Status != EWorkflowStepStatus.Handled)
+                .ToListAsync(cancellationToken);
+        }
+
         /// <summary>
         /// 查找当前会签内所有节点(含start,end)
         /// </summary>

+ 30 - 1
src/Hotline/Orders/IOrderRepository.cs

@@ -1,4 +1,5 @@
-using Hotline.Share.Requests;
+using Hotline.Settings;
+using Hotline.Share.Requests;
 using SqlSugar;
 using System.Data;
 using XF.Domain.Repository;
@@ -53,6 +54,34 @@ namespace Hotline.Orders
         /// <returns></returns>
         Task<DataTable> OrderHotspotTimeExport(TimeSharingPagedKeywordRequest dto);
 
+        /// <summary>
+        /// 受理类型分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<object> OrderAcceptanceTime(TimeSharingPagedKeywordRequest dto);
+
+        /// <summary>
+        /// 受理类型分时统计---导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<DataTable> OrderAcceptanceTimeExport(TimeSharingPagedKeywordRequest dto);
+
+        /// <summary>
+        /// 信件来源分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<object> OrderSourceTime(TimeSharingPagedKeywordRequest dto);
+
+        /// <summary>
+        /// 信件来源分时统计---导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<DataTable> OrderSourceTimeExport(TimeSharingPagedKeywordRequest dto);
+
     }
 
     public interface IOrderScreenRepository : IRepositoryWorkflow<OrderScreen>

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

@@ -800,6 +800,30 @@ namespace Hotline.Orders
         /// 待发布人Id
         /// </summary>
         public string? WaitForPublisherId { get; set; }
+
+        /// <summary>
+        /// 是否政民互动公开
+        /// </summary>
+        [SugarColumn(DefaultValue = "f")]
+        public bool IsProvinceZmhd { get; set; }
+
+        /// <summary>
+        /// 初审人姓名
+        /// </summary>
+        [SugarColumn(ColumnDescription = "初审人姓名")]
+        public string? AuditFirstName { get; set; }
+
+        /// <summary>
+        /// 初审时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "初审时间")]
+        public DateTime? AuditFirstTime { get; set; }
+
+        /// <summary>
+        /// 政民互动公开ID
+        /// </summary>
+        [SugarColumn(ColumnDescription = "政民互动公开ID")]
+        public string? OrderProvinceZmhdId { get; set; }
     }
 
     public partial class Order

+ 83 - 0
src/Hotline/Orders/OrderProvinceZmhd.cs

@@ -0,0 +1,83 @@
+using SqlSugar;
+using XF.Domain.Repository;
+
+namespace Hotline.Orders
+{
+    /// <summary>
+    /// 政民互动公开
+    /// </summary>
+    public class OrderProvinceZmhd : CreationEntity
+    {
+        /// <summary>
+        /// 工单编号
+        /// </summary>
+        [SugarColumn( ColumnDescription = "工单编号")]
+        public string No { get; set; }
+
+        /// <summary>
+        /// 省工单编号
+        /// </summary>
+        [SugarColumn(ColumnDescription = "省工单编号")]
+        public string ProvinceNo { get; set; }
+
+        /// <summary>
+        /// 工单Id
+        /// </summary>
+        [SugarColumn(ColumnDescription = "工单Id")]
+        public string OrderId { get; set; }
+
+        /// <summary>
+        /// 工单标题
+        /// </summary>
+        [SugarColumn(ColumnDescription = "工单标题")]
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 部门答复时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "部门答复时间")]
+        public DateTime? AnswerTime { get; set; }
+
+        /// <summary>
+        /// 答复部门名称
+        /// </summary>
+        [SugarColumn(ColumnDescription = "答复部门名称")]
+        public string AnswerOu { get; set; }
+
+        /// <summary>
+        /// 答复内容
+        /// </summary>
+        [SugarColumn(ColumnDataType = "text", ColumnDescription = "答复内容")]
+        public string AnswerContent { get; set; }
+
+        /// <summary>
+        /// 初审人姓名
+        /// </summary>
+        [SugarColumn(ColumnDescription = "初审人姓名")]
+        public string? AuditFirstName { get; set; }
+
+        /// <summary>
+        /// 初审时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "初审时间")]
+        public DateTime? AuditFirstTime { get; set; }
+
+        /// <summary>
+        /// 二审人姓名
+        /// </summary>
+        [SugarColumn(ColumnDescription = "二审人姓名")]
+        public string? AuditSecondName { get; set; }
+
+        /// <summary>
+        /// 公开时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "公开时间")]
+        public DateTime? PublishDate { get; set; }
+
+        /// <summary>
+        /// 公开意见
+        /// </summary>
+        [SugarColumn(Length = 300, ColumnDescription = "公开意见")]
+        public string? PublicOpinion { get; set; }
+    }
+}

+ 6 - 1
src/Hotline/Settings/SettingConstants.cs

@@ -354,5 +354,10 @@ namespace Hotline.Settings
         /// 是否开启重复工单
         /// </summary>
         public const string IsOpenRepeatedWorkOrders = "IsOpenRepeatedWorkOrders";
-    }
+
+        /// <summary>
+        /// 班长代办
+        /// </summary>
+        public const string ChargeDAffaires = "ChargeDAffaires";
+	}
 }

+ 89 - 0
src/Hotline/dataview.md

@@ -0,0 +1,89 @@
+select aaa.*,bbb."SeatVisitResult" from 
+(select 
+CASE "ordertemp"."Status"
+	WHEN 500 THEN '已回访'
+	WHEN 400 THEN '已发布'
+	WHEN 300 THEN '已归档'
+	WHEN 200 THEN '会签中'
+	WHEN 100 THEN '办理中'
+	WHEN 9 THEN '退回省平台'
+	WHEN 2 THEN '特提待受理'
+	WHEN 1 THEN '退回待受理'
+	WHEN 0 THEN '待受理'
+	ELSE	'未知'
+END AS "Status",
+CASE 	WHEN "Status">=300 and "ExpiredTime">"FiledTime" THEN '正常'
+		  WHEN "Status">=300 AND "ExpiredTime"<"FiledTime" THEN '超期'
+			WHEN "Status"<300 AND "ExpiredTime"> now() AND now()> "NearlyExpiredTime" THEN '即将超期'
+			WHEN "Status"<300 AND "ExpiredTime">now() AND now()< "NearlyExpiredTime" THEN '正常'
+	ELSE '未知'
+END AS "IsOverExpiredTime",
+"SourceChannel" AS "Source" , 
+"TransferPhone" AS "TransferPhone" ,
+"ActualHandleStepName" AS "ActualHandleStepName" ,
+"ReTransactNum" AS "ReTransactNum" , 
+(select CASE "screentemp"."Status"
+	WHEN 0 THEN '待办'
+	WHEN 1 THEN '审批中'
+	WHEN 2 THEN '审批完成'
+	WHEN 3 THEN '审批拒绝'
+	ELSE '-'
+END AS "OrderScreenStatus"
+ from order_screen screentemp WHERE "OrderId"="ordertemp"."Id" order by "CreationTime" DESC LIMIT 1) as "OrderScreenStatus", 
+"No" AS "No" , 
+"ProvinceNo" AS "ProvinceNo" , 
+"CreationTime" AS "StartTime" , 
+"Title" AS "Title" , 
+"ExpiredTime" AS "ExpiredTime" , 
+"OrgLevelOneName" AS "OrgLevelOneName" , 
+"OrgLevelTwoName" AS "OrgLevelTwoName" , 
+"AcceptorOrgName" AS "AcceptorOrgName" , 
+"FiledTime" AS "FiledTime" , 
+"AcceptType" AS "AcceptType" , 
+"HotspotName" AS "HotspotName",
+"HotspotSpliceName" AS "HotspotSpliceName",
+CASE 
+	WHEN "Town" is not NULL and "Town" <>'' THEN "Town"
+  WHEN "County" is not null and "County" <>'' THEN "County"
+	ELSE "City"
+END AS "AreaName",
+"Address"  As "FullAreaName",
+"AcceptorName" AS "AcceptorName" ,
+ "FromName" AS "FromName" , 
+ "Contact" AS "Contact" , 
+ "FromPhone" AS "FromPhone" , 
+ "Street" AS "Address" ,
+ '' AS "Obj",
+ CASE "IdentityType"
+	WHEN 1 THEN '市民'
+	WHEN 2 THEN '企业'
+	ELSE
+		'市民'
+END AS "IdentityType",
+CASE "FromGender"
+	WHEN 0 THEN '女士'
+	WHEN 1 THEN '先生'
+	ELSE '未知'
+END AS "FromGender" , 
+'-' AS "SeatVisitResult",
+"FirstVisitResult" AS "FirstVisitResult" , 
+"PushType" AS "PushType" , 
+"Content" AS "Content" , 
+"ActualOpinion" AS "ActualOpinion" ,
+"FileOpinion" AS "FileOpinion" ,
+"Id" AS "SugarNav_Id" FROM "order" ordertemp  WHERE (( "CreationTime" >= '2024-06-26' ) AND ( "CreationTime" < '2024-07-3' ))  AND ( "IsDeleted" = FALSE )ORDER BY "CreationTime" ASC) aaa
+left join 
+(select DISTINCT CASE visitdetailtemp."SeatEvaluate"
+	WHEN 0 THEN '默认满意'
+	WHEN 2 THEN '不满意'
+	WHEN 4 THEN '满意'
+	WHEN 5 THEN '非常满意'
+	WHEN 6 THEN '未接通'
+	WHEN 7 THEN '未做评价'
+	ELSE
+		'-'
+END AS "SeatVisitResult",visittemp."OrderId" as "OrderId"
+ from order_visit visittemp
+left join order_visit_detail visitdetailtemp on visittemp."Id"= visitdetailtemp."VisitId"  
+where visittemp."CreationTime">='2024-06-26' and visitdetailtemp."VisitTarget"=10 AND visittemp."VisitState"=30 ) bbb on aaa."SugarNav_Id"=bbb."OrderId"
+