瀏覽代碼

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

Dun.Jason 1 月之前
父節點
當前提交
f11e0f345f
共有 42 個文件被更改,包括 5968 次插入183 次删除
  1. 1 0
      .gitignore
  2. 11 7
      src/Hotline.Api/Controllers/FilterController/ExportDataController.cs
  3. 3 1
      src/Hotline.Api/Controllers/OrderController.cs
  4. 3 1
      src/Hotline.Api/Controllers/SettingController.cs
  5. 306 3
      src/Hotline.Api/Controllers/Snapshot/BiSnapshotController.cs
  6. 2 3
      src/Hotline.Api/Controllers/Snapshot/RedPackController.cs
  7. 38 7
      src/Hotline.Api/Controllers/Snapshot/SnapshotOrderController.cs
  8. 1 0
      src/Hotline.Api/Controllers/SysController.cs
  9. 4 0
      src/Hotline.Api/Controllers/TestController.cs
  10. 1 1
      src/Hotline.Api/config/appsettings.Development.json
  11. 39 1
      src/Hotline.Application/ExportExcel/ExportApplication.cs
  12. 1 0
      src/Hotline.Application/ExportExcel/IExportApplication.cs
  13. 2 0
      src/Hotline.Application/Mappers/SnapshotMapperConfigs.cs
  14. 1 1
      src/Hotline.Application/Orders/Handlers/OrderScreenHandler/OrderScreenNextWorkflowHandler.cs
  15. 9 9
      src/Hotline.Application/Orders/OrderApplication.cs
  16. 955 8
      src/Hotline.Application/Snapshot/BiSnapshotApplication.cs
  17. 102 1
      src/Hotline.Application/Snapshot/IBiSnapshotApplication.cs
  18. 16 0
      src/Hotline.Application/Snapshot/IOrderSnapshotApplication.cs
  19. 23 0
      src/Hotline.Application/Snapshot/Notifications/SnapshotHandler.cs
  20. 86 52
      src/Hotline.Application/Snapshot/RedPackApplication.cs
  21. 3 0
      src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs
  22. 112 1
      src/Hotline.Application/Snapshot/SnapshotOrderApplication.cs
  23. 2 1
      src/Hotline.Application/Subscribers/DatasharingSubscriber.cs
  24. 8 0
      src/Hotline.Share/Attributes/ExportExcelAttribute.cs
  25. 1 1
      src/Hotline.Share/Dtos/Order/OrderStartFlowDto.cs
  26. 667 19
      src/Hotline.Share/Dtos/Snapshot/OrderDto.cs
  27. 3087 11
      src/Hotline.Share/Dtos/Snapshot/StatisticsDto.cs
  28. 38 0
      src/Hotline.Share/Tools/DateTimeExtensions.cs
  29. 67 0
      src/Hotline.Share/Tools/ListExtensions.cs
  30. 8 0
      src/Hotline.Share/Tools/MethodInfoExtensions.cs
  31. 1 0
      src/Hotline/Configurations/AppConfiguration.cs
  32. 18 0
      src/Hotline/Orders/Notifications/OrderSpecialNotify.cs
  33. 1 1
      src/Hotline/Snapshot/CommunityInfo.cs
  34. 45 1
      src/Hotline/Snapshot/OrderSnapshot.cs
  35. 2 2
      src/Hotline/Snapshot/RedPackAudit.cs
  36. 2 2
      src/Hotline/Snapshot/SupplementRecord.cs
  37. 112 0
      test/Hotline.Tests/Application/BiSnapshotApplicationTest.cs
  38. 30 27
      test/Hotline.Tests/Application/OrderSnapshotApplicationTest.cs
  39. 19 19
      test/Hotline.Tests/Application/RedPackApplicationTest.cs
  40. 133 3
      test/Hotline.Tests/Mock/OrderServiceMock.cs
  41. 5 0
      test/Hotline.Tests/Startup.cs
  42. 3 0
      test/Hotline.Tests/appsettings.Development.json

+ 1 - 0
.gitignore

@@ -347,3 +347,4 @@ healthchecksdb
 /merge.ps1
 /merge_245_test.ps1
 /merge_dev.ps1
+/merge_snapshot_test.ps1

+ 11 - 7
src/Hotline.Api/Controllers/FilterController/ExportDataController.cs

@@ -1,4 +1,5 @@
-using Hotline.Application.ExportExcel;
+using DocumentFormat.OpenXml.Office2010.Ink;
+using Hotline.Application.ExportExcel;
 using Hotline.Share.Attributes;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Tools;
@@ -53,10 +54,10 @@ public class ExportDataController : BaseController
             .Where(endpoint => endpoint.RoutePattern.RawText == originalPath)
             .ToList()
             ?? throw UserFriendlyException.SameMessage($"根据URL查询路由失败: {originalPath}");
-        var matchingEndpoint = matchingEndpoints.First();
+        var matchingEndpoint = matchingEndpoints.FirstOrDefault();
         if (matchingEndpoints.Count > 1)
         {
-            matchingEndpoint = matchingEndpoints.First(m => m.DisplayName.Contains("Get"));
+            matchingEndpoint = matchingEndpoints.FirstOrDefault(m => m.DisplayName.Contains("Get"));
         }
         if (matchingEndpoint == null)
             throw UserFriendlyException.SameMessage($"根据URL查询路由失败: {originalPath}");
@@ -98,6 +99,7 @@ public class ExportDataController : BaseController
 
         var returnType = method.ReturnType.GetGenericArguments()[0];
         var fileName = method.GetFileName() + "_";
+        var totalName = method.GetTotalName();
         if (pageIndex == null || pageSize == null)
         {
             pageSize = param.ParameterType.GetProperty("QueryCount")?.GetValue(queryDto);
@@ -108,13 +110,13 @@ public class ExportDataController : BaseController
                 pageIndex = 1;
                 pageSize = 20;
             }
-            else 
+            else
             {
                 pageIndex += 1;
             }
         }
 
-        return _exportApplication.GetExcelFile(returnType, genericType, exportData, ConvertToList(result, (bool)isExportAll, (int)pageIndex, (int)pageSize), fileName);
+        return _exportApplication.GetExcelFile(returnType, genericType, exportData, ConvertToList(result, (bool)isExportAll, (int)pageIndex, (int)pageSize), fileName, totalName);
     }
 
     public static List<object>? ConvertToList(object? result, bool isExportAll, int pageIndex, int pageSize)
@@ -125,14 +127,16 @@ public class ExportDataController : BaseController
         }
 
         var type = result.GetType();
+        if (!type.IsGenericType || type.GetGenericTypeDefinition() == typeof(List<>))
+        {
+            return (result as IEnumerable<object>).ToList();
+        }
 
         if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(PostgreSQLQueryable<>))
         {
             throw UserFriendlyException.SameMessage("被导出方法的返回类型不是 ISugarQueryable");
         }
 
-        var genericArgument = type.GetGenericArguments()[0];
-
         if (isExportAll)
         {
             var toListMethod = type.GetMethods()

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

@@ -6563,6 +6563,7 @@ public class OrderController : BaseController
         }
 
         await _orderSpecialRepository.AddAsync(special, HttpContext.RequestAborted);
+        await _publisher.PublishAsync(new AddOrderSpecialNotify(order.Id, order.SourceChannel, dto.ReTransactError), PublishStrategy.ParallelWhenAll, HttpContext.RequestAborted);
     }
 
     /// <summary>
@@ -7004,10 +7005,11 @@ public class OrderController : BaseController
             }
         }
 
+        var isInstaShot = order.SourceChannel.Contains("随手拍");
         var rsp = new
         {
             SpecialTimeType = EnumExts.GetDescriptions<ETimeType>(),
-            SpecialReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SpecialReason),
+            SpecialReason = isInstaShot ? _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.InstaShotSpecialReason) : _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SpecialReason),
             InstaShotSpecialReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.InstaShotSpecialReason),
             Step = step,
             IsTerminate =

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

@@ -1,4 +1,5 @@
-using Hotline.Caching.Interfaces;
+using Hotline.Api.Filter;
+using Hotline.Caching.Interfaces;
 using Hotline.Caching.Services;
 using Hotline.CallCenter.Manage;
 using Hotline.Orders;
@@ -139,6 +140,7 @@ namespace Hotline.Api.Controllers
         /// <param name="dto"></param>
         /// <returns></returns>
         [HttpPost("modifysettings")]
+        [LogFilter("修改系统配置")]
         public async Task ModifySettingsAsync([FromBody]ModifySettingDto  dto)
         {
             var model = await _systemSettingsRepository.GetAsync(dto.Id, HttpContext.RequestAborted);

+ 306 - 3
src/Hotline.Api/Controllers/Snapshot/BiSnapshotController.cs

@@ -1,6 +1,26 @@
 using Hotline.Application.Snapshot;
+using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.Snapshot;
 using Microsoft.AspNetCore.Mvc;
+using Hotline.Repository.SqlSugar.Extensions;
+using Hotline.Share.Tools;
+using Hotline.Snapshot.Interfaces;
+using Hotline.Settings.Hotspots;
+using Hotline.Share.Requests;
+using SqlSugar;
+using XF.Domain.Authentications;
+using Hotline.Settings;
+using Hotline.Caching.Interfaces;
+using Hotline.Share.Enums.Order;
+using Hotline.Share.Enums.Snapshot;
+using XF.Utility.EnumExtensions;
+using Amazon.Runtime.Internal.Util;
+using System.Collections;
+using Mapster;
+using Hotline.Share.Dtos.Settings;
+using XF.Domain.Repository;
+using Hotline.Configurations;
+using Microsoft.Extensions.Options;
 
 namespace Hotline.Api.Controllers.Snapshot;
 
@@ -10,10 +30,31 @@ namespace Hotline.Api.Controllers.Snapshot;
 public class BiSnapshotController : BaseController
 {
     private readonly IBiSnapshotApplication _biSnapshotApplication;
+    private readonly IIndustryRepository _industryRepository;
+    private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
+    private readonly IRepository<SystemArea> _areaRepository;
+    private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
 
-    public BiSnapshotController(IBiSnapshotApplication biSnapshotApplication)
+    public BiSnapshotController(IBiSnapshotApplication biSnapshotApplication, IIndustryRepository industryRepository, ISystemDicDataCacheManager systemDicDataCacheManager, IRepository<SystemArea> areaRepository, IOptionsSnapshot<AppConfiguration> appOptions)
     {
         _biSnapshotApplication = biSnapshotApplication;
+        _industryRepository = industryRepository;
+        _systemDicDataCacheManager = systemDicDataCacheManager;
+        _areaRepository = areaRepository;
+        _appOptions = appOptions;
+    }
+
+    /// <summary>
+    /// 随手拍统计基础数据
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("statistics/basedata")]
+    public async Task<Dictionary<string, object>> GetSnapshotStatisticsBaseDataAsync()
+    {
+        return new Dictionary<string, object>()
+        {
+            { "industry", await _industryRepository.GetDataBaseAsync() }
+        };
     }
 
     /// <summary>
@@ -21,7 +62,269 @@ public class BiSnapshotController : BaseController
     /// </summary>
     /// <returns></returns>
     [HttpGet("statistics")]
-    public async Task<SnapshotStatisticsOutDto> GetSnapshotStatisticsAsync([FromBody] SnapshotStatisticsInDto dto)
-        =>  await _biSnapshotApplication.GetSnapshotStatisticsAsync(dto, HttpContext.RequestAborted);
+    public async Task<SnapshotStatisticsOutDto> GetSnapshotStatisticsAsync([FromQuery] SnapshotStatisticsInDto dto)
+        => await _biSnapshotApplication.GetSnapshotStatisticsAsync(dto, HttpContext.RequestAborted);
+
+    /// <summary>
+    /// 随手拍统计详情集合
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("statistics/details")]
+    public async Task<PagedDto<SnapshotStatisticsDetailOutDto>> GetSnapshotStatisticsDetailAsync([FromQuery] SnapshotStatisticsDetailInDto dto)
+        => (await _biSnapshotApplication.GetSnapshotStatisticsDetail(dto).ToPagedListAsync(dto)).ToPaged();
+
+
+    /// <summary>
+    /// 市民红包审核统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("redpack/audit")]
+    public IList<RedPackStatisticsOutDto> GetRedPackAuditStatisticsAsync([FromQuery] RedPackStatisticsInDto dto)
+        => _biSnapshotApplication.GetRedPackAuditStatistics(dto);
+
+    /// <summary>
+    /// 市民红包审核统计详情
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("redpack/audit/details")]
+    public async Task<PagedDto<RedPackStatisticsDetailsOutDto>> GetRedPackAuditStatisticsDetailsAsync([FromQuery] RedPackStatisticsDetailsInDto dto)
+        => (await _biSnapshotApplication.GetRedPackAuditStatisticsDetails(dto).ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 热点类型小类统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("hotspot-statistics")]
+    public async Task<IList<HotspotStatisticsOutDto>> GetHotspotStatisticsAsync([FromQuery] HotspotStatisticsInDto dto)
+        => await _biSnapshotApplication.GetHotspotStatistics(dto).ToListAsync();
+
+    /// <summary>
+    /// 热点类型小类统计明细
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("hotspot-statistics-detail")]
+    public async Task<PagedDto<HotspotStatisticsDetailsOutDto>> GetHotspotStatisticsDetailAsync([FromQuery] HotspotStatisticsDetailsInDto dto)
+        => (await _biSnapshotApplication.HotspotStatisticsDetail(dto).ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 热点类型-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("hotspot-data-statistics")]
+    public async Task<IList<HotspotDataStatisticsOutDto>> GetHotspotDataStatisticsAsync([FromQuery] HotspotDataStatisticsInDto dto)
+    {
+        var items = await _biSnapshotApplication.GetHotspotDataStatisticsAsync(dto).ToListAsync();
+        if (items.Count != 0)
+        {
+            items.Add(new HotspotDataStatisticsOutDto
+            {
+                Name = "合计",
+                OrderCount = items.Sum(x => x.OrderCount),
+            });
+        }
+        return items;
+    }
+
+    /// <summary>
+    /// 办件统计-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("processing-statistics")]
+    public async Task<IList<SnapshotProcessingStatisticsOutDto>> GetSnapshotProcessingStatistics([FromQuery] SnapshotProcessingStatisticsInDto dto)
+        => await _biSnapshotApplication.GetSnapshotProcessingStatistics(dto).ToListAsync();
+
+    /// <summary>
+    /// 办件统计明细-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("processing-statistics-detail")]
+    public async Task<PagedDto<SnapshotProcessingStatisticsDetailsOutDto>> GetSnapshotProcessingStatisticsDetails([FromQuery] SnapshotProcessingStatisticsDetailsInDto dto)
+        => (await _biSnapshotApplication.GetSnapshotProcessingStatisticsDetails(dto).ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 网格员办理情况统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("guider-work-statistics")]
+    public async Task<IList<GuiderWorkStatisticsOutDto>> GetGuiderWorkStatisticsAsync([FromQuery] GuiderWorkStatisticsInDto dto)
+        => await _biSnapshotApplication.GetGuiderWorkStatisticsAsync(dto).ToListAsync();
+
+    /// <summary>
+    /// 网格员办理情况统计详情
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("guider-work-statistics-detail")]
+    public async Task<PagedDto<GuiderWorkStatisticsDetailsOutDto>> GetGuiderWorkStatisticsDetailsAsync([FromQuery] GuiderWorkStatisticsDetailsInDto dto)
+        => (await _biSnapshotApplication.GetGuiderWorkStatisticsDetails(dto).ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 网格员系统工单状态日志基础数据
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("guider-work-log/basedata")]
+    public async Task<Dictionary<string, object>> GetGuiderWorkLogsAsyncBasedataAsync()
+    {
+        return new Dictionary<string, object>
+        {
+            { "orderStatus", EnumExts.GetDescriptions<EGuiderSystemReplyType>()},
+        };
+    }
+
+    /// <summary>
+    /// 网格员系统工单状态日志
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("guider-work-log")]
+    public async Task<PagedDto<GuiderWorkLogsOutDto>> GetGuiderWorkLogsAsync([FromQuery] GuiderWorkLogsInDto dto)
+        => (await _biSnapshotApplication.GetGuiderWorkLogs(dto).ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 重复件-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("duplicate")]
+    public async Task<PagedDto<DuplicateItemsOutDto>> GetDuplicateItemsAsync([FromQuery] DuplicateItemsInDto dto)
+    => (await _biSnapshotApplication.GetDuplicateItems(dto).ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 社区统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("community-statistics")]
+    public async Task<IList<CommunityStatisticsOutDto>> GetCommunityStatisticsAsync([FromQuery] CommunityStatisticsInDto dto)
+        => await _biSnapshotApplication.GetCommunityStatistics(dto).ToListAsync();
+
+    /// <summary>
+    /// 社区统计-详情
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("community-statistics-detail")]
+    public async Task<PagedDto<CommunityStatisticsDetailsOutDto>> GetCommunityStatisticsDetailsAsync([FromQuery] CommunityStatisticsDetailsInDto dto)
+        => (await _biSnapshotApplication.GetCommunityStatisticsDetails(dto).ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 随手拍区域统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("county-redpack-statistics")]
+    public async Task<IList<CountyRedPackStatisticsOutDto>> GetCountyRedPackStatisticsAsync([FromQuery] CountyRedPackStatisticsInDto dto)
+        => await _biSnapshotApplication.GetCountyRedPackStatistics(dto).ToListAsync();
+
+    /// <summary>
+    /// 部门考核统计-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("department-statistics")]
+    public async Task<IList<SnapshotDepartmentStatisticsOutDto>> GetSnapshotDepartmentStatisticsAsync([FromQuery] SnapshotDepartmentStatisticsInDto dto)
+        => await _biSnapshotApplication.GetSnapshotDepartmentStatistics(dto).ToListAsync();
+
+    /// <summary>
+    /// 部门平均办理时间-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("department-avetime-statistics")]
+    public async Task<IList<SnapshotDepartmentAveTimeStatisticsOutDto>> GetSnapshotDepartmentAveTimeStatisticsAsync([FromQuery] SnapshotDepartmentAveTimeStatisticsInDto dto)
+        => await _biSnapshotApplication.GetSnapshotDepartmentAveTimeStatistics(dto).ToListAsync();
+
+    /// <summary>
+    /// 部门平均办理时间-随手拍-详情
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("department-avetime-statistics-detail")]
+    public async Task<PagedDto<SnapshotDepartmentAveTimeStatisticsDetailsOutDto>> GetSnapshotDepartmentAveTimeStatisticsDtailsAsync([FromQuery] SnapshotDepartmentAveTimeStatisticsDetailsInDto dto)
+        => (await _biSnapshotApplication.GetSnapshotDepartmentAveTimeStatisticsDtails(dto).ToPagedListAsync(dto)).ToPaged();
 
+    /// <summary>
+    /// 检查合规统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("compliant-statistics")]
+    public async Task<IList<CompliantStatisticsOutDto>> CompliantStatisticsAsync([FromQuery] CompliantStatisticsInDto dto)
+    {
+        var items = await _biSnapshotApplication.GetCompliantStatistics(dto).ToListAsync();
+        items.AddSumLine("OrgName");
+        return items;
+    }
+
+    /// <summary>
+    /// 行业统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("industry-statistics")]
+    public async Task<IndustryStatisticsOutDto> GetIndustryStatisticsAsync([FromQuery] IndustryStatisticsInDto dto)
+    {
+        var areaCode = _appOptions.Value.AreaCode;
+        return new IndustryStatisticsOutDto
+        {
+            Headers = await _areaRepository.Queryable().Where(m => m.ParentId == areaCode).Select(m => new SystemDicDataOutDto { 
+                Id = m.Id,
+                DicDataName = m.AreaName,
+                DicDataValue = m.AreaName,
+            }).ToListAsync(),
+            Data = _biSnapshotApplication.GetIndustryStatistics(dto)
+        };
+    }
+
+    /// <summary>
+    /// 行业统计详情
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("industry-statistics-detail")]
+    public async Task<PagedDto<IndustryStatisticsDetailsOutDto>> GetIndustryStatisticsDetailsAsync([FromQuery] IndustryStatisticsDetailsInDto dto)
+        => (await _biSnapshotApplication.GetIndustryStatisticsDetails(dto).ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 检查合规统计-详情
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("compliant-statistics-detail")]
+    public async Task<PagedDto<CompliantStatisticsDetailsOutDto>> CompliantStatisticsDetailsAsync([FromQuery] CompliantStatisticsDetailsInDto dto)
+        => (await _biSnapshotApplication.GetCompliantStatisticsDetails(dto).ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 重办统计-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("re_transact-statistics")]
+    public async Task<ReTransactStatisticsOutDto> GetReTransactStatisticsAsync([FromQuery] ReTransactStatisticsInDto dto)
+    {
+        var headers = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.InstaShotSpecialReason).Adapt<IList<SystemDicDataOutDto>>();
+        return new ReTransactStatisticsOutDto
+        {
+            Headers = headers,
+            Data = _biSnapshotApplication.GetReTransactStatistics(dto)
+        };
+    }
+
+    /// <summary>
+    /// 重办统计详情-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("re_transact-statistics-detail")]
+    public async Task<PagedDto<ReTransactStatisticsDetailsOutDto>> GetReTransactStatisticsDetailAsync([FromQuery] ReTransactStatisticsDetailsInDto dto)
+        => (await _biSnapshotApplication.GetReTransactStatisticsDetail(dto).ToPagedListAsync(dto)).ToPaged();
 }

+ 2 - 3
src/Hotline.Api/Controllers/Snapshot/RedPackController.cs

@@ -41,7 +41,7 @@ public class RedPackController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpGet("special")]
-    public async Task<PagedDto<SnapshotOrderAuditItemsOutDto>> GetRedPackSpecialItems([FromQuery] SnapshotOrderAuditItemsInDto dto)
+    public async Task<PagedDto<SnapshotOrderAuditItemsOutDto>> GetRedPackSpecialAuditItems([FromQuery] SnapshotOrderAuditItemsInDto dto)
         => (await _redPackApplication.GetRedPackSpecialAuditItems(dto).ToPagedListAsync(dto)).ToPaged();
 
     /// <summary>
@@ -129,7 +129,6 @@ public class RedPackController : BaseController
     /// <summary>
     /// 添加备注页面基础信息
     /// </summary>
-    /// <param name="dto"></param>
     /// <returns></returns>
     [HttpGet("audit/remark/basedata")]
     public async Task<Dictionary<string, object>> UpdateRedPackAuditRemarkBaseDataAsync()
@@ -147,7 +146,7 @@ public class RedPackController : BaseController
     [HttpGet("record/basedata/{id}")]
     public async Task<GetRedPackRecordBaseDataOutDto> UpdateRedPackRecordBaseDataAsync(string id)
     {
-        return await _redPackApplication.GetRedPackRecordBaseDataAsync(id); ;
+        return await _redPackApplication.GetRedPackRecordBaseDataAsync(id);
     }
 
     /// <summary>

+ 38 - 7
src/Hotline.Api/Controllers/Snapshot/SnapshotOrderController.cs

@@ -4,6 +4,7 @@ using Hotline.Application.Orders;
 using Hotline.Application.Snapshot;
 using Hotline.Caching.Interfaces;
 using Hotline.Caching.Services;
+using Hotline.Configurations;
 using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
@@ -20,6 +21,7 @@ using Hotline.Snapshot;
 using Hotline.Snapshot.Interfaces;
 using Mapster;
 using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
 using System.ComponentModel;
 using System.Text;
 using XF.Domain.Authentications;
@@ -46,8 +48,9 @@ public class SnapshotOrderController : BaseController
     private readonly IWorkflowApplication _workflowApplication;
     private readonly IRepository<WorkflowDefinition> _workflowDefinitionRepository;
     private readonly IOrderApplication _orderApplication;
+    private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
 
-    public SnapshotOrderController(IOrderSnapshotRepository orderSnapshotRepository, IOrderSnapshotApplication orderSnapshotApplication, ISystemAreaDomainService systemAreaDomainService, ISystemDicDataCacheManager systemDicDataCacheManager, IIndustryRepository industryRepository, ISessionContext sessionContext, IWorkflowDomainService workflowDomainService, IOrderRepository orderRepository, IWorkflowApplication workflowApplication, IRepository<WorkflowDefinition> workflowDefinitionRepository, IOrderApplication orderApplication)
+    public SnapshotOrderController(IOrderSnapshotRepository orderSnapshotRepository, IOrderSnapshotApplication orderSnapshotApplication, ISystemAreaDomainService systemAreaDomainService, ISystemDicDataCacheManager systemDicDataCacheManager, IIndustryRepository industryRepository, ISessionContext sessionContext, IWorkflowDomainService workflowDomainService, IOrderRepository orderRepository, IWorkflowApplication workflowApplication, IRepository<WorkflowDefinition> workflowDefinitionRepository, IOrderApplication orderApplication, IOptionsSnapshot<AppConfiguration> appOptions)
     {
         _orderSnapshotRepository = orderSnapshotRepository;
         _orderSnapshotApplication = orderSnapshotApplication;
@@ -60,6 +63,7 @@ public class SnapshotOrderController : BaseController
         _workflowApplication = workflowApplication;
         _workflowDefinitionRepository = workflowDefinitionRepository;
         _orderApplication = orderApplication;
+        _appOptions = appOptions;
     }
 
     /// <summary>
@@ -71,6 +75,24 @@ public class SnapshotOrderController : BaseController
     public async Task<PagedDto<OrderSnapshotItemsOutDto>> GetOrderSnapshotItems([FromQuery] OrderSnapshotItemsInDto dto)
         => (await _orderSnapshotApplication.GetOrderSnapshotItems(dto).ToPagedListAsync(dto)).ToPaged();
 
+    /// <summary>
+    /// 设为重点
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPut("isemphasis")]
+    public async Task UpdateIsEmphasisAsync([FromBody] UpdateIsEmphasisInDto dto)
+        => await _orderSnapshotApplication.UpdateIsEmphasisAsync(dto);
+
+    /// <summary>
+    /// 电气焊作业申报工单集合
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("order/electrogas")]
+    public async Task<PagedDto<OrderSnapshotElectrogasItemsOutDto>> GetOrderSnapshotElectrogasItems([FromQuery] OrderSnapshotItemsInDto dto)
+        => (await _orderSnapshotApplication.GetOrderSnapshotElectrogasItems(dto).ToPagedListAsync(dto)).ToPaged();
+
     /// <summary>
     /// 随手拍所有工单页面基础信息
     /// </summary>
@@ -81,11 +103,11 @@ public class SnapshotOrderController : BaseController
         await _workflowDefinitionRepository.Queryable()
             .Where(m => m.Status == EDefinitionStatus.Enable && m.Code == "gdbl")
             .OrderByDescending(m => m.Version)
