沙钢智慧能源系统前端代码
houzhongjian
2024-10-09 314507f8ddadd9c66e98d260c3b2a5dad1a04015
提交 | 用户 | 时间
314507 1 <template>
H 2   <div style="position: relative">
3     <div
4       v-if="type === '2'"
5       :style="{ height: parseInt(setSize.imgHeight) + vSpace + 'px' }"
6       class="verify-img-out"
7     >
8       <div :style="{ width: setSize.imgWidth, height: setSize.imgHeight }" class="verify-img-panel">
9         <img
10           :src="'data:image/png;base64,' + backImgBase"
11           alt=""
12           style="display: block; width: 100%; height: 100%"
13         />
14         <div v-show="showRefresh" class="verify-refresh" @click="refresh">
15           <i class="iconfont icon-refresh"></i>
16         </div>
17         <transition name="tips">
18           <span v-if="tipWords" :class="passFlag ? 'suc-bg' : 'err-bg'" class="verify-tips">
19             {{ tipWords }}
20           </span>
21         </transition>
22       </div>
23     </div>
24     <!-- 公共部分 -->
25     <div
26       :style="{ width: setSize.imgWidth, height: barSize.height, 'line-height': barSize.height }"
27       class="verify-bar-area"
28     >
29       <span class="verify-msg" v-text="text"></span>
30       <div
31         :style="{
32           width: leftBarWidth !== undefined ? leftBarWidth : barSize.height,
33           height: barSize.height,
34           'border-color': leftBarBorderColor,
35           transaction: transitionWidth
36         }"
37         class="verify-left-bar"
38       >
39         <span class="verify-msg" v-text="finishText"></span>
40         <div
41           :style="{
42             width: barSize.height,
43             height: barSize.height,
44             'background-color': moveBlockBackgroundColor,
45             left: moveBlockLeft,
46             transition: transitionLeft
47           }"
48           class="verify-move-block"
49           @mousedown="start"
50           @touchstart="start"
51         >
52           <i :class="['verify-icon iconfont', iconClass]" :style="{ color: iconColor }"></i>
53           <div
54             v-if="type === '2'"
55             :style="{
56               width: Math.floor((parseInt(setSize.imgWidth) * 47) / 310) + 'px',
57               height: setSize.imgHeight,
58               top: '-' + (parseInt(setSize.imgHeight) + vSpace) + 'px',
59               'background-size': setSize.imgWidth + ' ' + setSize.imgHeight
60             }"
61             class="verify-sub-block"
62           >
63             <img
64               :src="'data:image/png;base64,' + blockBackImgBase"
65               alt=""
66               style="display: block; width: 100%; height: 100%; -webkit-user-drag: none"
67             />
68           </div>
69         </div>
70       </div>
71     </div>
72   </div>
73 </template>
74 <script setup type="text/babel">
75 /**
76  * VerifySlide
77  * @description 滑块
78  * */
79 import { aesEncrypt } from './../utils/ase'
80 import { resetSize } from './../utils/util'
81 import { getCode, reqCheck } from '@/api/login'
82
83 const props = defineProps({
84   captchaType: {
85     type: String
86   },
87   type: {
88     type: String,
89     default: '1'
90   },
91   //弹出式pop,固定fixed
92   mode: {
93     type: String,
94     default: 'fixed'
95   },
96   vSpace: {
97     type: Number,
98     default: 5
99   },
100   explain: {
101     type: String,
102     default: ''
103   },
104   imgSize: {
105     type: Object,
106     default() {
107       return {
108         width: '310px',
109         height: '155px'
110       }
111     }
112   },
113   blockSize: {
114     type: Object,
115     default() {
116       return {
117         width: '50px',
118         height: '50px'
119       }
120     }
121   },
122   barSize: {
123     type: Object,
124     default() {
125       return {
126         width: '310px',
127         height: '30px'
128       }
129     }
130   }
131 })
132
133 const { t } = useI18n()
134 const { mode, captchaType, type, blockSize, explain } = toRefs(props)
135 const { proxy } = getCurrentInstance()
136 let secretKey = ref(''), //后端返回的ase加密秘钥
137   passFlag = ref(''), //是否通过的标识
138   backImgBase = ref(''), //验证码背景图片
139   blockBackImgBase = ref(''), //验证滑块的背景图片
140   backToken = ref(''), //后端返回的唯一token值
141   startMoveTime = ref(''), //移动开始的时间
142   endMovetime = ref(''), //移动结束的时间
143   tipWords = ref(''),
144   text = ref(''),
145   finishText = ref(''),
146   setSize = reactive({
147     imgHeight: 0,
148     imgWidth: 0,
149     barHeight: 0,
150     barWidth: 0
151   }),
152   moveBlockLeft = ref(undefined),
153   leftBarWidth = ref(undefined),
154   // 移动中样式
155   moveBlockBackgroundColor = ref(undefined),
156   leftBarBorderColor = ref('#ddd'),
157   iconColor = ref(undefined),
158   iconClass = ref('icon-right'),
159   status = ref(false), //鼠标状态
160   isEnd = ref(false), //是够验证完成
161   showRefresh = ref(true),
162   transitionLeft = ref(''),
163   transitionWidth = ref(''),
164   startLeft = ref(0)
165
166 const barArea = computed(() => {
167   return proxy.$el.querySelector('.verify-bar-area')
168 })
169 const init = () => {
170   if (explain.value === '') {
171     text.value = t('captcha.slide')
172   } else {
173     text.value = explain.value
174   }
175   getPictrue()
176   nextTick(() => {
177     let { imgHeight, imgWidth, barHeight, barWidth } = resetSize(proxy)
178     setSize.imgHeight = imgHeight
179     setSize.imgWidth = imgWidth
180     setSize.barHeight = barHeight
181     setSize.barWidth = barWidth
182     proxy.$parent.$emit('ready', proxy)
183   })
184
185   window.removeEventListener('touchmove', function (e) {
186     move(e)
187   })
188   window.removeEventListener('mousemove', function (e) {
189     move(e)
190   })
191
192   //鼠标松开
193   window.removeEventListener('touchend', function () {
194     end()
195   })
196   window.removeEventListener('mouseup', function () {
197     end()
198   })
199
200   window.addEventListener('touchmove', function (e) {
201     move(e)
202   })
203   window.addEventListener('mousemove', function (e) {
204     move(e)
205   })
206
207   //鼠标松开
208   window.addEventListener('touchend', function () {
209     end()
210   })
211   window.addEventListener('mouseup', function () {
212     end()
213   })
214 }
215 watch(type, () => {
216   init()
217 })
218 onMounted(() => {
219   // 禁止拖拽
220   init()
221   proxy.$el.onselectstart = function () {
222     return false
223   }
224 })
225 //鼠标按下
226 const start = (e) => {
227   e = e || window.event
228   if (!e.touches) {
229     //兼容PC端
230     var x = e.clientX
231   } else {
232     //兼容移动端
233     var x = e.touches[0].pageX
234   }
235   startLeft.value = Math.floor(x - barArea.value.getBoundingClientRect().left)
236   startMoveTime.value = +new Date() //开始滑动的时间
237   if (isEnd.value == false) {
238     text.value = ''
239     moveBlockBackgroundColor.value = '#337ab7'
240     leftBarBorderColor.value = '#337AB7'
241     iconColor.value = '#fff'
242     e.stopPropagation()
243     status.value = true
244   }
245 }
246 //鼠标移动
247 const move = (e) => {
248   e = e || window.event
249   if (status.value && isEnd.value == false) {
250     if (!e.touches) {
251       //兼容PC端
252       var x = e.clientX
253     } else {
254       //兼容移动端
255       var x = e.touches[0].pageX
256     }
257     var bar_area_left = barArea.value.getBoundingClientRect().left
258     var move_block_left = x - bar_area_left //小方块相对于父元素的left值
259     if (
260       move_block_left >=
261       barArea.value.offsetWidth - parseInt(parseInt(blockSize.value.width) / 2) - 2
262     ) {
263       move_block_left =
264         barArea.value.offsetWidth - parseInt(parseInt(blockSize.value.width) / 2) - 2
265     }
266     if (move_block_left <= 0) {
267       move_block_left = parseInt(parseInt(blockSize.value.width) / 2)
268     }
269     //拖动后小方块的left值
270     moveBlockLeft.value = move_block_left - startLeft.value + 'px'
271     leftBarWidth.value = move_block_left - startLeft.value + 'px'
272   }
273 }
274
275 //鼠标松开
276 const end = () => {
277   endMovetime.value = +new Date()
278   //判断是否重合
279   if (status.value && isEnd.value == false) {
280     var moveLeftDistance = parseInt((moveBlockLeft.value || '0').replace('px', ''))
281     moveLeftDistance = (moveLeftDistance * 310) / parseInt(setSize.imgWidth)
282     let data = {
283       captchaType: captchaType.value,
284       pointJson: secretKey.value
285         ? aesEncrypt(JSON.stringify({ x: moveLeftDistance, y: 5.0 }), secretKey.value)
286         : JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
287       token: backToken.value
288     }
289     reqCheck(data).then((res) => {
290       if (res.repCode == '0000') {
291         moveBlockBackgroundColor.value = '#5cb85c'
292         leftBarBorderColor.value = '#5cb85c'
293         iconColor.value = '#fff'
294         iconClass.value = 'icon-check'
295         showRefresh.value = false
296         isEnd.value = true
297         if (mode.value == 'pop') {
298           setTimeout(() => {
299             proxy.$parent.clickShow = false
300             refresh()
301           }, 1500)
302         }
303         passFlag.value = true
304         tipWords.value = `${((endMovetime.value - startMoveTime.value) / 1000).toFixed(2)}s
305             ${t('captcha.success')}`
306         var captchaVerification = secretKey.value
307           ? aesEncrypt(
308               backToken.value + '---' + JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
309               secretKey.value
310             )
311           : backToken.value + '---' + JSON.stringify({ x: moveLeftDistance, y: 5.0 })
312         setTimeout(() => {
313           tipWords.value = ''
314           proxy.$parent.closeBox()
315           proxy.$parent.$emit('success', { captchaVerification })
316         }, 1000)
317       } else {
318         moveBlockBackgroundColor.value = '#d9534f'
319         leftBarBorderColor.value = '#d9534f'
320         iconColor.value = '#fff'
321         iconClass.value = 'icon-close'
322         passFlag.value = false
323         setTimeout(function () {
324           refresh()
325         }, 1000)
326         proxy.$parent.$emit('error', proxy)
327         tipWords.value = t('captcha.fail')
328         setTimeout(() => {
329           tipWords.value = ''
330         }, 1000)
331       }
332     })
333     status.value = false
334   }
335 }
336
337 const refresh = async () => {
338   showRefresh.value = true
339   finishText.value = ''
340
341   transitionLeft.value = 'left .3s'
342   moveBlockLeft.value = 0
343
344   leftBarWidth.value = undefined
345   transitionWidth.value = 'width .3s'
346
347   leftBarBorderColor.value = '#ddd'
348   moveBlockBackgroundColor.value = '#fff'
349   iconColor.value = '#000'
350   iconClass.value = 'icon-right'
351   isEnd.value = false
352
353   await getPictrue()
354   setTimeout(() => {
355     transitionWidth.value = ''
356     transitionLeft.value = ''
357     text.value = explain.value
358   }, 300)
359 }
360
361 // 请求背景图片和验证图片
362 const getPictrue = async () => {
363   let data = {
364     captchaType: captchaType.value
365   }
366   const res = await getCode(data)
367   if (res.repCode == '0000') {
368     backImgBase.value = res.repData.originalImageBase64
369     blockBackImgBase.value = res.repData.jigsawImageBase64
370     backToken.value = res.repData.token
371     secretKey.value = res.repData.secretKey
372   } else {
373     tipWords.value = res.repMsg
374   }
375 }
376 </script>