亲宝软件园·资讯

展开

elementui之封装下载模板和导入文件组件方式

牛先森家的牛奶 人气:0

elementui封装下载模板和上传组件

封装代码如下

<template>
  <div>
    <el-dialog
      :title="exportStatus? '导入结果' : '一键导入数据'"
      :visible.sync="dialogVisible"
      width="905px"
      :before-close="handleClose"
      class="export-standard-speech"
    >
    <div class="standard-export" v-if="!exportStatus">
      <div class="export-title">1、下载导入模板</div>
      <div class="export-warning">根据提示完善表格内容</div>
      <div class="export-download-btn">
        <img
          src="@/assets/img/download-demo-icon.png"
          width="12px"
          style="
            vertical-align: baseline;
            margin-right: 3px;
            margin-top:2px;
            display: inline-block;
          "
        />
        <a
          class="a-line"
          :href="downloadDemoUrl" rel="external nofollow" 
          download="项目导入模板.xlsx"
          title="下载空的表格模板"
        >下载空的表格模板</a>
      </div>
      <div class="export-title">2、上传完善后的表格</div>
      <el-upload
        class="upload-demo-xls"
        drag
        ref="speechDemoUpload"
        action=""
        :file-list="fileList"
        :auto-upload="false"
        :show-file-list="false"
        accept=".xls,.xlsx,.csv"
        :on-change="handleChange"
      >
        <div class="el-upload__text" v-if="!uploadStatus">将文件拖到此处,或点击<em>上传</em></div>
        <div class="el-upload__text" v-else>
          <span class="file-name">{{ this.file && this.file.name }}</span>
          <span class="file-size">({{bytesToSize(this.file.size)}})</span>
          <span class="file-select">重新选择</span>
        </div>
      </el-upload>
      <div class="h32 flex-center-center" style="margin-top:38px">
        <Button text="取消" background="#fff" border="#4646E6" color="#4646E6" class="ml10"  @click.native="cancelExport" ></Button>
        <Button text="导入" background="#4646E6" color="#fff" class="ml10"  @click.native="xlsDemoExport" :setGray="isFile"></Button>
      </div>
    </div>
    <div v-if="exportStatus && failNum > 0">
      <div class="fail-num">
        <img src="@/assets/img/export-fail-img.png" alt="" class="mr10">
        导入失败
        <span>{{failNum}}条</span>
        数据
      </div>
      <div class="export-fail-table">
        <div class="export-fail-text">以下为导入失败的项目,您可修改后重新导入</div>
        <el-table
          :data="tableData"
          height="220"
        >
          <el-table-column
            prop="lineNum"
            label="Execel行数"
            width="220"
            align="left"
          >
          </el-table-column>
          <el-table-column
            prop="projectCode"
            label="项目编号"
            width="220"
            align="center"
          >
          </el-table-column>
          <el-table-column
            prop="failReason"
            label="失败原因"
            width="220"
            align="right"
          >
          </el-table-column>
        </el-table>
      </div>
      <div class="h32 flex-center-center" style="margin-top:23px">
        <Button text="关闭" background="#fff" border="#4646E6" color="#4646E6"   @click.native="cancelExport" ></Button>
      </div>
    </div>
    <div v-if="exportStatus && failNum == 0">
      <div class="success-img">
        <img src="@/assets/img/export-success-img.png" alt="" class="mr10">
      </div>
      <div class="success-text">
        成功导入
        <span>{{ successNum }}条</span>
        数据
      </div>
      <div class="h32 flex-center-center" style="margin-top:23px">
        <Button text="完成" background="#4646E6" color="#fff" class=""  @click.native="cancelExport"></Button>
      </div>
    </div>
    </el-dialog>
  </div>
</template>

<script>
import Button from "@/components/Button";
import { upload, service } from '@/utils/request-brand'
import { bytesToSize } from '@/utils'

