From 3509e721364f8cecd4d12e666c858e6910ac130a Mon Sep 17 00:00:00 2001 From: xuhuajiao <13476289682@163.com> Date: Fri, 22 Mar 2024 17:12:49 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A2=84=E8=A7=88/pdf=E5=BD=92=E6=A1=A3?= =?UTF-8?q?=E7=AB=A0=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/waterMark.js | 10 +- src/vendors/ofd/OfdView.vue | 8 - src/vendors/pdf/PdfView.vue | 254 ++++++++++++------ .../module/archivesInfo/index.vue | 1 + .../module/uploadFile/index.vue | 22 +- .../module/archivesInfo/index.vue | 1 - .../module/uploadFile/index.vue | 2 +- src/views/preview/index.vue | 88 +++--- 8 files changed, 249 insertions(+), 137 deletions(-) diff --git a/src/utils/waterMark.js b/src/utils/waterMark.js index 279eb86..30cb5cd 100644 --- a/src/utils/waterMark.js +++ b/src/utils/waterMark.js @@ -5,15 +5,15 @@ export const watermark = (settings, className, type) => { watermark_txt: settings.watermark_txt, watermark_x: 20, // 水印起始位置x轴坐标 watermark_y: 10, // 水印起始位置Y轴坐标 - watermark_rows: 6, // 水印行数 + watermark_rows: 10, // 水印行数 watermark_cols: 10, // 水印列数 - watermark_x_space: 100, // 水印x轴间隔 - watermark_y_space: 140, // 水印y轴间隔 + watermark_x_space: 50, // 水印x轴间隔 + watermark_y_space: 100, // 水印y轴间隔 watermark_color: settings.watermark_color, // 水印字体颜色 watermark_alpha: settings.watermark_alpha, // 水印透明度 watermark_fontsize: settings.watermark_fontsize || '15px', // 水印字体大小 watermark_font: '微软雅黑', // 水印字体 - watermark_width: 200, // 水印宽度 + watermark_width: 130, // 水印宽度 watermark_height: 40, // 水印长度 watermark_angle: 15, // 水印倾斜度数 watermark_position: settings.watermark_position || 'absolute' @@ -88,7 +88,7 @@ export const watermark = (settings, className, type) => { const cxt = canvas.getContext('2d') const divImg = document.createElement('div') - const imgScale = 0.4 + const imgScale = 0.1 // canvas.width = 200 var mask_div = document.createElement('div') diff --git a/src/vendors/ofd/OfdView.vue b/src/vendors/ofd/OfdView.vue index f008646..b2f4617 100644 --- a/src/vendors/ofd/OfdView.vue +++ b/src/vendors/ofd/OfdView.vue @@ -113,11 +113,7 @@ export default { // console.log("width: " + width + "height:" + height); that.domWidth = width - 500 }) - console.log('------------------') - console.log('ofd', this.dataOfd) - console.log('ofd2', this.ofdFile) this.viewOfd(this.dataOfd, this.domWidth) - console.log('------------------') }, methods: { // 鼠标滚动 @@ -335,14 +331,10 @@ export default { // 渲染ofd viewOfd(file, screenWidth) { import('./ofd.js').then(({ parseOfdDocument, renderOfd, getPageScale }) => { - console.log(parseOfdDocument) - console.log(renderOfd) - console.log(getPageScale) const that = this parseOfdDocument({ ofd: file, success(res) { - console.log('res', res) that.ofdObj = res[0] that.pageCount = res[0].pages.length const contentDiv = document.getElementById('ofdContainer') diff --git a/src/vendors/pdf/PdfView.vue b/src/vendors/pdf/PdfView.vue index d3339f8..45a782b 100644 --- a/src/vendors/pdf/PdfView.vue +++ b/src/vendors/pdf/PdfView.vue @@ -28,6 +28,8 @@ import { TextLayerBuilder, EventBus } from 'pdfdist-mergeofd/web/pdf_viewer' import 'pdfdist-mergeofd/web/pdf_viewer.css' PDFJS.GlobalWorkerOptions.workerSrc = require('pdfdist-mergeofd/build/pdf.worker.entry.js') import { saveByteArray } from '@/utils/index' +import { getInitWatermark } from '@/api/system/waterMask' +import { FetchGetFilingsealFormat, FetchGetFilingsealFormatDtails } from '@/api/system/category/category' import fontkit from '@pdf-lib/fontkit' export default { @@ -46,10 +48,21 @@ export default { arr: [ { zongshu: '001', yilei: '2015', erlei: '2' }, { zongshu: '', yilei: '长期', erlei: '1' } - ] + ], + watermarkInfo: null, + initColor: null, + fileParentInfo: null, + selectedCategory:null, + formatData:[] } }, mounted() { + if (localStorage.getItem('fileParentInfo')) { + this.fileParentInfo = JSON.parse(localStorage.getItem('fileParentInfo')) + } + if (localStorage.getItem('currentArchivesKey')) { + this.selectedCategory = JSON.parse(localStorage.getItem('currentArchivesKey')) + } this.loadFile() }, methods: { @@ -94,94 +107,117 @@ export default { pdfDoc.registerFontkit(fontkit) // 自定义字体挂载、fontkit为自定义字体注册工具 const customFont = await pdfDoc.embedFont(fontBytes) const pages = pdfDoc.getPages() - console.log('pages',pages) // let canvas = document.createElement('canvas') // const png = canvas.toDataURL('img/png') // const imagePDF = await pdfDoc.embedPng(png) + await getInitWatermark().then((res) => { + this.watermarkInfo = res + if (res.watermarkType === '1') { + // 图片水印 + let dom = document.getElementsByClassName('page') + let canvas = document.createElement('canvas') + let cxt = canvas.getContext('2d') + let divImg = document.createElement('div') - // 水印 - const drawTextParams = { - lineHeight: 50, - font: customFont, - size: 16, - color: rgb(0.08, 0.08, 0.2), - rotate: degrees(15), - opacity: 0.8 - } - - for (let index = 0; index < pages.length; index++) { - const currentPage = pages[index] - // 获取当前页宽高 - const { width, height } = currentPage.getSize() - // 要渲染的文字内容 - for (let ix = 10; ix < width; ix += 300) { // 水印横向间隔 - let lineNum = 0 - for (let iy = 50; iy <= height; iy += 200) { // 水印纵向间隔 - lineNum++ - currentPage.drawText('徐华姣' + this.formateTime(), { - x: lineNum & 1 ? ix : ix + 60, - y: iy, - ...drawTextParams - }) + let imgScale = 0.1 + //创建新的图片对象 + let img = new Image(); + //指定图片的URL + img.src = this.watermarkInfo.context; + let _this = this; + //浏览器加载图片完毕后再绘制图片 + img.onload = function() { + //cxt.drawImage(img,0,0); + cxt.rotate(-20 * Math.PI / 180) + let whScale = img.width / img.height + cxt.clearRect(0, 0, canvas.width, canvas.height); + cxt.drawImage(img, //规定要使用的图像、画布或视频。 + 0, 0, //开始剪切的 x 坐标位置。 + img.width, img.height, //被剪切图像的高度。 + 0, 50,//在画布上放置图像的 x 、y坐标位置。 + img.width * imgScale, img.height * imgScale //要使用的图像的宽度、高度 + ) + + divImg.style.opacity = parseFloat(_this.watermarkInfo.transparency) / 100 + divImg.style.background = 'url(' + canvas.toDataURL('image/png') + ') left top repeat' + _this.drawImage2(divImg,dom) } - } - } + } else if (res.watermarkType === '0') { + const rgbaValue = this.watermarkInfo.transparency; + const startIndex = rgbaValue.indexOf('('); // 找到第一个括号的位置 + const endIndex = rgbaValue.lastIndexOf(','); // 找到透明度部分的位置 + const rgbPart = 'rgb' + rgbaValue.slice(startIndex, endIndex) + ')'; // 提取 RGB 部分 + this.initOpacity = rgbaValue.slice(endIndex + 1, -1); // 提取透明度部分 - // 图片水印 - // let dom = document.getElementsByClassName('page') - // let canvas = document.createElement('canvas') - // let cxt = canvas.getContext('2d') - // let divImg = document.createElement('div') + const rgbValues = rgbPart.slice(4, -1).split(', ').map(value => { + const color = Number(value) / 255; + return color === 1 || color === 0 ? parseInt(color.toFixed(0)) : parseFloat(color.toFixed(2)); + }); + // const color = `rgb(${rgbValues.join(', ')})`; + this.initColor = { + red: rgbValues[0], + green: rgbValues[1], + blue: rgbValues[2], + type: "RGB" + } - // let imgScale = 0.3 - // //创建新的图片对象 - // let img = new Image(); - // //指定图片的URL - // img.src = this.logo; - // //浏览器加载图片完毕后再绘制图片 - // img.onload = function() { - // //cxt.drawImage(img,0,0); - // cxt.rotate(-20 * Math.PI / 180) - // let whScale = img.width / img.height - // cxt.clearRect(0, 0, canvas.width, canvas.height); - // cxt.drawImage(img, //规定要使用的图像、画布或视频。 - // 0, 0, //开始剪切的 x 坐标位置。 - // img.width, img.height, //被剪切图像的高度。 - // 0, 50,//在画布上放置图像的 x 、y坐标位置。 - // img.width * imgScale, img.height * imgScale //要使用的图像的宽度、高度 - // ) - // divImg.style.opacity = 0.3 - // divImg.style.background = 'url(' + canvas.toDataURL('image/png') + ') left top repeat' - // drawImage2(divImg,dom) - // } + const drawTextParams = { + lineHeight: 50, + font: customFont, + size: parseInt(this.watermarkInfo.watermarkFont), + color: this.initColor, + rotate: degrees(15), + opacity: parseFloat(this.initOpacity) + } - // function drawImage2 (div,dom) { - // div.style.pointerEvents = 'none' - // div.className = 'weterbox' - // div.style.top = 0 - // div.style.left = 0 - // div.style.position = 'absolute' - // div.style.zIndex = '100000' - // div.style.width = '100%' - // div.style.height = '100%' - // if( dom.length > 0){ - // for(let i = 0; i< dom.length;i++){ - // let child = dom[i].getElementsByClassName('weterbox') - // if(child.length > 0){ - // dom[i].removeChild(child[0]) - // } - // dom[i].appendChild(div.cloneNode(true)) - // } - // } - // } + for (let index = 0; index < pages.length; index++) { + const currentPage = pages[index] + // 获取当前页宽高 + const { width, height } = currentPage.getSize() + // 要渲染的文字内容 + for (let ix = 10; ix < width; ix += 300) { // 水印横向间隔 + let lineNum = 0 + for (let iy = 50; iy <= height; iy += 200) { // 水印纵向间隔 + lineNum++ + currentPage.drawText(this.watermarkInfo.context, { + x: lineNum & 1 ? ix : ix + 60, + y: iy, + ...drawTextParams + }) + } + } + } + } + }).catch(err => { + console.log(err) + }) const pdfBytes = await pdfDoc.save() this.pdfDoc = await PDFJS.getDocument(pdfBytes).promise this.pdf_pages = this.pdfDoc.numPages this.$nextTick(() => this.renderPagePdf()) }, + drawImage2 (div,dom) { + div.style.pointerEvents = 'none' + div.className = 'weterbox' + div.style.top = 0 + div.style.left = 0 + div.style.position = 'absolute' + div.style.zIndex = '100000' + div.style.width = '100%' + div.style.height = '100%' + if( dom.length > 0){ + for(let i = 0; i< dom.length;i++){ + let child = dom[i].getElementsByClassName('weterbox') + if(child.length > 0){ + dom[i].removeChild(child[0]) + } + dom[i].appendChild(div.cloneNode(true)) + } + } + }, async renderPagePdf(num = 1) { this.currentPage = num const page = await this.pdfDoc.getPage(num) @@ -228,7 +264,6 @@ export default { viewport: viewport, eventBus: eventBus }) - textLayer.setTextContent(textContent) textLayer.render() }) @@ -238,7 +273,68 @@ export default { return this.renderPagePdf(num + 1) }) } - chapter(this.arr) + + // 归档章数据获取操作 + this.getFilingsealFormat() + }, + getFilingsealFormat() { + FetchGetFilingsealFormat().then((res) => { + this.formatOptions = res + if (this.selectedCategory.filingId) { + res.map(item => { + if (item.id === this.selectedCategory.filingId) { + this.filingName = item.name + this.changeFormat(this.selectedCategory.filingId) + } + }) + } + }).catch(err => { + console.log(err) + }) + }, + changeFormat(value) { + this.formatData = [] + if (value) { + FetchGetFilingsealFormatDtails(value).then((res) => { + this.formatData = res.sort((a, b) => { + if (a.row === b.row) { + return a.line - b.line // 如果 row 相同,则按 line 升序排序 + } else { + return a.row - b.row // 否则,按 row 升序排序 + } + }) + + + for (let i = 0; i < this.formatData.length; i++) { + for (let j = 0; j < this.fileParentInfo.length; j++) { + if (this.formatData[i].fieldName === this.fileParentInfo[j].fieldName) { + this.formatData[i].context = this.fileParentInfo[j].context + } + } + } + + const chunkSize = 3; + const chapterArray = []; + + for (let i = 0; i < this.formatData.length; i += chunkSize) { + // const chunk = this.formatData.slice(i, i + chunkSize); + // const obj = {}; + // chunk.forEach(item => { + // obj[item.fieldName] = item.context; + // }); + const obj = { + zongshu: this.formatData[i].context || '', + yilei: this.formatData[i + 1].context || '', + erlei: this.formatData[i + 2].context || '' + }; + chapterArray.push(obj); + } + chapter(chapterArray) + + }).catch(err => { + console.log(err) + }) + } }, // , // nextPage() { @@ -275,14 +371,14 @@ export default { const { width, height } = noPage.getSize() for (let i = 0; i < 10; i++) { for (let j = 0; j < 3; j++) { - noPage.drawText('张三-2023-01-01', { + noPage.drawText(this.watermarkInfo.context, { x: 230 * j, y: (height / 4) * i, font: fontkitFile, - size: 16, - color: rgb(0.46, 0.53, 0.6), + size: parseInt(this.watermarkInfo.watermarkFont), + color: this.initColor, rotate: degrees(45), - opacity: 0.3 + opacity: parseFloat(this.initOpacity) }) } } diff --git a/src/views/archivesManage/managementLibrary/module/archivesInfo/index.vue b/src/views/archivesManage/managementLibrary/module/archivesInfo/index.vue index 60367eb..112f88e 100644 --- a/src/views/archivesManage/managementLibrary/module/archivesInfo/index.vue +++ b/src/views/archivesManage/managementLibrary/module/archivesInfo/index.vue @@ -166,6 +166,7 @@ export default { this.$nextTick(() => { if (this.$refs.uploadFile) { this.getIsAuthByLookType() + this.$refs.uploadFile.parentInfo = this.archivesDetailsData this.$refs.uploadFile.tableData = [] this.$refs.uploadFile.getFileList() } diff --git a/src/views/archivesManage/managementLibrary/module/uploadFile/index.vue b/src/views/archivesManage/managementLibrary/module/uploadFile/index.vue index b69a381..a3c5fdb 100644 --- a/src/views/archivesManage/managementLibrary/module/uploadFile/index.vue +++ b/src/views/archivesManage/managementLibrary/module/uploadFile/index.vue @@ -51,13 +51,11 @@ - - + @@ -104,7 +102,8 @@ export default { 'print': false, 'endTime': null, 'startTime': null - } + }, + parentInfo: null } }, computed: { @@ -117,9 +116,16 @@ export default { } }, methods: { - toPreview() { - const routeData = this.$router.resolve({ path: '/preview' }) + toPreview(row) { + const routeData = this.$router.resolve({ + path: '/preview', + query: { + 'archiveNo': this.parentInfo.find(item => item.fieldName === 'archive_no').context + }}) window.open(routeData.href, '_blank') + localStorage.setItem('fileParentInfo', JSON.stringify(this.parentInfo)) + localStorage.setItem('fileTables', JSON.stringify(this.tableData)) + localStorage.setItem('fileCurrent', JSON.stringify(row)) }, getFileSize(fileSize) { const fileSizeInKB = (fileSize / 1024).toFixed(2) + 'kB' diff --git a/src/views/collectReorganizi/collectionLibrary/module/archivesInfo/index.vue b/src/views/collectReorganizi/collectionLibrary/module/archivesInfo/index.vue index eeaa0db..5c381d1 100644 --- a/src/views/collectReorganizi/collectionLibrary/module/archivesInfo/index.vue +++ b/src/views/collectReorganizi/collectionLibrary/module/archivesInfo/index.vue @@ -154,7 +154,6 @@ export default { } this.$nextTick(() => { if (this.$refs.uploadFile) { - console.log(this.archivesDetailsData) this.$refs.uploadFile.parentInfo = this.archivesDetailsData this.$refs.uploadFile.tableData = [] this.$refs.uploadFile.getFileList() diff --git a/src/views/collectReorganizi/collectionLibrary/module/uploadFile/index.vue b/src/views/collectReorganizi/collectionLibrary/module/uploadFile/index.vue index 506be98..d633ffa 100644 --- a/src/views/collectReorganizi/collectionLibrary/module/uploadFile/index.vue +++ b/src/views/collectReorganizi/collectionLibrary/module/uploadFile/index.vue @@ -266,7 +266,6 @@ export default { }, // 上传list getFileList() { - console.log('parentInfo', this.parentInfo) const params = { 'categoryId': this.selectedCategory.id, 'archivesId': this.arcId, @@ -284,6 +283,7 @@ export default { 'archiveNo': this.parentInfo.find(item => item.fieldName === 'archive_no').context }}) window.open(routeData.href, '_blank') + localStorage.setItem('fileParentInfo', JSON.stringify(this.parentInfo)) localStorage.setItem('fileTables', JSON.stringify(this.tableData)) localStorage.setItem('fileCurrent', JSON.stringify(row)) }, diff --git a/src/views/preview/index.vue b/src/views/preview/index.vue index 70436c5..49d2e27 100644 --- a/src/views/preview/index.vue +++ b/src/views/preview/index.vue @@ -47,6 +47,7 @@ import { FetchBase64ByFileId } from '@/api/archivesManage/library' import { getExtend, readBuffer, render } from '@/components/util' import { parse } from 'qs' import { watermark } from '@/utils/waterMark' +import { getInitWatermark } from '@/api/system/waterMask' import html2canvas from 'html2canvas' // 转图片打印需要先安装html2Canvas和print-js import printJS from 'print-js' @@ -98,7 +99,8 @@ export default { parentArchiveNo: null, allFileTables: [], toFile: null, - fileCurrent: null + fileCurrent: null, + fileParentInfo: null } }, created() { @@ -120,6 +122,10 @@ export default { if (this.$route.query.archiveNo) { this.parentArchiveNo = this.$route.query.archiveNo } + if (localStorage.getItem('fileParentInfo')) { + this.fileParentInfo = JSON.parse(localStorage.getItem('fileTables')) + } + if (localStorage.getItem('fileTables')) { this.allFileTables = JSON.parse(localStorage.getItem('fileTables')) } @@ -127,26 +133,23 @@ export default { if (localStorage.getItem('fileCurrent')) { this.fileCurrent = JSON.parse(localStorage.getItem('fileCurrent')) } - console.log('this.fileCurrent', this.fileCurrent) - this.get() + this.getBase64ByFileId() }, methods: { selectFile(item) { this.fileCurrent = item - this.get() + this.getBase64ByFileId() }, - get() { + getBase64ByFileId() { this.loading = true const params = { 'fileId': this.fileCurrent ? this.fileCurrent.id : this.allFileTables[0].id } FetchBase64ByFileId(params).then(res => { - console.log('fffff', res) var base64String = res var fileName = this.fileCurrent && this.fileCurrent.file_name var mimeType = this.fileCurrent && this.fileCurrent.file_type this.toFile = this.base64ToFile(base64String, fileName, mimeType) - console.log(this.toFile) if (this.toFile) { this.handleChange() } @@ -182,7 +185,40 @@ export default { type: 'image', documentTitle: '打印图片' }) - console.log(url) + }) + }, + getWatermark() { + getInitWatermark().then((res) => { + this.watermarkInfo = res + // this.isEnable = this.watermarkInfo.isEnable + + if (res.watermarkType === '1') { + watermark({ + watermark_txt: this.watermarkInfo.context, + watermark_alpha: parseFloat(this.watermarkInfo.transparency) / 100 + }, 'water-mask', 'img') + } else if (res.watermarkType === '0') { + // if (parent.length > 0) { + // for (let i = 0; i < parent.length; i++) { + // const childImg = parent[i].getElementsByClassName('weterbox') + // if (childImg.length > 0) { + // for (let i = 0; i < childImg.length; i++) { + // parent[i].removeChild(childImg[i]) + // } + // } + // } + // } + watermark({ + watermark_txt: this.watermarkInfo.context, + watermark_color: this.watermarkInfo.transparency, + watermark_fontsize: this.watermarkInfo.watermarkFont + 'px' + }, 'water-mask', 'text') + } + if (document.getElementById('error-tip')) { + document.getElementsByClassName('water-mask')[0].innerHTML = '' + } + }).catch(err => { + console.log(err) }) }, async handleChange(e) { @@ -192,10 +228,8 @@ export default { // console.log('file', file) const fileReader = new FileReader() fileReader.readAsArrayBuffer(this.toFile) - console.log('fileReader', fileReader) fileReader.onload = () => { this.src = fileReader.result - console.log('fileReader22', fileReader.result) } const arrayBuffer = await readBuffer(this.toFile) @@ -203,13 +237,10 @@ export default { this.$nextTick(() => { // 取得扩展名 const extend = getExtend(this.toFile.name) - console.log('extend', extend) // 加水印 const maskDiv = document.getElementsByClassName('mask_div') const imgMaskDiv = document.getElementsByClassName('weterbox') - console.log(document.getElementById('error-tip')) - if (imgMaskDiv.length === 1) { document.getElementsByClassName('water-mask')[0].removeChild(imgMaskDiv[0]) } @@ -218,27 +249,8 @@ export default { document.getElementsByClassName('water-mask')[0].removeChild(maskDiv[j]) } - this.watermarkInfo = { - 'id': '9C5384EE889C0A977FC8F6', - 'watermarkType': '0', - 'watermarkFont': '30', - 'transparency': 'rgba(255, 69, 0, 0.45)', - 'context': '安全水印', - 'isEnable': true - } - if (!extend.includes('pdf')) { - // watermark({ watermark_txt: '徐华姣' + timeFormate() }, 'water-mask', 'text') - // watermark({ watermark_txt: this.logo }, 'water-mask', 'img') - watermark({ - watermark_txt: this.watermarkInfo.context, - watermark_color: this.watermarkInfo.transparency, - watermark_fontsize: this.watermarkInfo.watermarkFont + 'px' - }, 'water-mask', 'text') - } - - if (document.getElementById('error-tip')) { - document.getElementsByClassName('water-mask')[0].innerHTML = '' + this.getWatermark() } }) } catch (e) { @@ -371,14 +383,15 @@ export default { .file-list{ height: calc(100% - 48px); padding: 10px 0; - font-size: 14px; + font-size: 12px; overflow: hidden; overflow-y: scroll; li{ display: flex; justify-content: space-between; padding: 0 10px 0 20px; - line-height: 34px; + line-height: 26px; + margin-bottom: 4px; cursor:default; &.active-file{ background-color: #e8f2ff; @@ -426,4 +439,9 @@ export default { max-width: 1000px; margin: 0 auto; } +.el-loading-mask{ + position: fixed; + left: 300px; + top: 75px; +}