Browse Source

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

tangjiang 1 tháng trước cách đây
mục cha
commit
b516bd7b24

+ 259 - 136
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -2186,7 +2186,7 @@ namespace Hotline.Api.Controllers.Bi
                 })
                 .FirstAsync();
 
-			if (listInfo != null && listInfo.Rows.Count > 0 && orderAgingData != null)
+            if (listInfo != null && listInfo.Rows.Count > 0 && orderAgingData != null)
             {
                 orderAgingData.OrderCount = orderAgingData.OrderCount + Convert.ToInt32(listInfo.Rows[0]["AllCount"]);
                 orderAgingData.CompletedAging = orderAgingData.CompletedAging + Convert.ToInt32(listInfo.Rows[0]["OrderWorkTime"]);
@@ -2636,7 +2636,7 @@ namespace Hotline.Api.Controllers.Bi
                 })
                 .FirstAsync();
 
-			enterpriseOrderDto.InProgressCount = enterpriseOrderData.InProgressCount;
+            enterpriseOrderDto.InProgressCount = enterpriseOrderData.InProgressCount;
             enterpriseOrderDto.CompletedCount = enterpriseOrderData.CompletedCount;
             enterpriseOrderDto.CenterCount = enterpriseOrderData.CenterCount;
             enterpriseOrderDto.CityCount = enterpriseOrderData.CityCount;
@@ -2648,20 +2648,20 @@ namespace Hotline.Api.Controllers.Bi
                 .Where((it, so) => it.VisitTarget == EVisitTarget.Org && it.OrderVisit.VisitTime >= StartTime && it.OrderVisit.VisitTime <= EndTime && it.OrderVisit.VisitState == EVisitState.Visited && it.OrderVisit.Order.IdentityType == EIdentityType.Enterprise)
                 .GroupBy((it, so) => it.Id)
                 .Select((it, so) => new EnterpriseOrderDto
-                 {
-                     VisitdCount = SqlFunc.AggregateCount(1),
-					 Dissatisfied = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") || SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2"), 1, 0)),
-                     Satisfied = SqlFunc.AggregateSum(SqlFunc.IIF(!SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") && !SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2"), 1, 0)),
-                     CityDissatisfied = SqlFunc.AggregateSum(SqlFunc.IIF((SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") || SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2")) && so.OrgType == EOrgType.City, 1, 0)),
-                     CitySatisfied = SqlFunc.AggregateSum(SqlFunc.IIF(!SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") && !SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2") && so.OrgType == EOrgType.City, 1, 0)),
-                     CountyDissatisfied = SqlFunc.AggregateSum(SqlFunc.IIF((SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") || SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2")) && so.OrgType == EOrgType.County, 1, 0)),
-                     CountySatisfied = SqlFunc.AggregateSum(SqlFunc.IIF(!SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") && !SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2") && so.OrgType == EOrgType.County, 1, 0)),
-                 })
+                {
+                    VisitdCount = SqlFunc.AggregateCount(1),
+                    Dissatisfied = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") || SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2"), 1, 0)),
+                    Satisfied = SqlFunc.AggregateSum(SqlFunc.IIF(!SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") && !SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2"), 1, 0)),
+                    CityDissatisfied = SqlFunc.AggregateSum(SqlFunc.IIF((SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") || SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2")) && so.OrgType == EOrgType.City, 1, 0)),
+                    CitySatisfied = SqlFunc.AggregateSum(SqlFunc.IIF(!SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") && !SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2") && so.OrgType == EOrgType.City, 1, 0)),
+                    CountyDissatisfied = SqlFunc.AggregateSum(SqlFunc.IIF((SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") || SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2")) && so.OrgType == EOrgType.County, 1, 0)),
+                    CountySatisfied = SqlFunc.AggregateSum(SqlFunc.IIF(!SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "1") && !SqlFunc.JsonListObjectAny(it.OrgProcessingResults, "key", "2") && so.OrgType == EOrgType.County, 1, 0)),
+                })
                 .ToListAsync();
 
-			if (enterpriseOrderDto2.Any())
+            if (enterpriseOrderDto2.Any())
             {
-                centerReportStatisticsDto.EnterpriseOrderDto.VisitdCount = enterpriseOrderDto2.Sum(x=>x.VisitdCount);
+                centerReportStatisticsDto.EnterpriseOrderDto.VisitdCount = enterpriseOrderDto2.Sum(x => x.VisitdCount);
                 centerReportStatisticsDto.EnterpriseOrderDto.Dissatisfied = enterpriseOrderDto2.Sum(x => x.Dissatisfied);
                 centerReportStatisticsDto.EnterpriseOrderDto.CityDissatisfied = enterpriseOrderDto2.Sum(x => x.CityDissatisfied);
                 centerReportStatisticsDto.EnterpriseOrderDto.CountyDissatisfied = enterpriseOrderDto2.Sum(x => x.CountyDissatisfied);
@@ -3180,6 +3180,129 @@ namespace Hotline.Api.Controllers.Bi
             return ExcelStreamResult(stream, "部门受理类型统计周期数据");
         }
 
