Browse Source

上传修改

master
前端-胡立永 6 days ago
parent
commit
d206bfc9f9
10 changed files with 402 additions and 149 deletions
  1. +1
    -1
      api/api.js
  2. +6
    -0
      api/model/contact.js
  3. +2
    -3
      api/model/work.js
  4. +1
    -1
      components/list/contract/contractManagePopup.vue
  5. +2
    -2
      pages_order/components/canvas-drag/index.vue
  6. +99
    -70
      pages_order/contract/contract.vue
  7. +3
    -1
      pages_order/contract/contractDetail.vue
  8. +157
    -44
      pages_order/contract/contractManageEdit.vue
  9. +83
    -6
      pages_order/contract/electronicSignature.vue
  10. +48
    -21
      utils/wxBase64src.js

+ 1
- 1
api/api.js View File

@ -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()
}
}


+ 6
- 0
api/model/contact.js View File

@ -87,6 +87,12 @@ const api = {
method: 'GET',
auth: true,
},
//工具-pdf加签名
signPdf: {
url: '/employ/contract/signPdf',
method: 'GET',
auth: true,
},
}

+ 2
- 3
api/model/work.js View File

@ -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',


+ 1
- 1
components/list/contract/contractManagePopup.vue View File

@ -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,


+ 2
- 2
pages_order/components/canvas-drag/index.vue View File

@ -5,9 +5,9 @@
<script>
// components/canvas-drag/index.js
let DELETE_ICON = '/static/components/canvas-drag/close.png'; //
let DELETE_ICON = '../../static/components/canvas-drag/close.png'; //
//
let DRAG_ICON = '/static/components/canvas-drag/scale.png'; //
let DRAG_ICON = '../../static/components/canvas-drag/scale.png'; //
//
const STROKE_COLOR = '#fff';
const ROTATE_ENABLED = false;


+ 99
- 70
pages_order/contract/contract.vue View File

