Browse Source

Merge branch 'test' into test_Guardian

田爽 1 month ago
parent
commit
eb93174f73
41 changed files with 1304 additions and 467 deletions
  1. 1 1
      Hotline.sln
  2. 102 2
      src/Hotline.Api/Controllers/Bi/BiOrderController.cs
  3. 3 3
      src/Hotline.Api/Controllers/FwThirdController.cs
  4. 185 56
      src/Hotline.Api/Controllers/OrderController.cs
  5. 2 2
      src/Hotline.Api/Controllers/Snapshot/PointsController.cs
  6. 30 2
      src/Hotline.Api/Controllers/Snapshot/SnapshotController.cs
  7. 7 5
      src/Hotline.Api/Controllers/TelRestController.cs
  8. 40 22
      src/Hotline.Application/CallCenter/DefaultCallApplication.cs
  9. 18 2
      src/Hotline.Application/OrderApp/IOrderApplication.cs
  10. 152 143
      src/Hotline.Application/OrderApp/OrderAnalysisApplication.cs
  11. 170 0
      src/Hotline.Application/OrderApp/OrderApplication.cs
  12. 21 0
      src/Hotline.Application/Snapshot/Contracts/ISnapshotApplication.cs
  13. 1 1
      src/Hotline.Application/Snapshot/Contracts/ISnapshotPointsApplication.cs
  14. 0 0
      src/Hotline.Application/Snapshot/DefaultSnapshotApplication.cs
  15. 93 8
      src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs
  16. 5 2
      src/Hotline.Application/Snapshot/SnapshotOrderApplication.cs
  17. 6 5
      src/Hotline.Application/Snapshot/SnapshotPointsApplication.cs
  18. 0 0
      src/Hotline.Application/Snapshot/ZiGongSnapshotApplication.cs
  19. 2 1
      src/Hotline.Share/Dtos/Article/BulletinDto.cs
  20. 9 0
      src/Hotline.Share/Dtos/Order/OrderBiDto.cs
  21. 41 17
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  22. 172 165
      src/Hotline.Share/Dtos/Order/OrderSuperviseDto.cs
  23. 10 0
      src/Hotline.Share/Dtos/Order/OrderVisitDto.cs
  24. 6 0
      src/Hotline.Share/Dtos/Order/QueryOrderDto.cs
  25. 8 12
      src/Hotline.Share/Dtos/Snapshot/OrderDto.cs
  26. 5 0
      src/Hotline.Share/Dtos/Snapshot/OrderPublishDto.cs
  27. 101 1
      src/Hotline.Share/Dtos/Snapshot/PointsDto.cs
  28. 1 0
      src/Hotline.Share/Dtos/Snapshot/ThirdTokenDto.cs
  29. 1 1
      src/Hotline.Share/Tools/DataMaskExtensions.cs
  30. 13 0
      src/Hotline.Share/Tools/StringExtensions.cs
  31. 7 0
      src/Hotline/Caching/Interfaces/ISysDicDataCacheManager.cs
  32. 19 0
      src/Hotline/Caching/Services/SysDicDataCacheManager.cs
  33. 4 6
      src/Hotline/KnowledgeBase/KnowledgeDomainService.cs
  34. 14 8
      src/Hotline/Orders/Order.cs
  35. 13 0
      src/Hotline/SeedData/SystemDicDataSeedData.cs
  36. 5 0
      src/Hotline/Settings/SettingConstants.cs
  37. 5 0
      src/Hotline/Settings/SysDicTypeConsts.cs
  38. 1 0
      test/Hotline.Tests/Application/DefaultCallApplicationTest.cs
  39. 6 0
      test/Hotline.Tests/Application/OrderApplicationTest.cs
  40. 15 2
      test/Hotline.Tests/Application/PointsRecordApplicationTest.cs
  41. 10 0
      test/Hotline.Tests/Application/SnapshotApplicationTest.cs

+ 1 - 1
Hotline.sln

@@ -61,7 +61,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hotline.Ai.XingTang", "src\
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hotline.Pdf", "src\Hotline.Pdf\Hotline.Pdf.csproj", "{3AB75B51-A69D-4145-A564-1D9D1695992E}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hotline.Tests", "test\Hotline.Tests\Hotline.Tests.csproj", "{31855124-4EFC-47B9-A4D5-64822DE036E6}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hotline.Tests", "test\Hotline.Tests\Hotline.Tests.csproj", "{31855124-4EFC-47B9-A4D5-64822DE036E6}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+ 102 - 2
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -3112,7 +3112,10 @@ namespace Hotline.Api.Controllers.Bi
 				})
 				.FirstAsync();
             //催办
-            var orderUrge = await _orderUrgeRepository.Queryable().Where(p => p.CreationTime >= StartTime && p.CreationTime <= EndTime).Select(p => p.OrderId).Distinct().CountAsync();
+            var orderUrge = await _orderUrgeRepository.Queryable()
+                .LeftJoin<Order>((p,o)=>p.OrderId == o.Id)
+                .Where((p, o) => p.CreationTime >= StartTime && p.CreationTime <= EndTime)
+                .WhereIF(IdentityType.HasValue, (p, o) => o.IdentityType == IdentityType).Select((p, o) => p.OrderId).Distinct().CountAsync();
             orderData.orderUrge = orderUrge;
 			centerReportStatisticsDto.CenterReportOrder = orderData;
 			#endregion
@@ -3140,6 +3143,7 @@ namespace Hotline.Api.Controllers.Bi
 			  .Where((s, p) => s.DicTypeCode == "SourceChannel" && s.IsShow == true)
 			  .Select((s, p) => new CenterReportOrderSourceChannelDto
 			  {
+                  AllCountNum = sourceChannelCount,
 				  Code = s.DicDataValue,
 				  Name = s.DicDataName,
 				  CountNum = p.CountNum
@@ -6596,5 +6600,101 @@ namespace Hotline.Api.Controllers.Bi
             returnList.Add(SZYSM);
             return returnList;
         }
-    }
+
+		/// <summary>
+		/// 部门退回中心统计
+		/// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		[HttpGet("org_sendback_statistics")]
+		public async Task<List<OrgSendBackAuditListVo>> OrgSendBackAuditStatistics([FromQuery] OrgSendBackAuditListDto dto)
+		{
+			var quer = _orderApplication.OrgSendBackAuditList(dto);
+			var list = await quer.ToListAsync(HttpContext.RequestAborted);
+			list.Add(new OrgSendBackAuditListVo()
+			{
+				OrgName = "合计",
+				Num = list.Sum(m => m.Num),
+			});
+
+			return list;
+		}
+
+		/// <summary>
+		/// 部门退回中心统计
+		/// </summary>
+		/// <returns></returns>
+		[HttpPost("org_sendback_statistics/_export")]
+		public async Task<FileStreamResult> OrgSendBackAuditStatisticsExport([FromBody] ExportExcelDto<OrgSendBackAuditListDto> dto)
+		{
+			var query = _orderApplication.OrgSendBackAuditList(dto.QueryDto);
+			List<OrgSendBackAuditListVo> data;
+
+			data = await query.ToListAsync(HttpContext.RequestAborted);
+
+			data.Add(new OrgSendBackAuditListVo()
+			{
+				OrgName = "合计",
+				Num = data.Sum(m => m.Num),
+			});
+
+			dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<OrgSendBackAuditListVo>(dto.ColumnInfos);
+
+			var dtos = data
+				.Select(stu => _mapper.Map(stu, typeof(OrgSendBackAuditListVo), dynamicClass))
+				.Cast<object>()
+				.ToList();
+
+			var stream = ExcelHelper.CreateStream(dtos);
+
+			return ExcelStreamResult(stream, "部门退回统计");
+		}
+
+		/// <summary>
+		/// 部门退回中心统计明细
+		/// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		[HttpGet("org_sendback_detail")]
+		public async Task<PagedDto<SendBackDto>> OrgSendBackDetail([FromQuery] OrgSendBackAuditListDto dto)
+		{
+			var quer = _orderApplication.OrgSendBackAuditDetail(dto);
+			var (total, items) = await quer.ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+			return new PagedDto<SendBackDto>(total, _mapper.Map<IReadOnlyList<SendBackDto>>(items));
+		}
+
+		/// <summary>
+		/// 部门退回中心统计明细导出
+		/// </summary>
+		/// <returns></returns>
+		[HttpPost("org_sendback_detail/_export")]
+		public async Task<FileStreamResult> OrgSendBackDetailExport([FromBody] ExportExcelDto<OrgSendBackAuditListDto> dto)
+		{
+			var query = _orderApplication.OrgSendBackAuditDetail(dto.QueryDto);
+			List<OrderSendBackAudit> data;
+			if (dto.IsExportAll)
+			{
+				data = await query.ToListAsync(HttpContext.RequestAborted);
+			}
+			else
+			{
+				var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+				data = items;
+			}
+
+			var dataDtos = _mapper.Map<ICollection<SendBackDto>>(data);
+
+			dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<SendBackDto>(dto.ColumnInfos);
+
+			var dtos = dataDtos
+				.Select(stu => _mapper.Map(stu, typeof(SendBackDto), dynamicClass))
+				.Cast<object>()
+				.ToList();
+
+			var stream = ExcelHelper.CreateStream(dtos);
+
+			return ExcelStreamResult(stream, "部门退回统计明细");
+		}
+	}
 }

+ 3 - 3
src/Hotline.Api/Controllers/FwThirdController.cs

@@ -348,7 +348,7 @@ namespace Hotline.Api.Controllers
                 .WhereIF(!string.IsNullOrEmpty(dto.FlowEDate), (op, p) => p.StartTime <= DateTime.Parse(DateTime.Parse(dto.FlowEDate).ToString("yyyy-MM-dd 00:00:00")))// dto.FlowEDate
                 .WhereIF(!string.IsNullOrEmpty(dto.FlowFrom), (op, p) => p.FromName.Contains(dto.FlowFrom))
                 .WhereIF(dto.IdentityType.HasValue, (op, p) => p.IdentityType == dto.IdentityType)
-                .OrderByDescending((op, p) => p.CreationTime)
+                .OrderByDescending((op, p) => op.CreationTime)
                .Select((op, p) => new OrderListDto
                {
                    FlowID = p.Id,
@@ -388,8 +388,8 @@ namespace Hotline.Api.Controllers
             //            });
 
             var (total, items) = await queryNew
-                .OrderByDescending(p => p.PubDate)
-                 .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+                //.OrderByDescending(op => op.PubDate)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
 
             //计算总页数
             int nPageCount = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(total) / dto.PageSize));

+ 185 - 56
src/Hotline.Api/Controllers/OrderController.cs

@@ -1,4 +1,5 @@
-using DotNetCore.CAP;
+using DocumentFormat.OpenXml.Wordprocessing;
+using DotNetCore.CAP;
 using FluentValidation;
 using Hotline.Api.Filter;
 using Hotline.Application.CallCenter;
@@ -1409,12 +1410,15 @@ public class OrderController : BaseController
             Histories = histories,
             IsCanUpdate = isCanUpdate
         };
-        if (_appOptions.Value.IsLuZhou
-            && !_sessionContext.OrgIsCenter
-            && rsp.OrderVisitModel.Order.IsSecret)
+        if (!_sessionContext.OrgIsCenter && rsp.OrderVisitModel.Order.IsSecret)
         {
-            rsp.OrderVisitModel.Order.FromPhone = "****";//rsp.OrderVisitModel.Order.FromPhone?.Replace(rsp.OrderVisitModel.Order.FromPhone.Substring(3, 4), "****");
-            rsp.OrderVisitModel.Order.Contact = "****"; //rsp.OrderVisitModel.Order.Contact?.Replace(rsp.OrderVisitModel.Order.Contact.Substring(3, 4), "****");
+            if (_appOptions.Value.IsZiGong)
+                rsp.OrderVisitModel.Order = rsp.OrderVisitModel.Order.DataMask();
+            if (_appOptions.Value.IsLuZhou)
+            {
+                rsp.OrderVisitModel.Order.FromPhone = "****";//rsp.OrderVisitModel.Order.FromPhone?.Replace(rsp.OrderVisitModel.Order.FromPhone.Substring(3, 4), "****");
+                rsp.OrderVisitModel.Order.Contact = "****"; //rsp.OrderVisitModel.Order.Contact?.Replace(rsp.OrderVisitModel.Order.Contact.Substring(3, 4), "****");
+            }
         }
 
         return rsp;
@@ -2629,7 +2633,7 @@ public class OrderController : BaseController
         }
 
         var (total, items) = await _orderApplication.MayScreenList(dto)
-            .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+       .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
         var data = _mapper.Map<List<OrderVisitDetailDto>>(items);
         var isAdmin = _orderDomainService.IsCheckAdmin();
         data.ForEach(d => d.IsShowOperate = (dto.ScreenType == EOrderScreenType.Org && d.VisitOrgCode == _sessionContext.OrgId)
@@ -2690,7 +2694,7 @@ public class OrderController : BaseController
     public async Task<PagedDto<OrderScreenListDto>> ScreenList([FromQuery] ScreenListDto dto)
     {
         var (total, items) = await _orderApplication.OrderScreenList(dto)
-            .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+    .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
         return new PagedDto<OrderScreenListDto>(total, _mapper.Map<IReadOnlyList<OrderScreenListDto>>(items));
     }
 
@@ -3202,6 +3206,86 @@ public class OrderController : BaseController
         return new PagedDto<SuperviseOrderDto>(total, _mapper.Map<IReadOnlyList<SuperviseOrderDto>>(items));
     }
 