export default {
  name: 'ImportData',
  components: {
    Button
  },
  props: {
    showDialogVisible: {
      type: Boolean,
      default: false,
      required: true
    },
    downloadDemoUrl:{
      type: String,
      required: true
    },
    uploadFileUrl:{
      type: String,
      required: true
    },
    // 考虑上传时其他参数的情况
    otherUploadData:{
      type: Object,
      default:() => {
        return {}
      }
    }
  },
  computed: {
    userAccountID() {
      return this.$store.state.user.userAccountID;
    },
    isFile(){
      if(this.file){
        return false
      } else {
        return true
      }
    }
  },
  watch: {
    showDialogVisible(newVal) {
      // console.log(newVal);
      this.dialogVisible = newVal
    }
  },
  data () {
    return {
      dialogVisible: false,
      fileList: [],
      file: null,
      // 上传文件的状态切换
      uploadStatus: false,
      successNum: 0,
      failNum: 0,
      tableData: [],
      // 导入的状态
      exportStatus: false,
    };
  },
  methods: {
    bytesToSize,
    handleClose(done) {
      this.dialogVisible = false
      this.$emit('dialogVisible', false)
    },
    // 取消或者清空上传的文件和数据
    cancelExport(){
      // this.$refs.speechDemoUpload.clearFiles()
      this.fileList = []
      this.file = null
      this.successNum = 0
      this.failNum = 0
      this.tableData = []
      this.uploadStatus = false
      this.exportStatus = false
      this.$emit('dialogVisible', false)
    },
    // 上传的文件改变时(覆盖原来的文件)
    handleChange(file, fileList){
      // console.log(file);
      let extension = file.raw.name.substring(file.raw.name.lastIndexOf(".") + 1);
      let size = file.size / 1024 / 1024;
      // let size = file.size / 1024;
      // console.log(extension, extension.toLowerCase() !== "xlsx");
      if (!['xlsx','xls','csv'].includes(extension.toLowerCase())) {
        this.$message.warning("文件格式不正确,请上传xls / xlsx / csv格式");
        return false;
      }
      if (size > 10) {
        this.$message.warning("文件过大,请进行拆分后分多次上传");
        return false
      }
      // console.log(file.raw, fileList);
      if (fileList.length > 0) {
        this.fileList = [fileList[fileList.length - 1]]  // 这一步,是展示最后一次选择的csv文件
        this.file = this.fileList[0].raw
      }
      // console.log(this.file);
      this.uploadStatus = true
    },
    async xlsDemoExport(){
      if (!this.file) {
        // return this.$message.error('请上传文件')
        return false
      }
      const formData = new FormData()
      formData.append('file', this.file)
      // 添加其他参数
      if(Object.values(this.otherUploadData).length > 0){
        for (let key in this.otherUploadData) {
          formData.append(key, this.otherUploadData[key])
        }
      }
      //  调用上传接口...
      this.$loading.show()
      // `${process.env.VUE_APP_BASE_BRAND_API}/v1/inspectionSpeechArt/importExcel
      upload.uploadFile(this.uploadFileUrl, formData).then(res => {
        if(res.code == 0){
          this.exportStatus = true
          this.tableData = res.item.failList.map(item => {
            let obj = {}
            obj.lineNum = item.lineNum
            obj.failReason = item .failReason
            obj.projectCode = item. projectCode
            return obj
          })
          this.failNum  = res.item.failNum
          this.successNum = res.item.successNum
        } else {
          this.$message.error(res.message)
        }
        this.$loading.hide()
      }).catch((error) => {
        console.log(error);
        this.$message.error('上传失败,请稍后再试或联系IT解决')
        this.$loading.hide()
      })
    },
  },
}
</script>

<style  lang="scss" scoped>
::v-deep .el-dialog{
  width: 25%;
  border-radius: 12px;
  margin-top:-8vh !important;
  top: 50%;
  transform: translateY(-50%);
}
::v-deep .el-dialog__header {
  border-bottom: 1px solid #efeff6;
  padding-left: 50px;
  .el-dialog__title,
  .el-dialog__headerbtn i {
    color: #36395c !important;
    font-size: 18px !important;
    font-weight: 600;
  }
}
</style>

<style lang="scss">
.export-standard-speech {
  .el-list-enter-active,
  .el-list-leave-active {
    transition: none;
  }
  .el-list-enter,
  .el-list-leave-active {
    opacity: 0;
  }
  .el-upload-list {
    height: 40px;
  }
  // 表格body
  .el-dialog__body{
    padding: 30px 100px;
  }
  // 导入
  .standard-export{
    .upload-demo-xls{
      width: 100%;
      margin-top: 20px;
    }
    .el-upload.el-upload--text{
      width: 100%;
    }
    .el-upload-dragger{
      width: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      border: 1px solid #EFEFF6;
      height: 120px;
      .el-upload__text{
        font-weight: 600;
        color: #36395C;
        .file-name{
          color: #4646E6;
        }
        .file-size{
          color: #CCCDD8;
        }
        .file-select{
          color: #4646E6;
          text-decoration: underline;
        }
      }
    }
    .export-title{
      font-size: 14px;
      color: #36395C;
      font-weight: 600;
      line-height: 20px;
    }
    .export-warning{
      font-size: 14px;
      color: #CCCDD8;
      line-height: 20px;
    }
    .export-download-btn{
      width: 165px;
      height: 36px;
      border: 1px solid #4646E6;
      color: #4646E6;
      opacity: 1;
      border-radius: 6px;
      display: flex;
      align-items: center;
      justify-content: center;
      margin: 20px 0 30px;
    }
  }

  // 导入失败的表格数据
  .fail-num{
    display: flex;
    justify-content: center;
    align-items: center;
    margin-bottom: 24px;
    font-size: 16px;
    color: #36395C;
    font-weight: 600;
    span{
      color: #EF6E49;
      margin: 0 3px;
    }
  }
  .export-fail-table{
    width: 100%;
    height: 280px;
    border: 1px solid #EFEFF6;
    border-radius: 6px;
    padding: 0 20px;
    .export-fail-text{
      font-size: 14px;
      line-height: 20px;
      color: #36395C;
      font-weight: 600;
      margin-bottom: 20px;
      margin-top: 20px;
    }
    .el-table__row {
      height: 60px;
      td {
        padding: 0 30px;
      }
    }
    .has-gutter tr {
      height: 60px;
    }
    .has-gutter tr th {
      font-size: 14px;
      color: #333333;
      font-family: Arial;
      padding: 0 20px;
    }
    thead th {
      font-size: 14px;
      color: #333333;
      font-weight: 600;
      height: 40px;
      background: #F5F6FB;
    }
    // 滚动条的宽度
    .el-table__body-wrapper::-webkit-scrollbar {
      width: 6px; // 横向滚动条
      height: 6px; // 纵向滚动条
    }
    // 滚动条的滑块
    .el-table__body-wrapper::-webkit-scrollbar-thumb {
      background-color: #E2E2E2;
      border-radius: 3px;
    }
  }
  .success-img{
    display: flex;
    justify-content: center;
    align-items: center;
    margin-top: 103px;
  }
  .success-text{
    display: flex;
    justify-content: center;
    align-items: center;
    margin-top: 30px;
    margin-bottom: 50px;
    font-size: 16px;
    color: #36395C;
    font-weight: 600;
    span{
      color: #4646E6;
      margin: 0 3px;
    }
  }
}
</style>

