mirror of
				https://github.com/pure-admin/pure-admin-thin.git
				synced 2025-11-04 17:44:48 +08:00 
			
		
		
		
	feat: 新增后台全量导出excel
This commit is contained in:
		
							parent
							
								
									61a980a37d
								
							
						
					
					
						commit
						bc4d29cba0
					
				@ -42,6 +42,15 @@ export const getOperationLogListApi = (params?: OperationLogsQuery) => {
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const exportOperationLogExcelApi = (
 | 
				
			||||||
 | 
					  params: OperationLogsQuery,
 | 
				
			||||||
 | 
					  fileName: string
 | 
				
			||||||
 | 
					) => {
 | 
				
			||||||
 | 
					  return http.download("/logs/operationLogs/excel", fileName, {
 | 
				
			||||||
 | 
					    params
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const deleteOperationLogApi = (data: Array<number>) => {
 | 
					export const deleteOperationLogApi = (data: Array<number>) => {
 | 
				
			||||||
  return http.request<ResponseData<void>>("delete", "/logs/operationLogs", {
 | 
					  return http.request<ResponseData<void>>("delete", "/logs/operationLogs", {
 | 
				
			||||||
    params: {
 | 
					    params: {
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@ import { message } from "../message";
 | 
				
			|||||||
import { ElMessageBox } from "element-plus";
 | 
					import { ElMessageBox } from "element-plus";
 | 
				
			||||||
import { router } from "@/router";
 | 
					import { router } from "@/router";
 | 
				
			||||||
import { removeToken } from "@/utils/auth";
 | 
					import { removeToken } from "@/utils/auth";
 | 
				
			||||||
 | 
					import { downloadByData } from "@pureadmin/utils";
 | 
				
			||||||
// console.log("Utils:" + router);
 | 
					// console.log("Utils:" + router);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { VITE_APP_BASE_API } = import.meta.env;
 | 
					const { VITE_APP_BASE_API } = import.meta.env;
 | 
				
			||||||
@ -104,7 +105,34 @@ class PureHttp {
 | 
				
			|||||||
  private httpInterceptorsResponse(): void {
 | 
					  private httpInterceptorsResponse(): void {
 | 
				
			||||||
    const instance = PureHttp.axiosInstance;
 | 
					    const instance = PureHttp.axiosInstance;
 | 
				
			||||||
    instance.interceptors.response.use(
 | 
					    instance.interceptors.response.use(
 | 
				
			||||||
      (response: PureHttpResponse) => {
 | 
					      async (response: PureHttpResponse) => {
 | 
				
			||||||
 | 
					        let code = undefined;
 | 
				
			||||||
 | 
					        let msg = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 后台返回的二进制流
 | 
				
			||||||
 | 
					        if (response.data instanceof Blob) {
 | 
				
			||||||
 | 
					          // 返回二进制流的时候 可能出错  这时候返回的错误是Json格式
 | 
				
			||||||
 | 
					          if (response.data.type === "application/json") {
 | 
				
			||||||
 | 
					            const text = await this.readBlobAsText(response.data);
 | 
				
			||||||
 | 
					            const json = JSON.parse(text);
 | 
				
			||||||
 | 
					            // 提取错误消息中的code和msg
 | 
				
			||||||
 | 
					            code = json.code;
 | 
				
			||||||
 | 
					            msg = json.msg;
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            NProgress.done();
 | 
				
			||||||
 | 
					            return response.data;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          // 正常的返回类型 直接获取code和msg字段
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          code = response.data.code;
 | 
				
			||||||
 | 
					          msg = response.data.msg;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 如果不存在code说明后端格式有问题
 | 
				
			||||||
 | 
					        if (!code) {
 | 
				
			||||||
 | 
					          msg = "服务器返回数据结构有误";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 请求返回失败时,有业务错误时,弹出错误提示
 | 
					        // 请求返回失败时,有业务错误时,弹出错误提示
 | 
				
			||||||
        if (response.data.code !== 0) {
 | 
					        if (response.data.code !== 0) {
 | 
				
			||||||
          // token失效时弹出过期提示
 | 
					          // token失效时弹出过期提示
 | 
				
			||||||
@ -126,12 +154,12 @@ class PureHttp {
 | 
				
			|||||||
                message("取消重新登录", { type: "info" });
 | 
					                message("取消重新登录", { type: "info" });
 | 
				
			||||||
              });
 | 
					              });
 | 
				
			||||||
            NProgress.done();
 | 
					            NProgress.done();
 | 
				
			||||||
            return Promise.reject(response.data.msg);
 | 
					            return Promise.reject(msg);
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            // 其余情况弹出错误提示框
 | 
					            // 其余情况弹出错误提示框
 | 
				
			||||||
            message(response.data.msg, { type: "error" });
 | 
					            message(msg, { type: "error" });
 | 
				
			||||||
            NProgress.done();
 | 
					            NProgress.done();
 | 
				
			||||||
            return Promise.reject(response.data.msg);
 | 
					            return Promise.reject(msg);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -200,6 +228,19 @@ class PureHttp {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** 从二进制流中读取文本 */
 | 
				
			||||||
 | 
					  async readBlobAsText(blob: Blob): Promise<string> {
 | 
				
			||||||
 | 
					    return new Promise<string>((resolve, reject) => {
 | 
				
			||||||
 | 
					      const reader = new FileReader();
 | 
				
			||||||
 | 
					      reader.onload = () => {
 | 
				
			||||||
 | 
					        const text = reader.result as string;
 | 
				
			||||||
 | 
					        resolve(text);
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      reader.onerror = reject;
 | 
				
			||||||
 | 
					      reader.readAsText(blob, "UTF-8");
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** 单独抽离的post工具函数 */
 | 
					  /** 单独抽离的post工具函数 */
 | 
				
			||||||
  public post<T, P>(
 | 
					  public post<T, P>(
 | 
				
			||||||
    url: string,
 | 
					    url: string,
 | 
				
			||||||
@ -217,6 +258,54 @@ class PureHttp {
 | 
				
			|||||||
  ): Promise<P> {
 | 
					  ): Promise<P> {
 | 
				
			||||||
    return this.request<P>("get", url, params, config);
 | 
					    return this.request<P>("get", url, params, config);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** download文件方法 从后端获取文件流 */
 | 
				
			||||||
 | 
					  public download(
 | 
				
			||||||
 | 
					    url: string,
 | 
				
			||||||
 | 
					    fileName: string,
 | 
				
			||||||
 | 
					    params?: AxiosRequestConfig
 | 
				
			||||||
 | 
					  ): void {
 | 
				
			||||||
 | 
					    this.get(url, params, {
 | 
				
			||||||
 | 
					      headers: { "Content-Type": "application/x-www-form-urlencoded" },
 | 
				
			||||||
 | 
					      responseType: "blob"
 | 
				
			||||||
 | 
					    }).then((data: Blob) => {
 | 
				
			||||||
 | 
					      downloadByData(data, fileName);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // .post(url, params, {
 | 
				
			||||||
 | 
					  //   transformRequest: [params => encodeURIParams(params)],
 | 
				
			||||||
 | 
					  //   headers: { "Content-Type": "application/x-www-form-urlencoded" },
 | 
				
			||||||
 | 
					  //   responseType: "blob"
 | 
				
			||||||
 | 
					  // })
 | 
				
			||||||
 | 
					  // .then(async data => {
 | 
				
			||||||
 | 
					  //   const isLogin = await isBlobData(data);
 | 
				
			||||||
 | 
					  //   if (isLogin) {
 | 
				
			||||||
 | 
					  //     const blob = new Blob([data]);
 | 
				
			||||||
 | 
					  //     saveAs(blob, filename);
 | 
				
			||||||
 | 
					  //   } else {
 | 
				
			||||||
 | 
					  //     const resText = await data.text();
 | 
				
			||||||
 | 
					  //     const rspObj = JSON.parse(resText);
 | 
				
			||||||
 | 
					  //     const errMsg =
 | 
				
			||||||
 | 
					  //       errorCode[rspObj.code] || rspObj.msg || errorCode.default;
 | 
				
			||||||
 | 
					  //     ElMessage.error(errMsg);
 | 
				
			||||||
 | 
					  //   }
 | 
				
			||||||
 | 
					  //   downloadLoadingInstance.close();
 | 
				
			||||||
 | 
					  // })
 | 
				
			||||||
 | 
					  // .catch(r => {
 | 
				
			||||||
 | 
					  //   console.error(r);
 | 
				
			||||||
 | 
					  //   ElMessage.error("下载文件出现错误,请联系管理员!");
 | 
				
			||||||
 | 
					  //   downloadLoadingInstance.close();
 | 
				
			||||||
 | 
					  // });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // axios
 | 
				
			||||||
 | 
					  //   .get("https://pure-admin.github.io/pure-admin-doc/img/pure.png", {
 | 
				
			||||||
 | 
					  //     responseType: "blob"
 | 
				
			||||||
 | 
					  //   })
 | 
				
			||||||
 | 
					  //   .then(({ data }) => {
 | 
				
			||||||
 | 
					  //     downloadByData(data, "test-data.png");
 | 
				
			||||||
 | 
					  //   });
 | 
				
			||||||
 | 
					  // }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const http = new PureHttp();
 | 
					export const http = new PureHttp();
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ import View from "@iconify-icons/ep/view";
 | 
				
			|||||||
import Search from "@iconify-icons/ep/search";
 | 
					import Search from "@iconify-icons/ep/search";
 | 
				
			||||||
import Refresh from "@iconify-icons/ep/refresh";
 | 
					import Refresh from "@iconify-icons/ep/refresh";
 | 
				
			||||||
import { useUserStoreHook } from "@/store/modules/user";
 | 
					import { useUserStoreHook } from "@/store/modules/user";
 | 
				
			||||||
// 这个导入声明好长  看看如何优化
 | 
					// TODO 这个导入声明好长  看看如何优化
 | 
				
			||||||
import { CommonUtils } from "../../../../utils/common";
 | 
					import { CommonUtils } from "../../../../utils/common";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 组件name最好和菜单表中的router_name一致 */
 | 
					/** 组件name最好和菜单表中的router_name一致 */
 | 
				
			||||||
@ -35,6 +35,7 @@ const {
 | 
				
			|||||||
  multipleSelection,
 | 
					  multipleSelection,
 | 
				
			||||||
  onSearch,
 | 
					  onSearch,
 | 
				
			||||||
  resetForm,
 | 
					  resetForm,
 | 
				
			||||||
 | 
					  exportAllExcel,
 | 
				
			||||||
  openDialog,
 | 
					  openDialog,
 | 
				
			||||||
  getOperationLogList,
 | 
					  getOperationLogList,
 | 
				
			||||||
  handleDelete,
 | 
					  handleDelete,
 | 
				
			||||||
@ -147,11 +148,7 @@ const {
 | 
				
			|||||||
          @click="CommonUtils.exportExcel(columns, dataList, '操作日志列表')"
 | 
					          @click="CommonUtils.exportExcel(columns, dataList, '操作日志列表')"
 | 
				
			||||||
          >单页导出</el-button
 | 
					          >单页导出</el-button
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
        <el-button
 | 
					        <el-button type="primary" @click="exportAllExcel">全部导出</el-button>
 | 
				
			||||||
          type="primary"
 | 
					 | 
				
			||||||
          @click="CommonUtils.exportExcel(columns, dataList, '操作日志列表')"
 | 
					 | 
				
			||||||
          >全部导出</el-button
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
      </template>
 | 
					      </template>
 | 
				
			||||||
      <template v-slot="{ size, dynamicColumns }">
 | 
					      <template v-slot="{ size, dynamicColumns }">
 | 
				
			||||||
        <pure-table
 | 
					        <pure-table
 | 
				
			||||||
 | 
				
			|||||||
@ -3,10 +3,14 @@ import descriptionForm from "../description.vue";
 | 
				
			|||||||
import { message } from "@/utils/message";
 | 
					import { message } from "@/utils/message";
 | 
				
			||||||
import { addDialog, closeDialog } from "@/components/ReDialog";
 | 
					import { addDialog, closeDialog } from "@/components/ReDialog";
 | 
				
			||||||
import { ElMessageBox, Sort } from "element-plus";
 | 
					import { ElMessageBox, Sort } from "element-plus";
 | 
				
			||||||
import { OperationLogsQuery, getOperationLogListApi } from "@/api/system/log";
 | 
					import {
 | 
				
			||||||
 | 
					  OperationLogsQuery,
 | 
				
			||||||
 | 
					  getOperationLogListApi,
 | 
				
			||||||
 | 
					  deleteOperationLogApi,
 | 
				
			||||||
 | 
					  exportOperationLogExcelApi
 | 
				
			||||||
 | 
					} from "@/api/system/log";
 | 
				
			||||||
import { reactive, ref, onMounted, h, toRaw } from "vue";
 | 
					import { reactive, ref, onMounted, h, toRaw } from "vue";
 | 
				
			||||||
import { useUserStoreHook } from "@/store/modules/user";
 | 
					import { useUserStoreHook } from "@/store/modules/user";
 | 
				
			||||||
import { deleteOperationLogApi } from "@/api/system/log";
 | 
					 | 
				
			||||||
import { CommonUtils } from "@/utils/common";
 | 
					import { CommonUtils } from "@/utils/common";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const operationLogStatusMap =
 | 
					const operationLogStatusMap =
 | 
				
			||||||
@ -154,13 +158,23 @@ export function useOperationLogHook() {
 | 
				
			|||||||
    CommonUtils.fillPaginationParams(searchFormParams, pagination);
 | 
					    CommonUtils.fillPaginationParams(searchFormParams, pagination);
 | 
				
			||||||
    CommonUtils.fillTimeRangeParams(searchFormParams, timeRange.value);
 | 
					    CommonUtils.fillTimeRangeParams(searchFormParams, timeRange.value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { data } = await getOperationLogListApi(toRaw(searchFormParams));
 | 
					    const { data } = await getOperationLogListApi(
 | 
				
			||||||
 | 
					      toRaw(searchFormParams)
 | 
				
			||||||
 | 
					    ).finally(() => {
 | 
				
			||||||
 | 
					      pageLoading.value = false;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
    dataList.value = data.rows;
 | 
					    dataList.value = data.rows;
 | 
				
			||||||
    pagination.total = data.total;
 | 
					    pagination.total = data.total;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setTimeout(() => {
 | 
					  async function exportAllExcel(sort: Sort = defaultSort) {
 | 
				
			||||||
      pageLoading.value = false;
 | 
					    if (sort != null) {
 | 
				
			||||||
    }, 500);
 | 
					      CommonUtils.fillSortParams(searchFormParams, sort);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    CommonUtils.fillPaginationParams(searchFormParams, pagination);
 | 
				
			||||||
 | 
					    CommonUtils.fillTimeRangeParams(searchFormParams, timeRange.value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    exportOperationLogExcelApi(toRaw(searchFormParams), "操作日志.xls");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function handleDelete(row) {
 | 
					  async function handleDelete(row) {
 | 
				
			||||||
@ -244,6 +258,7 @@ export function useOperationLogHook() {
 | 
				
			|||||||
    timeRange,
 | 
					    timeRange,
 | 
				
			||||||
    multipleSelection,
 | 
					    multipleSelection,
 | 
				
			||||||
    onSearch,
 | 
					    onSearch,
 | 
				
			||||||
 | 
					    exportAllExcel,
 | 
				
			||||||
    // exportExcel,
 | 
					    // exportExcel,
 | 
				
			||||||
    getOperationLogList,
 | 
					    getOperationLogList,
 | 
				
			||||||
    resetForm,
 | 
					    resetForm,
 | 
				
			||||||
 | 
				
			|||||||
@ -153,14 +153,14 @@ export function useNoticeHook() {
 | 
				
			|||||||
    CommonUtils.fillPaginationParams(searchFormParams, pagination);
 | 
					    CommonUtils.fillPaginationParams(searchFormParams, pagination);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pageLoading.value = true;
 | 
					    pageLoading.value = true;
 | 
				
			||||||
    const { data } = await getSystemNoticeListApi(toRaw(searchFormParams));
 | 
					    const { data } = await getSystemNoticeListApi(
 | 
				
			||||||
 | 
					      toRaw(searchFormParams)
 | 
				
			||||||
 | 
					    ).finally(() => {
 | 
				
			||||||
 | 
					      pageLoading.value = false;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dataList.value = data.rows;
 | 
					    dataList.value = data.rows;
 | 
				
			||||||
    pagination.total = data.total;
 | 
					    pagination.total = data.total;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    setTimeout(() => {
 | 
					 | 
				
			||||||
      pageLoading.value = false;
 | 
					 | 
				
			||||||
    }, 500);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function handleDelete(row) {
 | 
					  async function handleDelete(row) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user