+    /// <summary>
+    /// 督办查询部门经办人手机号
+    /// </summary>
+    /// <param name="orgCode"></param>
+    /// <returns></returns>
+    [HttpGet("supervise/geturgetel/{orgCode}")]
+    public async Task<Kv> GetUrgeTel(string orgCode)
+    {
+        Kv k = new Kv();
+        var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
+        //查询部门所有账号
+        var userlist = await _userRepository.Queryable().Where(x =>
+            x.OrgId == orgCode && !string.IsNullOrEmpty(x.PhoneNo) &&
+            x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id))).ToListAsync();
+        if (userlist != null && userlist.Count > 0)
+        {
+            k.Key = userlist[0].Name;
+            k.Value = userlist[0].PhoneNo;
+        }
+        return k;
+    }
+
+    /// <summary>
+    /// 旅游列表
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("supervise/travel")]
+    public async Task<IReadOnlyList<OrderDto>> QueryTravel([FromQuery] QueryOrderDto dto)
+    {
+        var orders = await _orderApplication.QueryTravel(dto)
+            .ToPageListWithoutTotalAsync(dto, HttpContext.RequestAborted);
+        var list = _mapper.Map<IReadOnlyList<OrderDto>>(orders);
+        if (_appOptions.Value.IsLuZhou && !_sessionContext.OrgIsCenter)
+            list = list.Select(p => p.DataMask()).ToList();
+        return list;
+    }
+
+    /// <summary>
+    /// 旅游列表查询总数
+    /// </summary>
+    [HttpGet("supervise/travel/count")]
+    public async Task<int> QueryTravelCount([FromQuery] QueryOrderDto dto)
+    {
+        var query = _orderApplication.QueryTravel(dto);
+        return await query.CountAsync(HttpContext.RequestAborted);
+    }
+
+    [HttpPost("supervise/travel/export")]
+    public async Task<FileStreamResult> ExportTravel([FromBody] ExportExcelDto<QueryOrderDto> dto)
+    {
+        var query = _orderApplication.QueryTravel(dto.QueryDto);
+        List<Order> orders;
+        if (dto.IsExportAll)
+        {
+            orders = await query.ToListAsync(HttpContext.RequestAborted);
+        }
+        else
+        {
+            var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+            orders = items;
+        }
+
+        var orderDtos = _mapper.Map<ICollection<OrderDto>>(orders);
+
+        if (_appOptions.Value.IsLuZhou)
+            orderDtos = orderDtos.Select(p => p.DataMask()).ToList();
+
+        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<OrderDto>(dto.ColumnInfos);
+
+        var dtos = orderDtos
+            .Select(stu => _mapper.Map(stu, typeof(OrderDto), dynamicClass))
+            .Cast<object>()
+            .ToList();
+
+        var stream = ExcelHelper.CreateStream(dtos);
+
+        return ExcelStreamResult(stream, "旅游数据");
+    }
+
     /// <summary>
     /// 申请督办
     /// </summary>
@@ -3237,27 +3321,64 @@ public class OrderController : BaseController
                 //发送短信
                 try
                 {
-                    var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
-                    //查询部门所有账号
-                    var userlist = await _userRepository.Queryable().Where(x =>
-                        x.OrgId == model.OrgId && !string.IsNullOrEmpty(x.PhoneNo) &&
-                        x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id))).ToListAsync();
-                    //发送短信
-                    foreach (var user in userlist)
+                    if (string.IsNullOrEmpty(dto.PhoneNo))
                     {
-                        var messageDto = new Share.Dtos.Push.MessageDto
+                        #region 普通督办短信内容
+                        var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
+                        //查询部门所有账号
+                        var userlist = await _userRepository.Queryable().Where(x =>
+                            x.OrgId == model.OrgId && !string.IsNullOrEmpty(x.PhoneNo) &&
+                            x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id))).ToListAsync();
+                        //发送短信
+                        foreach (var user in userlist)
                         {
-                            PushBusiness = EPushBusiness.OrderSupervise,
-                            ExternalId = order.Id,
-                            OrderId = order.Id,
-                            PushPlatform = EPushPlatform.Sms,
-                            Remark = order.Title,
-                            Name = user.Name,
-                            TemplateCode = "1003",
-                            Params = new List<string>() { order.No },
-                            TelNumber = user.PhoneNo,
-                        };
-                        await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted);
+                            var messageDto = new Share.Dtos.Push.MessageDto
+                            {
+                                PushBusiness = EPushBusiness.OrderSupervise,
+                                ExternalId = order.Id,
+                                OrderId = order.Id,
+                                PushPlatform = EPushPlatform.Sms,
+                                Remark = order.Title,
+                                Name = user.Name,
+                                TemplateCode = "1003",
+                                Params = new List<string>() { order.No },
+                                TelNumber = user.PhoneNo,
+                            };
+                            await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted);
+                        }
+                        #endregion
+                    }
+                    else
+                    {
+                        #region 旅游督办短信内容
+
+                        var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
+                        //查询部门所有账号
+                        var userlist = await _userRepository.Queryable().Where(x =>
+                            x.OrgId == model.OrgId && x.PhoneNo == dto.PhoneNo &&
+                            x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id))).ToListAsync();
+
+                        var Contact = !string.IsNullOrEmpty(order.FromPhone) ? order.FromPhone : order.Contact;
+
+                        //发送短信
+                        if (userlist != null && userlist.Count > 0)
+                        {
+                            var messageDto = new Share.Dtos.Push.MessageDto
+                            {
+                                PushBusiness = EPushBusiness.OrderSupervise,
+                                ExternalId = order.Id,
+                                OrderId = order.Id,
+                                PushPlatform = EPushPlatform.Sms,
+                                Remark = order.Title,
+                                Name = userlist[0].Name,
+                                TemplateCode = "1022",
+                                Params = new List<string>() { dto.ApplyContent, order.No, Contact, order.Content },
+                                TelNumber = userlist[0].PhoneNo,
+                            };
+                            await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted);
+                        }
+
+                        #endregion
                     }
                 }
                 catch
@@ -4273,11 +4394,14 @@ public class OrderController : BaseController
         {
             await _orderSnapshotRepository.Queryable()
                 .Where(m => m.Id == order.Id)
-                .Select(m => new { m.IndustryId, m.IndustryName })
+                .Select(m => new { m.IndustryId, m.IndustryName, m.IndustryCase })
                 .FirstAsync(HttpContext.RequestAborted)
                 .Then(async snapshot =>
                 {
-                    dto.IndustryName = snapshot.IndustryName;
+                    if (snapshot.IndustryCase.IsNullOrEmpty())
+                        dto.IndustryName = snapshot.IndustryName;
+                    else
+                        dto.IndustryName = snapshot.IndustryName + " " + snapshot.IndustryCase;
                     dto.IndustryId = snapshot.IndustryId;
                 });
         }
@@ -5686,35 +5810,39 @@ public class OrderController : BaseController
         {
             if (order.FileJson != null)
             {
-				var ids = order.FileJson.Select(x => x.Id).ToList();
-				allFiles = await _fileRepository.GetFilesAsync(ids, cancellationToken: HttpContext.RequestAborted);
-				allFiles.ForEach(x => x.GetStepName("工单受理"));
-			}
-		}
-		foreach (var step in steps)
-		{
-			if (step.FileJson != null && step.FileJson.Any())
-			{
-				var ids = step.FileJson.Select(x => x.Id).ToList();
-				var stepFiles = await _fileRepository.GetPermissionFilesAsync(ids, HttpContext.RequestAborted);
-				stepFiles.ForEach(x => x.GetStepName(step.Name));
-				allFiles.AddRange(stepFiles);
-			}
-		}
-		return allFiles;
-	}
+                var ids = order.FileJson.Select(x => x.Id).ToList();
+                allFiles = await _fileRepository.GetFilesAsync(ids, cancellationToken: HttpContext.RequestAborted);
+                allFiles.ForEach(x => x.GetStepName("工单受理"));
+            }
+        }
+        foreach (var step in steps)
+        {
+            if (step.FileJson != null && step.FileJson.Any())
+            {
+                var ids = step.FileJson.Select(x => x.Id).ToList();
+                var stepFiles = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted);
+                stepFiles.ForEach(x => x.GetStepName(step.Name));
+                allFiles.AddRange(stepFiles);
+            }
+        }
+        return allFiles;
+    }
 
-	/// <summary>
-	/// 获取流程信息
-	/// </summary>
-	/// <param name="workflowId"></param>
-	/// <returns></returns>
-	[HttpGet("all_file/workflow/{workflowId}")]
-	public async Task<WorkflowDto> GetOrderWorkflowAsync(string workflowId)
-	{
-		var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withSteps: true,
-			cancellationToken: HttpContext.RequestAborted);
+    /// <summary>
+    /// 获取流程信息
+    /// </summary>
+    /// <param name="workflowId"></param>
+    /// <returns></returns>
+    [HttpGet("all_file/workflow/{workflowId}")]
+    public async Task<WorkflowDto> GetOrderWorkflowAsync(string workflowId)
+    {
+        var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withSteps: true,
+            cancellationToken: HttpContext.RequestAborted);
         var steps = _mapper.Map<List<WorkflowTraceDto>>(workflow.Steps);
+        if (!_sessionContext.OrgIsCenter)
+        {
+            steps = steps.Where(x => x.HandlerOrgId != null && x.HandlerOrgId.StartsWith(_sessionContext.RequiredOrgId)).ToList();
+        }
         var workflowDto = _mapper.Map<WorkflowDto>(workflow);
         workflowDto.Traces = steps;
         foreach (var item in workflowDto.Traces)
@@ -5724,6 +5852,7 @@ public class OrderController : BaseController
                 var ids = item.FileJson.Select(x => x.Id).ToList();
                 item.Files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted);
             }
+            item.Name = item.Name + "(" + item.HandlerOrgName + ")";
         }
         return workflowDto;
     }

+ 2 - 2
src/Hotline.Api/Controllers/Snapshot/PointsController.cs

@@ -15,9 +15,9 @@ namespace Hotline.Api.Controllers.Snapshot;
 [Description("积分管理")]
 public class PointsController : BaseController
 {
-    private readonly IPointsRecordApplication _pointsRecordApplication;
+    private readonly ISnapshotPointsApplication _pointsRecordApplication;
 
-    public PointsController(IPointsRecordApplication pointsRecordApplication)
+    public PointsController(ISnapshotPointsApplication pointsRecordApplication)
     {
         _pointsRecordApplication = pointsRecordApplication;
     }

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

@@ -103,12 +103,13 @@ public class SnapshotController : BaseController
         order.AcceptTypeCode = industry.AcceptTypeCode;
         order.AcceptType = industry.AcceptType;
         order.FromGender = EGender.Unknown;
-        order.Title = dto.GetTitle(industry.IndustryType, industry.AcceptType);
-        order.Content = dto.GetContent(industry.IndustryType);
+        order.Title = dto.GetTitle(industry.IndustryType, industry.TitleSuffix);
+        order.Content = dto.GetContent(industry.IndustryType, _systemDicDataCacheManager.JobType);
         order.FromPhone = _sessionContext.Phone;
         order.Contact = _sessionContext.Phone;
         order.SourceChannel = ssp.DicDataName;
         order.SourceChannelCode = ssp.DicDataValue;
+        order.FullAddress = dto.Address + dto.FullAddress;
         order.InitId();
         await _orderDomainService.AddAsync(order);
         if (dto.Files.NotNullOrEmpty())
@@ -359,6 +360,33 @@ public class SnapshotController : BaseController
             await _snapshotApplication.PostOrderGuiderSystemAsync(orderId, HttpContext.RequestAborted);
         }
     }
+    #region 积分
+    /// <summary>
+    /// 积分榜
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("points/rank")]
+    public async Task<PointsRankOutDto> GetPointsRankAsync()
+        => await _snapshotApplication.GetPointsRankAsync();
+
+    /// <summary>
+    /// 积分详情
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("points")]
+    public async Task<IList<PointItemsOutDto>> GetPointItemsAsync([FromQuery] PointItemsInDto dto)
+        => await _snapshotApplication.GetPointItemsAsync(dto, HttpContext.RequestAborted);
+
+    /// <summary>
+    /// 积分总计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("points/total")]
+    public async Task<int> GetPointsTotalAsync([FromQuery] PointItemsInDto dto)
+        => await _snapshotApplication.GetPointsTotalAsync(dto, HttpContext.RequestAborted);
+    #endregion
 
     #region 第三方系统
     /// <summary>

+ 7 - 5
src/Hotline.Api/Controllers/TelRestController.cs

@@ -123,14 +123,15 @@ namespace Hotline.Api.Controllers
         public async Task<string> AddTelRest([FromBody] TelRestApplyAddDto dto)
         {
             if (string.IsNullOrEmpty(dto.TelNo))
-                return "分机号不能为空!";
-            if (dto.Reason == null)
-                return "小休原因不能为空!";
+                throw new  UserFriendlyException("分机号不能为空!", "分机号不能为空!");
+                
+            if (dto.Reason == null) 
+                throw new UserFriendlyException("小休原因不能为空!", "小休原因不能为空!");
 
             var data = await _telRestApplyRepository.GetAsync(p => p.TelNo == dto.TelNo && p.CreatorId == _sessionContext.RequiredUserId &&
             p.AuditStatus == ETelRestAuditStatus.NoAudit, HttpContext.RequestAborted);
             if (data != null)
-                return "小休申请审批中,暂时无法操作!";
+                throw new UserFriendlyException("小休申请审批中,暂时无法操作!", "小休申请审批中,暂时无法操作!");
 
             TelRestApply telRestApply = new()
             {
@@ -195,7 +196,8 @@ namespace Hotline.Api.Controllers
         public async Task<string> TelRestApplyAudit([FromBody] TelRestApplyAuditDto dto)
         {
             if (dto.IsPass != true && string.IsNullOrEmpty(dto.AuditOpinion))
-                return "审批原因不能为空!";
+                throw new UserFriendlyException("审批原因不能为空!", "审批原因不能为空!");
+
             foreach (var item in dto.Ids)
             {
                 var data = await _telRestApplyRepository.GetAsync(item, HttpContext.RequestAborted);

+ 40 - 22
src/Hotline.Application/CallCenter/DefaultCallApplication.cs

@@ -201,26 +201,38 @@ public abstract class DefaultCallApplication : ICallApplication
             dto.GroupId, _sessionContext.StaffNo, null);
         await _workRepository.AddAsync(work, cancellationToken);
 
-        //如果有未结束的小休,先结束
-        var telRest = await _telRestRepository.GetAsync(x => x.TelNo == work.TelNo && !x.EndTime.HasValue, cancellationToken);
-        if (telRest != null)
+        try
         {
-            telRest.EndRest();
-            await _telRestRepository.UpdateAsync(telRest, cancellationToken);
-        }
+            //工单保存特殊身份验证
+            var signInCheckRest = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SignInCheckRest).SettingValue[0]);
+            if (signInCheckRest)
+            {
+                //如果有未结束的小休,先结束
+                var telRest = await _telRestRepository.GetAsync(x => x.TelNo == work.TelNo && !x.EndTime.HasValue, cancellationToken);
+                if (telRest != null)
+                {
+                    telRest.EndRest();
+                    await _telRestRepository.UpdateAsync(telRest, cancellationToken);
+                }
+
+                //如果有未结束的话机动作先结束话机动作
+                var telAction = await _telActionRecordRepository.GetAsync(x => x.TelNo == work.TelNo && x.ActionType == EActionType.TelRest && !x.EndTime.HasValue, cancellationToken);
+                if (telAction != null)
+                {
+                    telAction.EndAction();
+                    await _telActionRecordRepository.UpdateAsync(telAction);
+                }
+            }
 
-        //如果有未结束的话机动作先结束话机动作
-        var telAction = await _telActionRecordRepository.GetAsync(x => x.TelNo == work.TelNo && x.ActionType == EActionType.TelRest && !x.EndTime.HasValue, cancellationToken);
-        if (telAction != null)
-        {
-            telAction.EndAction();
-            await _telActionRecordRepository.UpdateAsync(telAction);
-        }
+            //记录签入日志
+            var actionRecord = new TelActionRecord(work.UserId, work.UserName, work.TelNo, work.QueueId, EActionType.SignIn);
 
-        //记录签入日志
-        var actionRecord = new TelActionRecord(work.UserId, work.UserName, work.TelNo, work.QueueId, EActionType.SignIn);
+            await _telActionRecordRepository.AddAsync(actionRecord, cancellationToken);
+        }
+        catch (Exception)
+        {
 
-        await _telActionRecordRepository.AddAsync(actionRecord, cancellationToken);
+        }
 
         return new TrOnDutyResponseDto
         {
@@ -251,11 +263,17 @@ public abstract class DefaultCallApplication : ICallApplication
         await _cacheWork.RemoveAsync(work.GetKey(KeyMode.UserId), cancellationToken);
         await _cacheWork.RemoveAsync(work.GetKey(KeyMode.TelNo), cancellationToken);
 
-        var list = await _telActionRecordRepository.Queryable().Where(x => x.TelNo == work.TelNo && !x.EndTime.HasValue).ToListAsync();
-        foreach (var item in list)
+        try
+        {
+            var list = await _telActionRecordRepository.Queryable().Where(x => x.TelNo == work.TelNo && !x.EndTime.HasValue).ToListAsync();
+            foreach (var item in list)
+            {
+                item.EndAction();
+                await _telActionRecordRepository.UpdateAsync(item);
+            }
+        }
+        catch (Exception)
         {
-            item.EndAction();
-            await _telActionRecordRepository.UpdateAsync(item);
         }
     }
 
