Vue2 doc、excel、pdf、ppt、txt、图片以及视频等在线预览

打印 上一主题 下一主题

主题 1602|帖子 1602|积分 4806

安装

  1. npm install --save @vue-office/docx @vue-office/excel @vue-office/pdf vue-demi@0.14.6
复制代码
  vue-demi@0.14.6; 此中 @0.14.6 为版本号,可以不加,默认下载最新版。
  如果是 vue2.6 版本或以下还必要额外安装 @vue/composition-api
  1. npm install @vue/composition-api
复制代码
利用

目录结构

src\components

直接上代码

src\components\FileView\doc\index.vue

  1. <template>
  2.   <div>
  3.     <vue-office-docx
  4.       :src="docx"
  5.       style="height: 75vh"
  6.       @rendered="rendered"
  7.       @error="errorHandler"
  8.     />
  9.   </div>
  10. </template>
  11. <script>
  12. //引入VueOfficeDocx组件
  13. import VueOfficeDocx from "@vue-office/docx";
  14. //引入相关样式
  15. import "@vue-office/docx/lib/index.css";
  16. export default {
  17.   components: {
  18.     VueOfficeDocx,
  19.   },
  20.   props: {
  21.     docx: {
  22.       type: String,
  23.       default:
  24.         "http://qncdn.qkongtao.cn/lib/teamadmin/files/Hadoop2.7.1%E4%BC%AA%E5%88%86%E5%B8%83%E5%BC%8F%E9%9B%86%E7%BE%A4%E5%AE%89%E8%A3%85%E6%96%87%E6%A1%A3.docx", //设置文档网络地址,可以是相对地址
  25.     },
  26.   },
  27.   data() {
  28.     return {};
  29.   },
  30.   methods: {
  31.     rendered() {
  32.       console.log("渲染完成");
  33.     },
  34.     errorHandler() {
  35.       console.log("渲染失败");
  36.     },
  37.   },
  38. };
  39. </script>
复制代码
src\components\FileView\excel\index.vue

  1. <template>
  2.   <vue-office-excel
  3.     :src="excel"
  4.     :options="options"
  5.     @rendered="renderedHandler"
  6.     @error="errorHandler"
  7.     style="height: 75vh"
  8.   />
  9. </template>
  10. <script>
  11. //引入VueOfficeExcel组件
  12. import VueOfficeExcel from "@vue-office/excel";
  13. //引入相关样式
  14. import "@vue-office/excel/lib/index.css";
  15. export default {
  16.   components: {
  17.     VueOfficeExcel,
  18.   },
  19.   props: {
  20.     excel: {
  21.       type: String,
  22.       default:
  23.         "http://qncdn.qkongtao.cn/lib/teamadmin/files/2021%E5%B1%8A%E5%85%A8%E5%9B%BD%E5%90%84%E5%9C%B0%E6%B4%BE%E9%81%A3%E5%9C%B0%E5%9D%80.xlsx", //设置文档地址
  24.     },
  25.   },
  26.   data() {
  27.     return {
  28.       options: {
  29.         xls: true, //预览xlsx文件设置为false 预览xls文件设置为true
  30.         minColLength: 0,
  31.         minRowLength: 0,
  32.         widthOffset: 10,
  33.         heightOffset: 10,
  34.       },
  35.     };
  36.   },
  37.   methods: {
  38.     renderedHandler() {
  39.       console.log("渲染完成");
  40.     },
  41.     errorHandler() {
  42.       console.log("渲染失败");
  43.     },
  44.   },
  45. };
  46. </script>
复制代码
src\components\FileView\img\index.vue

  1. <template>
  2.   <div style="display: flex; justify-content: center">
  3.     <el-image :src="imgUrl" :preview-src-list="[imgUrl]"> fit="contain"></el-image>
  4.   </div>
  5. </template>
  6. <script>
  7. export default {
  8.   props: {
  9.     imgUrl: {
  10.       type: String,
  11.       default: "",
  12.     },
  13.   },
  14.   components: {},
  15.   data() {
  16.     return {};
  17.   },
  18.   methods: {
  19.     closeImage() {},
  20.   },
  21. };
  22. </script>
