| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- <template>
- <view class="signature-container">
- <view class="flex justify-between items-center mb-2">
- <text class="text-sm text-gray-600">{{ title }}</text>
- <text class="text-xs text-blue-500" @click="clear">
- <text class="uni-icons uniui-trash mr-1"></text>
- 清除
- </text>
- </view>
-
- <canvas
- :id="canvasId"
- :canvas-id="canvasId"
- class="w-full rounded-lg border border-gray-200 bg-white"
- :style="{ height: height + 'px' }"
- @touchstart="touchStart"
- @touchmove="touchMove"
- @touchend="touchEnd"
- />
-
- <view v-if="hasSignature" class="mt-2 flex gap-2">
- <button class="flex-1 py-2 bg-gray-200 text-gray-700 rounded-lg text-sm" @click="clear">
- 重新签名
- </button>
- <button class="flex-1 py-2 bg-blue-500 text-white rounded-lg text-sm" @click="save">
- <text class="uni-icons uniui-checkmarkempty mr-1"></text>
- 确认签名
- </button>
- </view>
- </view>
- </template>
- <script setup lang="ts">
- import { ref, onMounted } from 'vue'
- interface Props {
- title?: string
- height?: number
- canvasId?: string
- }
- const props = withDefaults(defineProps<Props>(), {
- title: '请在下方签字',
- height: 200,
- canvasId: 'signature-canvas',
- })
- const emit = defineEmits<{
- save: [imagePath: string]
- }>()
- const hasSignature = ref(false)
- let ctx: UniApp.CanvasContext | null = null
- let isDrawing = false
- let points: { x: number; y: number }[] = []
- onMounted(() => {
- ctx = uni.createCanvasContext(props.canvasId)
- if (ctx) {
- ctx.setLineWidth(3)
- ctx.setLineCap('round')
- ctx.setLineJoin('round')
- ctx.setStrokeStyle('#333')
- }
- })
- function touchStart(e: any) {
- isDrawing = true
- const { x, y } = e.touches[0]
- points = [{ x, y }]
- ctx?.moveTo(x, y)
- }
- function touchMove(e: any) {
- if (!isDrawing) return
- const { x, y } = e.touches[0]
- points.push({ x, y })
- ctx?.lineTo(x, y)
- ctx?.stroke()
- ctx?.draw(true)
- hasSignature.value = true
- }
- function touchEnd() {
- isDrawing = false
- points = []
- }
- function clear() {
- ctx?.clearRect(0, 0, 1000, 1000)
- ctx?.draw()
- hasSignature.value = false
- }
- function save() {
- if (!hasSignature.value) {
- uni.showToast({ title: '请先签名', icon: 'none' })
- return
- }
- uni.canvasToTempFilePath({
- canvasId: props.canvasId,
- success: (res) => {
- emit('save', res.tempFilePath)
- uni.showToast({ title: '签名已保存', icon: 'success' })
- },
- fail: () => {
- uni.showToast({ title: '保存失败', icon: 'none' })
- },
- })
- }
- // 暴露方法给父组件
- defineExpose({
- clear,
- save,
- })
- </script>
|