@@ -339,7 +357,7 @@ public abstract class DefaultCallApplication : ICallApplication
         query = query.WhereIF(dto.Type == 3, (d, o, v) => d.AnsweredTime == null);
         query = query.WhereIF(dto.Type == 1, (d, o, v) => d.Direction == ECallDirection.In && d.AnsweredTime != null);
         query = query.WhereIF(dto.Type == 2, (d, o, v) => d.Direction == ECallDirection.Out && d.AnsweredTime != null);
-        query = query.WhereIF(dto.Type != 3 && !string.IsNullOrEmpty(dto.StaffNo), p => p.StaffNo == dto.StaffNo);
+        query = query.WhereIF(dto.Type != 3 && !string.IsNullOrEmpty(dto.StaffNo), d => d.StaffNo == dto.StaffNo);
 
         if (dto.Type == 2)
         {
@@ -376,7 +394,7 @@ public abstract class DefaultCallApplication : ICallApplication
                         .Max(m => m.TelNo)
                     ),
             }, true)
-                .WhereIF(!string.IsNullOrEmpty(dto.StaffNo), p => p.StaffNo == dto.StaffNo);
+                .WhereIF(!string.IsNullOrEmpty(dto.StaffNo), d => d.StaffNo == dto.StaffNo);
         }
         return query.Select((d, o, v) => new CallNativeDto
         {

+ 18 - 2
src/Hotline.Application/OrderApp/IOrderApplication.cs

@@ -115,6 +115,7 @@ namespace Hotline.Application.OrderApp
         #region 工单办理
 
         ISugarQueryable<Order> QueryOrders(QueryOrderDto dto);
+        ISugarQueryable<Order> QueryTravel(QueryOrderDto dto);
 
         /// <summary>
         /// 保存工单办理时页面填写的数据
@@ -414,7 +415,7 @@ namespace Hotline.Application.OrderApp
         /// 将工单从网格员节点办理至工单标记节点
         /// </summary>
         /// <returns></returns>
-        Task HandleFromWanggeyuanToMaskAsync(string orderId,string opinion, CancellationToken cancellation);
+        Task HandleFromWanggeyuanToMaskAsync(string orderId, string opinion, CancellationToken cancellation);
 
         /// <summary>
         /// 查询退回操作目标节点的指派对象
@@ -466,5 +467,20 @@ namespace Hotline.Application.OrderApp
         /// 依据当前待办节点随意获取一个合法办理人
         /// </summary>
         Task<User> GetHandlerRandomAsync(WorkflowStep step, CancellationToken cancellationToken);
-    }
+
+        /// <summary>
+        /// 部门退回中心统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<OrgSendBackAuditListVo> OrgSendBackAuditList(OrgSendBackAuditListDto dto);
+
+		/// <summary>
+		/// 部门退回中心统计明细
+		/// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		ISugarQueryable<OrderSendBackAudit> OrgSendBackAuditDetail(OrgSendBackAuditListDto dto);
+
+	}
 }

+ 152 - 143
src/Hotline.Application/OrderApp/OrderAnalysisApplication.cs

@@ -11,147 +11,156 @@ using XF.Utility.SequentialId;
 
 namespace Hotline.Application.OrderApp
 {
-	public class OrderAnalysisApplication : IOrderAnalysisApplication, IScopeDependency
-	{
-		private readonly IRepository<OrderAnalysis> _orderAnalysisRepository;
-		private readonly IMapper _mapper;
-		private readonly IOrderRepository _orderRepository;
-		private readonly IRepository<SystemArea> _systemAreaRepository;
-
-		public OrderAnalysisApplication(
-			IMapper mapper,
-			IOrderRepository orderRepository,
-			IRepository<SystemArea> systemAreaRepository,
-			IRepository<OrderAnalysis> orderAnalysisRepository
-			) 
-		{
-			_mapper = mapper;
-			_orderRepository = orderRepository;
-			_orderAnalysisRepository = orderAnalysisRepository;
-			_systemAreaRepository = systemAreaRepository;
-		}
-
-		/// <summary>
-		/// 新增
-		/// </summary>
-		/// <returns></returns>
-		public async Task AddAsync(AddOrderAnalysisDto dto, CancellationToken cancellationToken) {
-			var analysisAny =  await _orderAnalysisRepository.Queryable().AnyAsync(x => x.AnalysisName == dto.AnalysisName, cancellationToken);
-			if (analysisAny)
-				throw UserFriendlyException.SameMessage("当前报告名称已经存在,请修改报告名称!");
-
-			var analysisId = SequentialStringGenerator.Create();
-			var generatedTime = DateTime.Now;
-			var analysiss = new List<OrderAnalysis>();
-			foreach (var item in dto.AnalysisList)
-			{
-				var analysis = _mapper.Map<OrderAnalysis>(item);
-				analysis.AnalysisId = analysisId;
-				analysis.AnalysisName =  dto.AnalysisName;
-				analysis.Remark = dto.Remark;
-				analysis.GeneratedTime = generatedTime;
-				analysiss.Add(analysis);
-			}
-			await _orderAnalysisRepository.AddRangeAsync(analysiss, cancellationToken);
-		}
-		
-		/// <summary>
-		/// 修改
-		/// </summary>
-		/// <returns></returns>
-		public async Task UpdateAsync(UpdateOrderAnalysisDto dto, CancellationToken cancellationToken) 
-		{
-			var analysisIdAny = await _orderAnalysisRepository.Queryable().AnyAsync(x =>  x.AnalysisId == dto.AnalysisId, cancellationToken);
-			if (!analysisIdAny)
-				throw UserFriendlyException.SameMessage("当前报告不存在,请查询报告是否已变更!");
-			var analysisNameAny = await _orderAnalysisRepository.Queryable().AnyAsync(x => x.AnalysisName == dto.AnalysisName && x.AnalysisId != dto.AnalysisId, cancellationToken);
-			if (analysisNameAny)
-				throw UserFriendlyException.SameMessage("当前报告名称已经存在,请修改报告名称!");
-			await _orderAnalysisRepository.Updateable().SetColumns(x => new OrderAnalysis { AnalysisName = dto.AnalysisName, Remark = dto.Remark })
-				.Where(x => x.AnalysisId == dto.AnalysisId).ExecuteCommandAsync(cancellationToken);
-		}
-
-		/// <summary>
-		/// 删除
-		/// </summary>
-		/// <returns></returns>
-		public async Task DeleteAsync(DeleteOrderAnalysisDto dto, CancellationToken cancellationToken) {
-
-			await _orderAnalysisRepository.Removeable().In(x => x.AnalysisId, dto.AnalysisIds).ExecuteCommandAsync(cancellationToken);
-		}
-
-
-		/// <summary>
-		/// 查询列表
-		/// </summary>
-		/// <returns></returns>
-		public ISugarQueryable<OrderAnalysisDto> ListQuery(OrderAnalysisListDto dto, CancellationToken cancellationToken) {
-			if (dto.GeneratedEndTime.HasValue)
-				dto.GeneratedEndTime = dto.GeneratedEndTime.Value.AddDays(1).AddSeconds(-1);
-			var query = _orderAnalysisRepository.Queryable()
-				.WhereIF(!string.IsNullOrEmpty(dto.AnalysisName), x => x.AnalysisName == dto.AnalysisName)
-				.WhereIF(dto.GeneratedStartTime.HasValue && dto.GeneratedEndTime.HasValue, x => x.GeneratedTime >= dto.GeneratedStartTime && x.GeneratedTime <= dto.GeneratedEndTime)
-				.GroupBy(x => new { x.AnalysisId, x.AnalysisName, x.Remark, x.GeneratedTime })
-				.Select(x => new OrderAnalysisDto { AnalysisId = x.AnalysisId, AnalysisName = x.AnalysisName, Remark = x.Remark, GeneratedTime = x.GeneratedTime })
-				.OrderByDescending(x=> x.GeneratedTime);
-			return query;
-		}
-
-		/// <summary>
-		///  查看预警事件
-		/// </summary>
-		/// <returns></returns>
-		public ISugarQueryable<Order> DetailQuery(OrderAnalysisDetailDto dto, CancellationToken cancellationToken) {
-			var query = _orderAnalysisRepository.Queryable()
-				.LeftJoin<Order>((a, o) => a.AcceptTypeCode == o.AcceptTypeCode && a.HotspotId == o.HotspotId && o.AreaCode.StartsWith(a.AreaCode))
-				.Where((a, o) => a.AnalysisId == dto.AnalysisId)
-				.Select((a, o) => o);
-			return query;
-		}
-
-		/// <summary>
-		/// 生成报告
-		/// </summary>
-		/// <returns></returns>
-		public async Task<object> ReportQuery(OrderAnalysisDetailDto dto, CancellationToken cancellationToken) {
-
-			var analysis = await _orderAnalysisRepository.Queryable()
-				.Where(x => x.AnalysisId == dto.AnalysisId)
-				.GroupBy(x => new { x.AnalysisId, x.AnalysisName, x.GeneratedTime, x.Remark })
-				.Select(x => new { x.AnalysisId, x.AnalysisName, x.GeneratedTime, x.Remark }).FirstAsync(cancellationToken);
-
-			var orders = await _orderAnalysisRepository.Queryable()
-				.LeftJoin<Order>((a, o) => a.AcceptTypeCode == o.AcceptTypeCode && a.HotspotId == o.HotspotId && o.AreaCode.StartsWith(a.AreaCode))
-				.Where((a, o) => a.AnalysisId == dto.AnalysisId)
-				.Select((a, o) => o).ToListAsync(cancellationToken) ;
-			var introductionData = orders.GroupBy(x=>x.SourceChannel)
-				.Select(x=>new { SourceChannel = x.Key, Num  = x.Count(), Rate = Math.Round((x.Count() /(double)orders.Count) * 100, 2) })
-				.OrderByDescending(x=>x.Num);
-			var introduction = new { total = orders.Count, data = introductionData };
-			var orderAreas = orders.GroupBy(x=>x.AreaCode.Substring(0,6))
-				.Select(x=> new { AreaCode =x.Key, Num = x.Count(), Rate = Math.Round((x.Count() / (double)orders.Count) * 100, 2) })
-				.OrderByDescending(x => x.Num);
-			var areaList = await _systemAreaRepository.Queryable().Where(x=>x.Id.Length == 6).ToListAsync(cancellationToken);
-			var areaData = (from t1 in orderAreas
-							join t2 in areaList on t1.AreaCode equals t2.Id into t1_t2
-				from item in t1_t2.DefaultIfEmpty()
-				select new
-				{
-					AreaCode = t1.AreaCode,
-					Num = t1.Num,
-					Rate = t1.Rate,
-					AreaName = t1_t2.Select(x => x.AreaName).FirstOrDefault(),
-				}).OrderByDescending(x=>x.Num).ToList();
-			var areaNames = areaData.Select(x=>x.AreaName).ToList();
-
-			var area = new { AreaNames = areaNames, data = areaData };
-
-			var handle = new { HandleFiled = orders.Count(x => x.Status >= EOrderStatus.Filed), Handle = orders.Count(x => x.Status < Share.Enums.Order.EOrderStatus.Filed) };
-
-			var first = _mapper.Map<List<OrderDto>>(orders.OrderByDescending(x=>x.CreationTime).Take(2).ToList());
-			return new { Analysis = analysis, Introduction = introduction, Area = area, Handle = handle, First = first };
-		}
-
-
-	}
+    public class OrderAnalysisApplication : IOrderAnalysisApplication, IScopeDependency
+    {
+        private readonly IRepository<OrderAnalysis> _orderAnalysisRepository;
+        private readonly IMapper _mapper;
+        private readonly IOrderRepository _orderRepository;
+        private readonly IRepository<SystemArea> _systemAreaRepository;
+
+        public OrderAnalysisApplication(
+            IMapper mapper,
+            IOrderRepository orderRepository,
+            IRepository<SystemArea> systemAreaRepository,
+            IRepository<OrderAnalysis> orderAnalysisRepository
+            )
+        {
+            _mapper = mapper;
+            _orderRepository = orderRepository;
+            _orderAnalysisRepository = orderAnalysisRepository;
+            _systemAreaRepository = systemAreaRepository;
+        }
+
+        /// <summary>
+        /// 新增
+        /// </summary>
+        /// <returns></returns>
+        public async Task AddAsync(AddOrderAnalysisDto dto, CancellationToken cancellationToken)
+        {
+            var analysisAny = await _orderAnalysisRepository.Queryable().AnyAsync(x => x.AnalysisName == dto.AnalysisName, cancellationToken);
+            if (analysisAny)
+                throw UserFriendlyException.SameMessage("当前报告名称已经存在,请修改报告名称!");
+
+            var analysisId = SequentialStringGenerator.Create();
+            var generatedTime = DateTime.Now;
+            var analysiss = new List<OrderAnalysis>();
+            foreach (var item in dto.AnalysisList)
+            {
+                var analysis = _mapper.Map<OrderAnalysis>(item);
+                analysis.AnalysisId = analysisId;
+                analysis.AnalysisName = dto.AnalysisName;
+                analysis.Remark = dto.Remark;
+                analysis.GeneratedTime = generatedTime;
+                analysis.StartTime = dto.StartTime;
+                analysis.EndTime = dto.EndTime;
+                analysiss.Add(analysis);
+            }
+            await _orderAnalysisRepository.AddRangeAsync(analysiss, cancellationToken);
+        }
+
+        /// <summary>
+        /// 修改
+        /// </summary>
+        /// <returns></returns>
+        public async Task UpdateAsync(UpdateOrderAnalysisDto dto, CancellationToken cancellationToken)
+        {
+            var analysisIdAny = await _orderAnalysisRepository.Queryable().AnyAsync(x => x.AnalysisId == dto.AnalysisId, cancellationToken);
+            if (!analysisIdAny)
+                throw UserFriendlyException.SameMessage("当前报告不存在,请查询报告是否已变更!");
+            var analysisNameAny = await _orderAnalysisRepository.Queryable().AnyAsync(x => x.AnalysisName == dto.AnalysisName && x.AnalysisId != dto.AnalysisId, cancellationToken);
+            if (analysisNameAny)
+                throw UserFriendlyException.SameMessage("当前报告名称已经存在,请修改报告名称!");
+            await _orderAnalysisRepository.Updateable().SetColumns(x => new OrderAnalysis { AnalysisName = dto.AnalysisName, Remark = dto.Remark })
+                .Where(x => x.AnalysisId == dto.AnalysisId).ExecuteCommandAsync(cancellationToken);
+        }
+
+        /// <summary>
+        /// 删除
+        /// </summary>
+        /// <returns></returns>
+        public async Task DeleteAsync(DeleteOrderAnalysisDto dto, CancellationToken cancellationToken)
+        {
+
+            await _orderAnalysisRepository.Removeable().In(x => x.AnalysisId, dto.AnalysisIds).ExecuteCommandAsync(cancellationToken);
+        }
+
+
+        /// <summary>
+        /// 查询列表
+        /// </summary>
+        /// <returns></returns>
+        public ISugarQueryable<OrderAnalysisDto> ListQuery(OrderAnalysisListDto dto, CancellationToken cancellationToken)
+        {
+            if (dto.GeneratedEndTime.HasValue)
+                dto.GeneratedEndTime = dto.GeneratedEndTime.Value.AddDays(1).AddSeconds(-1);
+            var query = _orderAnalysisRepository.Queryable()
+                .WhereIF(!string.IsNullOrEmpty(dto.AnalysisName), x => x.AnalysisName == dto.AnalysisName)
+                .WhereIF(dto.GeneratedStartTime.HasValue && dto.GeneratedEndTime.HasValue, x => x.GeneratedTime >= dto.GeneratedStartTime && x.GeneratedTime <= dto.GeneratedEndTime)
+                .GroupBy(x => new { x.AnalysisId, x.AnalysisName, x.Remark, x.GeneratedTime })
+                .Select(x => new OrderAnalysisDto { AnalysisId = x.AnalysisId, AnalysisName = x.AnalysisName, Remark = x.Remark, GeneratedTime = x.GeneratedTime })
+                .OrderByDescending(x => x.GeneratedTime);
+            return query;
+        }
+
+        /// <summary>
+        ///  查看预警事件
+        /// </summary>
+        /// <returns></returns>
+        public ISugarQueryable<Order> DetailQuery(OrderAnalysisDetailDto dto, CancellationToken cancellationToken)
+        {
+            var query = _orderAnalysisRepository.Queryable()
+                .LeftJoin<Order>((a, o) => a.AcceptTypeCode == o.AcceptTypeCode && a.HotspotId == o.HotspotId && o.AreaCode.StartsWith(a.AreaCode))
+                .Where((a, o) => a.AnalysisId == dto.AnalysisId)
+                .Where((a, o) => o.CreationTime >= a.StartTime && o.CreationTime <= a.EndTime)
+                .Select((a, o) => o);
+            return query;
+        }
+
+        /// <summary>
+        /// 生成报告
+        /// </summary>
+        /// <returns></returns>
+        public async Task<object> ReportQuery(OrderAnalysisDetailDto dto, CancellationToken cancellationToken)
+        {
+
+            var analysis = await _orderAnalysisRepository.Queryable()
+                .Where(x => x.AnalysisId == dto.AnalysisId)
+                .GroupBy(x => new { x.AnalysisId, x.AnalysisName, x.GeneratedTime, x.Remark })
+                .Select(x => new { x.AnalysisId, x.AnalysisName, x.GeneratedTime, x.Remark }).FirstAsync(cancellationToken);
+
+            var orders = await _orderAnalysisRepository.Queryable()
+                .LeftJoin<Order>((a, o) => a.AcceptTypeCode == o.AcceptTypeCode && a.HotspotId == o.HotspotId && o.AreaCode.StartsWith(a.AreaCode))
+                .Where((a, o) => a.AnalysisId == dto.AnalysisId)
+                .Where((a, o) => o.CreationTime >=)
+                .Select((a, o) => o).ToListAsync(cancellationToken);
+            var introductionData = orders.GroupBy(x => x.SourceChannel)
+                .Select(x => new { SourceChannel = x.Key, Num = x.Count(), Rate = Math.Round((x.Count() / (double)orders.Count) * 100, 2) })
+                .OrderByDescending(x => x.Num);
+            var introduction = new { total = orders.Count, data = introductionData };
+            var orderAreas = orders.GroupBy(x => x.AreaCode.Substring(0, 6))
+                .Select(x => new { AreaCode = x.Key, Num = x.Count(), Rate = Math.Round((x.Count() / (double)orders.Count) * 100, 2) })
+                .OrderByDescending(x => x.Num);
+            var areaList = await _systemAreaRepository.Queryable().Where(x => x.Id.Length == 6).ToListAsync(cancellationToken);
+            var areaData = (from t1 in orderAreas
+                            join t2 in areaList on t1.AreaCode equals t2.Id into t1_t2
+                            from item in t1_t2.DefaultIfEmpty()
+                            select new
+                            {
+                                AreaCode = t1.AreaCode,
+                                Num = t1.Num,
+                                Rate = t1.Rate,
+                                AreaName = t1_t2.Select(x => x.AreaName).FirstOrDefault(),
+                            }).OrderByDescending(x => x.Num).ToList();
+            var areaNames = areaData.Select(x => x.AreaName).ToList();
+
+            var area = new { AreaNames = areaNames, data = areaData };
+
+            var handle = new { HandleFiled = orders.Count(x => x.Status >= EOrderStatus.Filed), Handle = orders.Count(x => x.Status < Share.Enums.Order.EOrderStatus.Filed) };
+
+            var first = _mapper.Map<List<OrderDto>>(orders.OrderByDescending(x => x.CreationTime).Take(2).ToList());
+            return new { Analysis = analysis, Introduction = introduction, Area = area, Handle = handle, First = first };
+        }
+
+
+    }
 }

