10 changed files with 359 additions and 25 deletions
@ -0,0 +1,89 @@ |
|||
<script lang="ts" setup> |
|||
import { useRoute } from 'vue-router' |
|||
import { DocumentEditor } from "@onlyoffice/document-editor-vue"; |
|||
import { useUserStore } from "@/store/modules/user"; |
|||
|
|||
const route = useRoute() |
|||
const userStore = useUserStore(); |
|||
const siteHost=document.location.origin; |
|||
const apiURL=import.meta.env.VITE_APP_BASE_API+"/hxpan/api" |
|||
const onlyOfficeHost= import.meta.env.VITE_ONLYOFFICE_HOST |
|||
const props = withDefaults(defineProps<{ |
|||
fileurl:string |
|||
}>(),{}) |
|||
|
|||
const config=ref({ |
|||
document: { |
|||
title: "Example Document Title.docx", |
|||
url:"", //云盘服务文件地址 |
|||
key:"" |
|||
}, |
|||
|
|||
documentType: "word", |
|||
editorConfig: { |
|||
"lang": "zh-CN",//"en-US", |
|||
mode: "view",//设置编辑模式,view, edit,review |
|||
callbackUrl: `${siteHost}${apiURL}/matter/save`, //当前网站的域名 |
|||
user: { |
|||
id: userStore.userInfoCont.number, |
|||
name: userStore.userInfoCont.nickname, |
|||
}, |
|||
} |
|||
}) |
|||
|
|||
function onLoadComponentError (errorCode:number, errorDescription:string) { |
|||
switch(errorCode) { |
|||
case -1: // Unknown error loading component |
|||
alert(errorDescription); |
|||
break; |
|||
case -2: // Error load DocsAPI from http://documentserver/ |
|||
alert(errorDescription); |
|||
break; |
|||
case -3: // DocsAPI is not defined |
|||
alert(errorDescription); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
onMounted(()=>{ |
|||
const query = route.query |
|||
if (query.fileurl){ |
|||
const info=query.info?.toString()??"error" |
|||
const _info=decodeURIComponent(atob(info)) |
|||
const _url=decodeURIComponent(query.fileurl) |
|||
const name=query.name?.toString()??"" |
|||
const dtype=query.dtype?.toString()??"word" |
|||
//验证一下文件名是否合规 |
|||
if (_info.includes(name)){ |
|||
config.value.document.url=_url |
|||
config.value.document.title=name |
|||
const _key=_url.match(/(\w+-\w+-\w+)/)![0] |
|||
if(_key) config.value.document.key=_key //合作编辑必须要有一个unique key |
|||
config.value.documentType=dtype |
|||
config.value.editorConfig.callbackUrl+=`?info=${_info}` |
|||
//设置编辑模式 |
|||
if(!query.verify) return; |
|||
const _verify = atob(query.verify) |
|||
//1:必须是验证通过,以true结尾 2:校验uuid是否匹配 |
|||
if(_verify.endsWith("true") && _key.includes(_verify.replace("true",""))){ |
|||
config.value.editorConfig.mode="edit" |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
|
|||
</script> |
|||
|
|||
<template> |
|||
<DocumentEditor |
|||
id="docEditor" |
|||
style="height: inherit;" |
|||
:documentServerUrl="onlyOfficeHost" |
|||
:config="config" |
|||
:onLoadComponentError="onLoadComponentError" |
|||
/> |
|||
</template> |
|||
<style> |
|||
|
|||
|
|||
</style> |
|||
@ -0,0 +1,160 @@ |
|||
<script lang="ts" setup> |
|||
import { |
|||
Document, |
|||
Delete, |
|||
Edit, |
|||
View, |
|||
} from '@element-plus/icons-vue' |
|||
import { shareItem} from "@/api/doc/type" |
|||
import {fileType } from "./tools" |
|||
|
|||
const apiURL=import.meta.env.VITE_APP_BASE_API+"/hxpan/api" |
|||
const siteHost=document.location.origin; |
|||
const officeHost=import.meta.env.VITE_OFFICE_HOST |
|||
const currentHoverRow=ref("") //当前选择的table行 |
|||
const visitList=ref<shareItem[]>([]) |
|||
let _db:Object; //indexedDB |
|||
|
|||
const props = withDefaults(defineProps<{ |
|||
uid:string, |
|||
udprt:string, |
|||
}>(),{}) |
|||
|
|||
//在线预览 |
|||
function onlyOfficeView(row:shareItem){ |
|||
const _type=fileType(row.name!) |
|||
if(_type!==""){ //office file |
|||
const info =btoa(encodeURIComponent(`${row.userUuid}/root${row.matters[0].path}`)) |
|||
const _url=`${siteHost}${apiURL}/share/zip?shareUuid=${row.uuid}&code=${row.code}&uid=${props.uid}&dprt=${props.udprt}&puuid=root&rootUuid=root` |
|||
window.open(`/#/onlyoffice?name=${row.name}&dtype=${_type}&info=${info}&fileurl=`+encodeURIComponent(_url),"_blank") |
|||
}else{ |
|||
//by kkFilePreview |
|||
let a = row.name ?? ''; |
|||
if(a.endsWith('...')){ |
|||
a=`${row.uuid}-${row.code}.zip` |
|||
} |
|||
|
|||
//由于预览服务在缓存文件时,直接按文件名缓存,所以同名文件就会出现覆盖错乱的问题 |
|||
a=a.match("(\.[a-zA-Z]+)$") |
|||
if (a && a.length>0) { |
|||
a=`${row.uuid}-${row.code}${a[0]}` |
|||
}else{ |
|||
a=`${row.uuid}${row.name}` |
|||
} |
|||
|
|||
let _url=`${siteHost}${apiURL}/share/zip?shareUuid=${row.uuid}&code=${row.code}&uid=${props.uid}&dprt=${props.udprt}&puuid=root&rootUuid=root&fullfilename=${a}` |
|||
window.open(`${officeHost}/kkpreview/onlinePreview?url=`+window.btoa(encodeURIComponent(_url)),"_blank") |
|||
} |
|||
} |
|||
|
|||
//在线编辑 |
|||
function onlyOfficeEdit(row:shareItem){ |
|||
const _type=fileType(row.name!) |
|||
if(_type===""){ |
|||
alert("暂不支持该类型编辑") |
|||
return |
|||
} |
|||
|
|||
const pstate=(row.permitList?.includes(props.uid)|| row.userUuid===atob(props.uid)) |
|||
if (!pstate){ |
|||
alert("你没有权限编辑") |
|||
return |
|||
} |
|||
|
|||
ElMessageBox.confirm("线上资源有限,确定继续线上编辑吗", "提示", { |
|||
confirmButtonText: "确定", |
|||
cancelButtonText: "取消", |
|||
type: "warning", |
|||
}).then(()=>{ |
|||
//office file |
|||
//base64 encode for MASK |
|||
const _verify = btoa(row.uuid.match(/(\w+-\w+)/)[0]+`${pstate}`) //增加一个权限验证的标记 |
|||
const info =btoa(encodeURIComponent(`${row.userUuid}/root${row.matters[0].path}`)) |
|||
const _url=`${siteHost}${apiURL}/share/zip?shareUuid=${row.uuid}&code=${row.code}&uid=${props.uid}&dprt=${props.udprt}&puuid=root&rootUuid=root` |
|||
window.open(`/#/onlyoffice?name=${row.name}&dtype=${_type}&info=${info}&verify=${_verify}&fileurl=`+encodeURIComponent(_url),"_blank") |
|||
}) |
|||
} |
|||
|
|||
//前端indexedDB的记录删除操作 |
|||
function onClearHistory(row:shareItem){ |
|||
_db.transaction('vlist','readwrite').objectStore("vlist").delete(row.uuid); |
|||
visitList.value=visitList.value.filter((item)=>{ |
|||
return item.uuid!==row.uuid |
|||
}) |
|||
} |
|||
|
|||
function handleMouseEnter(row:any){ |
|||
currentHoverRow.value=row.uuid |
|||
} |
|||
|
|||
onMounted(()=>{ |
|||
const request = indexedDB.open('visitList') |
|||
request.onupgradeneeded = (event) => { |
|||
// 首次创建或升级版本时触发 |
|||
_db = event.target.result; |
|||
if (!_db.objectStoreNames.contains('vlist')) { |
|||
// 创建对象仓库(类似表) |
|||
const store = _db.createObjectStore('vlist', { |
|||
keyPath: 'uuid', // 主键 |
|||
}); |
|||
} |
|||
}; |
|||
request.onsuccess = (e) => { |
|||
if (!_db) _db= e.target.result; |
|||
const store = _db.transaction('vlist', 'readonly').objectStore("vlist"); |
|||
|
|||
store.openCursor().onsuccess = (event) => { |
|||
const cursor = event.target.result; |
|||
if (cursor) { |
|||
visitList.value.push(cursor.value); |
|||
cursor.continue(); |
|||
} |
|||
}; |
|||
}; |
|||
}) |
|||
|
|||
onUnmounted(()=>{ |
|||
if (_db) _db.close() |
|||
}) |
|||
|
|||
</script> |
|||
|
|||
<template> |
|||
<el-row :gutter="24"> |
|||
<el-table |
|||
stripe |
|||
:data="visitList" |
|||
:header-cell-style="{ background: '#f5f8fd' }" |
|||
style="width: 100%" |
|||
row-key="uuid" |
|||
:row-style ="() => ({ height: '30px' })" |
|||
@cell-mouse-enter="handleMouseEnter"> |
|||
<el-table-column style="width: 70%;" property="name" label="最近访问"> |
|||
<template #default="scope"> |
|||
<div style="display: flex; align-items: center"> |
|||
<el-icon :size="20"><component :is="Document" /></el-icon> |
|||
<span style="margin-left: 10px">{{scope.row.name }}</span> |
|||
</div> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column width="250" align="center"> |
|||
<template #default="scope"> |
|||
<div v-show="currentHoverRow === scope.row.uuid"> |
|||
<el-button size="small" :icon="View" circle @click="onlyOfficeView(scope.row)"></el-button> |
|||
<el-button size="small" :icon="Edit" circle @click="onlyOfficeEdit(scope.row)"></el-button> |
|||
<el-button size="small" :icon="Delete" circle @click="onClearHistory(scope.row)"></el-button> |
|||
</div> |
|||
</template> |
|||
</el-table-column> |
|||
|
|||
<el-table-column width="100" prop="expireTime" label="失效日期"> |
|||
<template #default="scope"> |
|||
<span v-if="scope.row.expireTime">{{ scope.row.expireInfinity? '永久有效': scope.row.expireTime.slice(0,16) }}</span> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
</el-row> |
|||
</template> |
|||
<style> |
|||
|
|||
</style> |
|||
Loading…
Reference in new issue