+
+        /// <summary>
+        /// 部门受理类型统计(宜宾原始功能)
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("department_acceptance_type_statistics_v1")]
+        public async Task<object> DepartmentAcceptanceTypeStatisticsV1([FromQuery] DepartmentKeyWordRequest dto)
+        {
+            var items = await _orderReportApplication.DepartmentAcceptanceTypeStatisticsV1(dto).ToListAsync();
+
+            var countySumModel = new DepartmentAcceptanceTypeStatisticsV1Dto()
+            {
+                OrgName = "区县合计",
+                OrgCode = "",
+                OrgTypeText = "",
+                ZxAllCount = items.Where(x => x.OrgType == EOrgType.County).Sum(p => p.ZxAllCount),
+                ZxAcceptanceTypeCode = "10",
+
+                JyAllCount = items.Where(x => x.OrgType == EOrgType.County).Sum(p => p.JyAllCount),
+                JyAcceptanceTypeCode = "15",
+
+                QzAllCount = items.Where(x => x.OrgType == EOrgType.County).Sum(p => p.QzAllCount),
+                QzAcceptanceTypeCode = "20",
+
+                ByAllCount = items.Where(x => x.OrgType == EOrgType.County).Sum(p => p.ByAllCount),
+                ByAcceptanceTypeCode = "25",
+
+                JbAllCount = items.Where(x => x.OrgType == EOrgType.County).Sum(p => p.JbAllCount),
+                JbAcceptanceTypeCode = "30",
+
+                TsAllCount = items.Where(x => x.OrgType == EOrgType.County).Sum(p => p.TsAllCount),
+                TsAcceptanceTypeCode = "35",
+
+                QtAllCount = items.Where(x => x.OrgType == EOrgType.County).Sum(p => p.QtAllCount),
+                QtAcceptanceTypeCode = "40",
+
+                YjAllCount = items.Where(x => x.OrgType == EOrgType.County).Sum(p => p.YjAllCount),
+                YjAcceptanceTypeCode = "1",
+
+                HmAllCount = items.Where(x => x.OrgType == EOrgType.County).Sum(p => p.HmAllCount),
+                HmAcceptanceTypeCode = "2",
+
+                DqAllCount = items.Where(x => x.OrgType == EOrgType.County).Sum(p => p.DqAllCount),
+                DqAcceptanceTypeCode = "3"
+            };
+
+            var citySumModel = new DepartmentAcceptanceTypeStatisticsV1Dto()
+            {
+                OrgName = "市直合计",
+                OrgCode = "",
+                OrgTypeText = "",
+                ZxAllCount = items.Where(x => x.OrgType == EOrgType.City && x.OrgCode != "001").Sum(p => p.ZxAllCount),
+                ZxAcceptanceTypeCode = "10",
+
+                JyAllCount = items.Where(x => x.OrgType == EOrgType.City && x.OrgCode != "001").Sum(p => p.JyAllCount),
+                JyAcceptanceTypeCode = "15",
+
+                QzAllCount = items.Where(x => x.OrgType == EOrgType.City && x.OrgCode != "001").Sum(p => p.QzAllCount),
+                QzAcceptanceTypeCode = "20",
+
+                ByAllCount = items.Where(x => x.OrgType == EOrgType.City && x.OrgCode != "001").Sum(p => p.ByAllCount),
+                ByAcceptanceTypeCode = "25",
+
+                JbAllCount = items.Where(x => x.OrgType == EOrgType.City && x.OrgCode != "001").Sum(p => p.JbAllCount),
+                JbAcceptanceTypeCode = "30",
+
+                TsAllCount = items.Where(x => x.OrgType == EOrgType.City && x.OrgCode != "001").Sum(p => p.TsAllCount),
+                TsAcceptanceTypeCode = "35",
+
+                QtAllCount = items.Where(x => x.OrgType == EOrgType.City && x.OrgCode != "001").Sum(p => p.QtAllCount),
+                QtAcceptanceTypeCode = "40",
+
+                YjAllCount = items.Where(x => x.OrgType == EOrgType.City && x.OrgCode != "001").Sum(p => p.YjAllCount),
+                YjAcceptanceTypeCode = "1",
+
+                HmAllCount = items.Where(x => x.OrgType == EOrgType.City && x.OrgCode != "001").Sum(p => p.HmAllCount),
+                HmAcceptanceTypeCode = "2",
+
+                DqAllCount = items.Where(x => x.OrgType == EOrgType.City && x.OrgCode != "001").Sum(p => p.DqAllCount),
+                DqAcceptanceTypeCode = "3"
+            };
+
+            var sumModel = new DepartmentAcceptanceTypeStatisticsV1Dto()
+            {
+                OrgName = "总计",
+                OrgCode = "",
+                OrgTypeText = "",
+                ZxAllCount = items.Sum(p => p.ZxAllCount),
+                ZxAcceptanceTypeCode = "10",
+
+                JyAllCount = items.Sum(p => p.JyAllCount),
+                JyAcceptanceTypeCode = "15",
+
+                QzAllCount = items.Sum(p => p.QzAllCount),
+                QzAcceptanceTypeCode = "20",
+
+                ByAllCount = items.Sum(p => p.ByAllCount),
+                ByAcceptanceTypeCode = "25",
+
+                JbAllCount = items.Sum(p => p.JbAllCount),
+                JbAcceptanceTypeCode = "30",
+
+                TsAllCount = items.Sum(p => p.TsAllCount),
+                TsAcceptanceTypeCode = "35",
+
+                QtAllCount = items.Sum(p => p.QtAllCount),
+                QtAcceptanceTypeCode = "40",
+
+                YjAllCount = items.Sum(p => p.YjAllCount),
+                YjAcceptanceTypeCode = "1",
+
+                HmAllCount = items.Sum(p => p.HmAllCount),
+                HmAcceptanceTypeCode = "2",
+
+                DqAllCount = items.Sum(p => p.DqAllCount),
+                DqAcceptanceTypeCode = "3"
+            };
+
+            return new { DataList = items, CountySumModel = countySumModel, CitySumModel = citySumModel, SumModel = sumModel };
+        }
+
+
         /// <summary>
         /// 部门办件统计表
         /// </summary>
@@ -5861,123 +5984,123 @@ namespace Hotline.Api.Controllers.Bi
                    .ToListAsync(HttpContext.RequestAborted);
         }
 