+ 170 - 0
src/Hotline.Application/OrderApp/OrderApplication.cs

@@ -50,6 +50,7 @@ using MapsterMapper;
 using MediatR;
 using Microsoft.Extensions.Options;
 using PanGu;
+using Quartz.Simpl;
 using SqlSugar;
 using XF.Domain.Authentications;
 using XF.Domain.Dependency;
@@ -1762,6 +1763,136 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         return query;
     }
 
+    public ISugarQueryable<Order> QueryTravel(QueryOrderDto dto)
+    {
+        var query = _orderRepository.Queryable(canView: false);
+        query = query.Includes(d => d.OrderScreens).Includes(d => d.OrderTags);
+
+        query = query
+                .Where(d => d.FocusOnEvents.Contains("7"))
+                .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!)) //标题
+                .WhereIF(!string.IsNullOrEmpty(dto.ProvinceNo), d => d.ProvinceNo.Contains(dto.ProvinceNo)) //省本地编号
+                .WhereIF(!string.IsNullOrEmpty(dto.ReceiveProvinceNo), d => d.ReceiveProvinceNo.Contains(dto.ReceiveProvinceNo)) //省编号
+                .WhereIF(dto.IsSecret.HasValue, d => d.IsSecret == dto.IsSecret.Value)
+                .WhereIF(dto.IsReTransact.HasValue && dto.IsReTransact.Value, d => d.ReTransactNum > 0)
+                .WhereIF(dto.IsReTransact.HasValue && dto.IsReTransact.Value == false, d => d.ReTransactNum == null || d.ReTransactNum == 0)
+                .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No)) //工单编码
+                .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.AcceptTypeCode == dto.AcceptType) //受理类型
+                                                                                                         //.WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptTypeCode)) //受理类型
+                .WhereIF(!string.IsNullOrEmpty(dto.Channel), d => d.SourceChannelCode == dto.Channel)
+                .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.HotspotSpliceName != null && d.HotspotSpliceName.Contains(dto.Hotspot))
+                .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone == dto.TransferPhone!) //转接号码
+                                                                                                               //.WhereIF(dto.OrgCodes.Any(), d => d.Workflow.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode)))
+                                                                                                               //.WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.ActualHandleOrgCode)) //接办部门
+                                                                                                               //.WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.CurrentHandleOrgId == dto.OrgId)//接办部门
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), d => d.OrgLevelOneName.Contains(dto.OrgLevelOneName)) //一级部门
+                .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门(综合查询模糊)
+                .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName == dto.NameOrNo! || d.AcceptorStaffNo == dto.NameOrNo!) //受理人/坐席
+                .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始
+                .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束
+                .WhereIF(dto.StartTimeStart.HasValue, d => d.StartTime >= dto.StartTimeStart) //流程开启时间开始
+                .WhereIF(dto.StartTimeEnd.HasValue, d => d.StartTime <= dto.StartTimeEnd) //流程开启时间结束
+                                                                                          //.WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))  //紧急程度
+                .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.FromPhone.Contains(dto.FromPhone)) //来电号码
+                .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.Contact.Contains(dto.PhoneNo)) //联系电话
+                                                                                                   //.WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode) //推送分类
+                .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), x => x.OrderPushTypes.Any(opt => opt.PushTypeCode == dto.PushTypeCode)) //推送分类
+                .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始
+                .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) //超期时间结束
+                                                                                                //.WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status))  //工单状态
+                .WhereIF(dto.Status.HasValue, d => d.Status == dto.Status) //工单状态
+                                                                           //.WhereIF(dto.Statuses.Any(d => d == EOrderStatus.SpecialToUnAccept), d => d.Status <= EOrderStatus.SpecialToUnAccept)
+                .WhereIF(!string.IsNullOrEmpty(dto.ActualHandlerName), d => d.ActualHandlerName == dto.ActualHandlerName) //接办人
+                .WhereIF(dto.IsScreen == true, d => d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //有甄别
+                .WhereIF(dto.IsScreen == false, d => !d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //无甄别
+                .WhereIF(!string.IsNullOrEmpty(dto.CurrentStepCode), d => d.CurrentStepCode == dto.CurrentStepCode) //当前办理节点
+                .WhereIF(dto.ActualHandleTimeStart.HasValue, d => d.FiledTime >= dto.ActualHandleTimeStart) //办结时间开始
+                .WhereIF(dto.ActualHandleTimeEnd.HasValue, d => d.FiledTime <= dto.ActualHandleTimeEnd) //办结时间结束
+                .WhereIF(dto.IsOverTime == true,
+                    d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) ||
+                         (d.ExpiredTime < d.FiledTime && d.Status >= EOrderStatus.Filed)) //是 超期
+                .WhereIF(dto.IsOverTime == false,
+                    d => (d.ExpiredTime > DateTime.Now && d.Status < EOrderStatus.Filed) ||
+                         (d.ExpiredTime > d.FiledTime && d.Status >= EOrderStatus.Filed)) //否 超期
+                .WhereIF(dto.IdentityType != null, d => d.IdentityType == dto.IdentityType) //来电主体
+                .WhereIF(!string.IsNullOrEmpty(dto.FromName), d => d.FromName == dto.FromName) //来电人姓名
+                .WhereIF(!string.IsNullOrEmpty(dto.AreaCode) && dto.AreaCode.LastIndexOf("00") > 0,
+                    d => d.AreaCode.StartsWith(SqlFunc.Substring(dto.AreaCode, 0, 4)))
+                .WhereIF(!string.IsNullOrEmpty(dto.AreaCode) && dto.AreaCode.LastIndexOf("00") <= 0, d => d.AreaCode.StartsWith(dto.AreaCode))
+                .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true && dto.ProvinceSearch != true, d => d.IsProvince == true)
+                .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false && dto.ProvinceSearch != true, d => d.IsProvince == false)
+                .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true && dto.ProvinceSearch == true, d => d.Source == ESource.ProvinceStraight)
+                .WhereIF(!string.IsNullOrEmpty(dto.SensitiveWord), d => SqlFunc.JsonArrayAny(d.Sensitive, dto.SensitiveWord))
+                .WhereIF(dto.IsSensitiveWord.HasValue && dto.IsSensitiveWord == true,
+                    d => d.Sensitive != null && SqlFunc.JsonArrayLength(d.Sensitive) > 0)
+                .WhereIF(dto.IsUrgent.HasValue, d => d.IsUrgent == dto.IsUrgent.Value)
+                .WhereIF(!string.IsNullOrEmpty(dto.ProvinceChannel) && dto.ProvinceChannel == "1", d => d.Source == ESource.ProvinceStraight &&
+                    d.SourceChannelCode == "SZMHD" && d.IsProvince == false) //政民互动直派
+                .WhereIF(!string.IsNullOrEmpty(dto.ProvinceChannel) && dto.ProvinceChannel == "2", d => d.Source == ESource.ProvinceStraight &&
+                    d.SourceChannelCode == "SZMHD" && d.IsProvince == true) //政民互动
+                .WhereIF(!string.IsNullOrEmpty(dto.ProvinceChannel) && dto.ProvinceChannel == "3", d => d.Source == ESource.ProvinceStraight &&
+                    d.SourceChannelCode == "S12345" && d.IsProvince == true) //省12345
+                                                                             //.WhereIF(!string.IsNullOrEmpty(dto.ContentRetrieval),d => d.Title.Contains(dto.ContentRetrieval) || d.Content.Contains(dto.ContentRetrieval) || d.FileOpinion.Contains(dto.ContentRetrieval) || d.ActualOpinion.Contains(dto.ContentRetrieval))
+                .WhereIF(!string.IsNullOrEmpty(dto.ContentRetrieval), d => d.Content.Contains(dto.ContentRetrieval!))
+                .WhereIF(!string.IsNullOrEmpty(dto.FileOption), d => d.FileOpinion.Contains(dto.FileOption!))
+                .WhereIF(dto.IsSgin.HasValue && dto.IsSgin == true, d => d.CurrentStepAcceptTime != null)
+                .WhereIF(dto.IsSgin.HasValue && dto.IsSgin == false, d => d.CurrentStepAcceptTime == null)
+                .WhereIF(dto.FiledType is FiledType.CenterFiled, d => d.FileOrgIsCenter == true) //d => d.ProcessType == EProcessType.Zhiban
+                .WhereIF(dto.FiledType is FiledType.OrgFiled, d => d.FileOrgIsCenter == false) //d => d.ProcessType == EProcessType.Jiaoban
+                                                                                               //.WhereIF(!string.IsNullOrEmpty(dto.OrderTagCode), d => d.OrderTagCode == dto.OrderTagCode)// 工单标签
+                .WhereIF(!string.IsNullOrEmpty(dto.OrderTagCode), d => d.OrderTags.Any(ot => ot.DicDataValue == dto.OrderTagCode)) //工单标签
+                .OrderByIF(string.IsNullOrEmpty(dto.SortField), d => d.CreationTime, OrderByType.Desc) //默认排序时间为创建时间
+                .OrderByIF(dto is { SortField: "no", SortRule: 0 }, d => d.No, OrderByType.Asc) //工单编号升序
+                .OrderByIF(dto is { SortField: "no", SortRule: 1 }, d => d.No, OrderByType.Desc) //工单编号降序
+                .OrderByIF(dto is { SortField: "isProvinceText", SortRule: 0 }, d => d.IsProvince, OrderByType.Asc) //是否省工单升序
+                .OrderByIF(dto is { SortField: "isProvinceText", SortRule: 1 }, d => d.IsProvince, OrderByType.Desc) //是否省工单降序
+                .OrderByIF(dto is { SortField: "reTransactNum", SortRule: 0 }, d => d.ReTransactNum, OrderByType.Asc) //重办次数升序
+                .OrderByIF(dto is { SortField: "reTransactNum", SortRule: 1 }, d => d.ReTransactNum, OrderByType.Desc) //重办次数降序
+                .OrderByIF(dto is { SortField: "isUrgentText", SortRule: 0 }, d => d.IsUrgent, OrderByType.Asc) //是否紧急升序
+                .OrderByIF(dto is { SortField: "isUrgentText", SortRule: 1 }, d => d.IsUrgent, OrderByType.Desc) //是否紧急降序
+                .OrderByIF(dto is { SortField: "isSecret", SortRule: 0 }, d => d.IsSecret, OrderByType.Asc) //是否紧急升序
+                .OrderByIF(dto is { SortField: "isSecret", SortRule: 1 }, d => d.IsSecret, OrderByType.Desc) //是否紧急降序
+                .OrderByIF(dto is { SortField: "currentStepName", SortRule: 0 }, d => d.CurrentStepName, OrderByType.Asc) //当前节点升序
+                .OrderByIF(dto is { SortField: "currentStepName", SortRule: 1 }, d => d.CurrentStepName, OrderByType.Desc) //当前节点降序
+                .OrderByIF(dto is { SortField: "actualStepAcceptText", SortRule: 0 }, d => d.ActualHandleStepAcceptTime.HasValue,
+                    OrderByType.Asc) //受理情况升序
+                .OrderByIF(dto is { SortField: "actualStepAcceptText", SortRule: 1 }, d => d.ActualHandleStepAcceptTime.HasValue,
+                    OrderByType.Desc) //受理情况降序
+                .OrderByIF(dto is { SortField: "statusText", SortRule: 0 }, d => d.Status, OrderByType.Asc) //工单状态升序
+                .OrderByIF(dto is { SortField: "statusText", SortRule: 1 }, d => d.Status, OrderByType.Desc) //工单状态降序
+                .OrderByIF(dto is { SortField: "creationTime", SortRule: 0 }, d => d.StartTime, OrderByType.Asc) //受理时间升序
+                .OrderByIF(dto is { SortField: "creationTime", SortRule: 1 }, d => d.StartTime, OrderByType.Desc) //受理时间降序
+                .OrderByIF(dto is { SortField: "expiredTime", SortRule: 0 }, d => d.ExpiredTime, OrderByType.Asc) //超期时间升序
+                .OrderByIF(dto is { SortField: "expiredTime", SortRule: 1 }, d => d.ExpiredTime, OrderByType.Desc) //超期时间降序
+                .OrderByIF(dto is { SortField: "filedTime", SortRule: 0 }, d => d.FiledTime, OrderByType.Asc) //办结时间升序
+                .OrderByIF(dto is { SortField: "filedTime", SortRule: 1 }, d => d.FiledTime, OrderByType.Desc) //办结时间降序
+                .OrderByIF(dto is { SortField: "orgLevelOneName", SortRule: 0 }, d => d.OrgLevelOneName, OrderByType.Asc) //一级部门升序
+                .OrderByIF(dto is { SortField: "orgLevelOneName", SortRule: 1 }, d => d.OrgLevelOneName, OrderByType.Desc) //一级部门降序
+                .OrderByIF(dto is { SortField: "orgLevelTwoName", SortRule: 0 }, d => d.OrgLevelTwoName, OrderByType.Asc) //二级部门升序
+                .OrderByIF(dto is { SortField: "orgLevelTwoName", SortRule: 1 }, d => d.OrgLevelTwoName, OrderByType.Desc) //二级部门降序
+                .OrderByIF(dto is { SortField: "actualHandleOrgName", SortRule: 0 }, d => d.ActualHandleOrgName, OrderByType.Asc) //接办部门升序
+                .OrderByIF(dto is { SortField: "actualHandleOrgName", SortRule: 1 }, d => d.ActualHandleOrgName, OrderByType.Desc) //接办部门降序
+                .OrderByIF(dto is { SortField: "acceptType", SortRule: 0 }, d => d.AcceptTypeCode, OrderByType.Asc) //受理类型升序
+                .OrderByIF(dto is { SortField: "acceptType", SortRule: 1 }, d => d.AcceptTypeCode, OrderByType.Desc) //受理类型降序
+                .OrderByIF(dto is { SortField: "counterSignTypeText", SortRule: 0 }, d => d.CounterSignType, OrderByType.Asc) //是否会签升序
+                .OrderByIF(dto is { SortField: "counterSignTypeText", SortRule: 1 }, d => d.CounterSignType, OrderByType.Desc) //是否会签降序
+                .OrderByIF(dto is { SortField: "hotspotSpliceName", SortRule: 0 }, d => d.HotspotSpliceName, OrderByType.Asc) //热点分类全称升序
+                .OrderByIF(dto is { SortField: "hotspotSpliceName", SortRule: 1 }, d => d.HotspotSpliceName, OrderByType.Desc) //热点分类全称降序
+                .OrderByIF(dto is { SortField: "hotspotName", SortRule: 0 }, d => d.HotspotName, OrderByType.Asc) //热点分类升序
+                .OrderByIF(dto is { SortField: "hotspotName", SortRule: 1 }, d => d.HotspotName, OrderByType.Desc) //热点分类降序
+                .OrderByIF(dto is { SortField: "acceptorName", SortRule: 0 }, d => d.AcceptorName, OrderByType.Asc) //受理人升序
+                .OrderByIF(dto is { SortField: "acceptorName", SortRule: 1 }, d => d.AcceptorName, OrderByType.Desc) //受理人降序
+                .OrderByIF(dto is { SortField: "currentStepAcceptTime", SortRule: 0 }, d => d.CurrentStepAcceptTime, OrderByType.Asc) //接办时间升序
+                .OrderByIF(dto is { SortField: "currentStepAcceptTime", SortRule: 1 }, d => d.CurrentStepAcceptTime, OrderByType.Desc) //接办时间降序
+            ;
+
+        query = query
+            .Includes(x => x.OrderSupervises.OrderByDescending(d => d.CreationTime).Take(2).ToList())
+            .Includes(x => x.OrderVisits, d => d.OrderVisitDetails.Where(c => c.VisitTarget == EVisitTarget.Org).Take(1).ToList());
+
+        return query;
+    }
+
     /// <summary>
     /// 未签收统计
     /// </summary>
