From d206bfc9f9f2fd62d898bccfad5c00cd324dca58 Mon Sep 17 00:00:00 2001 From: huliyong <2783385703@qq.com> Date: Sat, 22 Feb 2025 19:53:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/api.js | 2 +- api/model/contact.js | 6 + api/model/work.js | 5 +- components/list/contract/contractManagePopup.vue | 2 +- pages_order/components/canvas-drag/index.vue | 4 +- pages_order/contract/contract.vue | 169 +++++++++++-------- pages_order/contract/contractDetail.vue | 4 +- pages_order/contract/contractManageEdit.vue | 201 ++++++++++++++++++----- pages_order/contract/electronicSignature.vue | 89 +++++++++- utils/wxBase64src.js | 69 +++++--- 10 files changed, 402 insertions(+), 149 deletions(-) diff --git a/api/api.js b/api/api.js index 61086ff..f24afdc 100644 --- a/api/api.js +++ b/api/api.js @@ -149,7 +149,7 @@ export function api(key, data, callback, loadingTitle) { if (req.auth) { if (!uni.getStorageSync('token')) { utils.toLogin() - console.error('需要登录') + console.error('需要登录', req.url) return Promise.reject() } } diff --git a/api/model/contact.js b/api/model/contact.js index b949893..3c43908 100644 --- a/api/model/contact.js +++ b/api/model/contact.js @@ -87,6 +87,12 @@ const api = { method: 'GET', auth: true, }, + //工具-pdf加签名 + signPdf: { + url: '/employ/contract/signPdf', + method: 'GET', + auth: true, + }, } diff --git a/api/model/work.js b/api/model/work.js index e941332..4be2cdf 100644 --- a/api/model/work.js +++ b/api/model/work.js @@ -26,13 +26,12 @@ const api = { limit : 1500, showLoading : true, }, - // 首页-根据Id查看工作详情 + // 首页-查询工作信息列表 employeeQueryJobList: { url: '/employ/job/queryJobList', method: 'GET', - auth : true, }, - // 首页-查询工作信息列表 + // 首页-根据Id查看工作详情 employeeQueryJobById: { url: '/employ/job/queryJobById', method: 'GET', diff --git a/components/list/contract/contractManagePopup.vue b/components/list/contract/contractManagePopup.vue index ff27d59..0644e72 100644 --- a/components/list/contract/contractManagePopup.vue +++ b/components/list/contract/contractManagePopup.vue @@ -50,7 +50,7 @@ employeePage : item.employeePage, employeePosition : item.employeePosition, template : item.template, - contract : item.contract, + contract : item.template, employeeStatus : 0, employeeId : this.uid, title : item.title, diff --git a/pages_order/components/canvas-drag/index.vue b/pages_order/components/canvas-drag/index.vue index 08f0543..e5164cd 100644 --- a/pages_order/components/canvas-drag/index.vue +++ b/pages_order/components/canvas-drag/index.vue @@ -5,9 +5,9 @@ + diff --git a/pages_order/contract/contractDetail.vue b/pages_order/contract/contractDetail.vue index 1a2fb2a..b8c93f8 100644 --- a/pages_order/contract/contractDetail.vue +++ b/pages_order/contract/contractDetail.vue @@ -92,7 +92,6 @@ }) }, showPDF(){ - console.log(1); uni.downloadFile({ url : this.detail.contract, success : res => { @@ -109,6 +108,7 @@ // 去签名 toSignature(){ + console.log('toSignature'); uni.showModal({ title: '签署前请熟知合同完整内容!', cancelText: '已知晓', @@ -201,9 +201,11 @@ if(this.role){ graph = JSON.parse(this.form.bossPosition) this.detail.bossImage = url + this.detail.bossStatus = 1 }else{ graph = JSON.parse(this.form.employeePosition) this.detail.employeeImage = url + this.detail.employeeStatus = 1 } for(let k in graph){ diff --git a/pages_order/contract/contractManageEdit.vue b/pages_order/contract/contractManageEdit.vue index c4c9d84..587a6dd 100644 --- a/pages_order/contract/contractManageEdit.vue +++ b/pages_order/contract/contractManageEdit.vue @@ -14,7 +14,11 @@ enableUndo="true"> - + + 上一页 + {{ imagesIndex + 1 }}/{{ imageArr.length }} + 下一页 + 导入合同 @@ -23,6 +27,8 @@ 保存 + 预览合同 + @@ -42,7 +48,7 @@ width: 700, drawArr : {}, form : { - template : 'https://img.teyizhao.com/2025-01-29/891f7516-dd40-42a4-82e5-d8efc46f4ea7.pdf', + template : '', employeePage : 0,//求职者(乙方)签字页码 employeePosition : '',//求职者(乙方)签字坐标 bossPage : 0,//招聘者(甲方)签字页码 @@ -71,6 +77,67 @@ console.log("mounted mounted mounted"); }, methods: { + // async pro(){ + // if(this.imagesIndex == 0){ + // uni.showToast({ + // title: '已经是第一页了' + // }) + // return + // } + // this.imagesIndex-- + // await wxBase64src.unlink() + // this.changeBgImage() + // }, + // async next(){ + // if(this.imagesIndex == this.imageArr.length - 1){ + // uni.showToast({ + // title: '已经是最后一页了' + // }) + // return + // } + // this.imagesIndex++ + // await wxBase64src.unlink() + // this.changeBgImage() + // }, + async pro(){ + if(this.imagesIndex == 0){ + uni.showToast({ + title: '已经是第一页了' + }) + return + } + this.imagesIndex-- + await wxBase64src.unlink() + // 强制重新渲染canvas + this.$nextTick(async () => { + await this.changeBgImage() + }) + }, + async next(){ + if(this.imagesIndex == this.imageArr.length - 1){ + uni.showToast({ + title: '已经是最后一页了' + }) + return + } + this.imagesIndex++ + await wxBase64src.unlink() + // 强制重新渲染canvas + this.$nextTick(async () => { + await this.changeBgImage() + }) + }, + // 预览合同 + previewContract(){ + uni.downloadFile({ + url : this.form.template, + success : res => { + uni.openDocument({ + filePath: res.tempFilePath, + }) + } + }) + }, // 签名位置更新时 onDrawArrChange(arr){ console.log(arr); @@ -112,7 +179,8 @@ } uni.getImageInfo({ - src: 'https://img.teyizhao.com/2025-02-07/3d837c0e-91f4-4682-82d9-a04c2af737e8.png', + src: this.configList.config_sign_a, + // src: 'https://img.teyizhao.com/2025-02-07/3d837c0e-91f4-4682-82d9-a04c2af737e8.png', success : res => { this.setData({ graph: { @@ -132,7 +200,8 @@ }) uni.getImageInfo({ - src: 'https://img.teyizhao.com/2025-02-07/af4786c0-7b62-4a86-a090-9f28eca3674a.png', + src: this.configList.config_sign_b, + // src: 'https://img.teyizhao.com/2025-02-07/af4786c0-7b62-4a86-a090-9f28eca3674a.png', success : res => { this.setData({ graph: { @@ -159,42 +228,82 @@ async onChangeBgImage() { let self = this - // let pdfUrl = await self.loadFDP() - - // console.log(pdfUrl); + let pdfUrl = await self.loadFDP() - // this.form.template = pdfUrl + this.form.template = pdfUrl - this.pdf2imagebase64() + await this.pdf2imagebase64() this.changeBgImage() }, - async changeBgImage(){ - let self = this + // async changeBgImage(){ + // let self = this - let src = await wxBase64src.base64src(this.imageArr[this.imagesIndex]) + // let src = await wxBase64src.base64src(this.imageArr[this.imagesIndex]) - uni.getImageInfo({ - src, - success: image => { - console.log(image); + // uni.getImageInfo({ + // src, + // success: image => { + // console.log(image); - let allwh = image.height + image.width - let imgw = (image.width / allwh).toFixed(2) - let imgh = (image.height / allwh).toFixed(2) + // let allwh = image.height + image.width + // let imgw = (image.width / allwh).toFixed(2) + // let imgh = (image.height / allwh).toFixed(2) - self.height = imgh * Math.ceil(this.width / imgw) + // self.height = imgh * Math.ceil(this.width / imgw) - self.$nextTick(() => { - this.$refs.canvasRef.changeBgImage(image.path) - }) - }, - fail(err) { - console.log(err); - } - }) - }, + // self.$nextTick(() => { + // uni.hideLoading() + // this.$refs.canvasRef.changeBgImage(image.path) + // }) + // }, + // fail(err) { + // wxBase64src.unlink() + // console.log(err); + // } + // }) + // }, + async changeBgImage(){ + let self = this + + try { + uni.showLoading({ + title: '加载中...' + }) + + let src = await wxBase64src.base64src(this.imageArr[this.imagesIndex]) + + const imageInfo = await new Promise((resolve, reject) => { + uni.getImageInfo({ + src, + success: resolve, + fail: reject + }) + }) + + let allwh = imageInfo.height + imageInfo.width + let imgw = (imageInfo.width / allwh).toFixed(2) + let imgh = (imageInfo.height / allwh).toFixed(2) + + self.height = imgh * Math.ceil(this.width / imgw) + + // 确保DOM更新后再更新canvas + await this.$nextTick() + // 先清空画布再设置新图片 + // await this.$refs.canvasRef.clearCanvas() + await this.$refs.canvasRef.changeBgImage(imageInfo.path) + + // 重新添加签名位置 + // this.onAddImage() + + } catch(err) { + console.error('changeBgImage error:', err) + wxBase64src.unlink() + } finally { + uni.hideLoading() + } + }, loadFDP(){ let that = this return new Promise((success, error) => { @@ -276,31 +385,28 @@ this.form.bossPosition = JSON.stringify(bossPosition) this.form.employeePosition = JSON.stringify(employeePosition) + this.form.bossPage = this.imagesIndex + this.form.employeePage = this.imagesIndex + this.$api(this.id ? 'updateContractTemplate' : 'addContractTemplate', this.form).then(res => { if(res.code == 200){ uni.navigateBack(-1) } }) - }, - // pdf2imagebase64(){ - // this.$api('pdf2imagebase64', { - - // }, res => { - - // }) - // }, - // 修改或者保存模板 - saveOrUpdate(){ - }, // pdf转图片base64 async pdf2imagebase64(){ + uni.showLoading({ + title: '解析文档中...' + }) let res = await this.$api('pdf2imagebase64', { pdfPath : this.form.template }) - this.imageArr = res.result - console.log(this.imageArr); + this.imageArr = [] + for(let key in res.result){ + this.imageArr.push(res.result[key]) + } }, getDetail(){ if(!this.id){ @@ -309,16 +415,22 @@ } this.$api('queryContractTemplateById', { contractTemplateId : this.id - }).then(res => { + }).then(async (res) => { if(res.code == 200){ this.form = res.result + this.imagesIndex = this.form.employeePage + delete this.form.createBy delete this.form.createTime delete this.form.updateBy delete this.form.updateTime this.onAddImage() + + await this.pdf2imagebase64() + + this.changeBgImage() } }) }, @@ -344,8 +456,9 @@ .btn-list { display: flex; flex-wrap: wrap; + align-items: center; padding: 20rpx; - gap: 60rpx; + gap: 30rpx; justify-content: center; .uni-color-btn { margin: 0; diff --git a/pages_order/contract/electronicSignature.vue b/pages_order/contract/electronicSignature.vue index 2de378b..ac47601 100644 --- a/pages_order/contract/electronicSignature.vue +++ b/pages_order/contract/electronicSignature.vue @@ -44,6 +44,7 @@ width : '700rpx', crosswise : false, options : {}, + detail : {}, } }, onReady() { @@ -54,29 +55,105 @@ }, onShow() { this.initPM() + this.getDetail() }, methods: { + // 获取合同内容 + getDetail(){ + let data = { + contractId: this.options.id + } + if (uni.getStorageSync('token')) { + // data.token = uni.getStorageSync('token') + } + this.$api('queryContracById', data, res => { + if (res.code == 200) { + this.detail = res.result + } + }) + }, initPM(){ if(!this.crosswise) return let info = uni.getSystemInfoSync(); console.log(info.windowWidth); console.log(info.windowHeight); - - }, open() { this.initCanvas(); }, + async save(imagePath){ + let graph = {}, pageNo = 1; + + if(this.role){ + graph = JSON.parse(this.detail.bossPosition) + this.detail.bossImage = imagePath + this.detail.bossStatus = 1 + pageNo = this.detail.bossPage + }else{ + graph = JSON.parse(this.detail.employeePosition) + this.detail.employeeImage = imagePath + this.detail.employeeStatus = 1 + pageNo = this.detail.employeePage + } + + for(let k in graph){ + graph[k] = (parseFloat(graph[k]) / 700.0).toFixed(2) + } + + let res = await this.$api('signPdf', { + imageHeight : graph.h, + imageWidth : graph.w, + positionX : graph.x, + positonY : graph.y, + // pdfPath : this.detail.contract, + // imagePath, + pdfPath : 'https://augcl.oss-cn-guangzhou.aliyuncs.com/test/mytest.pdf', + imagePath : 'https://augcl.oss-cn-guangzhou.aliyuncs.com/test/image.png', + pageNo : parseInt(pageNo) + 1, + }) + + // uni.downloadFile({ + // url : res.result, + // success : res => { + // uni.openDocument({ + // filePath: res.tempFilePath, + // }) + // } + // }) + + // return + + delete this.detail.createBy + delete this.detail.createTime + delete this.detail.updateBy + delete this.detail.updateTime + + this.detail.contract = res.result + + this.$api('updateContract', this.detail) + .then(res => { + if(res.code == 200){ + uni.navigateBack(-1) + } + }) + + }, close() { + let self = this uni.canvasToTempFilePath({ canvasId: "mycanvas", success: (res) => { console.log(res.tempFilePath); - const canvas = res.tempFilePath; + const imagePath = res.tempFilePath; + + // uni.setStorageSync('electronicSignature', imagePath) + // let o = this.options + // uni.navigateBack(-1) + + self.$Oss.ossUpload(imagePath).then(url => { + self.save(url) + }) - uni.setStorageSync('electronicSignature', canvas) - let o = this.options - uni.navigateBack(-1) }, fail(error) { console.error("转化图片错误!", error) diff --git a/utils/wxBase64src.js b/utils/wxBase64src.js index 7433ac5..a20f804 100644 --- a/utils/wxBase64src.js +++ b/utils/wxBase64src.js @@ -2,28 +2,55 @@ const fsm = wx.getFileSystemManager(); const FILE_BASE_NAME = 'tmp_base64src'; const base64src = function(base64data) { - return new Promise((resolve, reject) => { - const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || []; - if (!format) { - reject(new Error('ERROR_BASE64SRC_PARSE')); - } - const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`; - const buffer = wx.base64ToArrayBuffer(bodyData); - - fsm.writeFile({ - filePath, - data: buffer, - encoding: 'binary', - success() { - resolve(filePath); - }, - fail() { - reject(new Error('ERROR_BASE64SRC_WRITE')); - }, - }); - }); + return new Promise((resolve, reject) => { + // 添加时间戳生成唯一文件名 + const timestamp = Date.now(); + const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}_${timestamp}.png`; + const buffer = wx.base64ToArrayBuffer(base64data); + + fsm.writeFile({ + filePath, + data: buffer, + encoding: 'binary', + success() { + resolve(filePath); + }, + fail() { + reject(new Error('ERROR_BASE64SRC_WRITE')); + }, + }); + }); +}; + +const unlink = function() { + return new Promise((resolve, reject) => { + // 获取临时文件列表 + fsm.readdir({ + dirPath: wx.env.USER_DATA_PATH, + success: (res) => { + // 删除所有tmp_base64src开头的临时文件 + const promises = res.files + .filter(file => file.startsWith(FILE_BASE_NAME)) + .map(file => { + return new Promise((res, rej) => { + fsm.unlink({ + filePath: `${wx.env.USER_DATA_PATH}/${file}`, + success: res, + fail: rej + }); + }); + }); + + Promise.all(promises) + .then(resolve) + .catch(reject); + }, + fail: reject + }); + }); }; export default { - base64src, + base64src, + unlink, }; \ No newline at end of file