复制代码
src\components\FileView\pdf\index.vue

  1. <template>
  2.   <vue-office-pdf :src="pdf" style="height: 75vh" @rendered="rendered" />
  3. </template>
  4. <script>
  5. //引入VueOfficePdf组件
  6. import VueOfficePdf from "@vue-office/pdf";
  7. export default {
  8.   components: {
  9.     VueOfficePdf,
  10.   },
  11.   props: {
  12.     pdf: {
  13.       type: String,
  14.       default:
  15.         "http://qncdn.qkongtao.cn/lib/teamadmin/files/%E6%B7%B1%E5%9C%B3-xx-Java%E9%AB%98%E7%BA%A7.pdf",
  16.     },
  17.   },
  18.   data() {
  19.     return {};
  20.   },
  21.   methods: {
  22.     rendered() {
  23.       console.log("渲染完成");
  24.     },
  25.   },
  26. };
  27. </script>
复制代码
src\components\FileView\ppt\index.vue

PPT预览利用微软提供的方法进行文件预览
  1. <template>
  2.   <iframe
  3.     id="iframe1"
  4.     width="100%"
  5.     height="700px"
  6.     frameborder="0"
  7.     border="0"
  8.     marginwidth="0"
  9.     marginheight="0"
  10.     scrolling="no"
  11.     allowtransparency="no"
  12.     :src="'https://view.officeapps.live.com/op/embed.aspx?src=' + fileUrl"
  13.   ></iframe>
  14. </template>
  15. <script>
  16. export default {
  17.   props: {
  18.     fileUrl: {
  19.       type: String,
  20.       default: "",
  21.     },
  22.   },
  23.   components: {},
  24.   data() {
  25.     return {};
  26.   },
  27.   methods: {},
  28. };
  29. </script>
复制代码
src\components\FileView\txt\index.vue

  1. <template>
  2.   <div>
  3.     <pre class="pre-txt">{{ txtContent }}</pre>
  4.   </div>
  5. </template>
  6. <script>
  7. import axios from "axios";
  8. export default {
  9.   components: {},
  10.   props: {
  11.     fileUrl: {
  12.       type: String,
  13.       default: "https://example.com/your-txt-file.txt",
  14.     },
  15.   },
  16.   data() {
  17.     return {
  18.       txtContent: "",
  19.     };
  20.   },
  21.   mounted() {
  22.     this.fetchTxtFile();
  23.   },
  24.   methods: {
  25.     fetchTxtFile() {
  26.       axios
  27.         .get(this.fileUrl)
  28.         .then((response) => {
  29.           this.txtContent = response.data;
  30.         })
  31.         .catch((error) => {
  32.           console.error("获取txt文件失败:", error);
  33.         });
  34.     },
  35.   },
  36. };
  37. </script>
  38. <style scoped>
  39. .pre-txt {
  40.   font-size: 12px;
  41.   padding: 0;
  42.   width: 100%;
  43.   max-height: 70vh;
  44.   min-height: 70vh;
  45.   margin: 0;
  46.   background: #f0f0f0;
  47.   line-height: 20px; /* 行距 */
  48.   overflow: auto; /* 超出宽度出现滑动条 */
  49.   overflow-y: auto; /* 作用是隐藏IE的右侧滑动条 */
  50. }
  51. </style>
