Files
zhxg_app_v1.0/uni_modules/jp-signature/components/jp-signature-popup/jp-signature-popup.vue

328 lines
7.4 KiB
Vue
Raw Normal View History

2025-07-16 15:34:34 +08:00
<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支持bas64url 等图片显示
* 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>