一、背景

企业微信自建项目中要求PC端也能进行文件预览,但是企业微信提供的接口只能在移动端使用,通过查阅资料修改成贴合项目的方法。参考:https://blog.csdn.net/w_t_y_y/article/details/115767747
kkFileView官方文档

二、preview-file组件

1.三种方式:
①、Office Web 查看器 http://view.officeapps.live.com/op/view.aspx?src=encodeuricomponent(url)
②、XDOC文档预览云服务 只能免费使用几天,后续需要付费400/年/IP
https://view.xdocin.com/view?src=encodeURIComponent(url)
③、kkFileView http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(url))

2.在components文件中,创建preview-file.vue文件,代码如下:

<template>
  <div>
    <!--图片-->
    <!--d-flex f-jc-c:display:flex; justify-content: center;-->
    <div class="d-flex f-jc-c" v-if="fileMessage.imgShow">
      <img :src="fileMessage.downloadUrl" />
    </div>

    <!--doc,excel-->
    <div v-else-if="fileMessage.docShow || fileMessage.excelShow">

       <!--Office Web 查看器 http://view.officeapps.live.com/op/view.aspx?src= -->
      <!-- XDOC文档预览云服务  只能免费使用几天,后续需要付费 https://view.xdocin.com/view?src=encodeURIComponent(fileMessage.downloadUrl)  -->
      <!-- kkFileView  http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(url))  -->
      
      <iframe class="child" frameborder="0"
        :src="'https://view.xdocin.com/view?src=' + encodeURIComponent(fileMessage.downloadUrl)"
        :style="{ width: fileStyle.width, height: fileStyle.height }">
      </iframe>
    </div>

    <!--音频-->
    <div v-else-if="fileMessage.audioShow">
      <!-- loop="loop"  循环播放 -->
      <audio id="myaudio" :src="fileMessage.downloadUrl" controls="controls" preload="preload">
        不支持audio标签
      </audio>
    </div>

    <!--视频-->
    <div class="d-flex f-jc-c" v-else-if="fileMessage.videoShow">
      <video preload="auto" align="center" controls="true">
        <source :src="fileMessage.downloadUrl" type="video/mp4" />
      </video>
    </div>

    <!--其他不能预览的-->
    <div v-else-if="fileMessage.otherShow"></div>

  </div>
</template>

<script lang="ts" setup>

import Video from 'video.js';

import 'video.js/dist/video-js.css';

interface Props {

  file: any

}

interface Emits {

  (event: 'downLoadFile', id: string | number): void
}

interface FileMessage {

  fileId: string | number,

  fileName: string,

  downloadUrl: string,

  imgShow: boolean,

  docShow: boolean,

  excelShow: boolean,

  audioShow: boolean,

  videoShow: boolean,

  //其他不能预览的
  otherShow: boolean,

}

interface FileStyle {

  height: string,

  width: string
}

const $props = defineProps<Props>();

const $emits = defineEmits<Emits>();

const file = computed(() => $props.file);

// 文件信息
const fileMessage = reactive<FileMessage>({

  fileId: '',

  fileName: '',

  downloadUrl: '',

  imgShow: false,

  docShow: false,

  excelShow: false,

  audioShow: false,

  videoShow: false,

  //其他不能预览的
  otherShow: false,
})

const fileStyle = reactive<FileStyle>({

  height: window.innerHeight + 'px',

  width: '100%'

})

// 判断文件类型
const judgeFileType = () => {

  fileMessage.fileName = file.value.fileName;

  fileMessage.downloadUrl = file.value.downloadUrl;

  fileMessage.fileId = file.value.id;

  console.log(fileMessage.downloadUrl, 'fileMessage');

 if (

    fileMessage.fileName.endsWith('png') ||

    fileMessage.fileName.endsWith('jpg') ||

    fileMessage.fileName.endsWith('jpeg') ||

    fileMessage.fileName.endsWith('gif')

  ) {
    //图片
    fileMessage.imgShow = true;

  } else if (

    fileMessage.fileName.endsWith('docx') ||

    fileMessage.fileName.endsWith('doc') ||

    fileMessage.fileName.endsWith('pdf') ||

    fileMessage.fileName.endsWith('pptx') ||

    fileMessage.fileName.endsWith('ppt') ||

    fileMessage.fileName.endsWith('txt')

  ) {

    //doc
    fileMessage.docShow = true;

  } else if (fileMessage.fileName.endsWith('xlsx') || fileMessage.fileName.endsWith('xls')) {

    //excel
    fileMessage.excelShow = true;

  }
  else if (fileMessage.fileName.endsWith('mp3')) {

    fileMessage.audioShow = true;
  }
  else if (fileMessage.fileName.endsWith('mp4')) {

    fileMessage.videoShow = true;

  } else {

    // fileMessage.otherShow = true;
    $emits('downLoadFile', fileMessage.fileId);

  }

}

onMounted(async () => {

  await judgeFileType();

})

</script>

<style scoped lang="scss">
img {
  width: 50%;
}

audio {
  width: 100%;
}

video {
  width: 30%;
}

.child {
  // width: 100%;
  // height: 100%;
  scrolling: no;
  frameborder: 0;
  border: 0;
  marginwidth: 0;
  marginheight: 0;
}
</style>

三、preview-file使用

1.template中使用方式

<!-- 查看附件 -->
    <van-popup v-model:show="previewFile.fileShow">
      <preview-file v-if="previewFile.fileShow" :file="previewFile.fileMessage" @downLoadFile="downLoadFile">
      </preview-file>
    </van-popup>

2.方法处理:

// 预览文件
const previewFile = reactive({
  fileShow: false,
  fileMessage: {
    id: '',
    fileName: '',
    downloadUrl: '',
  }
});

// 下载附件 适配PC Iphone Android
const handleDownFile = (file: any) => {

  // 不是企业微信
  if (!isWxWork()) {

    return drNotify('请用企业微信打开');

  }

  isMobile() ?

    (isAndroid() ? window.open(handleImgSrc(file.group, file.filepath)) : handlePreviewFile(file))

    :

    PCpreview(file);
}

// pc端预览文件
const PCpreview = (file: any) => {

  previewFile.fileMessage.id = file.id;

  previewFile.fileMessage.fileName = file.filename;

// handleImgSrc --- 为下载的路径
  previewFile.fileMessage.downloadUrl = handleImgSrc(file.group, file.filepath);

  previewFile.fileShow = true;

}

// 下载附件  PC端
const downLoadFile = (id: string | number) => {

  previewFile.fileShow = false;

  downloadLogFile.derive({ id }).then((res: any) => {

    if (!res.message) { }

  })
}

PS:Iphone与Android区分开来的原因:使用企业微信提供的文件预览的功能,Android使用会自动跳转浏览器并下载。

效果图展示:
vue3+ts 实现文件在线预览-LMLPHP
vue3+ts 实现文件在线预览-LMLPHP

12-08 09:54