@@ -5557,4 +5688,43 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     }
 
     #endregion
+
+    /// <summary>
+    /// 部门退回中心统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+
+    public ISugarQueryable<OrgSendBackAuditListVo> OrgSendBackAuditList(OrgSendBackAuditListDto dto)
+    {
+        var query = _orderSendBackAuditRepository.Queryable()
+            .Where(x => x.State == ESendBackAuditState.End && x.ApplyOrgId != OrgSeedData.CenterId && x.SendBackOrgId == OrgSeedData.CenterId)
+            .WhereIF(dto.StartTime.HasValue && dto.EndTime.HasValue, x => x.AuditTime >= dto.StartTime && x.AuditTime <= dto.EndTime)
+            .GroupBy(x => new { x.ApplyOrgId, x.ApplyOrgName })
+            .Select(x => new OrgSendBackAuditListVo
+            {
+                OrgId = x.ApplyOrgId,
+                OrgName = x.ApplyOrgName,
+                Num = SqlFunc.AggregateCount(1)
+            });
+        return query;
+    }
+
+    public ISugarQueryable<OrderSendBackAudit> OrgSendBackAuditDetail(OrgSendBackAuditListDto dto)
+    {
+        var query = _orderSendBackAuditRepository.Queryable()
+                .Includes(x => x.Order)
+                .Where(x => x.State == ESendBackAuditState.End && x.ApplyOrgId != OrgSeedData.CenterId && x.SendBackOrgId == OrgSeedData.CenterId)
+                .WhereIF(dto.StartTime.HasValue && dto.EndTime.HasValue, x => x.AuditTime >= dto.StartTime && x.AuditTime <= dto.EndTime)
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgId), x => x.ApplyOrgId == dto.OrgId)
+                .OrderByIF(string.IsNullOrEmpty(dto.SortField), x => x.CreationTime, OrderByType.Desc)
+                .OrderByIF(dto is { SortField: "order.startTime", SortRule: 0 }, x => x.Order.StartTime, OrderByType.Asc)
+                .OrderByIF(dto is { SortField: "order.startTime", SortRule: 1 }, x => x.Order.StartTime, OrderByType.Desc)
+                .OrderByIF(dto is { SortField: "creationTime", SortRule: 0 }, x => x.CreationTime, OrderByType.Asc)
+                .OrderByIF(dto is { SortField: "creationTime", SortRule: 1 }, x => x.CreationTime, OrderByType.Desc)
+                .OrderByIF(dto is { SortField: "auditTime", SortRule: 0 }, x => x.AuditTime, OrderByType.Asc)
+                .OrderByIF(dto is { SortField: "auditTime", SortRule: 1 }, x => x.AuditTime, OrderByType.Desc)
+            ;
+        return query;
+    }
 }

+ 21 - 0
src/Hotline.Application/Snapshot/Contracts/ISnapshotApplication.cs

@@ -212,4 +212,25 @@ public interface ISnapshotApplication
     /// <param name="id"></param>
     /// <returns></returns>
     Task<IList<OrderVisitItemsOutDto>> GetOrderVisitDetailAsync(string id);
+
+    /// <summary>
+    /// 积分榜
+    /// </summary>
+    /// <returns></returns>
+    Task<PointsRankOutDto> GetPointsRankAsync();
+
+    /// <summary>
+    /// 积分详情集合
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    Task<IList<PointItemsOutDto>> GetPointItemsAsync(PointItemsInDto dto, CancellationToken token);
+
+    /// <summary>
+    /// 积分总计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="requestAborted"></param>
+    /// <returns></returns>
+    Task<int> GetPointsTotalAsync(PointItemsInDto dto, CancellationToken requestAborted);
 }

+ 1 - 1
src/Hotline.Application/Snapshot/Contracts/IPointsRecordApplication.cs → src/Hotline.Application/Snapshot/Contracts/ISnapshotPointsApplication.cs

@@ -7,7 +7,7 @@ using System.Text;
 using System.Threading.Tasks;
 
 namespace Hotline.Application.Snapshot.Contracts;
