Jelajahi Sumber

导出Excel日期,数字格式支持排序

xf 1 bulan lalu
induk
melakukan
98638d6ebf

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

@@ -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))

+ 66 - 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,68 @@ 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 = "reTransactNum", Name = "重办次数" },
+        };
+        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<MyClass>(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);
+
+        dynamic temp = dtos
+            .Select(stu => _mapper.Map(stu, typeof(MyClass), dynamicClass))
+            .Cast<object>()
+            .ToList();
+
+        var stream = ExcelHelper.CreateStream(temp);
+
+        return ExcelStreamResult(stream, "工单数据");
+    }
+}
+
+class MyClass
+{
+    public string Title { get; set; }
+    public DateTime ExpiredTime { get; set; }
+    public int ReTransactNum { get; set; }
 }

+ 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))
+            {
+                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;
+    }
 }