-		/// <summary>
-		/// 超期退回统计
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpGet("extended_sendback_statistics")]
-		public async Task<List<ExtendedSendBackVo>> ExtendedSendBackStatistics([FromQuery] PagedKeywordRequest dto)
-		{
-			var quer = _orderApplication.ExtendedSendBackStatistics(dto);
+        /// <summary>
+        /// 超期退回统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("extended_sendback_statistics")]
+        public async Task<List<ExtendedSendBackVo>> ExtendedSendBackStatistics([FromQuery] PagedKeywordRequest dto)
+        {
+            var quer = _orderApplication.ExtendedSendBackStatistics(dto);
             var list = await quer.ToListAsync(HttpContext.RequestAborted);
-			list.Add(new ExtendedSendBackVo()
-			{
-                OrgName ="合计",
-				TotalNum = list.Sum(m => m.TotalNum),
-				PassNum = list.Sum(p => p.PassNum),
-				NoPassNum = list.Sum(m => m.NoPassNum),
-				AuditNum = list.Sum(m => m.AuditNum)
-			});
-
-			return list;
-		}
-
-		/// <summary>
-		/// 超期退回统计导出
-		/// </summary>
-		/// <returns></returns>
-		[HttpPost("extended_sendback_statistics/_export")]
-		public async Task<FileStreamResult> ExtendedSendBackStatisticsExport([FromBody] ExportExcelDto<PagedKeywordRequest> dto)
-		{
-			var query = _orderApplication.ExtendedSendBackStatistics(dto.QueryDto);
-			List<ExtendedSendBackVo> data;
-
-			data = await query.ToListAsync(HttpContext.RequestAborted);
-
-			data.Add(new ExtendedSendBackVo()
-			{
-				OrgName = "合计",
-				TotalNum = data.Sum(m => m.TotalNum),
-				PassNum = data.Sum(p => p.PassNum),
-				NoPassNum = data.Sum(m => m.NoPassNum),
-				AuditNum = data.Sum(m => m.AuditNum)
-			});
-
-			dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-
-			var dtos = data
-				.Select(stu => _mapper.Map(stu, typeof(ExtendedSendBackVo), dynamicClass))
-				.Cast<object>()
-				.ToList();
-
-			var stream = ExcelHelper.CreateStream(dtos);
-
-			return ExcelStreamResult(stream, "超期退回统计");
-		}
-
-		/// <summary>
-		/// 超期退回统计明细
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpGet("extended_sendback_detail")]
-		public async Task<PagedDto<SendBackDto>> ExtendedSendBackDetail([FromQuery] ExtendedSendBackRequest dto)
-		{
-			var quer = _orderApplication.ExtendedSendBackDetail(dto);
-			var (total, items) = await quer.ToPagedListAsync(dto.PageIndex, dto.PageSize);
-
-			return new PagedDto<SendBackDto>(total, _mapper.Map<IReadOnlyList<SendBackDto>>(items));
-		}
-
-		/// <summary>
-		/// 超期退回统计明细导出
-		/// </summary>
-		/// <returns></returns>
-		[HttpPost("extended_sendback_detail/_export")]
-		public async Task<FileStreamResult> ExtendedSendBackDetailExport([FromBody] ExportExcelDto<ExtendedSendBackRequest> dto)
-		{
-			var query = _orderApplication.ExtendedSendBackDetail(dto.QueryDto);
-			List<OrderSendBackAudit> data;
-			if (dto.IsExportAll)
-			{
-				data = await query.ToListAsync(HttpContext.RequestAborted);
-			}
-			else
-			{
-				var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
-				data = items;
-			}
-
-			var dataDtos = _mapper.Map<ICollection<SendBackDto>>(data);
-
-			dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-
-			var dtos = dataDtos
-				.Select(stu => _mapper.Map(stu, typeof(SendBackDto), dynamicClass))
-				.Cast<object>()
-				.ToList();
-
-			var stream = ExcelHelper.CreateStream(dtos);
-
-			return ExcelStreamResult(stream, "超期退回统计明细");
-		}
-
-		/// <summary>
-		/// 列表页面基础数据
-		/// </summary>
-		/// <returns></returns>
-		[HttpGet("extended_sendback_detail/base-data")]
-		public async Task<object> ExtendedSendBackDetailBaseData()
-		{
-			var rsp = new
-			{
-				AcceptTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType),
-				ChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel),
-				SendBackAuditState = EnumExts.GetDescriptions<ESendBackAuditState>()
-			};
-			return rsp;
-		}
+            list.Add(new ExtendedSendBackVo()
+            {
+                OrgName = "合计",
+                TotalNum = list.Sum(m => m.TotalNum),
+                PassNum = list.Sum(p => p.PassNum),
+                NoPassNum = list.Sum(m => m.NoPassNum),
+                AuditNum = list.Sum(m => m.AuditNum)
+            });
+
+            return list;
+        }
+
+        /// <summary>
+        /// 超期退回统计导出
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost("extended_sendback_statistics/_export")]
+        public async Task<FileStreamResult> ExtendedSendBackStatisticsExport([FromBody] ExportExcelDto<PagedKeywordRequest> dto)
+        {
+            var query = _orderApplication.ExtendedSendBackStatistics(dto.QueryDto);
+            List<ExtendedSendBackVo> data;
+
+            data = await query.ToListAsync(HttpContext.RequestAborted);
+
+            data.Add(new ExtendedSendBackVo()
+            {
+                OrgName = "合计",
+                TotalNum = data.Sum(m => m.TotalNum),
+                PassNum = data.Sum(p => p.PassNum),
+                NoPassNum = data.Sum(m => m.NoPassNum),
+                AuditNum = data.Sum(m => m.AuditNum)
+            });
+
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+
+            var dtos = data
+                .Select(stu => _mapper.Map(stu, typeof(ExtendedSendBackVo), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "超期退回统计");
+        }
+
+        /// <summary>
+        /// 超期退回统计明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("extended_sendback_detail")]
+        public async Task<PagedDto<SendBackDto>> ExtendedSendBackDetail([FromQuery] ExtendedSendBackRequest dto)
+        {
+            var quer = _orderApplication.ExtendedSendBackDetail(dto);
+            var (total, items) = await quer.ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+            return new PagedDto<SendBackDto>(total, _mapper.Map<IReadOnlyList<SendBackDto>>(items));
+        }
+
+        /// <summary>
+        /// 超期退回统计明细导出
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost("extended_sendback_detail/_export")]
+        public async Task<FileStreamResult> ExtendedSendBackDetailExport([FromBody] ExportExcelDto<ExtendedSendBackRequest> dto)
+        {
+            var query = _orderApplication.ExtendedSendBackDetail(dto.QueryDto);
+            List<OrderSendBackAudit> data;
+            if (dto.IsExportAll)
+            {
+                data = await query.ToListAsync(HttpContext.RequestAborted);
+            }
+            else
+            {
+                var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+                data = items;
+            }
+
+            var dataDtos = _mapper.Map<ICollection<SendBackDto>>(data);
+
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+
+            var dtos = dataDtos
+                .Select(stu => _mapper.Map(stu, typeof(SendBackDto), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "超期退回统计明细");
+        }
+
+        /// <summary>
+        /// 列表页面基础数据
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("extended_sendback_detail/base-data")]
+        public async Task<object> ExtendedSendBackDetailBaseData()
+        {
+            var rsp = new
+            {
+                AcceptTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType),
+                ChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel),
+                SendBackAuditState = EnumExts.GetDescriptions<ESendBackAuditState>()
+            };
+            return rsp;
+        }
 
         /// <summary>
         /// 网上群众路线通报
