项目需要,主要做薪酬这一块,薪酬又关系到人员统计,部门划分,以及各个站所,因此会产生很多表格展示数据,并且需要导入数据,导出数据,导出表格模板的功能。
依旧是对组件封装,通过JSON管理状态,如需要导出带出表名字,需要后端配合。另外导出接口配置添加
responseType: "blob"
如果icon 加载不出来 自行更替一下即可 我用的项目自带封装
效果展示
代码部分
index.vue 部分
<template>
<div class="ImportAndExport">
<div style="display: flex;">
<ExporTtemplate
v-if="templateComShow && templateConfig"
:templateConfig="templateConfig"
@success="templateSuccess"
@exTemCheckFun="$emit('exTemCheckFun', $event)"
@exportTempChange="$emit('exportTempChange', $event)"
></ExporTtemplate>
<div style="width: 8px;" v-if="templateComShow && importComShow"></div>
<importCom
v-if="importComShow && importConfig"
:importConfig="importConfig"
@success="importSuccess"
></importCom>
<div style="width: 8px;" v-if="importComShow && exportComShow"></div>
<exportCom
v-if="exportComShow && exportConfig"
:exportConfig="exportConfig"
:isCheck="isCheck"
@success="exportSuccess"
@checkFun="$emit('checkFun', $event)"
@exportChange="$emit('exportChange', $event)"
></exportCom>
</div>
</div>
</template>
<script>
import importCom from "./importd";
import exportCom from "./exportd";
import ExporTtemplate from "./exporTtemplate";
export default {
components: {
importCom,
exportCom,
ExporTtemplate
},
props: {
// 参数配置
config: {
// 是否必填
isCheck: false,
importComShow: true, // 导入组件显示
exportComShow: true, // 导出组件显示
templateComShow: true, // 导出模板组件显示
// 导入配置
importConfig: {
// 是否多文件上传
multiple: false,
// 导入文件类型
fileTypeArr: [],
// 导入方法
importMethod: null,
// 导入参数
importParams: {},
// 导入名字
impName: "导入"
},
// 导出配置
exportConfig: {
// 导出方法
exportMethod: null,
// 导出参数
exportParams: {},
// 导出按钮名字
expName: "导出",
// 导出文件名
exportFileName: "未命名.xlsx"
},
// 导出模板配置
templateConfig: {
// 导出模板方法
temMethod: null,
// 导出模板参数
temParams: {},
// 导出模板按钮名字
temName: "导出模板",
// 导出模板文件名
temFileName: "未命名.xlsx"
}
}
},
data() {
return {
isCheck: false, //是否必填
importComShow: true, // 导入组件显示
exportComShow: true, // 导出组件显示
templateComShow: true, // 导出模板组件显示
Filetype:
".text,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.html,.png,.jpg,.jpeg,.gif,.bmp,.zip,.rar,.7z,.tar,.gz,.bz2,.cab,.iso,.dmg,.apk,.ipa,.exe,.bin,.dll,.so,.sql,.md,.xml,.json,.csv,.ts,.js,.php,.py,.java,.c,.cpp,.h,.hpp,.cs,.bat,.cmd,",
// 导入配置
importConfig: {},
// 导出配置
exportConfig: {},
// 导出模板配置
templateConfig: {}
};
},
computed: {},
watch: {
config: {
handler(newVal, oldVal) {
this.init();
},
deep: true,
immediate: true
}
},
created() {}, // 生命周期 - 创建完成
mounted() {}, // 生命周期 - 挂载完成
beforeCreate() {}, // 生命周期 - 创建之前
beforeMount() {}, // 生命周期 - 挂载之前
beforeUpdate() {}, // 生命周期 - 更新之前
updated() {}, // 生命周期 - 更新之后
beforeDestroy() {}, // 生命周期 - 销毁之前
destroyed() {}, // 生命周期 - 销毁完成
activated() {}, // 如果页面有keep-alive缓存功能,这个函数会触发
methods: {
init() {
if (!this.config) return;
// 基础部分
const {
importComShow,
exportComShow,
importConfig,
exportConfig,
templateConfig,
templateComShow,
isCheck
} = this.config;
this.importComShow = importComShow;
this.exportComShow = exportComShow;
this.templateComShow = templateComShow;
this.isCheck = isCheck;
// 导入配置部分
if (importConfig) {
this.importConfig = {
fileTypeArr: importConfig.fileTypeArr
? importConfig.fileTypeArr
: this.Filetype.split(","),
importMethod: importConfig.importMethod
? importConfig.importMethod
: null,
importParams: importConfig.importParams
? importConfig.importParams
: {},
impName: importConfig.impName ? importConfig.impName : "导入"
};
}
// 导出配置部分
if (exportConfig) {
this.exportConfig = {
exportMethod: exportConfig.exportMethod
? exportConfig.exportMethod
: null,
exportParams: exportConfig.exportParams
? exportConfig.exportParams
: {},
exportName: exportConfig.expName ? exportConfig.expName : "导出",
exportFileName: exportConfig.exportFileName
? exportConfig.exportFileName
: "未命名.xlsx"
};
}
// 导出模板配置部分
if (templateConfig) {
this.templateConfig = {
exportMethod: templateConfig.temMethod
? templateConfig.temMethod
: null,
exportParams: templateConfig.temParams
? templateConfig.temParams
: {},
exportName: templateConfig.temName
? templateConfig.temName
: "导出模板",
exportFileName: templateConfig.temFileName
? templateConfig.temFileName
: "未命名.xlsx"
};
}
},
importSuccess(val) {
// 导入回调
this.$emit("importSuccess", val);
},
exportSuccess(val) {
// 导出回调
this.$emit("exportSuccess", val);
},
templateSuccess(val) {
// 导出模板回调
this.$emit("templateSuccess", val);
}
}
};
</script>
<style scoped lang="scss"></style>
importd.vue 部分
<template>
<div class="import">
<el-upload
class="upload-import"
action=" "
ref="upload"
:accept="Filetype"
:http-request="fileUpload"
:show-file-list="false"
:before-upload="beforeAvatarUpload"
:on-change="uploadChange"
>
<el-button icon="wk wk-import"
>{{ impName }}<i class="el-icon-loading" v-if="importLoading"></i
></el-button>
</el-upload>
</div>
</template>
<script>
export default {
components: {},
props: {
importConfig: {
type: Object,
default: () => {
return {
// 是否多文件上传
multiple: false,
// 导入文件类型
fileTypeArr: [],
// 导入方法
importMethod: null,
// 导入参数
importParams: null,
// 导入名字
impName: "导入"
};
}
}
},
data() {
return {
Filetype:
".text,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.html,.png,.jpg,.jpeg,.gif,.bmp,.zip,.rar,.7z,.tar,.gz,.bz2,.cab,.iso,.dmg,.apk,.ipa,.exe,.bin,.dll,.so,.sql,.md,.xml,.json,.csv,.ts,.js,.php,.py,.java,.c,.cpp,.h,.hpp,.cs,.bat,.cmd,",
multiple: false,
fileTypeArr: [],
importMethod: null,
importParams: {},
impName: "导入",
importLoading: false
};
},
computed: {},
watch: {
importConfig: {
handler(newVal, oldVal) {
this.init();
},
deep: true,
immediate: true
}
},
created() {}, // 生命周期 - 创建完成
mounted() {}, // 生命周期 - 挂载完成
beforeCreate() {}, // 生命周期 - 创建之前
beforeMount() {}, // 生命周期 - 挂载之前
beforeUpdate() {}, // 生命周期 - 更新之前
updated() {}, // 生命周期 - 更新之后
beforeDestroy() {}, // 生命周期 - 销毁之前
destroyed() {}, // 生命周期 - 销毁完成
activated() {}, // 如果页面有keep-alive缓存功能,这个函数会触发
methods: {
// 初始化参数配置
init() {
const {
multiple,
fileTypeArr,
importMethod,
importParams,
impName
} = this.importConfig;
this.multiple = multiple ? multiple : false;
this.fileTypeArr =
fileTypeArr && fileTypeArr.length
? fileTypeArr
: this.Filetype.split(",");
this.importMethod = importMethod ? importMethod : null;
this.importParams = importParams ? importParams : {};
this.impName = impName ? impName : "导入";
},
// 上传钩子
beforeAvatarUpload(file) {
const typeArr = this.fileTypeArr;
const isType = typeArr.some(item => {
return file.name.lastIndexOf(item) >= 0;
});
if (!isType) {
this.$message.error("请上传正确文件类型!");
}
return isType;
},
/** 附件上传 */
fileUpload(val) {
this.importLoading = true;
let file = val.file;
let params = new FormData();
params.append("file", file);
let keys = Object.keys(this.importParams);
keys &&
keys.forEach(item => {
params.append(item, this.importParams[item]);
});
// 调用接口
let importMethod = this.importMethod;
// 如果是一个函数 就调用接口
if (importMethod && importMethod instanceof Function) {
importMethod(params)
.then(res => {
this.importLoading = false;
if (res.code != 0) return this.$message.error("网络异常");
this.$message.success("导入成功");
// 成功回调
this.$emit("success", res);
})
.catch(() => {});
} else {
this.importLoading = false;
this.$message.error("请先配置接口数据!");
}
},
// 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用
uploadChange(file, fileList) {
console.log(file, fileList, "文件状态改变时的钩子");
// this.progressFlag = true; // 显示进度条
// this.loadProgress = parseInt(event.percent); // 动态获取文件上传进度
// console.log("上传进度", this.loadProgress);
// if (this.loadProgress >= 100) {
// this.loadProgress = 100
// setTimeout( () => {this.progressFlag = false}, 1000) // 一秒后关闭进度条
// }
}
}
};
</script>
<style scoped lang="scss"></style>
exportd.vue 部分
<template>
<div class="export">
<el-button icon="wk wk-export" @click="ExportAttendance"
>{{ expName }}<i class="el-icon-loading" v-if="exportLoading"></i
></el-button>
</div>
</template>
<script>
import { BlobExport } from "@/utils/export.js";
export default {
components: {},
data() {
return {
exportMethod: null,
exportParams: {},
expName: "导出",
exportLoading: false
};
},
props: {
exportConfig: {
type: Object,
default: () => {
return {
// 导出方法
exportMethod: null,
// 导出参数
exportParams: null,
// 导出按钮名字
expName: "导出",
// 导出文件名
exportFileName: "未命名.xlsx"
};
}
},
isCheck: {
type: Boolean,
default: () => {
return false;
}
}
},
computed: {},
watch: {
exportConfig: {
handler(newVal, oldVal) {
this.init();
},
deep: true,
immediate: true
}
},
created() {}, // 生命周期 - 创建完成
mounted() {}, // 生命周期 - 挂载完成
beforeCreate() {}, // 生命周期 - 创建之前
beforeMount() {}, // 生命周期 - 挂载之前
beforeUpdate() {}, // 生命周期 - 更新之前
updated() {}, // 生命周期 - 更新之后
beforeDestroy() {}, // 生命周期 - 销毁之前
destroyed() {}, // 生命周期 - 销毁完成
activated() {}, // 如果页面有keep-alive缓存功能,这个函数会触发
methods: {
// 初始化参数配置
init() {
const {
exportMethod,
exportParams,
exportName,
exportFileName
} = this.exportConfig;
this.exportMethod = exportMethod ? exportMethod : null;
this.exportParams = exportParams ? exportParams : {};
this.exportFileName = exportFileName ? exportFileName : "未命名.xlsx";
this.expName = exportName ? exportName : "导出";
},
// 遍历值
isNotEmpty(obj) {
for (let key in obj) {
if (obj[key] === "") {
return false;
}
}
return true;
},
// 导出
ExportAttendance() {
// 传递导出事件
this.$emit("exportChange", this.exportParams);
if (this.isCheck) {
if (this.isNotEmpty(this.exportParams)) {
this.BlobExport();
} else {
this.$emit("checkFun", this.exportParams);
}
} else {
this.BlobExport();
}
},
// 封装导出
BlobExport() {
this.exportLoading = true;
let than = this;
// 如果是一个函数 就调用接口
let exportMethod = this.exportMethod;
if (exportMethod && exportMethod instanceof Function) {
exportMethod({
...this.exportParams
}).then(workbook => {
// 判断是否接口返回正常
this.exportLoading = false;
let res = workbook.data;
if (res == null) return this.$message.error("导出错误,请稍候再试!");
if (res.type === "application/json") {
const reader = new FileReader();
reader.readAsText(res, "utf-8");
// 此处为接口返回值
reader.onload = function() {
const _res = JSON.parse(reader.result);
than.$message.error(_res.msg);
};
} else {
// 获取后端返回的文件名
let flg =
(workbook.headers && workbook.headers["content-disposition"]) ||
false; // 存在文件名字信息
if (flg) {
// 存在文件名字信息
BlobExport(workbook);
this.$message.success("导出成功!");
// 成功回调
this.$emit("success", workbook);
} else {
// 不存在文件名字信息
BlobExport(workbook, this.exportFileName);
// 成功回调
this.$emit("success", workbook);
}
}
});
} else {
this.exportLoading = false;
// 成功回调
this.$message.error("请先配置接口数据!");
}
}
}
};
</script>
<style scoped lang="scss"></style>
exporTtemplate.vue 部分
<template>
<div class="export">
<el-button icon="wk wk-download" @click="ExportAttendance"
>{{ expName }}<i class="el-icon-loading" v-if="exportLoading"></i
></el-button>
</div>
</template>
<script>
import { BlobExport } from "@/utils/export.js";
export default {
components: {},
data() {
return {
exportMethod: null,
exportParams: {},
expName: "导出模板",
exportLoading: false
};
},
props: {
templateConfig: {
type: Object,
default: () => {
return {
// 导出方法
exportMethod: null,
// 导出参数
exportParams: null,
// 导出按钮名字
expName: "下载模板",
// 导出文件名
exportFileName: "未命名.xlsx"
};
}
},
isCheck: {
type: Boolean,
default: () => {
return false;
}
}
},
computed: {},
watch: {
templateConfig: {
handler(newVal, oldVal) {
this.init();
},
deep: true,
immediate: true
}
},
created() {}, // 生命周期 - 创建完成
mounted() {}, // 生命周期 - 挂载完成
beforeCreate() {}, // 生命周期 - 创建之前
beforeMount() {}, // 生命周期 - 挂载之前
beforeUpdate() {}, // 生命周期 - 更新之前
updated() {}, // 生命周期 - 更新之后
beforeDestroy() {}, // 生命周期 - 销毁之前
destroyed() {}, // 生命周期 - 销毁完成
activated() {}, // 如果页面有keep-alive缓存功能,这个函数会触发
methods: {
// 遍历值
isNotEmpty(obj) {
for (let key in obj) {
if (obj[key] === "") {
return false;
}
}
return true;
},
// 初始化参数配置
init() {
const {
exportMethod,
exportParams,
exportName,
exportFileName
} = this.templateConfig;
this.exportMethod = exportMethod ? exportMethod : null;
this.exportParams = exportParams ? exportParams : {};
this.exportFileName = exportFileName ? exportFileName : "未命名.xlsx";
this.expName = exportName ? exportName : "下载模板";
},
// 导出
ExportAttendance() {
// 传递导出事件
this.$emit("exportTempChange", this.exportParams);
if (this.isCheck) {
if (this.isNotEmpty(this.exportParams)) {
this.BlobExport();
} else {
this.$emit("exTemCheckFun", this.exportParams);
}
} else {
this.BlobExport();
}
},
// 封装导出
BlobExport() {
this.exportLoading = true;
let than = this;
// 如果是一个函数 就调用接口
let exportMethod = this.exportMethod;
if (exportMethod && exportMethod instanceof Function) {
exportMethod({
...this.exportParams
}).then(workbook => {
this.exportLoading = false;
// 判断是否接口返回正常
let res = workbook.data;
if (res == null) return this.$message.error("导出错误,请稍候再试!");
if (res.type === "application/json") {
const reader = new FileReader();
reader.readAsText(res, "utf-8");
// 此处为接口返回值
reader.onload = function() {
const _res = JSON.parse(reader.result);
than.$message.error(_res.msg);
};
} else {
// 获取后端返回的文件名
let flg =
(workbook.headers && workbook.headers["content-disposition"]) ||
false; // 存在文件名字信息
if (flg) {
// 存在文件名字信息
BlobExport(workbook);
this.$message.success("导出成功!");
// 成功回调
this.$emit("success", workbook);
} else {
// 不存在文件名字信息
BlobExport(workbook, this.exportFileName);
// 成功回调
this.$emit("success", workbook);
}
}
});
} else {
this.exportLoading = false;
// 成功回调
this.$message.error("请先配置接口数据!");
}
}
}
};
</script>
<style scoped lang="scss"></style>
使用方法
HTML
<ImportAndExport
@importSuccess="importSuccess"
@exportSuccess="exportSuccess"
@templateSuccess="templateSuccess"
@checkFun="checkFun"
@exportChange="exportChange"
@exTemCheckFun="exTemCheckFun"
@exportTempChange="exportTempChange"
:config="IeConfig"
/>
JS
import ImportAndExport from "@/components/ImportAndExport";
export default {
components: {
ImportAndExport
},
data(){
return{
IeConfig: {
importComShow: true, // 导入组件显示
exportComShow: true, // 导出组件显示
templateComShow: true, // 导出模板组件显示
// 导入配置
importConfig: {
// 是否多文件上传
multiple: false,
// 导入文件类型
fileTypeArr: [],
// 导入方法
importMethod: null,
// 导入参数
importParams: {},
// 导入名字
impName: "导入测试"
},
// 导出配置
exportConfig: {
// 导出方法
exportMethod: null,
// 导出参数
exportParams: {},
// 导出按钮名字
expName: "导出测试",
// 导出文件名
exportFileName: "未命名.xlsx"
},
// 导出模板配置
templateConfig: {
// 导出模板方法
temMethod: null,
// 导出模板参数
temParams: {},
// 导出模板按钮名字
temName: "导出模板",
// 导出模板文件名
temFileName: "未命名.xlsx"
}
},
}
},
methods:{
//导出模板必填校验
exTemCheckFun(val){
console.log(val,'exTemCheckFun');
},
// 导出模板事件
exportTempChange(val){
console.log(val,'exportTempChange');
},
//导出必填校验
checkFun(val){
console.log(val,'checkFun');
},
//导入成功回调
importSuccess(val){
console.log(val,'importSuccess');
},
// 导出事件
exportChange(val){
console.log(val,'exportChange');
},
// 导出成功回调
exportSuccess(val){
console.log(val,'exportSuccess');
},
// 导出模板成功回调
templateSuccess(val) {
console.log(val, "templateSuccess");
},
}
}