-            .Select(m => new { m.Id, m.Steps})
+            .Select(m => new { m.Id, m.Steps })
             .FirstAsync().Then(async workflowSteps =>
             {
                 steps = workflowSteps.Steps.Adapt<IList<NameCodeDto>>()
-               .ToList().Select(m => new Kv 
+               .ToList().Select(m => new Kv
                {
                    Key = m.Code,
                    Value = m.Name,
@@ -94,7 +116,7 @@ public class SnapshotOrderController : BaseController
         return new Dictionary<string, object>
         {
             { "orderStatus", EnumExts.GetDescriptions<EOrderStatus>()},
-            { "area", await _systemAreaDomainService.GetAreaKeyValue(parentId: "510300")},
+            { "area", await _systemAreaDomainService.GetAreaKeyValue(parentId: _appOptions.Value.AreaCode)},
             { "steps", steps},
             { "orderTags", _systemDicDataCacheManager.OrderTag},
             { "industry", await _industryRepository.Queryable().Select(d => new { d.Id, d.Name, }).ToListAsync()},
@@ -136,11 +158,11 @@ public class SnapshotOrderController : BaseController
     /// <returns></returns>
     [HttpGet("label/{id}")]
     public async Task<LabelOrderSnapshotDetailOutDto> GetLabelOrderSnapshotDetailAsync(string id)
-    { 
+    {
         var order = await _orderRepository.Queryable()
             .LeftJoin<OrderSnapshot>((order, snapshot) => order.Id == snapshot.Id)
             .Where((order, snapshot) => order.Id == id)
-            .Select((order, snapshot) => new LabelOrderSnapshotDetailOutDto { Id = order.Id, Title = order.Title, Lables =snapshot.Labels })
+            .Select((order, snapshot) => new LabelOrderSnapshotDetailOutDto { Id = order.Id, Title = order.Title, Lables = snapshot.Labels })
             .FirstAsync();
         var snapshot = await _orderSnapshotRepository.GetAsync(id, HttpContext.RequestAborted);
         order.Lables = snapshot.Labels;
@@ -241,7 +263,7 @@ public class SnapshotOrderController : BaseController
             { "publishStatus", EnumExts.GetDescriptions<EOrderSnapshotPublishStatus>()},
             { "acceptCode", _systemDicDataCacheManager.AcceptType.Adapt<List<Kv>>() },
             { "orderStatus", EnumExts.GetDescriptions<EOrderStatus>()},
-            { "area", await _systemAreaDomainService.GetAreaKeyValue(parentId: "510300")},
+            { "area", await _systemAreaDomainService.GetAreaKeyValue(parentId: _appOptions.Value.AreaCode)},
             { "industry", industry}
         };
     }
@@ -256,4 +278,13 @@ public class SnapshotOrderController : BaseController
     {
         await _orderApplication.HandleFromWanggeyuanToMaskAsync(id, HttpContext.RequestAborted);
     }
+
+    /// <summary>
+    /// 市民追加奖励集合
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("citizen/reward")]
+    public async Task<PagedDto<CitizenRewardOutDto>> GetCitizenRewardItemsAsync([FromQuery] CitizenRewardInDto dto)
+        => (await _orderSnapshotApplication.GetCitizenRewardItems(dto).ToPagedListAsync(dto)).ToPaged();
 }

+ 1 - 0
src/Hotline.Api/Controllers/SysController.cs

@@ -362,6 +362,7 @@ namespace Hotline.Api.Controllers
         /// <param name="dto"></param>
         /// <returns></returns>
         [HttpPost("update-dicdata")]
+        [LogFilter("修改字典数据")]
         public async Task UpdateDicData([FromBody] UpdateDicDataDto dto)
         {
             var dicData = await _sysDicDataRepository.GetAsync(dto.Id, HttpContext.RequestAborted);

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

@@ -256,6 +256,10 @@ ICallApplication callApplication,
     [AllowAnonymous]
     public async Task<ThirdPhoneOutDto> GetPhoneNumberTest()
     {
+        var order = await _orderRepository.Queryable().Includes(d => d.Workflow).FirstAsync(d => d.ReceiveProvinceNo == "");
+
+        var order1 = await _orderRepository.Queryable().Includes(d => d.Workflow).FirstAsync(d => d.ReceiveProvinceNo =="20202020202020");
+        var order2 = await _orderRepository.Queryable().Includes(d => d.Workflow).FirstAsync(d => d.ReceiveProvinceNo == "ZMHD995100002024111101317");
 
         var inDto = new ThirdTokenDto
         {

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

@@ -1,7 +1,7 @@
 {
   "AllowedHosts": "*",
   "AppConfiguration": {
-    "AppScope": "YiBin",
+    "AppScope": "ZiGong",
     "YiBin": {
       "AreaCode": "511500",
       "CallCenterType": "TianRun", //XunShi、WeiErXin、TianRun、XingTang

+ 39 - 1
src/Hotline.Application/ExportExcel/ExportApplication.cs

@@ -1,4 +1,5 @@
 
+using DocumentFormat.OpenXml.ExtendedProperties;
 using Hotline.Application.Tools;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Dtos.Order;
@@ -12,6 +13,7 @@ using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.DependencyInjection;
 using MiniExcelLibs;
 using NPOI.HPSF;
+using NPOI.SS.Formula.Functions;
 using SqlSugar;
 using System.Net.Http;
 using System.Reflection;
@@ -69,6 +71,42 @@ namespace Hotline.Application.ExportExcel
             return GetExcelStream(dto, items, func).GetExcelFile(fileName);
         }
 
+        public FileStreamResult GetExcelFile(Type typeT, Type typeD, object dto, IList<object> items, string fileName, string? totalFiledName)
+        {
+            if (totalFiledName.IsNullOrEmpty()) return GetExcelFile(typeT, typeD, dto, items, fileName);
+            var fieldsAll = typeT.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+            var fields = fieldsAll.Where(f => IsNumericType(f.FieldType)); // 只选择数值类型字段
+            var totalField = fieldsAll.Where(m => m.Name.Contains(totalFiledName)).First();
+
+            var sumDict = new Dictionary<FieldInfo, dynamic>();
+
+            foreach (var field in fields)
+            {
+                sumDict[field] = 0;
+            }
+
+            foreach (var item in items)
+            {
+                foreach (var field in fields)
+                {
+                    var value = field.GetValue(item);
+                    if (value != null)
+                    {
+                        sumDict[field] += (dynamic)value; // 使用 dynamic 累加
+                    }
+                }
+            }
+
+            var resultItem = Activator.CreateInstance(typeT);
+            totalField.SetValue(resultItem, "合计");
+            foreach (var field in fields)
+            {
+                field.SetValue(resultItem, sumDict[field]);
+            }
+            items.Add(resultItem);
+            return GetExcelFile(typeT, typeD, dto, items, fileName);
+        }
+
         public FileStreamResult GetExcelFile(Type typeT, Type typeD, object dto, IList<object> items, string fileName)
         {
             var columnInfos = typeD.GetProperty("ColumnInfos")?.GetValue(dto) as List<ColumnInfo>;
@@ -142,7 +180,7 @@ namespace Hotline.Application.ExportExcel
             return type == typeof(int) || type == typeof(float) || type == typeof(double) ||
                    type == typeof(decimal) || type == typeof(long) || type == typeof(short) ||
                    type == typeof(byte) || type == typeof(uint) || type == typeof(ulong) ||
-                   type == typeof(ushort) || type == typeof(sbyte);
+                   type == typeof(ushort) || type == typeof(sbyte) || type == typeof(double?);
         }
     }
 }

+ 1 - 0
src/Hotline.Application/ExportExcel/IExportApplication.cs

@@ -27,6 +27,7 @@ namespace Hotline.Application.ExportExcel
         FileStreamResult GetExcelFile<T, D>(ExportExcelDto<D> dto, IList<T> items,string fileName, Func<IList<T>, T>? func = null);
 
         FileStreamResult GetExcelFile(Type typeT, Type typeD, object dto, IList<object> items, string fileName);
+        FileStreamResult GetExcelFile(Type typeT, Type typeD, object dto, IList<object> items, string fileName, string? totalFiledName);
 
         /// <summary>
         /// 导入数据

+ 2 - 0
src/Hotline.Application/Mappers/SnapshotMapperConfigs.cs

@@ -90,6 +90,8 @@ public class SnapshotMapperConfigs : IRegister
             .Map(m => m.MemberName, n => n.MemberName)
             .Map(m => m.MemberMobile, n => n.MemberMobile)
             .Map(m => m.CommunityId, n => n.OrgId)
+            .Map(m => m.CommunityName, n => n.OrgName)
+            .Map(m => m.CommunityFullName, n => n.OrgFullName)
             .Map(m => m.NetworkRemark, n => n.ReplyContent);
     }
 }

+ 1 - 1
src/Hotline.Application/Orders/Handlers/OrderScreenHandler/OrderScreenNextWorkflowHandler.cs

@@ -83,7 +83,7 @@ public class OrderScreenNextWorkflowHandler : INotificationHandler<NextStepNotif
                                     screenDto.Content = notification.Dto.Opinion;
 									screenDto.Files = new List<Share.Dtos.File.FileDto>();
                                     screenDto.FileJson = screenDto.ProvinceFileJson;
-									if (screenDto.ProvinceFileJson.Any())
+									if (screenDto.ProvinceFileJson != null && screenDto.ProvinceFileJson.Any())
                                     {
                                         var fileIds = screenDto.ProvinceFileJson.Select(x => x.Id).ToList();
 										screenDto.Files = await _fileRepository.GetFilesAsync(fileIds, cancellationToken);

+ 9 - 9
src/Hotline.Application/Orders/OrderApplication.cs

@@ -224,7 +224,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         _sessionContextManager = sessionContextManager;
         _orderVisitApplication = orderVisitApplication;
         _roleRepository = roleRepository;
-	}
+    }
 
     /// <summary>
     /// 更新工单办理期满时间(延期调用,其他不调用)
@@ -3485,27 +3485,27 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         var orderSecondaries = await _orderSecondaryHandlingRepository.Queryable()
             .Where(x => x.OrderId == order.Id && x.State == ESecondaryHandlingState.Apply).ToListAsync(cancellationToken);
 
-        if (screen.Any())
+        if (screen != null && screen.Any())
         {
             await _orderScreenRepository.RemoveRangeAsync(screen, false, cancellationToken);
         }
 
-        if (sendBackAudit.Any())
+        if (sendBackAudit != null && sendBackAudit.Any())
         {
             await _orderSendBackAuditRepository.RemoveRangeAsync(sendBackAudit, false, cancellationToken);
         }
 
-        if (orderDelay.Any())
+        if (orderDelay != null && orderDelay.Any())
         {
             await _orderDelayRepository.RemoveRangeAsync(orderDelay, false, cancellationToken);
         }
 
-        if (orderSecondaries.Any())
+        if (orderSecondaries != null && orderSecondaries.Any())
         {
             await _orderSecondaryHandlingRepository.RemoveRangeAsync(orderSecondaries, false, cancellationToken);
         }
 
-        if (order.Workflow.IsInCountersign)
+        if (order.Workflow != null && order.Workflow.IsInCountersign)
         {
             var workflowStep = await _workflowStepRepository.Queryable().Where(x => x.Id == order.Workflow.TopCountersignStepId)
                 .FirstAsync(cancellationToken);
@@ -4339,8 +4339,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
 
         var orderExtension = await _orderDomainService.GetOrderExtensionsAsync(dto.ReceiveProvinceNo, cancellationToken);
 
-        var order = await _orderRepository.GetAsync(d => d.ReceiveProvinceNo == dto.ReceiveProvinceNo, cancellationToken);
-
+        //  var order = await _orderRepository.GetAsync(d => d.ReceiveProvinceNo == dto.ReceiveProvinceNo, cancellationToken);
+        var order = await _orderRepository.Queryable().Includes(d => d.Workflow).FirstAsync(d => d.ReceiveProvinceNo == dto.ReceiveProvinceNo);
         //处理省下行数据,热点名称为空
         if (!string.IsNullOrEmpty(dto.HotspotId) && string.IsNullOrEmpty(dto.HotspotName))
         {
@@ -5394,7 +5394,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             }
             else if (newStep.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(newStep.RoleId))
             {
-                var role = await _roleRepository.Queryable().Includes(x=> x.Accounts).FirstAsync(x => x.Name == newStep.RoleId, cancellationToken);
+                var role = await _roleRepository.Queryable().Includes(x => x.Accounts).FirstAsync(x => x.Name == newStep.RoleId, cancellationToken);
                 foreach (var user in role.Accounts)
                 {
                     await _circularRecordDomainService.OrderSendBackCircularMessage(user.Id, user.Name, order, cancellationToken);

+ 955 - 8
src/Hotline.Application/Snapshot/BiSnapshotApplication.cs

@@ -1,16 +1,963 @@
-using Hotline.Share.Dtos.Snapshot;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using Hotline.Configurations;
+using Hotline.Orders;
+using Hotline.Settings;
+using Hotline.Settings.Hotspots;
+using Hotline.Share.Attributes;
+using Hotline.Share.Dtos.Snapshot;
+using Hotline.Share.Enums.FlowEngine;
+using Hotline.Share.Enums.Order;
+using Hotline.Share.Enums.Snapshot;
+using Hotline.Share.Tools;
+using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
+using Hotline.Tools;
+using Mapster;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+using SqlSugar;
+using XF.Domain.Authentications;
 using XF.Domain.Dependency;
+using XF.Domain.Exceptions;
+using XF.Domain.Repository;
+using static NPOI.SS.Format.CellNumberFormatter;
 
 namespace Hotline.Application.Snapshot;
 public class BiSnapshotApplication : IBiSnapshotApplication, IScopeDependency
 {
-    public Task<SnapshotStatisticsOutDto> GetSnapshotStatisticsAsync(SnapshotStatisticsInDto dto, CancellationToken token)
+    private readonly IOrderSnapshotRepository _orderSnapshotRepository;
+    private readonly IRedPackRecordRepository _redPackRecordRepository;
+    private readonly IIndustryRepository _industryRepository;
+    private readonly IIndustryCaseRepository _industryCaseRepository;
+    private readonly IRedPackAuditRepository _redPackAuditRepository;
+    private readonly IRepository<Hotspot> _hotspotTypeRepository;
+    private readonly ISessionContext _sessionContext;
+    private readonly IOrderRepository _orderRepository;
+    private readonly ICommunityInfoRepository _communityInfoRepository;
+    private readonly IRepository<SystemArea> _systemAreaRepository;
+    private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
+
+    public BiSnapshotApplication(IOrderSnapshotRepository orderSnapshotRepository, IRedPackRecordRepository redPackRecordRepository, IIndustryRepository industryRepository, IIndustryCaseRepository industryCaseRepository, IRedPackAuditRepository redPackAuditRepository, IRepository<Hotspot> hotspotTypeRepository, ISessionContext sessionContext, IOrderRepository orderRepository, ICommunityInfoRepository communityInfoRepository, IRepository<SystemArea> systemAreaRepository, IOptionsSnapshot<AppConfiguration> appOptions)
+    {
+        _orderSnapshotRepository = orderSnapshotRepository;
+        _redPackRecordRepository = redPackRecordRepository;
+        _industryRepository = industryRepository;
+        _industryCaseRepository = industryCaseRepository;
+        _redPackAuditRepository = redPackAuditRepository;
+        _hotspotTypeRepository = hotspotTypeRepository;
+        _sessionContext = sessionContext;
+        _orderRepository = orderRepository;
+        _communityInfoRepository = communityInfoRepository;
+        _systemAreaRepository = systemAreaRepository;
+        _appOptions = appOptions;
+    }
+
+    public ISugarQueryable<HotspotStatisticsOutDto> GetHotspotStatistics(HotspotStatisticsInDto dto)
+    {
+        var IsCenter = _sessionContext.OrgIsCenter;
+        string count = "2";
+        string countx = string.Empty;
+        if (dto.HotspotCode.NotNullOrEmpty())
+        {
+            count = (dto.HotspotCode.Length + 2).ToString();
+            countx = dto.HotspotCode.Length.ToString();
+        }
+        return _hotspotTypeRepository.Queryable()
+        .LeftJoin<Order>((it, o) => it.Id == o.HotspotId)
+        .LeftJoin<OrderSnapshot>((it, o, s) => o.Id == s.Id)
+        .Where((it, o, s) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && s.Id != null)
+        .WhereIF(dto.HotspotCode.IsNullOrEmpty(), (it, o) => o.Id != null)
+        .WhereIF(dto.HotspotCode.NotNullOrEmpty(), (it, o) => it.ParentId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>(countx)) == dto.HotspotCode)
+        .WhereIF(IsCenter == false, (it, o) => o.ActualHandleOrgCode.StartsWith(_sessionContext.RequiredOrgId))
+        .GroupBy((it, o) => new { Id = it.Id.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>(count)) })
+        .Select((it, o) => new
+        {
+            HotspotCode = it.Id.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>(count)),
+            SumCount = SqlFunc.AggregateCount(it.HotSpotName)
+        })
+        .MergeTable()
+        .LeftJoin<Hotspot>((x, q) => x.HotspotCode == q.Id)
+        .Select((x, q) => new HotspotStatisticsOutDto
+        {
+            HotspotCode = x.HotspotCode,
+            SumCount = x.SumCount,
+            HotspotName = q.HotSpotName,
+            HasChild = SqlFunc.Subqueryable<Hotspot>().Where(d => d.ParentId == x.HotspotCode).Any()
+        });
+    }
+
+    /// <summary>
+    /// 热点类型小类统计明细
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    public ISugarQueryable<HotspotStatisticsDetailsOutDto> HotspotStatisticsDetail([FromQuery] HotspotStatisticsDetailsInDto dto)
+    {
+        var IsCenter = _sessionContext.OrgIsCenter;
+        IsCenter = true;
+        var query = _orderRepository.Queryable()
+            .Includes(d => d.OrderVisits)
+            .Where(d => d.CreationTime >= dto.StartTime && d.CreationTime <= dto.EndTime)
+            .WhereIF(dto.HotspotCode.NotNullOrEmpty(), d => d.HotspotId.StartsWith(dto.HotspotCode))
+            .WhereIF(IsCenter == false, d => d.ActualHandleOrgCode.StartsWith(_sessionContext.RequiredOrgId))
+            .Select(d => new HotspotStatisticsDetailsOutDto
+            {
+                OrderScreenStatus = SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == d.Id).OrderByDesc(q => q.CreationTime).Select(q => q.Status), //x.OrderScreens.FirstOrDefault().Status,
+            }, true);
+        return query;
+    }
+
+    /// <summary>
+    /// 市民红包审批统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="requestAborted"></param>
+    /// <returns></returns>
+    /// <exception cref="NotImplementedException"></exception>
+    [ExportExcel("市民红包审核统计")]
+    public IList<RedPackStatisticsOutDto> GetRedPackAuditStatistics(RedPackStatisticsInDto dto)
+    {
+        var industries = _industryRepository.Queryable(includeDeleted: true)
+            .LeftJoin<IndustryCase>((industry, industryCase) => industry.Id == industryCase.IndustryId && industryCase.IsEnable == true)
+            .Select((industry, industryCase) => new RedPackStatisticsOutDto
+            {
+                Id = industry.Id,
+                Name = industry.Name,
+                CaseId = industryCase.Id,
+                CaseName = industryCase.Name,
+                ShouldAmount = industryCase.CitizenReadPackAmount == null ? industry.CitizenReadPackAmount : industryCase.CitizenReadPackAmount,
+            }).ToList();
+
+        var redPackOutDto = _redPackAuditRepository.Queryable(includeDeleted: true)
+            .LeftJoin<OrderSnapshot>((audit, snapshot) => audit.OrderId == snapshot.Id)
+            .LeftJoin<RedPackRecord>((audit, snapshot, record) => record.RedPackAuditId == audit.Id)
+            .LeftJoin<SupplementRecord>((audit, snapshot, record, supplement) => supplement.RedPackAuditId == audit.Id)
+            .Where((audit, snapshot) => audit.CreationTime >= dto.StartTime && audit.CreationTime <= dto.EndTime)
+            .GroupBy((audit, snapshot) => new { snapshot.IndustryCase, snapshot.IndustryId, snapshot.IndustryName })
+            .Select((audit, snapshot, record, supplement) => new RedPackStatisticsOutDto
+            {
+                Id = snapshot.IndustryId,
+                Name = snapshot.IndustryName,
+                CaseId = snapshot.IndustryCase,
+                ApprovalAmount = SqlFunc.AggregateSum(SqlFunc.IIF(audit.Status == ERedPackAuditStatus.Agree, audit.ApprovedAmount, 0)), //审批同意总金额
+                ApprovalCount = SqlFunc.AggregateSum(SqlFunc.IIF(audit.Status == ERedPackAuditStatus.Agree, 1, 0)), // 审批同意总个数
+                SentAmount = SqlFunc.AggregateSum(SqlFunc.IIF(audit.IsSend == true, audit.AcutalAmount, 0)), // 发送成功金额
+                SentCount = SqlFunc.AggregateSum(SqlFunc.IIF(audit.IsSend == true, 1, 0)), // 发送成功个数
+                SendFailAmount = SqlFunc.AggregateSum(SqlFunc.IIF(record.DistributionState == EReadPackSendStatus.Fail, record.Amount, 0)), //发送失败金额
+                SendFailCount = SqlFunc.AggregateSum(SqlFunc.IIF(record.DistributionState == EReadPackSendStatus.Fail, 1, 0)), // 发送失败个数
+                PendingAmount = SqlFunc.AggregateSum(SqlFunc.IIF(record.DistributionState == EReadPackSendStatus.Unsend, audit.ApprovedAmount, 0)), // 待发金额
+                PendingCount = SqlFunc.AggregateSum(SqlFunc.IIF(record.DistributionState == EReadPackSendStatus.Unsend, 1, 0)), // 待发个数
+                SupplementAmount = SqlFunc.AggregateSum(supplement.ReplenishAmount), // 补充红包金额
+                SupplementCount = SqlFunc.AggregateCount(supplement.Id), // 补充红包数
+            }).ToList();
+
+        foreach (var industry in industries)
+        {
+            var item = redPackOutDto
+                .WhereIF(industry.CaseId != null, m => m.CaseId == industry.CaseId)
+                .WhereIF(industry.CaseId == null, m => m.Id == industry.Id)
+                .FirstOrDefault();
+
+            var config = new TypeAdapterConfig();
+            config.ForType<RedPackStatisticsOutDto, RedPackStatisticsOutDto>()
+                .Ignore(dest => dest.CaseId)
+                .Ignore(dest => dest.CaseName)
+                .Ignore(dest => dest.ShouldAmount);
+            item?.Adapt(industry, config);
+            if (industry.CaseId == null)
+            {
+                industry.IndustryName = $"{industry.Name}({industry.ShouldAmount?.ToString("f2")})";
+                industry.IndustryType = 1;
+                industry.IndustryId = industry.Id;
+            }
+            else
+            {
+                industry.IndustryType = 2;
+                industry.IndustryId = industry.CaseId;
+                if (industry.CaseName == industry.Name)
+                    industry.IndustryName = $"{industry.Name}({industry.ShouldAmount?.ToString("f2")})";
+                else
+                {
+                    industry.IndustryName = $"{industry.Name}-{industry.CaseName}({industry.ShouldAmount?.ToString("f2")})";
+                }
+            }
+        }
+        return industries;
+    }
+
+    public ISugarQueryable<RedPackStatisticsDetailsOutDto> GetRedPackAuditStatisticsDetails(RedPackStatisticsDetailsInDto dto)
+    {
+        dto.ValidateObject();
+        dto.FieldName = dto.FieldName.ToLower();
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => order.Id == snapshot.Id)
+            .LeftJoin<RedPackAudit>((snapshot, order, audit) => snapshot.Id == audit.OrderId)
+            .LeftJoin<RedPackRecord>((snapshot, order, audit, record) => audit.Id == record.RedPackAuditId)
+            .LeftJoin<SupplementRecord>((snapshot, order, audit, record, supplement) => audit.Id == supplement.RedPackAuditId)
+            .Where((snapshot, order, audit) => audit.CreationTime >= dto.StartTime && audit.CreationTime <= dto.EndTime)
+            .WhereIF(dto.IndustryType == 1, (snapshot, order, audit) => snapshot.IndustryId == dto.IndustryId)
+            .WhereIF(dto.IndustryType == 2, (snapshot, order, audit) => snapshot.IndustryCase == dto.IndustryId);
+        query = dto.FieldName switch
+        {
+            "approvalamount" => query.Where((snapshot, order, audit) => audit.Status == ERedPackAuditStatus.Agree),
+            "approvalcount" => query.Where((snapshot, order, audit) => audit.Status == ERedPackAuditStatus.Agree),
+            "sentamount" => query.Where((snapshot, order, audit) => audit.IsSend == true),
+            "sentcount" => query.Where((snapshot, order, audit) => audit.IsSend == true),
+            "sendfailamount" => query.Where((snapshot, order, audit, record) => record.DistributionState == EReadPackSendStatus.Fail),
+            "sendfailcount" => query.Where((snapshot, order, audit, record) => record.DistributionState == EReadPackSendStatus.Fail),
+            "pendingamount" => query.Where((snapshot, order, audit, record) => record.DistributionState == EReadPackSendStatus.Unsend),
+            "pendingcount" => query.Where((snapshot, order, audit, record) => record.DistributionState == EReadPackSendStatus.Unsend),
+            "supplementamount" => query.Where((snapshot, order, audit, record, supplement) => supplement.Id != null),
+            "supplementcount" => query.Where((snapshot, order, audit, record, supplement) => supplement.Id != null),
+            _ => throw new UserFriendlyException($"不支持输入字段: {dto.FieldName}")
+        };
+        return query.Select((snapshot, order, audit, record, supplement) => new RedPackStatisticsDetailsOutDto
+        {
+            CreationTime = order.CreationTime
+        }, true);
+    }
+
+    public async Task<SnapshotStatisticsOutDto> GetSnapshotStatisticsAsync(SnapshotStatisticsInDto dto, CancellationToken token)
+    {
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => order.Id == snapshot.Id)
+            .LeftJoin<RedPackAudit>((snapshot, order, redPackAudit) => snapshot.Id == redPackAudit.OrderId)
+            .LeftJoin<SpecialRedPackAudit>((snapshot, order, redPackAudit, special) => snapshot.Id == special.OrderId)
+            .LeftJoin<RedPackGuiderAudit>((snapshot, order, redPackAudit, special, guiderAudit) => snapshot.Id == guiderAudit.OrderId)
+            .LeftJoin<RedPackRecord>((snapshot, order, redPackAudit, special, guiderAudit, record) => redPackAudit.Id == record.RedPackAuditId)
+            .LeftJoin<OrderSecondaryHandling>((snapshot, order, redPackAudit, special, guiderAudit, record, second) => snapshot.Id == second.OrderId)
+            .LeftJoin<OrderSpecial>((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial) => snapshot.Id == orderSpecial.OrderId)
+            .LeftJoin<SystemOrganize>((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => order.ActualHandleOrgCode == organize.Id)
+            .Where((snapshot) => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime)
+            .Select((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => new SnapshotStatisticsOutDto
+            {
+                WZSLFWNJS = SqlFunc.AggregateSum(SqlFunc.IIF(order.HotspotName == "非受理范围", 1, 0)), // 未在受理范围内件数,
+                SSPZ12345JS = SqlFunc.AggregateSum(SqlFunc.IIF(order.SourceChannelCode == "SJP12345", 1, 0)), // 随手拍转12345件数,
+                SLFWNZJS = SqlFunc.AggregateSum(SqlFunc.IIF(order.HotspotName != "非受理范围" && order.SourceChannelCode == "SJP12345", 1, 0)), // 受理范围内总件数,
+                SLFWNPGWGYSXSNHFJS = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.IsGuidSystemCallBack == true && snapshot.GuidSystemCallBackTime.Value.AddHours(-4) > snapshot.SendGuidSystemTime, 1, 0)), // 受理范围内派给网格员四小时内回复件数,
+                SLFWNPGWGYCGSXSHFJS = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.IsGuidSystemCallBack == true && snapshot.GuidSystemCallBackTime.Value.AddHours(-4) <= snapshot.SendGuidSystemTime, 1, 0)), // 受理范围内派给网格员超过四小时回复件数
+                SLFWNPGWGYWHFJS = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.IsGuidSystemCallBack == false, 1, 0)), // 受理范围内派给网格员未回复件数
+                SLFWNA12345ZPGGBMJS = SqlFunc.AggregateSum(SqlFunc.IIF(organize.OrgType == EOrgType.City && snapshot.SendGuidSystemTime == null, 1, 0)), //受理范围内按12345直派给各部门件数,
+                SLFWNA12345ZPGGQXJS = SqlFunc.AggregateSum(SqlFunc.IIF(organize.OrgType == EOrgType.County && snapshot.SendGuidSystemTime == null, 1, 0)), //受理范围内按12345直派给各区县件数
+                ZXYB = SqlFunc.AggregateSum(SqlFunc.IIF(order.FileOrgIsCenter == true, 1, 0)), // 中心已办
+                BMYB = SqlFunc.AggregateSum(SqlFunc.IIF(order.FileOrgIsCenter == false, 1, 0)), // 部门已办
+                //SLFWMYD = 0, //受理范围满意度
+                MYL = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(order.OrgProcessingResults, "key", "1") || SqlFunc.JsonListObjectAny(order.OrgProcessingResults, "key", "2"), 0, 1)), // 满意量
+                BMYL = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(order.OrgProcessingResults, "key", "1") || SqlFunc.JsonListObjectAny(order.OrgProcessingResults, "key", "2"), 1, 0)), // 不满意量
+                SPBTYHBGS = SqlFunc.AggregateSum(SqlFunc.IIF(redPackAudit.Status == ERedPackAuditStatus.Refuse, 1, 0)), // 审批不同意红包个数
+                SPTYHBGS = SqlFunc.AggregateSum(SqlFunc.IIF(redPackAudit.Status == ERedPackAuditStatus.Agree, 1, 0)), // 审批同意红包个数
+                TSHBSP = 0, //特殊红包审批统计
+                SPTYGS = SqlFunc.AggregateSum(SqlFunc.IIF(special.Status == ERedPackAuditStatus.Agree, 1, 0)), //审批同意个数
+                YFJE = SqlFunc.AggregateSum(SqlFunc.IIF(special.IsSend == true, special.AcutalAmount, 0)), // 已发金额
+                JSHFFWGJLGS = 0, //局审核发放网格员奖励个数
+                SPTYWGYHBGS = SqlFunc.AggregateSum(SqlFunc.IIF(guiderAudit.LevelTwoStatus == ERedPackAuditStatus.Agree, 1, 0)), //审批同意(网格员)红包个数
+                SPBTYWGYHBGS = SqlFunc.AggregateSum(SqlFunc.IIF(guiderAudit.LevelOneStatus == ERedPackAuditStatus.Refuse || guiderAudit.LevelTwoStatus == ERedPackAuditStatus.Refuse, 1, 0)),  //审批不同意(网格员)红包个数
+                SMJLZE = SqlFunc.AggregateSum(redPackAudit.AcutalAmount), // 市民奖励总额
+                SMYFFJLZE = SqlFunc.AggregateSum(SqlFunc.IIF(redPackAudit.IsSend == true, redPackAudit.AcutalAmount, 0)),  // 市民已发放奖励总额
+                SMDFFJLZE = SqlFunc.AggregateSum(SqlFunc.IIF(redPackAudit.IsSend == false, redPackAudit.ApprovedAmount, 0)),  // 市民待发奖励总额
+                YFG = SqlFunc.AggregateSum(SqlFunc.IIF(redPackAudit.IsSend == true, 1, 0)), //已发(个)
+                WFLXG = SqlFunc.AggregateSum(SqlFunc.IIF(record.FailCase == ERedPackPickupFailCase.NotContact, 1, 0)), // 无法联系(个)
+                WJHBG = SqlFunc.AggregateSum(SqlFunc.IIF(record.FailCase == ERedPackPickupFailCase.Excuse, 1, 0)),  // 婉拒红包(个)
+                WGYYFJLJE = SqlFunc.AggregateSum(SqlFunc.IIF(guiderAudit.LevelTwoStatus == ERedPackAuditStatus.Agree, guiderAudit.AcutalAmount, 0)), //网格员应发奖励金额
+                WGYYFFJLZE = SqlFunc.AggregateSum(SqlFunc.IIF(guiderAudit.IsSend == true, guiderAudit.AcutalAmount, 0)), // 网格员已发放奖励总额
+                WGYDFFJLZE = SqlFunc.AggregateSum(SqlFunc.IIF(guiderAudit.LevelTwoStatus == ERedPackAuditStatus.Agree && guiderAudit.IsSend == false, guiderAudit.ApprovedAmount, 0)), // 网格员待发放奖励总额
+                WGYKKZEYF = 0, // 网格员扣款总额(已发)
+                WGYKKZEDF = 0, // 网格员扣款总额(待发)
+                SLFWNDBMHQJJS = SqlFunc.AggregateSum(SqlFunc.IIF(order.CounterSignType != null, 1, 0)), // 受理范围内多部门会签件件数
+                SLFWNRXZXGDJS = SqlFunc.AggregateSum(SqlFunc.IIF(order.FileOrgIsCenter == true, 1, 0)), // 受理范围内热线中心归档件数
+                RXZXFQHQJJS = SqlFunc.AggregateSum(SqlFunc.IIF(order.CounterSignType != null && order.CounterSignType == ECounterSignType.Center, 1, 0)), // 热线中心发起会签件件数
+                AQYH = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.IsDangerDepartment == true, 1, 0)), // 安全隐患
+                YWCAQYHZG = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.IsRectifyDepartment == true, 1, 0)), // 已完成安全隐患整改
+                SQYQGDJS = SqlFunc.AggregateSum(SqlFunc.IIF(order.OrderDelays.Count(m => m.DelayState == EDelayState.Pass) > 0, 1, 0)), // 申请延期工单件数
+                SQYQGDCS = SqlFunc.AggregateSum(SqlFunc.IIF(order.OrderDelays.Count() > 0, order.OrderDelays.Count(m => m.DelayState == EDelayState.Pass), 0)), // 申请延期工单次数
+                CQJ = SqlFunc.AggregateSum(SqlFunc.IIF(order.Status >= EOrderStatus.Filed && order.ExpiredTime < order.FiledTime, 1, 0)), // 超期件
+                ECBLJSTHBM = SqlFunc.AggregateSum(SqlFunc.IIF(second.State == ESecondaryHandlingState.Handled && second.ApplyOrgId != "001", 1, 0)), // 二次办理件数 - 退回部门
+                ECBLJSHFBMYCB = SqlFunc.AggregateSum(SqlFunc.IIF(second.State == ESecondaryHandlingState.Handled, 1, 0)), // 二次办理件数-回访不满意重办
+                ECBLJSTTDYYJBM = SqlFunc.AggregateSum(SqlFunc.IIF(second.State == ESecondaryHandlingState.Handled, 1, 0)), // 二次办理件数-特提到原一级部门
+                ECBLJSHFMY = SqlFunc.AggregateSum(SqlFunc.IIF(second.State == ESecondaryHandlingState.Handled && (SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "5" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "4" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "-1" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "0"), 1, 0)), // 二次办理件数-回访满意
+                // ECBLGDMYL = , // 二次办理工单满意率
+                ECBLGDJSTMBMHFMYD = SqlFunc.AggregateSum(SqlFunc.IIF(second.State == ESecondaryHandlingState.Handled && second.ApplyOrgId != "001" && (SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "5" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "4" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "-1" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "0"), 1, 0)), // 二次办理工单件数-退回部门回访满意
+                // ECBLGDMYLTHBM = , // 二次办理工单满意率-退回部门
+                // ECBLGDMYLHFBMYCB = 0, // 二次办理工单满意率-回访不满意重办
+
+                TTDYYJBMJS = SqlFunc.AggregateSum(SqlFunc.IIF(orderSpecial.State == 1 && orderSpecial.SpecialType == ESpecialType.Special && orderSpecial.NextStepName == "一级部门", 1, 0)), // 特提到原一级部门件数
+                TTDPDZJS = SqlFunc.AggregateSum(SqlFunc.IIF(orderSpecial.State == 1 && orderSpecial.SpecialType == ESpecialType.Special && orderSpecial.NextStepName == "派单组", 1, 0)), // 特提到派单组件数
+                QTTTJS = SqlFunc.AggregateSum(SqlFunc.IIF(orderSpecial.State == 1 && orderSpecial.SpecialType == ESpecialType.Special && (orderSpecial.NextStepName != "一级部门" || orderSpecial.NextStepName != "派单组"), 1, 0)), // 其他特提件数
+
+
+            });
+        return await query.FirstAsync();
+    }
+
+    public ISugarQueryable<SnapshotStatisticsDetailOutDto> GetSnapshotStatisticsDetail(SnapshotStatisticsDetailInDto dto)
+    {
+        dto.FieldName = dto.FieldName.ToUpper();
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => order.Id == snapshot.Id)
+            .LeftJoin<RedPackAudit>((snapshot, order, redPackAudit) => snapshot.Id == redPackAudit.OrderId)
+            .LeftJoin<SpecialRedPackAudit>((snapshot, order, redPackAudit, special) => snapshot.Id == special.OrderId)
+            .LeftJoin<RedPackGuiderAudit>((snapshot, order, redPackAudit, special, guiderAudit) => snapshot.Id == guiderAudit.OrderId)
+            .LeftJoin<RedPackRecord>((snapshot, order, redPackAudit, special, guiderAudit, record) => redPackAudit.Id == record.RedPackAuditId)
+            .LeftJoin<OrderSecondaryHandling>((snapshot, order, redPackAudit, special, guiderAudit, record, second) => snapshot.Id == second.OrderId)
+            .LeftJoin<OrderSpecial>((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial) => snapshot.Id == orderSpecial.OrderId)
+            .LeftJoin<SystemOrganize>((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => order.ActualHandleOrgCode == organize.Id)
+            .Where((snapshot, order) => order.CreationTime >= dto.StartTime && order.CreationTime <= dto.EndTime);
+        query = dto.FieldName switch
+        {
+            "WZSLFWNJS" => query.Where((snapshot, order) => order.SourceChannelCode != "SSP"),
+            "SSPZ12345JS" => query.Where((snapshot, order) => order.SourceChannelCode != "SSP"),
+            "SLFWNZJS" => query.Where((snapshot, order) => order.HotspotName != "非受理范围" && order.SourceChannelCode == "SJP12345"),
+            "SLFWNPGWGYSXSNHFJS" => query.Where((snapshot, order) => snapshot.IsGuidSystemCallBack == true && snapshot.GuidSystemCallBackTime!.Value.AddHours(-4) <= snapshot.SendGuidSystemTime),
+            "SLFWNPGWGYCGSXSHFJS" => query.Where((snapshot, order) => snapshot.IsGuidSystemCallBack == true && snapshot.GuidSystemCallBackTime!.Value.AddHours(-4) <= snapshot.SendGuidSystemTime),
+            "SLFWNPGWGYWHFJS" => query.Where((snapshot, order) => snapshot.IsGuidSystemCallBack == false),
+            "SLFWNA12345ZPGGBMJS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => organize.OrgType == EOrgType.County && snapshot.SendGuidSystemTime == null),
+            "SLFWNA12345ZPGGQXJS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => organize.OrgType == EOrgType.County && snapshot.SendGuidSystemTime == null),
+            "ZXYB" => query.Where((snapshop, order) => order.FileOrgIsCenter == true),
+            "BMYB" => query.Where((snapshop, order) => order.FileOrgIsCenter == false),
+            "MYL" => query.Where((snapshot, order) => SqlFunc.JsonListObjectAny(order.OrgProcessingResults, "key", "-1") || SqlFunc.JsonListObjectAny(order.OrgProcessingResults, "key", "3") || SqlFunc.JsonListObjectAny(order.OrgProcessingResults, "key", "4") || SqlFunc.JsonListObjectAny(order.OrgProcessingResults, "key", "5")),
+            "BMYL" => query.Where((snapshot, order) => SqlFunc.JsonListObjectAny(order.OrgProcessingResults, "key", "1") || SqlFunc.JsonListObjectAny(order.OrgProcessingResults, "key", "2")),
+            "SPBTYHBGS" => query.Where((snapshot, order, redPackAudit) => redPackAudit.Status == ERedPackAuditStatus.Refuse),
+            "SPTYHBGS" => query.Where((snapshot, order, redPackAudit) => redPackAudit.Status == ERedPackAuditStatus.Agree),
+            "TSHBSP" => query,
+            "SPTYGS" => query.Where((snapshot, order, redPackAudit, special) => special.Status == ERedPackAuditStatus.Agree),
+            "YFJE" => query.Where((snapshot, order, redPackAudit, special) => special.IsSend == true),
+            "SPTYWGYHBGS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit) => guiderAudit.LevelTwoStatus == ERedPackAuditStatus.Agree),
+            "SPBTYWGYHBGS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit) => guiderAudit.LevelOneStatus == ERedPackAuditStatus.Refuse || guiderAudit.LevelTwoStatus == ERedPackAuditStatus.Refuse),
+            "SMYFFJLZE" => query.Where((snapshot, order, redPackAudit, special, guiderAudit) => redPackAudit.IsSend == true),
+            "SMDFFJLZE" => query.Where((snapshot, order, redPackAudit, special, guiderAudit) => redPackAudit.IsSend == false),
+            "YFG" => query.Where((snapshot, order, redPackAudit, special, guiderAudit) => redPackAudit.IsSend == true),
+            "WFLXG" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => record.FailCase == ERedPackPickupFailCase.NotContact),
+            "WJHBG" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => record.FailCase == ERedPackPickupFailCase.Excuse),
+            "WGYYFJLJE" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => guiderAudit.LevelTwoStatus == ERedPackAuditStatus.Agree),
+            "WGYYFFJLZE" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => guiderAudit.IsSend == true),
+            "WGYDFFJLZE" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => guiderAudit.LevelTwoStatus == ERedPackAuditStatus.Agree && guiderAudit.IsSend == false),
+            "WGYKKZEYF" => query,
+            "WGYKKZEDF" => query,
+            "SLFWNDBMHQJJS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => order.CounterSignType != null),
+            "SLFWNRXZXGDJS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => order.FileOrgIsCenter == true),
+            "RXZXFQHQJJS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => order.CounterSignType != null && order.CounterSignType == ECounterSignType.Center),
+            "AQYH" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => snapshot.IsDangerDepartment == true),
+            "YWCAQYHZG" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => snapshot.IsRectifyDepartment == true),
+            "SQYQGDJS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => order.OrderDelays.Count(m => m.DelayState == EDelayState.Pass) > 0),
+            "SQYQGDCS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => order.OrderDelays.Count() > 0),
+            "CQJ" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => order.Status >= EOrderStatus.Filed && order.ExpiredTime < order.FiledTime),
+            "ECBLJSTHBM" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => second.State == ESecondaryHandlingState.Handled && second.ApplyOrgId != "001"),
+            "ECBLJSHFBMYCB" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => second.State == ESecondaryHandlingState.Handled),
+            "ECBLJSTTDYYJBM" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => second.State == ESecondaryHandlingState.Handled),
+            "ECBLJSHFMY" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => second.State == ESecondaryHandlingState.Handled && (SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "5" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "4" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "-1" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "0")),
+            "ECBLGDJSTMBMHFMYD" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => second.State == ESecondaryHandlingState.Handled && second.ApplyOrgId != "001" && (SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "5" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "4" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "-1" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "0")),
+            "TTDYYJBMJS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => orderSpecial.State == 1 && orderSpecial.SpecialType == ESpecialType.Special && orderSpecial.NextStepName == "一级部门"),
+            "TTDPDZJS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => orderSpecial.State == 1 && orderSpecial.SpecialType == ESpecialType.Special && orderSpecial.NextStepName == "派单组"),
+            "QTTTJS" => query.Where((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => orderSpecial.State == 1 && orderSpecial.SpecialType == ESpecialType.Special && (orderSpecial.NextStepName != "一级部门" || orderSpecial.NextStepName != "派单组")),
+            _ => throw new UserFriendlyException("入参错误:" + dto.FieldName + " 未实现")
+        };
+
+        return query.Select((snapshot, order, redPackAudit, special, guiderAudit, record, second, orderSpecial, organize) => new SnapshotStatisticsDetailOutDto
+        {
+            CreationTime = order.CreationTime
+        }, true);
+    }
+
+    /// <summary>
+    /// 办件统计-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    /// <exception cref="NotImplementedException"></exception>
+    public ISugarQueryable<SnapshotProcessingStatisticsOutDto> GetSnapshotProcessingStatistics(SnapshotProcessingStatisticsInDto dto)
+    {
+        bool IsCenter = _sessionContext.OrgIsCenter;
+        var orgLevel = _sessionContext.OrgLevel;
+        string orgLevelStr = (_sessionContext.RequiredOrgId.Length + 3).ToString();
+
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
+            .LeftJoin<OrderSendBackAudit>((snapshot, order, back) => snapshot.Id == back.OrderId && back.State == ESendBackAuditState.End)
+            .LeftJoin<OrderVisit>((snapshot, order, back, visit) => snapshot.Id == visit.OrderId && visit.VisitState == EVisitState.Visited)
+            .LeftJoin<OrderSecondaryHandling>((snapshot, order, back, visit, second) => snapshot.Id == second.OrderId && second.State == ESecondaryHandlingState.End)
+            .Where(snapshot => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime)
+            .WhereIF(dto.IndustryId.NotNullOrEmpty(), snapshot => snapshot.IndustryId == dto.IndustryId)
+            .GroupBy((snapshot, order) => new
+            {
+                OrgCode = order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6"))
+            })
+            .Select((snapshot, order, back, visit, second) => new SnapshotProcessingStatisticsOutDto()
+            {
+                OrgCode = order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                YbOrderCountNum = SqlFunc.AggregateCount(SqlFunc.IIF(order.Status >= EOrderStatus.Filed, 1, 0)),
+                ZbOrderCountNum = SqlFunc.AggregateCount(SqlFunc.IIF(order.Status < EOrderStatus.Filed, 1, 0)),
+                ReceiveIn20Minutes = SqlFunc.AggregateCount(SqlFunc.IIF(order.ActualHandleStepCreateTime != null && order.ActualHandleStepCreateTime.Value.AddMinutes(-20) <= order.CreationTime, 1, 0)),
+                ReceiveOut20Minutes = SqlFunc.AggregateCount(SqlFunc.IIF(order.ActualHandleStepCreateTime == null || order.ActualHandleStepCreateTime.Value.AddMinutes(-20) > order.CreationTime, 1, 0)),
+                BackNum = SqlFunc.AggregateCount(SqlFunc.IIF(back.OrderId != null && back.OrderId != "", 1, 0)),
+                TotalHandleDuration = SqlFunc.AggregateSum(order.HandleDuration),
+                End3Day = SqlFunc.AggregateSum(SqlFunc.IIF(order.FiledTime != null && order.FiledTime.Value.AddDays(-3) < order.CreationTime, 1, 0)),
+                End3To5Day = SqlFunc.AggregateSum(SqlFunc.IIF(order.FiledTime != null && order.FiledTime.Value.AddDays(-3) > order.CreationTime && order.FiledTime.Value.AddDays(-5) < order.CreationTime, 1, 0)),
+                End5To7Day = SqlFunc.AggregateSum(SqlFunc.IIF(order.FiledTime != null && order.FiledTime.Value.AddDays(-5) > order.CreationTime && order.FiledTime.Value.AddDays(-7) < order.CreationTime, 1, 0)),
+                End7Day = SqlFunc.AggregateSum(SqlFunc.IIF(order.FiledTime != null && order.FiledTime.Value.AddDays(-7) < order.CreationTime, 1, 0)),
+                OnTimeCount = SqlFunc.AggregateSum(SqlFunc.IIF(order.FiledTime <= order.ExpiredTime, 1, 0)),
+                SatisfiedCount = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "1") || SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "2"), 1, 0)),
+                NoSatisfiedCount = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "1") || SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "2"), 0, 1)),
+                SecondNum = SqlFunc.AggregateCount(second.Id)
+            })
+            .MergeTable()
+            .LeftJoin<SystemOrganize>((it, o) => it.OrgCode == o.Id)
+            .Select((it, o) => new SnapshotProcessingStatisticsOutDto()
+            {
+                OrgName = o.Name,
+                OrgCode = it.OrgCode,
+                YbOrderCountNum = it.YbOrderCountNum,
+                ZbOrderCountNum = it.ZbOrderCountNum,
+                ReceiveIn20Minutes = it.ReceiveIn20Minutes,
+                ReceiveOut20Minutes = it.ReceiveOut20Minutes,
+                BackNum = it.BackNum,
+                TotalHandleDuration = it.TotalHandleDuration,
+                End3Day = it.End3Day,
+                End3To5Day = it.End3To5Day,
+                End5To7Day = it.End5To7Day,
+                End7Day = it.End7Day,
+                OnTimeCount = it.OnTimeCount,
+                SatisfiedCount = it.SatisfiedCount,
+                NoSatisfiedCount = it.NoSatisfiedCount,
+                SecondNum = it.SecondNum
+            });
+
+        return query;
+    }
+
+    public ISugarQueryable<SnapshotProcessingStatisticsDetailsOutDto> GetSnapshotProcessingStatisticsDetails(SnapshotProcessingStatisticsDetailsInDto dto)
+    {
+        dto.FieldName = dto.FieldName.ToLower();
+        var IsCenter = _sessionContext.OrgIsCenter;
+        IsCenter = true;
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
+            .LeftJoin<OrderSendBackAudit>((snapshot, order, back) => snapshot.Id == back.OrderId && back.State == ESendBackAuditState.End)
+            .LeftJoin<OrderVisit>((snapshot, order, back, visit) => snapshot.Id == visit.OrderId && visit.VisitState == EVisitState.Visited)
+            .LeftJoin<OrderSecondaryHandling>((snapshot, order, back, visit, second) => snapshot.Id == second.OrderId && second.State == ESecondaryHandlingState.End)
+            .Where((snapshot, order, back) => order.CreationTime >= dto.StartTime && order.CreationTime <= dto.EndTime && order.ActualHandleOrgCode.StartsWith(dto.OrgId))
+            .WhereIF(IsCenter == false, (snapshot, order, back) => order.ActualHandleOrgCode.StartsWith(_sessionContext.RequiredOrgId))
+            .WhereIF(dto.IndustryId.NotNullOrEmpty(), (snapshot, order, back) => snapshot.IndustryId == dto.IndustryId);
+
+        query = dto.FieldName switch
+        {
+            "ybordercountnum" => query.Where((snapshot, order, back) => order.Status >= EOrderStatus.Filed),
+            "zbordercountnum" => query.Where((snapshot, order, back) => order.Status < EOrderStatus.Filed),
+            "receivein20minutes" => query.Where((snapshot, order, back) => order.ActualHandleStepCreateTime != null && order.ActualHandleStepCreateTime.Value.AddMinutes(-20) <= order.CreationTime),
+            "receiveout20minutes" => query.Where((snapshot, order, back) => order.ActualHandleStepCreateTime == null || order.ActualHandleStepCreateTime.Value.AddMinutes(-20) > order.CreationTime),
+            "backnum" => query.Where((snapshot, order, back) => back.OrderId != null && back.OrderId != ""),
+            "end3day" => query.Where((snapshot, order, back) => order.FiledTime != null && order.FiledTime.Value.AddDays(-3) < order.CreationTime),
+            "end3to5day" => query.Where((snapshot, order, back) => order.FiledTime != null && order.FiledTime.Value.AddDays(-3) > order.CreationTime && order.FiledTime.Value.AddDays(-5) < order.CreationTime),
+            "end5to7day" => query.Where((snapshot, order, back) => order.FiledTime != null && order.FiledTime.Value.AddDays(-5) > order.CreationTime && order.FiledTime.Value.AddDays(-7) < order.CreationTime),
+            "end7day" => query.Where((snapshot, order, back) => order.FiledTime != null && order.FiledTime.Value.AddDays(-7) < order.CreationTime),
+            "satisfiedcount" => query.Where((snapshot, order, back, visit) => SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "1") || SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "2")),
+            "nosatisfiedcount" => query.Where((snapshot, order, back, visit) => SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "1") || SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "2")),
+            "secondnum" => query.Where((snapshot, order, back, visit, second) => second.Id != null || second.Id != ""),
+            _ => throw new UserFriendlyException($"入参: {dto.FieldName} 异常")
+        };
+        return query.Select((snapshot, order, back, visit, second) => new SnapshotProcessingStatisticsDetailsOutDto
+        {
+            OrderScreenStatus = SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == order.Id).OrderByDesc(q => q.CreationTime).Select(q => q.Status),
+        }, true);
+    }
+
+    public ISugarQueryable<GuiderWorkStatisticsOutDto> GetGuiderWorkStatisticsAsync(GuiderWorkStatisticsInDto dto)
+    {
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .Where(snapshot => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime && snapshot.MemberName != null)
+            .GroupBy(snapshot => new { snapshot.MemberName, snapshot.MemberMobile })
+            .Select(snapshot => new GuiderWorkStatisticsOutDto
+            {
+                MemberMobile = snapshot.MemberMobile,
+                MemberName = snapshot.MemberName,
+                ReplyIn4HourCount = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.ReplyResultType == EGuiderSystemReplyType.Field && snapshot.GuidSystemCallBackTime.Value.AddHours(-4) <= snapshot.SendGuidSystemTime, 1, 0)),
+                ReplyOut4HourCount = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.ReplyResultType == EGuiderSystemReplyType.Field && snapshot.GuidSystemCallBackTime.Value.AddHours(-4) > snapshot.SendGuidSystemTime, 1, 0)),
+                UnReplyCount = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.ReplyResultType != EGuiderSystemReplyType.Field, 1, 0)),
+            });
+
+        return query;
+    }
+
+    public ISugarQueryable<GuiderWorkStatisticsDetailsOutDto> GetGuiderWorkStatisticsDetails(GuiderWorkStatisticsDetailsInDto dto)
+    {
+        dto.FieldName = dto.FieldName.ToLower();
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => order.Id == snapshot.Id)
+            .Where(snapshot => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime && snapshot.MemberMobile == dto.MemberMobile);
+
+        query = dto.FieldName switch
+        {
+            "replyin4hourcount" => query.Where(snapshot => snapshot.ReplyResultType == EGuiderSystemReplyType.Field && snapshot.GuidSystemCallBackTime.Value.AddHours(-4) <= snapshot.SendGuidSystemTime),
+            "replyout4hourcount" => query.Where(snapshot => snapshot.ReplyResultType == EGuiderSystemReplyType.Field && snapshot.GuidSystemCallBackTime.Value.AddHours(-4) > snapshot.SendGuidSystemTime),
+            "unreplycount" => query.Where(snapshot => snapshot.ReplyResultType != EGuiderSystemReplyType.Field),
+            _ => throw new UserFriendlyException($"入参: {dto.FieldName} 异常")
+        };
+        return query.Select((snapshot, order) => new GuiderWorkStatisticsDetailsOutDto
+        {
+        }, true);
+    }
+
+    public ISugarQueryable<HotspotDataStatisticsOutDto> GetHotspotDataStatisticsAsync(HotspotDataStatisticsInDto dto)
+    {
+        var isCenter = _sessionContext.OrgIsCenter;
+        var query = _hotspotTypeRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((hotspot, order) => order.HotspotSpliceName != null && (hotspot.HotSpotName == order.HotspotSpliceName || order.HotspotSpliceName.Contains(hotspot.HotSpotName)) && order.IsDeleted == false && order.CreationTime >= dto.StartTime && order.CreationTime <= dto.EndTime)
+            .WhereIF(isCenter == false, (hotspot, order) => order.ActualHandleOrgCode == _sessionContext.RequiredOrgId)
+            .Where(hotspot => hotspot.ParentId == null)
+            .GroupBy((hotspot, order) => new { hotspot.Id, hotspot.HotSpotName })
+            .Select((hotspot, order) => new HotspotDataStatisticsOutDto
+            {
+                Name = hotspot.HotSpotName,
+                OrderCount = SqlFunc.AggregateSum(SqlFunc.IIF(order.Id != null, 1, 0)),
+            });
+        return query;
+    }
+
+    public ISugarQueryable<GuiderWorkLogsOutDto> GetGuiderWorkLogs(GuiderWorkLogsInDto dto)
+    {
+        var query = _orderSnapshotRepository.Queryable()
+            .LeftJoin<Order>((snapshot, order) => order.Id == snapshot.Id)
+            .Where((snapshot, order) => snapshot.IsGuidSystemCallBack == true)
+            .WhereIF(dto.MemberMobile.NotNullOrEmpty(), snapshot => snapshot.MemberMobile.Contains(dto.MemberMobile))
+            .WhereIF(dto.BeginCreationTime != null && dto.EndCreationTime != null, snapshot => snapshot.CreationTime >= dto.BeginCreationTime && snapshot.CreationTime <= dto.EndCreationTime)
+            .WhereIF(dto.MemberName.NotNullOrEmpty(), snapshot => snapshot.MemberName.Contains(dto.MemberName))
+            .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order) => order.No.Contains(dto.No))
+            .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.Title))
+            .WhereIF(dto.NetworkENumber.NotNullOrEmpty(), (snapshot, order) => snapshot.NetworkENumber.Contains(dto.NetworkENumber))
+            .WhereIF(dto.Status != null, (snapshot, order) => order.Status == dto.Status)
+            .OrderByDescending(snapshot => snapshot.CreationTime)
+            .Select(snapshot => new GuiderWorkLogsOutDto(), true);
+        return query;
+    }
+
+    public ISugarQueryable<DuplicateItemsOutDto> GetDuplicateItems(DuplicateItemsInDto dto)
+    {
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => order.Id == snapshot.Id)
+            .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order) => order.No.Contains(dto.No))
+            .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.Title))
+            .WhereIF(dto.FromName.NotNullOrEmpty(), (snapshot, order) => order.FromName.Contains(dto.FromName))
+            .WhereIF(dto.FromPhone.NotNullOrEmpty(), (snapshot, order) => order.FromPhone.Contains(dto.FromPhone))
+            .WhereIF(dto.BeginCreationTime != null && dto.EndCreationTime != null, (snapshot, order) => order.CreationTime >= dto.BeginCreationTime && order.CreationTime <= dto.EndCreationTime)
+            .WhereIF(dto.BeginExpiredTime != null && dto.EndExpiredTime != null, (snapshot, order) => order.ExpiredTime >= dto.BeginExpiredTime && order.ExpiredTime <= dto.EndExpiredTime)
+            .WhereIF(dto.ActualHandleOrgName.NotNullOrEmpty(), (snapshot, order) => order.ActualHandleOrgName == dto.ActualHandleOrgName)
+            .WhereIF(dto.AcceptType.NotNullOrEmpty(), (snapshot, order) => order.AcceptType == dto.AcceptType)
+            .WhereIF(dto.HotspotName.NotNullOrEmpty(), (snapshot, order) => order.HotspotName == dto.HotspotName)
+            .WhereIF(dto.AcceptorName.NotNullOrEmpty(), (snapshot, order) => order.AcceptorName == dto.AcceptorName)
+            .WhereIF(dto.IndustryId.NotNullOrEmpty(), (snapshot, order) => snapshot.IndustryId == dto.IndustryId)
+            .Select((snapshot, order) => new DuplicateItemsOutDto(), true);
+        return query;
+    }
+
+    public ISugarQueryable<CommunityStatisticsOutDto> GetCommunityStatistics(CommunityStatisticsInDto dto)
+    {
+        var query = _communityInfoRepository.Queryable(includeDeleted: true)
+        .LeftJoin<OrderSnapshot>((it, s) => s.CommunityFullName.Contains(it.FullName) && s.CreationTime >= dto.StartTime && s.CreationTime <= dto.EndTime)
+        .WhereIF(dto.CommunityCode.IsNullOrEmpty(), (it, s) => it.ParentCode == null)
+        .WhereIF(dto.CommunityCode.NotNullOrEmpty(), (it, s) => it.ParentCode == dto.CommunityCode)
+        .WhereIF(dto.IndustryId.NotNullOrEmpty(), (it, s) => s.IndustryId == dto.IndustryId)
+        .GroupBy((it, s) => new { it.Name, it.Id })
+        .Select((it, s) => new CommunityStatisticsOutDto
+        {
+            CommunityCode = it.Id,
+            CommunityName = it.Name,
+            CommunityFullName = it.FullName,
+            SumCount = SqlFunc.Subqueryable<OrderSnapshot>().Where(snapshot => snapshot.CommunityFullName!.Contains(it.FullName)).Count(),
+            HasChild = SqlFunc.Subqueryable<CommunityInfo>().Where(c => c.ParentCode == it.Id).Any()
+        });
+#if DEBUG
+        var sql = query.ToSqlString();
+#endif
+        return query;
+    }
+
+    public ISugarQueryable<CommunityStatisticsDetailsOutDto> GetCommunityStatisticsDetails(CommunityStatisticsDetailsInDto dto)
+    {
+        var communityFullName = _communityInfoRepository.Queryable().Where(c => c.Id == dto.CommunityCode).Select(c => c.FullName).First();
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
+            .Where((snapshot, order) => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime && snapshot.CommunityFullName!.Contains(communityFullName))
+            .WhereIF(dto.IndustryId.NotNullOrEmpty(), (snapshot, order) => snapshot.IndustryId == dto.IndustryId)
+            .Select((snapshot, order) => new CommunityStatisticsDetailsOutDto(), true);
+#if DEBUG
+        var sql = query.ToSqlString();
+#endif
+        return query;
+    }
+
+    [ExportExcel("随手拍区域统计", "County")]
+    public ISugarQueryable<CountyRedPackStatisticsOutDto> GetCountyRedPackStatistics(CountyRedPackStatisticsInDto dto)
+    {
+        var parentId = _appOptions.Value.AreaCode;
+        var query = _systemAreaRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((area, order) => order.County == area.AreaName && order.CreationTime >= dto.StartTime && order.CreationTime <= dto.EndTime && order.County != null)
+            .LeftJoin<OrderSnapshot>((area, order, snapshot) => snapshot.Id == order.Id && (dto.IndustryId.IsNullOrEmpty() || snapshot.IndustryId == dto.IndustryId))
+            .LeftJoin<RedPackAudit>((area, order, snapshot, audit) => snapshot.Id == audit.OrderId)
+            .LeftJoin<RedPackRecord>((area, order, snapshot, audit, record) => audit.Id == record.RedPackAuditId)
+            .LeftJoin<SupplementRecord>((area, order, snapshot, audit, record, supplement) => supplement.RedPackAuditId == audit.Id)
+            .LeftJoin<RedPackGuiderAudit>((area, order, snapshot, audit, record, supplement, guiderAudit) => guiderAudit.OrderId == snapshot.Id)
+            .LeftJoin<RedPackRecord>((area, order, snapshot, audit, record, supplement, guiderAudit, guiderRecord) => guiderAudit.Id == guiderRecord.RedPackAuditId)
+            .LeftJoin<Industry>((area, order, snapshot, audit, record, supplement, guiderAudit, guiderRecord, industry) => snapshot.IndustryId == industry.Id)
+            .Where((area, order, snapshot, audit, record, supplement, guiderAudit, guiderRecord) => area.ParentId == parentId || area.AreaName == "外地")
+            .GroupBy((area, order, snapshot, audit, record, supplement, guiderAudit, guiderRecord) => new { area.AreaName, order.County })
+            .Select((area, order, snapshot, audit, record, supplement, guiderAudit, guiderRecord, industry) => new CountyRedPackStatisticsOutDto
+            {
+                County = area.AreaName,
+                JuBaoZongShu = SqlFunc.AggregateSum(SqlFunc.IIF(industry.IndustryType == EIndustryType.Clue, 1, 0)),
+                YiBanJieShu = SqlFunc.AggregateSum(SqlFunc.IIF(order.Status >= EOrderStatus.Filed && industry.IndustryType == EIndustryType.Clue, 1, 0)),
+                ShiMinShenHeTongGuoShu = SqlFunc.AggregateSum(SqlFunc.IIF(record.PeopleType == EReadPackUserType.Citizen && audit.Status == ERedPackAuditStatus.Agree, 1, 0)),
+                ShiMinZongJinE = SqlFunc.AggregateSum(SqlFunc.IIF(record.PeopleType == EReadPackUserType.Citizen && audit.Status == ERedPackAuditStatus.Agree, audit.ApprovedAmount, 0)),
+                ShiMinYiLing = SqlFunc.AggregateSum(SqlFunc.IIF(record.PeopleType == EReadPackUserType.Citizen && record.PickupStatus == ERedPackPickupStatus.Received, record.Amount, 0)),
+                ShiMinDaiLing = SqlFunc.AggregateSum(SqlFunc.IIF(record.PeopleType == EReadPackUserType.Citizen && record.PickupStatus == ERedPackPickupStatus.Unreceived, record.Amount, 0)),
+                ShiMinDaiBuLing = SqlFunc.AggregateSum(SqlFunc.IIF(record.PeopleType == EReadPackUserType.Citizen && supplement.Id != null, supplement.ReplenishAmount, 0)),
+                WangGeYuanZongJianShu = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.IsDeal == true, 1, 0)),
+                WangGeYuanShenHeTongGuoShu = SqlFunc.AggregateSum(SqlFunc.IIF(guiderAudit.LevelTwoStatus == ERedPackAuditStatus.Agree, 1, 0)),
+                WangGeYuanZongJinE = SqlFunc.AggregateSum(SqlFunc.IIF(guiderAudit.LevelTwoStatus == ERedPackAuditStatus.Agree, guiderAudit.ApprovedAmount, 0)),
+                WangGeYuanYiLing = SqlFunc.AggregateSum(SqlFunc.IIF(guiderRecord.PickupStatus == ERedPackPickupStatus.Received, guiderRecord.Amount, 0)),
+                WangGeYuanDaiLing = SqlFunc.AggregateSum(SqlFunc.IIF(guiderRecord.PickupStatus == ERedPackPickupStatus.Unreceived, guiderRecord.Amount, 0)),
+            });
+
+#if DEBUG
+        var sql = query.ToSqlString();
+#endif
+        return query;
+    }
+
+    /// <summary>
+    /// 部门考核统计-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    /// <exception cref="NotImplementedException"></exception>
+    public ISugarQueryable<SnapshotDepartmentStatisticsOutDto> GetSnapshotDepartmentStatistics(SnapshotDepartmentStatisticsInDto dto)
+    {
+        bool IsCenter = _sessionContext.OrgIsCenter;
+        var orgLevel = _sessionContext.OrgLevel;
+        string orgLevelStr = (_sessionContext.RequiredOrgId.Length + 3).ToString();
+
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
+            .LeftJoin<OrderSendBackAudit>((snapshot, order, back) => snapshot.Id == back.OrderId && back.State == ESendBackAuditState.End)
+            .LeftJoin<OrderVisit>((snapshot, order, back, visit) => snapshot.Id == visit.OrderId && visit.VisitState == EVisitState.Visited)
+            .LeftJoin<OrderSecondaryHandling>((snapshot, order, back, visit, second) => snapshot.Id == second.OrderId && second.State == ESecondaryHandlingState.End)
+            .Where((snapshot, order) => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime && order.ActualHandleOrgCode != null)
+            .GroupBy((snapshot, order) => new
+            {
+                OrgCode = order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6"))
+            })
+            .Select((snapshot, order, back, visit, second) => new SnapshotDepartmentStatisticsOutDto()
+            {
+                OrgCode = order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                OrderCountNum = SqlFunc.AggregateCount(snapshot.Id),
+                ReceiveIn4Hour = SqlFunc.AggregateCount(SqlFunc.IIF(order.ActualHandleStepCreateTime != null && order.ActualHandleStepCreateTime.Value.AddHours(-4) <= order.CreationTime, 1, 0)),
+                TimeOutField = SqlFunc.AggregateCount(SqlFunc.IIF(order.Status >= EOrderStatus.Filed && order.FiledTime > order.ExpiredTime, 1, 0)),
+                TimeOutNoField = SqlFunc.AggregateCount(SqlFunc.IIF(order.Status < EOrderStatus.Filed && DateTime.Now > order.ExpiredTime, 1, 0)),
+                OnTimeCount = SqlFunc.AggregateSum(SqlFunc.IIF(order.FiledTime <= order.ExpiredTime, 1, 0)),
+                SatisfiedCount = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "1") || SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "2"), 1, 0)),
+                NoSatisfiedCount = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "1") || SqlFunc.JsonListObjectAny(visit.NowEvaluate, "key", "2"), 0, 1)),
+                SecondNum = SqlFunc.AggregateCount(second.Id),
+                FirstFiledOrderCount = SqlFunc.AggregateCount(SqlFunc.IIF(order.Status >= EOrderStatus.Filed && second.Id == null, 1, 0)),
+                SecondSatisfied = SqlFunc.AggregateCount(SqlFunc.IIF(second.State == ESecondaryHandlingState.Handled && (SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "1" || SqlFunc.JsonField(order.OrgProcessingResults, "Key") == "2"), 1, 0)),
+            })
+            .MergeTable()
+            .LeftJoin<SystemOrganize>((it, o) => it.OrgCode == o.Id)
+            .Select((it, o) => new SnapshotDepartmentStatisticsOutDto()
+            {
+                OrgName = o.Name,
+                OrgCode = it.OrgCode,
+                ReceiveIn4Hour = it.ReceiveIn4Hour,
+                TimeOutField = it.TimeOutField,
+                TimeOutNoField = it.TimeOutNoField,
+                OnTimeCount = it.OnTimeCount,
+                SatisfiedCount = it.SatisfiedCount,
+                NoSatisfiedCount = it.NoSatisfiedCount,
+                SecondNum = it.SecondNum,
+                FirstFiledOrderCount = it.FirstFiledOrderCount,
+                SecondSatisfied = it.SecondSatisfied
+            });
+
+        return query;
+    }
+
+    public ISugarQueryable<SnapshotDepartmentAveTimeStatisticsOutDto> GetSnapshotDepartmentAveTimeStatistics(SnapshotDepartmentAveTimeStatisticsInDto dto)
+    {
+        bool IsCenter = _sessionContext.OrgIsCenter;
+        var orgLevel = _sessionContext.OrgLevel;
+        string orgLevelStr = (_sessionContext.RequiredOrgId.Length + 3).ToString();
+
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
+            .LeftJoin<OrderSendBackAudit>((snapshot, order, back) => snapshot.Id == back.OrderId && back.State == ESendBackAuditState.End)
+            .LeftJoin<OrderVisit>((snapshot, order, back, visit) => snapshot.Id == visit.OrderId && visit.VisitState == EVisitState.Visited)
+            .LeftJoin<OrderSecondaryHandling>((snapshot, order, back, visit, second) => snapshot.Id == second.OrderId && second.State == ESecondaryHandlingState.End)
+            .Where((snapshot, order) => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime && order.ActualHandleOrgCode != null)
+            .GroupBy((snapshot, order) => new
+            {
+                OrgCode = order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6"))
+            })
+            .Select((snapshot, order, back, visit, second) => new SnapshotDepartmentAveTimeStatisticsOutDto()
+            {
+                OrgCode = order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                OrderCountNum = SqlFunc.AggregateCount(snapshot.Id),
+                TotalSeconds = SqlFunc.AggregateSum(order.AllDuration),
+            })
+            .MergeTable()
+            .LeftJoin<SystemOrganize>((it, o) => it.OrgCode == o.Id)
+            .Select((it, o) => new SnapshotDepartmentAveTimeStatisticsOutDto()
+            {
+                OrgName = o.Name,
+                OrgCode = it.OrgCode,
+                TotalSeconds = it.TotalSeconds,
+                OrderCountNum = it.OrderCountNum
+            });
+
+        return query;
+    }
+
+    public ISugarQueryable<SnapshotDepartmentAveTimeStatisticsDetailsOutDto> GetSnapshotDepartmentAveTimeStatisticsDtails(SnapshotDepartmentAveTimeStatisticsDetailsInDto dto)
+    {
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
+            .Where((snapshot, order) => order.CreationTime >= dto.StartTime && order.CreationTime <= dto.EndTime && order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) == dto.OrgCode)
+            .Select((snapshot, order) => new SnapshotDepartmentAveTimeStatisticsDetailsOutDto(), true);
+        return query;
+    }
+
+    [ExportExcel("检查合规统计", "OrgName")]
+    public ISugarQueryable<CompliantStatisticsOutDto> GetCompliantStatistics(CompliantStatisticsInDto dto)
+    {
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
+            .LeftJoin<OrderSendBackAudit>((snapshot, order, back) => snapshot.Id == back.OrderId && back.State == ESendBackAuditState.End)
+            .LeftJoin<OrderVisit>((snapshot, order, back, visit) => snapshot.Id == visit.OrderId && visit.VisitState == EVisitState.Visited)
+            .LeftJoin<OrderSecondaryHandling>((snapshot, order, back, visit, second) => snapshot.Id == second.OrderId && second.State == ESecondaryHandlingState.End)
+            .Where((snapshot, order) => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime && order.ActualHandleOrgCode != null)
+            .GroupBy((snapshot, order) => new
+            {
+                OrgCode = order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6"))
+            })
+            .Select((snapshot, order, back, visit, second) => new CompliantStatisticsOutDto()
+            {
+                OrgCode = order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                OrderCountNum = SqlFunc.AggregateCount(snapshot.Id),
+                First = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.CompliantType == ECompliantType.First, 1, 0)),
+                Second = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.CompliantType == ECompliantType.Second, 1, 0)),
+                Third = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.CompliantType == ECompliantType.Third, 1, 0)),
+                Not = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.CompliantType == ECompliantType.Not, 1, 0)),
+            })
+            .MergeTable()
+            .LeftJoin<SystemOrganize>((it, o) => it.OrgCode == o.Id)
+            .Select((it, o) => new CompliantStatisticsOutDto()
+            {
+                OrgName = o.Name,
+                OrgCode = it.OrgCode,
+                OrderCountNum = it.OrderCountNum,
+                First = it.First,
+                Second = it.Second,
+                Third = it.Third,
+                Not = it.Not
+            });
+
+        return query;
+    }
+
+    public ISugarQueryable<CompliantStatisticsDetailsOutDto> GetCompliantStatisticsDetails(CompliantStatisticsDetailsInDto dto)
+    {
+        dto.FieldName = dto.FieldName.ToLower();
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => order.Id == snapshot.Id)
+            .Where((snapshot, order) => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime && order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) == dto.OrgCode);
+
+        query = dto.FieldName switch
+        {
+            "ordercountnum" => query,
+            "first" => query.Where(snapshot => snapshot.CompliantType == ECompliantType.First),
+            "second" => query.Where(snapshot => snapshot.CompliantType == ECompliantType.Second),
+            "third" => query.Where(snapshot => snapshot.CompliantType == ECompliantType.Third),
+            "not" => query.Where(snapshot => snapshot.CompliantType == ECompliantType.Not),
+            _ => throw new UserFriendlyException($"入参: {dto.FieldName} 异常")
+        };
+        return query.Select((snapshot, order) => new CompliantStatisticsDetailsOutDto
+        {
+        }, true);
+    }
+
+    [ExportExcel("随手拍重办统计")]
+    public List<Dictionary<string, object>> GetReTransactStatistics(ReTransactStatisticsInDto dto)
+    {
+        var rawData = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => order.Id == snapshot.Id)
+            .Where((snapshot, order) => snapshot.SpecialReasonId != null && snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime)
+            .GroupBy((snapshot, order) => new
+            {
+                OrgCode = order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                SpecialReasonId = snapshot.SpecialReasonId,
+                snapshot.SpecialReasonName
+            })
+            .Select((snapshot, order) => new
+            {
+                OrgCode = order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                OrderCountNum = SqlFunc.AggregateCount(snapshot.Id),
+                SpecialReasonId = snapshot.SpecialReasonId,
+                SpecialReasonName = snapshot.SpecialReasonName
+            }, true)
+            .MergeTable()
+            .LeftJoin<SystemOrganize>((it, o) => it.OrgCode == o.Id)
+            .Select((it, o) => new
+            {
+                OrgName = o.Name,
+                OrgCode = it.OrgCode,
+                OrderCountNum = it.OrderCountNum,
+                SpecialReasonId = it.SpecialReasonId,
+                SpecialReasonName = it.SpecialReasonName
+            }).ToList();
+
+        var pivotResult = new List<Dictionary<string, object>>();
+
+        var orgGroups = rawData.GroupBy(x => new { x.OrgCode, x.OrgName });
+
+        var specialReasons = rawData
+            .Select(x => x.SpecialReasonId)
+            .Distinct()
+            .ToList();
+
+        foreach (var orgGroup in orgGroups)
+        {
+            var row = new Dictionary<string, object>
+            {
+                ["OrgName"] = orgGroup.Key.OrgName,
+                ["OrgCode"] = orgGroup.Key.OrgCode
+            };
+
+            foreach (var reason in specialReasons)
+            {
+                row[reason] = 0;
+            }
+
+            foreach (var item in orgGroup)
+            {
+                if (item.SpecialReasonId != null)
+                {
+                    row[item.SpecialReasonId] = item.OrderCountNum;
+                }
+            }
+
+            pivotResult.Add(row);
+        }
+        pivotResult.AddSumLine("OrgName");
+        return pivotResult;
+    }
+
+    [ExportExcel("随手拍重办统计")]
+    public ISugarQueryable<ReTransactStatisticsDetailsOutDto> GetReTransactStatisticsDetail(ReTransactStatisticsDetailsInDto dto)
+    {
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => order.Id == snapshot.Id)
+            .LeftJoin<OrderSpecial>((snapshot, order, special) => special.OrderId == order.Id)
+            .LeftJoin<SystemOrganize>((snapshot, order, special, org) => org.Id == special.OrgId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")))
+            .Where((snapshot, order, special) => order.CreationTime >= dto.StartTime && order.CreationTime <= dto.EndTime && order.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) == dto.OrgCode && special.Id != null && snapshot.SpecialReasonId != null && special.SpecialType == ESpecialType.ReTransact)
+            .WhereIF(dto.FieldName.NotNullOrEmpty(), (snapshot, order) => dto.FieldName == snapshot.SpecialReasonId)
+            .OrderByDescending((snapshot, order) => order.CreationTime)
+            .Select((snapshot, order, special, org) => new ReTransactStatisticsDetailsOutDto
+            {
+                ReTransactOrgName = special.OrgName, // 被重办部门
+                ReTransactOneOrgName = org.Name, // 被重办一级部门
+                ReTransactTime = special.CreationTime, // 重办时间
+                ReTransactHandlerName = special.CreatorName, // 重办操作人
+                ReTransactContent = special.Opinion // 重办理由
+            }, true);
+#if DEBUG
+        var sql = query.ToSqlString();
+#endif
+        return query;
+    }
+
+    public List<Dictionary<string, object>> GetIndustryStatistics(IndustryStatisticsInDto dto)
+    {
+        var parentId = _appOptions.Value.AreaCode;
+        var query = _systemAreaRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((area, order) => order.County == area.AreaName && order.CreationTime >= dto.StartTime && order.CreationTime <= dto.EndTime && order.County != null)
+            .LeftJoin<OrderSnapshot>((area, order, snapshot) => order.Id == snapshot.Id)
+            .Where((area, order, snapshot) => area.ParentId == parentId)
+            .GroupBy((area, order, snapshot) => new
+            {
+                IndustryId = snapshot.IndustryId,
+                snapshot.IndustryName,
+                area.AreaName
+            })
+            .Select((area, order, snapshot) => new
+            {
+                OrgName = area.AreaName,
+                OrderCountNum = SqlFunc.AggregateCount(snapshot.Id),
+                AllDuration = SqlFunc.AggregateSum(order.AllDuration),
+                IsEmphasis = SqlFunc.AggregateSum(SqlFunc.IIF(snapshot.IsEmphasis == true, 1, 0)),
+                IndustryName = snapshot.IndustryName,
+                IndustryId = snapshot.IndustryId,
+            })
+            .FullJoin<Industry>((it, o) => it.IndustryId == o.Id)
+            .Select((it, o) => new
+            {
+                IndustryName = o.Name,
+                IndustryId = o.Id,
+                OrderCountNum = it.OrderCountNum,
+                AllDuration = it.AllDuration,
+                OrgName = it.OrgName,
+            });
+#if DEBUG
+        var sql = query.ToSqlString();
+#endif
+        var rawData = query.ToList();
+        var pivotResult = new List<Dictionary<string, object>>();
+
+        var industryGroups = rawData.GroupBy(x => new { x.IndustryId, x.IndustryName }).ToList();
+
+        var orgNames = rawData
+            .Select(x => x.OrgName)
+            .Distinct()
+            .ToList();
+
+        foreach (var industryItem in industryGroups)
+        {
+            if (industryItem.Key.IndustryName == null) continue;
+            var row = new Dictionary<string, object>
+            {
+                ["IndustryName"] = industryItem.Key.IndustryName,
+                ["IndustryId"] = industryItem.Key.IndustryId,
+                ["AllDuration"] = 0,
+                ["OrderCountNum"] = 0,
+            };
+
+            foreach (var orgCode in orgNames)
+            {
+                if (orgCode != null)
+                {
+                    row[orgCode] = 0;
+                }
+            }
+
+            foreach (var item in industryItem)
+            {
+                if (item.IndustryId != null && item.OrgName != null)
+                {
+                    row[item.OrgName] = item.OrderCountNum;
+                    row["AllDuration"] = item.AllDuration;
+                    row["OrderCountNum"] = int.Parse(row["OrderCountNum"].ToString()) + item.OrderCountNum;
+                    if (item.AllDuration != null && item.AllDuration != 0)
+                        row["AllDuration"] = ((double)row["AllDuration"] + (double)item.AllDuration / 60 / 60).ToString("f2");
+                }
+            }
+
+            pivotResult.Add(row);
+        }
+        pivotResult.AddSumLine("IndustryName");
+        return pivotResult;
+    }
+
+    public ISugarQueryable<IndustryStatisticsDetailsOutDto> GetIndustryStatisticsDetails(IndustryStatisticsDetailsInDto dto)
     {
-        throw new NotImplementedException();
+        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
+            .Where((snapshot, order) => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime && snapshot.IndustryId == dto.IndustryId)
+            .WhereIF(dto.FieldName != "OrderCountNum", (Snapshot, order) => order.County == dto.FieldName)
+            .Select((snapshot, order) => new IndustryStatisticsDetailsOutDto(), true);
+        return query;
     }
 }

