You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
273 lines
7.8 KiB
273 lines
7.8 KiB
<template> |
|
<div style="position: relative"> |
|
<div class="verify-img-out"> |
|
<div |
|
class="verify-img-panel" |
|
:style="{ |
|
width: setSize.imgWidth, |
|
height: setSize.imgHeight, |
|
'background-size': setSize.imgWidth + ' ' + setSize.imgHeight, |
|
'margin-bottom': vSpace + 'px', |
|
}" |
|
> |
|
<div v-show="showRefresh" class="verify-refresh" style="z-index: 3" @click="refresh"> |
|
<i class="iconfont icon-refresh" /> |
|
</div> |
|
<img |
|
ref="canvas" |
|
:src="pointBackImgBase ? 'data:image/png;base64,' + pointBackImgBase : defaultImg" |
|
alt="" |
|
style="width: 100%; height: 100%; display: block" |
|
@click="bindingClick ? canvasClick($event) : undefined" |
|
/> |
|
|
|
<div |
|
v-for="(tempPoint, index) in tempPoints" |
|
:key="index" |
|
class="point-area" |
|
:style="{ |
|
'background-color': '#1abd6c', |
|
color: '#fff', |
|
'z-index': 9999, |
|
width: '20px', |
|
height: '20px', |
|
'text-align': 'center', |
|
'line-height': '20px', |
|
'border-radius': '50%', |
|
position: 'absolute', |
|
top: parseInt(tempPoint.y - 10) + 'px', |
|
left: parseInt(tempPoint.x - 10) + 'px', |
|
}" |
|
> |
|
{{ index + 1 }} |
|
</div> |
|
</div> |
|
</div> |
|
<!-- 'height': this.barSize.height, --> |
|
<div |
|
class="verify-bar-area" |
|
:style="{ |
|
width: setSize.imgWidth, |
|
color: this.barAreaColor, |
|
'border-color': this.barAreaBorderColor, |
|
'line-height': this.barSize.height, |
|
}" |
|
> |
|
<span class="verify-msg">{{ text }}</span> |
|
</div> |
|
</div> |
|
</template> |
|
<script type="text/babel"> |
|
/** |
|
* VerifyPoints |
|
* @description 点选 |
|
* */ |
|
import { resetSize, _code_chars, _code_color1, _code_color2 } from './../utils/util'; |
|
import { aesEncrypt } from './../utils/ase'; |
|
// import { reqGet, reqCheck } from './../api/index'; |
|
|
|
export default { |
|
name: 'VerifyPoints', |
|
props: { |
|
// 弹出式pop,固定fixed |
|
mode: { |
|
type: String, |
|
default: 'fixed', |
|
}, |
|
captchaType: { |
|
type: String, |
|
}, |
|
// 间隔 |
|
vSpace: { |
|
type: Number, |
|
default: 5, |
|
}, |
|
imgSize: { |
|
type: Object, |
|
default() { |
|
return { |
|
width: '310px', |
|
height: '155px', |
|
}; |
|
}, |
|
}, |
|
barSize: { |
|
type: Object, |
|
default() { |
|
return { |
|
width: '310px', |
|
height: '40px', |
|
}; |
|
}, |
|
}, |
|
defaultImg: { |
|
type: String, |
|
default: '', |
|
}, |
|
}, |
|
data() { |
|
return { |
|
secretKey: '', // 后端返回的ase加密秘钥 |
|
checkNum: 3, // 默认需要点击的字数 |
|
fontPos: [], // 选中的坐标信息 |
|
checkPosArr: [], // 用户点击的坐标 |
|
num: 1, // 点击的记数 |
|
pointBackImgBase: '', // 后端获取到的背景图片 |
|
poinTextList: [], // 后端返回的点击字体顺序 |
|
backToken: '', // 后端返回的token值 |
|
setSize: { |
|
imgHeight: 0, |
|
imgWidth: 0, |
|
barHeight: 0, |
|
barWidth: 0, |
|
}, |
|
tempPoints: [], |
|
text: '', |
|
barAreaColor: undefined, |
|
barAreaBorderColor: undefined, |
|
showRefresh: true, |
|
bindingClick: true, |
|
}; |
|
}, |
|
computed: { |
|
resetSize() { |
|
return resetSize; |
|
}, |
|
}, |
|
watch: { |
|
// type变化则全面刷新 |
|
type: { |
|
immediate: true, |
|
handler() { |
|
this.init(); |
|
}, |
|
}, |
|
}, |
|
mounted() { |
|
// 禁止拖拽 |
|
this.$el.onselectstart = function () { |
|
return false; |
|
}; |
|
}, |
|
methods: { |
|
init() { |
|
// 加载页面 |
|
this.fontPos.splice(0, this.fontPos.length); |
|
this.checkPosArr.splice(0, this.checkPosArr.length); |
|
this.num = 1; |
|
this.getPictrue(); |
|
this.$nextTick(() => { |
|
this.setSize = this.resetSize(this); // 重新设置宽度高度 |
|
this.$parent.$emit('ready', this); |
|
}); |
|
}, |
|
canvasClick(e) { |
|
this.checkPosArr.push(this.getMousePos(this.$refs.canvas, e)); |
|
if (this.num == this.checkNum) { |
|
this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e)); |
|
// 按比例转换坐标值 |
|
this.checkPosArr = this.pointTransfrom(this.checkPosArr, this.setSize); |
|
// 等创建坐标执行完 |
|
setTimeout(() => { |
|
// var flag = this.comparePos(this.fontPos, this.checkPosArr); |
|
// 发送后端请求 |
|
var captchaVerification = this.secretKey |
|
? aesEncrypt(this.backToken + '---' + JSON.stringify(this.checkPosArr), this.secretKey) |
|
: this.backToken + '---' + JSON.stringify(this.checkPosArr); |
|
const data = { |
|
captchaType: this.captchaType, |
|
pointJson: this.secretKey |
|
? aesEncrypt(JSON.stringify(this.checkPosArr), this.secretKey) |
|
: JSON.stringify(this.checkPosArr), |
|
token: this.backToken, |
|
}; |
|
reqCheck(data).then((res) => { |
|
if (res.repCode == '0000') { |
|
this.barAreaColor = '#4cae4c'; |
|
this.barAreaBorderColor = '#5cb85c'; |
|
this.text = '验证成功'; |
|
this.bindingClick = false; |
|
if (this.mode == 'pop') { |
|
setTimeout(() => { |
|
this.$parent.clickShow = false; |
|
this.refresh(); |
|
}, 1500); |
|
} |
|
this.$parent.$emit('success', { captchaVerification }); |
|
} else { |
|
this.$parent.$emit('error', this); |
|
this.barAreaColor = '#d9534f'; |
|
this.barAreaBorderColor = '#d9534f'; |
|
this.text = '验证失败'; |
|
setTimeout(() => { |
|
this.refresh(); |
|
}, 700); |
|
} |
|
}); |
|
}, 400); |
|
} |
|
if (this.num < this.checkNum) { |
|
this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e)); |
|
} |
|
}, |
|
|
|
// 获取坐标 |
|
getMousePos: function (obj, e) { |
|
var x = e.offsetX; |
|
var y = e.offsetY; |
|
return { x, y }; |
|
}, |
|
// 创建坐标点 |
|
createPoint: function (pos) { |
|
this.tempPoints.push(Object.assign({}, pos)); |
|
return ++this.num; |
|
}, |
|
refresh: function () { |
|
this.tempPoints.splice(0, this.tempPoints.length); |
|
this.barAreaColor = '#000'; |
|
this.barAreaBorderColor = '#ddd'; |
|
this.bindingClick = true; |
|
this.fontPos.splice(0, this.fontPos.length); |
|
this.checkPosArr.splice(0, this.checkPosArr.length); |
|
this.num = 1; |
|
this.getPictrue(); |
|
this.text = '验证失败'; |
|
this.showRefresh = true; |
|
}, |
|
|
|
// 请求背景图片和验证图片 |
|
getPictrue() { |
|
const data = { |
|
captchaType: this.captchaType, |
|
clientUid: localStorage.getItem('point'), |
|
ts: Date.now(), // 现在的时间戳 |
|
}; |
|
reqGet(data).then((res) => { |
|
if (res.repCode == '0000') { |
|
this.pointBackImgBase = res.repData.originalImageBase64; |
|
this.backToken = res.repData.token; |
|
this.secretKey = res.repData.secretKey; |
|
this.poinTextList = res.repData.wordList; |
|
this.text = '请依次点击【' + this.poinTextList.join(',') + '】'; |
|
} else { |
|
this.text = res.repMsg; |
|
} |
|
|
|
// 判断接口请求次数是否失效 |
|
if (res.repCode == '6201') { |
|
this.pointBackImgBase = null; |
|
} |
|
}); |
|
}, |
|
// 坐标转换函数 |
|
pointTransfrom(pointArr, imgSize) { |
|
var newPointArr = pointArr.map((p) => { |
|
const x = Math.round((310 * p.x) / parseInt(imgSize.imgWidth)); |
|
const y = Math.round((155 * p.y) / parseInt(imgSize.imgHeight)); |
|
return { x, y }; |
|
}); |
|
return newPointArr; |
|
}, |
|
}, |
|
}; |
|
</script>
|
|
|