@@ -5989,9 +6112,9 @@ namespace Hotline.Api.Controllers.Bi
         {
             var nowList = await _orderRepository.Queryable()
                 .Where(x => x.CreationTime >= dto.StartTime && x.CreationTime <= dto.EndTime).ToListAsync();
-                
 
-            var oldList =await _orderRepository.Queryable()
+
+            var oldList = await _orderRepository.Queryable()
                 .Where(x => x.CreationTime >= dto.ChainStartTime && x.CreationTime <= dto.ChainEndTime).ToListAsync();
 
 
@@ -5999,7 +6122,7 @@ namespace Hotline.Api.Controllers.Bi
             //市12345政务服务便民热线
             var Other = new OnlineMassLineReportRes();
             Other.SourceChannel = "市12345政务服务便民热线";
-            Other.SumCount = nowList.Where(x => x.IsProvince==false && x.SourceChannelCode != "SZYSM").Count(); //市12345政务服务便民热线
+            Other.SumCount = nowList.Where(x => x.IsProvince == false && x.SourceChannelCode != "SZYSM").Count(); //市12345政务服务便民热线
             Other.PreviousCount = oldList.Where(x => x.IsProvince == false && x.SourceChannelCode != "SZYSM").Count(); //市12345政务服务便民热线
             returnList.Add(Other);
             //中国政府网“我向总理说句话”
@@ -6017,16 +6140,16 @@ namespace Hotline.Api.Controllers.Bi
             //省12345政务服务便民热线
             var Province12345 = new OnlineMassLineReportRes();
             Province12345.SourceChannel = "省12345政务服务便民热线";
-            Province12345.SumCount = nowList.Where(x => x.IsProvince == true && x.ReceiveProvinceNo.StartsWith("GJZWFWPT")==false && x.ReceiveProvinceNo.StartsWith("ZGZFW")==false).Count(); //国家政务服务平台“投诉与建议”
-            Province12345.PreviousCount = oldList.Where(x => x.IsProvince == true && x.ReceiveProvinceNo.StartsWith("GJZWFWPT")==false && x.ReceiveProvinceNo.StartsWith("ZGZFW")==false).Count(); //国家政务服务平台“投诉与建议”
+            Province12345.SumCount = nowList.Where(x => x.IsProvince == true && x.ReceiveProvinceNo.StartsWith("GJZWFWPT") == false && x.ReceiveProvinceNo.StartsWith("ZGZFW") == false).Count(); //国家政务服务平台“投诉与建议”
+            Province12345.PreviousCount = oldList.Where(x => x.IsProvince == true && x.ReceiveProvinceNo.StartsWith("GJZWFWPT") == false && x.ReceiveProvinceNo.StartsWith("ZGZFW") == false).Count(); //国家政务服务平台“投诉与建议”
             returnList.Add(Province12345);
             //市政府网站“市长与网民”
             var SZYSM = new OnlineMassLineReportRes();
             SZYSM.SourceChannel = "市政府网站“市长与网民”";
-            SZYSM.SumCount = nowList.Where(x => x.SourceChannelCode=="SZYSM").Count(); //国家政务服务平台“投诉与建议”
+            SZYSM.SumCount = nowList.Where(x => x.SourceChannelCode == "SZYSM").Count(); //国家政务服务平台“投诉与建议”
             SZYSM.PreviousCount = oldList.Where(x => x.SourceChannelCode == "SZYSM").Count(); //国家政务服务平台“投诉与建议”
             returnList.Add(SZYSM);
             return returnList;
         }
-	}
+    }
 }

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

@@ -363,31 +363,31 @@ namespace Hotline.Api.Controllers
                    RSFlagName = p.Status >= EOrderStatus.Filed ? "办理完成" : "办理中"
                });
 
