<template>
  <div class="signature-container">
    <canvas
        ref="canvasRef"
        @mousedown="startDrawing"
        @mousemove="draw"
        @mouseup="stopDrawing"
        @mouseleave="stopDrawing"
        @touchstart.prevent="startDrawing"
        @touchmove.prevent="draw"
        @touchend.prevent="stopDrawing"
    ></canvas>
    <div class="actions">
      <el-button size="small" @click="clear">重签</el-button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'

const canvasRef = ref<HTMLCanvasElement | null>(null)
const isDrawing = ref(false)
const ctx = ref<CanvasRenderingContext2D | null>(null)

// 初始化 Canvas
onMounted(() => {
  if (canvasRef.value) {
    const canvas = canvasRef.value
    // 设置画布大小 (可以根据父容器调整)
    canvas.width = canvas.offsetWidth
    canvas.height = 300 // 固定高度
    ctx.value = canvas.getContext('2d')
    if (ctx.value) {
      ctx.value.lineWidth = 3
      ctx.value.lineCap = 'round'
      ctx.value.strokeStyle = '#000'
    }
  }
})

// 获取坐标 (兼容鼠标和触摸)
const getPos = (e: MouseEvent | TouchEvent) => {
  const canvas = canvasRef.value
  if (!canvas) return { x: 0, y: 0 }

  const rect = canvas.getBoundingClientRect()
  let clientX, clientY

  if ('touches' in e) {
    clientX = e.touches[0].clientX
    clientY = e.touches[0].clientY
  } else {
    clientX = (e as MouseEvent).clientX
    clientY = (e as MouseEvent).clientY
  }

  return {
    x: clientX - rect.left,
    y: clientY - rect.top
  }
}

const startDrawing = (e: MouseEvent | TouchEvent) => {
  isDrawing.value = true
  const { x, y } = getPos(e)
  ctx.value?.beginPath()
  ctx.value?.moveTo(x, y)
}

const draw = (e: MouseEvent | TouchEvent) => {
  if (!isDrawing.value) return
  const { x, y } = getPos(e)
  ctx.value?.lineTo(x, y)
  ctx.value?.stroke()
}

const stopDrawing = () => {
  isDrawing.value = false
}

const clear = () => {
  if (canvasRef.value && ctx.value) {
    ctx.value.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)
  }
}

/**
 * 导出签名为 File 对象
 */
const generateFile = (): Promise<File | null> => {
  return new Promise((resolve) => {
    if (!canvasRef.value) {
      resolve(null)
      return
    }
    canvasRef.value.toBlob((blob) => {
      if (blob) {
        const file = new File([blob], `sign_${Date.now()}.png`, { type: 'image/png' })
        resolve(file)
      } else {
        resolve(null)
      }
    }, 'image/png')
  })
}

// 暴露方法给父组件
defineExpose({
  clear,
  generateFile
})
</script>

<style scoped>
.signature-container {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  background: #f5f7fa;
  position: relative;
  width: 100%;
}
canvas {
  display: block;
  width: 100%; /* 响应式宽度 */
  height: 300px;
  cursor: crosshair;
  background: #fff;
}
.actions {
  position: absolute;
  bottom: 10px;
  right: 10px;
}
</style>