add: pptx文件预览

This commit is contained in:
liyulin 2024-10-21 20:06:07 +08:00
parent e5491ed202
commit 10b236eb87
17 changed files with 440 additions and 75 deletions

144
README.md
View File

@ -1,15 +1,12 @@
# vue-office
支持多种文件(**docx、excel、pdf**)预览的vue组件库支持vue2/3。也支持非Vue框架的预览。
支持多种文件(**docx、excel、pdf、pptx**)预览的vue组件库支持vue2/3。也支持非Vue框架的预览。
[《演示效果》](https://501351981.github.io/vue-office/examples/dist/)
[《使用非Vue框架原生js、React等、或者Vue里面报错看这里》](https://501351981.github.io/vue-office/examples/docs/guide/js-preview.html)
[《详细配置》](https://501351981.github.io/vue-office/examples/docs/config/)
## 功能特色
- 一站式提供word(.docx)、pdf、excel(.xlsx, .xls)多种文档的在线预览方案,有它就够了
- 一站式提供word(.docx)、pdf、excel(.xlsx, .xls)、ppt(.pptx)多种文档的在线预览方案,有它就够了
- 简单只需提供文档的src(网络地址)即可完成文档预览
- 体验好:选择每个文档的最佳预览方案,保证用户体验和性能都达到最佳状态
- 性能好:针对数据量较大做了优化
@ -24,6 +21,9 @@ npm install @vue-office/excel vue-demi@0.14.6
#pdf文档预览组件
npm install @vue-office/pdf vue-demi@0.14.6
#pptx文档预览组件
npm install @vue-office/pptx vue-demi@0.14.6
```
如果是vue2.6版本或以下还需要额外安装 @vue/composition-api
```shell
@ -39,11 +39,11 @@ npm install @vue/composition-api
**使用网络地址预览**
```vue
<template>
<vue-office-docx
:src="docx"
style="height: 100vh;"
@rendered="rendered"
/>
<vue-office-docx
:src="docx"
style="height: 100vh;"
@rendered="rendered"
/>
</template>
<script>
@ -53,19 +53,19 @@ import VueOfficeDocx from '@vue-office/docx'
import '@vue-office/docx/lib/index.css'
export default {
components:{
VueOfficeDocx
},
data(){
return {
docx: 'http://static.shanhuxueyuan.com/test6.docx' //设置文档网络地址,可以是相对地址
components:{
VueOfficeDocx
},
data(){
return {
docx: 'http://static.shanhuxueyuan.com/test6.docx' //设置文档网络地址,可以是相对地址
}
},
methods:{
rendered(){
console.log("渲染完成")
}
}
},
methods:{
rendered(){
console.log("渲染完成")
}
}
}
</script>
```
@ -75,10 +75,10 @@ export default {
读取文件的ArrayBuffer
```vue
<template>
<div>
<input type="file" @change="changeHandle"/>
<vue-office-docx :src="src"/>
</div>
<div>
<input type="file" @change="changeHandle"/>
<vue-office-docx :src="src"/>
</div>
</template>
<script>
@ -86,24 +86,24 @@ import VueOfficeDocx from '@vue-office/docx'
import '@vue-office/docx/lib/index.css'
export default {
components: {
VueOfficeDocx
},
data(){
return {
src: ''
components: {
VueOfficeDocx
},
data(){
return {
src: ''
}
},
methods:{
changeHandle(event){
let file = event.target.files[0]
let fileReader = new FileReader()
fileReader.readAsArrayBuffer(file)
fileReader.onload = () => {
this.src = fileReader.result
}
}
}
},
methods:{
changeHandle(event){
let file = event.target.files[0]
let fileReader = new FileReader()
fileReader.readAsArrayBuffer(file)
fileReader.onload = () => {
this.src = fileReader.result
}
}
}
}
</script>
```
@ -114,11 +114,11 @@ export default {
```vue
<template>
<vue-office-docx
:src="docx"
style="height: 100vh;"
@rendered="rendered"
/>
<vue-office-docx
:src="docx"
style="height: 100vh;"
@rendered="rendered"
/>
</template>
<script>
@ -128,29 +128,29 @@ import VueOfficeDocx from '@vue-office/docx'
import '@vue-office/docx/lib/index.css'
export default {
components:{
VueOfficeDocx
},
data(){
return {
docx: ''
}
},
mounted(){
fetch('你的API文件地址', {
method: 'post'
}).then(res=>{
//读取文件的arrayBuffer
res.arrayBuffer().then(res=>{
this.docx = res
components:{
VueOfficeDocx
},
data(){
return {
docx: ''
}
},
mounted(){
fetch('你的API文件地址', {
method: 'post'
}).then(res=>{
//读取文件的arrayBuffer
res.arrayBuffer().then(res=>{
this.docx = res
})
})
})
},
methods:{
rendered(){
console.log("渲染完成")
},
methods:{
rendered(){
console.log("渲染完成")
}
}
}
}
</script>
```
@ -200,7 +200,7 @@ export default {
通过网络地址预览示例如下通过文件ArrayBuffer预览和上面docx的使用方式一致。
```vue
<template>
<vue-office-pdf
<vue-office-pdf
:src="pdf"
style="height: 100vh"
@rendered="renderedHandler"
@ -249,7 +249,3 @@ export default {
<img src="https://501351981.github.io/vue-office/examples/dist/static/wxqrcode.png" alt="个人微信" width="260"/>
# 我的其他库:
- 如何更优雅地进行前端表单开发:[ConfigForm](https://github.com/501351981/config-form)

View File

@ -0,0 +1 @@
import{d as r}from"./docx-629d4f97.js";import{d as p}from"./url-065d6777.js";import{d as x,_ as l,r as _,o as h,w as v,a as m,c as g,b as D,e as w,f as y,g as O,u as B}from"./index-69842e67.js";import{P as R,u}from"./PreviewWrapper-d9a4255b.js";import"./jszip.min-391c5e2f.js";import"./_commonjs-dynamic-modules-302442b1.js";typeof window.setImmediate>"u"&&(window.setImmediate=function(e,...o){setTimeout(()=>e(o))});const $=x({name:"VueOfficeDocx",props:{src:[String,ArrayBuffer,Blob],requestOptions:{type:Object,default:()=>({})},options:{type:Object,default:()=>({})}},emits:["rendered","error"],setup(e,{emit:o}){const n=_(null);let c=null;function a(){let t=n.value;r.getData(e.src,e.requestOptions).then(async i=>{c=await r.getBlob(i),r.render(c,t,e.options).then(()=>{o("rendered")}).catch(f=>{r.render("",t,e.options),o("error",f)})}).catch(i=>{r.render("",t,e.options),o("error",i)})}h(()=>{e.src&&a()}),v(()=>e.src,()=>{e.src?a():r.render("",n.value,e.options).then(()=>{o("rendered")})});function s(t){p(t||`vue-office-docx-${new Date().getTime()}.docx`,c)}return{rootRef:n,save:s}}}),b={class:"vue-office-docx"},V={class:"vue-office-docx-main",ref:"rootRef"};function k(e,o,n,c,a,s){return m(),g("div",b,[D("div",V,null,512)])}const d=l($,[["render",k]]);d.install=function(e){e.component(d.name,d)};const q={__name:"DocxDemo",setup(e){function o(){u.hideLoading()}function n(t){console.log("出差",t),u.hideLoading()}const c=location.origin+(location.pathname+"/").replace("//","/")+"static/test-files/test.docx",a=_(),s={headers:{"component-name":"VueOfficeDocx"}};return(t,i)=>(m(),w(R,{accept:".docx",placeholder:"请输入docx文件地址","default-src":c},{default:y(f=>[O(B(d),{ref_key:"docxRef",ref:a,src:f.src,"request-options":s,style:{flex:"1",height:"0"},onRendered:o,onError:n},null,8,["src"])]),_:1}))}},P=l(q,[["__scopeId","data-v-844ea5ef"]]);export{P as default};

View File

@ -0,0 +1 @@
import{r as $,S as L,a as b,g as C,b as q,t as F,c as E}from"./hack-42be15c5.js";import{l as V}from"./lodash-cf981bf5.js";import{d as W}from"./url-065d6777.js";import{d as j,_ as M,r as S,o as N,n as A,h as H,w as P,a as T,c as U,b as z,i as G,e as J,f as K,j as Q,g as X,u as Y}from"./index-69842e67.js";import{P as Z,u as O}from"./PreviewWrapper-d9a4255b.js";import"./_commonjs-dynamic-modules-302442b1.js";const k={xls:!1,minColLength:20},ee=j({name:"VueOfficeExcel",props:{src:[String,ArrayBuffer,Blob],requestOptions:{type:Object,default:()=>({})},options:{type:Object,default:()=>({...k})}},emits:["rendered","error","switchSheet","cellSelected","cellsSelected"],setup(e,{emit:n}){const u=S(null),f=S(null);let a={_worksheets:[]},r=[],h=0,x=null,t=null,w=null,o=null;function d(_){o=_,q(_,e.options.xls).then(i=>{if(!i._worksheets||i._worksheets.length===0)throw new Error("未获取到数据,可能文件格式不正确或文件已损坏");e.options.beforeTransformData&&typeof e.options.beforeTransformData=="function"&&(i=e.options.beforeTransformData(i));let{workbookData:m,medias:y,workbookSource:s}=F(i,{...k,...e.options});e.options.transformData&&typeof e.options.transformData=="function"&&(m=e.options.transformData(m)),r=y,a=s,w=null,h=0,E(),t.loadData(m),b(x,r,a._worksheets[h],w,e.options),n("rendered"),n("switchSheet",0)}).catch(i=>{console.warn(i),r=[],a={_worksheets:[]},E(),t&&t.loadData({}),n("error",i),n("switchSheet",0)})}const l=V.debounce($,200).bind(this,f.value),c=new MutationObserver(l),v={attributes:!0,childList:!0,subtree:!0};N(()=>{A(()=>{c.observe(f.value,v),l(f),t=new L(f.value,{mode:"read",showToolbar:!1,showContextmenu:e.options.showContextmenu||!1,view:{height:()=>u.value&&u.value.clientHeight||300,width:()=>u.value&&u.value.clientWidth||1200},row:{height:24,len:100},col:{len:26,width:80,indexWidth:60,minWidth:60},autoFocus:!1}).loadData({}),t.on("cell-selected",(s,p,D)=>{n("cellSelected",{cell:s,rowIndex:p,columnIndex:D})}),t.on("cells-selected",(s,{sri:p,sci:D,eri:I,eci:B})=>{n("cellsSelected",{cell:s,startRowIndex:p,startColumnIndex:D,endRowIndex:I,endColumnIndex:B})});let _=t.bottombar.swapFunc;t.bottombar.swapFunc=function(s){_.call(t.bottombar,s),h=s,setTimeout(()=>{t.reRender(),b(x,r,a._worksheets[h],w,e.options),n("switchSheet",s)})};let i=t.sheet.editor.clear;t.sheet.editor.clear=function(...s){i.apply(t.sheet.editor,s),setTimeout(()=>{b(x,r,a._worksheets[h],w,e.options)})};let m=t.sheet.editor.setOffset;t.sheet.editor.setOffset=function(...s){m.apply(t.sheet.editor,s),w=s[0],b(x,r,a._worksheets[h],w,e.options)},x=f.value.querySelector("canvas").getContext("2d"),e.src&&C(e.src,e.requestOptions).then(d).catch(s=>{r=[],a={_worksheets:[]},t.loadData({}),n("error",s)})})}),H(()=>{c.disconnect(),t=null}),P(()=>e.src,()=>{e.src?C(e.src,e.requestOptions).then(d).catch(_=>{r=[],a={_worksheets:[]},t.loadData({}),n("error",_)}):(r=[],a={_worksheets:[]},t.loadData({}),n("error",new Error("src属性不能为空")))});function R(_){W(_||`vue-office-excel-${new Date().getTime()}.xlsx`,o)}return{wrapperRef:u,rootRef:f,save:R}}}),te={class:"vue-office-excel",ref:"wrapperRef"},oe={class:"vue-office-excel-main",ref:"rootRef"};function se(e,n,u,f,a,r){return T(),U("div",te,[z("div",oe,null,512)],512)}const g=M(ee,[["render",se]]);g.install=function(e){e.component(g.name,g)};const fe={__name:"ExcelDemo",setup(e){function n(){O.hideLoading()}function u(o){console.log("出差",o),O.hideLoading()}function f(o){return console.log("transformData",o),o}const a=location.origin+(location.pathname+"/").replace("//","/")+"static/test-files/test.xlsx",r=S();function h(o){return console.log("beforeTransformData",o,r),o._worksheets.forEach(d=>{let l=0;if(d._rows[l]&&d._rows[l]._cells)for(let c=0;c<d._rows[l]._cells.length;c++){let v=d._rows[l]._cells[c];v?v.style={bgcolor:"#00ff00"}:d._rows[l]._cells[c]={text:"",value:"",style:{bgcolor:"#00ff00"}}}}),o}function x(o){console.log("当前sheet",o)}function t(o){console.log("点击了单元格",o)}function w(o){console.log("选择了单元格",o)}return(o,d)=>{const l=G("loading");return T(),J(Z,{accept:".xlsx,.xls",placeholder:"请输入xlsx文件地址","default-src":a},{default:K(c=>[Q(X(Y(g),{ref_key:"docxRef",ref:r,src:c.src,options:{beforeTransformData:h,transformData:f,xls:c.xls},style:{flex:"1",height:"0"},onRendered:n,onError:u,onSwitchSheet:x,onCellSelected:t,onCellsSelected:w},null,8,["src","options"]),[[l,!0]])]),_:1})}}};export{fe as default};

View File

@ -0,0 +1 @@
var p=Object.defineProperty;var c=(i,e,t)=>e in i?p(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var n=(i,e,t)=>(c(i,typeof e!="symbol"?e+"":e,t),t);import{d as r}from"./docx-629d4f97.js";import{d as l}from"./url-065d6777.js";import{r as h,o as d,a as u,c as m}from"./index-69842e67.js";import"./jszip.min-391c5e2f.js";import"./_commonjs-dynamic-modules-302442b1.js";typeof window.setImmediate>"u"&&(window.setImmediate=function(i,...e){setTimeout(()=>i(e))});class w{constructor(e,t={},s={}){n(this,"container",null);n(this,"wrapper",null);n(this,"wrapperMain",null);n(this,"options",{});n(this,"requestOptions",{});n(this,"fileData",null);this.container=e,this.options=t,this.requestOptions=s,this.createWrapper()}createWrapper(){this.wrapper=document.createElement("div"),this.wrapper.className="vue-office-docx",this.wrapperMain=document.createElement("div"),this.wrapperMain.className="vue-office-docx-main",this.wrapper.appendChild(this.wrapperMain),this.container.appendChild(this.wrapper)}setOptions(e){this.options=e}setRequestOptions(e){this.requestOptions=e}preview(e){return new Promise((t,s)=>{r.getData(e,this.requestOptions).then(async o=>{this.fileData=await r.getBlob(o),r.render(this.fileData,this.wrapperMain,this.options).then(()=>{t()}).catch(a=>{r.render("",this.wrapperMain,this.options),s(a)})}).catch(o=>{r.render("",this.wrapperMain,this.options),s(o)})})}save(e){l(e||`js-preview-docx-${new Date().getTime()}.docx`,this.fileData)}destroy(){this.container.removeChild(this.wrapper),this.container=null,this.wrapper=null,this.wrapperMain=null,this.options=null,this.requestOptions=null}}function f(i,e,t){return new w(i,e,t)}const v={init:f};const g={__name:"JsDocxDemo",setup(i){const e=h(null);return d(()=>{let t=v.init(e.value);t.preview("/vue-office/examples/dist/static/test-files/test.docx").then(s=>{console.log("docx preview done"),setTimeout(()=>{t.preview("/vue-office/examples/dist/static/test-files/test2.docx")},3e3)}).catch(s=>{console.log("err",s)})}),(t,s)=>(u(),m("div",{ref_key:"dom",ref:e},null,512))}};export{g as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{r as u,m as C,_ as I,w as N,l as n,a as d,c as k,u as t,g as i,f as r,p as g,q as S,e as h,s as y,k as V,t as A,v as R,b as T}from"./index-69842e67.js";function $(e){const p=u("url"),a=u(e),o=u(e),l=u(typeof e=="string"?e.endsWith(".xls"):!1),c=u([]);function x(_){l.value=_.name.endsWith("xls");let f=new FileReader;return f.onload=s=>{let v=s.target.result;o.value=v},f.readAsArrayBuffer(_),!1}return{type:p,inputSrc:a,src:o,xls:l,fileList:c,beforeUpload:x}}let w=u(!1),B;function q(e){B=C.loading(e,0),w.value=!0}function E(){w.value===!0&&(B(),w.value=!1)}const F={loading:w,showLoading:q,hideLoading:E};function j(){return location.href.includes("test")}const z=e=>(A("data-v-0bd825a5"),e=e(),R(),e),D={class:"preview-wrapper"},G={key:0,class:"operate-area"},H=z(()=>T("div",{class:"preview-wrapper-main"},null,-1)),J={__name:"PreviewWrapper",props:{accept:String,placeholder:String,defaultSrc:String},setup(e){const p=e,{type:a,inputSrc:o,src:l,xls:c,fileList:x,beforeUpload:_}=$(p.defaultSrc);return N(l,()=>{F.showLoading()},{immediate:!0}),(f,s)=>{const v=n("a-radio-button"),L=n("a-radio-group"),U=n("a-input"),b=n("a-button"),W=n("upload-outlined"),P=n("a-upload");return d(),k("div",D,[t(j)()?y("",!0):(d(),k("div",G,[i(L,{value:t(a),"onUpdate:value":s[0]||(s[0]=m=>S(a)?a.value=m:null),"button-style":"solid"},{default:r(()=>[i(v,{value:"url"},{default:r(()=>[g("远程文件地址")]),_:1}),i(v,{value:"upload"},{default:r(()=>[g("上传本地文件")]),_:1})]),_:1},8,["value"]),t(a)==="url"?(d(),h(U,{key:0,value:t(o),"onUpdate:value":s[1]||(s[1]=m=>S(o)?o.value=m:null),placeholder:p.placeholder,style:{width:"600px","margin-left":"10px"}},null,8,["value","placeholder"])):y("",!0),t(a)==="url"?(d(),h(b,{key:1,type:"primary",style:{"margin-left":"10px"},onClick:s[2]||(s[2]=m=>{l.value=t(o),c.value=t(o).endsWith("xls")})},{default:r(()=>[g(" 预览 ")]),_:1})):y("",!0),t(a)!=="url"?(d(),h(P,{key:2,accept:p.accept,action:"",beforeUpload:t(_),"file-list":[]},{default:r(()=>[i(b,{style:{"margin-left":"10px"}},{default:r(()=>[i(W),g(" 选择文件 ")]),_:1})]),_:1},8,["accept","beforeUpload"])):y("",!0)])),V(f.$slots,"default",{src:t(l),xls:t(c)},void 0,!0),H])}}},M=I(J,[["__scopeId","data-v-0bd825a5"]]);export{M as P,F as u};

22
examples/dist/assets/docx-629d4f97.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

173
examples/dist/assets/hack-42be15c5.js vendored Normal file

File diff suppressed because one or more lines are too long

121
examples/dist/assets/index-69842e67.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

27
examples/dist/assets/lodash-cf981bf5.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -7,7 +7,7 @@
content="width=device-width, initial-scale=1.0,minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<title>@vue-office演示demo</title>
<script type="module" crossorigin src="/vue-office/examples/dist/assets/index-7cd18a29.js"></script>
<script type="module" crossorigin src="/vue-office/examples/dist/assets/index-69842e67.js"></script>
<link rel="stylesheet" href="/vue-office/examples/dist/assets/index-9a3c0236.css">
</head>
<body>

Binary file not shown.