Sfoglia il codice sorgente

feat: 😀新增导出功能

喵你个旺呀 1 anno fa
parent
commit
6a2b704181

+ 1 - 1
Admin.NET/Admin.NET.Core/Utils/ExcelHelper.cs

@@ -78,7 +78,7 @@ public class ExcelHelper
     /// <param name="filename"></param>
     /// <param name="addListValidationFun"></param>
     /// <returns></returns>
-    public static IActionResult ExportTemplate<T>(List<T> list, string filename = "导入模板", Func<ExcelWorksheet, PropertyInfo, IEnumerable<string>> addListValidationFun = null)
+    public static IActionResult ExportTemplate<T>(IEnumerable<T> list, string filename = "导入模板", Func<ExcelWorksheet, PropertyInfo, IEnumerable<string>> addListValidationFun = null)
     {
         using var package = new ExcelPackage((ExportData(list, filename) as XlsxFileResult)!.Stream);
         var worksheet = package.Workbook.Worksheets[0];

+ 13 - 12
Admin.NET/Admin.NET.Web.Entry/wwwroot/template/Service.cs.vm

@@ -82,18 +82,6 @@ public class @(Model.ClassName)Service : IDynamicApiController, ITransient
 		return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
     }
 
-    /// <summary>
-    /// 获取@(Model.BusName)列表 🔖
-    /// </summary>
-    /// <param name="input"></param>
-    /// <returns></returns>
-    [DisplayName("获取@(Model.BusName)列表")]
-    [ApiDescriptionSettings(Name = "List"), HttpGet]
-    public async Task<List<@(Model.ClassName)Output>> List([FromQuery] Page@(Model.ClassName)Input input)
-    {
-        return await _@(Model.LowerClassName)Rep.AsQueryable().Select<@(Model.ClassName)Output>().ToListAsync();
-    }
-
     /// <summary>
     /// 获取@(Model.BusName)详情 ℹ️
     /// </summary>
