直播帶貨原始碼,二次封裝a-upload元件,自定義上傳預覽

zhibo系統開發發表於2023-02-21

直播帶貨原始碼,二次封裝a-upload元件,自定義上傳預覽

入參是本地上傳的檔案流

這裡我修改檔案流的名稱,返回file的promise

    transformFile(file) {
      return new Promise((resolve) => {
        const currentTime = new Date()
        const type = file.type.split('/')
        const renameFile = new File([file], currentTime.valueOf() + '.' + type[1], { type: file.type })
        resolve(renameFile)
      })
    }


自定義預覽

    handlePreview(file) {
      return new Promise((resolve, reject) => {
        try {
          resolve(this.previewFile(file))
        } catch (r) {
          reject(r)
        }
      })
    },


調整props和a-uoload一致

<template>
  <div style="display: inline-block">
    <div>
      <a-upload
        name="file"
        :accept="accept"
        :multiple="isMultiple"
        :disabled="disabled"
        :headers="headers"
        :fileList="[]"
        :customRequest="customRequest"
        :beforeUpload="beforeUpload"
        :remove="handleDelete"
        :transformFile="transformFile"
      >
        <a-button :loading="uploadLoading" v-if="!disabled && isMultiple && fileList.length < limit">
          <a-icon type="upload" /> {{text}}
        </a-button>
      </a-upload>
      <template v-if="fileList.length">
        <div v-for="(item, index) in fileList" :key="index" class="file-list-box">
          <img v-if="isImg(item.type)" :src="item.url" class="upload-icon-view" />
          <a-icon v-else-if="isPdf(item.type)" class="upload-icon-view" type="file" />
          <a-tooltip :title="item.name">
            <span class="upload-name-view">{{ item.name }}</span>
          </a-tooltip>
          <a-tooltip title="預覽">
            <span style="color: #0071fc; margin: 0 20px"><a-icon type="eye" @click="handlePreview(item)" /></span>
          </a-tooltip>
          <a-tooltip title="刪除">
            <span style="color: #f5222d" v-if="!disabled"><a-icon type="delete" @click="handleDelete(item)" /></span>
          </a-tooltip>
        </div>
      </template>
      <template v-else-if="disabled">
        <div style="text-align: left">
          <img :src="require('@/assets/gaoxinImgs/null-content.png')" alt="暫無資料" style="max-width: 100px" />
          <p style="text-align: center; width: 100px">暫無資料</p>
        </div>
      </template>
    </div>
    <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
      <img alt="圖片" style="width: 100%; height: 100%" :src="previewImage" />
    </a-modal>
  </div>
