| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- <template>
- <div class="slider-verify-container w-320px my-3" v-loading="isResetting">
- <div class="relative">
- <img :src="captcha.canvasSrc" alt="验证图" draggable="false"/>
- <img
- ref="blockImage"
- :src="captcha.blockSrc"
- class="absolute left-0"
- :style="{top: captcha.blockY + 'px', transform: `translateX(${blockX}px)`}"
- alt="缺失的块"
- draggable="false"
- />
- </div>
- <div class="relative bg-white text-center line-height-50px h-50px shadow-inset shadow-black shadow-sm bg-opacity-50">
- <span v-show="!isDragging">向右拖动滑块来验证</span>
- <div
- ref="sliderBlock"
- class="absolute top-0 left-0 mt-5px ml-8px w-49px h-40px bg-blue cursor-pointer rounded-5px"
- :class="{'shadow-inset shadow-black shadow-sm': isDragging,'cursor-not-allowed':isResetting}"
- :style="{transform: `translateX(${currentX}px)`}"
- @mousedown="startDrag"
- @mousemove="onDrag"
- @mouseup="endDrag"
- ></div>
- </div>
- <div class="text-black text-5 rounded-50%">
- <el-icon class="cursor-pointer hover:text-cyan" @click="reset">
- <RefreshRight />
- </el-icon>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import request from '@/utils/request'
- import { ElMessage } from 'element-plus'
- import { ref } from 'vue'
- import { RefreshRight } from '@element-plus/icons-vue'
- interface Captcha {
- nonceStr: string,
- value: string,
- canvasSrc: string,
- canvasWidth: number,
- canvasHeight: number,
- blockSrc: string,
- blockWidth: number,
- blockHeight: number,
- blockRadius: number,
- blockX: number,
- blockY: number,
- place: number,
- }
- interface SliderVerifyResponse extends AxiosResponse{
- data: Captcha
- }
- const captcha = ref<Captcha>({
- blockHeight: 0,
- blockRadius: 0,
- blockSrc: '',
- blockWidth: 0,
- blockX: 0,
- blockY: 0,
- canvasHeight: 0,
- canvasSrc: '',
- canvasWidth: 0,
- nonceStr: '',
- place: 0,
- value: ''
- })
- const sliderBlock = ref<HTMLElement | null>(null)
- const blockImage = ref<HTMLElement | null>(null)
- const isDragging = ref(false);
- const startX = ref(0)
- const currentX = ref(0)
- const blockX = ref(0)
- const isResetting = ref(false);
- const startTime = ref(0);
- const emits = defineEmits(['verify','resetSlider']);
- const getImg = async () => {
- const res = await request.post<Captcha, SliderVerifyResponse>("/captchaSlider/getCaptcha", {})
- if (res.code !== 200) {
- ElMessage.error("当次获取验证图失败")
- }
- captcha.value = res.data
- blockX.value = captcha.value.blockX
- }
- const init = () => {
- getImg()
- }
- const startDrag = (event: MouseEvent) => {
- startTime.value = Date.now()
- if (sliderBlock.value && !isResetting.value) {
- isDragging.value = true
- startX.value = event.clientX - sliderBlock.value.offsetLeft
- }
- }
- const onDrag = (event: MouseEvent) => {
- event.preventDefault()
- if (isDragging.value && sliderBlock.value) {
- currentX.value = event.clientX - startX.value
- if (currentX.value < 0) currentX.value = 0
- if (currentX.value > 252) currentX.value = 252
- blockX.value = currentX.value
- }
- }
- const endDrag = () => {
- if(Date.now() - startTime.value > 10000){
- emits('resetSlider');
- return
- }
- if(Date.now() - startTime.value < 100){
- reset()
- return
- }
- if (isDragging.value) {
- emits('verify', captcha.value.nonceStr, currentX.value);
- isDragging.value = false
- isResetting.value = true
- }
- }
- const reset =async ()=>{
- await getImg();
- isResetting.value = false
- isDragging.value = false
- blockX.value = 0;
- currentX.value = 0;
- }
- defineExpose({reset});
- init()
- </script>
|