实现签名确认功能,支持生成签名图片并上传至服务器 添加图片预览和保存功能,优化用户交互体验 重构页面布局和样式,增加时间戳显示 集成API调用处理签名数据的获取和提交
282 lines
6.3 KiB
Vue
282 lines
6.3 KiB
Vue
<template>
|
||
<view>
|
||
<view v-if="!showSignature" style="padding-bottom: 100rpx;">
|
||
<view v-if="!zhen_url">
|
||
<view @click="openImg()">
|
||
<l-painter ref="painter">
|
||
<l-painter-image :src="imgUrl+info.yuan_image" css="width: 100%; height: 100%" />
|
||
<l-painter-image :src="signatureBase64"
|
||
css="width: 18%;position:absolute;bottom:20rpx;left:110rpx" />
|
||
<l-painter-text
|
||
css="font-size:10px;width: 100%;position:absolute;bottom:24rpx;left:300rpx">{{getFormattedTime()}}</l-painter-text>
|
||
</l-painter>
|
||
</view>
|
||
</view>
|
||
<view v-if="zhen_url">
|
||
<image @click="openImg()" :src="zhen_url" style="width: 100%;" mode="widthFix"></image>
|
||
<view style="text-align: center;margin-top: 10rpx;font-size: 20px;font-weight: 600;">↑↑↑长按图片保存↑↑↑</view>
|
||
</view>
|
||
<view v-if="info.nlinesignature_image=='' || info.nlinesignature_image==null">
|
||
<button @click="showSignature = true"
|
||
style="margin-top: 20px;background-color:#0066FF;border: #0066FF;color: #fff;width: 80%;">{{zhen_url?'重签':'签名确认'}}</button>
|
||
<button v-if="zhen_url" @click="submit()"
|
||
style="margin-top: 20px;background-color:#00CC33;border: #00CC33;color: #fff;width: 80%;">确认提交</button>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="wrapper" v-if="showSignature">
|
||
<view class="handBtn">
|
||
<button @click="fanhui()" class="fanBtn">返回</button>
|
||
<button @click="clear()" class="delBtn">清空</button>
|
||
<button @click="subCanvas()" class="previewBtn">完成</button>
|
||
</view>
|
||
<view class="handCenter">
|
||
<l-signature :penSize="10" :maxLineWidth="10" :minLineWidth="5" :openSmooth="true" ref="signatureRef"
|
||
landscape></l-signature>
|
||
</view>
|
||
<view class="handRight">
|
||
<view class="handTitle">请签名</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
getInfo,getUpdate
|
||
} from '@/utils/api.js';
|
||
export default {
|
||
data() {
|
||
return {
|
||
imgUrl: "http://qz.hschool.com.cn",
|
||
signatureBase64: '',
|
||
showSignature: false,
|
||
url: '',
|
||
info: {},
|
||
token: '',
|
||
time: '',
|
||
zhen_url: '',
|
||
}
|
||
},
|
||
onLoad(t) {
|
||
console.log(t);
|
||
this.token = t.token;
|
||
this.getContentInfo();
|
||
},
|
||
methods: {
|
||
submit() {
|
||
getUpdate({
|
||
token: this.token,
|
||
nlinesignature_image: this.zhen_url
|
||
})
|
||
.then(res => {
|
||
console.log(res);
|
||
if(res.code==1){
|
||
uni.showToast({
|
||
icon:'none',
|
||
title: '提交成功!',
|
||
duration: 2000
|
||
});
|
||
}
|
||
this.getContentInfo();
|
||
})
|
||
.catch(error => {
|
||
uni.showToast({
|
||
title: error,
|
||
duration: 2000
|
||
});
|
||
})
|
||
},
|
||
getContentInfo() {
|
||
|
||
getInfo({
|
||
token: this.token,
|
||
})
|
||
.then(res => {
|
||
console.log(res);
|
||
this.info = res.data;
|
||
this.zhen_url=res.data.nlinesignature_image;
|
||
uni.setNavigationBarTitle({
|
||
title: res.data.name
|
||
});
|
||
})
|
||
.catch(error => {
|
||
uni.showToast({
|
||
title: error,
|
||
duration: 2000
|
||
});
|
||
})
|
||
},
|
||
insImg() {
|
||
|
||
this.$refs.painter.canvasToTempFilePathSync({
|
||
// 在nvue里是jpeg
|
||
fileType: "png",
|
||
quality: 1,
|
||
success: (res) => {
|
||
//this.url = res.tempFilePath;
|
||
uni.uploadFile({
|
||
url: 'http://qz.hschool.com.cn/api/common/upload', //仅为示例,非真实的接口地址
|
||
filePath: res.tempFilePath,
|
||
name: 'file',
|
||
formData: {
|
||
'token': this.token
|
||
},
|
||
success: (uploadFileRes) => {
|
||
console.log(uploadFileRes);
|
||
var data = JSON.parse(uploadFileRes.data);
|
||
this.zhen_url = data.data.fullurl;
|
||
setTimeout(()=>{
|
||
uni.hideLoading();
|
||
}, 3000);
|
||
},
|
||
fail(re) {
|
||
console.log(re);
|
||
}
|
||
});
|
||
},
|
||
fail: (re) => {
|
||
console.log(re);
|
||
},
|
||
});
|
||
},
|
||
subCanvas() {
|
||
this.$refs.signatureRef.canvasToTempFilePath({
|
||
success: (res) => {
|
||
this.signatureBase64 = res.tempFilePath;
|
||
//console.log(res);
|
||
this.showSignature = false;
|
||
uni.showLoading({
|
||
title: '签名生成中...',
|
||
mask: true
|
||
});
|
||
setTimeout(() => {
|
||
this.insImg();
|
||
}, 1000)
|
||
}
|
||
})
|
||
},
|
||
fanhui() {
|
||
this.showSignature = false;
|
||
this.$refs.signatureRef.clear();
|
||
},
|
||
clear() {
|
||
this.$refs.signatureRef.clear();
|
||
},
|
||
openImg() {
|
||
if (this.zhen_url != '') {
|
||
uni.previewImage({
|
||
urls: [this.zhen_url],
|
||
current: 0
|
||
});
|
||
} else {
|
||
|
||
if (this.info.nlinesignature_image != '') {
|
||
uni.previewImage({
|
||
urls: [this.info.nlinesignature_image],
|
||
current: 0
|
||
});
|
||
} else {
|
||
uni.previewImage({
|
||
urls: [this.imgUrl + this.info.yuan_image],
|
||
current: 0
|
||
});
|
||
}
|
||
}
|
||
|
||
},
|
||
getFormattedTime() {
|
||
const now = new Date();
|
||
const year = now.getFullYear();
|
||
const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份补零
|
||
const day = String(now.getDate()).padStart(2, '0'); // 日期补零
|
||
const hours = String(now.getHours()).padStart(2, '0'); // 小时补零
|
||
const minutes = String(now.getMinutes()).padStart(2, '0'); // 分钟补零
|
||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
page {
|
||
background: #fbfbfb;
|
||
height: auto;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.wrapper {
|
||
width: 100%;
|
||
height: 95vh;
|
||
margin: 40rpx 0;
|
||
overflow: hidden;
|
||
display: flex;
|
||
align-content: center;
|
||
flex-direction: row;
|
||
justify-content: center;
|
||
font-size: 28rpx;
|
||
z-index: 1000000000;
|
||
}
|
||
|
||
.handWriting {
|
||
background: #fff;
|
||
width: 100%;
|
||
height: 95vh;
|
||
}
|
||
|
||
.handRight {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.handCenter {
|
||
border: 4rpx dashed #e9e9e9;
|
||
flex: 5;
|
||
overflow: hidden;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.handTitle {
|
||
transform: rotate(90deg);
|
||
flex: 1;
|
||
color: #666;
|
||
}
|
||
|
||
.handBtn button {
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.handBtn {
|
||
height: 95vh;
|
||
display: inline-flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
align-content: space-between;
|
||
flex: 1;
|
||
}
|
||
|
||
.delBtn {
|
||
position: absolute;
|
||
top: 250rpx;
|
||
left: 0rpx;
|
||
transform: rotate(90deg);
|
||
color: #666;
|
||
}
|
||
|
||
.fanBtn {
|
||
position: absolute;
|
||
top: 100rpx;
|
||
left: 0rpx;
|
||
transform: rotate(90deg);
|
||
color: #666;
|
||
}
|
||
|
||
.previewBtn {
|
||
position: absolute;
|
||
bottom: 100rpx;
|
||
left: 0rpx;
|
||
background: #008ef6;
|
||
transform: rotate(90deg);
|
||
color: #ffffff;
|
||
}
|
||
</style> |