328 lines
7.4 KiB
Vue
328 lines
7.4 KiB
Vue
<template>
|
||
<div class="signature">
|
||
<div class="inputs" v-if="!popup">
|
||
<div class="label" :class="required?'labelqr':''">{{label}}</div>
|
||
<div>
|
||
<div v-if="value" class="images">
|
||
<image @tap="toImg" class="images" mode="aspectFit" :src="value"></image>
|
||
<view v-if="!readonly" @click="toDeleteImg" class="icons">
|
||
<view class="Deletes">×</view>
|
||
</view>
|
||
</div>
|
||
<div v-if="!value && !readonly" class="explain" @click="toPop">
|
||
{{placeholder?placeholder:'点击签名'}}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<view class="bottomPopup" v-if="showPopup" @touchmove.stop.prevent="moveHandle">
|
||
<transition name="slide-up" appear>
|
||
<view class="popup-content">
|
||
<view class="popup">
|
||
<div class="hader" v-if="!isHeight">
|
||
<div @click="toclear">取消</div>
|
||
<div class="text">{{label}}</div>
|
||
<div @click="isEmpty">确定</div>
|
||
</div>
|
||
<div :class="isHeight?'wgSignatureq':'wgSignature'">
|
||
<div v-if="isHeight" key="999" style="width: 750rpx ;height: 100vh;">
|
||
<jp-signature :beforeDelay="200" :landscape="true" disableScroll ref="signatureRef" :openSmooth="openSmooth" :penSize="6" :bounding-box="boundingBox"></jp-signature>
|
||
</div>
|
||
<div v-else key="888" style="width: 750rpx ;height: 35vh;">
|
||
<jp-signature :beforeDelay="200" disableScroll ref="signatureRef" :openSmooth="openSmooth" :bounding-box="boundingBox" :penSize="3"></jp-signature>
|
||
</div>
|
||
<div v-if="!isHeight" class="appBut" >
|
||
<div class="buts" @click="undo" >撤销</div>
|
||
<div class="buts" @click="deleteImg" >清除</div>
|
||
<div class="buts" style="background-color: #55aaff;color: #fff;" @click="Tomagnify" >全屏</div>
|
||
</div>
|
||
<div v-else class="appBut" style="height: 80px;">
|
||
<div class="butx" @click="undo" >撤销</div>
|
||
<div class="butx" @click="deleteImg">清除</div>
|
||
<div class="butx" style="background-color: #55aaff;color: #fff;" @click="Tomagnify" >小屏</div>
|
||
<div class="butx" @click="toclear">取消</div>
|
||
<div class="butx" style="background-color: #E59C36;color: #fff;" @click="isEmpty">完成</div>
|
||
</div>
|
||
</div>
|
||
</view>
|
||
</view>
|
||
</transition>
|
||
</view>
|
||
|
||
</div>
|
||
</template>
|
||
<!-- 有项目需要开发的请联系 扣 - 371524845 -->
|
||
<script>
|
||
/**
|
||
* 手写签名组件
|
||
* 用于手写签名(弹框签名支持小屏和全屏)
|
||
*
|
||
*********参数********
|
||
* label 选项名称
|
||
* value 初始值String(支持bas64,url 等图片显示)
|
||
* required 是否显示必填
|
||
* placeholder 默认值
|
||
* readonly 是否只读
|
||
*
|
||
* *********回调********
|
||
* @input(e) 点击确认 e生成的图片数据(bas64)
|
||
*
|
||
*********方法********
|
||
* isEmpty() 生成图片
|
||
* deleteImg() 删除图片
|
||
*/
|
||
export default {
|
||
props: {
|
||
popup: {
|
||
type: [Boolean, String],
|
||
default: false,
|
||
},
|
||
label: {
|
||
type: String,
|
||
default: '手写签名',
|
||
},
|
||
value: {
|
||
type: String,
|
||
default: '',
|
||
},
|
||
required: {
|
||
type: [Boolean, String],
|
||
default: false,
|
||
},
|
||
placeholder: {
|
||
type: String,
|
||
default: '点击签名',
|
||
},
|
||
readonly: {
|
||
type: [Boolean, String],
|
||
default: false,
|
||
},
|
||
openSmooth: {
|
||
type: [Boolean, String],
|
||
default: true,
|
||
},
|
||
boundingBox: {
|
||
type: [Boolean, String],
|
||
default: true,
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
showPopup: false,
|
||
isHeight: false,
|
||
height1: uni.getSystemInfoSync().windowWidth / 2,
|
||
width: uni.getSystemInfoSync().windowWidth, //实时屏幕宽度
|
||
height: uni.getSystemInfoSync().windowHeight, //实时屏幕高度
|
||
showPicker: false
|
||
}
|
||
},
|
||
methods: {
|
||
moveHandle(){
|
||
|
||
},
|
||
toImg(){
|
||
this.$emit('toImg',this.value)
|
||
},
|
||
undo() {
|
||
this.$refs.signatureRef.undo()
|
||
},
|
||
toPop() {
|
||
this.showPopup = true
|
||
},
|
||
toDeleteImg() {
|
||
// #ifndef VUE3
|
||
this.$emit('input','')
|
||
// #endif
|
||
// #ifdef VUE3
|
||
this.$emit('update:value','')
|
||
// #endif
|
||
},
|
||
toclear() {
|
||
this.isHeight = false
|
||
this.showPopup = false
|
||
},
|
||
close() {
|
||
this.isHeight = false
|
||
this.showPopup = false
|
||
const {signatureRef} = this.$refs
|
||
signatureRef.clear()
|
||
},
|
||
deleteImg() {
|
||
const {signatureRef} = this.$refs
|
||
signatureRef.clear()
|
||
},
|
||
toDataURL(url) {
|
||
// #ifndef VUE3
|
||
this.$emit('input',url)
|
||
// #endif
|
||
// #ifdef VUE3
|
||
this.$emit('update:value',url)
|
||
// #endif
|
||
this.showPicker = false
|
||
},
|
||
Tomagnify() {
|
||
this.isHeight = !this.isHeight
|
||
const {signatureRef} = this.$refs
|
||
signatureRef.clear()
|
||
},
|
||
isEmpty() {
|
||
const {signatureRef} = this.$refs
|
||
signatureRef.canvasToTempFilePath({
|
||
quality: 0.8,
|
||
success: (res) => {
|
||
if (this.required) {
|
||
if (!res.isEmpty) {
|
||
// #ifndef VUE3
|
||
this.$emit('input', res.tempFilePath)
|
||
// #endif
|
||
// #ifdef VUE3
|
||
this.$emit('update:value',res.tempFilePath)
|
||
// #endif
|
||
this.$emit('change', res.tempFilePath)
|
||
this.isHeight = false
|
||
this.showPopup = false
|
||
} else {
|
||
uni.showToast({
|
||
title: '请先签名',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
} else {
|
||
// #ifndef VUE3
|
||
this.$emit('input', res.tempFilePath)
|
||
// #endif
|
||
// #ifdef VUE3
|
||
this.$emit('update:value',res.tempFilePath)
|
||
// #endif
|
||
this.$emit('change', res.tempFilePath)
|
||
this.isHeight = false
|
||
this.showPopup = false
|
||
}
|
||
|
||
}
|
||
})
|
||
},
|
||
},
|
||
beforeCreate() {},
|
||
created() {}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.wgSignatureq{
|
||
|
||
}
|
||
.appBut{
|
||
display: flex;justify-content: flex-start;align-items: center;text-align: center;height: 50px;line-height: 35px;
|
||
.buts{
|
||
color: #333;flex: 1;margin: 0 15px;background-color: #ccc;border-radius: 5px;height: 35px;
|
||
}
|
||
.butx{
|
||
color: #333;flex: 1;margin: 0 5px;background-color: #ccc;border-radius: 5px;height: 35px;
|
||
transform: rotate(90deg);
|
||
}
|
||
}
|
||
|
||
.bottomPopup {
|
||
position: fixed;
|
||
left: 0;
|
||
top: 0;
|
||
bottom: 0;
|
||
right: 0;
|
||
z-index: 999;
|
||
background-color: rgba(0, 0, 0, 0.5);
|
||
|
||
.popup-content {
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
// top: 0;
|
||
background-color: #ffffff;
|
||
}
|
||
|
||
.slide-up-enter-active,
|
||
.slide-up-leave-active {
|
||
transition: all .3s ease;
|
||
}
|
||
|
||
.slide-up-enter,
|
||
.slide-up-leave-to {
|
||
transform: translateY(100%);
|
||
}
|
||
}
|
||
|
||
.signature {
|
||
.inputs {
|
||
background-color: #fff;
|
||
padding: 10px 16px;
|
||
|
||
.label {
|
||
line-height: 35px;
|
||
position: relative;
|
||
}
|
||
|
||
.labelqr:before {
|
||
content: "*";
|
||
color: #f00;
|
||
}
|
||
|
||
.explain {
|
||
width: 100%;
|
||
background-color: #f1f1f1;
|
||
text-align: center;
|
||
line-height: 40px;
|
||
border: 1px dotted #ccc;
|
||
color: #999;
|
||
}
|
||
|
||
.Deletes {
|
||
border: 1px solid #f00;
|
||
width: 30rpx;
|
||
height: 30rpx;
|
||
border-radius: 50%;
|
||
color: #f00;
|
||
text-align: center;
|
||
font-size: 30rpx;
|
||
line-height: 30rpx;
|
||
}
|
||
}
|
||
|
||
.images {
|
||
width: 300rpx;
|
||
height: 150rpx;
|
||
position: relative;
|
||
|
||
.icons {
|
||
position: absolute;
|
||
top: 0;
|
||
right: 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
.popup {
|
||
background-color: #fff;
|
||
}
|
||
|
||
.hader {
|
||
display: flex;
|
||
justify-content: center;
|
||
text-align: center;
|
||
height: 45px;
|
||
border-bottom: 1px solid #f5f5f5;
|
||
align-items: center;
|
||
|
||
div {
|
||
text-align: center;
|
||
width: 80px;
|
||
color: #E59C36;
|
||
}
|
||
|
||
.text {
|
||
color: #333;
|
||
flex: 1;
|
||
}
|
||
}
|
||
|
||
|
||
</style> |