-            var queryold = _oldPublicDataRepository.Queryable()
-                      .WhereIF(!string.IsNullOrEmpty(dto.FlowCode), p => p.OrderNo == dto.FlowCode)
-                      .WhereIF(!string.IsNullOrEmpty(dto.FlowName), p => p.Title.Contains(dto.FlowName))
-                      .WhereIF(!string.IsNullOrEmpty(dto.FlowSType), p => p.AcceptTypeCode == dto.FlowSType)
-                      .WhereIF(!string.IsNullOrEmpty(dto.FlowRType), p => p.HotspotId == dto.FlowRType)
-                      .WhereIF(!string.IsNullOrEmpty(dto.FlowSDate), p => p.AcceptTime >= DateTime.Parse(DateTime.Parse(dto.FlowSDate).ToString("yyyy-MM-dd 00:00:00")))//dto.FlowSDate
-                      .WhereIF(!string.IsNullOrEmpty(dto.FlowEDate), p => p.AcceptTime <= DateTime.Parse(DateTime.Parse(dto.FlowEDate).ToString("yyyy-MM-dd 00:00:00")))// dto.FlowEDate
-                      .WhereIF(!string.IsNullOrEmpty(dto.FlowFrom), p => p.FromName.Contains(dto.FlowFrom))
-                      .WhereIF(dto.IdentityType.HasValue, p => p.IdentityType == dto.IdentityType)
-                      .OrderByDescending(p => p.PubDate)
-                        .Select(p => new OrderListDto
-                        {
-                            FlowID = p.OrderId,
-                            FlowCode = p.OrderNo,
-                            FlowPwd = p.OrderPwd,
-                            FlowTitle = p.Title,
-                            FlowFromName = p.SourceChannelCode,
-                            FlowPurTypeName = p.AcceptTypeCode,
-                            ConTypeName = p.HotspotName,
-                            FlowAddDate = p.CreationTime,
-                            PubDate = p.CreationTime,
-                            RSFlagName = p.State == "1" ? "办理完成" : "办理中"
-                        });
-
-            var (total, items) = await _orderRepository.UnionAll(queryNew, queryold)
+            //var queryold = _oldPublicDataRepository.Queryable()
+            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowCode), p => p.OrderNo == dto.FlowCode)
+            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowName), p => p.Title.Contains(dto.FlowName))
+            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowSType), p => p.AcceptTypeCode == dto.FlowSType)
+            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowRType), p => p.HotspotId == dto.FlowRType)
+            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowSDate), p => p.AcceptTime >= DateTime.Parse(DateTime.Parse(dto.FlowSDate).ToString("yyyy-MM-dd 00:00:00")))//dto.FlowSDate
+            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowEDate), p => p.AcceptTime <= DateTime.Parse(DateTime.Parse(dto.FlowEDate).ToString("yyyy-MM-dd 00:00:00")))// dto.FlowEDate
+            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowFrom), p => p.FromName.Contains(dto.FlowFrom))
+            //          .WhereIF(dto.IdentityType.HasValue, p => p.IdentityType == dto.IdentityType)
+            //          .OrderByDescending(p => p.PubDate)
+            //            .Select(p => new OrderListDto
+            //            {
+            //                FlowID = p.OrderId,
+            //                FlowCode = p.OrderNo,
+            //                FlowPwd = p.OrderPwd,
+            //                FlowTitle = p.Title,
+            //                FlowFromName = p.SourceChannelCode,
+            //                FlowPurTypeName = p.AcceptTypeCode,
+            //                ConTypeName = p.HotspotName,
+            //                FlowAddDate = p.CreationTime,
+            //                PubDate = p.CreationTime,
+            //                RSFlagName = p.State == "1" ? "办理完成" : "办理中"
+            //            });
+
+            var (total, items) = await queryNew
                 .OrderByDescending(p => p.PubDate)
                  .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
 

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

@@ -679,6 +679,7 @@ namespace Hotline.Api.Controllers
             var knowledge = await _knowledgeRepository.Queryable()
                 .Includes(x => x.SourceOrganize)
                 .Includes(x => x.KnowledgeTypes)
+                .Includes(x=>x.KnowledgeOrganizes)
                 .Includes(x => x.HotspotType)
                 .FirstAsync(p => p.Id == Id, HttpContext.RequestAborted);
             if (knowledge is null)

+ 7 - 7
src/Hotline.Api/Controllers/OrderController.cs

@@ -2981,13 +2981,13 @@ public class OrderController : BaseController
 	public async Task Update([FromBody] OrderScreenAlterDto dto)
 	{
         var screen = await _orderScreenRepository.GetAsync(dto.ScreenId);
-		var FileJson = new List<Share.Dtos.File.FileJson>();
-        if (dto.Files.Any())
-            FileJson = await _fileRepository.AddFileAsync(dto.Files, dto.ScreenId, "", HttpContext.RequestAborted);
-        else
-            FileJson = screen.FileJson;
+		//var FileJson = new List<Share.Dtos.File.FileJson>();
+  //      if (dto.Files.Any())
+  //          FileJson = await _fileRepository.AddFileAsync(dto.Files, dto.ScreenId, "", HttpContext.RequestAborted);
+  //      else
+  //          FileJson = screen.FileJson;
         dto.Content = string.IsNullOrEmpty(dto.Content) ? screen.Content : dto.Content;
-		await _orderScreenRepository.Updateable().SetColumns(x => new OrderScreen { Content = dto.Content,FileJson = FileJson })
+		await _orderScreenRepository.Updateable().SetColumns(x => new OrderScreen { Content = dto.Content })
 			.Where(x => x.Id == dto.ScreenId).ExecuteCommandAsync();
 	}
 
@@ -3758,7 +3758,7 @@ public class OrderController : BaseController
         if (_appOptions.Value.IsLuZhou && !_sessionContext.OrgIsCenter)
             orderDtos = orderDtos.Select(p => p.DataMask()).ToList();
 
-        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<OrderDto>(dto.ColumnInfos);
 
         var dtos = orderDtos
             .Select(stu => _mapper.Map(stu, typeof(OrderDto), dynamicClass))

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

@@ -41,6 +41,7 @@ using Hotline.Share.Enums.JudicialManagement;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Mq;
 using Hotline.ThirdAccountDomainServices.Interfaces;
