分页组件、上传组件、文件分片

分页组件

// <!--封装组件  vue页面-->
/*
1. background  是否为分页按钮添加背景色 接受boolean类型
2. current-page   当前页数,支持 .sync 修饰符  接受类型 number
3. page-size 每页显示条目个数,支持 .sync 修饰符    number
4. page-sizes  每页显示个数选择器的选项设置 number[] —  [10, 20, 30, 40, 50, 100]
5. total 总条目数 number
6. size-change pageSize 改变时会触发
7. current-change  currentPage 改变时会触发
*/

<template>
  <div>
    <el-pagination
      :background="background"
      :current-page.sync="currentPage"
      :page-size.sync="pageSize"
      :layout="layout"
      :page-sizes="pageSizes"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>
<script>
  export default {
    name: 'Pagination',
    props: {
      total: {
        required: true,
        type: Number
      },
      page: {
        type: Number,
        default: 1
      },
      limit: {
        type: Number,
        default: 20
      },
      pageSizes: {
        type: Array,
        default() {
          return [5, 10, 20, 30, 50]
        }
      },
      layout: {
        type: String,
        default: 'total, sizes, prev, pager, next, jumper'
      },
      background: {
        type: Boolean,
        default: true
      },
    },
    computed: {
      currentPage: {
        get() {
          return this.page
        },
        set(val) {
          this.$emit('update:page', val)
        }
      },
      pageSize: {
        get() {
          return this.limit
        },
        set(val) {
          this.$emit('update:limit', val)
        }
      }
    },
    methods: {
      handleSizeChange(val) {
        // this.$emit('pagination', { page: this.currentPage, limit: val })
        this.$emit('pagination', {page: 1, limit: val})
      },
      handleCurrentChange(val) {
        this.$emit('pagination', {page: val, limit: this.pageSize})
      }
    }
  }
</script>

父组件使用分页组件

data() {
      return {
        myToDoList: [],
        queryParams: {
          demandName: '',
          hardwareModel: '',
          manager: '',
          state: '',
          pageNum: 1,
          pageSize: 5
        },
        total: 0,
      }
    },
    mounted() {
      this.getMyToDoList()
    },
    methods: {
      handleSelectionChange(val) {
        console.log(val)
        this.queryParams.pageNum = val.page
        this.queryParams.pageSize = val.limit
        this.getMyToDoList()
      },
      selectMyToDoList() {
        this.queryParams.pageNum = 1
        this.getMyToDoList()
      },
      async getMyToDoList() {
        const request = this.queryParams
        console.log('请求参数', request)
        const res = await getMyToDoList(request)
        console.log('我的待办', res)
        const myToDoList = res.data.data.myToDoList
        this.myToDoList = myToDoList.content
        this.total = myToDoList.totalNum
        this.queryParams.pageNum = myToDoList.pageNum
        this.queryParams.pageSize = myToDoList.pageSize
      },
    }

上传文件组件

<template>
  <div class="Upload">
    <!--    <el-dialog title="附件上传" :visible.sync="visible" width="800px" :close-on-click-modal="false" @close="cancel">-->
    <div class="upload-file">
      <!--
       :action="action"  // 手动上传,这个参数没有用,但因为是必填的,所以随便填一个值就行
        :before-upload="handleBeforeUpload"  // 文件上传之前进行的操作
        :file-list="fileList"   // 已选择文件列表
        :limit="3"   // 一次最多上传几个文件
        multiple   // 可以多选
        :accept="accept"   // 可以上传的文件类型
        :on-error="handleUploadError"   // 上传出错时调用
        :on-exceed="handleExceed"   // 文件数量超过限制时调用
        :on-success="handleUploadSuccess"   // 上传成功时调用
        :on-change="handChange"   // 文件发生变化时调用
        :http-request="httpRequest"   // 自定义的文件上传方法,我们手动点击上传按钮后会调用
        :show-file-list="true"   // 是否显示文件列表
        :auto-upload="false"   // 关闭自动上传
        class="upload-file-uploader"
        ref="upload"
        -->
      <el-upload
        :action="action"
        :before-upload="handleBeforeUpload"
        :on-preview="handlePreview"
        :on-remove="handleRemove"
        :file-list="fileList"
        :limit="limit"
        multiple
        :accept="accept"
        :on-error="handleUploadError"
        :on-exceed="handleExceed"
        :on-success="handleUploadSuccess"
        :on-change="handChange"
        :http-request="httpRequest"
        :show-file-list="true"
        :auto-upload="false"
        class="upload-file-uploader"
        ref="upload"
      >
        <!-- 上传按钮 -->
        <el-button slot="trigger" size="mini" type="primary">选取文件</el-button>
        <el-button style="margin-left: 10px;" :disabled="fileList&&fileList.length < 1" size="small" type="success"
                   @click="submitUpload">上传到服务器
        </el-button>
        <!-- 上传提示 -->
        <div class="el-upload__tip" slot="tip" v-if="isShowTip">
          请上传
          <template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b></template>
          <template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b></template>
          的文件
        </div>
      </el-upload>
      <!-- 文件列表 -->
      <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear"
                        tag="ul">
        <li v-for="(file, index) in fileList" :key="file.id"
            class="el-upload-list__item ele-upload-list__item-content">
