From e1b028d486713eaf55aaf35fbf334aa568059c0d Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期二, 14 四月 2026 15:46:54 +0800
Subject: [PATCH] 项目复制

---
 src/views/components/Signature.vue |  261 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 261 insertions(+), 0 deletions(-)

diff --git a/src/views/components/Signature.vue b/src/views/components/Signature.vue
new file mode 100644
index 0000000..7d1bf71
--- /dev/null
+++ b/src/views/components/Signature.vue
@@ -0,0 +1,261 @@
+<template>
+  <div class="signature">
+    <el-row justify="space-between">
+      <el-text>绛惧悕</el-text>
+      <el-text v-if="imageUrl" @click="imageUrl=''">娓呴櫎绛惧悕</el-text>
+      <el-text v-else @click="signatureDialog=true">鐐瑰嚮绛惧悕</el-text>
+    </el-row>
+    <el-image v-if="imageUrl" :src="imageUrl"></el-image>
+    <div v-else class="image-slot"></div>
+
+    <el-dialog 
+      v-model="signatureDialog" 
+      fullscreen 
+      :show-close="false"
+      class="p-0"
+    >
+      <div class="signature_content p-4" :class="{'rotate_90': xsOnly}" ref="signBox" @click="endMove">
+        <el-row justify="space-between">
+          <el-col :span="3"></el-col>
+          <el-col :span="18">
+            <el-row justify="center">
+              <el-text class=" text-xl font-bold">鎵嬪啓绛惧悕</el-text>
+            </el-row>
+          </el-col>
+          <el-col :span="3">
+            <el-row justify="end">
+              <el-button text @click="signatureDialog=false">
+                <Icon icon="material-symbols:close-rounded" width="24" height="24"  style="color: black" />
+              </el-button>
+            </el-row>
+          </el-col>
+        </el-row>
+        <div class="canvas_box_normal">
+          <canvas ref="signCanvas" style="background-color: white;"></canvas>
+        </div>
+        <el-row justify="end">
+          <el-button @click="clearCanvas()">閲嶇疆</el-button>
+          <el-button type="primary" @click="confirm()">
+            纭畾
+          </el-button>
+        </el-row>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { useWindowSize } from '@/utils/hook.js'
+import { uploadByBase64 } from '@/utils/tool.js';
+export default {
+  setup() {
+    const { width, height } = useWindowSize()
+    return { width, height }
+  },
+  data() {
+    return {
+      imageUrl: '',
+      signatureDialog: false,
+      editCanvas: null,
+      startDrawFlag: false,
+      drawingFlag: false,
+      canvasMarginY: 12,
+      canvasMarginX: 12,
+      flag: false
+    }
+  },
+  props: {
+    modelValue: {
+      type: String,
+      default: ''
+    }
+  },
+  computed: {
+    xsOnly: function() {
+      return this.width <= 576
+    }
+  },
+  watch: {
+    modelValue: function(val) {
+      this.imageUrl = val
+    },
+    width: function(){
+      this.initMobileStyle()
+    },
+    height: function(){
+      this.updateCanvasMargin()
+    },
+    xsOnly: function(){
+      this.updateCanvasMargin()
+    },
+    signatureDialog: function(val) {
+      if (val) {
+        this.$nextTick(() => {
+          this.initSignCanvas()
+        })
+      } else {
+        this.clearCanvas()
+      }
+    },
+  },
+  methods: {
+    initSignCanvas: function(){
+      if (this.editCanvas || !this.$refs.signCanvas) return true
+      
+      this.editCanvas = this.$refs.signCanvas
+
+      this.initMobileStyle()
+
+      this.initCanvasStyle()
+
+      this.initCanvasEvent()
+
+      this.updateCanvasMargin()
+    },
+    initMobileStyle: function(){
+      if (!this.xsOnly) return false
+      
+      this.$refs.signBox.style.transformOrigin = `${(window.innerWidth / 2 / window.innerHeight) * 100}%`
+    },
+    initCanvasStyle: function(){
+      let parentW = this.editCanvas.parentElement.offsetWidth - 16
+      let parentH = this.editCanvas.parentElement.offsetHeight - 48
+
+      let canvasW = Math.min(parentH * 3, 720)
+      let canvasH = Math.min(parentW / 3, 240)
+      if (canvasH > parentH) {
+        this.editCanvas.width = canvasW
+        this.editCanvas.height = canvasW / 3
+      } else {
+        this.editCanvas.height = canvasH
+        this.editCanvas.width = canvasH * 3
+      }
+    },
+    initCanvasEvent: function(){
+      this.editCanvas.onmousedown = this.startMove
+      this.editCanvas.onmousemove = this.moving
+      this.editCanvas.onmouseup = this.endMove
+      this.editCanvas.ontouchstart = this.startMove
+      this.editCanvas.ontouchmove = this.moving
+      this.editCanvas.ontouchend = this.endMove
+    },
+    updateCanvasMargin: function(){
+      this.canvasMarginY = (this.editCanvas.parentElement.offsetHeight - this.editCanvas.height) / 2
+      this.canvasMarginX = (this.editCanvas.parentElement.offsetWidth - this.editCanvas.width) / 2
+    },
+    startMove: function(event){
+      this.drawingFlag = true
+      
+      let { x, y } = this.getPosition(event)
+      let cxt = this.editCanvas.getContext('2d')
+      cxt.lineWidth = Math.max(this.editCanvas.width / 240, 2)
+      cxt.beginPath()
+      cxt.moveTo(x, y)
+      event.preventDefault()
+    },
+    moving: function(event){
+      if (!this.drawingFlag) return
+
+      this.startDrawFlag = true
+
+      let { x, y } = this.getPosition(event)
+      let cxt = this.editCanvas.getContext('2d')
+      cxt.lineTo(x, y)
+      cxt.stroke()
+      event.preventDefault()
+    },
+    getPosition: function(event){
+      let x, y
+      let touches = event.touches || event.targetTouches || [{}]
+      let positionX = touches[0].clientX || event.clientX
+      let positionY = touches[0].clientY || event.clientY
+      if (this.xsOnly) {
+        x = positionY - this.canvasMarginX
+        y = window.innerWidth - positionX - 48 - this.canvasMarginY
+      } else {
+        x = positionX - this.canvasMarginX - 16
+        y = positionY - this.canvasMarginY - 48
+      }
+      return { x, y }
+    },
+    endMove: function(){
+      this.drawingFlag = false
+    },
+    clearCanvas: function(){
+      this.startDrawFlag = false
+      let cxt = this.editCanvas.getContext('2d')
+      cxt.clearRect(0, 0, this.editCanvas.width, this.editCanvas.height);
+    },
+    async confirm() {
+      if (!this.startDrawFlag) {
+        this.$message.error('璇峰厛绛惧悕锛�')
+        return
+      }
+      let base64 = this.editCanvas.toDataURL('image/png', 1)
+      let smallBase64 = await this.resizedataURL(base64, 240, 80)
+      // let url = await uploadByBase64(smallBase64, '绛惧悕')
+      // if (!url) return false
+      this.imageUrl = smallBase64
+      this.signatureDialog = false
+    },
+    resizedataURL: function(base64, wantedWidth, wantedHeight){
+      return new Promise((resolve) => {
+        let img = document.createElement('img')
+        img.onload = function() {
+          let canvas = document.createElement('canvas')
+          canvas.width = wantedWidth
+          canvas.height = wantedHeight
+          let ctx = canvas.getContext('2d')
+          ctx.fillStyle = '#ffffff'
+          ctx.fillRect(0, 0, wantedWidth, wantedHeight);
+          ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight)
+          resolve(canvas.toDataURL('image/png', 1))
+        }
+        img.src = base64
+      })
+    },
+  }
+}
+</script>
+
+<style scoped>
+.image-slot {
+  width: 100%;
+  max-width: 400px;
+  aspect-ratio: 16/9;
+  border: 1px solid #EAEAEA;
+  background: #F5F5F5F5;
+  margin-top: 10px;
+  border-radius: 8px;
+}
+.signature_content {
+  width: 100vw;
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+}
+.rotate_90 {
+  width: 100vh !important;
+  height: 100vw !important;
+  transform: rotate(90deg);
+}
+.canvas_box_normal {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: calc(100vh - 96px);
+}
+.signature :deep(.el-dialog__header)  {
+  display: none;
+}
+.signature :deep(.el-dialog__body) {
+  width: 100vw;
+  height: 100vh;
+  overflow: hidden;
+}
+.signature :deep(.el-dialog) {
+  background: #f5f5f5;
+}
+
+</style>
\ No newline at end of file

--
Gitblit v1.8.0