From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/components/Verifition/src/Verify/VerifyPoints.vue |  250 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 250 insertions(+), 0 deletions(-)

diff --git a/src/components/Verifition/src/Verify/VerifyPoints.vue b/src/components/Verifition/src/Verify/VerifyPoints.vue
new file mode 100644
index 0000000..9d04f29
--- /dev/null
+++ b/src/components/Verifition/src/Verify/VerifyPoints.vue
@@ -0,0 +1,250 @@
+<template>
+  <div style="position: relative">
+    <div class="verify-img-out">
+      <div
+        :style="{
+          width: setSize.imgWidth,
+          height: setSize.imgHeight,
+          'background-size': setSize.imgWidth + ' ' + setSize.imgHeight,
+          'margin-bottom': vSpace + 'px'
+        }"
+        class="verify-img-panel"
+      >
+        <div v-show="showRefresh" class="verify-refresh" style="z-index: 3" @click="refresh">
+          <i class="iconfont icon-refresh"></i>
+        </div>
+        <img
+          ref="canvas"
+          :src="'data:image/png;base64,' + pointBackImgBase"
+          alt=""
+          style="display: block; width: 100%; height: 100%"
+          @click="bindingClick ? canvasClick($event) : undefined"
+        />
+
+        <div
+          v-for="(tempPoint, index) in tempPoints"
+          :key="index"
+          :style="{
+            'background-color': '#1abd6c',
+            color: '#fff',
+            'z-index': 9999,
+            width: '20px',
+            height: '20px',
+            'text-align': 'center',
+            'line-height': '20px',
+            'border-radius': '50%',
+            position: 'absolute',
+            top: parseInt(tempPoint.y - 10) + 'px',
+            left: parseInt(tempPoint.x - 10) + 'px'
+          }"
+          class="point-area"
+        >
+          {{ index + 1 }}
+        </div>
+      </div>
+    </div>
+    <!-- 'height': this.barSize.height, -->
+    <div
+      :style="{
+        width: setSize.imgWidth,
+        color: barAreaColor,
+        'border-color': barAreaBorderColor,
+        'line-height': barSize.height
+      }"
+      class="verify-bar-area"
+    >
+      <span class="verify-msg">{{ text }}</span>
+    </div>
+  </div>
+</template>
+<script setup type="text/babel">
+/**
+ * VerifyPoints
+ * @description 鐐归��
+ * */
+import { resetSize } from './../utils/util'
+import { aesEncrypt } from './../utils/ase'
+import { getCode, reqCheck } from '@/api/login'
+import { getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs } from 'vue'
+
+const props = defineProps({
+  //寮瑰嚭寮弍op锛屽浐瀹歠ixed
+  mode: {
+    type: String,
+    default: 'fixed'
+  },
+  captchaType: {
+    type: String
+  },
+  //闂撮殧
+  vSpace: {
+    type: Number,
+    default: 5
+  },
+  imgSize: {
+    type: Object,
+    default() {
+      return {
+        width: '310px',
+        height: '155px'
+      }
+    }
+  },
+  barSize: {
+    type: Object,
+    default() {
+      return {
+        width: '310px',
+        height: '40px'
+      }
+    }
+  }
+})
+
+const { t } = useI18n()
+const { mode, captchaType } = toRefs(props)
+const { proxy } = getCurrentInstance()
+let secretKey = ref(''), //鍚庣杩斿洖鐨刟se鍔犲瘑绉橀挜
+  checkNum = ref(3), //榛樿闇�瑕佺偣鍑荤殑瀛楁暟
+  fontPos = reactive([]), //閫変腑鐨勫潗鏍囦俊鎭�
+  checkPosArr = reactive([]), //鐢ㄦ埛鐐瑰嚮鐨勫潗鏍�
+  num = ref(1), //鐐瑰嚮鐨勮鏁�
+  pointBackImgBase = ref(''), //鍚庣鑾峰彇鍒扮殑鑳屾櫙鍥剧墖
+  poinTextList = reactive([]), //鍚庣杩斿洖鐨勭偣鍑诲瓧浣撻『搴�
+  backToken = ref(''), //鍚庣杩斿洖鐨則oken鍊�
+  setSize = reactive({
+    imgHeight: 0,
+    imgWidth: 0,
+    barHeight: 0,
+    barWidth: 0
+  }),
+  tempPoints = reactive([]),
+  text = ref(''),
+  barAreaColor = ref(undefined),
+  barAreaBorderColor = ref(undefined),
+  showRefresh = ref(true),
+  bindingClick = ref(true)
+
+const init = () => {
+  //鍔犺浇椤甸潰
+  fontPos.splice(0, fontPos.length)
+  checkPosArr.splice(0, checkPosArr.length)
+  num.value = 1
+  getPictrue()
+  nextTick(() => {
+    let { imgHeight, imgWidth, barHeight, barWidth } = resetSize(proxy)
+    setSize.imgHeight = imgHeight
+    setSize.imgWidth = imgWidth
+    setSize.barHeight = barHeight
+    setSize.barWidth = barWidth
+    proxy.$parent.$emit('ready', proxy)
+  })
+}
+onMounted(() => {
+  // 绂佹鎷栨嫿
+  init()
+  proxy.$el.onselectstart = function () {
+    return false
+  }
+})
+const canvas = ref(null)
+const canvasClick = (e) => {
+  checkPosArr.push(getMousePos(canvas, e))
+  if (num.value == checkNum.value) {
+    num.value = createPoint(getMousePos(canvas, e))
+    //鎸夋瘮渚嬭浆鎹㈠潗鏍囧��
+    let arr = pointTransfrom(checkPosArr, setSize)
+    checkPosArr.length = 0
+    checkPosArr.push(...arr)
+    //绛夊垱寤哄潗鏍囨墽琛屽畬
+    setTimeout(() => {
+      // var flag = this.comparePos(this.fontPos, this.checkPosArr);
+      //鍙戦�佸悗绔姹�
+      var captchaVerification = secretKey.value
+        ? aesEncrypt(backToken.value + '---' + JSON.stringify(checkPosArr), secretKey.value)
+        : backToken.value + '---' + JSON.stringify(checkPosArr)
+      let data = {
+        captchaType: captchaType.value,
+        pointJson: secretKey.value
+          ? aesEncrypt(JSON.stringify(checkPosArr), secretKey.value)
+          : JSON.stringify(checkPosArr),
+        token: backToken.value
+      }
+      reqCheck(data).then((res) => {
+        if (res.repCode == '0000') {
+          barAreaColor.value = '#4cae4c'
+          barAreaBorderColor.value = '#5cb85c'
+          text.value = t('captcha.success')
+          bindingClick.value = false
+          if (mode.value == 'pop') {
+            setTimeout(() => {
+              proxy.$parent.clickShow = false
+              refresh()
+            }, 1500)
+          }
+          proxy.$parent.$emit('success', { captchaVerification })
+        } else {
+          proxy.$parent.$emit('error', proxy)
+          barAreaColor.value = '#d9534f'
+          barAreaBorderColor.value = '#d9534f'
+          text.value = t('captcha.fail')
+          setTimeout(() => {
+            refresh()
+          }, 700)
+        }
+      })
+    }, 400)
+  }
+  if (num.value < checkNum.value) {
+    num.value = createPoint(getMousePos(canvas, e))
+  }
+}
+//鑾峰彇鍧愭爣
+const getMousePos = function (obj, e) {
+  var x = e.offsetX
+  var y = e.offsetY
+  return { x, y }
+}
+//鍒涘缓鍧愭爣鐐�
+const createPoint = function (pos) {
+  tempPoints.push(Object.assign({}, pos))
+  return num.value + 1
+}
+const refresh = async function () {
+  tempPoints.splice(0, tempPoints.length)
+  barAreaColor.value = '#000'
+  barAreaBorderColor.value = '#ddd'
+  bindingClick.value = true
+  fontPos.splice(0, fontPos.length)
+  checkPosArr.splice(0, checkPosArr.length)
+  num.value = 1
+  await getPictrue()
+  showRefresh.value = true
+}
+
+// 璇锋眰鑳屾櫙鍥剧墖鍜岄獙璇佸浘鐗�
+const getPictrue = async () => {
+  let data = {
+    captchaType: captchaType.value
+  }
+  const res = await getCode(data)
+  if (res.repCode == '0000') {
+    pointBackImgBase.value = res.repData.originalImageBase64
+    backToken.value = res.repData.token
+    secretKey.value = res.repData.secretKey
+    poinTextList.value = res.repData.wordList
+    text.value = t('captcha.point') + '銆�' + poinTextList.value.join(',') + '銆�'
+  } else {
+    text.value = res.repMsg
+  }
+}
+//鍧愭爣杞崲鍑芥暟
+const pointTransfrom = function (pointArr, imgSize) {
+  var newPointArr = pointArr.map((p) => {
+    let x = Math.round((310 * p.x) / parseInt(imgSize.imgWidth))
+    let y = Math.round((155 * p.y) / parseInt(imgSize.imgHeight))
+    return { x, y }
+  })
+  return newPointArr
+}
+</script>

--
Gitblit v1.8.0