安装
- 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
- npm install @vue/composition-api
复制代码 利用
目录结构
src\components
直接上代码
src\components\FileView\doc\index.vue
- <template>
- <div>
- <vue-office-docx
- :src="docx"
- style="height: 75vh"
- @rendered="rendered"
- @error="errorHandler"
- />
- </div>
- </template>
- <script>
- //引入VueOfficeDocx组件
- import VueOfficeDocx from "@vue-office/docx";
- //引入相关样式
- import "@vue-office/docx/lib/index.css";
- export default {
- components: {
- VueOfficeDocx,
- },
- props: {
- docx: {
- type: String,
- default:
- "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", //设置文档网络地址,可以是相对地址
- },
- },
- data() {
- return {};
- },
- methods: {
- rendered() {
- console.log("渲染完成");
- },
- errorHandler() {
- console.log("渲染失败");
- },
- },
- };
- </script>
复制代码 src\components\FileView\excel\index.vue
- <template>
- <vue-office-excel
- :src="excel"
- :options="options"
- @rendered="renderedHandler"
- @error="errorHandler"
- style="height: 75vh"
- />
- </template>
- <script>
- //引入VueOfficeExcel组件
- import VueOfficeExcel from "@vue-office/excel";
- //引入相关样式
- import "@vue-office/excel/lib/index.css";
- export default {
- components: {
- VueOfficeExcel,
- },
- props: {
- excel: {
- type: String,
- default:
- "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", //设置文档地址
- },
- },
- data() {
- return {
- options: {
- xls: true, //预览xlsx文件设置为false 预览xls文件设置为true
- minColLength: 0,
- minRowLength: 0,
- widthOffset: 10,
- heightOffset: 10,
- },
- };
- },
- methods: {
- renderedHandler() {
- console.log("渲染完成");
- },
- errorHandler() {
- console.log("渲染失败");
- },
- },
- };
- </script>
复制代码 src\components\FileView\img\index.vue
- <template>
- <div style="display: flex; justify-content: center">
- <el-image :src="imgUrl" :preview-src-list="[imgUrl]"> fit="contain"></el-image>
- </div>
- </template>
- <script>
- export default {
- props: {
- imgUrl: {
- type: String,
- default: "",
- },
- },
- components: {},
- data() {
- return {};
- },
- methods: {
- closeImage() {},
- },
- };
- </script>
复制代码 src\components\FileView\pdf\index.vue
- <template>
- <vue-office-pdf :src="pdf" style="height: 75vh" @rendered="rendered" />
- </template>
- <script>
- //引入VueOfficePdf组件
- import VueOfficePdf from "@vue-office/pdf";
- export default {
- components: {
- VueOfficePdf,
- },
- props: {
- pdf: {
- type: String,
- default:
- "http://qncdn.qkongtao.cn/lib/teamadmin/files/%E6%B7%B1%E5%9C%B3-xx-Java%E9%AB%98%E7%BA%A7.pdf",
- },
- },
- data() {
- return {};
- },
- methods: {
- rendered() {
- console.log("渲染完成");
- },
- },
- };
- </script>
复制代码 src\components\FileView\ppt\index.vue
PPT预览利用微软提供的方法进行文件预览
- <template>
- <iframe
- id="iframe1"
- width="100%"
- height="700px"
- frameborder="0"
- border="0"
- marginwidth="0"
- marginheight="0"
- scrolling="no"
- allowtransparency="no"
- :src="'https://view.officeapps.live.com/op/embed.aspx?src=' + fileUrl"
- ></iframe>
- </template>
- <script>
- export default {
- props: {
- fileUrl: {
- type: String,
- default: "",
- },
- },
- components: {},
- data() {
- return {};
- },
- methods: {},
- };
- </script>
复制代码 src\components\FileView\txt\index.vue
- <template>
- <div>
- <pre class="pre-txt">{{ txtContent }}</pre>
- </div>
- </template>
- <script>
- import axios from "axios";
- export default {
- components: {},
- props: {
- fileUrl: {
- type: String,
- default: "https://example.com/your-txt-file.txt",
- },
- },
- data() {
- return {
- txtContent: "",
- };
- },
- mounted() {
- this.fetchTxtFile();
- },
- methods: {
- fetchTxtFile() {
- axios
- .get(this.fileUrl)
- .then((response) => {
- this.txtContent = response.data;
- })
- .catch((error) => {
- console.error("获取txt文件失败:", error);
- });
- },
- },
- };
- </script>
- <style scoped>
- .pre-txt {
- font-size: 12px;
- padding: 0;
- width: 100%;
- max-height: 70vh;
- min-height: 70vh;
- margin: 0;
- background: #f0f0f0;
- line-height: 20px; /* 行距 */
- overflow: auto; /* 超出宽度出现滑动条 */
- overflow-y: auto; /* 作用是隐藏IE的右侧滑动条 */
- }
- </style>
复制代码 src\components\FileView\index.vue
- <template>
- <el-dialog
- title="文件预览"
- :visible.sync="open"
- width="50vw"
- :before-close="handleClose"
- :close-on-click-modal="true"
- >
- <DOC :docx="url" v-if="componentToUse === 'DOC'"></DOC>
- <PDF :pdf="url" v-if="componentToUse === 'PDF'"></PDF>
- <EXCEL :excel="url" v-if="componentToUse === 'EXCEL'"></EXCEL>
- <TXT :fileUrl="url" v-if="componentToUse === 'TXT'"></TXT>
- <IMG :imgUrl="url" v-if="componentToUse === 'IMG'"></IMG>
- <PPT :fileUrl="url" v-if="componentToUse === 'PPT'"></PPT>
- <!-- <span slot="footer" class="dialog-footer">
- <el-button @click="handleClose" size="small">关 闭</el-button>
- </span> -->
- <div v-if="componentToUse === 'WZ'">不支持的文件类型</div>
- </el-dialog>
- </template>
- <script>
- import DOC from "./doc/index.vue";
- import PDF from "./pdf/index.vue";
- import EXCEL from "./excel/index.vue";
- import TXT from "./txt/index.vue";
- import IMG from "./img/index.vue";
- import PPT from "./ppt/index.vue";
- export default {
- components: {
- DOC,
- PDF,
- EXCEL,
- TXT,
- IMG,
- PPT,
- },
- props: {
- open: {
- type: Boolean,
- default: false,
- },
- url: {
- type: String,
- default:
- "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", //设置文档网络地址,可以是相对地址
- },
- },
- data() {
- return {
- componentToUse: null, // 用于存储要使用的组件
- };
- },
- watch: {
- url() {
- // 当 url 改变时,重新判断文件类型并设置组件
- this.determineComponentType();
- },
- },
- created() {
- // 在组件创建时判断文件类型并设置组件
- this.determineComponentType();
- },
- methods: {
- rendered() {
- console.log("渲染完成");
- },
- handleClose() {
- this.$emit("update:open", false);
- },
- determineComponentType() {
- const fileExtension = this.url.split(".").pop().toLowerCase();
- switch (fileExtension) {
- case "docx":
- this.componentToUse = "DOC";
- break;
- case "pdf":
- this.componentToUse = "PDF";
- break;
- case "xlsx":
- case "xls":
- this.componentToUse = "EXCEL";
- break;
- case "txt":
- case "html":
- case "vue":
- case "js":
- case "json":
- this.componentToUse = "TXT";
- break;
- case "png":
- case "jpg":
- case "jpeg":
- this.componentToUse = "IMG";
- break;
- case "ppt":
- case "pptx":
- this.componentToUse = "PPT";
- break;
- default:
- console.error("不支持的文件类型");
- this.componentToUse = "WZ";
- }
- },
- },
- };
- </script>
复制代码 src\components\FileView\video\index.vue
- <template>
- <div
- class="m-video"
- :class="{ 'u-video-hover': !hidden }"
- :style="`width: ${veoWidth}; height: ${veoHeight};`"
- >
- <video
- ref="veoRef"
- class="u-video"
- :style="`object-fit: ${zoom};`"
- :src="src"
- :poster="veoPoster"
- :autoplay="autoplay"
- :controls="!originPlay && controls"
- :loop="loop"
- :muted="autoplay || muted"
- :preload="preload"
- crossorigin="anonymous"
- @loadeddata="poster ? () => false : getPoster()"
- @pause="showPlay ? onPause() : () => false"
- @playing="showPlay ? onPlaying() : () => false"
- @click.prevent.once="onPlay"
- v-bind="$attrs"
- >
- 您的浏览器不支持video标签。
- </video>
- <svg
- v-show="originPlay || showPlay"
- class="u-play"
- :class="{ hidden: hidden }"
- :style="`width: ${playWidth}px; height: ${playWidth}px;`"
- viewBox="0 0 24 24"
- >
- <path
- stroke-linecap="round"
- stroke-linejoin="round"
- stroke-width="1.5"
- 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"
- ></path>
- <path
- stroke-linecap="round"
- stroke-linejoin="round"
- stroke-width="1.5"
- d="M15.25 12L9.75 8.75V15.25L15.25 12Z"
- ></path>
- </svg>
- </div>
- </template>
- <script>
- export default {
- name: "Video",
- props: {
- src: {
- // 视频文件url,必传,支持网络地址 https 和相对地址 require('@/assets/files/Bao.mp4')
- type: String,
- required: true,
- default: "",
- },
- poster: {
- // 视频封面url,支持网络地址 https 和相对地址 require('@/assets/images/Bao.jpg')
- type: String,
- default: "",
- },
- second: {
- // 在未设置封面时,自动截取视频第 second 秒对应帧作为视频封面
- type: Number,
- default: 0.5,
- },
- width: {
- // 视频播放器宽度,单位 px
- type: [String, Number],
- default: 800,
- },
- height: {
- // 视频播放器高度,单位 px
- type: [String, Number],
- default: 450,
- },
- /*
- 参考 MDN 自动播放指南:https://developer.mozilla.org/zh-CN/docs/Web/Media/Autoplay_guide
- Autoplay 功能
- 据新政策,媒体内容将在满足以下至少一个的条件下自动播放:
- 1.音频被静音或其音量设置为 0
- 2.用户和网页已有交互行为(包括点击、触摸、按下某个键等等)
- 3.网站已被列入白名单;如果浏览器确定用户经常与媒体互动,这可能会自动发生,也可能通过首选项或其他用户界面功能手动发生
- 4.自动播放策略应用到<iframe>或者其文档上
- autoplay:由于目前在最新版的Chrome浏览器(以及所有以Chromium为内核的浏览器)中,
- 已不再允许自动播放音频和视频。就算你为video或audio标签设置了autoplay属性也一样不能自动播放!
- 解决方法:设置视频 autoplay 时,视频必须设置为静音 muted: true 即可实现自动播放,
- 然后用户可以使用控制栏开启声音,类似某宝商品自动播放的宣传视频逻辑
- */
- autoplay: {
- // 视频就绪后是否马上播放,优先级高于 preload
- type: Boolean,
- default: false,
- },
- controls: {
- // 是否向用户显示控件,比如进度条,全屏等
- type: Boolean,
- default: true,
- },
- loop: {
- // 视频播放完成后,是否循环播放
- type: Boolean,
- default: false,
- },
- muted: {
- // 是否静音
- type: Boolean,
- default: false,
- },
- preload: {
- // 是否在页面加载后载入视频,如果设置了autoplay属性,则preload将被忽略;
- type: String,
- default: "metadata", // auto:一旦页面加载,则开始加载视频; metadata:当页面加载后仅加载视频的元数据 none:页面加载后不应加载视频
- },
- showPlay: {
- // 播放暂停时是否显示播放器中间的暂停图标
- type: Boolean,
- default: true,
- },
- playWidth: {
- // 中间播放暂停按钮的边长
- type: Number,
- default: 96,
- },
- zoom: {
- // video的poster默认图片和视频内容缩放规则
- type: String,
- default: "contain", // none:(默认)保存原有内容,不进行缩放; fill:不保持原有比例,内容拉伸填充整个内容容器; contain:保存原有比例,内容以包含方式缩放; cover:保存原有比例,内容以覆盖方式缩放
- },
- },
- data() {
- return {
- veoPoster: this.poster,
- originPlay: true,
- hidden: false,
- };
- },
- computed: {
- veoWidth() {
- return '100%';
- },
- veoHeight() {
- if (typeof this.height === "number") {
- return this.height + "px";
- }
- return this.height;
- },
- },
- mounted() {
- if (this.autoplay) {
- this.hidden = true;
- this.originPlay = false;
- }
- /*
- 自定义设置播放速度,经测试:
- 在vue2中需设置:this.$refs.veoRef.playbackRate = 2
- 在vue3中需设置:veo.value.defaultPlaybackRate = 2
- */
- // this.$refs.veoRef.playbackRate = 2
- },
- methods: {
- /*
- loadedmetadata 事件在元数据(metadata)被加载完成后触发
- loadeddata 事件在媒体当前播放位置的视频帧(通常是第一帧)加载完成后触发
- 若在移动/平板设备的浏览器设置中开启了流量节省(data-saver)模式,该事件则不会被触发。
- preload 为 none 时不会触发
- */
- getPoster() {
- // 在未设置封面时,自动获取视频0.5s对应帧作为视频封面
- // 由于不少视频第一帧为黑屏,故设置视频开始播放时间为0.5s,即取该时刻帧作为封面图
- this.$refs.veoRef.currentTime = this.second;
- // 创建canvas元素
- const canvas = document.createElement("canvas");
- const ctx = canvas.getContext("2d");
- // canvas画图
- canvas.width = this.$refs.veoRef.videoWidth;
- canvas.height = this.$refs.veoRef.videoHeight;
- ctx.drawImage(this.$refs.veoRef, 0, 0, canvas.width, canvas.height);
- // 把canvas转成base64编码格式
- this.veoPoster = canvas.toDataURL("image/png");
- },
- onPlay() {
- if (this.originPlay) {
- this.$refs.veoRef.currentTime = 0;
- this.originPlay = false;
- }
- if (this.autoplay) {
- this.$refs.veoRef.pause();
- } else {
- this.hidden = true;
- this.$refs.veoRef.play();
- }
- },
- onPause() {
- this.hidden = false;
- },
- onPlaying() {
- this.hidden = true;
- },
- },
- };
- </script>
- <style scoped>
- * {
- box-sizing: border-box;
- margin: 0;
- padding: 0;
- }
- .m-video {
- display: inline-block;
- position: relative;
- background: #000;
- cursor: pointer;
- }
- .u-play {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- margin: auto;
- fill: none;
- color: #fff;
- pointer-events: none;
- opacity: 0.7;
- transition: opacity 0.3s;
- }
- .hidden {
- opacity: 0;
- }
- .u-video {
- display: inline-block;
- width: 100%;
- height: 100%;
- vertical-align: bottom;
- }
- .u-video-hover {
- }
- </style>
复制代码 应用实例
建议在main.js中增长全局组件引用
- import FileView from '@/components/FileView'
- Vue.component('FileView',FileView)
复制代码 如果倒霉用全局挂载,那么请局部注册
我的利用场景
- <FileView :open.sync="fileViewOpen" :url="fileUrl" v-if="fileViewOpen" />
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |