VerifyPoints.vue 9.68 KB
<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 class="verify-refresh" style="z-index:3" @click="refresh" v-show="showRefresh">
                    <i class="iconfont icon-refresh"></i>
                </div>
                <img :src="'data:image/png;base64,'+pointBackImgBase" 
                ref="canvas"
                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'
                    }
                }
            }
        },
        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
            }
        },
        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)
                        let 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(){
                let data = {
                    captchaType:this.captchaType
                }
                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;
                    }
                })
            },
            //坐标转换函数
            pointTransfrom(pointArr,imgSize){
                var newPointArr = pointArr.map(p=>{
                    let x = Math.round(310 * p.x/parseInt(imgSize.imgWidth)) 
                    let y =Math.round(155 * p.y/parseInt(imgSize.imgHeight)) 
                    return {x,y}
                })
                // console.log(newPointArr,"newPointArr");
                return newPointArr
            }
        },
        watch: {
            // type变化则全面刷新
            type: {
                immediate: true,
                handler() {
                    this.init()
                }
            }
        },
        mounted() {
            // 禁止拖拽
            this.$el.onselectstart = function () {
                return false
            }
        },
    }
</script>