|
@@ -1,472 +0,0 @@
|
|
-import { getArrValue, getRandom, isNullES, isNumber, isString } from 'js-fast-way'
|
|
|
|
-
|
|
|
|
-//PDF签章
|
|
|
|
-export default class HcPdfSign {
|
|
|
|
-
|
|
|
|
- static iframeDom = null
|
|
|
|
- static pdfViewer = null
|
|
|
|
- static signImgCss = {}
|
|
|
|
- static signType = ''
|
|
|
|
- static disX = 0
|
|
|
|
- static disY = 0
|
|
|
|
- static curSignDom = null
|
|
|
|
- static signList = []
|
|
|
|
- static signChange = null
|
|
|
|
- static pdfLoadFunc = null
|
|
|
|
- static batchSign = false
|
|
|
|
- static signNum = 0
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 初始化创建PDF预览
|
|
|
|
- * @param ele 元素的ref,或id值
|
|
|
|
- * @param url pdf的url
|
|
|
|
- * @param img 签章图片url
|
|
|
|
- * @param func 回调函数
|
|
|
|
- */
|
|
|
|
- static createPdf({ ele, url, img, change, load, isShowYinzhang }) {
|
|
|
|
- this.initVarNull()
|
|
|
|
- //判断参数是否合法
|
|
|
|
- if (isNullES(ele)) {
|
|
|
|
- console.warn('请传入参数,必须是,ref的dom元素,或id值')
|
|
|
|
- return false
|
|
|
|
- }
|
|
|
|
- //是否为字符串或数值类型
|
|
|
|
- let dom = null, errTip = 'ele参数不合法,必须是ref的dom元素,或id值'
|
|
|
|
- if (isString(ele) || isNumber(ele)) {
|
|
|
|
- try {
|
|
|
|
- dom = document.getElementById(ele)
|
|
|
|
- } catch (e) {
|
|
|
|
- console.error(errTip)
|
|
|
|
- return false
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- try {
|
|
|
|
- ele.cloneNode(true)
|
|
|
|
- if (ele.nodeType === 1 || ele.nodeType === 9) {
|
|
|
|
- dom = ele
|
|
|
|
- } else {
|
|
|
|
- console.error(errTip)
|
|
|
|
- return false
|
|
|
|
- }
|
|
|
|
- } catch (e) {
|
|
|
|
- console.error(errTip)
|
|
|
|
- return false
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- //清空dom
|
|
|
|
- const children = dom.children
|
|
|
|
- if (children.length > 0) {
|
|
|
|
- for (let i = children.length - 1; i >= 0; i--) {
|
|
|
|
- dom.removeChild(children[i])
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (isNullES(url)) {
|
|
|
|
- console.warn('请传入Pdf的url参数')
|
|
|
|
- return false
|
|
|
|
- }
|
|
|
|
- //创建iframe
|
|
|
|
- const iframe = document.createElement('iframe')
|
|
|
|
- iframe.setAttribute('id', 'pdf-sign-' + getRandom(6))
|
|
|
|
- iframe.src = `/plugins/pdfjs/sign/web/viewer.html?file=${url}#zoom=100`
|
|
|
|
- iframe.style.width = '100%'
|
|
|
|
- iframe.style.height = '100%'
|
|
|
|
- iframe.style.border = '1px solid #ccc'
|
|
|
|
- iframe.name = 'HcPdfSign'
|
|
|
|
- iframe.addEventListener('load', () => {
|
|
|
|
- this.iframeLoad(isShowYinzhang)
|
|
|
|
- })
|
|
|
|
- dom.appendChild(iframe)
|
|
|
|
- this.iframeDom = iframe
|
|
|
|
- //设置签章图片
|
|
|
|
- if (isNullES(img)) {
|
|
|
|
- console.warn('请传入签章图片')
|
|
|
|
- return false
|
|
|
|
- }
|
|
|
|
- this.signImage(img).then()
|
|
|
|
- //设置回调事件
|
|
|
|
- if (!isNullES(change)) {
|
|
|
|
- this.addEventFunc(change)
|
|
|
|
- }
|
|
|
|
- //设置回调事件
|
|
|
|
- if (!isNullES(load)) {
|
|
|
|
- this.addPdfLoadFunc(load)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //初始化空值
|
|
|
|
- static initVarNull() {
|
|
|
|
- this.iframeDom = null
|
|
|
|
- this.pdfViewer = null
|
|
|
|
- this.signImgCss = {}
|
|
|
|
- this.signType = ''
|
|
|
|
- this.disX = 0
|
|
|
|
- this.disY = 0
|
|
|
|
- this.curSignDom = null
|
|
|
|
- this.signList = []
|
|
|
|
- this.signChange = null
|
|
|
|
- this.pdfLoadFunc = null
|
|
|
|
- this.signNum = 0
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //设置回调事件
|
|
|
|
- static addEventFunc(func) {
|
|
|
|
- if (typeof func !== 'function') {
|
|
|
|
- console.warn('请传入函数')
|
|
|
|
- return false
|
|
|
|
- } else {
|
|
|
|
- this.signChange = func
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //触发回调事件
|
|
|
|
- static signChangeFunc() {
|
|
|
|
- if (typeof this.signChange !== 'function') {
|
|
|
|
- return false
|
|
|
|
- } else {
|
|
|
|
- this.signChange(this.signList)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //设置加载完成的回调事件
|
|
|
|
- static addPdfLoadFunc(func) {
|
|
|
|
- if (typeof func !== 'function') {
|
|
|
|
- console.warn('请传入函数')
|
|
|
|
- return false
|
|
|
|
- } else {
|
|
|
|
- this.pdfLoadFunc = func
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //加载完成
|
|
|
|
- static setPdfLoadFunc(val) {
|
|
|
|
- if (typeof this.pdfLoadFunc !== 'function') {
|
|
|
|
- return false
|
|
|
|
- } else {
|
|
|
|
- this.pdfLoadFunc(val)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //设置签章图片
|
|
|
|
- static async signImage(url) {
|
|
|
|
- const res = await this.getImageSize(url)
|
|
|
|
- if (res.width === res.height) {
|
|
|
|
- this.signImgCss = { url: url, width: 170, height: 170 }
|
|
|
|
- } else if (res.width > res.height) {
|
|
|
|
- const scaleFactor = 30 / res.height
|
|
|
|
- const newWidth = res.width * scaleFactor
|
|
|
|
- this.signImgCss = { url: url, width: newWidth, height: 30 }
|
|
|
|
- } else {
|
|
|
|
- const scaleFactor = 170 / res.height
|
|
|
|
- const newWidth = res.width * scaleFactor
|
|
|
|
- this.signImgCss = { url: url, width: newWidth, height: 170 }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //获取网络图片的高宽
|
|
|
|
- static async getImageSize(url) {
|
|
|
|
- return new Promise((resolve) => {
|
|
|
|
- let img = new Image()
|
|
|
|
- img.onload = function () {
|
|
|
|
- let width = img.width
|
|
|
|
- let height = img.height
|
|
|
|
- resolve({ width, height })
|
|
|
|
- }
|
|
|
|
- img.src = url
|
|
|
|
- })
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //创建签章图片
|
|
|
|
- static async createSignImage(event) {
|
|
|
|
- //创建图片元素
|
|
|
|
- const { url, width, height } = this.signImgCss
|
|
|
|
- const uuid = 'pdf-sign-img-' + getRandom(6)
|
|
|
|
- const signImg = document.createElement('img')
|
|
|
|
- signImg.setAttribute('id', uuid)
|
|
|
|
- signImg.src = url
|
|
|
|
- signImg.style.position = 'absolute'
|
|
|
|
- signImg.style.width = width + 'px'
|
|
|
|
- signImg.style.height = height + 'px'
|
|
|
|
- signImg.style.left = (event.layerX - (width / 2)) + 'px'
|
|
|
|
- signImg.style.top = (event.layerY - (height / 2)) + 'px'
|
|
|
|
- signImg.style.pointerEvents = 'auto'
|
|
|
|
- signImg.style.zIndex = 999
|
|
|
|
- return signImg
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 是否批量签章
|
|
|
|
- * @param val true/false
|
|
|
|
- */
|
|
|
|
- static setBatchSign(val = false) {
|
|
|
|
- console.log('111', val)
|
|
|
|
- this.batchSign = val
|
|
|
|
- this.setPageScrolling()
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //让PDF页面全部渲染一下
|
|
|
|
- static async setPageScrolling() {
|
|
|
|
- const pageDom = this.pdfViewer?.children ?? []
|
|
|
|
- await this.toPdfPage('firstPage')
|
|
|
|
- for (let i = 0; i < pageDom.length; i++) {
|
|
|
|
- await this.toPdfPage('next')
|
|
|
|
- }
|
|
|
|
- await this.toPdfPage('firstPage')
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 跳转pdf的页面
|
|
|
|
- * @param pageId 最后一页:lastPage,第一页:firstPage,上一页:previous,下一页:next
|
|
|
|
- */
|
|
|
|
- static async toPdfPage(pageId) {
|
|
|
|
- return new Promise((resolve) => {
|
|
|
|
- this.iframeDom?.contentDocument?.getElementById(pageId)?.click()
|
|
|
|
- setTimeout(() => {
|
|
|
|
- resolve(true)
|
|
|
|
- }, 100)
|
|
|
|
- })
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //PDF加载完成
|
|
|
|
- static iframeLoad(isShowYinzhang) {
|
|
|
|
- const viewer = this.iframeDom?.contentDocument?.getElementById('viewer')
|
|
|
|
- if (isShowYinzhang) {
|
|
|
|
- viewer.classList.add('stamp-cursor')
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //页面被点击
|
|
|
|
- viewer.addEventListener('click', (event) => {
|
|
|
|
- this.viewerClick(event).then()
|
|
|
|
- })
|
|
|
|
- //鼠标移动
|
|
|
|
- viewer.addEventListener('mousemove', (event) => {
|
|
|
|
- event.preventDefault()
|
|
|
|
- if (this.signType !== '移动' || !this.curSignDom) {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- //鼠标位置
|
|
|
|
- const left = (event.clientX - this.disX) + 'px'
|
|
|
|
- const top = (event.clientY - this.disY) + 'px'
|
|
|
|
- this.curSignDom.style.left = left
|
|
|
|
- this.curSignDom.style.top = top
|
|
|
|
- //批量处理
|
|
|
|
- if (this.batchSign) {
|
|
|
|
- const curDom = this.curSignDom
|
|
|
|
- let { data: curSign } = this.getSignImgDom(curDom)
|
|
|
|
- if (!curSign) return
|
|
|
|
- const newArr = this.signList.filter(item => {
|
|
|
|
- return item.type === curSign.type
|
|
|
|
- })
|
|
|
|
- newArr.forEach(item => {
|
|
|
|
- item.dom.style.left = left
|
|
|
|
- item.dom.style.top = top
|
|
|
|
- })
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
- //鼠标抬起
|
|
|
|
- viewer.addEventListener('mouseup', () => {
|
|
|
|
- if (!this.curSignDom) return
|
|
|
|
- this.signType = '签名'
|
|
|
|
- this.curSignDom.style.cursor = 'default'
|
|
|
|
- const curDom = this.curSignDom
|
|
|
|
- //获取数据
|
|
|
|
- let { data: curSign } = this.getSignImgDom(curDom)
|
|
|
|
- if (!curSign) return
|
|
|
|
- //计算坐标
|
|
|
|
- const left = curDom.style.left.replace('px', '')
|
|
|
|
- const top = curDom.style.top.replace('px', '')
|
|
|
|
- const { width, height } = this.signImgCss
|
|
|
|
- const lefts = Number(left) + Number(width / 2)
|
|
|
|
- const tops = Number(top) + Number(height / 2)
|
|
|
|
- const lx = ((lefts * 100) / curDom.parentNode.clientWidth).toFixed(4)
|
|
|
|
- const ly = ((tops * 100) / curDom.parentNode.clientHeight).toFixed(4)
|
|
|
|
- //批量处理
|
|
|
|
- if (this.batchSign) {
|
|
|
|
- const newArr = this.signList.filter(item => {
|
|
|
|
- return item.type === curSign.type
|
|
|
|
- })
|
|
|
|
- newArr.forEach(item => {
|
|
|
|
- item.lx = lx
|
|
|
|
- item.ly = ly
|
|
|
|
- item.width = curDom.clientWidth
|
|
|
|
- item.height = curDom.clientHeight
|
|
|
|
- })
|
|
|
|
- } else {
|
|
|
|
- curSign.lx = lx
|
|
|
|
- curSign.ly = ly
|
|
|
|
- curSign.width = curDom.clientWidth
|
|
|
|
- curSign.height = curDom.clientHeight
|
|
|
|
- }
|
|
|
|
- this.signChangeFunc()
|
|
|
|
- })
|
|
|
|
- //监听按键
|
|
|
|
- const container = this.iframeDom?.contentDocument?.getElementById('outerContainer')
|
|
|
|
- container.addEventListener('keyup', (event) => {
|
|
|
|
- //删除签章
|
|
|
|
- if (event.keyCode === 8 && event.key === 'Backspace') {
|
|
|
|
- const curDom = this.curSignDom
|
|
|
|
- const { index } = this.getSignImgDom(curDom)
|
|
|
|
- if (index <= -1) return
|
|
|
|
- this.delSignImg(index).then()
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
- this.pdfViewer = viewer
|
|
|
|
- //处理pdf渲染
|
|
|
|
- if (this.batchSign) {
|
|
|
|
- setTimeout(async () => {
|
|
|
|
- await this.setPageScrolling()
|
|
|
|
- this.setPdfLoadFunc(true)
|
|
|
|
- }, 500)
|
|
|
|
- } else {
|
|
|
|
- setTimeout(async () => {
|
|
|
|
- this.setPdfLoadFunc(true)
|
|
|
|
- }, 100)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //删除签章
|
|
|
|
- static async delSignImg(index) {
|
|
|
|
- if (index <= -1) return
|
|
|
|
- if (this.batchSign) {
|
|
|
|
- const list = this.signList, curDom = list[index]
|
|
|
|
- //倒序删除签章
|
|
|
|
- for (let i = list.length - 1; i >= 0; i--) {
|
|
|
|
- if (list[i].type === curDom.type) {
|
|
|
|
- list[i].dom.remove()
|
|
|
|
- delete list[i].dom
|
|
|
|
- list.splice(i, 1)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- this.signList = list
|
|
|
|
- this.signChangeFunc()
|
|
|
|
- } else {
|
|
|
|
- this.signList[index].dom.remove()
|
|
|
|
- this.signList.splice(index, 1)
|
|
|
|
- this.signChangeFunc()
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- //获取签章图片的数据
|
|
|
|
- static getSignImgDom(curDom) {
|
|
|
|
- if (isNullES(curDom)) {
|
|
|
|
- return { data: null, index: -1 }
|
|
|
|
- }
|
|
|
|
- //获取数据
|
|
|
|
- const id = curDom?.getAttribute('id')
|
|
|
|
- let curSign = null, index = -1
|
|
|
|
- for (let i = 0; i < this.signList.length; i++) {
|
|
|
|
- const item = this.signList[i]
|
|
|
|
- if (item.id === id) {
|
|
|
|
- curSign = item
|
|
|
|
- index = i
|
|
|
|
- break
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return { data: curSign, index }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //页面被点击
|
|
|
|
- static async viewerClick(event) {
|
|
|
|
- const target = event.target
|
|
|
|
- //当前为移动模式
|
|
|
|
- if (this.signType === '移动') {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- //不在PDF页面上点击
|
|
|
|
- if (target.className !== 'textLayer') {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- //批量签章
|
|
|
|
- this.signNum ++
|
|
|
|
- console.log(this.batchSign)
|
|
|
|
- if (this.batchSign) {
|
|
|
|
- const parent = target?.parentNode?.parentNode?.children ?? []
|
|
|
|
- console.log(parent)
|
|
|
|
- for (let i = 0; i < parent.length; i++) {
|
|
|
|
- await this.setPdfNodeSign(parent[i], parent[i]?.children[1], event)
|
|
|
|
- }
|
|
|
|
- this.signChangeFunc()
|
|
|
|
- } else {
|
|
|
|
- await this.setPdfNodeSign(target?.parentNode, target, event)
|
|
|
|
- this.signChangeFunc()
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //设置PDF节点签章
|
|
|
|
- static async setPdfNodeSign(node, textLayer, event) {
|
|
|
|
- if (isNullES(node) || isNullES(textLayer) || isNullES(event)) {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // if (node.children.length < 3) {
|
|
|
|
- // node.prepend('<div class="signLayer" style="position: absolute;height: 100%;width: 100%;z-index: 999;pointer-events: none;overflow: hidden"></div>')
|
|
|
|
- // }
|
|
|
|
- //插入图片
|
|
|
|
- const signImgDom = await this.createSignImage(event)
|
|
|
|
- node.children[0].append(signImgDom)
|
|
|
|
- //鼠标按下
|
|
|
|
- signImgDom.addEventListener('mousedown', (e) => {
|
|
|
|
- //新的当前选中项
|
|
|
|
- this.curSignDom = e.target
|
|
|
|
- this.signType = '移动'
|
|
|
|
- e.target.style.cursor = 'move'
|
|
|
|
- //鼠标相对于图片的位置
|
|
|
|
- this.disX = e.clientX - e.target.offsetLeft
|
|
|
|
- this.disY = e.clientY - e.target.offsetTop
|
|
|
|
- })
|
|
|
|
- //保存签章信息
|
|
|
|
- this.signList.push({
|
|
|
|
- type: this.signNum,
|
|
|
|
- url: this.signImgCss?.url ?? '',
|
|
|
|
- page: node.getAttribute('data-page-number'),
|
|
|
|
- id: signImgDom.getAttribute('id'),
|
|
|
|
- lx: ((event.layerX * 100) / textLayer.clientWidth).toFixed(4),
|
|
|
|
- ly: ((event.layerY * 100) / textLayer.clientHeight).toFixed(4),
|
|
|
|
- width: signImgDom.clientWidth,
|
|
|
|
- height: signImgDom.clientHeight,
|
|
|
|
- dom: signImgDom,
|
|
|
|
- })
|
|
|
|
- return signImgDom
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //设置PDF签章图片
|
|
|
|
- static async setPdfSignImg(arr) {
|
|
|
|
- const list = getArrValue(arr)
|
|
|
|
- if (list.length <= 0) return
|
|
|
|
- const pageDom = this.pdfViewer?.children ?? []
|
|
|
|
- for (let i = 0; i < list.length; i++) {
|
|
|
|
- const page = Number(list[i].page) - 1
|
|
|
|
- const dom = pageDom[page]?.getElementsByClassName('canvasWrapper')[0]
|
|
|
|
- //创建图片元素
|
|
|
|
- const signImg = document.createElement('img')
|
|
|
|
- signImg.setAttribute('id', list[i].id)
|
|
|
|
- signImg.src = list[i].url
|
|
|
|
- signImg.style.position = 'absolute'
|
|
|
|
- signImg.style.width = list[i].dom.style.width
|
|
|
|
- signImg.style.height = list[i].dom.style.height
|
|
|
|
- signImg.style.left = list[i].dom.style.left
|
|
|
|
- signImg.style.top = list[i].dom.style.top
|
|
|
|
- signImg.style.pointerEvents = 'auto'
|
|
|
|
- signImg.style.zIndex = 999
|
|
|
|
- dom.append(signImg)
|
|
|
|
- //鼠标按下
|
|
|
|
- signImg.addEventListener('mousedown', (e) => {
|
|
|
|
- //新的当前选中项
|
|
|
|
- this.curSignDom = e.target
|
|
|
|
- this.signType = '移动'
|
|
|
|
- e.target.style.cursor = 'move'
|
|
|
|
- //鼠标相对于图片的位置
|
|
|
|
- this.disX = e.clientX - e.target.offsetLeft
|
|
|
|
- this.disY = e.clientY - e.target.offsetTop
|
|
|
|
- })
|
|
|
|
- //保存签章信息
|
|
|
|
- this.signList.push({
|
|
|
|
- ...list[i],
|
|
|
|
- width: signImg.clientWidth,
|
|
|
|
- height: signImg.clientHeight,
|
|
|
|
- dom: signImg,
|
|
|
|
- })
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-}
|
|
|