+ 102 - 1
src/Hotline.Application/Snapshot/IBiSnapshotApplication.cs

@@ -1,5 +1,7 @@
-using Hotline.Share.Dtos.Snapshot;
+using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.Snapshot;
 using Microsoft.AspNetCore.Http;
+using SqlSugar;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -9,5 +11,104 @@ using System.Threading.Tasks;
 namespace Hotline.Application.Snapshot;
 public interface IBiSnapshotApplication
 {
+    /// <summary>
+    /// 热点类型小统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<HotspotStatisticsOutDto> GetHotspotStatistics(HotspotStatisticsInDto dto);
+    ISugarQueryable<HotspotStatisticsDetailsOutDto> HotspotStatisticsDetail(HotspotStatisticsDetailsInDto dto);
+    IList<RedPackStatisticsOutDto> GetRedPackAuditStatistics(RedPackStatisticsInDto dto);
+    ISugarQueryable<RedPackStatisticsDetailsOutDto> GetRedPackAuditStatisticsDetails(RedPackStatisticsDetailsInDto dto);
     Task<SnapshotStatisticsOutDto> GetSnapshotStatisticsAsync(SnapshotStatisticsInDto dto, CancellationToken token);
+    ISugarQueryable<SnapshotStatisticsDetailOutDto> GetSnapshotStatisticsDetail(SnapshotStatisticsDetailInDto dto);
+
+    /// <summary>
+    /// 办件统计-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<SnapshotProcessingStatisticsOutDto> GetSnapshotProcessingStatistics(SnapshotProcessingStatisticsInDto dto);
+
+    /// <summary>
+    /// 办件统计明细-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<SnapshotProcessingStatisticsDetailsOutDto> GetSnapshotProcessingStatisticsDetails(SnapshotProcessingStatisticsDetailsInDto dto);
+
+    /// <summary>
+    /// 网格员办理情况统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<GuiderWorkStatisticsOutDto> GetGuiderWorkStatisticsAsync(GuiderWorkStatisticsInDto dto);
+
+    ISugarQueryable<GuiderWorkStatisticsDetailsOutDto> GetGuiderWorkStatisticsDetails(GuiderWorkStatisticsDetailsInDto dto);
+    ISugarQueryable<HotspotDataStatisticsOutDto> GetHotspotDataStatisticsAsync(HotspotDataStatisticsInDto dto);
+
+    /// <summary>
+    /// 网格员系统工单状态日志
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<GuiderWorkLogsOutDto> GetGuiderWorkLogs(GuiderWorkLogsInDto dto);
+    ISugarQueryable<DuplicateItemsOutDto> GetDuplicateItems(DuplicateItemsInDto dto);
+    ISugarQueryable<CommunityStatisticsOutDto> GetCommunityStatistics(CommunityStatisticsInDto dto);
+
+    /// <summary>
+    /// 社区统计-详情
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<CommunityStatisticsDetailsOutDto> GetCommunityStatisticsDetails(CommunityStatisticsDetailsInDto dto);
+
+    /// <summary>
+    /// 随手拍区域统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<CountyRedPackStatisticsOutDto> GetCountyRedPackStatistics(CountyRedPackStatisticsInDto dto);
+
+    /// <summary>
+    /// 部门考核统计-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    /// <exception cref="NotImplementedException"></exception>
+    ISugarQueryable<SnapshotDepartmentStatisticsOutDto> GetSnapshotDepartmentStatistics(SnapshotDepartmentStatisticsInDto dto);
+
+    /// <summary>
+    /// 部门平均办理时间-随手拍
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<SnapshotDepartmentAveTimeStatisticsOutDto> GetSnapshotDepartmentAveTimeStatistics(SnapshotDepartmentAveTimeStatisticsInDto dto);
+
+    ISugarQueryable<SnapshotDepartmentAveTimeStatisticsDetailsOutDto> GetSnapshotDepartmentAveTimeStatisticsDtails(SnapshotDepartmentAveTimeStatisticsDetailsInDto dto);
+
+    /// <summary>
+    /// 检查合规统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<CompliantStatisticsOutDto> GetCompliantStatistics(CompliantStatisticsInDto dto);
+
+    ISugarQueryable<CompliantStatisticsDetailsOutDto> GetCompliantStatisticsDetails(CompliantStatisticsDetailsInDto dto);
+    List<Dictionary<string, object>> GetReTransactStatistics(ReTransactStatisticsInDto dto);
+    ISugarQueryable<ReTransactStatisticsDetailsOutDto> GetReTransactStatisticsDetail(ReTransactStatisticsDetailsInDto dto);
+
+    /// <summary>
+    /// 行业统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    List<Dictionary<string, object>> GetIndustryStatistics(IndustryStatisticsInDto dto);
+
+    /// <summary>
+    /// 行业统计详情
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<IndustryStatisticsDetailsOutDto> GetIndustryStatisticsDetails(IndustryStatisticsDetailsInDto dto);
 }