页面使用

只上传文件的形式

<template>
  <div class="upload">
  	<Button  text="批量导入"  background="#36395C" color="#fff" :icon="true"  @click.native="handleExportBtn" />
    
    // ...
    <ImportData
      :showDialogVisible="exportVisible"
      :downloadDemoUrl="downloadStandardSpeech"
      :uploadFileUrl="uploadFileUrl"
      @dialogVisible="closeVisible"
    />
  </div>
</template>

<script>
import ImportData from '@/views/components/ImportData.vue'

export default {
  name: "index",
  components: {
    ImportData,
  },
  data() {
    return {
      // 导入弹框显示和隐藏
      exportVisible: false,
      downloadStandardSpeech: `${process.env.VUE_APP_EXPORTDEOM_API}/fileResources/templates_standardSpeech.xlsx`, // 模板下载文件地址,
      uploadFileUrl: 'http://10.0.0.10:3000/v1/inspectionSpeechArt/importExcel' // 可以写在配置文件中
    };
  },
  computed: {
    userAccountID() {
      return this.$store.state.user.userAccountID;
    },
  },
  // created() {
  //   this.getDataList();
  //   this.getCheckType();
  // },
  activated() {
    this.getDataList();
    this.getCheckType();
  },
  watch:{},
  methods: {
    // 导入
    handleExportBtn(){
      this.exportVisible = true
    },
    // 关闭导入
    closeVisible(){
      this.exportVisible = false
      // 刷新列表等操作
    },
  },
};
</script>


<style lang="scss" scoped>
</style>

上传文件和其他必传参数的形式

<template>
  <div class="upload">
  	<Button  text="批量导入"  background="#36395C" color="#fff" :icon="true"  @click.native="handleExportBtn" />
    
    // ...
    <ImportData
      :showDialogVisible="exportVisible"
      :downloadDemoUrl="downloadStandardSpeech"
      :uploadFileUrl="uploadFileUrl"
      :otherUploadData="otherUploadData"
      @dialogVisible="closeVisible"
    />
  </div>
</template>

<script>
import ImportData from '@/views/components/ImportData.vue'

export default {
  name: "index",
  components: {
    ImportData,
  },
  data() {
    return {
      // 导入弹框显示和隐藏
      exportVisible: false,
      downloadStandardSpeech: `${process.env.VUE_APP_EXPORTDEOM_API}/fileResources/templates_standardSpeech.xlsx`, // 模板下载文件地址,
      uploadFileUrl: 'http://10.0.0.10:3000/v1/inspectionSpeechArt/importExcel',
      otherUploadData: {},
    };
  },
  computed: {
    userAccountID() {
      return this.$store.state.user.userAccountID;
    },
  },
  // created() {
  //   this.getDataList();
  //   this.getCheckType();
  //   this.otherUploadData = { key : 'value' };
  // },
  activated() {
    this.getDataList();
    this.getCheckType();
    this.otherUploadData = { key : 'value' };
  },
  watch:{},
  methods: {
    // 导入
    handleExportBtn(){
      this.exportVisible = true
    },
    // 关闭导入
    closeVisible(){
      this.exportVisible = false
      // 刷新列表等操作
    },
  },
};
</script>


<style lang="scss" scoped>
</style>

效果如下

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

加载全部内容

相关教程
猜你喜欢
用户评论