ofd文件预览
文件列表
<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 = falseif (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 = 0let 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下
资源在笔记里面找一下
相关文章:
ofd文件预览
文件列表 <template><div><div classfile v-if$myUtils.coll.isNotEmpty(filesList)><div classfile-view><div classfile-view-item :style{justifyContent: align } v-for(item, index) in filesList :keyindex><img classfile-view-item-…...
浅浅了解下Spring中生命周期函数(Spring6全攻略)
你好,这里是codetrend专栏“Spring6全攻略”。 Spring框架设计生命周期回调函数的主要目的是为了提供一种机制,使开发人员能够在对象创建、初始化和销毁等生命周期阶段执行特定的操作。这种机制可以帮助开发人员编写更加灵活和可维护的代码。 举个例子…...
建议收藏!亚马逊卖家必须知道的37个常用术语解释
运营亚马逊,经常会看到很多个专业术语,想必大部分新手卖家都比较陌生,熟悉这些常用术语的含义有助于你更好地运营亚马逊。下面为各位整理了37个在亚马逊跨境电商中常见的术语及其解释,建议收藏! 1、SKU Stock Keeping…...
黑苹果睡眠总是自动唤醒(RTC)
黑苹果睡眠总是自动唤醒【RTC】 1. 问题2. 解决方案2.1. 查看重启日志2.2. 配置Disable RTC wake scheduling补丁 3. 后续4. 参考 1. 问题 黑苹果EFI 更换后,总是在手动 睡眠后,间歇性重启,然后再次睡眠,然后再重启。原因归结为&…...
【代码随想录训练营】【Day 49+】【动态规划-8】| Leetcode 121, 122, 123
【代码随想录训练营】【Day 49】【动态规划-8】| Leetcode 121, 122, 123 需强化知识点 买卖股票系列 题目 121. 买卖股票的最佳时机 动态规划贪心:记录左侧的最小值 class Solution:def maxProfit(self, prices: List[int]) -> int:# n len(prices)# # 0…...
k8s metrics-server服务监控pod 的 cpu、内存
项目场景: 需要开启指标服务,依据pod 的 cpu、内存使用率进行自动的扩容或缩容 pod 的数量 解决方案: 下载 metrics-server 组件配置文件: wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/…...
电脑自带录屏在哪?电脑录屏,4个详细方法
在现代社会中,越来越多的人需要在电脑上录制视频,比如录制游戏操作、制作教学视频、演示文稿等等。因此,电脑录屏成为了一项非常重要的功能。那么电脑自带录屏在哪?本文将带领大家看看可以使用哪些方法进行录屏。 录屏方法一&…...
[Cloud Networking] Layer3 (Continue)
文章目录 1. DHCP Protocol1.1 DHCP 三种分配方式1.2 DHCP Relay (中继) 2. 路由协议 (Routing Protocol)2.1 RIP (Routing Information Protocol)2.2 OSPF Protocol2.2.1 OSPF Area2.2.2 Route ID / DR / BDR2.2.3 LSA / OSPF 邻居表 / LSDB / OSPF路由表 2.3 BGP Protocol2.4…...
missing authentication credentials for REST request
1、报错截图 2、解决办法 将elasticsearch的elasticsearch.yml的 xpack.security.enabled: true 改为 xpack.security.enabled: false...
Unity 从0开始编写一个技能编辑器_02_Buff系统的生命周期
工作也有一年了,对技能编辑器也有了一些自己的看法,从刚接触时的惊讶,到大量工作时觉得有一些设计的冗余,在到特殊需求的修改,运行效率低时的优化,技能编辑器在我眼中已经不再是神圣不可攀的存在的…...
计算机网络简答题
第一章 计算机网络 1.因特网是一个世界范围的计算机网络,记一个互联了遍及全世界的计算机设备的网络。 2.计算机网络将众多分散的、自治的(一台坏了不影响其他)计算机系统,通过通信设备与线路连接起来,由功能完善的软件实现资源共享和信息传递的系统。 3.计算机网络的组…...
探索Java 8 Stream API:现代数据处理的新纪元
Stream流 Stream初探:何方神圣? Stream流是一种处理集合数据的高效工具,它可以让你以声明性的方式处理数据集合。Stream不是存储数据的数据结构,而是对数据源(如集合、数组)的运算操作概念,支…...
vim 删除光标到最后一行的所有内容
在 Vim 中删除从光标所在位置到文件末尾的所有内容 删除从光标所在位置到文件末尾的所有内容使用 dG 命令 参考 删除从光标所在位置到文件末尾的所有内容 使用 dG 命令 确保你在正常模式下(按 Esc 键)。移动光标到你想要开始删除的位置。输入以下命令&…...
k8s之kubelet证书时间过期升级
1.查看当前证书时间 # kubeadm alpha certs renew kubelet Kubeadm experimental sub-commands kubeadm是一个用于引导Kubernetes集群的工具,它提供了许多命令和子命令来管理集群的一生周期。过去,某些功能被标记为实验性的,并通过kubeadm a…...
5G消息 x 文旅 | 一站式智慧文旅解决方案
5G消息 x 文旅 | 一站式智慧文旅解决方案 文旅 x 5G 消息将进一步强化资源整合,满足游客服务需求、企业营销需求、政府管理需求,推进文化旅游项目的智慧化、数字化,增强传播力、竞争力和可持续性。5G 消息的“原生入口”、“超强呈现”、“智…...
如何评估员工在新版FMEA培训后应用知识的效果?
随着制造业的快速发展,新版FMEA已成为企业提升产品质量、减少故障风险的关键一环。然而,培训只是第一步,如何有效评估员工在新版FMEA培训后应用知识的效果,才是确保培训成果转化的关键所在。 评估员工知识应用效果的首要步骤是制定…...
python脚本之解析命令参数
import requests import argparseprint(f"{__name__}:start")parser argparse.ArgumentParser(description使用方法) parser.add_argument(-p, --prefix, typestr, help域名) parser.add_argument(-t, --token, typestr, helptoken) parser.add_argument(-i, --queu…...
当JS遇上NLP:开启图片分析的奇幻之旅
前言 在当今科技飞速发展的时代,JavaScript(JS)作为广泛应用的编程语言,展现出了强大的活力与无限的可能性。与此同时,自然语言处理(NLP)领域也正在经历着深刻的变革与进步。 当这两者碰撞在一…...
trpc快速上手
tRPC (Type-safe Remote Procedure Call) 是一个用于构建类型安全的 API 的框架,它能够在前端和后端之间共享类型,确保类型安全性。这对于使用 TypeScript 的项目特别有用,因为它消除了前后端类型不一致的问题,提高了开发效率和代…...
知识图谱存在的挑战---隐私、安全和伦理相关和测试认证相关
文章目录 隐私、安全和伦理相关测试认证相关 隐私、安全和伦理相关 从部署拓扑结构而言,知识图谱技术以数据为核心、数据库为载体的方式来存储,有单机、云平台、集群及其组合的部署方式,结合大数据平台、云平台、业务系统、灾备、网络系统及其…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇
根据 QYResearch 发布的市场报告显示,全球市场规模预计在 2031 年达到 9848 万美元,2025 - 2031 年期间年复合增长率(CAGR)为 3.7%。在竞争格局上,市场集中度较高,2024 年全球前十强厂商占据约 74.0% 的市场…...
文件上传漏洞防御全攻略
要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...
Java并发编程实战 Day 11:并发设计模式
【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...
