npm install qrcodejs2
npm install signature_pad
在移动端需要安装 vant和jquery
npm install vant
npm install jquery
<template>
<div v-loading="loading" class="dashboard-container">
<div v-if="imgState" class="autograph-wrapper">
<img :src="src" alt>
<el-button size="small" type="primary" @click="resetClick">修改签名</el-button>
</div>
<div v-else class="qrcode-wrapper">
<div id="qrcode" ref="qrCode" class="qrcode" />
<p class="qrcode-wrapper-codeText">{{ qrcodeText }}</p>
</div>
</div>
</template>
<script>
import QRCode from 'qrcodejs2'
import { getSignature } from '@/api/audit'
import { getToken } from '@/utils/auth'
export default {
data() {
return {
src: '',
token: getToken(),
// 在服务上页面的地址路径
qrcodeUrl:process.env.VUE_APP_URL + '*******/audit/signature',
qrcodeText: '您尚未进行签名,请手机扫描以下二维码,完善个人签名信息。',
imgState: false,
code: null,
loading: false
}
},
mounted() {
// 查询个人签名
this.getAtograph()
},
methods: {
// 查询个人签名
async getAtograph() {
this.imgState = false
this.crateQrcode()
this.loading = true
const res = await getSignature()
if (res.code == '-1') {
this.imgState = false
this.code ? '' : this.crateQrcode()
} else {
this.imgState = true
this.src = res.response.image
}
this.loading = false
},
// 二维码
crateQrcode() {
this.$nextTick(() => {
this.code = new QRCode(this.$refs.qrCode, {
width: 160,
height: 160, // 高度
text: this.qrcodeUrl, // 二维码内容
background: '#f0f',
foreground: '#ff0'
})
})
},
// 修改签名
resetClick() {
this.imgState = false
this.qrcodeText = '请手机扫描以下二维码,修改个人签名信息。'
this.crateQrcode()
}
}
}
</script>
<style scoped lang="scss">
.dashboard-container {
font-size: 14px;
padding: 20px 0;
margin: 0 20px;
.autograph-wrapper {
position: relative;
width: 234px;
height: 260px;
margin: 40px auto;
border: 1px solid #dddd;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
img {
width: 100%;
height: 100%;
// width: 700px;
margin: 0 auto;
display: block;
}
.el-button {
position: absolute;
bottom: -50px;
left: 50%;
transform: translateX(-50%);
}
}
.qrcode-wrapper {
position: relative;
width: 234px;
height: 280px;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
padding: 40px;
margin-top: 80px;
box-sizing: border-box;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
#qrcode {
margin: 0 auto 10px;
width: 160px;
}
.qrcode-wrapper-codeText {
text-align: center;
color: #2d61ad;
}
}
}
</style>
移动端页面
<template>
<div id="signature-pad" class="signature-pad" :style="{'max-height':maxHeight}">
<div>
<div class="signature-pad--body">
<canvas id="signature-canvas" :width="width" :height="height" />
<i class="leftup lefta" />
<i class="leftup rightup" />
<i class="leftup leftdown" />
<i class="leftup rightdown" />
</div>
<div class="signature-pad--footer">
<p @click="saveButton">
<span>确定</span>
</p>
<p @click="cancelButton">
<span>重签</span>
</p>
</div>
</div>
</div>
</template>
<script>
import $ from 'jquery'
import SignaturePad from 'signature_pad'
import { autograph } from '@/api/audit'
import Vue from 'vue'
import 'vant/lib/index.css'
import { Dialog } from 'vant'
// 全局注册
Vue.use(Dialog)
export default {
name: 'Signature',
data() {
return {
signaturePad: '',
canvas: '',
width: '',
height: '',
maxHeight: '',
buttonState: false
}
},
watch: {},
mounted() {
this.canvas = document.querySelector('canvas')
const signaturePad = new SignaturePad(this.canvas)
this.signaturePad = signaturePad
/* */
this.height = $(window).height()
this.width = $(window).width()
this.maxHeight = this.height
signaturePad.penColor = 'rgb(0, 0, 0)'
signaturePad.backgroundColor = 'rgb(255, 255, 255)'
this.resizeCanvas()
window.onresize = () => {
this.resizeCanvas()
}
},
methods: {
// 保存个人签名
async postAutograph(val) {
this.tableLoading = true
const params = {
file: val
}
/* eslint-disable no-undef */
var res = await autograph(params)
if (res.code == 0) {
Dialog.alert({
title: '提示',
message: '个人签名提交成功,点击确定关闭页面。'
}).then(() => {
this.buttonState = true
WeixinJSBridge.call('closeWindow')
window.AlipayJSBridge.call('closeWebview')
})
}
},
saveButton() {
if (this.buttonState == true) {
// 重复提交签名
Dialog.alert({
title: '提示',
message: '个人签名不能重复提交。'
})
} else {
// 未提交签名
// 签名为空的判断
if (this.signaturePad.isEmpty()) {
Dialog.alert({
title: '提示',
message: '个人签名不能为空'
})
} else {
const ctx = this.canvas.getContext('2d')
const imageData = ctx.getImageData(
0,
0,
this.canvas.width,
this.canvas.height
)
for (var i = 0; i < imageData.data.length; i += 4) {
// 当该像素是透明的,则设置成白色
if (imageData.data[i + 3] == 0) {
imageData.data[i] = 255
imageData.data[i + 1] = 255
imageData.data[i + 2] = 255
imageData.data[i + 3] = 255
}
}
ctx.putImageData(imageData, 0, 0)
// 使用canvas的toDataURL方法返回一个包含图片展示的 data URI
const data = this.signaturePad.toDataURL('image/jpeg')
this.postAutograph(data)
}
}
},
cancelButton() {
this.signaturePad.clear()
},
resizeCanvas() {
const ratio = Math.max(window.devicePixelRatio || 1, 1)
this.canvas.width = this.canvas.offsetWidth * ratio
this.canvas.height = this.canvas.offsetWidth * ratio
this.canvas.getContext('2d').scale(ratio, ratio)
this.signaturePad.clear() // otherwise isEmpty() might return incorrect value
}
}
}
</script>
<style scoped lang="scss">
.signature-pad,
.signature-pad--body {
height: 90%;
}
.signature-pad {
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
width: 100%;
height: 100%;
background: #fff;
font-size: 10px;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
.signature-pad--body {
position: absolute;
right: 0;
width: 85%;
height: 100%;
}
.signature-pad--body canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
// border-radius: 4px;
// box-shadow: 0 0 5px rgba(0, 0, 0, 0.02) inset;
}
.signature-pad--footer {
width: 15%;
position: absolute;
left: 0;
height: 100%;
p {
left: 10px;
padding: 26px 2px;
position: absolute;
bottom: 220px;
color: #fff;
background-color: #2d61ad;
border-color: #2d61ad;
border-radius: 7px;
span {
font-size: 15px;
transform: rotate(90deg);
display: block;
color: #fff;
}
&:last-child {
bottom: 100px;
background-color: #fff;
border: 1px solid #ccc;
span {
color: #828282;
}
}
}
}
</style>