/*          <!--<el-link :href="file.filepath" :underline="false" target="_blank">
            &lt;!&ndash;                          <span class="el-icon-document">{{ getFileName(file.filename) }} </span>&ndash;&gt;
            <span class="el-icon-document">{{ file.filename }} </span>
          </el-link>
          <div class="ele-upload-list__item-content-action">
            <el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
          </div>-->
        </li>
      </transition-group>
    </div>
    <!--    </el-dialog>-->
    */
  </div>
</template>

<script>
  import {uploadAttachment, downloadAttachmentByID, deleteAttachmentByID} from '@/api/mmis/index.js'

  export default {
    name: "Upload",
    props: {
      // 值
      value: [String, Object, Array],
      // 大小限制(MB)
      fileSize: {
        type: Number,
        default: 2,
      },
      // 文件类型, 例如['png', 'jpg', 'jpeg']
      fileType: {
        type: Array,
        default: () => [".jpg", ".jpeg", ".png", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".txt", ".pdf", ".xml", ".XML"],
      },
      // 是否显示提示
      isShowTip: {
        type: Boolean,
        default: false
      },
      //个数限制
      limit: {
        type: Number,
        default: 5
      },
      requestParams: {},
      fileList: [],
    },
    data() {
      return {
        // 已选择文件列表
        // fileList: [],
        // 是否显示文件上传弹窗
        visible: false,
        // 可上传的文件类型
        accept: '',
        action: 'action'
      }
    },
    watch: {
      "fileList": {
        handler(newData) {
          console.log('fileList', newData)
          /*  this.fileList = newData
            console.log(' this.fileList',  this.fileList)*/
        },
        deep: true,
      }
    },
    mounted() {
      // 拼接
      this.fileType.forEach(el => {
        this.accept += el
        this.accept += ','
      })
      /* this.fileType.slice(0, this.fileList.length - 2)
             console.log('fileType',this.fileType)
 */
      /* this.$nextTick(() => {
         this.fileList = this.list
         console.log('fffffffffffff', this.fileList)
       })*/
    },

    methods: {
      /** 手动提交上传 */
      submitUpload() {
        console.log('上传', this.fileList)
        if (this.fileList.length <= 0) {
          return false
        }
        this.$refs.upload.submit()
      },

      /** 调用接口上传 */
      httpRequest(param) {
        console.log("uploadFile", param.file);
        console.log("requestParams", this.requestParams.itemName, this.requestParams.sourceNode);
        const formdata = new FormData();
        formdata.append("uploadFile", param.file);
        for (let i in this.requestParams) {
          formdata.append(i, this.requestParams[i]);
        }
        /*  formdata.append("itemName", this.requestParams.itemName);
          formdata.append("sourceNode", this.requestParams.sourceNode);*/
        uploadAttachment(formdata).then(res => {
          console.log(res)
          if (res.data.code === 200) {
            // 回调方法,文件上传成功后,会调用`getfileList`指定的方法,在调用方定义
            this.$emit("getfileList", res.data.data)
            // 自定义上传时,需自己执行成功回调函数
            param.onSuccess()
            this.$refs.upload.clearFiles()
          }
        }).catch((err) => {
        })
      },

      // 上传失败
      handleUploadError(err) {
        this.$message.error("上传失败, 请重试");
      },
      // 上传成功回调
      handleUploadSuccess(res, file) {
        this.$message.success("上传成功");
        this.cancel()
      },
      //下载文件
      async handlePreview(file) {
        console.log('上传的file', file)
        console.log('fileList', this.fileList)
        const res = await downloadAttachmentByID({id: file.id})
        console.log(res);
        // const filename = res.headers["content-disposition"]
        const blob = new Blob([res.data])
        const a = document.createElement('a')
        const href = window.URL.createObjectURL(blob)
        a.href = href
        a.download = file.name
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
        window.URL.revokeObjectURL(href)
      },
      //删除文件
      async handleRemove(file) {
        console.log(file)
        if (file.status == "success") {
          console.log("删除的文件id------------", file.id);
          const request = {id: file.id};
          console.log(request);
          const res = await deleteAttachmentByID(request);
          console.log('deleteres', res)
          if (res.data.code == 200) {
            this.$message.success("文件删除成功");
            this.$emit('delfileList', file.id)
            // this.fileList = this.fileList.filter(item => item.id !== file.id)
          }
        }
      },
      // 上传前校检格式和大小
      handleBeforeUpload(file) {
        // 校检文件类型
        // if (this.fileType) {
        let fileExtension = "";
        if (file.name.lastIndexOf(".") > -1) {
          fileExtension = file.name.slice(file.name.lastIndexOf("."));
        }
        const isTypeOk = this.fileType.some((type) => {
          if (file.type.indexOf(type) > -1) return true;
          if (fileExtension && fileExtension.indexOf(type) > -1) return true;
          return false;
        });
        if (!isTypeOk) {
          this.$message.error(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
          return false;
        }
        // }
        // 校检文件大小
        if (this.fileSize) {
          const isLt = file.size / 1024 / 1024 < this.fileSize;
          if (!isLt) {
            this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
            return false;
          }
        }
        return true;
      },
      // 文件个数超出
      handleExceed() {
        this.$message.error(`允许上传最多${this.limit}个文件`);
      },

      /** 文件状态改变时调用 */
      handChange(file, fileList) {
        this.fileList = fileList
      },
      /* // 删除文件
       handleDelete(index) {
         this.fileList.splice(index, 1);
       },*/
      // 获取文件名称
      getFileName(name) {
        if (name.lastIndexOf("/") > -1) {
          return name.slice(name.lastIndexOf("/") + 1).toLowerCase();
        } else {
          return "";
        }
      },
    }
  }
</script>

<style scoped>

</style>

父组件使用

<template>
   <el-form-item label="性能指标:" prop="performanceIndexList">
  <Upload ref="fileUploadDialog" :request-params="{itemName:'性能指标',sourceNode:'需求申请'}"
          :fileList.sync="applyForm.performanceIndexList"
          @getfileList="getPerformanceList"
          @delfileList="delPerformanceList"></Upload>
</el-form-item>
</template>

methods:{
  //获取性能指标上传列表
  getPerformanceList(data) {
  this.applyForm.performanceIndexList.push(data.attachment)
  },
  //删除性能指标附件
  delPerformanceList(id) {
  this.applyForm.performanceIndexList = this.applyForm.performanceIndexList.filter(item => item.id !== id)
  },
}

文件分片

分片上传

<template>
  <!-- 上传器 -->
  <uploader
    ref="uploader"
    :options="options"
    :autoStart=false
    :file-status-text="fileStatusText"
    @file-added="onFileAdded"
    @file-success="onFileSuccess"
    @file-error="onFileError"
    class="uploader-ui">
    <uploader-unsupport></uploader-unsupport>
    <uploader-drop>
      <div>
        <uploader-btn id="global-uploader-btn" :attrs="attrs" ref="uploadBtn">选择文件<i
          class="el-icon-upload el-icon--right"></i></uploader-btn>
      </div>
    </uploader-drop>
    <uploader-list></uploader-list>
  </uploader>
</template>

<script>
  import {ACCEPT_CONFIG} from "@/api/dkyun/config.js"
  import SparkMD5 from 'spark-md5';
  import {mergeFile} from "@/api/dkyun/dkyun.js"
  import {getToken} from '@/utils/auth'
  import bus from "../bus.js"

  export default {
    data() {
      return {
        url: "",
        superId: "",
        options: {
          //目标上传 URL,默认POST
          target: 'http://10.3.74.84:9773/' + "wds/uploader/chunk",
          // target: 'http://10.12.113.217:9773/'+"wds/uploader/chunk",
          //target: `${this.url}`+"wds/uploader/chunk",
          //分块大小(单位:字节)
          chunkSize: '2048000',
          //上传文件时文件内容的参数名,对应chunk里的Multipart对象名,默认对象名为file
          fileParameterName: 'upfile',
          //失败后最多自动重试上传次数
          maxChunkRetries: 3,
          //是否开启服务器分片校验,对应GET类型同名的target URL
          testChunks: true,
          headers: {
            JWTHeaderName: getToken() ? getToken() : ''
          },
          /*
          服务器分片校验函数,判断秒传及断点续传,传入的参数是Uploader.Chunk实例以及请求响应信息
          reponse码是successStatuses码时,才会进入该方法
          reponse码如果返回的是permanentErrors 中的状态码,不会进入该方法,直接进入onFileError函数 ,并显示上传失败
          reponse码是其他状态码,不会进入该方法,正常走标准上传
          checkChunkUploadedByResponse函数直接return true的话,不再调用上传接口
          */
          // checkChunkUploadedByResponse: function (chunk, response_msg) {
          //     console.log("response_msg",response_msg)
          //     let objMessage = JSON.parse(response_msg);
          //     if (objMessage.skipUpload) {
          //         return true;
          //     }
          //     return (objMessage.uploadedChunks || []).indexOf(chunk.offset + 1) >= 0;
          // }
        },

        attrs: {
          accept: ACCEPT_CONFIG.getAll()
        },
        fileStatusText: {
          success: '上传成功',
          error: '上传失败',
          uploading: '上传中',
          paused: '暂停',
          waiting: '等待上传'
        },
      }
    },

    methods: {
      onFileAdded(file) {
        this.computeMD5(file);
        console.log("添加文件完成")
        console.log(this.superId, "asdfgh");
      },
      /*
      第一个参数 rootFile 就是成功上传的文件所属的根 Uploader.File 对象,它应该包含或者等于成功上传文件;
      第二个参数 file 就是当前成功的 Uploader.File 对象本身;
      第三个参数就是 message 就是服务端响应内容,永远都是字符串;
      第四个参数 chunk 就是 Uploader.Chunk 实例,它就是该文件的最后一个块实例,如果你想得到请求响应码的话,chunk.xhr.status就是
      */
      onFileSuccess(rootFile, file, response, chunk) {
        console.log("onFileSuccess")
        //refProjectId为预留字段,可关联附件所属目标,例如所属档案,所属工程等
        file.refProjectId = "123456789";
        file.superId = this.$store.state.dkyun.superid;
        console.log("file.superIdfile.superId", file.superId)
        console.log("file111", JSON.stringify(file))
        console.log("fize.size", file.size)
        mergeFile(file).then(responseData => {
          if (responseData.data.code === 415) {
            console.log("合并操作未成功,结果码:" + responseData.data.code);
          }
        }).catch(function (error) {
          console.log("合并后捕获的未知异常:" + error);
        });

      },
      onFileError(rootFile, file, response, chunk) {
        console.log('上传完成后异常信息:' + response);
      },

      /**
       * 计算md5,实现断点续传及秒传
       * @param file
       */
      computeMD5(file) {
        file.pause();

        //单个文件的大小限制1G
        let fileSizeLimit = 3 * 1024 * 1024 * 1024;
        console.log("文件大小:" + file.size);
        console.log("限制大小:" + fileSizeLimit);
        if (file.size > fileSizeLimit) {
          this.$message({
            showClose: true,
            type: 'error',
            message: '文件大小不能超过3G'
          });
          location.reload()
          return;
          // file.cancel();

        }

        let fileReader = new FileReader();
        let time = new Date().getTime();
        let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
        let currentChunk = 0;
        const chunkSize = 10 * 1024 * 1000;
        let chunks = Math.ceil(file.size / chunkSize);
        let spark = new SparkMD5.ArrayBuffer();
        //由于计算整个文件的Md5太慢,因此采用只计算第1块文件的md5的方式
        let chunkNumberMD5 = 1;

        loadNext();

        fileReader.onload = (e => {
          spark.append(e.target.result);

          if (currentChunk < chunkNumberMD5) {
            loadNext();
          } else {
            let md5 = spark.end();
            file.uniqueIdentifier = md5;
            file.resume();
            console.log(`MD5计算完毕:${file.name} \nMD5:${md5} \n分片:${chunks} 大小:${file.size} 用时:${new Date().getTime() - time} ms`);
          }
        });

        fileReader.onerror = function () {
          this.error(`文件${file.name}读取出错,请检查该文件`)
          file.cancel();
        };

        function loadNext() {
          let start = currentChunk * chunkSize;
          let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;

          fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
          currentChunk++;
          console.log("计算第" + currentChunk + "块");
        }
      },
      close() {
        this.uploader.cancel();
      },
      error(msg) {
        this.$notify({
          title: '错误',
          message: msg,
          type: 'error',
          duration: 2000
        })
      }
    },
    created() {
      console.log("create1111")
      this.url = localStorage.getItem('baseURL')
      console.log(this.url, "urlrrrrrrrr")
      //this.superId="0";

    },
    watch: {
      "$store.state.dkyun.superid"(current) {
        this.superId = current;
        //console.log(this.superId,"this.superIdthis.superIdthis.superId")
      }
    }
  }
</script>

<style>
  .uploader-ui {
    padding: 15px;
    margin: 40px auto 0;
    font-size: 12px;
    font-family: Microsoft YaHei;
    box-shadow: 0 0 10px rgba(0, 0, 0, .4);
  }

  .uploader-ui .uploader-btn {
    margin-right: 4px;
    font-size: 12px;
    border-radius: 3px;
    color: #FFF;
    background-color: #409EFF;
    border-color: #409EFF;
    display: inline-block;
    line-height: 1;
    white-space: nowrap;
  }

  .uploader-ui .uploader-list {
    max-height: 440px;
    overflow: auto;
    overflow-x: hidden;
    overflow-y: auto;
  }
</style>

分片下载

<template>
   <el-dialog title="文件下载" :visible.sync="downloadVisible" width="60%">
     <div class="warning"> 文件正在下载中,请勿操作电脑!</div>
     <el-progress :text-inside="true" :stroke-width="16" :percentage="percentage" status="success"></el-progress>
     <span slot="footer">
         <el-button type="danger" @click="cancleDownload">取消下载</el-button>
     </span>
   </el-dialog>
</template>

methods: {
      async downfiles(row) {
        this.downloadVisible = true
        this.downloading = true
        this.percentage = 0
        console.log(row, "下载文件下载文件");
        /*let a = document.createElement('a');
        a.href = it;
        a.click();*/
        let fileId = row.fileId.toString()
        const request1 = {
          fileId: fileId
        }
        const res = await getDownloadChunks(request1)
        this.totalNum = res.data.number
        console.log('块数', this.totalNum)
        if (this.downloading == true) {
          let result = []
          console.log('result', result)
          for (let i = 0; i < this.totalNum; i++) {
            if (this.downloading == true) {
              let request = {
                newFileName: row.fileName,
                fileId: fileId,
                shareId: row.shareId,
                index: i + 1
              };
              console.log('this.downloading)【【【【【【【【【【【', this.downloading)
              console.log("i2223=", i)
              const percentageNow = parseInt(i / this.totalNum * 100)
              console.log(percentageNow)
              this.percentage = percentageNow
              this.downloading = true
              // this.$emit('percentageChange', percentageNow, true)
              const Response = await downloadfile(request)
              console.log("Response", Response.data);
              const blob = Response.data
              result.push(blob)
              if (i == this.totalNum - 1) {
              // this.$emit('percentageChange', 100, false)
                this.percentage = 100
                this.downloading = false
                const data = new Blob(result, {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})
                const a = document.createElement('a')
                const href = window.URL.createObjectURL(data)
                a.href = href
                a.download = row.fileName
                document.body.appendChild(a)
                a.click()
                document.body.removeChild(a)
                window.URL.revokeObjectURL(href)
                this.downloadVisible = false
                this.$message({
                  type: "success",
                  message: "下载成功",
                });
              }
            }
          }
        }
      },
      cancleDownload() {
        this.downloadVisible = false
        this.downloading = false
        this.percentage = 0
        this.$message('已取消下载')
      },
    } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值