阿里云链接 预览组件

40 阅读1分钟

image.png

<template>
    <el-dialog :class="[curFileType === 'img' ? 'file-preview-dialog-img' : 'file-preview-dialog']" v-model="showDialog"
        :width="curFileType === 'img' ? '600' : '60%'" title="文件预览" append-to-body
        @close="handlerClose">
      <div v-loading="loading" style="width: 100%;height: 100%">
        <!-- word -->
        <vue-office-docx v-if="curFileType === 'word' && isRenderSuccess" class="office" :src="fileUrl"
                         @rendered="renderedHandler" @error="errorHandler" />
        <!-- execl -->
        <vue-office-excel v-else-if="curFileType === 'execl' && isRenderSuccess" class="office" :src="fileUrl"
                          @rendered="renderedHandler" @error="errorHandler" />
        <!-- pdf -->
        <VuePdfEmbed v-else-if="curFileType === 'pdf' && isRenderSuccess" class="office" :source="fileUrl"
                     @rendered="renderedHandler" @rendering-failed="errorHandler" />
        <!-- img -->
        <el-image v-else-if="curFileType === 'img' && isRenderSuccess" class="image" :src="fileUrl"
                  @load="renderedHandler" @error="errorHandler" />
        <!-- video -->
        <video v-else-if="curFileType === 'video' && isRenderSuccess" class="video" :src='fileUrl' autoplay loop
               muted></video>
        <!-- 加载失败 -->
        <el-empty v-else-if="curFileType && !isRenderSuccess" :image="loadError" description="加载失败" />
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="download">下载</el-button>
        </div>
      </template>
    </el-dialog>
</template>

<script setup>
import {ref} from "vue";

const { proxy } = getCurrentInstance();

const loadError = new URL(`@/assets/images/load-error.png`, import.meta.url).href;

// docx
import VueOfficeDocx from '@vue-office/docx'
import '@vue-office/docx/lib/index.css';

// execl
import VueOfficeExcel from '@vue-office/excel'
import '@vue-office/excel/lib/index.css'

// pdf
import VuePdfEmbed from 'vue-pdf-embed';
import { getCurrentInstance, onMounted} from 'vue';

// 获取文件类型
const imgTypeList = ['jpg', 'png', 'jpeg', 'ofd']
const videoTypeList = ['mp4', 'avi', 'wmv', 'rmvb', 'flv', 'mkv']
const wordTypeList = ['docx','doc']
const execlTypeList = ['xlsx','xls']
const pdfTypeList = ['pdf']

const curFileType = ref('')

const loading = ref(false)
const fileUrl = ref('')
let fileType


const handlerFileType = () => {
  let targetType
  if (imgTypeList.includes(fileType)) {
    targetType = 'img'
  } else if (videoTypeList.includes(fileType)) {
    targetType = 'video'
  } else if (wordTypeList.includes(fileType)) {
    targetType = 'word'
  } else if (execlTypeList.includes(fileType)) {
    targetType = 'execl'
  } else if (pdfTypeList.includes(fileType)) {
    targetType = 'pdf'
  }

  return targetType
}

function show(url,type){
  loading.value = true
  fileUrl.value = url
  fileType = type
  curFileType.value = handlerFileType()
  showDialog.value = true
}



// 渲染成功
const isRenderSuccess = ref(true)
const renderedHandler = () => {
  loading.value = false
}

// 渲染失败
const errorHandler = (err) => {
    isRenderSuccess.value = false
  loading.value = false
}

const showDialog = ref(false)

// 关闭弹窗
const handlerClose = () => {
  fileType = ''
  fileUrl.value = ''
  showDialog.value = false
}

function download(){
  window.open(fileUrl.value)
}

defineExpose({
  show
})
</script>

<style scoped lang='scss'>
.office {
    width: 100%;
    height: 60vh;
    overflow-y: auto;

    :deep(.docx-wrapper) {
        background-color: #fff !important;
    }

    :deep(.vue-office-pdf-wrapper) {
        background-color: #fff !important;
    }
}

.image {
    width: 500px;
    // height: 420px;
    // object-fit: fill;
}

.video {
    width: 100%;
    max-height: 80vh;
}

.dialog-footer{
  width: 100%;
  display: flex;
  flex-direction: row;
  justify-content: center;
}
</style>

<style lang="scss">
.file-preview-dialog {
    .el-dialog__body {
        display: flex;
        justify-content: center;
    }
}

.file-preview-dialog-img {
    .el-dialog__body {
        height: calc(85vh - 72px);
        overflow: auto;
        text-align: center;
    }
}
</style>