+using Hotline.Tools;
 using Hotline.Users;
 using Mapster;
 using MapsterMapper;
@@ -50,6 +51,7 @@ using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
 using MiniExcelLibs;
 using NETCore.Encrypt;
+using Senparc.Weixin.MP.AdvancedAPIs.MerChant;
 using SqlSugar;
 using System.Threading;
 using XC.RSAUtil;
@@ -1475,4 +1477,75 @@ public class TestController : BaseController
     //    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFiled, orderFlowDto, cancellationToken: cancellationToken);
     //}
 
+    [AllowAnonymous]
+    [HttpGet("TestExport")]
+    public async Task<FileStreamResult> TestExport()
+    {
+        var columns = new List<ColumnInfo>
+        {
+            /*
+             *9
+               :
+               {prop: "title", name: "工单标题"}
+               10
+               :
+               {prop: "expiredTime", name: "期满时间"}
+
+               {prop: "reTransactNum", name: "重办次数"}
+             */
+            new ColumnInfo { Prop = "title", Name = "工单标题" },
+            new ColumnInfo { Prop = "expiredTime", Name = "期满时间" },
+            new ColumnInfo { Prop = "allDurationHour", Name = "办理时长" },
+            new ColumnInfo { Prop = "creationTimeHandleDuration", Name = "办结时长" },
+        };
+        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<OrderDto>(columns);
+
+        //var order = await _orderRepository.GetAsync("08dd65e7-7a7c-43ce-8212-242435a18216", HttpContext.RequestAborted);
+        //var dto = _mapper.Map<OrderDto>(order);
+
+        //var dtos = new List<MyClass> {
+        //    new MyClass
+        //{
+        //    Title = "测试标题",
+        //    ExpiredTime = DateTime.Now,
+        //    ReTransactNum = 12
+        //},
+        //    new MyClass
+        //    {
+        //        Title = "测试标题1",
+        //        ExpiredTime = DateTime.Now.AddDays(1),
+        //        ReTransactNum = 13
+        //    },
+        //    new MyClass
+        //    {
+        //        Title = "测试标题2",
+        //        ExpiredTime = DateTime.Now.AddDays(2),
+        //        ReTransactNum = 14
+        //    }
+        //};
+
+        //dynamic temp = _mapper.Map(dtos, typeof(List<MyClass>), dynamicClass);
+        var orders = await _orderRepository.Queryable()
+            .OrderByDescending(d => d.CreationTime)
+            .Take(10)
+            .ToListAsync(HttpContext.RequestAborted);
+
+        var orderDtos = _mapper.Map<List<OrderDto>>(orders);
+
+        var dtos = orderDtos
+            .Select(stu => _mapper.Map(stu, typeof(OrderDto), dynamicClass))
+            .Cast<object>()
+            .ToList();
+
+        var stream = ExcelHelper.CreateStream(dtos);
+
+        return ExcelStreamResult(stream, "工单数据");
+    }
+}
+
+class MyClass
+{
+    public string Title { get; set; }
+    public DateTime ExpiredTime { get; set; }
+    public int ReTransactNum { get; set; }
 }

+ 7 - 0
src/Hotline.Application/StatisticalReport/IOrderReportApplication.cs

@@ -117,6 +117,13 @@ namespace Hotline.Application.StatisticalReport
         /// <returns></returns>
         ISugarQueryable<DepartmentAcceptanceTypeStatisticsDto> DepartmentAcceptanceTypeStatistics(DepartmentKeyWordRequest dto);
 
+        /// <summary>
+        /// 部门受理类型统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<DepartmentAcceptanceTypeStatisticsV1Dto> DepartmentAcceptanceTypeStatisticsV1(DepartmentKeyWordRequest dto);
+
         /// <summary>
         /// 部门受理类型统计周期--明细列表
         /// </summary>

+ 73 - 0
src/Hotline.Application/StatisticalReport/OrderReportApplication.cs

@@ -23,6 +23,7 @@ using Hotline.Statistics;
 using Hotline.Users;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
+using Quartz.Simpl;
 using SqlSugar;
 using System.Data;
 using XF.Domain.Authentications;
@@ -2305,6 +2306,78 @@ namespace Hotline.Application.StatisticalReport
                  .MergeTable();
         }
 
