mirror of
https://github.com/yangjian102621/geekai.git
synced 2026-04-26 21:14:27 +08:00
161 lines
3.6 KiB
Vue
161 lines
3.6 KiB
Vue
<template>
|
|
<el-container class="captcha-box">
|
|
<el-dialog
|
|
v-model="show"
|
|
:close-on-click-modal="true"
|
|
:show-close="isMobileInternal"
|
|
style="width: 360px; --el-dialog-padding-primary: 5px 15px 15px 15px"
|
|
>
|
|
<template #header>
|
|
<div
|
|
class="text-center p-3"
|
|
style="color: var(--el-text-color-primary)"
|
|
v-if="isMobileInternal"
|
|
>
|
|
<span>人机验证</span>
|
|
</div>
|
|
</template>
|
|
<slide-captcha
|
|
v-if="isMobileInternal"
|
|
:bg-img="bgImg"
|
|
:bk-img="bkImg"
|
|
:result="result"
|
|
@refresh="getSlideCaptcha"
|
|
@confirm="handleSlideConfirm"
|
|
@hide="show = false"
|
|
/>
|
|
|
|
<captcha-plus
|
|
v-else
|
|
:max-dot="maxDot"
|
|
:image-base64="imageBase64"
|
|
:thumb-base64="thumbBase64"
|
|
width="300"
|
|
@close="show = false"
|
|
@refresh="handleRequestCaptCode"
|
|
@confirm="handleConfirm"
|
|
/>
|
|
</el-dialog>
|
|
</el-container>
|
|
</template>
|
|
|
|
<script setup>
|
|
import CaptchaPlus from '@/components/CaptchaPlus.vue'
|
|
import SlideCaptcha from '@/components/SlideCaptcha.vue'
|
|
import { showMessageError } from '@/utils/dialog'
|
|
import { httpGet, httpPost } from '@/utils/http'
|
|
import { isMobile } from '@/utils/libs'
|
|
import lodash from 'lodash'
|
|
import { ref } from 'vue'
|
|
|
|
const show = ref(false)
|
|
const maxDot = ref(5)
|
|
const imageBase64 = ref('')
|
|
const thumbBase64 = ref('')
|
|
const captKey = ref('')
|
|
const dots = ref(null)
|
|
const isMobileInternal = isMobile()
|
|
|
|
const emits = defineEmits(['success'])
|
|
const handleRequestCaptCode = () => {
|
|
httpGet('/api/captcha/get')
|
|
.then((res) => {
|
|
const data = res.data
|
|
imageBase64.value = data.image
|
|
thumbBase64.value = data.thumb
|
|
captKey.value = data.key
|
|
})
|
|
.catch((e) => {
|
|
showMessageError('获取人机验证数据失败:' + e.message)
|
|
})
|
|
}
|
|
|
|
const handleConfirm = (dts) => {
|
|
if (lodash.size(dts) <= 0) {
|
|
return showMessageError('请进行人机验证再操作')
|
|
}
|
|
|
|
let dotArr = []
|
|
lodash.forEach(dts, (dot) => {
|
|
dotArr.push(dot.x, dot.y)
|
|
})
|
|
dots.value = dotArr.join(',')
|
|
httpPost('/api/captcha/check', {
|
|
dots: dots.value,
|
|
key: captKey.value,
|
|
})
|
|
.then(() => {
|
|
// ElMessage.success('人机验证成功')
|
|
show.value = false
|
|
emits('success', { key: captKey.value, dots: dots.value })
|
|
})
|
|
.catch(() => {
|
|
showMessageError('人机验证失败')
|
|
handleRequestCaptCode()
|
|
})
|
|
}
|
|
|
|
const loadCaptcha = () => {
|
|
show.value = true
|
|
// 手机用滑动验证码
|
|
if (isMobile()) {
|
|
getSlideCaptcha()
|
|
} else {
|
|
handleRequestCaptCode()
|
|
}
|
|
}
|
|
|
|
// 滑动验证码
|
|
const bgImg = ref('')
|
|
const bkImg = ref('')
|
|
const result = ref(0)
|
|
|
|
const getSlideCaptcha = () => {
|
|
result.value = 0
|
|
httpGet('/api/captcha/slide/get')
|
|
.then((res) => {
|
|
bkImg.value = res.data.bkImg
|
|
bgImg.value = res.data.bgImg
|
|
captKey.value = res.data.key
|
|
})
|
|
.catch((e) => {
|
|
showMessageError('获取人机验证数据失败:' + e.message)
|
|
})
|
|
}
|
|
|
|
const handleSlideConfirm = (x) => {
|
|
httpPost('/api/captcha/slide/check', {
|
|
key: captKey.value,
|
|
x: x,
|
|
})
|
|
.then(() => {
|
|
result.value = 1
|
|
show.value = false
|
|
emits('success', { key: captKey.value, x: x })
|
|
})
|
|
.catch(() => {
|
|
result.value = 2
|
|
})
|
|
}
|
|
|
|
// 导出方法以便父组件调用
|
|
defineExpose({
|
|
loadCaptcha,
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.captcha-box {
|
|
.el-dialog {
|
|
.el-dialog__header {
|
|
padding: 0;
|
|
}
|
|
|
|
.el-dialog__body {
|
|
padding-bottom: 5px;
|
|
overflow: hidden;
|
|
}
|
|
}
|
|
}
|
|
</style>
|