linwenxin před 1 rokem
rodič
revize
dcf840e559
1 změnil soubory, kde provedl 369 přidání a 0 odebrání
  1. 369 0
      src/components/file-upload/index_oss.vue

+ 369 - 0
src/components/file-upload/index_oss.vue

@@ -0,0 +1,369 @@
+<template>
+  <div>
+    <el-upload name="file" :class="['uploader', uid]" :action="oss_url" :data="dataObj" :multiple="multiple"
+      :accept="accept" :show-file-list="false" :on-success="uploadSuccess" :before-upload="beforeUpload" />
+    <div class="images" v-if="modType === 'view'">
+      <div v-for="(item, index) in files" :key="index" class="item">
+        <div v-if="item.url" class="img">
+          <el-image v-if="checkFileType(item.url) == 'image'" ref="img" :src="imageURL + item.url"
+            :preview-src-list="previewImages" style="width: 120px; height: 120px" fit="cover" />
+          <el-image v-else ref="img" :src="imageURL + item.url" style="width: 120px; height: 120px" fit="cover">
+            <div slot="error" class="image-slot">
+              <img v-if="checkFileType(item.url) == 'word'" class="file" src="@/assets/common/word.png" />
+              <img v-if="checkFileType(item.url) == 'excel'" class="file" src="@/assets/common/excel.png" />
+              <img v-if="checkFileType(item.url) == 'ppt'" class="file" src="@/assets/common/ppt.png" />
+              <img v-if="checkFileType(item.url) == 'pdf'" class="file" src="@/assets/common/pdf.png" />
+              <img v-if="checkFileType(item.url) == 'file'" class="file" src="@/assets/common/zip.jpeg" />
+              <img v-if="checkFileType(item.url) == 'video'" class="file" src="@/assets/common/video.jpeg" />
+            </div>
+          </el-image>
+          <div v-if="isEdit || checkFileType(item.url) == 'image'" class="mask">
+            <i v-if="checkFileType(item.url) == 'image'" class="el-icon-zoom-in" @click="previewImage(item.url)" />
+            <i v-if="isEdit && isUpdate" class="el-icon-upload2" @click="uploadImage(item.url)" />
+            <i v-if="isEdit" class="el-icon-delete" @click="deleteImage(item.url)" />
+          </div>
+        </div>
+      </div>
+      <template v-if="isEdit">
+        <div v-if="limit">
+          <div v-if="limit !== files.length" class="add" @click="uploadImage()">
+            <i class="el-icon-plus" />
+          </div>
+        </div>
+        <div v-else>
+          <div v-if="multiple || (!multiple && files.length < 1)" class="add" @click="uploadImage()">
+            <i class="el-icon-plus" />
+          </div>
+        </div>
+      </template>
+    </div>
+    <div v-if="modType === 'btn'">
+      <el-button size="mini" type="primary" @click="uploadImage()">上传</el-button>
+    </div>
+  </div>
+</template>
+<script>
+import { getOssConfig } from '@/api/common'
+import { findElem } from '@/utils/util'
+
+export default {
+  name: 'FileUpload',
+  props: {
+    modType: {
+      type: String,
+      default: 'view'
+    },
+    uid: {
+      type: String,
+      default: 'uidImgfile'
+    },
+    // 最大上传数量
+    limit: {
+      type: Number,
+      default: 1
+    },
+    // 接受上传的文件列表
+    fileList: {
+      type: Array,
+      default: () => []
+    },
+    // 接受上传的文件类型
+    fileType: {
+      type: Array,
+      default: () => ['image', 'word', 'excel', 'ppt', 'pdf', 'file', 'video']
+    },
+    // 是否支持多选文件
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    startRestricting: {
+      type: Boolean,
+      default: false
+    },
+    restrictFilename: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    isEdit: {
+      type: Boolean,
+      default: true
+    },
+    isUpdate: {
+      type: Boolean,
+      default: true
+    },
+  },
+  data() {
+    return {
+      imageURL: this.$imageUrl,
+      oss_url: '',
+      dataObj: {},
+      uploadImageUrl: '',
+      waitUploadList: [],
+      fileName: '',
+      files: this.fileList
+    }
+  },
+  computed: {
+    isShowFileList: {
+      get: function () {
+        if (this.files.length > 0 && this.files[0].url) {
+          return true
+        } else {
+          return false
+        }
+      },
+      set: function (newValue) { }
+    },
+    accept() {
+      const imageList = ['.jpg', '.jpeg', '.png']
+      const videoList = ['.mp4']
+      const wordList = ['.doc', '.docx', '.dot', '.wps', '.wpt']
+      const excelList = ['.xls', '.xlsx', '.xlt', '.et', '.ett']
+      const pptList = ['.ppt', '.pptx', '.dps', '.dpt', '.pot', '.pps']
+      const pdfList = ['.pdf']
+      const fileList = ['.zip', '.rar', '.gz', '.apk']
+      let whiteList = []
+      this.fileType.includes('image') && (whiteList = whiteList.concat(imageList))
+      this.fileType.includes('video') && (whiteList = whiteList.concat(videoList))
+      this.fileType.includes('word') && (whiteList = whiteList.concat(wordList))
+      this.fileType.includes('excel') && (whiteList = whiteList.concat(excelList))
+      this.fileType.includes('ppt') && (whiteList = whiteList.concat(pptList))
+      this.fileType.includes('pdf') && (whiteList = whiteList.concat(pdfList))
+      this.fileType.includes('file') && (whiteList = whiteList.concat(fileList))
+      return whiteList.join(',')
+    },
+    previewImages() {
+      const fileList = []
+      if (this.files && this.files.length > 0) {
+        this.files.forEach(item => {
+          if (this.checkFileType(item.url) == 'image') {
+            fileList.push(this.imageURL + item.url)
+          }
+        })
+      }
+      return fileList
+    }
+  },
+  watch: {
+    files() {
+      if (this.isEdit) {
+        this.$emit('getFiles', this.files)
+      }
+    },
+    fileList() {
+      this.files = this.fileList
+    }
+  },
+  created() {
+    getOssConfig().then(res => {
+      this.oss_url = res.data.host
+    })
+  },
+  methods: {
+    getUUID() {
+      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
+        return (c === 'x' ? (Math.random() * 16) | 0 : 'r&0x3' | '0x8').toString(16)
+      })
+    },
+    createName(name) {
+      const date = Date.now()
+      const uuid = this.getUUID()
+      const fileSuffix = name.substring(name.lastIndexOf('.') + 1)
+      return `${date}${uuid}.${fileSuffix}`
+    },
+    // 检查文件类型
+    checkFileType(url) {
+      if (!url) return ''
+      const fileSuffix = url.substring(url.lastIndexOf('.') + 1)
+      if (['jpg', 'jpeg', 'png'].includes(fileSuffix)) {
+        return 'image'
+      } else if (['doc', 'docx', 'dot', 'wps', 'wpt'].includes(fileSuffix)) {
+        return 'word'
+      } else if (['xls', 'xlsx', 'xlt', 'et', 'ett'].includes(fileSuffix)) {
+        return 'excel'
+      } else if (['ppt', 'pptx', 'dps', 'dpt', 'pot', 'pps'].includes(fileSuffix)) {
+        return 'ppt'
+      } else if (['pdf'].includes(fileSuffix)) {
+        return 'pdf'
+      } else if (['zip', 'rar', 'gz', 'apk'].includes(fileSuffix)) {
+        return 'file'
+      } else if (['mp4'].includes(fileSuffix)) {
+        return 'video'
+      }
+    },
+    // 获取oss配置
+    async getOssConfig(fileName) {
+      const result = await new Promise((resolve, reject) => {
+        getOssConfig()
+          .then(res => {
+            const fileKey = this.createName(fileName)
+            res.data.name = fileName
+            res.data.key = res.data.dir + fileKey
+            resolve(res.data)
+          })
+          .catch(res => {
+            resolve({})
+          })
+      })
+      return result
+    },
+    // 预览图片
+    previewImage(url) {
+      const index = findElem(this.files, 'url', url)
+      this.$refs.img[index].showViewer = true
+    },
+    // 删除图片
+    deleteImage(url) {
+      const index = findElem(this.files, 'url', url)
+      this.files.splice(index, 1)
+    },
+    // 点击上传
+    uploadImage(url) {
+      this.uploadImageUrl = url
+      document.querySelector(`.${this.uid}` + ' input').click()
+    },
+    // 上传文件之前
+    async beforeUpload(file) {
+      const loading = this.$loading({
+        lock: true,
+        text: 'Loading',
+        spinner: 'el-icon-loading',
+        background: 'rgba(0, 0, 0, 0.7)'
+      })
+      this.getFileName(file.name)
+      this.$emit('handleIsFileName', this.fileName)
+      this.dataObj = await this.getOssConfig(this.fileName)
+      this.waitUploadList.push(this.dataObj)
+    },
+    // 文件上传成功
+    uploadSuccess(res, file) {
+      const loading = this.$loading({
+        lock: true,
+        text: 'Loading',
+        spinner: 'el-icon-loading',
+        background: 'rgba(0, 0, 0, 0.7)'
+      })
+      if (this.uploadImageUrl) {
+        const index = findElem(this.files, 'url', this.uploadImageUrl)
+        this.$set(this.files, index, {
+          name: this.dataObj.name,
+          url: this.dataObj.key,
+          size: file.size,
+          type: file.name.split(".")[file.name.split(".").length - 1]
+        })
+        this.waitUploadList = []
+      } else {
+        this.getFileName(file.name)
+        const index = findElem(this.waitUploadList, 'name', this.fileName)
+        this.files.push({
+          name: this.waitUploadList[index].name,
+          url: this.waitUploadList[index].key,
+          size: file.size,
+          type: file.name.split(".")[file.name.split(".").length - 1]
+        })
+        this.waitUploadList.splice(index, 1)
+      }
+      this.showFileList = true
+      loading.close()
+    },
+    getFileName(name) {
+      const fileName = name.substring(0, name.lastIndexOf('.'))
+      let suffix = name.match(/.[^.]+$/)[0]
+      // 押金申请上传限制
+      this.fileName = name
+      if (this.startRestricting) {
+        // 检查是否存在相应文字,否filterKeywords.length = 0
+        const filterKeywords = this.restrictFilename.filter(k => fileName.includes(k))
+        // filterKeywords = 0 || 'zip', 'rar', 'gz', 'apk' 归为 其他文件
+        if (!filterKeywords.length || suffix.includes('zip', 'rar', 'gz', 'apk')) {
+          this.fileName = `其他文件-${fileName}${suffix}`
+        }
+        // 限制照片/相片名称统一为照片 , restrictFilename[restrictFilename.length-1|restrictFilename.length-1]为照片、相片
+        if (fileName.includes('相片') || fileName.includes('照片')) {
+          this.fileName = `照片-${fileName}${suffix}`
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.images {
+  display: flex;
+  flex-wrap: wrap;
+
+  .item {
+    margin-right: 20px;
+    margin-bottom: 20px;
+
+    .img {
+      width: 120px;
+      height: 120px;
+      border-radius: 5px;
+      overflow: hidden;
+      position: relative;
+      border: 1px dashed #eaeaea;
+      display: flex;
+
+      .el-image {
+        display: block;
+      }
+
+      .file {
+        width: 120px;
+        height: 120px;
+        display: block;
+        padding: 30px;
+      }
+
+      .mask {
+        position: absolute;
+        left: 0;
+        top: 0;
+        width: 120px;
+        height: 120px;
+        background: rgba($color: #000000, $alpha: 0.3);
+        display: none;
+        align-items: center;
+        justify-content: center;
+
+        i {
+          font-size: 20px;
+          color: #ffffff;
+          cursor: pointer;
+          margin: 0 8px;
+        }
+      }
+
+      &:hover .mask {
+        display: flex;
+      }
+    }
+  }
+
+  .add {
+    width: 120px;
+    height: 120px;
+    border: 1px dashed #eaeaea;
+    border-radius: 5px;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    i {
+      font-size: 30px;
+      color: #999;
+    }
+  }
+}
+
+.uploader {
+  height: 0;
+}
+</style>