-public interface IPointsRecordApplication
+public interface ISnapshotPointsApplication
 {
     ISugarQueryable<PointsItemsOutDto> GetPointsItems(PointsItemsInDto dto);
     Task UpdateIsSecurityMaxAsync(UpdateIsSecurityMaxAsync dto, CancellationToken token);

File diff suppressed because it is too large
+ 0 - 0
src/Hotline.Application/Snapshot/DefaultSnapshotApplication.cs


+ 93 - 8
src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs

@@ -35,6 +35,8 @@ using Hotline.Quality.Notifications;
 using XF.Utility.EnumExtensions;
 using Hotline.ThirdAccountDomainServices.Interfaces;
 using Hotline.Snapshot.IRepository;
+using Hotline.Share.Enums.CallCenter;
+using Hotline.Repository.SqlSugar.Snapshot;
 
 namespace Hotline.Application.Snapshot;
 
@@ -78,8 +80,9 @@ public abstract class SnapshotApplicationBase
     private readonly IInviteCodeRecordRepository _inviteCodeRecordRepository;
     private readonly IInviteCodeRepository _inviteCodeRepository;
     private readonly ICitizenRepository _citizenRepository;
+    private readonly ISnapshotPointsRecordRepository _pointsRecordRepository;
 
-    public SnapshotApplicationBase(IThirdIdentiyService thirdLoginService, IIndustryRepository industryRepository, ISnapshotBulletinRepository bulletinRepository, ISessionContext sessionContext, IRepository<RedPackRecord> redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IOrderSnapshotRepository orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISnapshotOrderPublishRepository snapshotOrderPublishRepository, IRepository<WorkflowTrace> workflowTraceRepository, IPractitionerRepository practitionerRepository, IRepository<SystemArea> systemAreaRepository, IVolunteerRepository volunteerRepository, IVolunteerReportRepository volunteerReportRepository, ISystemLogRepository systemLog, IGuiderSystemService guiderSystemService, ICapPublisher capPublisher, Publisher publisher, IFileDomainService fileDomainService, ICommunityInfoRepository communityInfoRepository, IRedPackAuditRepository redPackAuditRepository, IOrderVisitRepository orderVisitRepository, IOrderVisitDetailRepository orderVisitDetailRepository, IRedPackGuiderAuditRepository redPackGuiderAuditRepository, IInviteCodeRecordRepository inviteCodeRecordRepository, IInviteCodeRepository inviteCodeRepository, ICitizenRepository citizenRepository)
+    public SnapshotApplicationBase(IThirdIdentiyService thirdLoginService, IIndustryRepository industryRepository, ISnapshotBulletinRepository bulletinRepository, ISessionContext sessionContext, IRepository<RedPackRecord> redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IOrderSnapshotRepository orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISnapshotOrderPublishRepository snapshotOrderPublishRepository, IRepository<WorkflowTrace> workflowTraceRepository, IPractitionerRepository practitionerRepository, IRepository<SystemArea> systemAreaRepository, IVolunteerRepository volunteerRepository, IVolunteerReportRepository volunteerReportRepository, ISystemLogRepository systemLog, IGuiderSystemService guiderSystemService, ICapPublisher capPublisher, Publisher publisher, IFileDomainService fileDomainService, ICommunityInfoRepository communityInfoRepository, IRedPackAuditRepository redPackAuditRepository, IOrderVisitRepository orderVisitRepository, IOrderVisitDetailRepository orderVisitDetailRepository, IRedPackGuiderAuditRepository redPackGuiderAuditRepository, IInviteCodeRecordRepository inviteCodeRecordRepository, IInviteCodeRepository inviteCodeRepository, ICitizenRepository citizenRepository, ISnapshotPointsRecordRepository snapshotPointsRecordRepository)
     {
         _thirdLoginService = thirdLoginService;
         _industryRepository = industryRepository;
@@ -112,6 +115,7 @@ public abstract class SnapshotApplicationBase
         _inviteCodeRecordRepository = inviteCodeRecordRepository;
         _inviteCodeRepository = inviteCodeRepository;
         _citizenRepository = citizenRepository;
+        _pointsRecordRepository = snapshotPointsRecordRepository;
     }
 
     #region 小程序
@@ -204,10 +208,10 @@ public abstract class SnapshotApplicationBase
         if (indurstry.IndustryType == EIndustryType.Declare)
         {
             outDto.AreaTree = (await _systemAreaDomainService.GetAreaTree(parentId: "510300")).Adapt<List<SystemAreaOutDto>>();
-            outDto.AreaTree.ToList().ForEach(m => 
+            outDto.AreaTree.ToList().ForEach(m =>
             {
                 if (m.Children.IsNullOrEmpty())
-                    m.Children = new List<SystemAreaOutDto>() { new SystemAreaOutDto { Id = "0",  AreaName = "无"} };
+                    m.Children = new List<SystemAreaOutDto>() { new SystemAreaOutDto { Id = "0", AreaName = "无" } };
             });
             outDto.Files = (await _fileRepository.GetByKeyAsync(indurstry.Id, requestAborted)).Adapt<List<IndustryFileDto>>();
             outDto.Files.ToList().ForEach(m => m.Url = fileDownloadApi + m.AdditionId);
@@ -284,7 +288,7 @@ public abstract class SnapshotApplicationBase
     public async Task<IReadOnlyList<BulletinOutDto>> GetBulletinsAsync(BulletinInDto dto, CancellationToken cancellationToken)
     {
         var items = await _bulletinRepository.Queryable()
-            .Where(m => m.BulletinState == EBulletinState.ReviewPass)
+            .Where(m => m.BulletinState == EBulletinState.ReviewPass && m.IsArrive == true)
             .LeftJoin<Industry>((bulletin, industry) => bulletin.SnapshotBulletinTypeId == industry.BulletinTypePublicityId)
             .Where((bulletin, industry) => industry.Id == dto.IndustryId)
             .ToFixedListAsync(dto, cancellationToken);
@@ -334,6 +338,7 @@ public abstract class SnapshotApplicationBase
             .WhereIF(dto.Status == EOrderQueryStatus.NoReply, (snapshot, order) => order.Status < EOrderStatus.Filed)
             .WhereIF(dto.Status == EOrderQueryStatus.Reply, (snapshot, order) => order.Status >= EOrderStatus.Filed)
             .WhereIF(dto.KeyWords.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.KeyWords) || order.No.Contains(dto.KeyWords))
+            .OrderByDescending((snapshot, order) => snapshot.CreationTime)
             .Select((snapshot, order) => new OrderOutDto
             {
                 Id = snapshot.Id,
@@ -349,6 +354,35 @@ public abstract class SnapshotApplicationBase
         return items;
     }
 
+    /// <summary>
+    /// 积分详情集合
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    public async Task<IList<PointItemsOutDto>> GetPointItemsAsync(PointItemsInDto dto, CancellationToken token)
+    {
+        var items = await _pointsRecordRepository.Queryable()
+            .Where(m => m.UserId == _sessionContext.UserId && dto.Direction == m.Direction)
+            .Select(m => new PointItemsOutDto(), true)
+            .OrderByDescending(m => m.CreationTime)
+            .ToFixedListAsync(dto, token);
+        return items;
+    }
+
+    /// <summary>
+    /// 积分总计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="requestAborted"></param>
+    /// <returns></returns>
+    public async Task<int> GetPointsTotalAsync(PointItemsInDto dto, CancellationToken token)
+    {
+        return await _pointsRecordRepository.Queryable()
+            .Where(m => m.UserId == _sessionContext.UserId && dto.Direction == m.Direction)
+            .SumAsync(m => m.Points);
+    }
+
+
     /// <summary>
     /// 获取工单详情
     /// </summary>
@@ -409,7 +443,7 @@ public abstract class SnapshotApplicationBase
     /// <param name="id"></param>
     /// <returns></returns>
     public async Task<IList<OrderVisitItemsOutDto>> GetOrderVisitDetailAsync(string id)
-    { 
+    {
         var orderVisitId = await _orderVisitRepository.Queryable()
             .Where(m => m.OrderId == id)
             .Select(m => m.Id)
@@ -427,7 +461,7 @@ public abstract class SnapshotApplicationBase
         }
         var org = orderVisitDetail.Where(m => m.VisitTarget == EVisitTarget.Org).First();
         if (org != null)
-        { 
+        {
             if (org.OrgProcessingResults != null) item.OrgProcessingResults = org.OrgProcessingResults.Value;
             if (org.OrgHandledAttitude != null) item.OrgHandledAttitude = org.OrgHandledAttitude.Value;
         }
@@ -526,7 +560,7 @@ public abstract class SnapshotApplicationBase
     {
         dto.ValidateObject();
         if (int.TryParse(dto.InvitationCode, out var invitationCode) == false)
-        { 
+        {
             throw new UserFriendlyException(200, "邀请码格式错误");
         }
         var userInfo = await _citizenRepository.GetAsync(_sessionContext.UserId)
@@ -833,7 +867,7 @@ public abstract class SnapshotApplicationBase
     {
         var order = await _orderRepository.Queryable()
             .Where(m => m.Id == orderId)
-            .Select(m => new { m.Id, m.Status, m.No , m.FromPhone})
+            .Select(m => new { m.Id, m.Status, m.No, m.FromPhone })
             .FirstAsync(cancellationToken) ?? throw new UserFriendlyException($"{orderId} 工单不存在");
         var snapshot = await _orderSnapshotRepository.GetAsync(orderId) ?? throw new UserFriendlyException("工单不存在");
         if (order.Status != EOrderStatus.Filed) return $"{order.No} 工单状态非 {EOrderStatus.Filed} 不处理;";
@@ -901,4 +935,55 @@ public abstract class SnapshotApplicationBase
         await _bulletinRepository.UpdateAsync(bulletin);
     }
     #endregion
+
+    #region 积分
+    public async Task<PointsRankOutDto> GetPointsRankAsync()
+    {
+        var outDto = new PointsRankOutDto();
+        var record = await _pointsRecordRepository.Queryable()
+            .Where(m => m.UserId == _sessionContext.UserId)
+            .Select(m => new
+            {
+                Total = SqlFunc.AggregateSum(m.Points),
+                Out = SqlFunc.AggregateSum(SqlFunc.IIF(m.Direction == EPointsDirection.Out, m.Points, 0))
+            }).FirstAsync();
+        outDto.ValidPoints = record.Total - record.Out;
+        var startTime = new DateTime(DateTime.Now.Year, 1, 1, 0, 0, 0);
+        var endTime = new DateTime(DateTime.Now.Year, 12, 31, 23, 59, 59);
+        var query = _pointsRecordRepository.Queryable()
+            .LeftJoin<Citizen>((points, citizen) => points.UserId == citizen.Id)
+            .Where((points, citizen) => points.CreationTime >= startTime && points.CreationTime <= endTime)
+            .GroupBy((points, citizen) => new { citizen.Id, points.UserId, citizen.IsSecurityMax, citizen.Name, citizen.PhoneNumber })
+            .Select((points, citizen) => new PointsRankUserDto
+            {
+                IsSecurityMax = citizen.IsSecurityMax ?? false,
+                Rank = SqlFunc.MappingColumn<int>($@"
+            CASE 
+                WHEN citizen.""Id"" = '{_sessionContext.UserId}' THEN 1 
+                ELSE DENSE_RANK() OVER (ORDER BY SUM(CASE WHEN ""points"".""Direction"" = 1 THEN ""points"".""Points"" ELSE 0 END) DESC)
+            END"),
+                Points = SqlFunc.AggregateSum(points.Points),
+                UserName = citizen.Name!,
+                PhoneNumber = citizen.PhoneNumber,
+                CitizenId = citizen.Id,
+            }).MergeTable()
+            .OrderByDescending(points => points.Rank)
+            .Take(11);
+
+#if DEBUG
+        var sql = query.ToSqlString();
+#endif
+        var item = await query.ToListAsync();
+
+        item.ForEach(m =>
+        {
+            if (m.IsSecurityMax)
+                m.HeadUrl = _systemDicDataCacheManager.HeaderImages("aqws");
+            else
+                m.HeadUrl = _systemDicDataCacheManager.HeaderImages("default");
+        });
+        outDto.Ranks = item;
+        return outDto;
+    }
+    #endregion
 }

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

@@ -72,6 +72,9 @@ public class SnapshotOrderApplication : IOrderSnapshotApplication, IScopeDepende
     public async Task<string> AddOrderPublishAsync(AddSnapshotOrderPublishInDto dto, CancellationToken cancellation)
     {
         dto.ValidateObject();
+        var oldPublish = await _snapshotOrderPublishRepository.Queryable().Where(m => m.OrderId == dto.OrderId).FirstAsync(cancellation);
+        if (oldPublish != null)
+            await _snapshotOrderPublishRepository.RemoveAsync(oldPublish,cancellationToken: cancellation);
         var snapshotOrder = await _orderSnapshotRepository.GetAsync(dto.OrderId)
             ?? throw UserFriendlyException.SameMessage("工单不存在");
         var order = await _orderRepository.Queryable()
@@ -212,8 +215,8 @@ public class SnapshotOrderApplication : IOrderSnapshotApplication, IScopeDepende
             .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
             .LeftJoin<WorkflowStep>((snapshot, order, step) => step.ExternalId == order.Id)
             .Where((snapshot, order, step) => snapshot.IndustryName == "安全隐患")
-            .WhereIF(dto.Status == 0, (snapshot, order, step) => step.Tag == TagDefaults.OrderMark) // 全部
-            .WhereIF(dto.Status == 1, (snapshot, order, step) => step.Tag == TagDefaults.OrderMark && step.Status != EWorkflowStepStatus.Handled && step.HandlerId == _sessionContext.UserId) // 待标记
+            //.WhereIF(dto.Status == 0, (snapshot, order, step) => step.Tag == TagDefaults.OrderMark) // 全部
+            .WhereIF(dto.Status == 1, (snapshot, order, step) => step.Tag == TagDefaults.OrderMark && step.Status != EWorkflowStepStatus.Handled &&  _sessionContext.Roles.Contains(step.RoleId)) // 待标记
             .WhereIF(dto.Status == 2, (snapshot, order, step) => step.Tag == TagDefaults.OrderMark && step.Status == EWorkflowStepStatus.Handled) // 已标记
             .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order, step) => order.No.Contains(dto.No))
             .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order, step) => order.Title.Contains(dto.Title))

+ 6 - 5
src/Hotline.Application/Snapshot/PointsRecordApplication.cs → src/Hotline.Application/Snapshot/SnapshotPointsApplication.cs

@@ -15,12 +15,12 @@ using XF.Domain.Dependency;
 
 namespace Hotline.Application.Snapshot;
 
-public class PointsRecordApplication : IPointsRecordApplication, IScopeDependency
+public class SnapshotPointsApplication : ISnapshotPointsApplication, IScopeDependency
 {
     private readonly ISnapshotPointsRecordRepository _snapshotPointsRecordRepository;
     private readonly ICitizenRepository _citizenRepository;
 
-    public PointsRecordApplication(ISnapshotPointsRecordRepository snapshotPointsRecordRepository, ICitizenRepository citizenRepository)
+    public SnapshotPointsApplication(ISnapshotPointsRecordRepository snapshotPointsRecordRepository, ICitizenRepository citizenRepository)
     {
         _snapshotPointsRecordRepository = snapshotPointsRecordRepository;
         _citizenRepository = citizenRepository;
@@ -30,7 +30,7 @@ public class PointsRecordApplication : IPointsRecordApplication, IScopeDependenc
     {
         var query = _snapshotPointsRecordRepository.Queryable()
             .LeftJoin<Citizen>((points, citizen) => points.UserId == citizen.Id)
-            .WhereIF(dto.PhoneNumber.NotNullOrEmpty(), (points, citizen) => dto.PhoneNumber == citizen.PhoneNumber)
+            .WhereIF(dto.PhoneNumber.NotNullOrEmpty(), (points, citizen) => citizen.PhoneNumber.Contains(dto.PhoneNumber!))
             .Where((points, citizen) => points.CreationTime >= dto.StartTime && points.CreationTime <= dto.EndTime)
             .GroupBy((points, citizen) => new { points.UserId, citizen.IsSecurityMax, citizen.Name, citizen.PhoneNumber })
             .Select((points, citizen) => new PointsItemsOutDto
@@ -41,8 +41,9 @@ public class PointsRecordApplication : IPointsRecordApplication, IScopeDependenc
                 OutPoints = SqlFunc.AggregateSum(SqlFunc.IIF(points.Direction == EPointsDirection.Out && points.Source == EPointsSource.Audit, points.Points, 0)),
                 TotalPoints = SqlFunc.AggregateSum(points.Points),
                 InTotalPoint = SqlFunc.AggregateSum(SqlFunc.IIF(points.Direction == EPointsDirection.In, points.Points, 0)),
-                UserName = citizen.Name,
-                PhoneNumber = citizen.PhoneNumber
+                UserName = citizen.Name!,
+                PhoneNumber = citizen.PhoneNumber,
+                UserId = points.UserId,
             })
             .OrderByPropertyNameIF(dto.SortField.NotNullOrEmpty() && dto.SortRule == 0, dto.SortField, OrderByType.Desc)
             .OrderByPropertyNameIF(dto.SortField.NotNullOrEmpty() && dto.SortRule == 1, dto.SortField, OrderByType.Asc);

File diff suppressed because it is too large
+ 0 - 0
src/Hotline.Application/Snapshot/ZiGongSnapshotApplication.cs


+ 2 - 1
src/Hotline.Share/Dtos/Article/BulletinDto.cs

@@ -560,10 +560,11 @@ namespace Hotline.Share.Dtos.Article
         /// </summary>
         public string Title { get; set; }
 
+        private string content;
         /// <summary>
         /// 内容
         /// </summary>
-        public string Content { get; set; }
+        public string Content { get { return content.RemoveHtmlTags(); } set { content = value; } }
 
         public DateTime CreationTime { get; set; }
     }

+ 9 - 0
src/Hotline.Share/Dtos/Order/OrderBiDto.cs

@@ -1616,4 +1616,13 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public double Chain => PreviousCount == 0 ? 0 : Math.Round((SumCount / (double)PreviousCount) * 100, 2);
     }
+
+	public class OrgSendBackAuditListVo
+	{
+		public string OrgId { get; set; }
+
+		public string OrgName { get; set; }
+
+		public int Num { get; set; }
+	}
 }

+ 41 - 17
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -7,6 +7,7 @@ using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Enums.Settings;
 using Hotline.Share.Requests;
+using Hotline.Share.Tools;
 using Novacode;
 using XF.Utility.EnumExtensions;
 
@@ -622,20 +623,20 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
 		public string ThreeHotspotName => !string.IsNullOrEmpty(HotspotSpliceName) && HotspotSpliceName.Split("-").Length >= 3 ? HotspotSpliceName.Split("-")[2] : string.Empty;
 
-		/// <summary>
-		/// 四级热点
-		/// </summary>
-		public string FourHotspotName => !string.IsNullOrEmpty(HotspotSpliceName) && HotspotSpliceName.Split("-").Length >=4 ? HotspotSpliceName.Split("-")[3] : string.Empty;
+        /// <summary>
+        /// 四级热点
+        /// </summary>
+        public string FourHotspotName => !string.IsNullOrEmpty(HotspotSpliceName) && HotspotSpliceName.Split("-").Length >= 4 ? HotspotSpliceName.Split("-")[3] : string.Empty;
 
-		/// <summary>
-		/// 五级热点
-		/// </summary>
-		public string FiveHotspotName => !string.IsNullOrEmpty(HotspotSpliceName) && HotspotSpliceName.Split("-").Length >= 5 ? HotspotSpliceName.Split("-")[4] : string.Empty;
+        /// <summary>
+        /// 五级热点
+        /// </summary>
+        public string FiveHotspotName => !string.IsNullOrEmpty(HotspotSpliceName) && HotspotSpliceName.Split("-").Length >= 5 ? HotspotSpliceName.Split("-")[4] : string.Empty;
 
-		/// <summary>
-		/// 特提次数
-		/// </summary>
-		public int SpecialNum { get; set; }
+        /// <summary>
+        /// 特提次数
+        /// </summary>
+        public int SpecialNum { get; set; }
 
         private string CalculateExpiredText()
         {
@@ -1071,6 +1072,29 @@ namespace Hotline.Share.Dtos.Order
 
             return overDays;
         }
+
+        /// <summary>
+        /// 工单督办
+        /// </summary>
+        public List<OrderSuperviseDto> OrderSupervises { get; set; }
+
+        /// <summary>
+        /// 督办情况1
+        /// </summary>
+        public string? SuperviseInfo1 => OrderSupervises != null && OrderSupervises.Count > 0 ? OrderSupervises[0].CreationTime.ToString("yyyy-MM-dd HH:mm:ss") + "已通知" + OrderSupervises[0].OrgName : "";
+
+        /// <summary>
+        /// 督办情况2
+        /// </summary>
+        public string? SuperviseInfo2 => OrderSupervises != null && OrderSupervises.Count > 1 ? OrderSupervises[1].CreationTime.ToString("yyyy-MM-dd HH:mm:ss") + "已通知" + OrderSupervises[1].OrgName : "";
+
+        /// <summary>
+        /// 不满意原因
+        /// </summary>
+        public string? orgNoSatisfiedReasonText =>
+            OrderVisits != null && OrderVisits.Count > 0 ?
+            OrderVisits.FirstOrDefault().OrderVisitDetails != null && OrderVisits.FirstOrDefault().OrderVisitDetails.Count > 0 ?
+            OrderVisits.FirstOrDefault().OrderVisitDetails.FirstOrDefault().OrgNoSatisfiedReasonText : "" : "";
     }
 
 
@@ -1838,9 +1862,9 @@ namespace Hotline.Share.Dtos.Order
     }
 
     public class OrderStepUploadFilesDto
-	{
-		public string OrderId { get; set; }
-		public string StepId { get; set; }
-		public List<FileDto> Files { get; set; } = new();
-	}
+    {
+        public string OrderId { get; set; }
+        public string StepId { get; set; }
+        public List<FileDto> Files { get; set; } = new();
+    }
 }

+ 172 - 165
src/Hotline.Share/Dtos/Order/OrderSuperviseDto.cs

@@ -8,170 +8,177 @@ using System.Threading.Tasks;
 
 namespace Hotline.Share.Dtos.Order
 {
-	public class OrderSuperviseDto: SuperviseOrderDto
-	{
-		/// <summary>
-		/// 附件列表
-		/// </summary>
-		public List<FileDto> Files { get; set; } = new();
-
-		/// <summary>
-		/// 附件列表
-		/// </summary>
-		public List<FileDto> ReplyFiles { get; set; } = new();
-	}
-
-	public class ApplyOrderSuperviseDto 
-	{
-		/// <summary>
-		/// 工单ID
-		/// </summary>
-		public string OrderId { get; set; }
-
-		public List<ApplyOrderSuperviseOrgDto> SuperviseOrgDtos { get; set; }
-
-		/// <summary>
-		/// 督办回复时限
-		/// </summary>
-		public DateTime ReplyLimitTime { get; set; }
-
-		/// <summary>
-		/// 督办申请内容
-		/// </summary>
-		public string ApplyContent { get; set; }
-
-		/// <summary>
-		/// 是否接受短信,勾选校验手机号
-		/// </summary>
-		public bool AcceptSms { get; set; }
-
-		/// <summary>
-		/// 督办省编号
-		/// </summary>
-		public string? SUPERVISE_SERIAL { get; set; }
-
-		/// <summary>
-		/// 附件列表
-		/// </summary>
-		public List<FileDto> Files { get; set; } = new();
-	}
-	public class ReplyOrderSuperviseDto 
-	{
-
-		public string Id { get; set; }
-
-		/// <summary>
-		/// 督办回复内容
-		/// </summary>
-		public string ReplyContent { get; set; }
-
-
-		/// <summary>
-		/// 回复人
-		/// </summary>
-		public string? ReplyId { get; set; }
-
-		/// <summary>
-		/// 附件列表
-		/// </summary>
-		public List<FileDto> Files { get; set; } = new();
-	}
-
-	public class SignOrderSuperviseDto 
-	{
-		public string Id { get; set; }
-	}
-
-	public class ApplyOrderSuperviseOrgDto {
-		/// <summary>
-		/// 被督办部门ID
-		/// </summary>
-		public string OrgId { get; set; }
-
-		/// <summary>
-		/// 被督办部门名称
-		/// </summary>
-		public string OrgName { get; set; }
-
-	}
-
-
-	public class ProvinceOrderSuperviseDto
-	{
-		/// <summary>
-		/// 督办编号
-		/// </summary>
-		public string SuperviseSerial { get; set; }
-
-		/// <summary>
-		/// 省工单编号
-		/// </summary>
-		public string CaseSerial { get; set; }
-
-		/// <summary>
-		/// 督办标题
-		/// </summary>
-		public string SuperviseTitle { get; set; }
-
-		/// <summary>
-		/// 督办内容
-		/// </summary>
-		public string SuperviseContent { get; set; }
-
-		/// <summary>
-		/// 督办发起人
-		/// </summary>
-		public string SupervisePerson { get; set; }
-
-		/// <summary>
-		/// 督办发起时间
-		/// </summary>
-		public DateTime SuperviseTime { get; set; }
-
-		/// <summary>
-		/// 督办发起单位
-		/// </summary>
-		public string SuperviseSendDept { get; set; }
-
-		/// <summary>
-		/// 被督办单位
-		/// </summary>
-		public string SuperviseRsvDept { get; set; }
-
-		/// <summary>
-		/// 督办类型
-		/// </summary>
-		public string SuperviseType { get; set; }
-
-		/// <summary>
-		/// 督办反馈截止时间
-		/// </summary>
-		public DateTime SuperviseReturnDate { get; set; }
-
-		/// <summary>
-		/// 行政区划代码
-		/// </summary>
-		public string AreaCode { get; set; }
-
-		/// <summary>
-		/// 附件列表
-		/// </summary>
-		public List<FileDto> Files { get; set; } = new();
-	}
-	public class PublishSuperviseDto
-	{
-		// <summary>
-		/// 工单对象
-		/// </summary>
-		public OrderDto Order { get; set; }
-
-
-		public SuperviseOrderDto Supervise { get; set; }
-
-		/// <summary>
-		/// 附件
-		/// </summary>
-		public string ClientGuid { get; set; }
-	}
+    public class OrderSuperviseDto : SuperviseOrderDto
+    {
+        /// <summary>
+        /// 附件列表
+        /// </summary>
+        public List<FileDto> Files { get; set; } = new();
+
+        /// <summary>
+        /// 附件列表
+        /// </summary>
+        public List<FileDto> ReplyFiles { get; set; } = new();
+    }
+
+    public class ApplyOrderSuperviseDto
+    {
+        /// <summary>
+        /// 工单ID
+        /// </summary>
+        public string OrderId { get; set; }
+
+        public List<ApplyOrderSuperviseOrgDto> SuperviseOrgDtos { get; set; }
+
+        /// <summary>
+        /// 督办回复时限
+        /// </summary>
+        public DateTime ReplyLimitTime { get; set; }
+
+        /// <summary>
+        /// 督办申请内容
+        /// </summary>
+        public string ApplyContent { get; set; }
+
+        /// <summary>
+        /// 是否接受短信,勾选校验手机号
+        /// </summary>
+        public bool AcceptSms { get; set; }
+
+        /// <summary>
+        /// 督办省编号
+        /// </summary>
+        public string? SUPERVISE_SERIAL { get; set; }
+
+        /// <summary>
+        /// 附件列表
+        /// </summary>
+        public List<FileDto> Files { get; set; } = new();
+
+        /// <summary>
+        /// 旅游督办手机号
+        /// </summary>
+        public string? PhoneNo { get; set; }
+
+    }
+    public class ReplyOrderSuperviseDto
+    {
+
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 督办回复内容
+        /// </summary>
+        public string ReplyContent { get; set; }
+
+
+        /// <summary>
+        /// 回复人
+        /// </summary>
+        public string? ReplyId { get; set; }
+
+        /// <summary>
+        /// 附件列表
+        /// </summary>
+        public List<FileDto> Files { get; set; } = new();
+    }
+
+    public class SignOrderSuperviseDto
+    {
+        public string Id { get; set; }
+    }
+
+    public class ApplyOrderSuperviseOrgDto
+    {
+        /// <summary>
+        /// 被督办部门ID
+        /// </summary>
+        public string OrgId { get; set; }
+
+        /// <summary>
+        /// 被督办部门名称
+        /// </summary>
+        public string OrgName { get; set; }
+
+    }
+
+
+    public class ProvinceOrderSuperviseDto
+    {
+        /// <summary>
+        /// 督办编号
+        /// </summary>
+        public string SuperviseSerial { get; set; }
+
+        /// <summary>
+        /// 省工单编号
+        /// </summary>
+        public string CaseSerial { get; set; }
+
+        /// <summary>
+        /// 督办标题
+        /// </summary>
+        public string SuperviseTitle { get; set; }
+
+        /// <summary>
+        /// 督办内容
+        /// </summary>
+        public string SuperviseContent { get; set; }
+
+        /// <summary>
+        /// 督办发起人
+        /// </summary>
+        public string SupervisePerson { get; set; }
+
+        /// <summary>
+        /// 督办发起时间
+        /// </summary>
+        public DateTime SuperviseTime { get; set; }
+
+        /// <summary>
+        /// 督办发起单位
+        /// </summary>
+        public string SuperviseSendDept { get; set; }
+
+        /// <summary>
+        /// 被督办单位
+        /// </summary>
+        public string SuperviseRsvDept { get; set; }
+
+        /// <summary>
+        /// 督办类型
+        /// </summary>
+        public string SuperviseType { get; set; }
+
+        /// <summary>
+        /// 督办反馈截止时间
+        /// </summary>
+        public DateTime SuperviseReturnDate { get; set; }
+
+        /// <summary>
+        /// 行政区划代码
+        /// </summary>
+        public string AreaCode { get; set; }
+
+        /// <summary>
+        /// 附件列表
+        /// </summary>
+        public List<FileDto> Files { get; set; } = new();
+    }
+    public class PublishSuperviseDto
+    {
+        // <summary>
+        /// 工单对象
+        /// </summary>
+        public OrderDto Order { get; set; }
+
+
+        public SuperviseOrderDto Supervise { get; set; }
+
+        /// <summary>
+        /// 附件
+        /// </summary>
+        public string ClientGuid { get; set; }
+    }
 
 }

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

@@ -875,6 +875,16 @@ namespace Hotline.Share.Dtos.Order
         /// 是否回访结果修改
         /// </summary>
         public bool? IsUpdate { get; set; }
+
+        /// <summary>
+        /// 不满意原因
+        /// </summary>
+        public List<Kv>? OrgNoSatisfiedReason { get; set; }
+
+        /// <summary>
+        /// 回访对象类型 10:话务员 20:部门
+        /// </summary>
+        public EVisitTarget VisitTarget { get; set; }
     }
 
     public class OrderVisitDetailDto