</template>
<script>
import Vue from 'vue'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { postAction, getFileAccessHttpUrl, getAction } from '@/api/manage'
const uidGenerator = () => {
  return '-' + parseInt(Math.random() * 10000 + 1, 10)
}
const getFileName = (path) => {
  if (path.lastIndexOf('\\') >= 0) {
    let reg = new RegExp('\\\\', 'g')
    path = path.replace(reg, '/')
  }
  return path.substring(path.lastIndexOf('/') + 1)
}
export default {
  name: 'JFileUpload',
  data() {
    return {
      url: window._CONFIG['pdfDomainURL'],
      staticUrl: window._CONFIG['pdfPreviewURL'],
      id: 'pdfFilePreviewIframeId',
      fileName: '',
      uploadAction: window._CONFIG['domianURL'] + '/sys/common/upload',
      uploadActionUrl: '/sys/common/upload',
      uploadLoading: false,
      picUrl: false,
      headers: {},
      token: {},
      fileList: [],
      previewImage: '',
      previewVisible: false,
    }
  },
  props: {
    accept: {
      type: String,
      default: () => 'image/*,.pdf',
    },
    limit: {
      type: Number,
      default: 10,
    },
    text: {
      type: String,
      required: false,
      default: '上傳附件(圖片、pdf)',
    },
    /*這個屬性用於控制檔案上傳的業務路徑*/
    bizPath: {
      type: String,
      required: false,
      default: 'temp',
    },
    value: {
      type: [String, Array],
      required: false,
    },
    disabled: {
      type: Boolean,
      required: false,
      default: false,
    },
    isMultiple: {
      type: Boolean,
      required: false,
      default: true,
    },
  },
  watch: {
    value: {
      deep: true,
      handler(val) {
        this.initFile(val)
      },
    },
  },
  created() {
    const token = Vue.ls.get(ACCESS_TOKEN)
    this.token = token
    this.headers = { 'X-Access-Token': token }
    this.initFile(this.value)
  },
  methods: {
    initFile(val) {
      if (val instanceof Array) {
        this.initFileList(val.join(','))
      } else {
        this.initFileList(val)
      }
    },
    isWord(fileType) {
      const wordTypeArray = ['doc', 'docx']
      const isWord = wordTypeArray.some((type) => {
        return fileType.toString().toUpperCase().includes(type.toString().toUpperCase())
      })
      return isWord
    },
    isExcel(fileType) {
      const excelTypeArray = ['XLS', 'XLSX', 'XLSB', 'XLSM', 'XLST', 'sheet']
      const isExcel = excelTypeArray.some((type) => {
        return fileType.toString().toUpperCase().includes(type.toString().toUpperCase())
      })
      return isExcel
    },
    isImg(fileType) {
      const imgTypeArray = ['BMP', 'JPG', 'JPEG', 'PNG', 'GIF']
      const isImgType = imgTypeArray.some((type) => {
        return fileType.toString().toUpperCase().includes(type.toString().toUpperCase())
      })
      return isImgType
    },
    isPdf(fileType) {
      const pdfTypeArray = ['PDF']
      const isPdfType = pdfTypeArray.some((type) => {
        return fileType.toString().toUpperCase().includes(type.toString().toUpperCase())
      })
      return isPdfType
    },
    renderDisplayName(name) {
      return name
    },
    async customRequest(file) {
      const form = new FormData()
      form.append('file', file.file)
      form.append('biz', this.bizPath)
      try {
        this.uploadLoading = true
        const res = await postAction(this.uploadActionUrl, form)
        if (res.success) {
          this.picUrl = true
          const length = this.fileList.length
          const url = getFileAccessHttpUrl(res.message)
          const type = res.message ? res.message.split('.')[res.message.split('.').length - 1] : 'null'
          const addFile = {
            uid: uidGenerator(),
            type: type,
            name: this.renderDisplayName(file.file.name),
            status: 'done',
            response: {
              status: 'done',
              message: res.message,
            },
            url: url,
            message: res.message,
            index: length,
          }
          this.fileList.push(addFile)
          this.$message.success('上傳成功')
          this.$emit('change', this.fileList.map((item) => item.message).join(','))
        } else {
          this.$message.error('上傳失敗')
        }
        this.uploadLoading = false
      } catch (r) {
        this.uploadLoading = false
        this.$message.error('上傳失敗')
        console.warn(r)
      }
    },
    transformFile(file) {
      return new Promise((resolve) => {
        const currentTime = new Date()
        const type = file.type.split('/')
        const renameFile = new File([file], currentTime.valueOf() + '.' + type[1], { type: file.type })
        resolve(renameFile)
      })
    },
    previewPdf(file) {
      const prefixUrl = this.staticUrl
      const path = file.response.message
      const fileUrl = prefixUrl + path
      return getAction(`/mybiz/myfile/preview/${fileUrl}`).then((previewUrl) => {
        if (previewUrl.toString().indexOf(') === 0) {
          const page = window.open(previewUrl)
          console.warn('page', page)
        } else {
          const page = window.open(' + previewUrl)
          console.warn('page', page)
        }
      })
    },
    previewImg(file) {
      this.previewImage = file.url
      this.previewVisible = true
    },
    previewExcel(file) {
      console.log('previewExcel', file)
      // 建立blob物件,解析流資料
    },
    previewFile(file) {
      const fileType = file.type
      console.log('fileType', fileType)
      if (this.isImg(fileType)) {
        return this.previewImg(file)
      } else {
        return this.previewPdf(file)
      }
    },
    initFileList(paths) {
      this.fileList = []
      if (!paths || paths.length === 0) {
        return 0
      }
      paths.split(',').forEach((item, index) => {
        const url = getFileAccessHttpUrl(item)
        const name = getFileName(item)
        const type = name && name.split('.').length ? name.split('.')[name.split('.').length - 1] : 'null'
        this.fileList.push({
          uid: uidGenerator(),
          name: this.renderDisplayName(name),
          type: type,
          status: 'done',
          url: url,
          response: {
            status: 'history',
            message: item,
          },
          message: item,
          index: index,
        })
      })
    },
    beforeUpload(file) {
      console.log('file', file)
      const fileType = file.name.split('.')[file.name.split('.').length - 1]
      // console.log('fileType', fileType)
      if (!this.isImg(fileType) && !this.isPdf(fileType)) {
        this.$message.warning('請上傳圖片或PDF')
        return false
      }
    },
    // 自定義預覽
    handlePreview(file) {
      return new Promise((resolve, reject) => {
        try {
          resolve(this.previewFile(file))
        } catch (r) {
          reject(r)
        }
      })
    },
    handleDelete(file) {
      this.fileList = this.fileList.filter((item) => item.uid!== file.uid)
    },
    handleCancel() {
      this.close()
    },
    close() {
      this.previewImage = ''
      this.previewVisible = false
    },
  },
  model: {
    prop: 'value',
    event: 'change',
  },
}
</script>
<style scoped>
.upload-name-view {
  max-width: 80px;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.upload-icon-view {
  position: relative;
  max-height: 48px;
  min-height: 48px;
  font-size: 32px;
  padding: 2px 10px 2px 2px;
  color: #0071fc;
}
.after-icon {
  line-height: 48px;
}
.file-list-box {
  position: relative;
  height: 66px;
  line-height: 48px;
  padding: 8px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  margin-top: 10px;
  width: fit-content;
}
</style> 
install封裝vue元件
丟擲去install在入口呼叫即可
import JFileUpload from './JFileUpload.vue'
export default {
  install(Vue) {
    Vue.component(JFileUpload.name, JFileUpload)
  },
}


以上就是 直播帶貨原始碼,二次封裝a-upload元件,自定義上傳預覽,更多內容歡迎關注之後的文章


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69978258/viewspace-2936173/,如需轉載,請註明出處,否則將追究法律責任。

相關文章