| | |
| | | <template> |
| | | <div> |
| | | <div v-loading="pdfLoading"> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | width="80%" |
| | | width="50%" |
| | | title="签名归档" |
| | | :before-close="handleClose" |
| | | :close-on-press-escape="false" |
| | |
| | | <!-- 背景文件切换按钮 --> |
| | | <div class="top"> |
| | | <div class="top-left"> |
| | | <div>签名列表</div> |
| | | <h3>签名列表</h3> |
| | | <img |
| | | style="width: 100px; height: auto" |
| | | v-for="(image, index) in signatureImages" |
| | | :src="image" |
| | | :key="index" |
| | |
| | | /> |
| | | </div> |
| | | <div v-if="pageNum>1"> |
| | | <span style="margin-right: 15px">{{currentBackgroundIndex + 1}}/{{pageNum}}</span> |
| | | <el-button icon="arrow-left" @click="prevBackground">上一页</el-button> |
| | | <el-button icon="arrow-right" @click="nextBackground">上一页</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 已放置的签名 --> |
| | | <div class="bottom" v-if="placedSignaturesByBackground[currentBackgroundIndex] && placedSignaturesByBackground[currentBackgroundIndex].length>0"> |
| | | <h3>已放签名:</h3> |
| | | <div v-for="(sig, index) in placedSignaturesByBackground[currentBackgroundIndex]" :key="index" class="controlBtns"> |
| | | <el-tag size="large" type="primary">签名{{index + 1}}</el-tag> |
| | | <el-button type="primary" @click="rotateSignature(index)" :icon="RefreshRight" circle/> |
| | | <el-button type="danger" @click="removeSignature(index)" :icon="Delete" circle/> |
| | | </div> |
| | | </div> |
| | | <!-- 画布 --> |
| | | <canvas ref="canvasRef" v-if="dialogVisible"></canvas> |
| | | |
| | | <!-- 已放置的签名 --> |
| | | <div class="bottom"> |
| | | <h3>已放置的签名:</h3> |
| | | <div v-for="(sig, index) in placedSignaturesByBackground[currentBackgroundIndex]" :key="index" style="margin-right: 10px"> |
| | | <el-button type="danger" @click="removeSignature(index)">删除签名 {{ index + 1 }}</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 导出PDF按钮 --> |
| | | <el-button type="primary" @click="saveAsPDF">确认归档</el-button> |
| | | <el-button type="primary" @click="saveAsPDF" style="margin-top: 20px">确认归档</el-button> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | |
| | | import {signArchive} from "@/api/signAgreement/signProject"; |
| | | import { jsPDF } from "jspdf"; // 导入 jsPDF |
| | | import {ElMessage, ElMessageBox} from "element-plus"; |
| | | import {RefreshRight,Delete} from '@element-plus/icons-vue' |
| | | import * as pdfjsLib from "pdfjs-dist"; |
| | | import {getToken} from "@/utils/auth"; |
| | | import axios from 'axios'; |
| | |
| | | import.meta.url |
| | | ).href; |
| | | const dialogVisible = ref(false) |
| | | const pdfLoading = ref(false) |
| | | const emit = defineEmits(["getList"]); |
| | | // 画布引用 |
| | | const canvasRef = ref(); |
| | |
| | | }) |
| | | |
| | | const openDialog= async (val)=>{ |
| | | console.log(JSON.parse(Cookies.get('userInfo')).userId,'serr') |
| | | dialogVisible.value = true |
| | | signatureImages.value = val.signatureFlows?.map(i=>i.signFile) |
| | | signatureImages.value = val.signatureFlows?.map(i=>import.meta.env.VITE_APP_BASE_API + i.signFile) |
| | | pdfFileUrl.value = import.meta.env.VITE_APP_BASE_API + val.tempFile |
| | | form.itemId = val.id |
| | | form.userId = JSON.parse(Cookies.get('userInfo')).userId |
| | | pdfLoading.value = true |
| | | await nextTick() |
| | | pdfLoading.value = true |
| | | const canvas = canvasRef.value; |
| | | if (canvas) { |
| | | ctx = canvas.getContext("2d"); |
| | | // 替换为实际的 PDF 文件地址 |
| | | console.log("pdfLoading before loadPDF:", pdfLoading.value); |
| | | await loadPDF(pdfFileUrl.value); |
| | | |
| | | console.log("pdfLoading after loadPDF:", pdfLoading.value); |
| | | // 监听鼠标事件 |
| | | canvas.addEventListener("mousedown", (e) => { |
| | | const mouseX = e.offsetX; |
| | |
| | | placedSignaturesByBackground.value.push([]); // 为每一页初始化签名图列表 |
| | | resolve(); |
| | | }; |
| | | pdfLoading.value = false |
| | | }); |
| | | } |
| | | |
| | |
| | | y: 100, |
| | | width: selectedImage.width, // 初始宽度为图片的原始宽度 |
| | | height: selectedImage.height, // 初始高度为图片的原始高度 |
| | | rotation: 0 // 初始旋转角度为 0 |
| | | }); |
| | | redrawCanvas(); |
| | | }; |
| | |
| | | const removeSignature = (index) => { |
| | | placedSignaturesByBackground.value[currentBackgroundIndex.value].splice(index, 1); |
| | | redrawCanvas(); |
| | | }; |
| | | |
| | | // 旋转签名图 |
| | | const rotateSignature = (index) => { |
| | | const currentSignatures = placedSignaturesByBackground.value[currentBackgroundIndex.value]; |
| | | if (currentSignatures[index]) { |
| | | currentSignatures[index].rotation = (currentSignatures[index].rotation + 90) % 360; // 每次旋转 90 度 |
| | | redrawCanvas(); |
| | | } |
| | | }; |
| | | |
| | | // 重新绘制画布 |
| | |
| | | |
| | | const currentSignatures = placedSignaturesByBackground.value[currentBackgroundIndex.value]; |
| | | currentSignatures.forEach((sig) => { |
| | | // 重新绘制所有签名图(包括大小) |
| | | ctx.drawImage(sig.image, sig.x, sig.y, sig.width, sig.height); |
| | | // 保存当前画布状态 |
| | | ctx.save(); |
| | | |
| | | // 移动到签名图的中心点 |
| | | ctx.translate(sig.x + sig.width / 2, sig.y + sig.height / 2); |
| | | |
| | | // 旋转画布 |
| | | ctx.rotate((sig.rotation * Math.PI) / 180); |
| | | |
| | | |
| | | // 绘制签名图 |
| | | ctx.drawImage(sig.image, -sig.width / 2, -sig.height / 2, sig.width, sig.height); |
| | | |
| | | // 恢复画布状态 |
| | | ctx.restore(); |
| | | |
| | | // 只有在非导出状态下才绘制缩放手柄 |
| | | if (!excludeHandle) { |
| | |
| | | ctx.drawImage(background, 0, 0, canvas.width, canvas.height); |
| | | const currentSignatures = placedSignaturesByBackground.value[index]; |
| | | currentSignatures.forEach((sig) => { |
| | | ctx.drawImage(sig.image, sig.x, sig.y, sig.width, sig.height); |
| | | // 保存当前画布状态 |
| | | ctx.save(); |
| | | |
| | | // 移动到签名图的中心点 |
| | | ctx.translate(sig.x + sig.width / 2, sig.y + sig.height / 2); |
| | | |
| | | // 旋转画布 |
| | | ctx.rotate((sig.rotation * Math.PI) / 180); |
| | | |
| | | // 绘制签名图 |
| | | ctx.drawImage(sig.image, -sig.width / 2, -sig.height / 2, sig.width, sig.height); |
| | | |
| | | // 恢复画布状态 |
| | | ctx.restore(); |
| | | }); |
| | | // 将画布内容添加到PDF |
| | | const imgData = canvas.toDataURL("image/jpeg"); |
| | |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | margin-bottom: 15px; |
| | | |
| | | .top-left{ |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | &>div{ |
| | | h3{ |
| | | margin-right: 20px; |
| | | } |
| | | img{ |
| | | margin-right: 20px; |
| | | width: 120px; |
| | | height: auto; |
| | | border: 1px solid #f0f0f0; |
| | | cursor: pointer; |
| | | box-sizing: border-box; |
| | | |
| | | &:hover{ |
| | | border: 2px solid #2563EB; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | margin: 20px 0; |
| | | margin-bottom: 20px; |
| | | |
| | | .controlBtns{ |
| | | margin-right: 20px; |
| | | |
| | | .el-button{ |
| | | margin: 0 0 0 5px; |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | | </style> |