|
|
@@ -0,0 +1,120 @@
|
|
|
+<template>
|
|
|
+ <div class="signature-wrapper">
|
|
|
+ <canvas
|
|
|
+ ref="canvas"
|
|
|
+ :width="width"
|
|
|
+ :height="height"
|
|
|
+ class="signature-canvas"
|
|
|
+ ></canvas>
|
|
|
+ <div class="signature-actions">
|
|
|
+ <el-button size="small" type="primary" @click="save">保存签名</el-button>
|
|
|
+ <el-button size="small" @click="clear">{{ clearButtonText }}</el-button>
|
|
|
+ </div>
|
|
|
+ <div v-if="preview" class="signature-preview">
|
|
|
+ <p>签名预览:</p>
|
|
|
+ <img :src="preview" alt="签名" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import SignaturePad from 'signature_pad'
|
|
|
+// import SignaturePad from 'signature_pad/dist/signature_pad.min.js'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'SignaturePad',
|
|
|
+ props: {
|
|
|
+ modelValue: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ width: {
|
|
|
+ type: Number,
|
|
|
+ default: 500
|
|
|
+ },
|
|
|
+ height: {
|
|
|
+ type: Number,
|
|
|
+ default: 200
|
|
|
+ },
|
|
|
+ penColor: {
|
|
|
+ type: String,
|
|
|
+ default: '#000'
|
|
|
+ },
|
|
|
+ backgroundColor: {
|
|
|
+ type: String,
|
|
|
+ default: '#fff'
|
|
|
+ },
|
|
|
+ clearButtonText: {
|
|
|
+ type: String,
|
|
|
+ default: '清空签名'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ signaturePad: null,
|
|
|
+ preview: this.modelValue
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ const canvas = this.$refs.canvas
|
|
|
+ const ctx = canvas.getContext('2d')
|
|
|
+ ctx.fillStyle = this.backgroundColor
|
|
|
+ ctx.fillRect(0, 0, this.width, this.height)
|
|
|
+
|
|
|
+ this.signaturePad = new SignaturePad(canvas, {
|
|
|
+ penColor: this.penColor,
|
|
|
+ backgroundColor: this.backgroundColor
|
|
|
+ })
|
|
|
+
|
|
|
+ this.signaturePad.onEnd = () => {
|
|
|
+ const dataUrl = this.signaturePad.toDataURL()
|
|
|
+ this.preview = dataUrl
|
|
|
+ this.$emit('update:modelValue', dataUrl)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ clear() {
|
|
|
+ this.signaturePad.clear()
|
|
|
+ this.preview = ''
|
|
|
+ this.$emit('update:modelValue', '')
|
|
|
+ },
|
|
|
+ save() {
|
|
|
+ if (this.signaturePad.isEmpty()) {
|
|
|
+ this.$message.warning('请先签名')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const dataUrl = this.signaturePad.toDataURL()
|
|
|
+ this.preview = dataUrl
|
|
|
+ this.$emit('update:modelValue', dataUrl)
|
|
|
+ this.$message.success('签名已保存')
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>.signature-wrapper {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+}
|
|
|
+
|
|
|
+.signature-canvas {
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: crosshair;
|
|
|
+}
|
|
|
+
|
|
|
+.signature-actions {
|
|
|
+ margin-top: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.signature-preview {
|
|
|
+ margin-top: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.signature-preview img {
|
|
|
+ border: 1px solid #ddd;
|
|
|
+ max-width: 100%;
|
|
|
+ height: auto;
|
|
|
+}
|
|
|
+</style>
|