Files
entityControl_mobile/pagesMine/signature.vue

278 lines
7.9 KiB
Vue
Raw Normal View History

2026-03-06 16:50:46 +08:00
<template>
<view class="box">
<canvas v-if="showCanvas" id="canvas" canvas-id="canvas" style="width: 100vw;background-color: green;" :style="`height:${canvasHeight}px`" @touchstart="startDraw" @touchmove="drawing" @@touchend="endDraw"></canvas>
<cover-view class="tipTxt">请在空白处横屏签名</cover-view>
<view class="btn">
<uv-button size="large" style="width: 50%;" @tap="clearSign"> </uv-button>
<uv-button type="primary" size="large" class="mainBtn" style="width: 50%;" @tap="confirm"> </uv-button>
</view>
</view>
</template>
<script setup>
import { onReady, onUnload } from '@dcloudio/uni-app';
import { ref, nextTick } from 'vue';
import { pathToBase64, base64ToPath } from './index.js'
import { uploadImg } from "@/api/upload"
const btnHeight = ref(null)
const BoxHeight = ref(null)
const canvasWidth = ref(null)
const canvasHeight = ref(null)
const showCanvas = ref(false)
const signFlag = ref(false)
const getBtnHeight = () => {
const query = uni.createSelectorQuery().in(this);
// 选择要查询的元素使用元素ID或类名
query.select('.btn').boundingClientRect(data => {
btnHeight.value = data.height
}).select('.box').boundingClientRect(res => {
// console.log('元素高度:', res);
// BoxHeight.value = res.height
// canvasWidth.value = res.width
}).exec(() => {
// 确保两个查询都完成后再初始化画布
if (btnHeight.value && BoxHeight.value && canvasWidth.value) {
console.log("获取",BoxHeight.value,btnHeight.value);
canvasHeight.value = BoxHeight.value - btnHeight.value
showCanvas.value = true
// 等待DOM更新完成后再初始化Canvas
nextTick(() => {
initCanvas();
});
} else {
console.error('获取元素尺寸失败,无法初始化画布');
}
}); // 执行查询
}
let canvasContext = null
const initCanvas = () => {
console.log(canvasWidth.value, canvasHeight.value)
canvasContext = uni.createCanvasContext('canvas');
canvasContext.setFillStyle('#F5F5F5'); // 设置填充颜色为红色
canvasContext.fillRect(0, 0, canvasWidth.value, canvasHeight.value); // 填充整个画板
canvasContext.draw(true)
}
const startX = ref(null)
const startY = ref(null)
const startDraw = (e) => {
startX.value = e.touches[0].x
startY.value = e.touches[0].y
canvasContext.beginPath(); // 开始创建一个路径
signFlag.value = true
}
const endDraw = (e) => {
startX.value = 0
startY.value = 0
}
const drawing = (e) => {
let temX = e.touches[0].x;
let temY = e.touches[0].y;
canvasContext.moveTo(startX.value, startY.value)
canvasContext.lineTo(temX, temY)
canvasContext.setStrokeStyle('#000') // 文字颜色
canvasContext.setLineWidth(4) // 文字宽度
canvasContext.setLineCap('round') // 文字圆角
canvasContext.stroke() // 文字绘制
startX.value = temX
startY.value = temY
canvasContext.draw(true) // 文字绘制到画布中
}
const clearSign = () => {
canvasContext.setFillStyle('#F5F5F5'); // 设置填充颜色为红色
canvasContext.fillRect(0, 0, canvasWidth.value, canvasHeight.value); // 填充整个画板
canvasContext.draw(true) // 文字绘制到画布中
signFlag.value = false
}
const confirm = () => {
// 确认按钮事件
if (!signFlag.value) {
uni.showToast({
title: '请签名后再点击确定',
icon: 'none',
duration: 2000
})
return
}
uni.showModal({
title: '确认',
content: '确认签名无误吗',
showCancel: true,
success: async ({ confirm }) => {
if (confirm) {
let tempFile
// if (this.horizontal) {
tempFile = await saveHorizontalCanvas()
// } else {
// tempFile = await this.saveCanvas()
// }
console.log(tempFile, "tempFile")
const base64 = await pathToBase64(tempFile)
const path = await base64ToPath(base64)
console.log(path, "path")
const res = await uploadImg(path, {});
uni.navigateBack();
uni.$emit('getSignImg', { base64, path, url: res.url });
// uploadImg(path, {}).then(res=>{
// console.log(base64, path, res.url, "打印")
// let url = res.url
// uni.$emit('getSignImg', { base64, path, url })
// uni.navigateBack()
// })
}
}
})
}
const saveHorizontalCanvas = async () => {
return await new Promise((resolve, reject) => {
uni.canvasToTempFilePath(
{
canvasId: 'canvas',
fileType: "png", // 只支持png和jpg
success: (res) => {
if (!res.tempFilePath) {
uni.showModal({
title: '提示',
content: '保存签名失败',
showCancel: false
})
return
}
// #ifdef APP
uni.compressImage({
src: res.tempFilePath,
quality: 100, // 范围 0 - 100
rotate: 270,
success: (r) => {
console.log('==== compressImage :', r)
resolve(r.tempFilePath)
}
})
// #endif
// #ifndef APP
// uni.getImageInfo({
// src: res.tempFilePath,
// success: (r) => {
// // console.log('==== getImageInfo :', r)
// // 将signCanvas的内容复制到hsignCanvas中
// const hcanvasCtx = uni.createCanvasContext('hsignCanvas', this)
// // 横屏宽高互换
// hcanvasCtx.translate(this.canvasHeight / 2, this.canvasWidth / 2)
// hcanvasCtx.rotate(Math.PI * (-90 / 180))
// hcanvasCtx.drawImage(
// r.path,
// -this.canvasWidth / 2,
// -this.canvasHeight / 2,
// this.canvasWidth,
// this.canvasHeight
// )
// hcanvasCtx.draw(false, async () => {
// const hpathRes = await uni.canvasToTempFilePath(
// {
// canvasId: 'hsignCanvas',
// fileType: this.expFile.fileType, // 只支持png和jpg
// quality: this.expFile.quality // 范围 0 - 1
// },
// this
// )
// let tempFile = ''
// if (Array.isArray(hpathRes)) {
// hpathRes.some((item) => {
// if (item) {
// tempFile = item.tempFilePath
// return
// }
// })
// } else {
// tempFile = hpathRes.tempFilePath
// }
// resolve(tempFile)
// })
// }
// })
// #endif
},
fail: (err) => {
console.log('图片生成失败:' + err)
resolve(false)
}
},
this
)
})
}
onReady(() => {
// uni.showLoading({
// title: '正在加载,请稍后...',
// mask: true
// })
// 页面加载完成后设置横屏
// plus.screen.lockOrientation('landscape-primary')
// nextTick(() => {
// getBtnHeight();
// });
// setTimeout(() => {
// uni.hideLoading();
uni.getSystemInfo({
success: function (res) {
console.log(res)
BoxHeight.value = res.windowHeight
canvasWidth.value = res.windowWidth
}
});
getBtnHeight();
// }, 1500);
// nextTick(() => {
// getBtnHeight();
// });
})
onUnload(() => {
// 页面卸载时恢复竖屏
// plus.screen.lockOrientation('portrait-primary');
})
</script>
<style scoped lang="scss">
.box {
position: relative;
width: 100vw;
height: 100vh;
.tipTxt{
position: absolute;
top: 10rpx;
left: 10rpx;
color: #999;
font-size: 44rpx;
}
.btn {
position: fixed;
width: 100vw;
bottom: 0;
z-index: 99;
display: flex;
align-items: center;
justify-content: space-between;
}
}
</style>