+ 6 - 0
src/Hotline.Share/Dtos/Order/QueryOrderDto.cs

@@ -923,6 +923,12 @@ namespace Hotline.Share.Dtos.Order
         public string? Address { get; set; }
     }
 
+    public record OrgSendBackAuditListDto : PagedKeywordRequest 
+    {
+		public string? OrgName { get; set; }
+		public string? OrgId { get; set; }
+	}
+
 
     public enum EPublicState
     {

+ 8 - 12
src/Hotline.Share/Dtos/Snapshot/OrderDto.cs

@@ -183,29 +183,25 @@ public class AddSnapshotOrderInDto : Position
     /// </summary>
     public string? Attach { get; set; }
 
-    public string GetContent(EIndustryType industryType)
+    public string GetContent(EIndustryType industryType, IReadOnlyList<SystemDicDataOutDto> dic)
     {
+        var name = (dic.FirstOrDefault(m => m.DicDataValue == JobType.ToString()) ?? new SystemDicDataOutDto()).DicDataName;
         if (industryType == EIndustryType.Declare)
         {
             return $"经营单位类别: {this.BusinessUnitType}\r\n" + // 个人
                     $"作业场所:{this.Workplace}\r\n" + // 化工、民爆物品生产经营企业
                     $"场所名称:{this.WorkplaceName}\r\n" + // 多业态混合经营场所 - 存储多种功能的劳动密集型企业
-                    $"作业区域: {this.County + this.Town}\r\n" + // 自流井区舒坪街道
-                    $"作业类型: {this.JobType}\r\n" + // 电焊
+                    $"作业区域: {this.WorkArea}\r\n" + // 自流井区舒坪街道
+                    $"作业类型: {name}\r\n" + // 电焊
                     $"作业时间:{this.StartWorkTime}~{this.EndWorkTime}\r\n" +
-                    $"作业地点: {this.Town}({this.County})({this.Street})"; // 舒平(自流井区)(油库)"
+                    $"作业地点: {Address}{FullAddress}"; // 舒平(自流井区)(油库)"
         }
         return $"{Description}";
     }
 
-    public string GetTitle(EIndustryType industryType, string acceptType)
+    public string GetTitle(EIndustryType industryType, string titleSuffix)
     {
-        if (industryType == EIndustryType.Declare)
-        {
-            return $"【随手拍】关于{Town}({County})的申报";
-        }
-
-        return $"【随手拍】关于{Town}({County})的" + acceptType;
+        return $"【随手拍】关于{Address}" + titleSuffix;
     }
 }
 