+        /// <summary>
+        /// 部门受理类型统计周期(宜宾原始)
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<DepartmentAcceptanceTypeStatisticsV1Dto> DepartmentAcceptanceTypeStatisticsV1(DepartmentKeyWordRequest dto)
+        {
+            var IsCenter = _sessionContext.OrgIsCenter;
+            var centerOrgName = _systemSettingCacheManager.GetSetting(SettingConstants.CenterOrgName)?.SettingValue[0];
+
+
+            var orderData = _orderRepository.Queryable()
+              .WhereIF(dto.StartTime.HasValue, it => it.StartTime >= dto.StartTime)
+              .WhereIF(dto.EndTime.HasValue, it => it.StartTime <= dto.EndTime)
+              .WhereIF(dto.TypeId != null && dto.TypeId == 1, it => it.IdentityType == EIdentityType.Citizen)
+              .WhereIF(dto.TypeId != null && dto.TypeId == 2, it => it.IdentityType == EIdentityType.Enterprise)
+              .Select(it => new
+              {
+                  OrgCode = string.IsNullOrEmpty(dto.OrgCode) ? it.ActualHandleOrgCode.Substring(0, 6) : it.ActualHandleOrgCode.Substring(0, _sessionContext.RequiredOrgId.Length + 3),
+                  AcceptTypeCode = it.AcceptTypeCode
+              })
+              .MergeTable()
+
+              //.WhereIF(!IsCenter, p => p.OrgCode.StartsWith(_sessionContext.RequiredOrgId))
+
+              .LeftJoin<SystemOrganize>((it, o) => it.OrgCode == o.Id)
+              .GroupBy((it, o) => new
+              {
+                  it.OrgCode,
+                  o.Name,
+                  o.OrgType
+              })
+              .Select((it, o) => new DepartmentAcceptanceTypeStatisticsV1Dto
+              {
+                  OrgName = it.OrgCode == "001" ? centerOrgName : o.Name,
+                  OrgCode = it.OrgCode,
+                  OrgType = o.OrgType,
+                  OrgTypeText = o.OrgType == EOrgType.County ? "区县部门" : "市直部门",
+                  ZxAllCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "10", 1, 0)),
+                  ZxAcceptanceTypeCode = "10",
+
+                  JyAllCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "15", 1, 0)),
+                  JyAcceptanceTypeCode = "15",
+
+                  QzAllCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "20", 1, 0)),
+                  QzAcceptanceTypeCode = "20",
+
+                  ByAllCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "25", 1, 0)),
+                  ByAcceptanceTypeCode = "25",
+
+                  JbAllCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "30", 1, 0)),
+                  JbAcceptanceTypeCode = "30",
+
+                  TsAllCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "35", 1, 0)),
+                  TsAcceptanceTypeCode = "35",
+
+                  QtAllCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "40", 1, 0)),
+                  QtAcceptanceTypeCode = "40",
+
+                  YjAllCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "1", 1, 0)),
+                  YjAcceptanceTypeCode = "1",
+
+                  HmAllCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "2", 1, 0)),
+                  HmAcceptanceTypeCode = "2",
+
+                  DqAllCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "3", 1, 0)),
+                  DqAcceptanceTypeCode = "3"
+              }).MergeTable();
+            return orderData;
+        }
+
+
         /// <summary>
         /// 受理类型统计
         /// </summary>

+ 2 - 1
src/Hotline.Share/Dtos/Knowledge/KnowledgeDto.cs

@@ -268,7 +268,8 @@ namespace Hotline.Share.Dtos.Knowledge
         public List<FileJson>? FileJson { get; set; }
 
         public List<KnowledgeTypeDto> KnowledgeTypes { get; set; }
-    }
+		public List<OrgDto> KnowledgeOrganizes { get; set; }
+	}
 
     public class KnowledgeBaseDto {
 		public DateTime? LastModificationTime { get; set; }

+ 84 - 1
src/Hotline.Share/Dtos/Order/DepartmentAcceptanceTypeStatisticsDto.cs

@@ -1,4 +1,6 @@
-namespace Hotline.Share.Dtos.Order
+using Hotline.Settings;
+
+namespace Hotline.Share.Dtos.Order
 {
 
     public class DepartmentAcceptanceTypeStatisticsDto
@@ -101,4 +103,85 @@
             return 0;
         }
     }
+
+    public class DepartmentAcceptanceTypeStatisticsV1Dto
+    {
+        /// <summary>
+        /// 部门名称
+        /// </summary>
+        public string OrgName { get; set; }
+        public string OrgCode { get; set; }
+
+        /// <summary>
+        /// 部门类型
+        /// </summary>
+        public EOrgType OrgType { get; set; }
+        public string OrgTypeText { get; set; }
+
+        /// <summary>
+        /// 总量
+        /// </summary>
+        public int AllCount => ZxAllCount + JyAllCount + QzAllCount + ByAllCount + JbAllCount + TsAllCount + QtAllCount;
+        public string? AcceptanceTypeCode { get; set; }
+
+        /// <summary>
+        /// 咨询
+        /// </summary>
+        public int ZxAllCount { get; set; }
+        public string? ZxAcceptanceTypeCode { get; set; }
+
+        /// <summary>
+        /// 建议
+        /// </summary>
+        public int JyAllCount { get; set; }
+        public string? JyAcceptanceTypeCode { get; set; }
+
+        /// <summary>
+        /// 求助
+        /// </summary>
+        public int QzAllCount { get; set; }
+        public string? QzAcceptanceTypeCode { get; set; }
+
+        /// <summary>
+        /// 表扬
+        /// </summary>
+        public int ByAllCount { get; set; }
+        public string? ByAcceptanceTypeCode { get; set; }
+
+        /// <summary>
+        /// 举报
+        /// </summary>
+        public int JbAllCount { get; set; }
+        public string? JbAcceptanceTypeCode { get; set; }
+
+        /// <summary>
+        /// 投诉
+        /// </summary>
+        public int TsAllCount { get; set; }
+        public string? TsAcceptanceTypeCode { get; set; }
+
+        /// <summary>
+        /// 其他
+        /// </summary>
+        public int QtAllCount { get; set; }
+        public string? QtAcceptanceTypeCode { get; set; }
+
+        /// <summary>
+        /// 意见
+        /// </summary>
+        public int YjAllCount { get; set; }
+        public string? YjAcceptanceTypeCode { get; set; }
+
+        /// <summary>
+        /// 惠民帮助
+        /// </summary>
+        public int HmAllCount { get; set; }
+        public string? HmAcceptanceTypeCode { get; set; }
+
+        /// <summary>
+        /// 大气污染举报
+        /// </summary>
+        public int DqAllCount { get; set; }
+        public string? DqAcceptanceTypeCode { get; set; }
+    }
 }

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

@@ -386,7 +386,7 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 附件
         /// </summary>
-		public List<FileDto> Files { get; set; }
+		//public List<FileDto> Files { get; set; }
 	}
 
     public enum EOrderScreenType

+ 2 - 2
src/Hotline.Share/Requests/DepartmentKeyWordRequest.cs

@@ -5,12 +5,12 @@
         /// <summary>
         /// 开始时间
         /// </summary>
-        public DateTime StartTime { get; set; }
+        public DateTime? StartTime { get; set; }
 
         /// <summary>
         /// 结束时间
         /// </summary>
