文接上回,上篇文章我们已经使用NestJS实现了后端部分的 excel 的导入和导出功能。本篇文章我们将介绍根据后端提供的接口如何在前端实现 excel 的导入和导出功能。实现效果如下图所示
点击导出按钮,可以根据我们的选择条件下载对应的 excel 文件。点击导入按钮,可以点击或拖拽上传对应的 excel 文件,并导入到数据库中。
导出 Excel
因为我们要导出文件,所以需要下载后台返回的二进制(blob)文件,这样一来我们通用的接口调用封装就不再适用了。所以我们需要在封装 axios 的文件utils/http/index.ts
中新增一个通用的下载方法downLoad
。并且安装file-saver
,使用它的saveAs
方法来下载文件。
js
import { saveAs } from "file-saver";
//....
//下载
export const downLoad = async (url: string, params: any, filename: string) => {
const res = await service({
url,
method: "get",
params: params,
responseType: "blob",
});
const blob = new Blob([res]);
saveAs(blob, `${filename}.xlsx`);
};
然后再user/index.vue
中新增导入按钮并设置其权限再调用下载方法并传入参数即可。
js
<el-col :span="1.5">
<el-button
type="warning"
v-hasPerm="['system:user:export']"
plain
icon="Download"
@click="exportDataList()"
>导出</el-button>
</el-col>
...
//导出
const exportDataList = async () => {
downLoad("/user/export", queryParams, `用户列表_${new Date().getTime()}`);
};
这样我们点击导出按钮就可以下载对应的 excel 文件了。
导入 Excel
当用户点击导入按钮后,我们需要弹窗让用户选择文件或拖拽文件,然后上传到后台。这里我们可以使用element-plus
的upload
组件来实现。
js
<el-dialog
width="400px"
:title="uploadParams.title"
v-model="uploadParams.open"
append-to-body
>
<el-upload
class="upload-demo"
drag
accept=".xlsx, .xls"
:limit="1"
ref="upload"
:auto-upload="false"
:action="uploadParams.url"
:headers="uploadParams.headers"
:on-exceed="handleExceed"
:disabled="uploadParams.isUploading"
:on-progress="handleProgress"
:on-success="handleFileSuccess"
>
<el-icon class="el-icon--upload">
<component is="UploadFilled" />
</el-icon>
<div class="el-upload__text">拖拽文件到这或 <em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip">仅允许导入xls、xlsx格式文件。</div>
</template>
</el-upload>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="uploadSubmit">确 定</el-button>
<el-button @click="uploadParams.open = false">取 消</el-button>
</div>
</template>
</el-dialog>
其中 action 是我们后台的请求地址,headers 是我们的请求头,auto-upload 是是否自动上传,disabled 是是否禁用,limit 是上传文件的数量。on-exceed 是超出限制时的回调函数,on-progress 是上传进度的回调函数,on-success 是上传成功的回调函数。
然后定义一下 uploadParams,处理一下相关逻辑
js
/*** 用户导入参数 */
const uploadParams = reactive({
// 是否显示弹出层(用户导入)
open: false,
// 弹出层标题(用户导入)
title: "",
// 上传中
isUploading: false,
// 设置上传的请求头部带上token
headers: { Authorization: "Bearer " + Storage.get("token") },
// 上传的地址
url: import.meta.env.VITE_APP_API + "/user/upload",
});
const importDataList = async () => {
uploadParams.open = true;
uploadParams.title = "用户导入";
};
const upload = ref<UploadInstance>();
// 文件选择覆盖前一个文件
const handleExceed: UploadProps["onExceed"] = (files) => {
upload.value!.clearFiles();
const file = files[0] as UploadRawFile;
file.uid = genFileId();
upload.value!.handleStart(file);
};
//上传中
const handleProgress: UploadProps["onProgress"] = () => {
uploadParams.isUploading = true;
};
// 上传提交
const uploadSubmit = () => {
upload.value!.submit();
};
// 上传成功处理
const handleFileSuccess: UploadProps["onSuccess"] = (response) => {
upload.value!.clearFiles();
uploadParams.isUploading = false;
const { code, describe } = response;
if (code !== 200) {
ElMessage.error(describe);
return;
}
ElMessage.success("导入成功");
uploadParams.open = false;
getList();
};
此时我们就可以进行文件导入了
我们导入两个用户试一下。
导入成功之后可以看到列表中已经有了我们导入的两个用户。
到这里就实现了 excel 的导入和导出功能。其它模块的导入导出基本和用户模块的导入导出一致,这里就不再一一介绍了。