Files
entityControl_mobile/pagesMine/signature.vue
2026-03-06 16:50:46 +08:00

278 lines
7.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>