+ 16 - 0
src/Hotline.Application/Snapshot/IOrderSnapshotApplication.cs

@@ -113,6 +113,13 @@ public interface IOrderSnapshotApplication
     /// <returns></returns>
     ISugarQueryable<OrderSnapshotItemsOutDto> GetOrderSnapshotItems(OrderSnapshotItemsInDto dto);
 
+    /// <summary>
+    /// 电气焊作业申请工单集合
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<OrderSnapshotElectrogasItemsOutDto> GetOrderSnapshotElectrogasItems(OrderSnapshotItemsInDto dto);
+
     /// <summary>
     /// 获取工单已经标签集合
     /// </summary>
@@ -128,4 +135,13 @@ public interface IOrderSnapshotApplication
     /// <param name="remark"></param>
     /// <returns></returns>
     Task<OrderSnapshot> UpdateSafetyAsync(string orderId, bool isSafetyDepartment, string remark);
+    ISugarQueryable<CitizenRewardOutDto> GetCitizenRewardItems(CitizenRewardInDto dto);
+
+    /// <summary>
+    /// 更新随手拍工单重办原因
+    /// </summary>
+    /// <param name="orderId"></param>
+    /// <param name="firstErrorId"></param>
+    Task UpdateSpecialReasonAsync(string orderId, string errorId, string errorName);
+    Task UpdateIsEmphasisAsync(UpdateIsEmphasisInDto dto);
 }

+ 23 - 0
src/Hotline.Application/Snapshot/Notifications/SnapshotHandler.cs

@@ -26,6 +26,7 @@ using Hotline.FlowEngine.Workflows;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 using Microsoft.Extensions.Logging;
+using Hotline.Orders.Notifications;
 
 namespace Hotline.Application.Snapshot.Notifications;
 
@@ -135,3 +136,25 @@ public class SnapshotPushNotificationHandler : INotificationHandler<PostGuiderSy
         await _snapshotApplication.PostOrderGuiderSystemAsync(notification.OrderId, cancellationToken);
     }
 }
+
+public class AddOrderSpecialHandler : INotificationHandler<AddOrderSpecialNotify>
+{
+    private readonly IOrderSnapshotApplication _orderSnapshotApplication;
+    private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+
+    public AddOrderSpecialHandler(IOrderSnapshotApplication orderSnapshotApplication, ISystemSettingCacheManager systemSettingCacheManager)
+    {
+        _orderSnapshotApplication = orderSnapshotApplication;
+        _systemSettingCacheManager = systemSettingCacheManager;
+    }
+
+    public async Task Handle(AddOrderSpecialNotify notification, CancellationToken cancellationToken)
+    {
+        if (notification.SourceChannel.Contains("随手拍") && _systemSettingCacheManager.Snapshot == true)
+        {
+            var item = notification.Reasons.FirstOrDefault();
+            if (item == null) return;
+            await _orderSnapshotApplication.UpdateSpecialReasonAsync(notification.OrderId, item.ErrorId, item.ErrorName);
+        }
+    }
+}

+ 86 - 52
src/Hotline.Application/Snapshot/RedPackApplication.cs

@@ -88,6 +88,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
         redPackAudit.AuditTime = DateTime.Now;
         redPackAudit.AuditOrgId = _sessionContext.OrgId;
         redPackAudit.AuditOrgName = _sessionContext.OrgName;
+        redPackAudit.ApprovedAmount = redPackAudit.ShouldAmount;
         var order = await _orderRepository.Queryable()
             .Where(m => m.Id == redPackAudit.OrderId)
             .Select(m => new { m.Id, m.No, m.FromName, m.FromPhone })
@@ -105,7 +106,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
                 WXOpenId = third?.OpenId,
                 No = order.No,
                 PickupStatus = ERedPackPickupStatus.Unreceived,
-                DistributionState = EReadPackSendStatus.Successful,
+                DistributionState = EReadPackSendStatus.Unsend,
             };
             if (redPackAudit.ApprovedAmount.HasValue)
                 entity.Amount = redPackAudit.ApprovedAmount.Value;
@@ -167,7 +168,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
                     PhoneNumber = order.FromPhone,
                     No = order.No,
                     PickupStatus = ERedPackPickupStatus.Unreceived,
-                    DistributionState = EReadPackSendStatus.Successful,
+                    DistributionState = EReadPackSendStatus.Unsend,
                 };
                 if (redPackAudit.ApprovedAmount.HasValue)
                     entity.Amount = redPackAudit.ApprovedAmount.Value;
@@ -258,16 +259,31 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
     {
         var beginTime = new DateTime(2024, 8, 1);
         var endTime = new DateTime(2024, 9, 30, 23, 59, 59);
-        var query = _redPackAuditRepository.Queryable()
+        var query = _redPackAuditRepository.Queryable(includeDeleted: true)
             .LeftJoin<OrderSnapshot>((redPackAudit, snapshot) => redPackAudit.OrderId == snapshot.Id)
             .LeftJoin<Order>((redPackAudit, snapshot, order) => redPackAudit.OrderId == order.Id)
             .LeftJoin<SpecialRedPackAudit>((redPackAudit, snapshot, order, special) => redPackAudit.OrderId == special.OrderId)
-            .Where((redPackAudit, snapshot, order, special) => (snapshot.IndustryName == "安全隐患" && order.OrderTagCode!.Contains("DHZY")) || (order.CreationTime >=beginTime && order.CreationTime <= endTime && redPackAudit.ApprovedAmount == 20 && order.AcceptTypeCode != "30" && snapshot.IndustryName != "电气焊作业申报"))
+            .Where((redPackAudit, snapshot, order, special) => (redPackAudit.Status == ERedPackAuditStatus.Agree && snapshot.IndustryName == "安全隐患" && order.OrderTagCode!.Contains("DHZY")) || (redPackAudit.Status == ERedPackAuditStatus.Agree && order.CreationTime >= beginTime && order.CreationTime <= endTime && redPackAudit.ApprovedAmount == 20 && order.AcceptTypeCode != "30" && snapshot.IndustryName != "电气焊作业申报"))
             .WhereIF(dto.Status == 0, (redPackAudit, snapshot, order, special) => special.Id == null)
             .WhereIF(dto.Status == 1, (redPackAudit, snapshot, order, special) => special.Status == ERedPackAuditStatus.Agree)
             .WhereIF(dto.Status == 2, (redPackAudit, snapshot, order, special) => special.Status == ERedPackAuditStatus.Refuse)
+            .WhereIF(dto.No.NotNullOrEmpty(), (redPackAudit, snapshot, order, special) => order.No!.Contains(dto.No!))
+            .WhereIF(dto.Title.NotNullOrEmpty(), (redPackAudit, snapshot, order, special) => order.Title!.Contains(dto.Title!))
+            .WhereIF(dto.FromPhone.NotNullOrEmpty(), (redPackAudit, snapshot, order, special) => order.FromPhone!.Contains(dto.FromPhone!))
+            .WhereIF(dto.BeginCreationTime.HasValue && dto.EndCreationTime.HasValue, (redPackAudit, snapshot, order, special) => order.CreationTime >= dto.BeginCreationTime && order.CreationTime <= dto.EndCreationTime)
+            .WhereIF(dto.IsDeal.HasValue, (redPackAudit, snapshot, order, special) => snapshot.IsDeal == dto.IsDeal)
+            .WhereIF(dto.IsTruth.HasValue, (redPackAudit, snapshot, order, special) => snapshot.IsTruth == dto.IsTruth)
+            .WhereIF(dto.IsTruthDepartment.HasValue, (redPackAudit, snapshot, order, special) => snapshot.IsTruthDepartment == dto.IsTruthDepartment)
+            .WhereIF(dto.BeginAuditTime.HasValue && dto.EndAuditTime.HasValue, (redPackAudit, snapshot, order, special) => redPackAudit.AuditTime >= dto.BeginAuditTime && redPackAudit.AuditTime <= dto.EndAuditTime)
+            .WhereIF(dto.BeginFiledTime.HasValue && dto.EndFiledTime.HasValue, (redPackAudit, snapshot, order, special) => order.FiledTime >= dto.BeginFiledTime && order.FiledTime <= dto.EndFiledTime)
+            .WhereIF(dto.IsIssued.HasValue, (redPackAudit, snapshot, order, special) => redPackAudit.IsSend == dto.IsIssued)
+            .WhereIF(dto.IndustryId.NotNullOrEmpty(), (redPackAudit, snapshot, order, special) => snapshot.IndustryId == dto.IndustryId)
+            .WhereIF(dto.ConfigAmount.HasValue, (redPackAudit, snapshot, order, special) => special.ShouldAmount == dto.ConfigAmount)
+            .WhereIF(dto.AcutalAmount.HasValue, (redPackAudit, snapshot, order, special) => special.AcutalAmount == dto.AcutalAmount)
+            .WhereIF(dto.ApprovedAmount.HasValue, (redPackAudit, snapshot, order, special) => special.ApprovedAmount == dto.ApprovedAmount)
+            .WhereIF(dto.IsDanger.HasValue, (redPackAudit, snapshot, order, special) => snapshot.IsDanger == dto.IsDanger)
             .OrderByDescending((redPackAudit, snapshot, order, special) => redPackAudit.CreationTime)
-                        .Select((redPackAudit, snapshot,order) => new SnapshotOrderAuditItemsOutDto
+                        .Select((redPackAudit, snapshot, order, special) => new SnapshotOrderAuditItemsOutDto
                         {
                             Id = redPackAudit.Id,
                             RedPackAuditId = redPackAudit.Id,
@@ -285,7 +301,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
                             AuditTime = redPackAudit.AuditTime,
                             ApprovedAmount = redPackAudit.ApprovedAmount,
                             AcutalAmount = redPackAudit.AcutalAmount,
-                            IsIssued = redPackAudit.IsIssued,
+                            IsIssued = redPackAudit.IsSend,
                             //RecordRemark = record.Remark,
                             County = order.County,
                             // IsRectify = s.IsRepetition
@@ -297,14 +313,14 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
                             CreationTime = order.CreationTime,
                             OrgLevelOneCode = order.OrgLevelOneCode,
                             OrgLevelOneName = order.OrgLevelOneName,
-                            AuditId = redPackAudit.AuditId,
-                            AuditName = redPackAudit.AuditName,
-                            AuditOrgId = redPackAudit.AuditOrgId,
-                            AuditOrgName = redPackAudit.AuditOrgName,
-                            AuditRemark = redPackAudit.AuditRemark,
+                            AuditId = special.AuditId,
+                            AuditName = special.AuditName,
+                            AuditOrgId = special.AuditOrgId,
+                            AuditOrgName = special.AuditOrgName,
+                            AuditRemark = special.AuditRemark,
                             //BankCardNo = record.BankCardNo,
                             //OpenBank = record.OpenBank,
-                            AuditStatus = redPackAudit.Status,
+                            AuditStatus = special.Status,
                         });
         return query;
     }
@@ -338,7 +354,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
             .WhereIF(dto.IsTruth.HasValue, (redPackAudit, order, snapshot, record, industry) => snapshot.IsTruth == dto.IsTruth)
             .WhereIF(dto.IsTruthDepartment.HasValue, (redPackAudit, order, snapshot, record, industry) => snapshot.IsTruthDepartment == dto.IsTruthDepartment)
             .WhereIF(dto.BeginAuditTime.HasValue && dto.EndAuditTime.HasValue, (redPackAudit, order, snapshot, record, industry) => redPackAudit.AuditTime <= dto.EndAuditTime && redPackAudit.AuditTime >= dto.BeginAuditTime)
-            .WhereIF(dto.IsIssued.HasValue, (redPackAudit, order, snapshot, record, industry) => redPackAudit.IsIssued == dto.IsIssued)
+            .WhereIF(dto.IsIssued.HasValue, (redPackAudit, order, snapshot, record, industry) => redPackAudit.IsSend == dto.IsIssued)
             .WhereIF(dto.IndustryId.NotNullOrEmpty(), (redPackAudit, order, snapshot, record, industry) => snapshot.IndustryId == dto.IndustryId)
             .WhereIF(dto.ConfigAmount.HasValue, (redPackAudit, order, snapshot, record, industry) => industry.CitizenReadPackAmount == dto.ConfigAmount)
             .WhereIF(dto.AcutalAmount.HasValue, (redPackAudit, order, snapshot, record, industry) => redPackAudit.AcutalAmount == dto.AcutalAmount)
@@ -364,7 +380,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
                 AuditTime = redPackAudit.AuditTime,
                 ApprovedAmount = redPackAudit.ApprovedAmount,
                 AcutalAmount = redPackAudit.AcutalAmount,
-                IsIssued = redPackAudit.IsIssued,
+                IsIssued = redPackAudit.IsSend,
                 RecordRemark = record.Remark,
                 County = order.County,
                 // IsRectify = s.IsRepetition
@@ -383,6 +399,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
                 AuditRemark = redPackAudit.AuditRemark,
                 BankCardNo = record.BankCardNo,
                 OpenBank = record.OpenBank,
+                AwardName = record.Name,
                 AuditStatus = redPackAudit.Status,
             });
         return query;
