vue实现签章
Vue 实现电子签章功能
电子签章功能通常包含绘制签名、保存签名图片、验证签名等环节。以下是基于 Vue 的实现方案:
使用 canvas 绘制签名
创建一个 Vue 组件,利用 HTML5 的 canvas 元素实现手写签名:
<template>
<div class="signature-pad">
<canvas
ref="canvas"
@mousedown="startDrawing"
@mousemove="draw"
@mouseup="stopDrawing"
@mouseleave="stopDrawing"
@touchstart="startDrawing"
@touchmove="draw"
@touchend="stopDrawing">
</canvas>
<button @click="clearSignature">清除</button>
<button @click="saveSignature">保存</button>
</div>
</template>
<script>
export default {
data() {
return {
isDrawing: false,
lastX: 0,
lastY: 0
}
},
mounted() {
this.resizeCanvas()
window.addEventListener('resize', this.resizeCanvas)
},
beforeDestroy() {
window.removeEventListener('resize', this.resizeCanvas)
},
methods: {
resizeCanvas() {
const canvas = this.$refs.canvas
canvas.width = canvas.offsetWidth
canvas.height = canvas.offsetHeight
},
startDrawing(e) {
this.isDrawing = true
const canvas = this.$refs.canvas
const rect = canvas.getBoundingClientRect()
this.lastX = (e.clientX || e.touches[0].clientX) - rect.left
this.lastY = (e.clientY || e.touches[0].clientY) - rect.top
},
draw(e) {
if (!this.isDrawing) return
const canvas = this.$refs.canvas
const ctx = canvas.getContext('2d')
const rect = canvas.getBoundingClientRect()
const currentX = (e.clientX || e.touches[0].clientX) - rect.left
const currentY = (e.clientY || e.touches[0].clientY) - rect.top
ctx.beginPath()
ctx.moveTo(this.lastX, this.lastY)
ctx.lineTo(currentX, currentY)
ctx.strokeStyle = '#000'
ctx.lineWidth = 2
ctx.lineCap = 'round'
ctx.lineJoin = 'round'
ctx.stroke()
this.lastX = currentX
this.lastY = currentY
},
stopDrawing() {
this.isDrawing = false
},
clearSignature() {
const canvas = this.$refs.canvas
const ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, canvas.width, canvas.height)
},
saveSignature() {
const canvas = this.$refs.canvas
const image = canvas.toDataURL('image/png')
this.$emit('save', image)
}
}
}
</script>
<style>
.signature-pad {
width: 100%;
max-width: 500px;
border: 1px solid #ccc;
}
canvas {
display: block;
width: 100%;
height: 200px;
background-color: #fff;
}
button {
margin-top: 10px;
padding: 5px 10px;
}
</style>
签名图片处理
保存的签名图片是 base64 编码的字符串,可以上传到服务器或直接嵌入文档:
// 在父组件中处理保存的签名
handleSaveSignature(imageData) {
// 上传到服务器
axios.post('/api/signature', { image: imageData })
.then(response => {
console.log('签名保存成功')
})
// 或者直接使用
this.signatureImage = imageData
}
使用第三方库简化实现
对于更复杂的需求,可以考虑使用现成的签名库:
-
安装 signature_pad 库:
npm install signature_pad -
在 Vue 组件中使用:
import SignaturePad from 'signature_pad'
export default { mounted() { const canvas = this.$refs.canvas this.signaturePad = new SignaturePad(canvas, { backgroundColor: 'rgba(255, 255, 255, 0)', penColor: 'rgb(0, 0, 0)' }) }, methods: { clear() { this.signaturePad.clear() }, save() { if (this.signaturePad.isEmpty()) { alert('请先签名') return } const data = this.signaturePad.toDataURL('image/png') this.$emit('save', data) } } }
#### 签名验证功能
实现简单的签名验证可以通过比较签名图片的哈希值:
```javascript
// 生成签名哈希
async function generateSignatureHash(imageData) {
const buffer = await fetch(imageData)
.then(res => res.arrayBuffer())
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer)
const hashArray = Array.from(new Uint8Array(hashBuffer))
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
}
// 比较两个签名
async function compareSignatures(sig1, sig2) {
const hash1 = await generateSignatureHash(sig1)
const hash2 = await generateSignatureHash(sig2)
return hash1 === hash2
}
注意事项
- 移动端适配需要处理 touch 事件
- 考虑添加签名时间戳和数字证书增强安全性
- 重要合同签名建议结合后端验证和区块链存证
- 签名图片建议添加水印防止篡改
以上方案提供了从基础绘制到高级验证的完整电子签章实现路径,可根据实际需求调整功能细节。