@@ -240,6 +228,19 @@ public class @(Model.ClassName)Service : IDynamicApiController, ITransient
     @if (Model.ImportFieldList.Count > 0) {
     @:
     @:/// <summary>
+    @:/// 导出@(Model.BusName)记录 🔖
+    @:/// </summary>
+    @:/// <param name="input"></param>
+    @:/// <returns></returns>
+    @:[DisplayName("导出@(Model.BusName)记录")]
+    @:[ApiDescriptionSettings(Name = "Export"), HttpPost, NonUnify]
+    @:public async Task<IActionResult> Export(Page@(Model.ClassName)Input input)
+    @:{
+        @:var list = (await Page(input)).Items?.Adapt<List<Export@(Model.ClassName)Output>>() ?? new();
+        @:return ExcelHelper.ExportTemplate(list, "@(Model.BusName)导出记录");
+    @:}
+    @:
+    @:/// <summary>
     @:/// 下载@(Model.BusName)数据导入模板 ⬇️
     @:/// </summary>
     @:/// <returns></returns>

+ 2 - 2
Admin.NET/Admin.NET.Web.Entry/wwwroot/template/api.ts.vm

@@ -6,8 +6,6 @@ export const use@(Model.ClassName)Api = () => {
 	return {
 		// 分页查询@(Model.BusName)
 		page: baseApi.page,
-		// 获取@(Model.BusName)导出数据
-		list: baseApi.list,
 		// 查看@(Model.BusName)详细
 		detail: baseApi.detail,
 		// 新增@(Model.BusName)
@@ -27,6 +25,8 @@ export const use@(Model.ClassName)Api = () => {
 		@:upload@(column.PropertyName): (params: any) => baseApi.uploadFile(params, baseApi.baseUrl + 'upload@(column.PropertyName)'),
 		}
 		@if (Model.ImportFieldList.Count > 0) {
+		@:// 导出@(Model.BusName)数据
+		@:exportData: baseApi.exportData,
 		@:// 导入@(Model.BusName)数据
 		@:importData: baseApi.importData,
 		@:// 下载@(Model.BusName)数据导入模板

+ 10 - 6
Admin.NET/Admin.NET.Web.Entry/wwwroot/template/index.vue.vm

@@ -3,6 +3,7 @@ import { ref, reactive, onMounted } from "vue";
 import { auth } from '/@@/utils/authFunction';
 import { getAPI } from '/@@/utils/axios-utils';
 import { ElMessageBox, ElMessage } from "element-plus";
+import { downloadStreamFile } from "/@@/utils/downloadFile";
 @if(Model.TableField.Any(x => x.EffectType == "ConstSelector")) {
 @:import { codeToName, getConstType } from '/@@/utils/constHelper';
 }
@@ -95,11 +96,6 @@ const openPrint@(Model.ClassName) = async (row: any) => {
   }
 }
 
-// 导出数据
-const export@(Model.LowerClassName) = async () => {
-  var data = await @(Model.LowerClassName)Api.list(Object.assign(state.tableQueryParams, state.tableParams)).then(res => res.data.result ?? []);
-}
-
 // 删除
 const del@(Model.ClassName) = (row: any) => {
   ElMessageBox.confirm(`确定要删除吗?`, "提示", {
@@ -127,6 +123,14 @@ const batchDel@(Model.ClassName) = () => {
   }).catch(() => {});
 };
 
+@if (Model.ImportFieldList.Count > 0) {
+@:// 导出数据
+@:const export@(Model.ClassName)Data = async () => {
+  @:const params = Object.assign(state.tableQueryParams, state.tableParams, { page: 1, pageSize: 99999999 });
+  @:@(Model.LowerClassName)Api.exportData(params).then(res => downloadStreamFile(res));
+@:}
+}
+
 handleQuery();
 </script>
 <template>
@@ -211,8 +215,8 @@ handleQuery();
                 }
                 <el-button type="danger" style="margin-left:5px;" icon="ele-Delete" @@click="batchDel@(Model.ClassName)" :disabled="state.selectData.length == 0" v-auth="'@(Model.LowerClassName):batchDelete'"> 删除 </el-button>
                 <el-button type="primary" style="margin-left:5px;" icon="ele-Plus" @@click="editDialogRef.openDialog(null, '新增@(Model.BusName)')" v-auth="'@(Model.LowerClassName):add'"> 新增 </el-button>
-                <el-button type="primary" style="margin-left:5px;" icon="ele-FolderOpened" @@click="export@(Model.LowerClassName)" v-auth="'@(Model.LowerClassName):export'"> 导出 </el-button>
                 @if (Model.ImportFieldList.Count > 0) {
+                @:<el-button type="primary" style="margin-left:5px;" icon="ele-FolderOpened" @@click="export@(Model.ClassName)Data" v-reclick="20000" v-auth="'@(Model.LowerClassName):export'"> 导出 </el-button>
                 @:<el-button type="warning" style="margin-left:5px;" icon="ele-MostlyCloudy" @@click="importDataRef.openDialog()" v-auth="'@(Model.LowerClassName):import'"> 导入 </el-button>
                 }
               </el-button-group>

+ 6 - 5
Web/src/api/base/index.ts

@@ -13,11 +13,6 @@ export const useBaseApi = (module: string) => {
             method: 'post',
             data,
         }),
-        list: (params: any) => request({
-            url: baseUrl + "list",
-            method: 'get',
-            params,
-        }),
         detail: (id: any) => request({
             url: baseUrl + "detail",
             method: 'get',
@@ -53,6 +48,12 @@ export const useBaseApi = (module: string) => {
             method: 'post',
             data
         }),
+        exportData: (data: any) => request({
+            responseType: 'arraybuffer',
+            url: baseUrl + 'export',
+            method: 'post',
+            data
+        }),
         downloadTemplate: () => request({
             responseType: 'arraybuffer',
             url: baseUrl + 'import',

+ 12 - 0
Web/src/utils/downloadFile.ts

@@ -16,4 +16,16 @@ export function downloadFile(url: string, filename: string | undefined = undefin
 
     document.body.removeChild(link);
     window.URL.revokeObjectURL(url);
+}
+
+/**
+ * 文件流下载
+ * @param res
+ */
+export function downloadStreamFile(res: any) {
+    const contentType = res.headers['content-type'];
+    const contentDisposition = res.headers['content-disposition'];
+    const filename = decodeURIComponent(contentDisposition.split('; ')[1].split('=')[1])
+    const blob = res.data instanceof Blob ? res.data : new Blob([res.data], { type: contentType });
+    downloadFile(window.URL.createObjectURL(blob), filename);
 }