复制代码
src\components\FileView\index.vue

  1. <template>
  2.   <el-dialog
  3.     title="文件预览"
  4.     :visible.sync="open"
  5.     width="50vw"
  6.     :before-close="handleClose"
  7.     :close-on-click-modal="true"
  8.   >
  9.     <DOC :docx="url" v-if="componentToUse === 'DOC'"></DOC>
  10.     <PDF :pdf="url" v-if="componentToUse === 'PDF'"></PDF>
  11.     <EXCEL :excel="url" v-if="componentToUse === 'EXCEL'"></EXCEL>
  12.     <TXT :fileUrl="url" v-if="componentToUse === 'TXT'"></TXT>
  13.     <IMG :imgUrl="url" v-if="componentToUse === 'IMG'"></IMG>
  14.     <PPT :fileUrl="url" v-if="componentToUse === 'PPT'"></PPT>
  15.     <!-- <span slot="footer" class="dialog-footer">
  16.       <el-button @click="handleClose" size="small">关 闭</el-button>
  17.     </span> -->
  18.     <div v-if="componentToUse === 'WZ'">不支持的文件类型</div>
  19.   </el-dialog>
  20. </template>
  21. <script>
  22. import DOC from "./doc/index.vue";
  23. import PDF from "./pdf/index.vue";
  24. import EXCEL from "./excel/index.vue";
  25. import TXT from "./txt/index.vue";
  26. import IMG from "./img/index.vue";
  27. import PPT from "./ppt/index.vue";
  28. export default {
  29.   components: {
  30.     DOC,
  31.     PDF,
  32.     EXCEL,
  33.     TXT,
  34.     IMG,
  35.     PPT,
  36.   },
  37.   props: {
  38.     open: {
  39.       type: Boolean,
  40.       default: false,
  41.     },
  42.     url: {
  43.       type: String,
  44.       default:
  45.         "http://qncdn.qkongtao.cn/lib/teamadmin/files/Hadoop2.7.1%E4%BC%AA%E5%88%86%E5%B8%83%E5%BC%8F%E9%9B%86%E7%BE%A4%E5%AE%89%E8%A3%85%E6%96%87%E6%A1%A3.docx", //设置文档网络地址,可以是相对地址
  46.     },
  47.   },
  48.   data() {
  49.     return {
  50.       componentToUse: null, // 用于存储要使用的组件
  51.     };
  52.   },
  53.   watch: {
  54.     url() {
  55.       // 当 url 改变时,重新判断文件类型并设置组件
  56.       this.determineComponentType();
  57.     },
  58.   },
  59.   created() {
  60.     // 在组件创建时判断文件类型并设置组件
  61.     this.determineComponentType();
  62.   },
  63.   methods: {
  64.     rendered() {
  65.       console.log("渲染完成");
  66.     },
  67.     handleClose() {
  68.       this.$emit("update:open", false);
  69.     },
  70.     determineComponentType() {
  71.       const fileExtension = this.url.split(".").pop().toLowerCase();
  72.       switch (fileExtension) {
  73.         case "docx":
  74.           this.componentToUse = "DOC";
  75.           break;
  76.         case "pdf":
  77.           this.componentToUse = "PDF";
  78.           break;
  79.         case "xlsx":
  80.         case "xls":
  81.           this.componentToUse = "EXCEL";
  82.           break;
  83.         case "txt":
  84.         case "html":
  85.         case "vue":
  86.         case "js":
  87.         case "json":
  88.           this.componentToUse = "TXT";
  89.           break;
  90.         case "png":
  91.         case "jpg":
  92.         case "jpeg":
  93.           this.componentToUse = "IMG";
  94.           break;
  95.         case "ppt":
  96.         case "pptx":
  97.           this.componentToUse = "PPT";
  98.           break;
  99.         default:
  100.           console.error("不支持的文件类型");
  101.           this.componentToUse = "WZ";
  102.       }
  103.     },
  104.   },
  105. };
  106. </script>