@@ -489,19 +506,25 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
     {
         var audit = await _redPackAuditRepository.GetAsync(dto.RedPackAuditId) ?? throw UserFriendlyException.SameMessage("审核记录不存在");
         audit.AcutalAmount = dto.AcutalAmount;
-        if (dto.IsSend == false)
-        {
-            await _redPackRecordRepository.Queryable()
-                .Where(m => m.RedPackAuditId == audit.Id)
-                .FirstAsync()
-                .Then(async (record) =>
-                {
-                    if (dto.FailCase != null)
-                        record.FailCase = dto.FailCase.Value;
-                    await _redPackRecordRepository.UpdateAsync(record);
-                });
-        }
+        audit.IsSend = dto.IsSend;
         audit.SendRemarks = dto.SendRemarks;
+        await _redPackRecordRepository.Queryable()
+            .Where(m => m.RedPackAuditId == audit.Id)
+            .FirstAsync()
+            .Then(async (record) =>
+            {
+                if (dto.FailCase != null)
+                {
+                    record.FailCase = dto.FailCase.Value;
+                    record.DistributionState = EReadPackSendStatus.Fail;
+                    if (record.FailCase == ERedPackPickupFailCase.Excuse)
+                        record.PickupStatus = ERedPackPickupStatus.Excuse;
+                }
+                if (dto.IsSend)
+                    record.DistributionState = EReadPackSendStatus.Successful;
+                await _redPackRecordRepository.UpdateAsync(record);
+            });
+
         await _redPackAuditRepository.UpdateAsync(audit);
     }
 
@@ -512,26 +535,29 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
     /// <returns></returns>
     public async Task UpdateRedPackRecordAsync(UpdateRedPackRecordInDto dto)
     {
-        var record = await _redPackRecordRepository.Queryable()
-            .Where(m => m.RedPackAuditId == dto.RedPackAuditId)
-            .FirstAsync() ?? throw UserFriendlyException.SameMessage("审核记录不存在");
-        record.DistributionState = EReadPackSendStatus.Successful;
-        record.PickupStatus = ERedPackPickupStatus.Received;
+        //var record = await _redPackRecordRepository.Queryable()
+        //    .Where(m => m.RedPackAuditId == dto.RedPackAuditId)
+        //    .FirstAsync() ?? throw UserFriendlyException.SameMessage("审核记录不存在");
+        //record.DistributionState = EReadPackSendStatus.Successful;
+        //record.PickupStatus = ERedPackPickupStatus.Received;
         var audit = await _redPackAuditRepository.GetAsync(dto.RedPackAuditId) ?? throw UserFriendlyException.SameMessage("审核记录不存在");
+        var orderNo = await _orderRepository.Queryable().Where(m => m.Id == audit.OrderId).Select(m => m.No).FirstAsync();
 
         dto.Adapt(audit);
+        audit.IsSend = true;
+        audit.AcutalAmount = dto.ReplenishAmount;
         await _redPackAuditRepository.UpdateAsync(audit);
-        await _redPackRecordRepository.UpdateAsync(record);
+        //await _redPackRecordRepository.UpdateAsync(record);
 
         var entity = dto.Adapt<SupplementRecord>();
         var industryName = await _orderSnapshotRepository.Queryable()
-            .Where(m => m.Id == record.OrderId)
+            .Where(m => m.Id == audit.OrderId)
             .Select(m => new { m.IndustryName, m.IndustryId })
             .FirstAsync();
-        entity.OrderId = record.OrderId;
-        entity.RedPackRecordId = record.Id;
+        entity.OrderId = audit.OrderId;
+        //entity.RedPackRecordId = record.Id;
         entity.RedPackAuditId = audit.Id;
-        entity.No = record.No;
+        entity.No = orderNo;
         entity.IndustryName = industryName.IndustryName;
         entity.IndustryId = industryName.IndustryId;
         await _supplementRecordRepository.AddAsync(entity);
@@ -549,26 +575,29 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
     /// <returns></returns>
     public async Task UpdateRedPackSpecialRecordAsync(UpdateRedPackRecordInDto dto)
     {
-        var record = await _redPackRecordRepository.Queryable()
-            .Where(m => m.RedPackAuditId == dto.RedPackAuditId)
-            .FirstAsync() ?? throw UserFriendlyException.SameMessage("审核记录不存在");
-        record.DistributionState = EReadPackSendStatus.Successful;
-        record.PickupStatus = ERedPackPickupStatus.Received;
+        //var record = await _redPackRecordRepository.Queryable()
+        //    .Where(m => m.RedPackAuditId == dto.RedPackAuditId)
+        //    .FirstAsync() ?? throw UserFriendlyException.SameMessage("审核记录不存在");
+        //record.DistributionState = EReadPackSendStatus.Successful;
+        //record.PickupStatus = ERedPackPickupStatus.Received;
         var audit = await _specialRedPackAuditRepository.GetAsync(dto.RedPackAuditId) ?? throw UserFriendlyException.SameMessage("审核记录不存在");
+        var orderNo = await _orderRepository.Queryable().Where(m => m.Id == audit.OrderId).Select(m => m.No).FirstAsync();
 
         dto.Adapt(audit);
+        audit.IsSend = true;
+        audit.AcutalAmount = dto.ReplenishAmount;
         await _specialRedPackAuditRepository.UpdateAsync(audit);
-        await _redPackRecordRepository.UpdateAsync(record);
+        //await _redPackRecordRepository.UpdateAsync(record);
 
         var entity = dto.Adapt<SupplementRecord>();
         var industryName = await _orderSnapshotRepository.Queryable()
-            .Where(m => m.Id == record.OrderId)
+            .Where(m => m.Id == audit.OrderId)
             .Select(m => new { m.IndustryName, m.IndustryId })
             .FirstAsync();
-        entity.OrderId = record.OrderId;
-        entity.RedPackRecordId = record.Id;
+        entity.OrderId = audit.OrderId;
+        //entity.RedPackRecordId = record.Id;
         entity.RedPackAuditId = audit.Id;
-        entity.No = record.No;
+        entity.No = orderNo;
         entity.IndustryName = industryName.IndustryName;
         entity.IndustryId = industryName.IndustryId;
         await _supplementRecordRepository.AddAsync(entity);
@@ -701,11 +730,11 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
         if (_specialRedPackAuditRepository.ExistByOrderId(audit.OrderId)) throw UserFriendlyException.SameMessage("已审核, 不可重复审核");
         var specialAudit = audit.Adapt<SpecialRedPackAudit>();
         if (dto.AuditTypeId.NotNullOrEmpty())
-        { 
+        {
             var specialType = _systemDic.SnapshotRedPackSpecialType.FirstOrDefault(m => m.Id == dto.AuditTypeId);
             if (specialType != null)
             {
-                specialAudit.AuditType = specialType.DicDataName;
+                specialAudit.AuditType = specialType.DicDataName.Split('|')[0];
                 specialAudit.AuditTypeCode = specialType.DicDataValue;
             }
         }
@@ -723,13 +752,19 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
         var outDto = new SnapshotOrderAuditSpecialDetailOutDto();
         var order = await _orderRepository.GetAsync(id) ?? throw new UserFriendlyException("工单不存在");
         outDto.Order = order.Adapt<SnapshotOrderAuditOrderDetailOutDto>();
-        outDto.AuditType = _systemDic.SnapshotRedPackSpecialType;
+        outDto.AuditType = _systemDic.SnapshotRedPackSpecialType.Adapt<List<SystemDicDataAmountOutDto>>();
         outDto.AuditComBox = EnumExts.GetDescriptions<ERedPackAuditStatus>().Where(m => m.Key != 0).ToList();
         var audit = await _redPackAuditRepository.GetAsync(m => m.OrderId == id);
         outDto.AuditDetail = audit.Adapt<SnapshotOrderAuditSpecialAuditDetailOutDto>();
         return outDto;
     }
 
+    /// <summary>
+    /// 获取补充发放记录基础数据
+    /// </summary>
+    /// <param name="v"></param>
+    /// <param name="orderId"></param>
+    /// <returns></returns>
     public async Task<GetRedPackRecordBaseDataOutDto> GetRedPackRecordBaseDataAsync(string orderId)
     {
         var snapshot = await _orderSnapshotRepository.Queryable()
@@ -740,7 +775,6 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
                 m.AwardBankCardNo,
                 m.AwardOpenBank,
                 m.AwardName,
-                m.AwardAmount
             })
             .FirstAsync();
         var outDto = new GetRedPackRecordBaseDataOutDto();
@@ -749,15 +783,15 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
             outDto.BankCardNo = snapshot.AwardBankCardNo;
             outDto.OpenBank = snapshot.AwardOpenBank;
             outDto.Name = snapshot.AwardName;
-            outDto.Amount = snapshot.AwardAmount;
         }
-        var audit = await _specialRedPackAuditRepository.Queryable().Where(m => m.OrderId == orderId).FirstAsync() 
+        var audit = await _specialRedPackAuditRepository.Queryable().Where(m => m.OrderId == orderId).FirstAsync()
             ?? throw new UserFriendlyException("审核记录不存在");
         if (audit != null)
         {
             outDto.AuditType = audit.AuditType;
             outDto.AuditTypeCode = audit.AuditTypeCode;
             outDto.RedPackAuditId = audit.Id;
+            outDto.Amount = audit.ApprovedAmount;
         }
         outDto.OrderId = orderId;
         outDto.ReplenishType = _systemDic.SnapshotReplenishType;

+ 3 - 0
src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs

@@ -576,6 +576,7 @@ public abstract class SnapshotApplicationBase
             return;
         }
         orderSnapshot.DeadLine = DateTime.Now.AddHours(_sysSetting.OvertimeBack);
+        orderSnapshot.SendGuidSystemTime = DateTime.Now;
         var keySecret = _sysSetting.TianQueAppKeySecret.Split('|');
 
         var token = new ThirdTokenDto
@@ -639,6 +640,8 @@ public abstract class SnapshotApplicationBase
                 await _fileDomainService.GetNetworkFileAsync(file, orderSnapshot.Id, token);
             }
         }
+        orderSnapshot.IsGuidSystemCallBack = true;
+        orderSnapshot.GuidSystemCallBackTime = DateTime.Now;
         await _orderSnapshotRepository.UpdateAsync(orderSnapshot);
         // 网格员办结
         if (orderSnapshot.ReplyResultType == EGuiderSystemReplyType.Field)

+ 112 - 1
src/Hotline.Application/Snapshot/SnapshotOrderApplication.cs

@@ -436,10 +436,67 @@ public class SnapshotOrderApplication : IOrderSnapshotApplication, IScopeDepende
     {
         var query = _orderSnapshotRepository.Queryable()
             .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
+            .LeftJoin<Industry>((snapshot, order, industry) => snapshot.IndustryId == industry.Id)
             .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order) => order.No.Contains(dto.No))
             .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.Title))
             .WhereIF(dto.ActualHandleOrgName.NotNullOrEmpty(), (snapshot, order) => order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
-            .Select((snapshot, order) => new OrderSnapshotItemsOutDto
+            .WhereIF(dto.AcceptType.NotNullOrEmpty(), (snapshot, order) => order.AcceptType == dto.AcceptType)
+            .WhereIF(dto.AcceptorName.NotNullOrEmpty(), (snapshot, order) => order.AcceptorName == dto.AcceptorName)
+            .WhereIF(dto.FromPhone.NotNullOrEmpty(), (snapshot, order) => order.FromPhone == dto.FromPhone)
+            .WhereIF(dto.FromName.NotNullOrEmpty(), (snapshot, order) => order.FromName == dto.FromName)
+            .WhereIF(dto.BeginExpiredTime.HasValue && dto.EndExpiredTime.HasValue, (snapshot, order) => order.ExpiredTime >= dto.BeginExpiredTime && order.ExpiredTime <= dto.EndExpiredTime)
+            .WhereIF(dto.BeginCreationTime.HasValue && dto.EndCreationTime.HasValue, (snapshot, order) => order.CreationTime >= dto.BeginCreationTime && order.CreationTime <= dto.EndCreationTime)
+            .WhereIF(dto.Status.HasValue, (snapshot, order) => order.Status == dto.Status)
+            .WhereIF(dto.County.NotNullOrEmpty(), (snapshot, order) => order.County == dto.County)
+            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == true, (snapshot, order) => order.OrderScreens.Count() > 0)
+            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == false, (snapshot, order) => order.OrderScreens.Count() == 0)
+            .WhereIF(dto.CurrentStepName.NotNullOrEmpty(), (snapshot, order) => order.CurrentStepName == dto.CurrentStepName)
+            .WhereIF(dto.BeginFiledTime.HasValue && dto.EndFiledTime.HasValue, (snapshot, order) => order.FiledTime >= dto.BeginFiledTime && order.FiledTime <= dto.EndFiledTime)
+            .WhereIF(dto.HotspotName.NotNullOrEmpty(), (snapshot, order) => order.HotspotName.Contains(dto.HotspotName))
+            .WhereIF(dto.OrderTagCode.NotNullOrEmpty(), (snapshot, order) => order.OrderTagCode.Contains(dto.OrderTagCode))
+            .WhereIF(dto.IsUrgent.HasValue, (snapshot, order) => order.IsUrgent == dto.IsUrgent)
+            .WhereIF(dto.TransferPhone.NotNullOrEmpty(), (snapshot, order) => order.TransferPhone.Contains(dto.TransferPhone))
+            .WhereIF(dto.OrgLevelOneCode.NotNullOrEmpty(), (snapshot, order) => order.OrgLevelOneCode == dto.OrgLevelOneCode)
+            //.WhereIF(dto.DiscontentTurnTo.HasValue, (snapshot, order) => order == dto.OrgLevelOneCode)
+            .WhereIF(dto.IndustryId.NotNullOrEmpty(), (snapshot, order) => snapshot.IndustryId == dto.IndustryId)
+            .Select((snapshot, order, industry) => new OrderSnapshotItemsOutDto
+            {
+                CreationTime = order.CreationTime
+            }
+             , true);
+        return query;
+    }
+
+    [ExportExcel("电气焊作业申报工单")]
+    public ISugarQueryable<OrderSnapshotElectrogasItemsOutDto> GetOrderSnapshotElectrogasItems(OrderSnapshotItemsInDto dto)
+    {
+        var query = _orderSnapshotRepository.Queryable()
+            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
+            .LeftJoin<Industry>((snapshot, order, industry) => snapshot.IndustryId == industry.Id)
+            .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order) => order.No.Contains(dto.No))
+            .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.Title))
+            .WhereIF(dto.ActualHandleOrgName.NotNullOrEmpty(), (snapshot, order) => order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
+            .WhereIF(dto.AcceptType.NotNullOrEmpty(), (snapshot, order) => order.AcceptType == dto.AcceptType)
+            .WhereIF(dto.AcceptorName.NotNullOrEmpty(), (snapshot, order) => order.AcceptorName == dto.AcceptorName)
+            .WhereIF(dto.FromPhone.NotNullOrEmpty(), (snapshot, order) => order.FromPhone == dto.FromPhone)
+            .WhereIF(dto.FromName.NotNullOrEmpty(), (snapshot, order) => order.FromName == dto.FromName)
+            .WhereIF(dto.BeginExpiredTime.HasValue && dto.EndExpiredTime.HasValue, (snapshot, order) => order.ExpiredTime >= dto.BeginExpiredTime && order.ExpiredTime <= dto.EndExpiredTime)
+            .WhereIF(dto.BeginCreationTime.HasValue && dto.EndCreationTime.HasValue, (snapshot, order) => order.CreationTime >= dto.BeginCreationTime && order.CreationTime <= dto.EndCreationTime)
+            .WhereIF(dto.Status.HasValue, (snapshot, order) => order.Status == dto.Status)
+            .WhereIF(dto.County.NotNullOrEmpty(), (snapshot, order) => order.County == dto.County)
+            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == true, (snapshot, order) => order.OrderScreens.Count() > 0)
+            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == false, (snapshot, order) => order.OrderScreens.Count() == 0)
+            .WhereIF(dto.CurrentStepName.NotNullOrEmpty(), (snapshot, order) => order.CurrentStepName == dto.CurrentStepName)
+            .WhereIF(dto.BeginFiledTime.HasValue && dto.EndFiledTime.HasValue, (snapshot, order) => order.FiledTime >= dto.BeginFiledTime && order.FiledTime <= dto.EndFiledTime)
+            .WhereIF(dto.HotspotName.NotNullOrEmpty(), (snapshot, order) => order.HotspotName.Contains(dto.HotspotName))
+            .WhereIF(dto.OrderTagCode.NotNullOrEmpty(), (snapshot, order) => order.OrderTagCode.Contains(dto.OrderTagCode))
+            .WhereIF(dto.IsUrgent.HasValue, (snapshot, order) => order.IsUrgent == dto.IsUrgent)
+            .WhereIF(dto.TransferPhone.NotNullOrEmpty(), (snapshot, order) => order.TransferPhone.Contains(dto.TransferPhone))
+            .WhereIF(dto.OrgLevelOneCode.NotNullOrEmpty(), (snapshot, order) => order.OrgLevelOneCode == dto.OrgLevelOneCode)
+            //.WhereIF(dto.DiscontentTurnTo.HasValue, (snapshot, order) => order == dto.OrgLevelOneCode)
+            .WhereIF(dto.IndustryId.NotNullOrEmpty(), (snapshot, order) => snapshot.IndustryId == dto.IndustryId)
+            .Where((snapshot, order, industry) => industry.IndustryType == EIndustryType.Declare)
+            .Select((snapshot, order, industry) => new OrderSnapshotElectrogasItemsOutDto
             {
                 CreationTime = order.CreationTime
             }
@@ -447,6 +504,7 @@ public class SnapshotOrderApplication : IOrderSnapshotApplication, IScopeDepende
         return query;
     }
 
+
     /// <summary>
     /// 获取工单已经标记集合
     /// </summary>
@@ -486,4 +544,57 @@ public class SnapshotOrderApplication : IOrderSnapshotApplication, IScopeDepende
         }
         return await _orderSnapshotRepository.UpdateSafetyAsync(orderId, isSafetyDepartment, remark);
     }
+
+    public ISugarQueryable<CitizenRewardOutDto> GetCitizenRewardItems(CitizenRewardInDto dto)
+    {
+        var query = _orderSnapshotRepository.Queryable()
+            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
+            .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order) => order.No.Contains(dto.No))
+            .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.Title))
+            .WhereIF(dto.ActualHandleOrgName.NotNullOrEmpty(), (snapshot, order) => order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
+            .WhereIF(dto.AcceptType.NotNullOrEmpty(), (snapshot, order) => order.AcceptType == dto.AcceptType)
+            .WhereIF(dto.AcceptorName.NotNullOrEmpty(), (snapshot, order) => order.AcceptorName == dto.AcceptorName)
+            .WhereIF(dto.ActualHandlerName.NotNullOrEmpty(), (snapshot, order) => order.ActualHandlerName == dto.ActualHandlerName)
+            .WhereIF(dto.FromPhone.NotNullOrEmpty(), (snapshot, order) => order.FromPhone == dto.FromPhone)
+            .WhereIF(dto.FromName.NotNullOrEmpty(), (snapshot, order) => order.FromName == dto.FromName)
+            .WhereIF(dto.BeginExpiredTime.HasValue && dto.EndExpiredTime.HasValue, (snapshot, order) => order.ExpiredTime >= dto.BeginExpiredTime && order.ExpiredTime <= dto.EndExpiredTime)
+            .WhereIF(dto.BeginCreationTime.HasValue && dto.EndCreationTime.HasValue, (snapshot, order) => order.CreationTime >= dto.BeginCreationTime && order.CreationTime <= dto.EndCreationTime)
+            .WhereIF(dto.Status.HasValue, (snapshot, order) => order.Status == dto.Status)
+            .WhereIF(dto.County.NotNullOrEmpty(), (snapshot, order) => order.County == dto.County)
+            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == true, (snapshot, order) => order.OrderScreens.Count() > 0)
+            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == false, (snapshot, order) => order.OrderScreens.Count() == 0)
+            .WhereIF(dto.CurrentStepName.NotNullOrEmpty(), (snapshot, order) => order.CurrentStepName == dto.CurrentStepName)
+            .WhereIF(dto.BeginFiledTime.HasValue && dto.EndFiledTime.HasValue, (snapshot, order) => order.FiledTime >= dto.BeginFiledTime && order.FiledTime <= dto.EndFiledTime)
+            .WhereIF(dto.HotspotName.NotNullOrEmpty(), (snapshot, order) => order.HotspotName.Contains(dto.HotspotName))
+            .WhereIF(dto.OrderTagCode.NotNullOrEmpty(), (snapshot, order) => order.OrderTagCode.Contains(dto.OrderTagCode))
+            .WhereIF(dto.IsUrgent.HasValue, (snapshot, order) => order.IsUrgent == dto.IsUrgent)
+            .WhereIF(dto.TransferPhone.NotNullOrEmpty(), (snapshot, order) => order.TransferPhone.Contains(dto.TransferPhone))
+            .WhereIF(dto.OrgLevelOneCode.NotNullOrEmpty(), (snapshot, order) => order.OrgLevelOneCode == dto.OrgLevelOneCode)
+            .WhereIF(dto.IndustryId.NotNullOrEmpty(), (snapshot, order) => snapshot.IndustryId == dto.IndustryId)
+            .Where((snapshot, order) => snapshot.IsAward == true)
+            .Select((snapshot, order) => new CitizenRewardOutDto
+            {
+                CreationTime = order.CreationTime
+            }
+             , true);
+        return query;
+
+    }
+
+    public async Task UpdateSpecialReasonAsync(string orderId, string errorId, string errorName)
+    {
+        await _orderSnapshotRepository.Updateable()
+            .SetColumns(m => m.SpecialReasonId, errorId)
+            .SetColumns(m => m.SpecialReasonName, errorName)
+            .Where(m => m.Id == orderId)
+            .ExecuteCommandAsync();
+    }
+
+    public async Task UpdateIsEmphasisAsync(UpdateIsEmphasisInDto dto)
+    {
+        await _orderSnapshotRepository.Updateable()
+            .SetColumns(m => m.IsEmphasis == true)
+            .Where(m => dto.Ids.Contains(m.Id))
+            .ExecuteCommandAsync();
+    }
 }

+ 2 - 1
src/Hotline.Application/Subscribers/DatasharingSubscriber.cs

@@ -248,7 +248,8 @@ namespace Hotline.Application.Subscribers
         [CapSubscribe(Hotline.Share.Mq.EventNames.SharingOrderRevoke)]
         public async Task RecCancelOrderAsync(CancelOrderDto dto, CancellationToken cancellationToken)
         {
-            var order = await _orderRepository.GetAsync(p => p.ReceiveProvinceNo == dto.ProvinceNo, cancellationToken);
+            //  var order = await _orderRepository.GetAsync(p => p.ReceiveProvinceNo == dto.ProvinceNo, cancellationToken);
+            var order = await _orderRepository.Queryable().Includes(d => d.Workflow).FirstAsync(p => p.ReceiveProvinceNo == dto.ProvinceNo);
             if (order is null)
                 throw new UserFriendlyException("未查询到工单");
 

+ 8 - 0
src/Hotline.Share/Attributes/ExportExcelAttribute.cs

@@ -12,8 +12,16 @@ public class ExportExcelAttribute : Attribute
     /// </summary>
     public string FileName { get; }
 
+    public string? TotalName { get; }
+
     public ExportExcelAttribute(string fileName)
     {
         FileName = fileName;
+        TotalName = null;
+    }
+    public ExportExcelAttribute(string fileName, string? totalName)
+    {
+        FileName = fileName;
+        TotalName = totalName;
     }
 }

+ 1 - 1
src/Hotline.Share/Dtos/Order/OrderStartFlowDto.cs

@@ -171,7 +171,7 @@ namespace Hotline.Share.Dtos.Order
         public bool? IsRectifyDepartment { get; set; }
 
         /// <summary>
-        /// 线索分类
+        /// 线索分类Id
         /// </summary>
         public string? IndustryCase { get; set; }
 

+ 667 - 19
src/Hotline.Share/Dtos/Snapshot/OrderDto.cs

@@ -3,6 +3,7 @@ using Hotline.Share.Enums;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Enums.Snapshot;
 using Hotline.Share.Requests;
+using Hotline.Share.Tools;
 using System.ComponentModel.DataAnnotations;
 using XF.Utility.EnumExtensions;
 
@@ -458,6 +459,11 @@ public class SnapshotOrderAuditItemsOutDto
     /// 红包审核状态
     /// </summary>
     public string AuditStatusTxt => AuditStatus.GetDescription();
+
+    /// <summary>
+    /// 奖励人姓名
+    /// </summary>
+    public string? AwardName { get; set; }
 }
 
 /// <summary>
@@ -703,7 +709,7 @@ public class GetRedPackAuditSMSTemplateInDto
 }
 
 public class SnapshotOrderAuditSpecialDetailOutDto
-{ 
+{
     /// <summary>
     /// 工单信息
     /// </summary>
@@ -722,7 +728,25 @@ public class SnapshotOrderAuditSpecialDetailOutDto
     /// <summary>
     /// 审核类型
     /// </summary>
-    public IEnumerable<SystemDicDataOutDto> AuditType { get; set; }
+    public IEnumerable<SystemDicDataAmountOutDto> AuditType { get; set; }
+}
+
+public class SystemDicDataAmountOutDto : SystemDicDataOutDto
+{
+    /// <summary>
+    /// 价格
+    /// </summary>
+    public int Amount => int.Parse(_dicDataName.Split('|')[1]);
+
+    private string _dicDataName;
+    new public string DicDataName
+    {
+        get
+        {
+            return _dicDataName.Split('|')[0];
+        }
+        set { _dicDataName = value; }
+    }
 }
 
 public class SnapshotOrderAuditSpecialAuditDetailOutDto
@@ -895,7 +919,7 @@ public class SnapshotOrderAuditOrderDetailOutDto
 }
 
 public class UpdateRedPackGuiderAuditInDto
