個(gè)人解決方案,歡迎批評(píng)指正。
在網(wǎng)絡(luò)上找了幾款別人封裝好的插件,最后選用vue-puzzle-vcode來(lái)實(shí)現(xiàn)。具體使用:
npm install vue-puzzle-vcode
代碼:
<template>
<Vcode
:show="isShow"
@onSuccess="onSuccess"
@onClose="onClose"
/>
<button @click="onSubmit">登錄</button>
</template>
<script>
import Vcode from "vue-puzzle-vcode";
export default {
data(){
return {
isShow: false, // 驗(yàn)證碼模態(tài)框是否出現(xiàn)
}
},
components:{
Vcode
},
methods:{
onSubmit(){
this.isShow = true;
},
// 用戶通過(guò)了驗(yàn)證
onSuccess(msg){
this.isShow = false; // 通過(guò)驗(yàn)證后,需要手動(dòng)隱藏模態(tài)框
},
// 用戶點(diǎn)擊遮罩層,應(yīng)該關(guān)閉模態(tài)框
onClose(){
this.isShow = false;
}
}
}
</script>
詳細(xì)用法參考:官方文檔
由于這個(gè)是純前端的實(shí)現(xiàn),沒(méi)有后端校驗(yàn)?zāi)K,所以我做了修改。
前后端校驗(yàn)的思路:
后端生成圖片拼圖位置的X、Y坐標(biāo)(pinX、pinY),并存入session中,然后將值傳給前端。前端以此做相應(yīng)驗(yàn)證的繪制。然后用戶操作后,前端獲取用戶移動(dòng)到的最終X坐標(biāo)(newX)判斷驗(yàn)證成功,再將用戶移動(dòng)到的最終X坐標(biāo)傳入后端,后端作為校驗(yàn)依據(jù)。
vue-puzzle-vcode插件是隨機(jī)生成拼圖位置的X、Y坐標(biāo)(pinX、pinY)的,我將組件新增輸入?yún)?shù)pinXY=[pinX,pinY]。
修改vue-puzzle-vcode源碼app.vue,新增傳入?yún)?shù)pinXY,然后把pinX和pinY的賦值部分傳修改成pinXY[0] pinXY[1]。最后,新增onSuccess的傳出值,把this.newX加上去。然后將this.newX和校驗(yàn)距離x丟到后端接口,后端就以像前臺(tái)一樣的校驗(yàn)方式去通過(guò)this.newX計(jì)算x,進(jìn)行校驗(yàn)。

/**
* //后端校驗(yàn)公式
* //session值:pinX pinY
* //傳入值newX
*const startWidth=50
* const startX=0
* const canvasWidth=310
* var w = startWidth + newX - startX;
* var styleWidth=w < 50 ? 50 : w > this.canvasWidth ? this.canvasWidth : w;
* var x = Math.abs(
pinX -
(styleWidth - 50) +
20 * ((styleWidth - 50) / (canvasWidth - 50)) -
3
);
x<10 且等于前端傳入的x 則成功校驗(yàn)
*/
修改完app.vue記得將cmd運(yùn)行路徑改為vue-puzzle-vcode下,npm install后,在npm run build 重新生成dist下面的文件,才能生效哦。
修改后引用組件:
<template>
<div>
<Vcode
:show="isShow"
:pinXY="pinXY"
:canvasWidth="canvasWidth"
:canvasHeight="canvasHeight"
@onSuccess="onSuccess"
@onClose="onClose"
:imgs="imgs_arr"
/>
<el-button @click="onSubmit">登錄</el-button>
</div>
</template>
<script>
import Vcode from "vue-puzzle-vcode";
import imgs_arr from './imgData.js'
export default {
data(){
return {
pinXY:[0,0],
canvasWidth:310,
canvasHeight:160,
imgs_arr,
isShow: false, // 驗(yàn)證碼模態(tài)框是否出現(xiàn)
}
},
components:{
Vcode
},
methods:{
getPinXY(){
// let pinX=this.getRandom(90, this.canvasWidth - 90);
// let pinY=this.getRandom(20, this.canvasHeight - 90);
//后端以此方式生成
this.pinXY=[pinX,pinY]
console.log('pinxy')
console.log(this.pinXY)
},
// 工具 - 范圍隨機(jī)數(shù)
getRandom(min, max) {
return Math.round(Math.random() * (max - min) + min);
},
onSubmit(){
// this.getPinXY();
this.isShow = true;
},
// 用戶通過(guò)了驗(yàn)證
onSuccess(msg,newX){
//后端校驗(yàn)
this.isShow = false; // 通過(guò)驗(yàn)證后,需要手動(dòng)隱藏模態(tài)框
},
// 用戶點(diǎn)擊遮罩層,應(yīng)該關(guān)閉模態(tài)框
onClose(){
this.isShow = false;
},
},
created(){
// this.init()
}
}
</script>