复制代码
src\components\FileView\video\index.vue

  1. <template>
  2.   <div
  3.     class="m-video"
  4.     :class="{ 'u-video-hover': !hidden }"
  5.     :style="`width: ${veoWidth}; height: ${veoHeight};`"
  6.   >
  7.     <video
  8.       ref="veoRef"
  9.       class="u-video"
  10.       :style="`object-fit: ${zoom};`"
  11.       :src="src"
  12.       :poster="veoPoster"
  13.       :autoplay="autoplay"
  14.       :controls="!originPlay && controls"
  15.       :loop="loop"
  16.       :muted="autoplay || muted"
  17.       :preload="preload"
  18.       crossorigin="anonymous"
  19.       @loadeddata="poster ? () => false : getPoster()"
  20.       @pause="showPlay ? onPause() : () => false"
  21.       @playing="showPlay ? onPlaying() : () => false"
  22.       @click.prevent.once="onPlay"
  23.       v-bind="$attrs"
  24.     >
  25.       您的浏览器不支持video标签。
  26.     </video>
  27.     <svg
  28.       v-show="originPlay || showPlay"
  29.       class="u-play"
  30.       :class="{ hidden: hidden }"
  31.       :style="`width: ${playWidth}px; height: ${playWidth}px;`"
  32.       viewBox="0 0 24 24"
  33.     >
  34.       <path
  35.         stroke-linecap="round"
  36.         stroke-linejoin="round"
  37.         stroke-width="1.5"
  38.         d="M4.75 6.75C4.75 5.64543 5.64543 4.75 6.75 4.75H17.25C18.3546 4.75 19.25 5.64543 19.25 6.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H6.75C5.64543 19.25 4.75 18.3546 4.75 17.25V6.75Z"
  39.       ></path>
  40.       <path
  41.         stroke-linecap="round"
  42.         stroke-linejoin="round"
  43.         stroke-width="1.5"
  44.         d="M15.25 12L9.75 8.75V15.25L15.25 12Z"
  45.       ></path>
  46.     </svg>
  47.   </div>
  48. </template>
  49. <script>
  50. export default {
  51.   name: "Video",
  52.   props: {
  53.     src: {
  54.       // 视频文件url,必传,支持网络地址 https 和相对地址 require('@/assets/files/Bao.mp4')
  55.       type: String,
  56.       required: true,
  57.       default: "",
  58.     },
  59.     poster: {
  60.       // 视频封面url,支持网络地址 https 和相对地址 require('@/assets/images/Bao.jpg')
  61.       type: String,
  62.       default: "",
  63.     },
  64.     second: {
  65.       // 在未设置封面时,自动截取视频第 second 秒对应帧作为视频封面
  66.       type: Number,
  67.       default: 0.5,
  68.     },
  69.     width: {
  70.       // 视频播放器宽度,单位 px
  71.       type: [String, Number],
  72.       default: 800,
  73.     },
  74.     height: {
  75.       // 视频播放器高度,单位 px
  76.       type: [String, Number],
  77.       default: 450,
  78.     },
  79.     /*
  80.       参考 MDN 自动播放指南:https://developer.mozilla.org/zh-CN/docs/Web/Media/Autoplay_guide
  81.       Autoplay 功能
  82.       据新政策,媒体内容将在满足以下至少一个的条件下自动播放:
  83.       1.音频被静音或其音量设置为 0
  84.       2.用户和网页已有交互行为(包括点击、触摸、按下某个键等等)
  85.       3.网站已被列入白名单;如果浏览器确定用户经常与媒体互动,这可能会自动发生,也可能通过首选项或其他用户界面功能手动发生
  86.       4.自动播放策略应用到<iframe>或者其文档上
  87.       autoplay:由于目前在最新版的Chrome浏览器(以及所有以Chromium为内核的浏览器)中,
  88.       已不再允许自动播放音频和视频。就算你为video或audio标签设置了autoplay属性也一样不能自动播放!
  89.       解决方法:设置视频 autoplay 时,视频必须设置为静音 muted: true 即可实现自动播放,
  90.       然后用户可以使用控制栏开启声音,类似某宝商品自动播放的宣传视频逻辑
  91.     */
  92.     autoplay: {
  93.       // 视频就绪后是否马上播放,优先级高于 preload
  94.       type: Boolean,
  95.       default: false,
  96.     },
  97.     controls: {
  98.       // 是否向用户显示控件,比如进度条,全屏等
  99.       type: Boolean,
  100.       default: true,
  101.     },
  102.     loop: {
  103.       // 视频播放完成后,是否循环播放
  104.       type: Boolean,
  105.       default: false,
  106.     },
  107.     muted: {
  108.       // 是否静音
  109.       type: Boolean,
  110.       default: false,
  111.     },
  112.     preload: {
  113.       // 是否在页面加载后载入视频,如果设置了autoplay属性,则preload将被忽略;
  114.       type: String,
  115.       default: "metadata", // auto:一旦页面加载,则开始加载视频; metadata:当页面加载后仅加载视频的元数据 none:页面加载后不应加载视频
  116.     },
  117.     showPlay: {
  118.       // 播放暂停时是否显示播放器中间的暂停图标
  119.       type: Boolean,
  120.       default: true,
  121.     },
  122.     playWidth: {
  123.       // 中间播放暂停按钮的边长
  124.       type: Number,
  125.       default: 96,
  126.     },
  127.     zoom: {
  128.       // video的poster默认图片和视频内容缩放规则
  129.       type: String,
  130.       default: "contain", // none:(默认)保存原有内容,不进行缩放; fill:不保持原有比例,内容拉伸填充整个内容容器; contain:保存原有比例,内容以包含方式缩放; cover:保存原有比例,内容以覆盖方式缩放
  131.     },
  132.   },
  133.   data() {
  134.     return {
  135.       veoPoster: this.poster,
  136.       originPlay: true,
  137.       hidden: false,
  138.     };
  139.   },
  140.   computed: {
  141.     veoWidth() {
  142.       return '100%';
  143.     },
  144.     veoHeight() {
  145.       if (typeof this.height === "number") {
  146.         return this.height + "px";
  147.       }
  148.       return this.height;
  149.     },
  150.   },
  151.   mounted() {
  152.     if (this.autoplay) {
  153.       this.hidden = true;
  154.       this.originPlay = false;
  155.     }
  156.     /*
  157.       自定义设置播放速度,经测试:
  158.       在vue2中需设置:this.$refs.veoRef.playbackRate = 2
  159.       在vue3中需设置:veo.value.defaultPlaybackRate = 2
  160.     */
  161.     // this.$refs.veoRef.playbackRate = 2
  162.   },
  163.   methods: {
  164.     /*
  165.       loadedmetadata 事件在元数据(metadata)被加载完成后触发
  166.       loadeddata 事件在媒体当前播放位置的视频帧(通常是第一帧)加载完成后触发
  167.         若在移动/平板设备的浏览器设置中开启了流量节省(data-saver)模式,该事件则不会被触发。
  168.       preload 为 none 时不会触发
  169.     */
  170.     getPoster() {
  171.       // 在未设置封面时,自动获取视频0.5s对应帧作为视频封面
  172.       // 由于不少视频第一帧为黑屏,故设置视频开始播放时间为0.5s,即取该时刻帧作为封面图
  173.       this.$refs.veoRef.currentTime = this.second;
  174.       // 创建canvas元素
  175.       const canvas = document.createElement("canvas");
  176.       const ctx = canvas.getContext("2d");
  177.       // canvas画图
  178.       canvas.width = this.$refs.veoRef.videoWidth;
  179.       canvas.height = this.$refs.veoRef.videoHeight;
  180.       ctx.drawImage(this.$refs.veoRef, 0, 0, canvas.width, canvas.height);
  181.       // 把canvas转成base64编码格式
  182.       this.veoPoster = canvas.toDataURL("image/png");
  183.     },
  184.     onPlay() {
  185.       if (this.originPlay) {
  186.         this.$refs.veoRef.currentTime = 0;
  187.         this.originPlay = false;
  188.       }
  189.       if (this.autoplay) {
  190.         this.$refs.veoRef.pause();
  191.       } else {
  192.         this.hidden = true;
  193.         this.$refs.veoRef.play();
  194.       }
  195.     },
  196.     onPause() {
  197.       this.hidden = false;
  198.     },
  199.     onPlaying() {
  200.       this.hidden = true;
  201.     },
  202.   },
  203. };
  204. </script>
  205. <style scoped>
  206. * {
  207.   box-sizing: border-box;
  208.   margin: 0;
  209.   padding: 0;
  210. }
  211. .m-video {
  212.   display: inline-block;
  213.   position: relative;
  214.   background: #000;
  215.   cursor: pointer;
  216. }
  217. .u-play {
  218.   position: absolute;
  219.   top: 0;
  220.   right: 0;
  221.   bottom: 0;
  222.   left: 0;
  223.   margin: auto;
  224.   fill: none;
  225.   color: #fff;
  226.   pointer-events: none;
  227.   opacity: 0.7;
  228.   transition: opacity 0.3s;
  229. }
  230. .hidden {
  231.   opacity: 0;
  232. }
  233. .u-video {
  234.   display: inline-block;
  235.   width: 100%;
  236.   height: 100%;
  237.   vertical-align: bottom;
  238. }
  239. .u-video-hover {
  240. }
  241. </style>
复制代码
应用实例

建议在main.js中增长全局组件引用
  1. import FileView from '@/components/FileView'
  2. Vue.component('FileView',FileView)
复制代码
如果倒霉用全局挂载,那么请局部注册
我的利用场景

  1. <FileView :open.sync="fileViewOpen" :url="fileUrl" v-if="fileViewOpen" />
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

缠丝猫

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表