Vue导入文件封装

550 阅读2分钟

「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战」。

vue项目开发中经常会用到导入文件功能,我们公司的项目中,文件导入统一设计的,如下图,在这个弹框中,上传分为3步,第一步:下载对应的模板,填入数据,选择对应的文件。第二步:上传文件,后台验证数据的合法性。第三步:下载错误信息。我们一起看看吧!

QQ图片20220126150713.png

封装组件

ele的分步骤组件(<el-steps)来布局,默认如上图,点击选取文件之后,文件的列表就出现在按钮的位置,此处只能一次上传一个文件,这时候第二步的导入文件按钮就会高亮,点导入文件,就可以上传了,在第3步会展示出导入成功和导入失败的数量。

QQ图片20220127101455.png

QQ图片20220127101533.png

<template>
    <div class="import-excel">
        <el-steps direction="vertical" :active="uploadStep">
            <el-step></el-step>
            <el-step></el-step>
            <el-step></el-step>
        </el-steps>
        <div class="excel-con">
            <div class="step-first">
                <div class="name">选取文件</div>
                <div class="desc">如果您是初次使用,建议您<span class="down" @click="exportInsertTable"> 下载模板 </span>进行查看。</div>
                <div class="select">
                    <el-upload
                        :disabled="disabled"
                        action=""
                        :on-remove="handleRemove"
                        :file-list="fileList"
                        :auto-upload="false"
                        accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
                        :limit="1"
                        :on-change="onChange"
                    >
                        <el-button type="primary" size="small" class="select-btn" plain v-if="fileList.length === 0" :disabled="disabled">点击选取</el-button>
                    </el-upload>
                </div>
            </div>
            <div class="step-next">
                <div class="name">导入文件</div>
                <div class="desc">等待文件导入完毕后自动检查数据</div>
                <el-button type="primary" size="small" class="select-btn" plain v-if="fileList.length !== 0 && uploadStep === 2" :loading="importBtn" @click="importExcel">导入文件</el-button>
            </div>
            <div class="step-finish">
                <div class="name">完成</div>
                <div class="desc" v-if="uploadStep === 3">
                    导入已完成, 共导入成功<span class="green-color">{{ successCount }}</span>条,
                    导入失败<span class="red-color">{{ failedCount }}</span>条。
                    <div v-if="failedCount > 0">
                        <span  class="grey-color">具体结果可
                        <span class="blue-color" @click="onerrorTemplate()">下载错误日志</span> 进行查看</span>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

ele的上传组件(el-upload)组件属性如下

参数说明类型
action必选参数,上传的地址string
headers设置上传的请求头部
multiple是否支持多选文件boolean
data上传时附带的额外参数object
name上传的文件字段名file
show-file-list是否显示已上传文件列表boolean
drag是否启用拖拽上传falseaccept接受上传的文件类型(thumbnail-mode 模式下此参数无效)stringon-preview点击文件列表中已上传的文件时的钩子function(file)
on-remove文件列表移除文件时的钩子function(file, fileList)
on-success文件上传成功时的钩子function(response, file, fileList)
on-error文件上传失败时的钩子function(err, file, fileList)
on-progress文件上传时的钩子function(event, file, fileList)
on-change文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用function(file, fileList)
before-upload上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。function(file)
before-remove删除文件之前的钩子,参数为上传的文件和文件列表,若返回 false 或者返回 Promise 且被 reject,则停止删除。function(file, fileList)
list-type文件列表的类型stringtext/picture/picture-cardtext
auto-upload是否在选取文件后立即进行上传booleantrue
file-list上传的文件列表, 例如: [{name: 'food.jpg', url: 'xxx.cdn.com/xxx.jpg'}]array[]
http-request覆盖默认的上传行为,可以自定义上传的实现functiondisabled是否禁用booleanfalse
limit最大允许上传个数number
on-exceed文件超出个数限制时的钩子function(files, fileList)
<script>
import {
    downTemp,// 公共下载模板
    importTeacher,// 导入
    exportExcelTeacher,// 下载错误模板
} from '@/utils/api.js';
export default {
    name: "ImportExport",
    props:{
        flagName: { // 页面标识
            type: String,
            default: ''
        },
        fileName: { // 传参
            type: String,
            default: ''
        },
        // 业务需要传过来的参数放这里
        importData: {
            type: Object,
            default: () => {}
        },
        disabled: {
            type: Boolean,
            default: false,
        }
    },
    data(){
        return {
            baseFile: process.env.VUE_APP_FILE_URL,
            fileList: [],
            uploadStep: 1,
            importBtn: false,
            successCount: 0,
            failedCount: 0,
            key: '',
        }
    },
    computed:{
        schoolNum() {
            return this.$store.state.user.schoolNum;
        },
        userNum() {
            return this.$store.state.user.userInfo.userNum;
        },
    },
    mounted() {
        let map = new Map([
            ['teacher',[importTeacher, downTemp, exportExcelTeacher]],
        ]);
        this.checkImportExcel = map.get(this.flagName)[0];// 导入
        this.downExcel = map.get(this.flagName)[1];// 下载模板
        this.exportErrorData = map.get(this.flagName)[2];// 导出错误
    },
    methods: {
        // 移除文件
        handleRemove(file, fileList) {
            this.fileList = fileList;
            this.uploadStep = 1;
            this.importBtn = false;
        },
        // 修改文件
        onChange(file, fileList) {
            this.fileList = fileList;
            this.uploadStep = 2;
        },
        // 导入
        importExcel() {
            const file = this.fileList[0].raw;
            this.importBtn = true;
            if (file.size < 10 * 1024 * 1024) {
                let params = new FormData();
                params.append('fileName', file);
                params.append('schoolNum', this.schoolNum);
                params.append('userNum', this.userNum);
                this.$postForm(this.checkImportExcel, params).then((res) => {
                    this.importBtn = false;
                    if (res.status == 200){
                        this.uploadStep = 3;
                        this.successCount = res.result.successCount;
                        this.failedCount = res.result.failedCount;
                        this.key = res.result.key;
                    }
                })
            } else {
                this.importBtn = false;
                this.$message({
                    message: '请上传10M以内的文件',
                    type: 'warning'
                })
            }
        },
        // 导出错误数据
        onerrorTemplate() {
            let postData = {
                schoolNum: this.$store.state.user.schoolNum,
                number: this.$store.state.user.userInfo.userNum,
                Authorization: this.$store.state.user.userToken
            };
            doExportExcel(this.exportErrorData, postData);
        },
        // 下载模板
        exportInsertTable() {
            doExportExcel(this.downExcel, { fileName: this.fileName });
        },
    },
}
</script>

封装好组件之后,只需要在需要导入的页面引入组件,传参进来,就可以轻松使用了,解决了很多的时间。记录一下,温故而知新