文件列表
<template>
<div>
<div class='file' v-if='$myUtils.coll.isNotEmpty(filesList)'>
<div class='file-view'>
<div class='file-view-item' :style='{justifyContent: align }' v-for='(item, index) in filesList' :key='index'>
<img class='file-view-item-icon' alt=''
:src='require(`@/assets/file/${getFileSuffix(item.fileSuffix)}.png`)' />
<template v-if='isShowQuery(item)'>
<div class='file-view-item-info file-view-item-infoHover' @click='previewFile(item)'>
<a-tooltip placement='topLeft' :title='item.fileName + item.fileSuffix'>
{{ item.fileName }}.{{ item.fileSuffix }}
</a-tooltip>
</div>
</template>
<template v-else>
<div class='file-view-item-info'>
<a-tooltip placement='top' :title='item.fileName + item.fileSuffix'>
{{ item.fileName }}.{{ item.fileSuffix }}
</a-tooltip>
</div>
</template>
<img class='file-view-item-icon mr-5' alt='' @click="downloadFile(item)"
:src='require(`@/assets/file/down.png`)' />
</div>
</div>
</div>
<div v-else class='not-file'>
暂无文件
</div>
<my-a ref='myA'></my-a>
</div>
</template>
<script>
import { filesApiGetListByIds, getPreviewFileUrl, getDownLoadFileUrl } from '@/api/system/files'
import MyA from '@/components/My/MyA'
let fileMap = {
image: ['png', 'jpeg', 'jpg'],
word: ['doc', 'docx', 'wps'],
pdf: ['pdf'],
ofd: ['ofd'],
excel: ['xls', 'xlsx'],
zip: ['zip', 'rar'],
pptx: ['ppt', 'pptx'],
bin: ['bin'],
txt: ['txt'],
deb: ['deb']
}
export default {
name: 'MyFileListMinor',
components: {
MyA
},
props: {
filesIds: [String, Array],
emptyText: {
type: String,
default: '暂无文件'
},
align: {
type: String,
default: 'left'
}
},
filters: {
toKB(val) {
return (Number(val) / 1024).toFixed(0)
}
},
watch: {
filesIds: {
handler: function(filesIds) {
if (filesIds != null
&& (this.$myUtils.str.isNotEmpty(filesIds)
|| this.$myUtils.coll.isNotEmpty(filesIds))) {
this.getFilesList(filesIds)
} else {
this.filesList = []
}
},
immediate: true
}
},
data() {
return {
filesList: []
}
},
methods: {
getFileSuffix(suffix) {
let result = ''
if (fileMap.word.indexOf(suffix) !== -1) {
result = 'word'
} else if (fileMap.pdf.indexOf(suffix) !== -1) {
result = 'pdf'
} else if (fileMap.ofd.indexOf(suffix) !== -1) {
result = 'ofd'
} else if (fileMap.excel.indexOf(suffix) !== -1) {
result = 'xlsx'
} else if (fileMap.image.indexOf(suffix) !== -1) {
result = 'image'
} else if (fileMap.zip.indexOf(suffix) !== -1) {
result = 'zip'
} else if (fileMap.pptx.indexOf(suffix) !== -1) {
result = 'ppt'
} else if (fileMap.bin.indexOf(suffix) !== -1) {
result = 'bin'
} else if (fileMap.txt.indexOf(suffix) !== -1) {
result = 'txt'
} else {
result = 'other'
}
return result
},
/**
* 是否显示查看按钮
* @param item
* @returns {boolean}
*/
isShowQuery(item) {
let show = false
if (item) {
switch (item.fileSuffix) {
case 'pdf':
case 'doc':
case 'docx':
case 'ofd':
case 'jpg':
case 'png':
case 'jpeg':
show = true
}
}
return show
},
/**
* 文件预览
* @param {*} files
*/
previewFile(files) {
if ('ofd' === files.fileSuffix) {
const routeData = this.$router.resolve({
path: '/ofd/preview',
query: {
id: files.fileId
}
});
window.open(routeData.href, "_blank");
} else {
const url = getPreviewFileUrl(files.fileId)
this.$refs.myA.target(url)
}
},
/**
* 文件下载
* @param {*} files
*/
downloadFile(files) {
const url = getDownLoadFileUrl(files.fileId)
this.$refs.myA.target(url)
},
getFilesList(filesIds) {
let ids = ''
if (filesIds.constructor == String) {
ids = filesIds
} else {
ids = filesIds.join()
}
filesApiGetListByIds(ids).then(res => {
this.filesList = res.data
})
}
}
}
</script>
<style lang='less' scoped>
@themeColor: #409eff;
.file {
width: 100%;
height: 100%;
&-view {
width: 100%;
&-item {
width: 100%;
height: 100%;
display: flex;
align-items: center;
box-sizing: border-box;
&:not(:last-child) {
margin-bottom: 3px;
}
&-icon {
width: 20px;
height: 20px;
object-fit: cover;
cursor: pointer;
}
&-info {
font-family: "Arial Negreta", "Arial Normal", "Arial", sans-serif;
font-size: 14px;
text-align: left;
margin-left: 5px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
&-infoHover {
color: @themeColor;
&:hover {
text-decoration: underline;
}
}
}
}
}
.mr-5 {
margin-left: 5px;
}
.not-file {
font-family: "Arial Negreta", "Arial Normal", "Arial", sans-serif;
font-size: 14px;
}
</style>
文件预览为ofd时走ofd预览,否则走正常的预览文件接口
previewFile(files) {
if ('ofd' === files.fileSuffix) {
const routeData = this.$router.resolve({
path: '/ofd/preview',
query: {
id: files.fileId
}
});
window.open(routeData.href, "_blank");
} else {
const url = getPreviewFileUrl(files.fileId)
this.$refs.myA.target(url)
}
},
ofd文件预览组件
<template>
<div class="main-section" id="content" ref="contentDiv" @mousewheel="scrool"></div>
</template>
<script>
import {parseOfdDocument, renderOfd, digestCheck, getPageScale} from '@/utils/ofd/ofd';
import {getPreviewFileUrl} from "@/api/system/files";
import axios from 'axios';
export default {
name: 'preview',
data() {
return {
docleft: 0,//公章距离左侧文档边缘的距离
leftMenu_width: 0,//左侧菜单宽度
ofdBase64: null,
loading: false,
pageIndex: 1,
pageCount: 0,
scale: 0,
ofdObj: null,
screenWidth: document.body.clientWidth,
}
},
mounted() {
this.screenWidth = document.body.clientWidth - this.leftMenu_width;
this.$refs.contentDiv.addEventListener('scroll', this.scrool);
this.getOfd(this.$route.query.id)
},
methods: {
getOfd(id) {
axios({
url: getPreviewFileUrl(id),
responseType: 'blob'
}).then(res => {
const files = new window.File([res.data], "ofd", {type: 'application/ofd'});
this.getOfdDocumentObj(files, this.screenWidth);
})
},
scrool() {
let scrolled = this.$refs.contentDiv.firstElementChild?.getBoundingClientRect()?.top - 60;
let top = 0
let index = 0;
for (let i = 0; i < this.$refs.contentDiv.childElementCount; i++) {
top += (Math.abs(this.$refs.contentDiv.children.item(i)?.style.height.replace('px', '')) + Math.abs(this.$refs.contentDiv.children.item(i)?.style.marginBottom.replace('px', '')));
if (Math.abs(scrolled) < top) {
index = i;
break;
}
}
this.pageIndex = index + 1;
},
getOfdDocumentObj(file, screenWidth) {
let that = this;
this.loading = true;
parseOfdDocument({
ofd: file,
success(res) {
that.ofdObj = res[0];
that.pageCount = res[0].pages.length;
const divs = renderOfd(screenWidth, res[0]);
that.displayOfdDiv(divs);
that.loading = false;
},
fail(error) {
that.loading = false;
that.$alert('OFD打开失败', error, {
confirmButtonText: '确定',
callback: action => {
this.$message({
type: 'info',
message: `action: ${action}`
});
}
});
}
});
},
displayOfdDiv(divs) {
this.scale = getPageScale();
let contentDiv = document.getElementById('content');
contentDiv.innerHTML = '';
for (const div of divs) {
contentDiv.appendChild(div)
}
for (let ele of document.getElementsByName('seal_img_div')) {
this.addEventOnSealDiv(ele, JSON.parse(ele.dataset.sesSignature), JSON.parse(ele.dataset.signedInfo));
}
},
addEventOnSealDiv(div, SES_Signature, signedInfo) {
try {
global.HashRet = null;
global.VerifyRet = signedInfo.VerifyRet;
div.addEventListener("click", function () {
document.getElementById('sealInfoDiv').hidden = false;
document.getElementById('sealInfoDiv').setAttribute('style', 'display:flex;align-items: center;justify-content: center;');
if (SES_Signature.realVersion < 4) {
document.getElementById('spSigner').innerText = SES_Signature.toSign.cert['commonName'];
document.getElementById('spProvider').innerText = signedInfo.Provider['@_ProviderName'];
document.getElementById('spHashedValue').innerText = SES_Signature.toSign.dataHash.replace(/\n/g, '');
document.getElementById('spSignedValue').innerText = SES_Signature.signature.replace(/\n/g, '');
document.getElementById('spSignMethod').innerText = SES_Signature.toSign.signatureAlgorithm.replace(/\n/g, '');
document.getElementById('spSealID').innerText = SES_Signature.toSign.eseal.esealInfo.esID;
document.getElementById('spSealName').innerText = SES_Signature.toSign.eseal.esealInfo.property.name;
document.getElementById('spSealType').innerText = SES_Signature.toSign.eseal.esealInfo.property.type;
document.getElementById('spSealAuthTime').innerText = "从 " + SES_Signature.toSign.eseal.esealInfo.property.validStart + " 到 " + SES_Signature.toSign.eseal.esealInfo.property.validEnd;
document.getElementById('spSealMakeTime').innerText = SES_Signature.toSign.eseal.esealInfo.property.createDate;
document.getElementById('spSealVersion').innerText = SES_Signature.toSign.eseal.esealInfo.header.version;
} else {
document.getElementById('spSigner').innerText = SES_Signature.cert['commonName'];
document.getElementById('spProvider').innerText = signedInfo.Provider['@_ProviderName'];
document.getElementById('spHashedValue').innerText = SES_Signature.toSign.dataHash.replace(/\n/g, '');
document.getElementById('spSignedValue').innerText = SES_Signature.signature.replace(/\n/g, '');
document.getElementById('spSignMethod').innerText = SES_Signature.signatureAlgID.replace(/\n/g, '');
document.getElementById('spSealID').innerText = SES_Signature.toSign.eseal.esealInfo.esID;
document.getElementById('spSealName').innerText = SES_Signature.toSign.eseal.esealInfo.property.name;
document.getElementById('spSealType').innerText = SES_Signature.toSign.eseal.esealInfo.property.type;
document.getElementById('spSealAuthTime').innerText = "从 " + SES_Signature.toSign.eseal.esealInfo.property.validStart + " 到 " + SES_Signature.toSign.eseal.esealInfo.property.validEnd;
document.getElementById('spSealMakeTime').innerText = SES_Signature.toSign.eseal.esealInfo.property.createDate;
document.getElementById('spSealVersion').innerText = SES_Signature.toSign.eseal.esealInfo.header.version;
}
document.getElementById('spVersion').innerText = SES_Signature.toSign.version;
document.getElementById('VerifyRet').innerText = "文件摘要值后台验证中,请稍等... " + (global.VerifyRet ? "签名值验证成功" : "签名值验证失败");
if (global.HashRet == null || global.HashRet == undefined || Object.keys(global.HashRet).length <= 0) {
setTimeout(function () {
const signRetStr = global.VerifyRet ? "签名值验证成功" : "签名值验证失败";
global.HashRet = digestCheck(global.toBeChecked.get(signedInfo.signatureID));
const hashRetStr = global.HashRet ? "文件摘要值验证成功" : "文件摘要值验证失败";
document.getElementById('VerifyRet').innerText = hashRetStr + " " + signRetStr;
}, 1000);
}
});
} catch (e) {
console.log(e);
}
if (!global.VerifyRet) {
div.setAttribute('class', 'gray');
}
}
}
}
</script>
<style scoped>
.main-section {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
margin: 10px auto 0;
border: 1px solid #f7f7f7;
box-shadow: 0 3px 10px 0 rgba(76, 101, 123, 0.12);
}
</style>
将文件引入到src下
资源在笔记里面找一下