@@ -1443,7 +1439,7 @@ public class GetOrderSnapshotPublishItemsOutDto
     /// <summary>
     /// 公开状态
     /// </summary>
-    public string? PublishStatusTxt => PublishStatus?.GetDescription() ?? "";
+    public string? PublishStatusTxt =>  PublishStatus.HasValue && PublishStatus.Value == EOrderSnapshotPublishStatus.Agree ? "公开" : PublishStatus?.GetDescription() ?? "";
 
     /// <summary>
     /// 信件状态

+ 5 - 0
src/Hotline.Share/Dtos/Snapshot/OrderPublishDto.cs

@@ -120,6 +120,11 @@ public class OrderPublishDetailOutDto : OrderPublishOutDto
     /// 线索名称
     /// </summary>
     public string HotspotSpliceName { get; set; }
+
+    /// <summary>
+    /// 上报时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
 }
 
 public class SnapshotWorkflow

+ 101 - 1
src/Hotline.Share/Dtos/Snapshot/PointsDto.cs

@@ -1,4 +1,7 @@
-using Hotline.Share.Requests;
+using Hotline.Share.Enums.CallCenter;
+using Hotline.Share.Enums.Snapshot;
+using Hotline.Share.Requests;
+using Hotline.Share.Tools;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
@@ -6,6 +9,7 @@ using System.Linq;
 using System.Text;
 using System.Text.Json.Serialization;
 using System.Threading.Tasks;
+using XF.Utility.EnumExtensions;
 
 namespace Hotline.Share.Dtos.Snapshot;
 
@@ -83,5 +87,101 @@ public class PointsItemsOutDto
     [JsonIgnore]
     [Newtonsoft.Json.JsonIgnore]
     public int InTotalPoint { get; set; }
+
+    /// <summary>
+    /// UserId
+    /// </summary>
+    public string UserId { get; set; }
+}
+
+
+public class PointsRankOutDto
+{
+    /// <summary>
+    /// 当前可用积分
+    /// </summary>
+    public int ValidPoints { get; set; }
+
+    /// <summary>
+    /// 排行
+    /// </summary>
+    public IList<PointsRankUserDto> Ranks { get; set; }
 }
 
+public class PointsRankUserDto
+{
+    /// <summary>
+    /// 用户名
+    /// </summary>
+    public string UserName { get; set; }
+
+
+    private string _phoneNumber;
+    /// <summary>
+    /// 联系电话
+    /// </summary>
+    public string PhoneNumber
+    {
+        get
+        {
+            return _phoneNumber.MaskPhoneNumber();
+        }
+        set { _phoneNumber = value; }
+    }
+
+    /// <summary>
+    /// 排名
+    /// </summary>
+    public int Rank { get; set; }
+
+    /// <summary>
+    /// 积分
+    /// </summary>
+    public int Points { get; set; }
+
+    /// <summary>
+    /// UserId
+    /// </summary>
+    public string CitizenId { get; set; }
+
+    /// <summary>
+    /// 是否安全卫士
+    /// </summary>
+    public bool IsSecurityMax { get; set; }
+
+    /// <summary>
+    /// 头像地址
+    /// </summary>
+    public string HeadUrl { get; set; }
+}
+
+public class PointItemsInDto : QueryFixedDto
+{
+    /// <summary>
+    /// 收入或者支出
+    /// </summary>
+    public EPointsDirection Direction { get; set; }
+}
+
+public class PointItemsOutDto
+{
+    /// <summary>
+    /// 创建时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 积分来源
+    /// </summary>
+    public EPointsSource Source { get; set; }
+
+    /// <summary>
+    /// 积分来源
+    /// </summary>
+    public string SourceTxt => Source.GetDescription();
+
+    /// <summary>
+    /// 积分
+    /// </summary>
+    public int Points { get; set; }
+}

+ 1 - 0
src/Hotline.Share/Dtos/Snapshot/ThirdTokenDto.cs

@@ -102,3 +102,4 @@ public class SaveInvitationCodeInDto
     [Required]
     public string InvitationCode { get; set; }
 }
+

+ 1 - 1
src/Hotline.Share/Tools/DataMaskExtensions.cs

@@ -23,7 +23,7 @@ public static class DataMaskExtensions
 
     public static string MaskPhoneNumber(this string original)
     {
-        if (original.Length != 11) return string.Empty;
+        if (original.Length < 11) return string.Empty;
         return original.Mask(3, 4);
     }
 

+ 13 - 0
src/Hotline.Share/Tools/StringExtensions.cs

@@ -109,4 +109,17 @@ public static class StringExtensions
         }
         return string.Empty;
     }
+
+    /// <summary>
+    /// 移除字符串中的所有 HTML 标签
+    /// </summary>
+    /// <param name="input">包含 HTML 的字符串</param>
+    /// <returns>去除 HTML 标签后的字符串</returns>
+    public static string RemoveHtmlTags(this string input)
+    {
+        if (string.IsNullOrWhiteSpace(input))
+            return string.Empty;
+
+        return Regex.Replace(input, "<.*?>", string.Empty);
+    }
 }

+ 7 - 0
src/Hotline/Caching/Interfaces/ISysDicDataCacheManager.cs

@@ -63,6 +63,13 @@ namespace Hotline.Caching.Interfaces
         /// <returns></returns>
         SystemDicDataOutDto GetSnapshotBulletinType(string dicDataValue);
 
+        /// <summary>
+        /// 用户头像
+        /// </summary>
+        /// <param name="v"></param>
+        /// <returns></returns>
+        string HeaderImages(string name);
+
         /// <summary>
         /// 红包补充发放类型
         /// </summary>

+ 19 - 0
src/Hotline/Caching/Services/SysDicDataCacheManager.cs

@@ -160,5 +160,24 @@ namespace Hotline.Caching.Services
             _cacheSysDicData.Remove(code);
         }
 
+        /// <summary>
+        /// 获取用户头像图片
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        /// <exception cref="NotImplementedException"></exception>
+        public string HeaderImages(string value)
+        {
+            var dto = GetOrAdd(SysDicTypeConsts.HeaderImages).Where(m => m.DicDataValue == value).FirstOrDefault() ?? new SystemDicDataOutDto();
+            if (dto.DicDataName == "LocalHeadImageDefault")
+            {
+                return SystemDicDataSeedData.LocalHeadImageDefault;
+            }
+            if (dto.DicDataName == "LocalHeadImageAQWS")
+            {
+                return SystemDicDataSeedData.LocalHeadImageAQWS;
+            }
+            return dto.DicDataName;
+        }
     }
 }

+ 4 - 6
src/Hotline/KnowledgeBase/KnowledgeDomainService.cs

@@ -491,20 +491,18 @@ namespace Hotline.KnowledgeBase
             }
 
            
-            var ktbool = dto.KnowledgeType.Any();
-			var kobool = dto.KnowledgeOrg.Any();
-			if (ktbool)
+			if (dto.KnowledgeType.Any())
 			{
 				knowledge.KnowledgeTypes = dto.KnowledgeType.Select(x => new KnowledgeType { Id = x.KnowledgeTypeId }).ToList();
 			}
-			if (kobool)
+			if (dto.KnowledgeOrg.Any())
 			{
 				knowledge.KnowledgeOrganizes = dto.KnowledgeOrg.Select(x => new SystemOrganize { Id = x }).ToList();
 			}
 
 			await _knowledgeRepository.UpdateNav(knowledge)
-				.Include(d => d.KnowledgeTypes, new UpdateNavOptions { ManyToManyIsUpdateA =true, ManyToManyIsUpdateB = ktbool })
-				.Include(d => d.KnowledgeOrganizes, new UpdateNavOptions { ManyToManyIsUpdateA = true, ManyToManyIsUpdateB = kobool })
+				.Include(d => d.KnowledgeTypes, new UpdateNavOptions { ManyToManyIsUpdateA =true})
+				.Include(d => d.KnowledgeOrganizes, new UpdateNavOptions { ManyToManyIsUpdateA = true})
 				.ExecuteCommandAsync();
             //if (dto.KnowledgeType.Any())
             //         {

+ 14 - 8
src/Hotline/Orders/Order.cs

@@ -910,17 +910,17 @@ namespace Hotline.Orders
         [SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true, ColumnDescription = "附件JSON")]
         public List<FileJson>? FileJson { get; set; }
 
-		//[SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true, ColumnDescription = "附件列表附件JSON")]
-		//public List<FileJson>? ListFileJson { get; set; }
+        //[SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true, ColumnDescription = "附件列表附件JSON")]
+        //public List<FileJson>? ListFileJson { get; set; }
 
-		#endregion
+        #endregion
 
-		#region 市州工单互转
+        #region 市州工单互转
 
-		/// <summary>
-		/// 是否转发
-		/// </summary>
-		[SugarColumn(ColumnDescription = "是否转发")]
+        /// <summary>
+        /// 是否转发
+        /// </summary>
+        [SugarColumn(ColumnDescription = "是否转发")]
         public bool? Transpond { get; set; }
 
         /// <summary>
@@ -1224,6 +1224,12 @@ namespace Hotline.Orders
         [Navigate(NavigateType.OneToOne, nameof(Id), nameof(OrderSnapshot.Id))]
         public OrderSnapshot OrderSnapshot { get; set; }
 
+        /// <summary>
+        /// 工单督办
+        /// </summary>
+        [Navigate(NavigateType.OneToMany, nameof(OrderSupervise.OrderId))]
+        public List<OrderSupervise> OrderSupervises { get; set; }
+
         #region Method
 
         public void Cancel()

File diff suppressed because it is too large
+ 13 - 0
src/Hotline/SeedData/SystemDicDataSeedData.cs


+ 5 - 0
src/Hotline/Settings/SettingConstants.cs

@@ -770,5 +770,10 @@ namespace Hotline.Settings
         /// 小休审批人角色
         /// </summary>
         public const string RestAuditRole = "RestAuditRole";
+
+        /// <summary>
+        /// 签入是否处理是否有小休
+        /// </summary>
+        public const string SignInCheckRest = "SignInCheckRest";
     }
 }

+ 5 - 0
src/Hotline/Settings/SysDicTypeConsts.cs

@@ -332,6 +332,11 @@ public class SysDicTypeConsts
     /// </summary>
     public static string ExtraDeductionPointsType = "ExtraDeductionPointsType";
 
+    /// <summary>
+    /// 用户头像集合
+    /// </summary>
+    public static string HeaderImages = "HeaderImages";
+
     /// <summary>
     /// 政治身份
     /// </summary>

+ 1 - 0
test/Hotline.Tests/Application/DefaultCallApplicationTest.cs

@@ -61,6 +61,7 @@ public class DefaultCallApplicationTest : TestBase
         var inDto = new QueryCallsFixedDto();
         inDto.CallStartTimeEnd = DateTime.Now;
         inDto.CallStartTimeStart = "2024/10/01 00:00:00".ObjToDate();
+        inDto.StaffNo = "8029";
 
         var items = await _defaultCallApplication.QueryCallsFixedAsync(inDto, new CancellationToken()).ToPageListWithoutTotalAsync(inDto, CancellationToken.None);
         items.ShouldNotBeNull();

+ 6 - 0
test/Hotline.Tests/Application/OrderApplicationTest.cs

@@ -3,7 +3,9 @@ using Hotline.Caching.Interfaces;
 using Hotline.Orders;
 using Hotline.Push.FWMessage;
 using Hotline.Push.Notifies;
+using Hotline.Settings;
 using Hotline.Share.Dtos.Order;
+using Hotline.Share.Dtos.Settings;
 using Hotline.Share.Enums.Order;
 using Mapster;
 using Shouldly;
@@ -55,5 +57,9 @@ public class OrderApplicationTest
         var m = data.Adapt<ReceiveMessageNotify>();
         m.NotifyDto.Name.ShouldBe(data.Name);
         m.NotifyDto.PushBusiness.ShouldBe(data.PushBusiness);
+
+        var a = new SystemDicData { Id = "123"};
+        var b = a.Adapt<SystemDicDataOutDto>();
+        b.ShouldNotBeNull();
     }
 }

+ 15 - 2
test/Hotline.Tests/Application/PointsRecordApplicationTest.cs

@@ -22,10 +22,12 @@ namespace Hotline.Tests.Application;
 
 public class PointsRecordApplicationTest : TestBase
 {
-    private readonly IPointsRecordApplication _pointsRecordApplication;
-    public PointsRecordApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, ITypedCache<SystemSetting> cacheSettingData, ThirdAccounSupplierFactory thirdAccountDomainFactory, IPointsRecordApplication pointsRecordApplication) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData, thirdAccountDomainFactory)
+    private readonly ISnapshotPointsApplication _pointsRecordApplication;
+    private readonly ISnapshotApplication _snapshotApplication;
+    public PointsRecordApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, ITypedCache<SystemSetting> cacheSettingData, ThirdAccounSupplierFactory thirdAccountDomainFactory, ISnapshotPointsApplication pointsRecordApplication, ISnapshotApplication snapshotApplication) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData, thirdAccountDomainFactory)
     {
         _pointsRecordApplication = pointsRecordApplication;
+        _snapshotApplication = snapshotApplication;
     }
 
     [Fact]
@@ -39,4 +41,15 @@ public class PointsRecordApplicationTest : TestBase
         var items = await _pointsRecordApplication.GetPointsItems(inDto).ToListAsync();
         items.ShouldNotBeNull();
     }
+
+    [Fact]
+    public async Task GetPointsRank_Test()
+    {
+        var item = await _snapshotApplication.GetPointsRankAsync();
+        item.ShouldNotBeNull();
+        foreach (var a in item.Ranks)
+        {
+            var s = a.PhoneNumber;
+        }
+    }
 }

+ 10 - 0
test/Hotline.Tests/Application/SnapshotApplicationTest.cs

@@ -312,6 +312,16 @@ public class SnapshotApplicationTest : TestBase
         detail.Content.ShouldNotBeNullOrEmpty();
     }
 
+    [Fact]
+    public async Task GetPointsItems_Test()
+    {
+        SetWeiXin();
+        var items = await _snapshotApplication.GetPointItemsAsync(new PointItemsInDto(), CancellationToken.None);
+        items.ShouldNotBeNull();
+        var total = await _snapshotApplication.GetPointsTotalAsync(new PointItemsInDto(), CancellationToken.None);
+        total.ShouldNotBe(0);
+    }
+
     /// <summary>
     /// 红包列表记录
     /// </summary>

Some files were not shown because too many files changed in this diff