feat(login): 实现滑动验证码功能
- 新增滑动验证码
@ -2,7 +2,7 @@
|
|||||||
<div class="puzzle-container">
|
<div class="puzzle-container">
|
||||||
<div class="puzzle-box" :style="{ height: boxHeight + 'px' }">
|
<div class="puzzle-box" :style="{ height: boxHeight + 'px' }">
|
||||||
<!-- 背景图 -->
|
<!-- 背景图 -->
|
||||||
<img :src="bgImageUrl" style="width: 320px;height: 189px;" ref="bgImage" @load="onImageLoad" @error="handleImageError">
|
<img :src="bgImageUrl" style="width: 320px;height: 191px;" ref="bgImage" @load="onImageLoad" @error="handleImageError">
|
||||||
<!-- 滑块 -->
|
<!-- 滑块 -->
|
||||||
<img
|
<img
|
||||||
class="slider-block"
|
class="slider-block"
|
||||||
@ -10,9 +10,12 @@
|
|||||||
:style="{
|
:style="{
|
||||||
top: `${blockY}px`,
|
top: `${blockY}px`,
|
||||||
left: `${moveX}px`,
|
left: `${moveX}px`,
|
||||||
visibility: loaded ? 'visible' : 'hidden'
|
visibility: loaded ? 'visible' : 'hidden',
|
||||||
|
width: '50px',
|
||||||
|
height: '50px'
|
||||||
}"
|
}"
|
||||||
></img>
|
></img>
|
||||||
|
<div v-if="verifySuccess || verifyError" :class="`text-#fff ${verifySuccess?'bg-#52C41A':'bg-#FF4D4F'} h-24px w-100% text-14px absolute left-0 bottom-0 text-center leading-24px`">{{ verifyTip }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 滑动条 -->
|
<!-- 滑动条 -->
|
||||||
@ -31,10 +34,7 @@
|
|||||||
<div class="slider-icon"></div>
|
<div class="slider-icon"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 验证结果提示 -->
|
|
||||||
<div v-if="verifySuccess || verifyError" class="verify-result-bar" :class="{ 'success': verifySuccess, 'error': verifyError }">
|
|
||||||
{{ verifyTip }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -75,6 +75,15 @@ const verifySuccess = ref(false)
|
|||||||
const verifyError = ref(false)
|
const verifyError = ref(false)
|
||||||
const verifyTip = ref('')
|
const verifyTip = ref('')
|
||||||
|
|
||||||
|
// 重置方法
|
||||||
|
const reset = () => {
|
||||||
|
moveX.value = 0
|
||||||
|
verifySuccess.value = false
|
||||||
|
verifyError.value = false
|
||||||
|
verifyTip.value = ''
|
||||||
|
isDragging.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// DOM引用
|
// DOM引用
|
||||||
const bgImage = ref(null)
|
const bgImage = ref(null)
|
||||||
|
|
||||||
@ -169,14 +178,18 @@ const handleMouseUp = async () => {
|
|||||||
verifySuccess.value = false
|
verifySuccess.value = false
|
||||||
verifyError.value = true
|
verifyError.value = true
|
||||||
verifyTip.value = '验证失败'
|
verifyTip.value = '验证失败'
|
||||||
moveX.value = 0 // 验证失败,滑块返回原位
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
verifySuccess.value = false
|
verifySuccess.value = false
|
||||||
verifyError.value = true
|
verifyError.value = true
|
||||||
verifyTip.value = '验证失败'
|
verifyTip.value = '验证失败'
|
||||||
moveX.value = 0
|
}finally{
|
||||||
|
setTimeout(() => {
|
||||||
|
reset()
|
||||||
|
}, 2000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,8 +235,7 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.puzzle-container {
|
.puzzle-container {
|
||||||
width: 100%;
|
position: relative;
|
||||||
max-width: 320px;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
BIN
app/components/slider-verify/slider-verify-image/de_DE/bg.png
Normal file
After Width: | Height: | Size: 600 KiB |
After Width: | Height: | Size: 610 KiB |
BIN
app/components/slider-verify/slider-verify-image/de_DE/error.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 6.0 KiB |
BIN
app/components/slider-verify/slider-verify-image/en_US/bg.png
Normal file
After Width: | Height: | Size: 681 KiB |
After Width: | Height: | Size: 691 KiB |
BIN
app/components/slider-verify/slider-verify-image/en_US/error.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 1.0 KiB |
BIN
app/components/slider-verify/slider-verify-image/ja_JP/bg.png
Normal file
After Width: | Height: | Size: 600 KiB |
After Width: | Height: | Size: 611 KiB |
BIN
app/components/slider-verify/slider-verify-image/ja_JP/error.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 6.4 KiB |
BIN
app/components/slider-verify/slider-verify-image/reload.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/components/slider-verify/slider-verify-image/zh_CN/bg.png
Normal file
After Width: | Height: | Size: 681 KiB |
After Width: | Height: | Size: 691 KiB |
BIN
app/components/slider-verify/slider-verify-image/zh_CN/error.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 7.2 KiB |
BIN
app/components/slider-verify/slider-verify-image/zh_TW/bg.png
Normal file
After Width: | Height: | Size: 600 KiB |
After Width: | Height: | Size: 611 KiB |
BIN
app/components/slider-verify/slider-verify-image/zh_TW/error.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 4.9 KiB |
418
app/components/slider-verify/slider-verify/index.vue
Normal file
@ -0,0 +1,418 @@
|
|||||||
|
<template>
|
||||||
|
<view class="slider-verify-box" v-if="isShow">
|
||||||
|
<view :style="`background-image: url('../../static/image/slider-verify/${
|
||||||
|
$i18n.locale
|
||||||
|
}/${isError ? 'bg_error' : 'bg'}.png');`" class="verifyBox">
|
||||||
|
<!-- <view class="slider-title">{{ $t('authentication.title') }}</view> -->
|
||||||
|
<image class="slider-verify-box-close" src="/static/image/icon/close.png" @click.stop="hideSliderBox">
|
||||||
|
</image>
|
||||||
|
<view class="slide-content">
|
||||||
|
<view class="slider-pintu">
|
||||||
|
<!-- <u-icon
|
||||||
|
name="reload"
|
||||||
|
size="32"
|
||||||
|
color="#fff"
|
||||||
|
class="reload"
|
||||||
|
@tap="refreshVerify"
|
||||||
|
v-if="!isLoading"
|
||||||
|
></u-icon> -->
|
||||||
|
<image src="../../static/image/slider-verify/reload.png" mode="widthFix" style="width: 38rpx"
|
||||||
|
class="reload" @tap="refreshVerify" v-if="!isLoading"></image>
|
||||||
|
<view class="load" v-if="isLoading">
|
||||||
|
<van-loading type="spinner" />
|
||||||
|
<!-- <u-loading-icon text="" textSize="16" :vertical="true"></u-loading-icon> -->
|
||||||
|
</view>
|
||||||
|
<template v-else>
|
||||||
|
<image id="pintuImg" :src="canvasSrc" class="pintu"></image>
|
||||||
|
<view class="pintukuai" :style="{ top: '0px', left: oldx + 'px' }">
|
||||||
|
<image :src="blockSrc" :style="{
|
||||||
|
top: blockY + 'px',
|
||||||
|
left: oldx + 'px',
|
||||||
|
width: blockWidth + 'px',
|
||||||
|
height: blockHeight + 'px'
|
||||||
|
}"></image>
|
||||||
|
</view>
|
||||||
|
<view class="mark" v-if="isMess">
|
||||||
|
<image :src="`../../static/image/slider-verify/${$i18n.locale}/error.png`" mode="widthFix"
|
||||||
|
v-if="isError"></image>
|
||||||
|
<image :src="`../../static/image/slider-verify/${$i18n.locale}/success.png`" mode="widthFix"
|
||||||
|
v-else></image>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
<view class="slider-movearea" @touchend="endTouchMove">
|
||||||
|
<movable-area :animation="true">
|
||||||
|
<movable-view :class="
|
||||||
|
isLoading
|
||||||
|
? 'movable-view btn_info'
|
||||||
|
: isError
|
||||||
|
? 'movable-view btn_error'
|
||||||
|
: 'movable-view btn_success'
|
||||||
|
" :x="x" direction="horizontal" @change="startMove"></movable-view>
|
||||||
|
</movable-area>
|
||||||
|
<view class="huadao">{{
|
||||||
|
$t('authentication.content')
|
||||||
|
}}</view>
|
||||||
|
<view :class="
|
||||||
|
isError ? 'huadao_done error_bg' : 'huadao_done'
|
||||||
|
" :style="'width:' + doneWindth + 'px;'"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
postDataByParams
|
||||||
|
} from '../../utils/api.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'slider-verify',
|
||||||
|
props: {
|
||||||
|
isShow: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
x: 0, //初始距离
|
||||||
|
oldx: 0, //移动的距离
|
||||||
|
top: 0, //拼图的top距离
|
||||||
|
canvasSrc: '',
|
||||||
|
blockSrc: '',
|
||||||
|
blockY: '',
|
||||||
|
nonceStr: '',
|
||||||
|
blockWidth: 50, //块图像的宽度(blockWidth大于14)
|
||||||
|
blockHeight: 50,
|
||||||
|
isLoading: true,
|
||||||
|
doneWindth: 0,
|
||||||
|
isError: false,
|
||||||
|
isMess: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// 每次打开重新刷新拼图
|
||||||
|
isShow(newValue, oldValue) {
|
||||||
|
if (newValue) {
|
||||||
|
this.refreshVerify() //刷新
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
var that = this
|
||||||
|
// that.refreshVerify();
|
||||||
|
that.getCaptcha()
|
||||||
|
// console.log(this.$i18n.locale, 'this.$i18n.locale')
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getCaptcha() {
|
||||||
|
this.isLoading = true
|
||||||
|
var that = this
|
||||||
|
let url = 'generate/captcha'
|
||||||
|
let params = {
|
||||||
|
canvasWidth: 320, //画布的宽度(canvasWidth大于41并且(canvasWidth-10)/2 - 1> blockWidth)
|
||||||
|
canvasHeight: 190, //画布的高度(canvasHeight大于26并且 canvasHeight - blockHeight > 11
|
||||||
|
blockWidth: this.blockWidth, //块图像的宽度(blockWidth大于14)
|
||||||
|
blockHeight: this.blockHeight, //块图像的高度(blockHeight大于14)
|
||||||
|
// blockRadius: 9, //块图像的圆角半径
|
||||||
|
place: 0 //图像来源标识,0表示URL下载,1表示本地文件 一般用0
|
||||||
|
}
|
||||||
|
postDataByParams(url, params)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status === 0) {
|
||||||
|
that.canvasSrc = 'data:image/jpg;base64,' + res.data.canvasSrc
|
||||||
|
that.blockSrc = 'data:image/jpg;base64,' + res.data.blockSrc
|
||||||
|
that.blockY = res.data.blockY
|
||||||
|
that.nonceStr = res.data.nonceStr
|
||||||
|
that.isLoading = false
|
||||||
|
} else {
|
||||||
|
this.$emit('sliderError', encodeURIComponent(JSON.stringify(res)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
this.$emit('sliderError', encodeURIComponent(JSON.stringify(err)), true)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//刷新验证
|
||||||
|
refreshVerify() {
|
||||||
|
this.x = 1
|
||||||
|
this.oldx = 1
|
||||||
|
setTimeout(() => {
|
||||||
|
this.x = 0
|
||||||
|
this.oldx = 0
|
||||||
|
this.doneWindth = 0
|
||||||
|
}, 300)
|
||||||
|
this.getCaptcha()
|
||||||
|
this.isError = false
|
||||||
|
this.isMess = false
|
||||||
|
},
|
||||||
|
/* 滑动中 */
|
||||||
|
startMove(e) {
|
||||||
|
// console.log(e.detail.x)
|
||||||
|
this.oldx = e.detail.x / 2 - 5
|
||||||
|
if (e.detail.x > 1) {
|
||||||
|
this.doneWindth = e.detail.x + 30
|
||||||
|
} else {
|
||||||
|
this.doneWindth = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* 滑动结束 */
|
||||||
|
async endTouchMove() {
|
||||||
|
var that = this
|
||||||
|
// console.log('滑块结束')
|
||||||
|
let url = 'validate/captcha'
|
||||||
|
let params = {
|
||||||
|
nonceStr: this.nonceStr,
|
||||||
|
blockX: this.oldx * 2 + 5
|
||||||
|
}
|
||||||
|
postDataByParams(url, params)
|
||||||
|
.then((res) => {
|
||||||
|
this.isMess = true
|
||||||
|
if (res.status == 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
that.$emit('touchSliderResult', res.data.nonceStr)
|
||||||
|
}, 1000)
|
||||||
|
} else {
|
||||||
|
this.isError = true
|
||||||
|
this.$emit('sliderError', encodeURIComponent(JSON.stringify(res)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
this.$emit('sliderError', encodeURIComponent(JSON.stringify(err)), true)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/* 重置阴影位置 */
|
||||||
|
/* resetMove() {
|
||||||
|
this.x = 1;
|
||||||
|
this.oldx = 1;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.x = 0;
|
||||||
|
this.oldx = 0;
|
||||||
|
}, 300);
|
||||||
|
}, */
|
||||||
|
// 关闭
|
||||||
|
closeSlider() {
|
||||||
|
this.$emit('touchSliderResult', false)
|
||||||
|
},
|
||||||
|
//隐藏滑块验证弹窗
|
||||||
|
hideSliderBox() {
|
||||||
|
this.$emit('hideSliderBox')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.slider-verify-box {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error_box {
|
||||||
|
// background: url('../../static/image/slider-verify/bg_error.png') no-repeat !important;
|
||||||
|
background-size: 100% 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyBox {
|
||||||
|
// width: 588rpx;
|
||||||
|
// height: 662rpx;
|
||||||
|
padding: 218rpx 45rpx 30rpx 45rpx;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
// width: 85%;
|
||||||
|
// background-color: #fff;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
// background: url('../../static/image/slider-verify/bg.png') no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
border-radius: 20upx;
|
||||||
|
// box-shadow: 0 0 5upx rgba(0, 0, 0, 1);
|
||||||
|
|
||||||
|
|
||||||
|
.slider-verify-box-close {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-title {
|
||||||
|
font-size: 36upx;
|
||||||
|
text-align: center;
|
||||||
|
padding: 12rpx 0;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
// width: 560rpx;
|
||||||
|
// padding: 0 ;
|
||||||
|
// margin: 0 auto;
|
||||||
|
|
||||||
|
.slide-tips {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: rgba(2, 20, 33, 0.45);
|
||||||
|
padding: 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-pintu {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.reload {
|
||||||
|
position: absolute;
|
||||||
|
right: 10rpx;
|
||||||
|
top: 10rpx;
|
||||||
|
z-index: 110;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load {
|
||||||
|
width: 320px;
|
||||||
|
height: 190px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pintu {
|
||||||
|
width: 320px;
|
||||||
|
height: 190px;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pintukuai {
|
||||||
|
position: absolute;
|
||||||
|
/* top: 0;
|
||||||
|
left: 0; */
|
||||||
|
z-index: 100;
|
||||||
|
box-shadow: 0 0 5upx rgba(0, 0, 0, 0.3);
|
||||||
|
|
||||||
|
image {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
/* width: 560rpx;
|
||||||
|
height: 315rpx; */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mark {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: #000000;
|
||||||
|
z-index: 101;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 60%;
|
||||||
|
height: 50rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.yinying {
|
||||||
|
position: absolute;
|
||||||
|
width: 120rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-movearea {
|
||||||
|
position: relative;
|
||||||
|
height: 80upx;
|
||||||
|
width: 320px;
|
||||||
|
margin-top: 25rpx;
|
||||||
|
|
||||||
|
movable-area {
|
||||||
|
width: 100%;
|
||||||
|
height: 64rpx;
|
||||||
|
|
||||||
|
.movable-view {
|
||||||
|
width: 100upx;
|
||||||
|
height: 74rpx;
|
||||||
|
border-radius: 40upx;
|
||||||
|
// background-color: #699A70;
|
||||||
|
background-image: url(../../static/image/slider-verify/icon-button-normal.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: auto 30upx;
|
||||||
|
background-position: center;
|
||||||
|
position: relative;
|
||||||
|
z-index: 100;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn_info {
|
||||||
|
background-color: #878787 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn_error {
|
||||||
|
background-color: #fd343c !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn_success {
|
||||||
|
background-color: #699a70 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error_bg {
|
||||||
|
background-color: #ffb7ba !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success_bg {
|
||||||
|
background-color: #aad0b0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.huadao {
|
||||||
|
width: 100%;
|
||||||
|
// width: 320px;
|
||||||
|
height: 66upx;
|
||||||
|
line-height: 66upx;
|
||||||
|
background: #ededed;
|
||||||
|
// box-shadow: inset 0 0 5upx #EDEDED;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
color: #bcbcbc;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
top: 7rpx;
|
||||||
|
left: 0;
|
||||||
|
font-size: 28rpx;
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
|
||||||
|
.huadao_done {
|
||||||
|
height: 66upx;
|
||||||
|
line-height: 66upx;
|
||||||
|
background: #aad0b0;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
top: 7rpx;
|
||||||
|
left: 0;
|
||||||
|
font-size: 28rpx;
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
</style>
|
@ -3,7 +3,7 @@ import { useRouter, useRoute } from 'vue-router';
|
|||||||
import Vcode from "vue3-puzzle-vcode";
|
import Vcode from "vue3-puzzle-vcode";
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import countryCode from '../countryRegion/data/index.js'
|
import countryCode from '../countryRegion/data/index.js'
|
||||||
import {senCode, userLogin,userCaptcha,userCaptchaValidate} from "@/api/auth/index.js";
|
import {senCode, userLogin,userCaptcha,userCaptchaValidate,} from "@/api/auth/index.js";
|
||||||
import {authStore} from "@/stores/auth/index.js";
|
import {authStore} from "@/stores/auth/index.js";
|
||||||
import {message} from '@/components/x-message/useMessage.js'
|
import {message} from '@/components/x-message/useMessage.js'
|
||||||
import {fddCheck} from "~/api/goods/index.js";
|
import {fddCheck} from "~/api/goods/index.js";
|
||||||
@ -14,7 +14,6 @@ const router = useRouter();
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { locale } = useI18n()
|
const { locale } = useI18n()
|
||||||
const imgs=ref([zu6020])
|
const imgs=ref([zu6020])
|
||||||
console.log('zu6020');
|
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
name: 'login',
|
name: 'login',
|
||||||
@ -93,7 +92,7 @@ const captchaUrl=ref('')
|
|||||||
const captchaVerifyUrl=ref('')
|
const captchaVerifyUrl=ref('')
|
||||||
const blockY=ref(0)
|
const blockY=ref(0)
|
||||||
const getCode =async () => {
|
const getCode =async () => {
|
||||||
|
loadingRef.value.loading1=true
|
||||||
const res=await userCaptcha({
|
const res=await userCaptcha({
|
||||||
"canvasWidth": 320, //画布的宽度(canvasWidth大于41并且(canvasWidth-10)/2 - 1> blockWidth)
|
"canvasWidth": 320, //画布的宽度(canvasWidth大于41并且(canvasWidth-10)/2 - 1> blockWidth)
|
||||||
"canvasHeight": 191, //画布的高度(canvasHeight大于26并且 canvasHeight - blockHeight > 11
|
"canvasHeight": 191, //画布的高度(canvasHeight大于26并且 canvasHeight - blockHeight > 11
|
||||||
@ -106,8 +105,9 @@ const getCode =async () => {
|
|||||||
captchaUrl.value=`data:image/png;base64,${res.data.canvasSrc}`
|
captchaUrl.value=`data:image/png;base64,${res.data.canvasSrc}`
|
||||||
captchaVerifyUrl.value=`data:image/png;base64,${res.data.blockSrc}`
|
captchaVerifyUrl.value=`data:image/png;base64,${res.data.blockSrc}`
|
||||||
blockY.value=res.data.blockY
|
blockY.value=res.data.blockY
|
||||||
captcha.value=res.data.nonceStr
|
captcha.value.nonceStr=res.data.nonceStr
|
||||||
isShow.value=true
|
isShow.value=true
|
||||||
|
loadingRef.value.loading1=false
|
||||||
}
|
}
|
||||||
// loadingRef.value.loading1=true
|
// loadingRef.value.loading1=true
|
||||||
// const res=await senCode({
|
// const res=await senCode({
|
||||||
@ -184,16 +184,30 @@ const onClose=()=>{
|
|||||||
isShow.value=false
|
isShow.value=false
|
||||||
}
|
}
|
||||||
const onLeave =async (moveX, callback) => {
|
const onLeave =async (moveX, callback) => {
|
||||||
console.log('moveX',moveX);
|
loadingRef.value.loading1=true
|
||||||
const res=await userCaptchaValidate({
|
const res=await senCode({
|
||||||
|
telNum:phoneNum.value,
|
||||||
|
zone:selectedZone.value,
|
||||||
|
verifyCaptcha:{
|
||||||
blockX:moveX,
|
blockX:moveX,
|
||||||
nonceStr:captcha.value.nonceStr
|
nonceStr:captcha.value.nonceStr
|
||||||
})
|
|
||||||
if (res.status===0){
|
|
||||||
callback(true)
|
|
||||||
}else {
|
|
||||||
callback(false)
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
loadingRef.value.loading1=false
|
||||||
|
if (res.status===408){
|
||||||
|
callback(false)
|
||||||
|
getCode()
|
||||||
|
}else{
|
||||||
|
callback(true)
|
||||||
|
setTimeout(() => {
|
||||||
|
pane.value = 1
|
||||||
|
vanSwipeRef.value?.swipeTo(pane.value)
|
||||||
|
startCountdown();
|
||||||
|
isShow.value=false
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -273,7 +287,6 @@ const onLeave =async (moveX, callback) => {
|
|||||||
</div>
|
</div>
|
||||||
<van-popup v-model:show="isShow" round>
|
<van-popup v-model:show="isShow" round>
|
||||||
<YourPuzzleComponent
|
<YourPuzzleComponent
|
||||||
:show="true"
|
|
||||||
:blockY="blockY"
|
:blockY="blockY"
|
||||||
:bgImageUrl="captchaUrl"
|
:bgImageUrl="captchaUrl"
|
||||||
:sliderImageUrl="captchaVerifyUrl"
|
:sliderImageUrl="captchaVerifyUrl"
|
||||||
|