2024-04-28 10:10:03 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view>
|
|
|
|
|
|
<view class="w-form-input-rv" v-if="readonly">
|
|
|
|
|
|
<image v-if="(_value || '') !== ''" :src="_value" mode="aspectFit" style="width: 250rpx; height: 150rpx;">
|
|
|
|
|
|
</image>
|
|
|
|
|
|
<text v-else style="color: #8b8b8b;">未签字</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-else-if="(props.modelValue || '').length < 10" @click="show"
|
|
|
|
|
|
class="w-sign-init">
|
|
|
|
|
|
<uni-icons type="compose" color="#B3B3B3" size="20"></uni-icons>
|
|
|
|
|
|
<text>{{formProps.placeholder ? formProps.placeholder:'点击签名'}}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-else>
|
|
|
|
|
|
<image :src="_value" mode="aspectFit" style="width: 250rpx; height: 150rpx;"
|
|
|
|
|
|
@click="show"></image>
|
|
|
|
|
|
<text>点击签名重签</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<uni-popup v-if="!readonly" ref="signatureRef">
|
|
|
|
|
|
<view class="w-sign" :style="{height: wheight + 'px'}">
|
|
|
|
|
|
<view>
|
|
|
|
|
|
<text class="w-sign-tip">请签字</text>
|
|
|
|
|
|
<l-signature ref="SignPanel" v-if="showPanel" class="w-sign-panel"
|
|
|
|
|
|
disableScroll :landscape="true" :beforeDelay="300" :maxLineWidth="10"
|
|
|
|
|
|
:penSize="formProps.thickness + 3" :penColor="formProps.color" :openSmooth="true">
|
|
|
|
|
|
</l-signature>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view :class="{'w-sign-opration': true, 'w-landscape': landscape}">
|
|
|
|
|
|
<view @click="SignPanel.clear()" hover-class="w-sop">
|
|
|
|
|
|
<uni-icons type="trash" color="#E79467" :size="30"></uni-icons>
|
|
|
|
|
|
<text style="color: #E79467;">清空</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view @click="SignPanel.undo()" hover-class="w-sop">
|
|
|
|
|
|
<uni-icons type="undo" color="#5B6AF7" :size="30"></uni-icons>
|
|
|
|
|
|
<text>撤销</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view @click="SignPanel.redo()" hover-class="w-sop">
|
|
|
|
|
|
<uni-icons type="redo" color="#5B6AF7" :size="30"></uni-icons>
|
|
|
|
|
|
<text>恢复</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view @click="save" hover-class="w-sop">
|
|
|
|
|
|
<uni-icons type="checkmarkempty" color="#5B6AF7" :size="30"></uni-icons>
|
|
|
|
|
|
<text>保存</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view @click="signatureRef.close()" hover-class="w-sop">
|
|
|
|
|
|
<uni-icons type="closeempty" color="#8b8b8b" :size="30"></uni-icons>
|
|
|
|
|
|
<text style="color: #8b8b8b;">关闭</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</uni-popup>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import { ref, computed, getCurrentInstance } from 'vue'
|
|
|
|
|
|
import { compressBase64Image } from "@/utils/imageUtil";
|
|
|
|
|
|
import { BASE_URL } from '@/api/request.js'
|
|
|
|
|
|
import { base64ToPath } from '@/uni_modules/lime-signature/components/l-signature/utils.js'
|
|
|
|
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
|
formProps: {
|
|
|
|
|
|
type: Object,
|
|
|
|
|
|
default: () => {
|
|
|
|
|
|
return {}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
modelValue: String,
|
|
|
|
|
|
readonly: Boolean,
|
|
|
|
|
|
position: {
|
|
|
|
|
|
type: String,
|
|
|
|
|
|
default: 'right'
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const wheight = uni.getSystemInfoSync().windowHeight
|
|
|
|
|
|
|
|
|
|
|
|
const _value = computed({
|
|
|
|
|
|
get() {
|
|
|
|
|
|
return props.modelValue
|
|
|
|
|
|
},
|
|
|
|
|
|
set(val) {
|
|
|
|
|
|
emits('update:modelValue', val)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const emits = defineEmits(['update:modelValue'])
|
|
|
|
|
|
|
|
|
|
|
|
const signatureRef = ref()
|
|
|
|
|
|
const SignPanel = ref()
|
|
|
|
|
|
|
|
|
|
|
|
const landscape = ref(true)
|
|
|
|
|
|
const showPanel = ref(false)
|
|
|
|
|
|
|
|
|
|
|
|
function show(){
|
|
|
|
|
|
signatureRef.value.open(props.position)
|
|
|
|
|
|
showPanel.value = true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function save(call) {
|
|
|
|
|
|
SignPanel.value.canvasToTempFilePath({
|
|
|
|
|
|
quality: 0.2,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
// 是否为空画板 无签名
|
|
|
|
|
|
if (res.isEmpty) {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
title: '您没有签字哦'
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log('签字图片路径',res.tempFilePath)
|
|
|
|
|
|
if(res.tempFilePath.startsWith('data:image/')){
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
const file = base64ToFile(res.tempFilePath, `${new Date().getTime()}.png`)
|
|
|
|
|
|
uploadSign(file)
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
// #ifndef H5
|
|
|
|
|
|
base64ToPath(res.tempFilePath).then(tp => {
|
|
|
|
|
|
uploadSign(null, tp)
|
|
|
|
|
|
})
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
}else {
|
|
|
|
|
|
uploadSign(null, res.tempFilePath)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function uploadSign(file, filePath) {
|
|
|
|
|
|
uni.uploadFile({
|
|
|
|
|
|
url: `${BASE_URL}/wflow/res`,
|
2024-05-25 13:53:36 +08:00
|
|
|
|
header: {
|
|
|
|
|
|
//大家在这里传自定义的token,这里默认wflow的
|
|
|
|
|
|
Authorization: "Bearer " + uni.getStorageSync('wflow-token'),
|
|
|
|
|
|
TenantId: JSON.parse(uni.getStorageSync("loginUser")).sn
|
|
|
|
|
|
},
|
2024-04-28 10:10:03 +08:00
|
|
|
|
filePath: filePath,
|
|
|
|
|
|
file: file,
|
|
|
|
|
|
name: 'file',
|
|
|
|
|
|
formData: {
|
|
|
|
|
|
isImg: 'true',
|
|
|
|
|
|
isSign: 'true'
|
|
|
|
|
|
},
|
|
|
|
|
|
success: (rsp) => {
|
|
|
|
|
|
if (rsp.statusCode === 200) {
|
|
|
|
|
|
const img = JSON.parse(rsp.data)
|
2024-05-25 13:53:36 +08:00
|
|
|
|
// _value.value = `${BASE_URL}/wflow/res/${img.id}?isSign=true`
|
|
|
|
|
|
_value.value = `${BASE_URL}/image/${img.id}?isSign=true`
|
|
|
|
|
|
// openLocalFile(file.name, `${BASE_URL}/image/${file.id}?name=${file.name}`)
|
2024-04-28 10:10:03 +08:00
|
|
|
|
signatureRef.value.close()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
title: '签名失败:' + rsp.data
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.log(err)
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
title: '签名上传异常'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function base64ToFile(base64, name) {
|
|
|
|
|
|
if (typeof base64 != 'string') {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
var arr = base64.split(',')
|
|
|
|
|
|
var type = arr[0].match(/:(.*?);/)
|
|
|
|
|
|
if (type && type.length > 1) {
|
|
|
|
|
|
type = type[1]
|
|
|
|
|
|
}else{
|
|
|
|
|
|
type = 'image/png'
|
|
|
|
|
|
}
|
|
|
|
|
|
var fileExt = type.split('/')[1]
|
|
|
|
|
|
var bstr = atob(arr[1])
|
|
|
|
|
|
var n = bstr.length
|
|
|
|
|
|
var u8arr = new Uint8Array(n)
|
|
|
|
|
|
while (n--) {
|
|
|
|
|
|
u8arr[n] = bstr.charCodeAt(n)
|
|
|
|
|
|
}
|
|
|
|
|
|
return new File([u8arr], `${name}.` + fileExt, {
|
|
|
|
|
|
type: type
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
|
|
|
.w-sop {
|
|
|
|
|
|
background-color: #e5e5e5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.w-sign-init {
|
|
|
|
|
|
padding: 16rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
color: #a7a7a7;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
background-color: #F7F7F7;
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.w-sign-panel {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.w-sign {
|
|
|
|
|
|
width: 100vw;
|
|
|
|
|
|
//height: 100vh;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
background-color: white;
|
|
|
|
|
|
|
|
|
|
|
|
.w-sign-tip {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
transform: rotate(90deg);
|
|
|
|
|
|
color: #CDCDCD;
|
|
|
|
|
|
font-size: 64rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&>view:first-child {
|
|
|
|
|
|
width: 80%;
|
|
|
|
|
|
height: 80%;
|
|
|
|
|
|
border: 2px dashed #CDCDCD;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
background-color: #F6F6F6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.w-sign-opration {
|
|
|
|
|
|
background-color: white;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
|
|
|
|
view {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
color: #5B6AF7;
|
|
|
|
|
|
margin: 10px;
|
|
|
|
|
|
transform: rotate(90deg);
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|