-        public DateTime EndTime { get; set; }
+        public DateTime? EndTime { get; set; }
 
         /// <summary>
         /// 部门编码

+ 7 - 2
src/Hotline.WeChat/WeChatService.cs

@@ -1,4 +1,5 @@
-using Hotline.Share.Dtos.Snapshot;
+using Hotline.Settings;
+using Hotline.Share.Dtos.Snapshot;
 using Hotline.ThirdAccountDomainServices.Interfaces;
 using Microsoft.Extensions.Logging;
 using Senparc.CO2NET.Extensions;
@@ -13,10 +14,12 @@ namespace Hotline.WeChat;
 public class WeChatService : IThirdIdentiyService
 {
     private readonly ILogger<WeChatService> _logger;
+    private readonly ISystemLogRepository _systemLog;
 
-    public WeChatService(ILogger<WeChatService> logger)
+    public WeChatService(ILogger<WeChatService> logger, ISystemLogRepository systemLog)
     {
         _logger = logger;
+        _systemLog = systemLog;
     }
 
     public async Task<ThirdTokenOutDto> GetTokenAsync(ThirdTokenDto dto, CancellationToken token)
@@ -24,6 +27,7 @@ public class WeChatService : IThirdIdentiyService
         try
         {
             var result = await SnsApi.JsCode2JsonAsync(dto.AppId, dto.Secret, dto.LoginCode);
+            _systemLog.Add("微信获取Token", dto, status: 1, executeResult: result.ToJson());
             if (result.errcode != ReturnCode.请求成功) throw UserFriendlyException.SameMessage("获取微信用户信息失败");
             return new ThirdTokenOutDto() { SessionKey = result.session_key, OpenId = result.openid , UnIonId = result.unionid};
 
@@ -45,6 +49,7 @@ public class WeChatService : IThirdIdentiyService
         await AccessTokenContainer.RegisterAsync(dto.AppId, dto.Secret);
         _logger.LogInformation($"GetPhoneNumberAsync: {dto.ToJson()}");
         var result = await BusinessApi.GetUserPhoneNumberAsync(dto.AppId, dto.TelCode);
+        _systemLog.Add("微信获取手机号码", dto, status: 1, executeResult: result.ToJson());
         if (result.errcode != ReturnCode.请求成功)
             _logger.LogError($"GetPhoneNumberAsync: {result.ToJson()}");
         return new ThirdPhoneOutDto()

+ 2 - 0
src/Hotline/Snapshot/SnapshotSMSTemplate.cs

@@ -2,12 +2,14 @@
 using SqlSugar;
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using XF.Domain.Repository;
 
 namespace Hotline.Snapshot;
+[Description("行业短信模板")]
 public class SnapshotSMSTemplate : FullStateEntity
 {
     /// <summary>

+ 52 - 1
src/Hotline/Tools/DynamicClassHelper.cs

@@ -17,7 +17,7 @@ public class DynamicClassHelper
         ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
         TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public);
 
-        foreach (var property in propInfos)
+        foreach (var property in propInfos.OrderBy(d=>d.Sort).ToList())
         {
             var propertyName = property.Prop.Trim().ToPascalCase();
             var propertyType = typeof(string);
@@ -51,4 +51,55 @@ public class DynamicClassHelper
         Type generatedType = typeBuilder.CreateType();
         return generatedType;
     }
+
+    public static Type CreateDynamicClass<TSource>(List<ColumnInfo> propInfos)
+    {
+        string className = "DynamicClass";
+        AssemblyName assemblyName = new AssemblyName("DynamicAssembly");
+        AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
+        ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
+        TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public);
+        var sourceProps = typeof(TSource).GetProperties();
+
+        foreach (var property in propInfos.OrderBy(d => d.Sort).ToList())
+        {
+            var propertyName = property.Prop.Trim().ToPascalCase();
+            var propertyType = sourceProps.FirstOrDefault(d => d.Name == propertyName)?.PropertyType ?? typeof(string);
+
+            FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
+            PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
+
+            MethodAttributes getSetAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
+
+            MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_" + propertyName, getSetAttributes, propertyType, Type.EmptyTypes);
+            ILGenerator getIL = getMethodBuilder.GetILGenerator();
+            getIL.Emit(OpCodes.Ldarg_0);
+            getIL.Emit(OpCodes.Ldfld, fieldBuilder);
+            getIL.Emit(OpCodes.Ret);
+
+            MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_" + propertyName, getSetAttributes, null, new Type[] { propertyType });
+            ILGenerator setIL = setMethodBuilder.GetILGenerator();
+            setIL.Emit(OpCodes.Ldarg_0);
+            setIL.Emit(OpCodes.Ldarg_1);
+            setIL.Emit(OpCodes.Stfld, fieldBuilder);
+            setIL.Emit(OpCodes.Ret);
+
+            propertyBuilder.SetGetMethod(getMethodBuilder);
+            propertyBuilder.SetSetMethod(setMethodBuilder);
+
+            var columnNameCtorInfo = typeof(ExcelColumnNameAttribute).GetConstructor(new Type[] { typeof(string), typeof(string[]) });
+            var attributeBuilder = new CustomAttributeBuilder(columnNameCtorInfo, new object[] { property.Name, null });
+            propertyBuilder.SetCustomAttribute(attributeBuilder);
+
+            if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?))
+            {
+                var columnExcelFormatCtorInfo = typeof(ExcelFormatAttribute).GetConstructor(new Type[] { typeof(string) });
+                var excelFormatAttributeBuilder = new CustomAttributeBuilder(columnExcelFormatCtorInfo, new object[] { "yyyy-MM-dd HH:mm:ss" });
+                propertyBuilder.SetCustomAttribute(excelFormatAttributeBuilder);
+            }
+        }
+
+        Type generatedType = typeBuilder.CreateType();
+        return generatedType;
+    }
 }