-{ 
+{
     /// <summary>
     /// 审核Id
     /// </summary>
@@ -1788,16 +1812,17 @@ public class LabelOrderSnapshotLogItemsOutDto
     /// 标注时间
     /// </summary>
     public DateTime LabelTime { get; set; }
+
 }
 
 public record OrderSnapshotItemsInDto : PagedRequest
 {
-    /// <summary>
-    /// 资金状态
-    /// 0: 全部;
-    /// 1: 已标记资金申请;
-    /// </summary>
-    public int AmountStatus { get; set; }
+    ///// <summary>
+    ///// 资金状态
+    ///// 0: 全部;
+    ///// 1: 已标记资金申请;
+    ///// </summary>
+    //public int AmountStatus { get; set; }
 
     /// <summary>
     /// 受理编号
@@ -1827,20 +1852,20 @@ public record OrderSnapshotItemsInDto : PagedRequest
     /// <summary>
     /// 接办人名称
     /// </summary>
-    public string? ActualHandlerName { get; set; }
+    //public string? ActualHandlerName { get; set; }
 
     /// <summary>
-    /// 来电号码
+    /// 申报人电话
     /// </summary>
     public string? FromPhone { get; set; }
 
     /// <summary>
     /// 联系号码
     /// </summary>
-    public string? Contact { get; set; }
+    //public string? Contact { get; set; }
 
     /// <summary>
-    /// 来电人
+    /// 申报人姓名
     /// </summary>
     public string? FromName { get; set; }
 
@@ -1887,12 +1912,12 @@ public record OrderSnapshotItemsInDto : PagedRequest
     /// <summary>
     /// 办结时间开始
     /// </summary>
-    public DateTime? BeginCenterToOrgTime { get; set; }
+    public DateTime? BeginFiledTime { get; set; }
 
     /// <summary>
     /// 办结时间结束
     /// </summary>
-    public DateTime? EndCenterToOrgTime { get; set; }
+    public DateTime? EndFiledTime { get; set; }
 
     /// <summary>
     /// 热点类型名称
@@ -1902,7 +1927,7 @@ public record OrderSnapshotItemsInDto : PagedRequest
     /// <summary>
     /// 工单标签
     /// </summary>
-    public string? Label { get; set; }
+    public string? OrderTagCode { get; set; }
 
     /// <summary>
     /// 是否紧急
@@ -1919,6 +1944,11 @@ public record OrderSnapshotItemsInDto : PagedRequest
     /// </summary>
     public string? OrgLevelOneCode { get; set; }
 
+    /// <summary>
+    /// 一级部门名称
+    /// </summary>
+    public string? OrgLevelOneName { get; set; }
+
     /// <summary>
     /// 不满意转办
     /// </summary>
@@ -1930,6 +1960,14 @@ public record OrderSnapshotItemsInDto : PagedRequest
     public string? IndustryId { get; set; }
 }
 
+public class UpdateIsEmphasisInDto
+{
+    /// <summary>
+    /// Id集合
+    /// </summary>
+    public IList<string> Ids { get; set; }
+}
+
 public class OrderSnapshotItemsOutDto
 {
     /// <summary>
@@ -1940,12 +1978,23 @@ public class OrderSnapshotItemsOutDto
     /// <summary>
     /// 过期状态
     /// </summary>
-    public EExpiredStatus ExpiredStatus { get; set; }
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
 
     /// <summary>
     /// 过期状态
     /// </summary>
-    public string ExpiredStatusText => ExpiredStatus.GetDescription();
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
 
     /// <summary>
     /// 受理编号
@@ -2073,7 +2122,218 @@ public class OrderSnapshotItemsOutDto
     /// <summary>
     /// 办结时间
     /// </summary>
-    public DateTime? CenterToOrgTime { get; set; }
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
+    /// </summary>
+    public string HotspotName { get; set; }
+
+    /// <summary>
+    /// 受理人
+    /// </summary>
+    public string AcceptorName { get; set; }
+
+    /// <summary>
+    /// 受理内容
+    /// </summary>
+    public string Content { get; set; }
+
+    /// <summary>
+    /// 办理结果
+    /// </summary>
+    public string FileOpinion { get; set; }
+}
+
+public class OrderSnapshotElectrogasItemsOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool IsUrgent { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public string IsUrgentTxt => IsUrgent ? "紧急" : "-";
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 是否超期
+    /// </summary>
+    public bool IsExpired
+    {
+        get
+        {
+            if (ExpiredTime.HasValue)
+                return DateTime.Now > ExpiredTime.Value;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 申报人姓名
+    /// </summary>
+    public string? FromName { get; set; }
+
+    /// <summary>
+    /// 申报人电话
+    /// </summary>
+    public string? FromPhone { get; set; }
+
+    /// <summary>
+    /// 作业类型
+    /// </summary>
+    public int? JobType { get; set; }
+
+    /// <summary>
+    /// 作业类型
+    /// </summary>
+    public string? JobTypeName { get; set; }
+
+    /// <summary>
+    /// 作业场所
+    /// </summary>
+    public string? Workplace { get; set; }
+
+    /// <summary>
+    /// 作业区域
+    /// </summary>
+    public string? WorkArea { get; set; }
+
+    /// <summary>
+    /// 作业时间
+    /// </summary>
+    public DateTime? StartWorkTime { get; set; }
+
+    /// <summary>
+    /// 作业结束时间
+    /// </summary>
+    public DateTime? EndWorkTime { get; set; }
+
+    /// <summary>
+    /// 作业地点
+    /// </summary>
+    public string? Address { get; set; }
+
+    /// <summary>
+    /// 行业
+    /// </summary>
+    public string IndustryName { get; set; }
+
+    /// <summary>
+    /// 办理时长
+    /// </summary>
+    public double CreationTimeHandleDuration { get; set; }
+
+    /// <summary>
+    /// 区域
+    /// </summary>
+    public string County { get; set; }
+
+    /// <summary>
+    /// 电话
+    /// </summary>
+    public string Contact { get; set; }
+
+    /// <summary>
+    /// 一级部门
+    /// </summary>
+    public string OrgLevelOneCode { get; set; }
+
+    /// <summary>
+    /// 一级部门名称
+    /// </summary>
+    public string? OrgLevelOneName { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? StartTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
 
     /// <summary>
     /// 受理类型
@@ -2085,6 +2345,31 @@ public class OrderSnapshotItemsOutDto
     /// </summary>
     public string HotspotName { get; set; }
 
+    /// <summary>
+    /// 核实方式
+    /// </summary>
+    public string? VerifyType { get; set; }
+
+    /// <summary>
+    /// 是否按清单检查
+    /// </summary>
+    public bool? IsCheckList { get; set; }
+
+    /// <summary>
+    /// 是否按清单检查
+    /// </summary>
+    public string? IsCheckListTxt => IsCheckList.HasValue && IsCheckList.Value ? "是" : "否";
+
+    /// <summary>
+    /// 是否重复
+    /// </summary>
+    public bool? IsRepetition { get; set; }
+
+    /// <summary>
+    /// 是否重复
+    /// </summary>
+    public string? IsRepetitionTxt => IsRepetition.HasValue && IsRepetition.Value ? "是" : "否";
+
     /// <summary>
     /// 受理人
     /// </summary>
@@ -2149,3 +2434,366 @@ public class LabelOrderSnapshotDetailOutDto
     /// </summary>
     public IReadOnlyCollection<SystemDicDataOutDto> LabelsBaseData { get; set; }
 }
+public record CitizenRewardInDto : PagedRequest
+{
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string? No { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string? Title { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string? ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string? AcceptType { get; set; }
+
+    /// <summary>
+    /// 受理人
+    /// </summary>
+    public string? AcceptorName { get; set; }
+
+    /// <summary>
+    /// 接办人名称
+    /// </summary>
+    public string? ActualHandlerName { get; set; }
+
+    /// <summary>
+    /// 来电号码
+    /// </summary>
+    public string? FromPhone { get; set; }
+
+    /// <summary>
+    /// 联系号码
+    /// </summary>
+    public string? Contact { get; set; }
+
+    /// <summary>
+    /// 来电人
+    /// </summary>
+    public string? FromName { get; set; }
+
+    /// <summary>
+    /// 期满时间开始
+    /// </summary>
+    public DateTime? BeginExpiredTime { get; set; }
+
+    /// <summary>
+    /// 期满时间结束
+    /// </summary>
+    public DateTime? EndExpiredTime { get; set; }
+
+    /// <summary>
+    /// 受理时间开始
+    /// </summary>
+    public DateTime? BeginCreationTime { get; set; }
+
+    /// <summary>
+    /// 受理时间结束
+    /// </summary>
+    public DateTime? EndCreationTime { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus? Status { get; set; }
+
+    /// <summary>
+    /// 区域信息
+    /// </summary>
+    public string? County { get; set; }
+
+    /// <summary>
+    /// 是否甄别
+    /// </summary>
+    public bool? IsScreen { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string? CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 办结时间开始
+    /// </summary>
+    public DateTime? BeginFiledTime { get; set; }
+
+    /// <summary>
+    /// 办结时间结束
+    /// </summary>
+    public DateTime? EndFiledTime { get; set; }
+
+    /// <summary>
+    /// 热点类型名称
+    /// </summary>
+    public string? HotspotName { get; set; }
+
+    /// <summary>
+    /// 工单标签
+    /// </summary>
+    public string? OrderTagCode { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool? IsUrgent { get; set; }
+
+    /// <summary>
+    /// 转接来源
+    /// </summary>
+    public string? TransferPhone { get; set; }
+
+    /// <summary>
+    /// 一级部门
+    /// </summary>
+    public string? OrgLevelOneCode { get; set; }
+
+    /// <summary>
+    /// 一级部门名称
+    /// </summary>
+    public string? OrgLevelOneName { get; set; }
+
+    /// <summary>
+    /// 不满意转办
+    /// </summary>
+    public bool? DiscontentTurnTo { get; set; }
+
+    /// <summary>
+    /// 行业
+    /// </summary>
+    public string? IndustryId { get; set; }
+}
+
+public class CitizenRewardOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool IsUrgent { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public string IsUrgentText => IsUrgent ? "紧急" : "-";
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 是否超期
+    /// </summary>
+    public bool IsExpired
+    {
+        get
+        {
+            if (ExpiredTime.HasValue)
+                return DateTime.Now > ExpiredTime.Value;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 行业名称
+    /// </summary>
+    public string IndustryName { get; set; }
+
+    /// <summary>
+    /// 是否发放补充奖励
+    /// </summary>
+    public bool IsAward { get; set; }
+
+    /// <summary>
+    /// 是否发放补充奖励
+    /// </summary>
+    public string? IsAwardTxt => IsAward ? "是" : "否";
+
+    /// <summary>
+    /// 追加奖励金额(元)
+    /// </summary>
+    public double? AwardAmount { get; set; }
+
+    /// <summary>
+    /// 发放时间
+    /// </summary>
+    public DateTime? AwardTime { get; set; }
+
+    /// <summary>
+    /// 追加奖励人银行卡号
+    /// </summary>
+    public string? AwardBankCardNo { get; set; }
+
+    /// <summary>
+    /// 追加奖励人开户银行
+    /// </summary>
+    public string? AwardOpenBank { get; set; }
+
+    /// <summary>
+    /// 补充发放人员
+    /// </summary>
+    public string? AwardName { get; set; }
+
+    /// <summary>
+    /// 重点
+    /// </summary>
+    public string? Emphasis { get; set; }
+
+    /// <summary>
+    /// 全流程时长(秒)
+    /// </summary>
+    public double? AllDuration { get; set; }
+
+    /// <summary>
+    /// 办理时长(天)
+    /// </summary>
+    public string? TotalFieldDay => AllDuration.HasValue ? (AllDuration.Value / 60 / 60 / 24).ToString("f2") : null;
+
+    /// <summary>
+    /// 区域
+    /// </summary>
+    public string? County { get; set; }
+
+    /// <summary>
+    /// 电话
+    /// </summary>
+    public string? FromPhone { get; set; }
+
+    /// <summary>
+    /// 网格员姓名
+    /// </summary>
+    public string? MemberName { get; set; }
+
+    /// <summary>
+    /// 网格员电话
+    /// </summary>
+    public string? MemberMobile { get; set; }
+
+    /// <summary>
+    /// 网格员回复内容
+    /// </summary>
+    public string? NetworkRemark { get; set; }
+
+    /// <summary>
+    /// 网格E通编号
+    /// </summary>
+    public string? NetworkENumber { get; set; }
+
+    /// <summary>
+    /// 一级部门名称
+    /// </summary>
+    public string? OrgLevelOneName { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
+    /// </summary>
+    public string HotspotName { get; set; }
+
+    /// <summary>
+    /// 受理人名称
+    /// </summary>
+    public string? AcceptorName { get; set; }
+
+    /// <summary>
+    /// 受理内容
+    /// </summary>
+    public string Content { get; set; }
+
+    /// <summary>
+    /// 办理结果
+    /// </summary>
+    public string? FileOpinion { get; set; }
+}

+ 3087 - 11
src/Hotline.Share/Dtos/Snapshot/StatisticsDto.cs

@@ -1,40 +1,3116 @@
-using System;
+using Hotline.Share.Dtos.Order;
+using Hotline.Share.Dtos.Settings;
+using Hotline.Share.Enums.Order;
+using Hotline.Share.Enums.Snapshot;
+using Hotline.Share.Requests;
+using Hotline.Share.Tools;
+using Newtonsoft.Json;
+using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
 using System.Linq;
 using System.Text;
+using System.Text.Json.Serialization;
 using System.Threading.Tasks;
+using XF.Utility.EnumExtensions;
+using JsonIgnoreAttribute = System.Text.Json.Serialization.JsonIgnoreAttribute;
 
 namespace Hotline.Share.Dtos.Snapshot;
 
+public record RedPackStatisticsDetailsInDto : PagedRequest
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 字段名称
+    /// </summary>
+    [Required]
+    public string FieldName { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    [Required]
+    public string? IndustryId { get; set; }
+
+    /// <summary>
+    /// 行业类型
+    /// </summary>
+    [Required]
+    public int IndustryType { get; set; }
+}
+
+public class RedPackStatisticsDetailsOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool IsUrgent { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public string IsUrgentText => IsUrgent ? "紧急" : "-";
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 是否超期
+    /// </summary>
+    public bool IsExpired
+    {
+        get
+        {
+            if (ExpiredTime.HasValue)
+                return DateTime.Now > ExpiredTime.Value;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 行业
+    /// </summary>
+    public string IndustryName { get; set; }
+
+    /// <summary>
+    /// 办理时长
+    /// </summary>
+    public double CreationTimeHandleDuration { get; set; }
+
+    /// <summary>
+    /// 区域
+    /// </summary>
+    public string County { get; set; }
+
+    /// <summary>
+    /// 电话
+    /// </summary>
+    public string Contact { get; set; }
+
+    /// <summary>
+    /// 受理期满时间
+    /// </summary>
+    public DateTime? AcceptExpiredTime { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
+    /// </summary>
+    public string HotspotName { get; set; }
+
+    /// <summary>
+    /// 受理人
+    /// </summary>
+    public string AcceptorName { get; set; }
+
+    /// <summary>
+    /// 受理内容
+    /// </summary>
+    public string Content { get; set; }
+
+    /// <summary>
+    /// 办理结果
+    /// </summary>
+    public string FileOpinion { get; set; }
+}
+
+public class RedPackStatisticsInDto
+{
+    public DateTime StartTime { get; set; }
+    public DateTime EndTime { get; set; }
+}
+
+public class RedPackStatisticsOutDto
+{
+    /// <summary>
+    /// 行业类型
+    /// </summary>
+    [JsonIgnore]
+    [Newtonsoft.Json.JsonIgnore]
+    public string CaseName { get; set; }
+
+    /// <summary>
+    /// 行业类型Id
+    /// </summary>
+    [JsonIgnore]
+    [Newtonsoft.Json.JsonIgnore]
+    public string CaseId { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    [JsonIgnore]
+    [Newtonsoft.Json.JsonIgnore]
+    public string? Id { get; set; }
+
+    /// <summary>
+    /// 行业名字
+    /// </summary>
+    [JsonIgnore]
+    [Newtonsoft.Json.JsonIgnore]
+    public string Name { get; set; }
+
+    /// <summary>
+    /// 配置金额(后端逻辑用, 前端不显示)
+    /// </summary>
+    [JsonIgnore]
+    [Newtonsoft.Json.JsonIgnore]
+    public double? ShouldAmount { get; set; } = 0;
+
+    /// <summary>
+    /// 审批同意总金额
+    /// </summary>
+    public double? ApprovalAmount { get; set; } = 0;
+
+    /// <summary>
+    /// 审批同意总金额
+    /// </summary>
+    public string? ApprovalAmountTxt => ApprovalAmount?.ToString("f2");
+
+    /// <summary>
+    /// 审批同意总个数
+    /// </summary>
+    public int ApprovalCount { get; set; }
+
+    /// <summary>
+    /// 发送成功金额
+    /// </summary>
+    public double? SentAmount { get; set; } = 0;
+
+    /// <summary>
+    /// 发送成功金额
+    /// </summary>
+    public string? SentAmountTxt => SentAmount?.ToString("f2");
+
+    /// <summary>
+    /// 发送成功个数
+    /// </summary>
+    public int SentCount { get; set; }
+
+    /// <summary>
+    /// 发送失败金额
+    /// </summary>
+    public double SendFailAmount { get; set; } = 0;
+
+    /// <summary>
+    /// 发送失败金额
+    /// </summary>
+    public string? SendFailAmountTxt => SendFailAmount.ToString("f2");
+
+    /// <summary>
+    /// 发送失败个数
+    /// </summary>
+    public int SendFailCount { get; set; }
+
+    /// <summary>
+    /// 待发金额
+    /// </summary>
+    public double? PendingAmount { get; set; } = 0;
+
+    /// <summary>
+    /// 待发金额
+    /// </summary>
+    public string? PendingAmountTxt => PendingAmount?.ToString("f2");
+
+    /// <summary>
+    /// 待发个数
+    /// </summary>
+    public int PendingCount { get; set; }
+
+    /// <summary>
+    /// 补充红包金额
+    /// </summary>
+    public double? SupplementAmount { get; set; } = 0;
+
+    /// <summary>
+    /// 补充红包金额
+    /// </summary>
+    public string? SupplementAmountTxt => SupplementAmount?.ToString("f2");
+
+    /// <summary>
+    /// 补充红包数
+    /// </summary>
+    public int SupplementCount { get; set; }
+
+    /// <summary>
+    /// 行业类型名称
+    /// </summary>
+    public string? IndustryName { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    public string? IndustryId { get; set; }
+
+    /// <summary>
+    /// 行业类型
+    /// </summary>
+    public int IndustryType { get; set; }
+}
+
 /// <summary>
 /// 随手拍统计输出Dto
 /// </summary>
 public class SnapshotStatisticsOutDto
-{ 
+{
+    /// <summary>
+    /// 随手拍来件数
+    /// </summary>
+    public int SSPLJS => WZSLFWNJS + SSPZ12345JS + SLFWNZJS;
+
+    /// <summary>
+    /// 未在受理范围内件数
+    /// </summary>
+    public int WZSLFWNJS { get; set; }
+
+    /// <summary>
+    /// 随手拍转12345件数
+    /// </summary>
+    public int SSPZ12345JS { get; set; }
+
+    /// <summary>
+    /// 受理范围内总件数
+    /// </summary>
+    public int SLFWNZJS { get; set; }
+
+    /// <summary>
+    /// 受理范围内派给各网格员件数
+    /// </summary>
+    public int SLFWNPGGWGYJS => SLFWNPGWGYSXSNHFJS + SLFWNPGWGYCGSXSHFJS + SLFWNPGWGYWHFJS;
+
+    /// <summary>
+    /// 受理范围内派给网格员四小时内回复件数
+    /// </summary>
+    public int SLFWNPGWGYSXSNHFJS { get; set; }
+
+    /// <summary>
+    /// 受理范围内派给网格员超过四小时回复件数
+    /// </summary>
+    public int SLFWNPGWGYCGSXSHFJS { get; set; }
+
+    /// <summary>
+    /// 受理范围内派给网格员未回复件数
+    /// </summary>
+    public int SLFWNPGWGYWHFJS { get; set; }
+
+    /// <summary>
+    /// 受理范围内按12345直派给各区县或部门件数
+    /// </summary>
+    public int SLFWNA12345ZPGGQXHBMJS => SLFWNA12345ZPGGBMJS + SLFWNA12345ZPGGQXJS;
+
+    /// <summary>
+    /// 受理范围内按12345直派给各部门件数
+    /// </summary>
+    public int SLFWNA12345ZPGGBMJS { get; set; }
+
+    /// <summary>
+    /// 受理范围内按12345直派给各区县件数
+    /// </summary>
+    public int SLFWNA12345ZPGGQXJS { get; set; }
+
+    /// <summary>
+    /// 受理范围内已办信件
+    /// </summary>
+    public int SLFWNYBXJ => ZXYB + BMYB;
+
+    /// <summary>
+    /// 中心已办
+    /// </summary>
+    public int ZXYB { get; set; }
+
+    /// <summary>
+    /// 部门已办
+    /// </summary>
+    public int BMYB { get; set; }
+
+    /// <summary>
+    /// 受理范围满意度
+    /// </summary>
+    public double SLFWMYD => SLFWNZJS == 0 ? 0 : (double)MYL / SLFWNZJS;
+
+    /// <summary>
+    /// 计算率
+    /// </summary>
+    /// <returns></returns>
+    public string CalcRate(int Quantity, int Count)
+    {
+        if (Count != 0 && Quantity != 0)
+        {
+            return Math.Round((Quantity / (double)Count) * 100, 2) + "%";
+        }
+        return "0%";
+    }
+
+    /// <summary>
+    /// 受理范围满意度
+    /// </summary>
+    public string SLFWMYDTxt => CalcRate(MYL, SLFWNZJS);
+
+    /// <summary>
+    /// 满意量
+    /// </summary>
+    public int MYL { get; set; }
+
+    /// <summary>
+    /// 不满意量
+    /// </summary>
+    public int BMYL { get; set; }
+
+    /// <summary>
+    /// 审核发放奖励个数
+    /// </summary>
+    public int SHFFJLGS => SPBTYHBGS + SPTYHBGS;
+
+    /// <summary>
+    /// 审批不同意红包个数
+    /// </summary>
+    public int SPBTYHBGS { get; set; }
+
+    /// <summary>
+    /// 审批同意红包个数
+    /// </summary>
+    public int SPTYHBGS { get; set; }
+
+    /// <summary>
+    /// 特殊红包审批统计
+    /// </summary>
+    public int TSHBSP { get; set; }
+
+    /// <summary>
+    /// 审批同意个数
+    /// </summary>
+    public int SPTYGS { get; set; }
+
+    /// <summary>
+    /// 已发金额
+    /// </summary>
+    public double? YFJE { get; set; }
+
+    /// <summary>
+    /// 局审核发放网格员奖励个数
+    /// </summary>
+    public int JSHFFWGJLGS { get; set; }
+
+    /// <summary>
+    /// 审批同意(网格员)红包个数
+    /// </summary>
+    public int SPTYWGYHBGS { get; set; }
+
+    /// <summary>
+    /// 审批不同意(网格员)红包个数
+    /// </summary>
+    public int SPBTYWGYHBGS { get; set; }
+
+    /// <summary>
+    /// 市民奖励总额
+    /// </summary>
+    public double? SMJLZE { get; set; }
+
+    /// <summary>
+    /// 市民已发放奖励总额
+    /// </summary>
+    public double? SMYFFJLZE { get; set; }
+
+    /// <summary>
+    /// 市民待发奖励总额
+    /// </summary>
+    public double? SMDFFJLZE { get; set; }
+
+    /// <summary>
+    /// 已发(个)
+    /// </summary>
+    public int YFG { get; set; }
+
+    /// <summary>
+    /// 无法联系(个)
+    /// </summary>
+    public int WFLXG { get; set; }
+
+    /// <summary>
+    /// 婉拒红包(个)
+    /// </summary>
+    public int WJHBG { get; set; }
+
+    /// <summary>
+    /// 网格员应发奖励金额
+    /// </summary>
+    public double? WGYYFJLJE { get; set; }
+
+    /// <summary>
+    /// 网格员已发放奖励总额
+    /// </summary>
+    public double? WGYYFFJLZE { get; set; }
+
+    /// <summary>
+    /// 网格员待发放奖励总额
+    /// </summary>
+    public double? WGYDFFJLZE { get; set; }
+
+    /// <summary>
+    /// 网格员扣款总额(已发)
+    /// </summary>
+    public float WGYKKZEYF { get; set; }
+
+    /// <summary>
+    /// 网格员扣款总额(待发)
+    /// </summary>
+    public float WGYKKZEDF { get; set; }
+
+    /// <summary>
+    /// 受理范围内多部门会签件件数
+    /// </summary>
+    public int SLFWNDBMHQJJS { get; set; }
+
+    /// <summary>
+    /// 受理范围内热线中心归档件数
+    /// </summary>
+    public int SLFWNRXZXGDJS { get; set; }
+
+    /// <summary>
+    /// 热线中心发起会签件件数
+    /// </summary>
+    public int RXZXFQHQJJS { get; set; }
+
+    /// <summary>
+    /// 安全隐患
+    /// </summary>
+    public int AQYH { get; set; }
+
+    /// <summary>
+    /// 已完成安全隐患整改
+    /// </summary>
+    public int YWCAQYHZG { get; set; }
+
+    /// <summary>
+    /// 申请延期工单件数
+    /// </summary>
+    public int SQYQGDJS { get; set; }
+
+    /// <summary>
+    /// 申请延期工单次数
+    /// </summary>
+    public int SQYQGDCS { get; set; }
+
+    /// <summary>
+    /// 超期件
+    /// </summary>
+    public int CQJ { get; set; }
+
+    /// <summary>
+    /// 二次办理件数
+    /// </summary>
+    public int ECBLJS => ECBLJSTHBM + ECBLJSHFBMYCB + ECBLJSTTDYYJBM;
+
+    /// <summary>
+    /// 二次办理件数-退回部门
+    /// </summary>
+    public int ECBLJSTHBM { get; set; }
+
+    /// <summary>
+    /// 二次办理件数-回访不满意重办
+    /// </summary>
+    public int ECBLJSHFBMYCB { get; set; }
+
+    /// <summary>
+    /// 二次办理件数-回访满意
+    /// </summary>
+    public int ECBLJSHFMY { get; set; }
+
+    /// <summary>
+    /// 二次办理件数-特提到原一级部门
+    /// </summary>
+    public int ECBLJSTTDYYJBM { get; set; }
+
+    /// <summary>
+    /// 二次办理工单满意率
+    /// </summary>
+    public double ECBLGDMYL => ECBLJS == 0 ? 0 : (ECBLJSHFMY / ECBLJS) * 100;
+
+    /// <summary>
+    /// 二次办理工单满意率
+    /// </summary>
+    public string ECBLGDMYLTxt => ECBLGDMYL.ToString("f4") + "%";
+
+    /// <summary>
+    /// 二次办理工单件数-退回部门回访满意
+    /// </summary>
+    public int ECBLGDJSTMBMHFMYD { get; set; }
+
+    /// <summary>
+    /// 二次办理工单满意率-退回部门
+    /// </summary>
+    public double ECBLGDMYLTHBM => ECBLJSTHBM == 0 ? 0 : (ECBLGDJSTMBMHFMYD / ECBLJSTHBM) * 100;
+
+    /// <summary>
+    /// 二次办理工单满意率-退回部门
+    /// </summary>
+    public string ECBLGDMYLTHBMTxt => ECBLGDMYLTHBM.ToString("f4") + "%";
+
+    /// <summary>
+    /// 二次办理工单满意率-回访不满意重办
+    /// </summary>
+    public double ECBLGDMYLHFBMYCB => ECBLJS == 0 ? 0 : (ECBLJSHFBMYCB / ECBLJS) * 100;
+
+    /// <summary>
+    /// 二次办理工单满意率-回访不满意重办
+    /// </summary>
+    public string ECBLGDMYLHFBMYCBTxt => ECBLGDMYLHFBMYCB.ToString("f4") + "%";
+
+    /// <summary>
+    /// 特提件数
+    /// </summary>
+    public int TTJS => TTDYYJBMJS + TTDPDZJS + QTTTJS;
+
+    /// <summary>
+    /// 特提到原一级部门件数
+    /// </summary>
+    public int TTDYYJBMJS { get; set; }
+
+    /// <summary>
+    /// 特提到派单组件数
+    /// </summary>
+    public int TTDPDZJS { get; set; }
+
+    /// <summary>
+    /// 其他特提件数
+    /// </summary>
+    public int QTTTJS { get; set; }
+}
+
+/// <summary>
+/// 随手拍统计输入Dto
+/// </summary>
+public class SnapshotStatisticsInDto
+{
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    [Required]
+    public DateTime StartTime { get; set; }
+
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    public string? IndustryId { get; set; }
+}
+
+public record SnapshotStatisticsDetailInDto : PagedRequest
+{
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    [Required]
+    public DateTime StartTime { get; set; }
+
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 字段名称
+    /// </summary>
+    [Required]
+    public string FieldName { get; set; }
+}
+
+public class SnapshotStatisticsDetailOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool IsUrgent { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public string IsUrgentText => IsUrgent ? "紧急" : "-";
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 是否超期
+    /// </summary>
+    public bool IsExpired
+    {
+        get
+        {
+            if (ExpiredTime.HasValue)
+                return DateTime.Now > ExpiredTime.Value;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 行业
+    /// </summary>
+    public string IndustryName { get; set; }
+
+    /// <summary>
+    /// 办理时长
+    /// </summary>
+    public double CreationTimeHandleDuration { get; set; }
+
+    /// <summary>
+    /// 区域
+    /// </summary>
+    public string County { get; set; }
+
+    /// <summary>
+    /// 电话
+    /// </summary>
+    public string Contact { get; set; }
+
+    /// <summary>
+    /// 网格员名称
+    /// </summary>
+    public string MemberName { get; set; }
+
+    /// <summary>
+    /// 网格员电话
+    /// </summary>
+    public string MemberMobile { get; set; }
+
+    /// <summary>
+    /// 网格员回复
+    /// </summary>
+    public string NetworkRemark { get; set; }
+
+    /// <summary>
+    /// 网格E通编号
+    /// </summary>
+    public string? NetworkENumber { get; set; }
+
+    /// <summary>
+    /// 受理期满时间
+    /// </summary>
+    public DateTime? AcceptExpiredTime { get; set; }
+
+    /// <summary>
+    /// 一级部门
+    /// </summary>
+    public string OrgLevelOneCode { get; set; }
+
+    /// <summary>
+    /// 一级部门名称
+    /// </summary>
+    public string? OrgLevelOneName { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
+    /// </summary>
+    public string HotspotName { get; set; }
+
+    /// <summary>
+    /// 受理人
+    /// </summary>
+    public string AcceptorName { get; set; }
+
+    /// <summary>
+    /// 受理内容
+    /// </summary>
+    public string Content { get; set; }
+
+    /// <summary>
+    /// 办理结果
+    /// </summary>
+    public string FileOpinion { get; set; }
+}
+public class StatisticsDto
+{
+}
+
+public class HotspotStatisticsInDto
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 分类Code
+    /// </summary>
+    public string? HotspotCode { get; set; }
+}
+
+public class HotspotStatisticsOutDto
+{
+    public string HotspotCode { get; set; }
+    public int SumCount { get; set; }
+    public string HotspotName { get; set; }
+    public bool HasChild { get; set; }
+}
+
+public record HotspotStatisticsDetailsInDto : PagedRequest
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    public string? HotspotCode { get; set; }
+
+}
+public class HotspotStatisticsDetailsOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 甄别状态
+    /// </summary>
+    public EScreenStatus? OrderScreenStatus { get; set; }
+
+    /// <summary>
+    /// 甄别状态
+    /// </summary>
+    public string? OrderScreenStatusText => OrderScreenStatus.HasValue && OrderScreenStatus != null ? OrderScreenStatus?.GetDescription() : "未甄别";
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool IsUrgent { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public string IsUrgentText => IsUrgent ? "紧急" : "-";
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 是否超期
+    /// </summary>
+    public bool IsExpired
+    {
+        get
+        {
+            if (ExpiredTime.HasValue)
+                return DateTime.Now > ExpiredTime.Value;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 行业
+    /// </summary>
+    public string IndustryName { get; set; }
+
+    /// <summary>
+    /// 办理时长
+    /// </summary>
+    public double CreationTimeHandleDuration { get; set; }
+
+    /// <summary>
+    /// 区域
+    /// </summary>
+    public string County { get; set; }
+
+    /// <summary>
+    /// 电话
+    /// </summary>
+    public string Contact { get; set; }
+
+    /// <summary>
+    /// 受理期满时间
+    /// </summary>
+    public DateTime? AcceptExpiredTime { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 满意度
+    /// </summary>
+    public Kv? OrgProcessingResults { get; set; }
+
+    /// <summary>
+    /// 满意度
+    /// </summary>
+    public string? OrgProcessingResultsTxt => OrgProcessingResults != null ? OrgProcessingResults.Value : "";
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
+    /// </summary>
+    public string HotspotName { get; set; }
+
+    /// <summary>
+    /// 受理人
+    /// </summary>
+    public string AcceptorName { get; set; }
+
+    /// <summary>
+    /// 受理内容
+    /// </summary>
+    public string Content { get; set; }
+
+    /// <summary>
+    /// 办理结果
+    /// </summary>
+    public string FileOpinion { get; set; }
+}
+
+public class SnapshotProcessingStatisticsInDto
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    public string? IndustryId { get; set; }
+}
+
+public class SnapshotProcessingStatisticsOutDto
+{
+    /// <summary>
+    /// 部门Code
+    /// </summary>
+    public string OrgCode { get; set; }
+
+    /// <summary>
+    /// 部门名称
+    /// </summary>
+    public string OrgName { get; set; }
+
+    /// <summary>
+    /// 信件总量
+    /// </summary>
+    public int OrderCountNum => YbOrderCountNum + ZbOrderCountNum;
+
+    /// <summary>
+    /// 信件已办总量
+    /// </summary>
+    public int YbOrderCountNum { get; set; }
+
+    /// <summary>
+    /// 信件未办总量
+    /// </summary>
+    public int ZbOrderCountNum { get; set; }
+
+    /// <summary>
+    /// 按时办结
+    /// </summary>
+    public int CompleteOnTime { get; set; }
+
+    /// <summary>
+    /// 按时办结率
+    /// </summary>
+    public string CompleteOnTimeRate => CalcRate(YbOrderCountNum, CompleteOnTime);
+
+    /// <summary>
+    /// 办结率
+    /// </summary>
+    public string OrderCompletionRate => CalcRate(YbOrderCountNum, OrderCountNum);
+
+    /// <summary>
+    /// 20分钟内接件
+    /// </summary>
+    public int ReceiveIn20Minutes { get; set; }
+
+    /// <summary>
+    /// 20分钟后接件
+    /// </summary>
+    public int ReceiveOut20Minutes { get; set; }
+
+    /// <summary>
+    /// 工单及时响应率
+    /// </summary>
+    public string PromptResponse => CalcRate(ReceiveIn20Minutes, ReceiveIn20Minutes + ReceiveOut20Minutes);
+
+    /// <summary>
+    /// 退回件
+    /// </summary>
+    public int BackNum { get; set; }
+
+    /// <summary>
+    /// 办件总时长
+    /// </summary>
+    public double? TotalHandleDuration { get; set; }
+
+    /// <summary>
+    /// 3日内办结
+    /// </summary>
+    public int End3Day { get; set; }
+
+    /// <summary>
+    /// 3至5日办结
+    /// </summary>
+    public int End3To5Day { get; set; }
+
+    /// <summary>
+    /// 5至7日办结
+    /// </summary>
+    public int End5To7Day { get; set; }
+
+    /// <summary>
+    /// 7日外办结
+    /// </summary>
+    public int End7Day { get; set; }
+
+    /// <summary>
+    /// 按时办结个数
+    /// </summary>
+    public int OnTimeCount { get; set; }
+
+    /// <summary>
+    /// 按时办结率
+    /// </summary>
+    public string CloseOnTimeRate => CalcRate(OnTimeCount, OrderCountNum);
+
+    /// <summary>
+    /// 满意量
+    /// </summary>
+    public int SatisfiedCount { get; set; }
+
+    /// <summary>
+    /// 不满意量
+    /// </summary>
+    public int NoSatisfiedCount { get; set; }
+
+    /// <summary>
+    /// 满意率
+    /// </summary>
+    public string SatisfiedRate => CalcRate(SatisfiedCount, SatisfiedCount + NoSatisfiedCount);
+
+    /// <summary>
+    /// 二次办理个数
+    /// </summary>
+    public int SecondNum { get; set; }
+
+    /// <summary>
+    /// 计算率
+    /// </summary>
+    /// <returns></returns>
+    public string CalcRate(int Quantity, int Count)
+    {
+        if (Count != 0 && Quantity != 0)
+        {
+            return Math.Round((Quantity / (double)Count) * 100, 2) + "%";
+        }
+        return "0%";
+    }
+}
+
+public record SnapshotProcessingStatisticsDetailsInDto : PagedRequest
+{
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    [Required]
+    public DateTime StartTime { get; set; }
+
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 字段名称
+    /// </summary>
+    [Required]
+    public string FieldName { get; set; }
+
+    /// <summary>
+    /// 部门Id
+    /// </summary>
+    [Required]
+    public string OrgId { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    public string? IndustryId { get; set; }
+}
+
+public class SnapshotProcessingStatisticsDetailsOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 甄别状态
+    /// </summary>
+    public EScreenStatus? OrderScreenStatus { get; set; }
+
+    /// <summary>
+    /// 甄别状态
+    /// </summary>
+    public string? OrderScreenStatusText => OrderScreenStatus.HasValue && OrderScreenStatus != null ? OrderScreenStatus?.GetDescription() : "未甄别";
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
+    /// </summary>
+    public string HotspotName { get; set; }
+}
+
+public class GuiderWorkStatisticsOutDto
+{
+    /// <summary>
+    /// 网格员姓名
+    /// </summary>
+    public string MemberName { get; set; }
+
+    /// <summary>
+    /// 网格员手机号
+    /// </summary>
+    public string MemberMobile { get; set; }
+
+    /// <summary>
+    /// 未回复
+    /// </summary>
+    public int UnReplyCount { get; set; }
+
+    /// <summary>
+    /// 4小时内回复
+    /// </summary>
+    public int ReplyIn4HourCount { get; set; }
+
+    /// <summary>
+    /// 4小时外回复
+    /// </summary>
+    public int ReplyOut4HourCount { get; set; }
+}
+
+public class GuiderWorkStatisticsInDto
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+}
+
+public record GuiderWorkStatisticsDetailsInDto : PagedRequest
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    [Required]
+    public string MemberMobile { get; set; }
+
+    /// <summary>
+    /// 字段名称
+    /// </summary>
+    [Required]
+    public string FieldName { get; set; }
+}
+
+public class GuiderWorkStatisticsDetailsOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool IsUrgent { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public string IsUrgentText => IsUrgent ? "紧急" : "-";
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 是否超期
+    /// </summary>
+    public bool IsExpired
+    {
+        get
+        {
+            if (ExpiredTime.HasValue)
+                return DateTime.Now > ExpiredTime.Value;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 行业
+    /// </summary>
+    public string IndustryName { get; set; }
+
+    /// <summary>
+    /// 办理时长
+    /// </summary>
+    public double CreationTimeHandleDuration { get; set; }
+
+    /// <summary>
+    /// 区域
+    /// </summary>
+    public string County { get; set; }
+
+    /// <summary>
+    /// 电话
+    /// </summary>
+    public string Contact { get; set; }
+
+    /// <summary>
+    /// 网格员姓名
+    /// </summary>
+    public string MemberName { get; set; }
+
+    /// <summary>
+    /// 网格员手机号
+    /// </summary>
+    public string MemberMobile { get; set; }
+
+    /// <summary>
+    /// 网格员回复内容
+    /// </summary>
+    public string? NetworkRemark { get; set; }
+
+    /// <summary>
+    /// 受理期满时间
+    /// </summary>
+    public DateTime? AcceptExpiredTime { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
+    /// </summary>
+    public string HotspotName { get; set; }
+
+    /// <summary>
+    /// 受理人
+    /// </summary>
+    public string AcceptorName { get; set; }
+}
+
+public class HotspotDataStatisticsOutDto
+{
+    /// <summary>
+    /// 热点名字
+    /// </summary>
+    public string Name { get; set; }
+
+    /// <summary>
+    /// 热点工单数量
+    /// </summary>
+    public int OrderCount { get; set; }
+}
+
+public class HotspotDataStatisticsInDto
+{
+    /// <summary>
+    /// 类型:
+    /// 0: 全部;
+    /// 1: 市民;
+    /// 2: 企业;
+    /// </summary>
+    [Required]
+    public int TypeId { get; set; }
+
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+}
+
+public class GuiderWorkLogsOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// title
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 区域
+    /// </summary>
+    public string County { get; set; }
+
+    /// <summary>
+    /// 网格员回复内容
+    /// </summary>
+    public string? NetworkRemark { get; set; }
+
+    /// <summary>
+    /// 回复时间
+    /// </summary>
+    public DateTime? ReplyDate { get; set; }
+
+    /// <summary>
+    /// 网格员姓名
+    /// </summary>
+    public string? MemberName { get; set; }
+
+    /// <summary>
+    /// 网格员电话
+    /// </summary>
+    public string? MemberMobile { get; set; }
+
+    /// <summary>
+    /// 网格E通编号
+    /// </summary>
+    public string? NetworkENumber { get; set; }
+
+    /// <summary>
+    /// 网格员办理状态
+    /// </summary>
+    public EGuiderSystemReplyType? ReplyResultType { get; set; }
+
+    /// <summary>
+    /// 网格员办理状态
+    /// </summary>
+    public string ReplyResultTypeTxt => ReplyResultType == null ? "未知" : ReplyResultType.Value.GetDescription();
+}
+
+public record GuiderWorkLogsInDto : PagedRequest
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// No
+    /// </summary>
+    public string? No { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string? Title { get; set; }
+
+    /// <summary>
+    /// 网格员姓名
+    /// </summary>
+    public string? MemberName { get; set; }
+
+    /// <summary>
+    /// 网格员电话
+    /// </summary>
+    public string? MemberMobile { get; set; }
+
+    /// <summary>
+    /// 编号
+    /// </summary>
+    public string? NetworkENumber { get; set; }
+
+    /// <summary>
+    /// 状态
+    /// </summary>
+    public EOrderStatus? Status { get; set; }
+
+    /// <summary>
+    /// 受理时间开始
+    /// </summary>
+    public DateTime? BeginCreationTime { get; set; }
+
+    /// <summary>
+    /// 受理时间结束
+    /// </summary>
+    public DateTime? EndCreationTime { get; set; }
+}
+
+public record DuplicateItemsInDto : PagedRequest
+{
+    /// <summary>
+    /// 编号
+    /// </summary>
+    public string? No { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string? Title { get; set; }
+
+    /// <summary>
+    /// 来电号码
+    /// </summary>
+    public string? FromPhone { get; set; }
+
+    /// <summary>
+    /// 联系号码
+    /// </summary>
+    public string? Contact { get; set; }
+
+    /// <summary>
+    /// 来电人
+    /// </summary>
+    public string? FromName { get; set; }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime? BeginCreationTime { get; set; }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime? EndCreationTime { get; set; }
+
+    /// <summary>
+    /// 期满时间开始
+    /// </summary>
+    public DateTime? BeginExpiredTime { get; set; }
+
+    /// <summary>
+    /// 期满时间结束
+    /// </summary>
+    public DateTime? EndExpiredTime { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string? ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string? AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
+    /// </summary>
+    public string? HotspotName { get; set; }
+
+    /// <summary>
+    /// 受理人
+    /// </summary>
+    public string? AcceptorName { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    public string? IndustryId { get; set; }
+}
+public class DuplicateItemsOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// No
+    /// </summary>
+    public string? No { get; set; }
+
+    /// <summary>
+    /// 类型
+    /// </summary>
+    public string? OrderSnapshotType { get; set; }
+
+    /// <summary>
+    /// 重复工单Id
+    /// </summary>
+    public List<string>? DuplicateIds { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string? Title { get; set; }
+
+    /// <summary>
+    /// 网格员姓名
+    /// </summary>
+    public string? MemberName { get; set; }
+
+    /// <summary>
+    /// 网格员电话
+    /// </summary>
+    public string? MemberMobile { get; set; }
+
+    /// <summary>
+    /// 编号
+    /// </summary>
+    public string? NetworkENumber { get; set; }
+
+    /// <summary>
+    /// 状态
+    /// </summary>
+    public EOrderStatus? Status { get; set; }
+
+    /// <summary>
+    /// 受理时间开始
+    /// </summary>
+    public DateTime? BeginCreationTime { get; set; }
+
+    /// <summary>
+    /// 受理时间结束
+    /// </summary>
+    public DateTime? EndCreationTime { get; set; }
+
+    /// <summary>
+    /// 行业
+    /// </summary>
+    public string IndustryName { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 受理人
+    /// </summary>
+    public string AcceptorName { get; set; }
+}
+
+public class CommunityStatisticsInDto
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    public string? IndustryId { get; set; }
+
+    public string? CommunityCode { get; set; }
+}
+
+public class CommunityStatisticsOutDto
+{
+    public string CommunityCode { get; set; }
+    public int SumCount { get; set; }
+    public string CommunityName { get; set; }
+    public bool HasChild { get; set; }
+    public string CommunityFullName { get; set; }
+}
+
+public class CommunityStatisticsDetailsOutDto
+{
+
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool IsUrgent { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public string IsUrgentText => IsUrgent ? "紧急" : "-";
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 是否超期
+    /// </summary>
+    public bool IsExpired
+    {
+        get
+        {
+            if (ExpiredTime.HasValue)
+                return DateTime.Now > ExpiredTime.Value;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
+    /// </summary>
+    public string HotspotName { get; set; }
+
+    /// <summary>
+    /// 社区名称
+    /// </summary>
+    public string CommunityName { get; set; }
+}
+
+public record CommunityStatisticsDetailsInDto : PagedRequest
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 社区全称
+    /// </summary>
+    [Required]
+    public string CommunityCode { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    public string? IndustryId { get; set; }
+}
+
+public class CountyRedPackStatisticsOutDto
+{
+    /// <summary>
+    /// 区域
+    /// </summary>
+    public string? County { get; set; }
+
+    /// <summary>
+    /// 举报总数
+    /// </summary>
+    public int JuBaoZongShu { get; set; }
+
+    /// <summary>
+    /// 已办结数
+    /// </summary>
+    public int YiBanJieShu { get; set; }
+
+    /// <summary>
+    /// 办结率
+    /// </summary>
+    public string BanJieLv => CalcRate(YiBanJieShu, JuBaoZongShu);
+
+    /// <summary>
+    /// 市民审核通过数
+    /// </summary>
+    public int ShiMinShenHeTongGuoShu { get; set; }
+
+    /// <summary>
+    /// 市民总金额
+    /// </summary>
+    public double? ShiMinZongJinE { get; set; }
+
+    /// <summary>
+    /// 市民已领
+    /// </summary>
+    public double ShiMinYiLing { get; set; }
+
+    /// <summary>
+    /// 市民待领
+    /// </summary>
+    public double ShiMinDaiLing { get; set; }
+
+    /// <summary>
+    /// 市民待补领
+    /// </summary>
+    public double? ShiMinDaiBuLing { get; set; }
+
+    /// <summary>
+    /// 网格员总件数
+    /// </summary>
+    public int WangGeYuanZongJianShu { get; set; }
+
+    /// <summary>
+    /// 网格员审核通过数
+    /// </summary>
+    public int WangGeYuanShenHeTongGuoShu { get; set; }
+
+    /// <summary>
+    /// 网格员总金额
+    /// </summary>
+    public double? WangGeYuanZongJinE { get; set; }
+
+    /// <summary>
+    /// 网格员已领
+    /// </summary>
+    public double WangGeYuanYiLing { get; set; }
+
+    /// <summary>
+    /// 网格员待领
+    /// </summary>
+    public double WangGeYuanDaiLing { get; set; }
+
+    /// <summary>
+    /// 网格员待补领
+    /// </summary>
+    public double WangGeYuianDaiBuLing { get; set; } = 0;
+
+    /// <summary>
+    /// 计算率
+    /// </summary>
+    /// <returns></returns>
+    public string CalcRate(int Quantity, int Count)
+    {
+        if (Count != 0 && Quantity != 0)
+        {
+            return Math.Round((Quantity / (double)Count) * 100, 2) + "%";
+        }
+        return "0%";
+    }
+
+}
+
+public class CountyRedPackStatisticsInDto
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    public string? IndustryId { get; set; }
+}
+
+
+public class SnapshotDepartmentStatisticsOutDto
+{
+    /// <summary>
+    /// 部门Code
+    /// </summary>
+    public string OrgCode { get; set; }
+
+    /// <summary>
+    /// 部门名称
+    /// </summary>
+    public string OrgName { get; set; }
+
+    /// <summary>
+    /// 信件总量
+    /// </summary>
+    public int OrderCountNum { get; set; }
+
+    /// <summary>
+    /// 按时办结个数
+    /// </summary>
+    public int OnTimeCount { get; set; }
+
+    /// <summary>
+    /// 工单及时率
+    /// </summary>
+    public string TimelinessRatio { get; set; } = "0.00";
+
+    /// <summary>
+    /// 4小时内
+    /// </summary>
+    public int ReceiveIn4Hour { get; set; }
+
+    /// <summary>
+    /// 超期办结
+    /// </summary>
+    public int TimeOutField { get; set; }
+
+    /// <summary>
+    /// 超期未办结
+    /// </summary>
+    public int TimeOutNoField { get; set; }
+
+    /// <summary>
+    /// 超期率
+    /// </summary>
+    public string TimeOutRate => CalcRate(TimeOutNoField + TimeOutField, OrderCountNum);
+
+    /// <summary>
+    /// 超期量
+    /// </summary>
+    public int TimeOutCount => TimeOutField + TimeOutNoField;
+
+    /// <summary>
+    /// 按时办结率
+    /// </summary>
+    public string CloseOnTimeRate => CalcRate(OnTimeCount, OrderCountNum);
+
+    /// <summary>
+    /// 满意工单
+    /// </summary>
+    public int SatisfiedCount { get; set; }
+
+    /// <summary>
+    /// 回访满意率
+    /// </summary>
+    public string SatisfiedRate => CalcRate(SatisfiedCount, SatisfiedCount + NoSatisfiedCount);
+
+    /// <summary>
+    /// 不满意量
+    /// </summary>
+    public int NoSatisfiedCount { get; set; }
+
+    /// <summary>
+    /// 一次办结工单
+    /// </summary>
+    public int FirstFiledOrderCount { get; set; }
+
+    /// <summary>
+    /// 一次办结率
+    /// </summary>
+    public string FirstFiledOrderRate => CalcRate(FirstFiledOrderCount, OrderCountNum);
+
+    /// <summary>
+    /// 二次办理个数
+    /// </summary>
+    public int SecondNum { get; set; }
+
+    /// <summary>
+    /// 二次办理满意率
+    /// </summary>
+    public int SecondSatisfied { get; set; }
+
+    /// <summary>
+    /// 二次办理率
+    /// </summary>
+    public string SecondRate => CalcRate(SecondNum, OrderCountNum);
+
+    /// <summary>
+    /// 计算率
+    /// </summary>
+    /// <returns></returns>
+    public string CalcRate(int Quantity, int Count)
+    {
+        if (Count != 0 && Quantity != 0)
+        {
+            return Math.Round((Quantity / (double)Count) * 100, 2) + "%";
+        }
+        return "0%";
+    }
+}
+
+public class SnapshotDepartmentStatisticsInDto
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+}
+
+public class SnapshotDepartmentAveTimeStatisticsOutDto
+{
+    public string OrgCode { get; set; }
+    public object OrgName { get; set; }
+
+    /// <summary>
+    /// 工单数
+    /// </summary>
+    public int OrderCountNum { get; set; }
+
+    /// <summary>
+    /// 总秒数
+    /// </summary>
+    public double? TotalSeconds { get; set; }
+
+    /// <summary>
+    /// 总分钟数
+    /// </summary>
+    public string TotalMinutes => TotalSeconds == null ? "0" : ((double)TotalSeconds / 60).ToString("f0");
+
+    /// <summary>
+    /// 平均分钟数
+    /// </summary>
+    public string AvgMinutes => OrderCountNum == 0 ? "0" : (double.Parse(TotalMinutes) / OrderCountNum).ToString("f2");
+
+    /// <summary>
+    /// 平均小时数
+    /// </summary>
+    public string AvgHours => OrderCountNum == 0 ? "0" : (double.Parse(TotalMinutes) / 60 / OrderCountNum).ToString("f2");
+}
+
+public class SnapshotDepartmentAveTimeStatisticsInDto
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+
+}
+
+public record SnapshotDepartmentAveTimeStatisticsDetailsInDto : PagedRequest
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 部门编号
+    /// </summary>
+    [Required]
+    public string OrgCode { get; set; }
+}
+
+public class SnapshotDepartmentAveTimeStatisticsDetailsOutDto
+{
+
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool IsUrgent { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public string IsUrgentText => IsUrgent ? "紧急" : "-";
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 是否超期
+    /// </summary>
+    public bool IsExpired
+    {
+        get
+        {
+            if (ExpiredTime.HasValue)
+                return DateTime.Now > ExpiredTime.Value;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 办理时长(秒)
+    /// </summary>
+    public double? AllDuration { get; set; }
+
+    /// <summary>
+    /// 办理时长(分)
+    /// </summary>
+    public string TotalMinutes => AllDuration == null ? "0" : ((double)AllDuration / 60).ToString("f0");
+
+    /// <summary>
+    /// 办理时长(时)
+    /// </summary>
+    public string TotalHours => AllDuration == null ? "0" : ((double)AllDuration / 60 / 60).ToString("f2");
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
+    /// </summary>
+    public string HotspotName { get; set; }
+
+}
+
+public class CompliantStatisticsInDto
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+}
+
+
+public class CompliantStatisticsOutDto
+{
+    public string OrgCode { get; set; }
+
+    /// <summary>
+    /// 部门名称
+    /// </summary>
+    public string OrgName { get; set; }
+
+    /// <summary>
+    /// 工单总数
+    /// </summary>
+    public int OrderCountNum { get; set; }
+
+    /// <summary>
+    /// 首次
+    /// </summary>
+    public int First { get; set; }
+
+    /// <summary>
+    /// 二次
+    /// </summary>
+    public int Second { get; set; }
+
+    /// <summary>
+    /// 三次及以上
+    /// </summary>
+    public int Third { get; set; }
+
+    /// <summary>
+    /// 不合规
+    /// </summary>
+    public int Not { get; set; }
+}
+
+public record CompliantStatisticsDetailsInDto : PagedRequest
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 字段名称
+    /// </summary>
+    [Required]
+    public string FieldName { get; set; }
+
+    /// <summary>
+    /// 部门编号
+    /// </summary>
+    [Required]
+    public string OrgCode { get; set; }
+}
+
+public class CompliantStatisticsDetailsOutDto
+{
+
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool IsUrgent { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public string IsUrgentText => IsUrgent ? "紧急" : "-";
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 是否超期
+    /// </summary>
+    public bool IsExpired
+    {
+        get
+        {
+            if (ExpiredTime.HasValue)
+                return DateTime.Now > ExpiredTime.Value;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
     /// <summary>
-    /// 随手拍来件数
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
     /// </summary>
-    public int SuiShouPaiLaiJianShu { get; set; }
+    public string HotspotName { get; set; }
+
 }
 
-/// <summary>
-/// 随手拍统计输入Dto
-/// </summary>
-public class SnapshotStatisticsInDto
+public class ReTransactStatisticsInDto
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+}
+
+public class ReTransactStatisticsOutDto
 {
     /// <summary>
-    /// 开始时间
+    /// 表头
+    /// </summary>
+    public IList<SystemDicDataOutDto> Headers { get; set; }
+
+    /// <summary>
+    /// 数据
+    /// </summary>
+    public List<Dictionary<string, object>> Data { get; set; }
+}
+
+public class ReTransactStatisticsDetailsOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// No
+    /// </summary>
+    public string? No { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool IsUrgent { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public string IsUrgentText => IsUrgent ? "紧急" : "-";
+
+    /// <summary>
+    /// 期满时间
     /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 是否超期
+    /// </summary>
+    public bool IsExpired
+    {
+        get
+        {
+            if (ExpiredTime.HasValue)
+                return DateTime.Now > ExpiredTime.Value;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string? Title { get; set; }
+
+    /// <summary>
+    /// 被重办部门
+    /// </summary>
+    public string? ReTransactOrgName { get; set; }
+
+    /// <summary>
+    /// 被重办一级部门
+    /// </summary>
+    public string? ReTransactOneOrgName { get; set; }
+
+    /// <summary>
+    /// 重办时间
+    /// </summary>
+    public DateTime? ReTransactTime { get; set; }
+
+    /// <summary>
+    /// 重办操作人
+    /// </summary>
+    public string? ReTransactHandlerName { get; set; }
+
+    /// <summary>
+    /// 重办理由
+    /// </summary>
+    public string ReTransactContent { get; set; }
+
+    /// <summary>
+    /// 受理时间开始
+    /// </summary>
+    public DateTime? BeginCreationTime { get; set; }
+
+    /// <summary>
+    /// 受理时间结束
+    /// </summary>
+    public DateTime? EndCreationTime { get; set; }
+
+    /// <summary>
+    /// 行业
+    /// </summary>
+    public string IndustryName { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 受理人
+    /// </summary>
+    public string AcceptorName { get; set; }
+
+}
+
+public record ReTransactStatisticsDetailsInDto : PagedRequest
+{
     [Required]
     public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
 
     /// <summary>
-    /// 结束时间
+    /// 字段名称
+    /// </summary>
+    public string? FieldName { get; set; }
+
+    /// <summary>
+    /// 部门Code
     /// </summary>
     [Required]
+    public string OrgCode { get; set; }
+}
+
+public class IndustryStatisticsOutDto
+{
+    /// <summary>
+    /// 表头
+    /// </summary>
+    public IList<SystemDicDataOutDto> Headers { get; set; }
+
+    /// <summary>
+    /// 数据
+    /// </summary>
+    public List<Dictionary<string, object>> Data { get; set; }
+
+}
+
+public class IndustryStatisticsInDto
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
     public DateTime EndTime { get; set; }
 }
-public class StatisticsDto
+
+public record IndustryStatisticsDetailsInDto : PagedRequest
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+    [Required]
+    public DateTime EndTime { get; set; }
+
+    /// <summary>
+    /// 字段名称
+    /// </summary>
+    [Required]
+    public string FieldName { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    [Required]
+    public string IndustryId { get; set; }
+}
+
+public class IndustryStatisticsDetailsOutDto
 {
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public EExpiredStatus? ExpiredStatus => FiledTime.CalculateExpiredState(Status, this.ExpiredTime, this.NearlyExpiredTime, this.NearlyExpiredTimeOne);
+
+    /// <summary>
+    /// 过期状态
+    /// </summary>
+    public string ExpiredStatusText => ExpiredStatus?.GetDescription();
+
+    /// <summary>
+    /// 受理编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public EOrderStatus Status { get; set; }
+
+    /// <summary>
+    /// 信件状态
+    /// </summary>
+    public string StatusTxt => Status.GetDescription();
+
+    /// <summary>
+    /// 来源
+    /// </summary>
+    public string SourceChannel { get; set; }
+
+    /// <summary>
+    /// 当前节点
+    /// </summary>
+    public string CurrentStepName { get; set; }
+
+    /// <summary>
+    /// 重办次数
+    /// </summary>
+    public int ReTransactNum { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public bool IsUrgent { get; set; }
+
+    /// <summary>
+    /// 是否紧急
+    /// </summary>
+    public string IsUrgentText => IsUrgent ? "紧急" : "-";
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间
+    /// </summary>
+    public DateTime? NearlyExpiredTime { get; set; }
+
+    /// <summary>
+    /// 即将超期时间第一级
+    /// </summary>
+    public DateTime? NearlyExpiredTimeOne { get; set; }
+
+    /// <summary>
+    /// 是否超期
+    /// </summary>
+    public bool IsExpired
+    {
+        get
+        {
+            if (ExpiredTime.HasValue)
+                return DateTime.Now > ExpiredTime.Value;
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 行业
+    /// </summary>
+    public string IndustryName { get; set; }
+
+    /// <summary>
+    /// 办理时长
+    /// </summary>
+    public double? AllDuration { get; set; }
+
+    /// <summary>
+    /// 办理时长(时)
+    /// </summary>
+    public string TotalHours => AllDuration == null ? "0" : ((double)AllDuration / 60 / 60).ToString("f2");
+
+    /// <summary>
+    /// 区域
+    /// </summary>
+    public string County { get; set; }
+
+    /// <summary>
+    /// 电话
+    /// </summary>
+    public string Contact { get; set; }
+
+    /// <summary>
+    /// 受理期满时间
+    /// </summary>
+    public DateTime? AcceptExpiredTime { get; set; }
+
+    /// <summary>
+    /// 接办部门
+    /// </summary>
+    public string ActualHandleOrgName { get; set; }
+
+    /// <summary>
+    /// 一级部门
+    /// </summary>
+    public string? OrgLevelOneName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime? ActualHandleTime { get; set; }
+
+    /// <summary>
+    /// 办结时间
+    /// </summary>
+    public DateTime? FiledTime { get; set; }
+
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public string AcceptType { get; set; }
+
+    /// <summary>
+    /// 热点类型
+    /// </summary>
+    public string HotspotName { get; set; }
+
+    /// <summary>
+    /// 受理人
+    /// </summary>
+    public string AcceptorName { get; set; }
+
+    /// <summary>
+    /// 受理内容
+    /// </summary>
+    public string Content { get; set; }
+
+    /// <summary>
+    /// 办理结果
+    /// </summary>
+    public string FileOpinion { get; set; }
+
 }

+ 38 - 0
src/Hotline.Share/Tools/DateTimeExtensions.cs

@@ -1,8 +1,11 @@
 using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.Order;
+using Hotline.Share.Enums.Order;
 using Novacode;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Runtime.CompilerServices;
 using System.Text;
 using System.Threading.Tasks;
 
@@ -37,4 +40,39 @@ public static class DateTimeExtensions
         return new DateTimeOffset(value).ToUnixTimeMilliseconds();
     }
 
+    public static EExpiredStatus? CalculateExpiredState(this DateTime? filedTime, EOrderStatus status, DateTime? expiredTime, DateTime? nearlyExpiredTime, DateTime? nearlyExpiredTimeOne)
+    {
+        DateTime? dateTime = DateTime.Now;
+        if (status >= EOrderStatus.Filed)
+        {
+            dateTime = filedTime;
+        }
+
+        if (expiredTime.HasValue)
+        {
+            if (nearlyExpiredTimeOne.HasValue && dateTime < nearlyExpiredTimeOne)
+            {
+                return EExpiredStatus.Normal;
+            }
+            else if (!nearlyExpiredTimeOne.HasValue && dateTime < nearlyExpiredTime)
+            {
+                return EExpiredStatus.Normal;
+            }
+            else if (nearlyExpiredTimeOne.HasValue && dateTime > nearlyExpiredTimeOne && dateTime < nearlyExpiredTime)
+            {
+                return EExpiredStatus.GoingToExpiredOne;
+            }
+            else if (dateTime > nearlyExpiredTime && dateTime < expiredTime)
+            {
+                return EExpiredStatus.GoingToExpired;
+            }
+            else
+            {
+                return EExpiredStatus.Expired;
+            }
+        }
+
+        return null;
+    }
+
 }

+ 67 - 0
src/Hotline.Share/Tools/ListExtensions.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Runtime.CompilerServices;
 using System.Text;
 using System.Threading.Tasks;
 
@@ -32,4 +33,70 @@ public static class ListExtensions
         return value != null && value.Count != 0;
     }
 
+    private static void AddSumLineForDictionaryList(IList<Dictionary<string, object>> list, string fieldName)
+    {
+        var sumRow = new Dictionary<string, object>();
+
+        foreach (var key in list.First().Keys)
+        {
+            sumRow[key] = key == fieldName ? "合计" : 0;
+        }
+
+        foreach (var item in list)
+        {
+            foreach (var key in item.Keys)
+            {
+                if (key != fieldName && item[key] is IConvertible) 
+                {
+                    try
+                    {
+                        sumRow[key] = Convert.ToDecimal(sumRow[key]) + Convert.ToDecimal(item[key]);
+                    }
+                    catch
+                    {
+                        sumRow[key] = item[key]; 
+                    }
+                }
+            }
+        }
+
+        list.Add(sumRow);
+    }
+
+    public static void AddSumLine<T>(this IList<T> list, string fieldName)
+    {
+        if (list == null || list.Count == 0) return;
+        var type = typeof(T);
+        if (typeof(T) == typeof(Dictionary<string, object>))
+        {
+            AddSumLineForDictionaryList(list as IList<Dictionary<string, object>>, fieldName);
+            return;
+        }
+        var properties = type.GetProperties();
+        var sumLine = Activator.CreateInstance<T>();
+        foreach (var property in properties)
+        {
+            if (property.Name == fieldName)
+            {
+                property.SetValue(sumLine, "合计");
+            }
+            else if (property.PropertyType == typeof(int))
+            {
+                property.SetValue(sumLine, list.Sum(m => (int)property.GetValue(m)));
+            }
+            else if (property.PropertyType == typeof(decimal))
+            {
+                property.SetValue(sumLine, list.Sum(m => (decimal)property.GetValue(m)));
+            }
+            else if (property.PropertyType == typeof(double?))
+            {
+                property.SetValue(sumLine, list.Sum(m => (double?)property.GetValue(m)));
+            }
+            else if (property.PropertyType == typeof(double))
+            {
+                property.SetValue(sumLine, list.Sum(m => (double?)property.GetValue(m)));
+            }
+        }
+        list.Add(sumLine);
+    }
 }

+ 8 - 0
src/Hotline.Share/Tools/MethodInfoExtensions.cs

@@ -17,4 +17,12 @@ public static class MethodInfoExtensions
         if (att == null) return string.Empty;
         return att.FileName;
     }
+
+    public static string? GetTotalName(this MethodInfo? value)
+    {
+        if (value == null) return string.Empty;
+        var att = value.GetCustomAttribute<ExportExcelAttribute>();
+        if (att == null) return null;
+        return att.TotalName;
+    }
 }

+ 1 - 0
src/Hotline/Configurations/AppConfiguration.cs

@@ -18,6 +18,7 @@ namespace Hotline.Configurations
         public bool IsYiBin => CheckScopeIs(AppDefaults.AppScope.YiBin);
         public bool IsZiGong => CheckScopeIs(AppDefaults.AppScope.ZiGong);
         public bool IsLuZhou => CheckScopeIs(AppDefaults.AppScope.LuZhou);
+        public string AreaCode => GetDefaultAppScopeConfiguration().AreaCode;
 
         private bool CheckScopeIs(string appscope) => string.CompareOrdinal(AppScope, appscope) == 0;
 

+ 18 - 0
src/Hotline/Orders/Notifications/OrderSpecialNotify.cs

@@ -0,0 +1,18 @@
+using Hotline.Share.Dtos.Order;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Orders.Notifications
+{
+    /// <summary>
+    /// 添加工单重办通知
+    /// </summary>
+    /// <param name="OrderId">工单Id</param>
+    /// <param name="SourceChannel">工单来源</param>
+    /// <param name="Reasons">重办原因</param>
+    public record AddOrderSpecialNotify(string OrderId, string SourceChannel, List<OrderSpecialDetailDto> Reasons) : INotification;
+}

+ 1 - 1
src/Hotline/Snapshot/CommunityInfo.cs

@@ -33,7 +33,7 @@ public class CommunityInfo : CreationSoftDeleteEntity
     /// 父社区Code
     /// </summary>
     [SugarColumn(ColumnDescription = "父社区Code")]
-    public string ParentCode { get; set; }
+    public string? ParentCode { get; set; }
 
     /// <summary>
     /// 社区唯一

+ 45 - 1
src/Hotline/Snapshot/OrderSnapshot.cs

@@ -41,6 +41,12 @@ public class OrderSnapshot : CreationSoftDeleteEntity
     [SugarColumn(ColumnDescription = "社区名字")]
     public string? CommunityName { get; set; }
 
+    /// <summary>
+    /// 社区名字
+    /// </summary>
+    [SugarColumn(ColumnDescription = "社区名字")]
+    public string? CommunityFullName { get; set; }
+
     /// <summary>
     /// 作业类型
     /// </summary>
@@ -95,6 +101,12 @@ public class OrderSnapshot : CreationSoftDeleteEntity
     [SugarColumn(ColumnDescription = "作业时间")]
     public DateTime? EndWorkTime { get; set; }
 
+    /// <summary>
+    /// 是否重点
+    /// </summary>
+    [SugarColumn(ColumnDescription = "是否重点")]
+    public bool? IsEmphasis { get; set; }
+
     #region 标记工单是否安全生产字段
 
     /// <summary>
@@ -147,7 +159,7 @@ public class OrderSnapshot : CreationSoftDeleteEntity
     public bool? IsRectifyDepartment { get; set; }
 
     /// <summary>
-    /// 线索分类
+    /// 线索分类Id
     /// </summary>
     [SugarColumn(ColumnDescription = "线索分类")]
     public string? IndustryCase { get; set; }
@@ -342,4 +354,36 @@ public class OrderSnapshot : CreationSoftDeleteEntity
     /// </summary>
     [SugarColumn(ColumnDescription = "购气单位/个人名称")]
     public string? CompanyName { get; set; }
+
+    /// <summary>
+    /// 发送网格员系统时间
+    /// </summary>
+    [SugarColumn(ColumnDescription = "发送网格员系统时间")]
+    public DateTime? SendGuidSystemTime { get; set; }
+
+    /// <summary>
+    /// 网格员系统回调时间
+    /// </summary>
+    [SugarColumn(ColumnDescription = "网格员系统回调时间")]
+    public DateTime? GuidSystemCallBackTime { get; set; }
+
+    /// <summary>
+    /// 网格员系统是否回调
+    /// </summary>
+    [SugarColumn(ColumnDescription = "网格员系统是否回调", DefaultValue = "f")]
+    public bool IsGuidSystemCallBack { get; set; }
+
+    #region 重办信息
+    /// <summary>
+    /// 重办原因Id
+    /// </summary>
+    [SugarColumn(ColumnDescription = "重办原因Id")]
+    public string? SpecialReasonId { get; set; }
+
+    /// <summary>
+    /// 重办原因
+    /// </summary>
+    [SugarColumn(ColumnDescription = "重办原因")]
+    public string? SpecialReasonName { get; set; }
+    #endregion
 }

+ 2 - 2
src/Hotline/Snapshot/RedPackAudit.cs

@@ -108,8 +108,8 @@ public class RedPackAudit : CreationSoftDeleteEntity
     /// <summary>
     /// 是否已发放
     /// </summary>
-    [SugarColumn(ColumnDescription = "是否已发放")]
-    public bool? IsIssued { get; set; }
+    //[SugarColumn(ColumnDescription = "是否已发放")]
+    //public bool? IsIssued { get; set; }
 
     /// <summary>
     /// 短信Id

+ 2 - 2
src/Hotline/Snapshot/SupplementRecord.cs

@@ -36,8 +36,8 @@ public class SupplementRecord : FullStateEntity
     /// <summary>
     /// RedPackRecordId
     /// </summary>
-    [SugarColumn(ColumnDescription = "RedPackRecordId")]
-    public string RedPackRecordId { get; set; }
+    //[SugarColumn(ColumnDescription = "RedPackRecordId")]
+    //public string RedPackRecordId { get; set; }
 
     /// <summary>
     /// 行业

+ 112 - 0
test/Hotline.Tests/Application/BiSnapshotApplicationTest.cs

@@ -0,0 +1,112 @@
+using Hotline.Api.Controllers;
+using Hotline.Application.Snapshot;
+using Hotline.Identity.Accounts;
+using Hotline.Identity.Roles;
+using Hotline.Settings;
+using Hotline.Share.Dtos.Snapshot;
+using Hotline.Share.Tools;
+using Hotline.Snapshot.Interfaces;
+using Hotline.Users;
+using Mapster;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Dynamic.Core;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Cache;
+using XF.Domain.Repository;
+
+namespace Hotline.Tests.Application;
+public class BiSnapshotApplicationTest : TestBase
+{
+    private readonly IBiSnapshotApplication _biSnapshotApplication;
+    public BiSnapshotApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, ITypedCache<SystemSetting> cacheSettingData, IBiSnapshotApplication biSnapshotApplication) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData)
+    {
+        _biSnapshotApplication = biSnapshotApplication;
+    }
+
+    [Fact]
+    public async Task GetCountyStatistics_Test()
+    {
+        var inDto = new CommunityStatisticsInDto
+        {
+            StartTime = DateTime.Now.AddDays(-30),
+            EndTime = DateTime.Now
+        };
+
+        var items = await _biSnapshotApplication.GetCommunityStatistics(inDto).ToListAsync();
+        var first = items.FirstOrDefault();
+        first.ShouldNotBeNull();
+        first.CommunityName.ShouldBe("自贡市");
+
+        var end = true;
+        while (end)
+        {
+            var hasChild = items.Where(m => m.SumCount != 0).FirstOrDefault();
+            if (hasChild == null)
+            {
+                end = false;
+                return;
+            }
+            inDto.CommunityCode = hasChild.CommunityCode;
+            items = await _biSnapshotApplication.GetCommunityStatistics(inDto).ToListAsync();
+            if (hasChild.SumCount != 0)
+            {
+                var inDto2 = inDto.Adapt<CommunityStatisticsDetailsInDto>();
+                inDto2.CommunityCode = hasChild.CommunityCode;
+                var details = await _biSnapshotApplication.GetCommunityStatisticsDetails(inDto2).ToListAsync();
+                details.Count.ShouldBe(hasChild.SumCount);
+            }
+        }
+    }
+
+    [Fact]
+    public async Task GetCountyRedPackStatistics_Test()
+    {
+        var inDto = new CountyRedPackStatisticsInDto
+        {
+            StartTime = DateTime.Now.AddDays(-30),
+            EndTime = DateTime.Now,
+        };
+        var items = await _biSnapshotApplication.GetCountyRedPackStatistics(inDto).ToListAsync();
+
+        var transposedItems = items.SelectMany(item => item.GetType().GetProperties()
+            .Select(prop => new { Property = prop.Name, Value = prop.GetValue(item) }))
+            .GroupBy(x => x.Property)
+            .ToDictionary(g => g.Key, g => g.Select(x => x.Value).ToList());
+
+        transposedItems.ShouldNotBeNull();
+        transposedItems.Count.ShouldNotBe(0);
+    }
+
+    [Fact]
+    public async Task GetSnapshotDepartmentStatistics_Test()
+    {
+        var inDto = new SnapshotDepartmentStatisticsInDto
+        {
+            StartTime = DateTime.Now.AddDays(-30),
+            EndTime = DateTime.Now,
+        };
+        var items = await _biSnapshotApplication.GetSnapshotDepartmentStatistics(inDto).ToListAsync();
+        items.ShouldNotBeNull();
+
+        var a = await _biSnapshotApplication.GetSnapshotDepartmentAveTimeStatistics(inDto.Adapt<SnapshotDepartmentAveTimeStatisticsInDto>()).ToListAsync();
+        a.ShouldNotBeNull();
+
+        var b = _biSnapshotApplication.GetReTransactStatistics(inDto.Adapt<ReTransactStatisticsInDto>());
+        b.ShouldNotBeNull();
+        var c = b.ToJson();
+
+        var bInDto = inDto.Adapt<ReTransactStatisticsDetailsInDto>();
+        bInDto.OrgCode = "001";
+        var d = await _biSnapshotApplication.GetReTransactStatisticsDetail(bInDto).ToListAsync();
+        d.ShouldNotBeNull();
+
+        var e = _biSnapshotApplication.GetIndustryStatistics(inDto.Adapt<IndustryStatisticsInDto>());
+        e.ShouldNotBeNull();
+    }
+}

+ 30 - 27
test/Hotline.Tests/Application/OrderSnapshotApplicationTest.cs

@@ -40,9 +40,10 @@ public class OrderSnapshotApplicationTest : TestBase
     private readonly IRedPackAuditRepository _redPackAuditRepository;
     private readonly IRedPackRecordRepository _redPackRecordRepository;
     private readonly ISnapshotLabelLogRepository _snapshotLabelLogRepository;
+    private readonly IRedPackApplication _redPackApplication;
     private readonly IOrderRepository _orderRepository;
 
-    public OrderSnapshotApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, OrderServiceMock orderServiceMock, ISystemDicDataCacheManager systemDicDataCacheManager, IOrderSnapshotRepository orderSnapshotRepository, IOrderSnapshotApplication orderSnapshotApplication, ISnapshotApplication snapshotApplication, IIndustryLogRepository industryLogRepository, ICommunityInfoRepository communityInfoRepository, IRedPackAuditRepository redPackAuditRepository, IRedPackRecordRepository redPackRecordRepository, ISnapshotLabelLogRepository snapshotLabelLogRepository, ITypedCache<SystemSetting> cacheSettingData, IOrderRepository orderRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData)
+    public OrderSnapshotApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, OrderServiceMock orderServiceMock, ISystemDicDataCacheManager systemDicDataCacheManager, IOrderSnapshotRepository orderSnapshotRepository, IOrderSnapshotApplication orderSnapshotApplication, ISnapshotApplication snapshotApplication, IIndustryLogRepository industryLogRepository, ICommunityInfoRepository communityInfoRepository, IRedPackAuditRepository redPackAuditRepository, IRedPackRecordRepository redPackRecordRepository, ISnapshotLabelLogRepository snapshotLabelLogRepository, ITypedCache<SystemSetting> cacheSettingData, IRedPackApplication redPackApplication, IOrderRepository orderRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData)
     {
         _orderServiceMock = orderServiceMock;
         _systemDicDataCacheManager = systemDicDataCacheManager;
@@ -54,6 +55,7 @@ public class OrderSnapshotApplicationTest : TestBase
         _redPackAuditRepository = redPackAuditRepository;
         _redPackRecordRepository = redPackRecordRepository;
         _snapshotLabelLogRepository = snapshotLabelLogRepository;
+        _redPackApplication = redPackApplication;
         _orderRepository = orderRepository;
     }
 
@@ -97,7 +99,7 @@ public class OrderSnapshotApplicationTest : TestBase
         var inputLable = snapshotLabels.Where(m => m.DicDataValue == "bss").ToList();
         var order = _orderServiceMock.CreateSnapshotOrder(SetWeiXin)
             .办理到网格员(SetZuoXi)
-            .StepHandle(async order =>
+            .StepHandle(async (order, mock) =>
             {
                 await _snapshotApplication.PostOrderGuiderSystemAsync(order.Id, CancellationToken.None);
                 var orderSnapshot = await _orderSnapshotRepository.GetAsync(order.Id);
@@ -112,34 +114,17 @@ public class OrderSnapshotApplicationTest : TestBase
                     .SetColumns(m => m.IndustryName, industryLog.OldIndustryName)
                     .Where(m => m.Id == order.Id)
                     .ExecuteCommandAsync();
+                await _orderRepository.Updateable()
+                    .SetColumns(m => m.OrderTagCode, "DHZY")
+                    .Where(m => m.Id == order.Id)
+                    .ExecuteCommandAsync();
                 orderSnapshot = await _orderSnapshotRepository.GetAsync(order.Id);
-                var replyDto = new GuiderSystemInDto
-                {
-                    ReplyCode = order.No,
-                    AppealNumber = orderSnapshot.NetworkENumber,
-                    ReplyDate = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"),
-                    ReplyUserName = "18181552753@zgsg",
-                    ReplyBMName = "瓦市村村民委员会",
-                    ReplyResultType = "2",
-                    ReplyISTrue = "1",
-                    IsRepeat = "0",
-                    IsHiddenDanger = "1",
-                    MemberName = "许利洪",
-                    MemberMobile = "18181552753",
-                    ReplyContent = "到现场查实,存在安全隐患",
-                    OrgId = "4828",
-                    OrgName = "瓦市村民委员会" + DateTime.Now.ToString("ss"),
-                    OrgFullName = "四川省/自贡市/沿滩区/永安镇/瓦市村村民委员会" + DateTime.Now.ToString("ss"),
-                    DepartmentNo = "510311106206",
-                    ParentOrgId = "4821",
-                    ReplyFileList = new List<string>
-                    {
-                        "http://10.0.188.11:1234/tqOssManager/getObjectByUri/sichuan/scgrid/jpg/2024/12/5/095020318625.jpg"
-                    }
-                };
+                var replyDto =  mock.GetGuiderSystemInDto(orderSnapshot.NetworkENumber);
                 await _snapshotApplication.SaveGuiderSystemReplyAsync(replyDto, CancellationToken.None);
+                orderSnapshot = await _orderSnapshotRepository.GetAsync(order.Id);
+                orderSnapshot.CommunityName.ShouldNotBeNull();
                 var orderReply = await _orderSnapshotRepository.GetByNetworkENumberAsync(replyDto.AppealNumber);
-                orderReply.IsDanger.ShouldBe(true);
+                orderReply.IsDanger.ShouldBe(replyDto.IsHiddenDanger == "1" ? true : false);
                 orderReply.MemberMobile.ShouldBe(replyDto.MemberMobile);
                 orderReply.MemberName.ShouldBe(replyDto.MemberName);
                 orderReply.NetworkRemark.ShouldBe(replyDto.ReplyContent);
@@ -159,8 +144,10 @@ public class OrderSnapshotApplicationTest : TestBase
             {
                 var log = _snapshotLabelLogRepository.Queryable().Where(m => m.OrderId == order.Id).First();
                 log.ShouldNotBeNull();
+                await _orderSnapshotApplication.UpdateIsEmphasisAsync(new UpdateIsEmphasisInDto { Ids = [order.Id]});
                 var snapshot = _orderSnapshotRepository.Get(order.Id);
                 snapshot.LabelName.ShouldBe(string.Join(',', inputLable.Select(m => m.DicDataName)), "label异常");
+                snapshot.IsEmphasis.ShouldBe(true);
             })
             .部门审核网格员红包(Set政法委)
             .部门审核网格员红包(Set应急管理局)
@@ -179,6 +166,14 @@ public class OrderSnapshotApplicationTest : TestBase
                 var redPackRecord = _redPackRecordRepository.Queryable().Where(m => m.OrderId == order.Id).First();
                 redPackRecord.ShouldNotBeNull();
             })
+            .部门审核特殊红包(Set应急管理局)
+            .StepHandle(async order => 
+            {
+                 var baseData = await _redPackApplication.GetRedPackRecordBaseDataAsync(order.Id);
+                baseData.AuditType.ShouldNotBeNull();
+                baseData.AuditTypeCode.ShouldNotBeNull();
+                baseData.Amount.ShouldNotBeNull();
+            })
             .GetCreateResult();
         order.Id.ShouldNotBeNull();
     }
@@ -219,5 +214,13 @@ public class OrderSnapshotApplicationTest : TestBase
         var sigedItems = await _orderSnapshotApplication.GetLabeledOrderSnapshotItems(new LabeledOrderSnapshotItemsInDto()).ToListAsync();
         sigedItems.Any(m => m.OrderId == order.Id).ShouldBe(true);
     }
+
+    [Fact]
+    public async Task GetOrderSnapshotElectrogasItems_Test()
+    {
+        var inDto = new OrderSnapshotItemsInDto();
+        var items = (await _orderSnapshotApplication.GetOrderSnapshotElectrogasItems(inDto).ToPagedListAsync(inDto));
+        items.Total.ShouldNotBe(0);
+    }
 }
 

+ 19 - 19
test/Hotline.Tests/Application/RedPackApplicationTest.cs

@@ -64,7 +64,7 @@ public class RedPackApplicationTest : TestBase
             .办理到归档(Set一级部门)
             .发布工单(SetZuoXi, _systemDicDataCacheManager.SnapshotOrderLabel.Where(m => m.DicDataValue == "bss").Select(m => new Kv(m.DicDataName, m.DicDataName)).ToList())
             .部门审核市民红包(Set应急管理局)
-            .StepHandle(async order => 
+            .StepHandle(async order =>
             {
                 var items = await _redPackApplication.GetRedPackSpecialAuditItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0)).ToListAsync();
                 items.Where(m => m.No == order.No).Count().ShouldBe(1);
@@ -75,26 +75,26 @@ public class RedPackApplicationTest : TestBase
                 items = await _redPackApplication.GetRedPackSpecialAuditItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 2)).ToListAsync();
                 items.Where(m => m.No == order.No).Count().ShouldBe(0);
             })
-            .部门审核特殊红包(Set应急管理局, 29)
-            .StepHandle(async order =>
-            {
-                var special = await _specialRedPackAuditRepository.Queryable().Where(m => m.OrderId == order.Id).FirstAsync();
-                special.ApprovedAmount.ShouldBe(29);
-                special.Status.ShouldBe(ERedPackAuditStatus.Agree);
-                special.AuditRemark.ShouldBe("红包审核通过");
-                var redPackAudit = await _redPackApplication.GetRedPackSpecialAuditBaseDataAsync(order.Id);
-                redPackAudit.AuditDetail.AuditId.ShouldNotBeNull();
-                redPackAudit.AuditDetail.AuditName.ShouldNotBeNull();
-                redPackAudit.AuditDetail.AuditOrgId.ShouldNotBeNull();
-                redPackAudit.AuditDetail.AuditOrgName.ShouldNotBeNull();
-                redPackAudit.AuditDetail.AuditRemark.ShouldNotBeNull("审核意见不能为空");
-                redPackAudit.AuditDetail.AuditRemark.ShouldBe("红包审核通过");
+            //.部门审核特殊红包(Set应急管理局, 29)
+            //.StepHandle(async order =>
+            //{
+            //    var special = await _specialRedPackAuditRepository.Queryable().Where(m => m.OrderId == order.Id).FirstAsync();
+            //    special.ApprovedAmount.ShouldBe(29);
+            //    special.Status.ShouldBe(ERedPackAuditStatus.Agree);
+            //    special.AuditRemark.ShouldBe("红包审核通过");
+            //    var redPackAudit = await _redPackApplication.GetRedPackSpecialAuditBaseDataAsync(order.Id);
+            //    redPackAudit.AuditDetail.AuditId.ShouldNotBeNull();
+            //    redPackAudit.AuditDetail.AuditName.ShouldNotBeNull();
+            //    redPackAudit.AuditDetail.AuditOrgId.ShouldNotBeNull();
+            //    redPackAudit.AuditDetail.AuditOrgName.ShouldNotBeNull();
+            //    redPackAudit.AuditDetail.AuditRemark.ShouldNotBeNull("审核意见不能为空");
+            //    redPackAudit.AuditDetail.AuditRemark.ShouldBe("红包审核通过");
 
-                var items = await _redPackApplication.GetRedPackSpecialAuditItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 1)).ToListAsync();
-                items.Count.ShouldNotBe(0, $"工单No: {order.No}");
-            })
+            //    var items = await _redPackApplication.GetRedPackSpecialAuditItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 1)).ToListAsync();
+            //    items.Count.ShouldNotBe(0, $"工单No: {order.No}");
+            //})
             .GetCreateResult();
-
+        order.Id.ShouldBeNull();
     }
 
     /// <summary>

+ 133 - 3
test/Hotline.Tests/Mock/OrderServiceMock.cs

@@ -27,6 +27,7 @@ using Hotline.FlowEngine.Notifications;
 using Hotline.Api.Controllers.Bi;
 using XF.Domain.Exceptions;
 using System;
+using DocumentFormat.OpenXml.Bibliography;
 
 namespace Hotline.Tests.Mock;
 public class OrderServiceMock
@@ -84,7 +85,7 @@ public class OrderServiceMock
         inDto.Street = "单元测试街道" + DateTime.Now.ToLongDateTimeString();
         inDto.IndustryId = industry.Id;
         inDto.Town = "仙市镇";
-        inDto.County = "沿滩区";
+        inDto.County = "大安区";
         inDto.Description = "单元测试添加的时间描述";
         inDto.IsSecret = false;
         inDto.PhoneNumber = _sessionContext.Phone;
@@ -431,6 +432,128 @@ public class OrderServiceMock
         return result;
     }
 
+    public GuiderSystemInDto GetGuiderSystemInDto(string number)
+    {
+        List<GuiderSystemInDto> items = [ new GuiderSystemInDto
+        {
+            ReplyCode = CreateOrderOutDto.No,
+            AppealNumber = number,
+            ReplyDate = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"),
+            ReplyUserName = "18181552753@zgsg",
+            ReplyBMName = "瓦市村村民委员会",
+            ReplyResultType = "2",
+            ReplyISTrue = "1",
+            IsRepeat = "0",
+            IsHiddenDanger = "1",
+            MemberName = "许利洪",
+            MemberMobile = "18181552753",
+            ReplyContent = "到现场查实,存在安全隐患",
+            OrgId = "4828",
+            OrgName = "瓦市村民委员会",
+            OrgFullName = "四川省/自贡市/沿滩区/永安镇/瓦市村村民委员会",
+            DepartmentNo = "510311106206",
+            ParentOrgId = "4821",
+            ReplyFileList =
+                    [
+                        "http://10.0.188.11:1234/tqOssManager/getObjectByUri/sichuan/scgrid/jpg/2024/12/5/095020318625.jpg"
+                    ]
+        },
+        new GuiderSystemInDto {
+            ReplyCode = CreateOrderOutDto.No,
+            AppealNumber = number,
+            ReplyDate = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"),
+            ReplyUserName = "18015707487@zgsg",
+            ReplyBMName = "大岩社区第一网格",
+            ReplyResultType = "2",
+            ReplyISTrue = "1",
+            IsRepeat = "0",
+            IsHiddenDanger = "1",
+            MemberName = "黄敬",
+            MemberMobile = "18015707487",
+            ReplyContent = "到现场查实,存在安全隐患",
+            OrgId = "138497",
+            OrgName = "大岩社区第一网格",
+            OrgFullName = "四川省/自贡市/自贡高新区/红旗街道/大岩社区居民委员会/大岩社区第一网格",
+            DepartmentNo = "510323004002001",
+            ParentOrgId = "137874",
+            ReplyFileList =
+                    [
+                        "http://10.0.188.11:1234/tqOssManager/getObjectByUri/sichuan/scgrid/jpg/2024/12/5/095020318625.jpg"
+                    ]
+        },
+        new GuiderSystemInDto {
+            ReplyCode = CreateOrderOutDto.No,
+            AppealNumber = number,
+            ReplyDate = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"),
+            ReplyUserName = "18015707367@zgsg",
+            ReplyBMName = "悦景社区第一网格",
+            ReplyResultType = "2",
+            ReplyISTrue = "1",
+            IsRepeat = "0",
+            IsHiddenDanger = "0",
+            MemberName = "余文惠",
+            MemberMobile = "18015707367",
+            ReplyContent = "确认情况属实,但是不属于我们管辖。属于市政工程。",
+            OrgId = "138563",
+            OrgName = "悦景社区第一网格",
+            OrgFullName = "四川省/自贡市/自贡高新区/红旗街道/悦景社区居民委员会/悦景社区第一网格",
+            DepartmentNo = "510323004004001",
+            ParentOrgId = "137875",
+            ReplyFileList =
+                    [
+                        "http://10.0.188.11:1234/tqOssManager/getObjectByUri/sichuan/scgrid/jpg/2024/12/5/095020318625.jpg"
+                    ]
+        },
+        new GuiderSystemInDto {
+            ReplyCode = CreateOrderOutDto.No,
+            AppealNumber = number,
+            ReplyDate = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"),
+            ReplyUserName = "18015707408@zgsg",
+            ReplyBMName = "大湾社区第一网格",
+            ReplyResultType = "2",
+            ReplyISTrue = "1",
+            IsRepeat = "0",
+            IsHiddenDanger = "0",
+            MemberName = "邓文文",
+            MemberMobile = "15928137497",
+            ReplyContent = "网格员到现场核实,情况属实,此地方属于物业处理,已通知物业及时处理。",
+            OrgId = "138520",
+            OrgName = "大湾社区第一网格",
+            OrgFullName = "四川省/自贡市/自贡高新区/红旗街道/大湾社区居民委员会/大湾社区第一网格",
+            DepartmentNo = "510323004001001",
+            ParentOrgId = "137873",
+            ReplyFileList =
+                    [
+                        "http://10.0.188.11:1234/tqOssManager/getObjectByUri/sichuan/scgrid/jpg/2024/12/5/095020318625.jpg"
+                    ]
+        },
+        new GuiderSystemInDto {
+            ReplyCode = CreateOrderOutDto.No,
+            AppealNumber = number,
+            ReplyDate = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"),
+            ReplyUserName = "18015707443@zgsg",
+            ReplyBMName = "明珠社区第一网格",
+            ReplyResultType = "2",
+            ReplyISTrue = "",
+            IsRepeat = "",
+            IsHiddenDanger = "",
+            MemberName = "周洪英",
+            MemberMobile = "15881342458",
+            ReplyContent = "现场查看情况属实,属于汇东公园管辖范围",
+            OrgId = "138372",
+            OrgName = "明珠社区第一网格",
+            OrgFullName = "四川省/自贡市/自贡高新区/丹桂街道/明珠社区居民委员会/明珠社区第一网格",
+            DepartmentNo = "510323001010001",
+            ParentOrgId = "137777",
+            ReplyFileList =
+                    [
+                        "http://10.0.188.11:1234/tqOssManager/getObjectByUri/sichuan/scgrid/jpg/2024/12/5/095020318625.jpg"
+                    ]
+        }];
+        var index = new Random().Next(0, items.Count);
+        return items[index];
+    }
+
     private string UploadFileFromMemory(byte[] fileBytes, string fileName, string uploadUrl)
     {
         using HttpClient client = new HttpClient();
@@ -447,12 +570,19 @@ public class OrderServiceMock
         return result;
     }
 
+    public OrderServiceMock StepHandle(Func<CreateOrderOutDto, OrderServiceMock, Task> handle)
+    {
+        handle(CreateOrderOutDto, this).GetAwaiter().GetResult();
+        return this;
+    }
+
     public OrderServiceMock StepHandle(Func<CreateOrderOutDto, Task> handle)
     {
         handle(CreateOrderOutDto).GetAwaiter().GetResult();
         return this;
     }
 
+
     public OrderServiceMock 办理到工单标注(Action action = null)
     {
         action?.Invoke();
@@ -488,7 +618,7 @@ public class OrderServiceMock
     public OrderServiceMock 部门审核特殊红包(Action action, double? approvedAmount = 0)
     {
         action?.Invoke();
-        var baseData = _redPackController.GetRedPackSpecialItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0)).GetAwaiter().GetResult();
+        var baseData = _redPackController.GetRedPackSpecialAuditItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0)).GetAwaiter().GetResult();
         var item = baseData.Items.FirstOrDefault(m => m.No == CreateOrderOutDto.No);
         var basedata = _systemDicDataCacheManager.SnapshotRedPackSpecialType.First();
         if (item == null)
@@ -496,7 +626,7 @@ public class OrderServiceMock
         var inDto = new UpdateRedPackSpecialAuditInDto
         {
             AuditTypeId = basedata.Id,
-            ApprovedAmount = approvedAmount,
+            ApprovedAmount = double.Parse(basedata.DicDataName.Split('|')[1]),
             RedPackAuditId = item.RedPackAuditId,
             Status = ERedPackAuditStatus.Agree,
             Opinion = "红包审核通过",

+ 5 - 0
test/Hotline.Tests/Startup.cs

@@ -11,6 +11,7 @@ using Hotline.Application.Jobs;
 using Hotline.Application.StatisticalReport.CallReport;
 using Hotline.Authentications;
 using Hotline.CallCenter.Configs;
+using Hotline.CallCenter.Tels;
 using Hotline.Configurations;
 using Hotline.DI;
 using Hotline.EventBus;
@@ -51,6 +52,7 @@ using XF.Domain.Repository.Events;
 using XF.EasyCaching;
 using XF.Utility.MQ;
 using Xunit.DependencyInjection.AspNetCoreTesting;
+using Hotline.Pdf;
 
 namespace Hotline.Tests;
 public class Startup
@@ -111,6 +113,8 @@ public class Startup
             //mq
             services.AddTestMq(configuration);
 
+            services.AddPdfManager();
+
             services.AddScoped<IDataPermissionFilterBuilder, DataPermissionFilterBuilder>();
             services.AddScoped(typeof(IRepository<>), typeof(BaseRepository<>));
             //services.AddScoped<IHttpContextAccessor, DefaultHttpContextAccessor>();
@@ -181,6 +185,7 @@ public class Startup
             services.AddScoped<IFileDomainService, FileDomainService>();
             services.AddScoped<IGuiderSystemService, TiqnQueService>();
             services.AddScoped<IWorkflowDomainService, WorkflowDomainService>();
+            services.AddScoped<ICallTelClient,XingTang.CallTelClient>();
 
             //ServiceLocator.Instance = services.BuildServiceProvider();
         }

+ 3 - 0
test/Hotline.Tests/appsettings.Development.json

@@ -12,6 +12,7 @@
     "AppConfiguration": {
         "AppScope": "ZiGong",
         "YiBin": {
+            "AreaCode": "511500",
             "CallCenterType": "TianRun", //XunShi、WeiErXin、TianRun、XingTang
             //智能回访
             "AiVisit": {
@@ -33,9 +34,11 @@
             }
         },
         "ZiGong": {
+            "AreaCode": "510300",
             "CallCenterType": "XingTang"
         },
         "LuZhou": {
+            "AreaCode": "510500",
             "CallCenterType": "XingTang"
         }
     },