@ -16,30 +16,38 @@
</view>
<view class="content">
<view class="projectContent"
v-for="(item, index) in list"
@click="showPDF(item)"
:key="index">
<image src="/static/image/contract/contract.png" mode="aspectFill"/>
<view class="itemList">
<view class="projectName">
<!-- xxxx电子合同 -->
{{ item.title }}
<view class="projectContent" v-for="(item, index) in list" :key="index">
<view class="item">
<image src="/static/image/contract/contract.png" mode="aspectFill"/>
<view class="itemList">
<view class="projectName">
{{ item.title }}
<text class="status" :class="{
'status-pending': role ? item.bossStatus === 0 : item.employeeStatus === 0,
'status-signed': role ? item.bossStatus === 1 : item.employeeStatus === 1,
'status-completed': role ? item.bossStatus === 2 : item.employeeStatus === 2
}">
{{ role ?
(item.bossStatus === 0 ? '待签署' : item.bossStatus === 1 ? '已签署' : '已完成') :
(item.employeeStatus === 0 ? '待签署' : item.employeeStatus === 1 ? '已签署' : '已完成')
}}
</text>
</view>
<view class="buyer">甲方{{ item.companyName }}</view>
<view class="seller">乙方{{ item.employeeName }}</view>
</view>
<view class="buyer">
<!-- 甲方湖南瀚海科技有限公司 -->
甲方{{ item.companyName }}
<view class="actions">
<view class="view-btn" @click="showPDF(item)">
<uv-icon name="eye" color="#2979ff" size="30rpx"></uv-icon>
<text>查看</text>
</view>
<view class="sign-btn"
v-if="(role && item.bossStatus === 0) || (!role && item.employeeStatus === 0)"
@click.stop="$utils.navigateTo('/pages_order/contract/electronicSignature?id=' + item.id)">
<uv-icon name="edit-pen" color="#fff" size="30rpx"></uv-icon>
<text>签署</text>
</view>
</view>
<view class="seller">
<!-- 乙方四川特能博世科技有限公司 -->
乙方{{ item.employeeName }}
</view>
</view>
<view class="run">
<uv-icon
name="arrow-right"
color="#2979ff"
size="30rpx"></uv-icon>
</view>
</view>
</view>
@ -82,75 +90,96 @@
this.getData()
},
showPDF(item){
this.$utils.
navigateTo('/pages_order/contract/contractDetail?id='
+ item.id)
// uni.showModal({
// title: '',
// cancelText: '',
// confirmText: '',
// success : e => {
// if(e.confirm){
// uni.downloadFile({
// url : item.contract,
// success : res => {
// uni.openDocument({
// filePath: res.tempFilePath,
// })
// }
// })
// }else{
// this.$utils.
// navigateTo('/pages_order/contract/contractDetail?id='
// + item.id)
// }
// }
// })
uni.downloadFile({
url : item.contract,
success : res => {
uni.openDocument({
filePath: res.tempFilePath,
})
}
})
},
}
}
</script>
<style scoped lang="scss">
.content {
width: 100%;
height: 100%;
.projectContent {
background-color: #fff;
.content {
width: 100%;
height: 100%;
.projectContent {
background-color: #fff;
display: flex;
margin: 30rpx;
border-radius: 20rpx;
.item{
display: flex;
margin: 30rpx;
border-radius: 20rpx;
width: 100%;
padding: 20rpx;
image {
width: 140rpx;
height: 120rpx;
margin: 20rpx;
margin-right: 20rpx;
}
.itemList {
margin: 28rpx 10rpx;
flex: 1;
.projectName {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 16rpx;
display: flex;
align-items: center;
.status {
font-size: 24rpx;
padding: 4rpx 16rpx;
border-radius: 20rpx;
margin-left: 16rpx;
&.status-pending {
background-color: #E6F7FF;
color: #1890FF;
}
&.status-signed {
background-color: #F6FFED;
color: #52C41A;
}
&.status-completed {
background-color: #F5F5F5;
color: #666666;
}
}
}
.buyer {
font-size: 24rpx;
}
.seller {
.buyer, .seller {
font-size: 24rpx;
color: #666;
margin-top: 8rpx;
}
}
.run{
margin: auto;
margin-right: 30rpx;
height: 60rpx;
width: 60rpx;
border-radius: 50%;
border: 1px solid $uni-color;
.actions {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 16rpx;
.view-btn, .sign-btn {
display: flex;
align-items: center;
padding: 12rpx 24rpx;
border-radius: 30rpx;
background-color: #F0F7FF;
text {
color: #2979ff;
font-size: 24rpx;
margin-left: 8rpx;
}
}
.sign-btn {
background-color: #2979ff;
text, uv-icon {
color: #fff;
}
}
}
}
}
}
</style>

+ 3
- 1
pages_order/contract/contractDetail.vue View File

@ -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){


+ 157
- 44
pages_order/contract/contractManageEdit.vue View File

@ -14,7 +14,11 @@
enableUndo="true"></canvas-drag>
</view>
<view class="btn-list" v-if="imageArr.length > 0">
<view class="uni-color-btn" @tap="pro">上一页</view>
<view>{{ imagesIndex + 1 }}/{{ imageArr.length }}</view>
<view class="uni-color-btn" @tap="next">下一页</view>
</view>
<view class="btn-list">
<!-- <view class="uni-color-btn" @tap="onAddImage">新建签名</view> -->
<view class="uni-color-btn" @tap="onChangeBgImage">导入合同</view>
@ -23,6 +27,8 @@
<view class="uni-color-btn" @tap="submit">保存</view>
<!-- <view class="uni-color-btn" @tap="onExportJSON">导出模板</view> -->
<!-- <view class="uni-color-btn" @tap="onAddText">添加文字</view> -->
<view class="uni-color-btn" @tap="previewContract" v-if="form.template">预览合同</view>
</view>
</view>
</template>
@ -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)
// DOMcanvas
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(){
},
// pdfbase64
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;


+ 83
- 6
pages_order/contract/electronicSignature.vue View File

@ -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)


+ 48
- 21
utils/wxBase64src.js View File

@ -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,
};

Loading…
Cancel
Save