沙钢智慧能源系统前端代码
houzhongjian
2024-10-09 314507f8ddadd9c66e98d260c3b2a5dad1a04015
提交 | 用户 | 时间
314507 1 <template>
H 2   <div style="position: relative">
3     <div class="verify-img-out">
4       <div
5         :style="{
6           width: setSize.imgWidth,
7           height: setSize.imgHeight,
8           'background-size': setSize.imgWidth + ' ' + setSize.imgHeight,
9           'margin-bottom': vSpace + 'px'
10         }"
11         class="verify-img-panel"
12       >
13         <div v-show="showRefresh" class="verify-refresh" style="z-index: 3" @click="refresh">
14           <i class="iconfont icon-refresh"></i>
15         </div>
16         <img
17           ref="canvas"
18           :src="'data:image/png;base64,' + pointBackImgBase"
19           alt=""
20           style="display: block; width: 100%; height: 100%"
21           @click="bindingClick ? canvasClick($event) : undefined"
22         />
23
24         <div
25           v-for="(tempPoint, index) in tempPoints"
26           :key="index"
27           :style="{
28             'background-color': '#1abd6c',
29             color: '#fff',
30             'z-index': 9999,
31             width: '20px',
32             height: '20px',
33             'text-align': 'center',
34             'line-height': '20px',
35             'border-radius': '50%',
36             position: 'absolute',
37             top: parseInt(tempPoint.y - 10) + 'px',
38             left: parseInt(tempPoint.x - 10) + 'px'
39           }"
40           class="point-area"
41         >
42           {{ index + 1 }}
43         </div>
44       </div>
45     </div>
46     <!-- 'height': this.barSize.height, -->
47     <div
48       :style="{
49         width: setSize.imgWidth,
50         color: barAreaColor,
51         'border-color': barAreaBorderColor,
52         'line-height': barSize.height
53       }"
54       class="verify-bar-area"
55     >
56       <span class="verify-msg">{{ text }}</span>
57     </div>
58   </div>
59 </template>
60 <script setup type="text/babel">
61 /**
62  * VerifyPoints
63  * @description 点选
64  * */
65 import { resetSize } from './../utils/util'
66 import { aesEncrypt } from './../utils/ase'
67 import { getCode, reqCheck } from '@/api/login'
68 import { getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs } from 'vue'
69
70 const props = defineProps({
71   //弹出式pop,固定fixed
72   mode: {
73     type: String,
74     default: 'fixed'
75   },
76   captchaType: {
77     type: String
78   },
79   //间隔
80   vSpace: {
81     type: Number,
82     default: 5
83   },
84   imgSize: {
85     type: Object,
86     default() {
87       return {
88         width: '310px',
89         height: '155px'
90       }
91     }
92   },
93   barSize: {
94     type: Object,
95     default() {
96       return {
97         width: '310px',
98         height: '40px'
99       }
100     }
101   }
102 })
103
104 const { t } = useI18n()
105 const { mode, captchaType } = toRefs(props)
106 const { proxy } = getCurrentInstance()
107 let secretKey = ref(''), //后端返回的ase加密秘钥
108   checkNum = ref(3), //默认需要点击的字数
109   fontPos = reactive([]), //选中的坐标信息
110   checkPosArr = reactive([]), //用户点击的坐标
111   num = ref(1), //点击的记数
112   pointBackImgBase = ref(''), //后端获取到的背景图片
113   poinTextList = reactive([]), //后端返回的点击字体顺序
114   backToken = ref(''), //后端返回的token值
115   setSize = reactive({
116     imgHeight: 0,
117     imgWidth: 0,
118     barHeight: 0,
119     barWidth: 0
120   }),
121   tempPoints = reactive([]),
122   text = ref(''),
123   barAreaColor = ref(undefined),
124   barAreaBorderColor = ref(undefined),
125   showRefresh = ref(true),
126   bindingClick = ref(true)
127
128 const init = () => {
129   //加载页面
130   fontPos.splice(0, fontPos.length)
131   checkPosArr.splice(0, checkPosArr.length)
132   num.value = 1
133   getPictrue()
134   nextTick(() => {
135     let { imgHeight, imgWidth, barHeight, barWidth } = resetSize(proxy)
136     setSize.imgHeight = imgHeight
137     setSize.imgWidth = imgWidth
138     setSize.barHeight = barHeight
139     setSize.barWidth = barWidth
140     proxy.$parent.$emit('ready', proxy)
141   })
142 }
143 onMounted(() => {
144   // 禁止拖拽
145   init()
146   proxy.$el.onselectstart = function () {
147     return false
148   }
149 })
150 const canvas = ref(null)
151 const canvasClick = (e) => {
152   checkPosArr.push(getMousePos(canvas, e))
153   if (num.value == checkNum.value) {
154     num.value = createPoint(getMousePos(canvas, e))
155     //按比例转换坐标值
156     let arr = pointTransfrom(checkPosArr, setSize)
157     checkPosArr.length = 0
158     checkPosArr.push(...arr)
159     //等创建坐标执行完
160     setTimeout(() => {
161       // var flag = this.comparePos(this.fontPos, this.checkPosArr);
162       //发送后端请求
163       var captchaVerification = secretKey.value
164         ? aesEncrypt(backToken.value + '---' + JSON.stringify(checkPosArr), secretKey.value)
165         : backToken.value + '---' + JSON.stringify(checkPosArr)
166       let data = {
167         captchaType: captchaType.value,
168         pointJson: secretKey.value
169           ? aesEncrypt(JSON.stringify(checkPosArr), secretKey.value)
170           : JSON.stringify(checkPosArr),
171         token: backToken.value
172       }
173       reqCheck(data).then((res) => {
174         if (res.repCode == '0000') {
175           barAreaColor.value = '#4cae4c'
176           barAreaBorderColor.value = '#5cb85c'
177           text.value = t('captcha.success')
178           bindingClick.value = false
179           if (mode.value == 'pop') {
180             setTimeout(() => {
181               proxy.$parent.clickShow = false
182               refresh()
183             }, 1500)
184           }
185           proxy.$parent.$emit('success', { captchaVerification })
186         } else {
187           proxy.$parent.$emit('error', proxy)
188           barAreaColor.value = '#d9534f'
189           barAreaBorderColor.value = '#d9534f'
190           text.value = t('captcha.fail')
191           setTimeout(() => {
192             refresh()
193           }, 700)
194         }
195       })
196     }, 400)
197   }
198   if (num.value < checkNum.value) {
199     num.value = createPoint(getMousePos(canvas, e))
200   }
201 }
202 //获取坐标
203 const getMousePos = function (obj, e) {
204   var x = e.offsetX
205   var y = e.offsetY
206   return { x, y }
207 }
208 //创建坐标点
209 const createPoint = function (pos) {
210   tempPoints.push(Object.assign({}, pos))
211   return num.value + 1
212 }
213 const refresh = async function () {
214   tempPoints.splice(0, tempPoints.length)
215   barAreaColor.value = '#000'
216   barAreaBorderColor.value = '#ddd'
217   bindingClick.value = true
218   fontPos.splice(0, fontPos.length)
219   checkPosArr.splice(0, checkPosArr.length)
220   num.value = 1
221   await getPictrue()
222   showRefresh.value = true
223 }
224
225 // 请求背景图片和验证图片
226 const getPictrue = async () => {
227   let data = {
228     captchaType: captchaType.value
229   }
230   const res = await getCode(data)
231   if (res.repCode == '0000') {
232     pointBackImgBase.value = res.repData.originalImageBase64
233     backToken.value = res.repData.token
234     secretKey.value = res.repData.secretKey
235     poinTextList.value = res.repData.wordList
236     text.value = t('captcha.point') + '【' + poinTextList.value.join(',') + '】'
237   } else {
238     text.value = res.repMsg
239   }
240 }
241 //坐标转换函数
242 const pointTransfrom = function (pointArr, imgSize) {
243   var newPointArr = pointArr.map((p) => {
244     let x = Math.round((310 * p.x) / parseInt(imgSize.imgWidth))
245     let y = Math.round((155 * p.y) / parseInt(imgSize.imgHeight))
246     return { x, y }
247   })
248   return newPointArr
249 }
250 </script>