(function ($, window, document, undefined) {
//请求图片get事件
function getPictrue(data, baseUrl) {
return new Promise((resolve, reject) => {
$.ajax({
type: "post",
contentType: "application/json;charset=UTF-8",
url: baseUrl + "/csi/captcha/get",
data: JSON.stringify(data),
success: function (res) {
resolve(res)
},
fail: function (err) {
reject(err)
}
})
})
}
//验证图片check事件
function checkPictrue(data, baseUrl) {
return new Promise((resolve, reject) => {
$.ajax({
type: "post",
contentType: "application/json;charset=UTF-8",
url: baseUrl + "/csi/captcha/check",
data: JSON.stringify(data),
success: function (res) {
if (res.repCode == "0000") {
resolve(res)
setTimeout(function () {
$('#click').hide(true)
$('#slipping').hide(true)
$(".modal-backdrop").css('disp }, 1000);
}
resolve(res)
},
fail: function (err) {
reject(err)
}
})
})
}
//定义Slide的构造函数
var Slide = function (ele, opt) {
this.$element = ele,
this.backToken = null,
this.moveLeftDistance = 0,
this.secretKey = '',
this.defaults = {
baseUrl: "/",
containerId: '',
captchaType: "blockPuzzle",
mode: 'fixed', //弹出式pop,固定fixed
vOffset: 5,
vSpace: 5,
explain: '向右滑动完成验证',
imgSize: {
width: '310px',
height: '155px',
},
blockSize: {
width: '50px',
height: '50px',
},
circleRadius: '10px',
barSize: {
width: '310px',
height: '50px',
},
beforeCheck() {
return true
},
ready: function () {
},
success: function () {
},
error: function () {
}
},
this.options = $.extend({}, this.defaults, opt)
};
//定义Slide的方法
Slide.prototype = {
init: function () {
var _this = this;
//加载页面
this.loadDom();
_this.refresh();
this.options.ready();
this.$element[0].onselectstart = document.body.ondrag = function () {
return false;
};
if (this.options.mode == 'pop') {
_this.$element.find('.verifybox-close').on('click', function () {
_this.$element.find(".mask").css("display", "none");
_this.refresh();
});
let clickBtn = document.getElementById(this.options.containerId);
clickBtn && (clickBtn.onclick = function () {
if (_this.options.beforeCheck()) {
_this.$element.find(".mask").css("display", "block");
}
})
}
//按下
this.htmlDoms.move_block.on('touchstart', function (e) {
_this.start(e);
});
this.htmlDoms.move_block.on('mousedown', function (e) {
_this.start(e);
});
//拖动(移动端)
window.addEventListener("touchmove", function (e) {
_this.move(e);
});
//拖动(PC端)
window.addEventListener("mousemove", function (e) {
_this.move(e);
});
//鼠标松开(移动端)
window.addEventListener("touchend", function () {
_this.end();
});
//鼠标松开(PC端)
window.addEventListener("mouseup", function () {
_this.end();
});
//刷新
_this.$element.find('.verify-refresh').on('click', function () {
_this.refresh();
});
},
//初始化加载
loadDom: function () {
this.status = false; //鼠标状态
this.isEnd = false; //是够验证完成
this.setSize = this.resetSize(this); //重新设置宽度高度
this.plusWidth = 0;
this.plusHeight = 0;
this.x = 0;
this.y = 0;
var panelHtml = '';
var wrapHtml = '';
var wrapStartHtml = '';
var wrapEndHtml = '';
this.lengthPercent = (parseInt(this.setSize.img_width) - parseInt(this.setSize.block_width) - parseInt(this.setSize.circle_radius) - parseInt(this.setSize.circle_radius) * 0.8) / (parseInt(this.setSize.img_width) - parseInt(this.setSize.bar_height));
wrapStartHtml = `
请完成安全验证
`
if (this.options.mode == 'pop') {
panelHtml = wrapStartHtml
}
panelHtml += `
`;
this.plusWidth = parseInt(this.setSize.block_width) + parseInt(this.setSize.circle_radius) * 2 - parseInt(this.setSize.circle_radius) * 0.2;
this.plusHeight = parseInt(this.setSize.block_height) + parseInt(this.setSize.circle_radius) * 2 - parseInt(this.setSize.circle_radius) * 0.2;
panelHtml += `
`;
wrapEndHtml = `
`
if (this.options.mode == 'pop') {
panelHtml += wrapEndHtml
}
this.$element.append(panelHtml);
this.htmlDoms = {
tips: this.$element.find('.verify-tips'),
sub_block: this.$element.find('.verify-sub-block'),
out_panel: this.$element.find('.verify-img-out'),
img_panel: this.$element.find('.verify-img-panel'),
img_canvas: this.$element.find('.verify-img-canvas'),
bar_area: this.$element.find('.verify-bar-area'),
move_block: this.$element.find('.verify-move-block'),
left_bar: this.$element.find('.verify-left-bar'),
msg: this.$element.find('.verify-msg'),
icon: this.$element.find('.verify-icon'),
refresh: this.$element.find('.verify-refresh')
};
this.$element.css('position', 'relative');
this.htmlDoms.sub_block.css({
'height': this.setSize.img_height, 'width': Math.floor(parseInt(this.setSize.img_width) * 47 / 310) + 'px',
'top': -(parseInt(this.setSize.img_height) + this.options.vSpace) + 'px'
})
this.htmlDoms.out_panel.css('height', parseInt(this.setSize.img_height) + this.options.vSpace + 'px');
this.htmlDoms.img_panel.css({'width': this.setSize.img_width, 'height': this.setSize.img_height});
this.htmlDoms.bar_area.css({
'width': this.setSize.img_width,
'height': this.setSize.bar_height,
'line-height': this.setSize.bar_height
});
this.htmlDoms.move_block.css({'width': this.setSize.bar_height, 'height': this.setSize.bar_height});
this.htmlDoms.left_bar.css({'width': this.setSize.bar_height, 'height': this.setSize.bar_height});
},
//鼠标按下
start: function (e) {
if (!e.touches) { //兼容移动端
var x = e.clientX;
} else { //兼容PC端
var x = e.touches[0].pageX;
}
this.startLeft = Math.floor(x - this.htmlDoms.bar_area[0].getBoundingClientRect().left);
this.startMoveTime = new Date().getTime();
if (this.isEnd == false) {
this.htmlDoms.msg.text('');
this.htmlDoms.move_block.css('background-color', '#337ab7');
this.htmlDoms.left_bar.css('border-color', '#337AB7');
this.htmlDoms.icon.css('color', '#fff');
e.stopPropagation();
this.status = true;
}
},
//鼠标移动
move: function (e) {
if (this.status && this.isEnd == false) {
if (!e.touches) { //兼容移动端
var x = e.clientX;
} else { //兼容PC端
var x = e.touches[0].pageX;
}
var bar_area_left = this.htmlDoms.bar_area[0].getBoundingClientRect().left;
var move_block_left = x - bar_area_left; //小方块相对于父元素的left值
if (move_block_left >= (this.htmlDoms.bar_area[0].offsetWidth - parseInt(this.setSize.bar_height) + parseInt(parseInt(this.setSize.block_width) / 2) - 2)) {
move_block_left = (this.htmlDoms.bar_area[0].offsetWidth - parseInt(this.setSize.bar_height) + parseInt(parseInt(this.setSize.block_width) / 2) - 2);
}
if (move_block_left <= parseInt(parseInt(this.setSize.block_width) / 2)) {
move_block_left = parseInt(parseInt(this.setSize.block_width) / 2);
}
//拖动后小方块的left值
this.htmlDoms.move_block.css('left', move_block_left - this.startLeft + "px");
this.htmlDoms.left_bar.css('width', move_block_left - this.startLeft + "px");
this.htmlDoms.sub_block.css('left', "0px");
this.moveLeftDistance = move_block_left - this.startLeft
}
},
//鼠标松开
end: function () {
this.endMovetime = new Date().getTime();
var _this = this;
//判断是否重合
if (this.status && this.isEnd == false) {
var vOffset = parseInt(this.options.vOffset);
this.moveLeftDistance = this.moveLeftDistance * 310 / parseInt(this.setSize.img_width)
//图片滑动
// 由于需要获取用户信息,后端修改了request参数,直接传对象会报错,需要多包裹一层
let data = {
captchaVO:
{
captchaType: this.options.captchaType,
pointJson: this.secretKey ? aesEncrypt(JSON.stringify({
x: this.moveLeftDistance,
y: 5.0
}), this.secretKey) : JSON.stringify({x: this.moveLeftDistance, y: 5.0}),
token: this.backToken
}
}
var captchaVerification = this.secretKey ? aesEncrypt(this.backToken + '---' + JSON.stringify({
x: this.moveLeftDistance,
y: 5.0
}), this.secretKey) : this.backToken + '---' + JSON.stringify({x: this.moveLeftDistance, y: 5.0});
checkPictrue(data, this.options.baseUrl).then(res => {
res = JSON.parse(res)
// 请求反正成功的判断
if (res.repCode == "0000") {
this.htmlDoms.move_block.css('background-color', '#5cb85c');
this.htmlDoms.left_bar.css({'border-color': '#5cb85c', 'background-color': '#fff'});
this.htmlDoms.icon.css('color', '#fff');
this.htmlDoms.icon.removeClass('fa-chevron-right');
this.htmlDoms.icon.addClass('fa-check');
//提示框
this.htmlDoms.tips.addClass('suc-bg').removeClass('err-bg')
this.htmlDoms.tips.css({"display": "block", animation: "move 1s cubic-bezier(0, 0, 0.39, 1.01)"});
this.htmlDoms.tips.text(`${((this.endMovetime - this.startMoveTime) / 1000).toFixed(2)}s验证成功`)
this.isEnd = true;
setTimeout(res => {
_this.$element.find(".mask").css("display", "none");
this.htmlDoms.tips.css({"display": "none", animation: "none"});
_this.refresh();
}, 1000)
this.options.success({captchaVerification});
} else {
this.htmlDoms.move_block.css('background-color', '#d9534f');
this.htmlDoms.left_bar.css('border-color', '#d9534f');
this.htmlDoms.icon.css('color', '#fff');
this.htmlDoms.icon.removeClass('fa-chevron-right');
this.htmlDoms.icon.addClass('fa-close');
this.htmlDoms.tips.addClass('err-bg').removeClass('suc-bg')
this.htmlDoms.tips.css({"display": "block", animation: "move 1.3s cubic-bezier(0, 0, 0.39, 1.01)"});
this.htmlDoms.tips.text(res.repMsg)
setTimeout(function () {
_this.refresh();
}, 400);
setTimeout(() => {
this.htmlDoms.tips.css({"display": "none", animation: "none"});
}, 1300)
this.options.error(this);
}
})
this.status = false;
}
},
resetSize: function (obj) {
var img_width, img_height, bar_width, bar_height, block_width, block_height, circle_radius; //图片的宽度、高度,移动条的宽度、高度
var parentWidth = obj.$element.parent().width() || $(window).width();
var parentHeight = obj.$element.parent().height() || $(window).height();
if (obj.options.imgSize.width.indexOf('%') != -1) {
img_width = parseInt(obj.options.imgSize.width) / 100 * parentWidth + 'px';
} else {
img_width = obj.options.imgSize.width;
}
if (obj.options.imgSize.height.indexOf('%') != -1) {
img_height = parseInt(obj.options.imgSize.height) / 100 * parentHeight + 'px';
} else {
img_height = obj.options.imgSize.height;
}
if (obj.options.barSize.width.indexOf('%') != -1) {
bar_width = parseInt(obj.options.barSize.width) / 100 * parentWidth + 'px';
} else {
bar_width = obj.options.barSize.width;
}
if (obj.options.barSize.height.indexOf('%') != -1) {
bar_height = parseInt(obj.options.barSize.height) / 100 * parentHeight + 'px';
} else {
bar_height = obj.options.barSize.height;
}
if (obj.options.blockSize) {
if (obj.options.blockSize.width.indexOf('%') != -1) {
block_width = parseInt(obj.options.blockSize.width) / 100 * parentWidth + 'px';
} else {
block_width = obj.options.blockSize.width;
}
if (obj.options.blockSize.height.indexOf('%') != -1) {
block_height = parseInt(obj.options.blockSize.height) / 100 * parentHeight + 'px';
} else {
block_height = obj.options.blockSize.height;
}
}
if (obj.options.circleRadius) {
if (obj.options.circleRadius.indexOf('%') != -1) {
circle_radius = parseInt(obj.options.circleRadius) / 100 * parentHeight + 'px';
} else {
circle_radius = obj.options.circleRadius;
}
}
return {
img_width: img_width,
img_height: img_height,
bar_width: bar_width,
bar_height: bar_height,
block_width: block_width,
block_height: block_height,
circle_radius: circle_radius
};
},
//刷新
refresh: function () {
var _this = this;
this.htmlDoms.refresh.show();
this.$element.find('.verify-msg:eq(1)').text('');
this.$element.find('.verify-msg:eq(1)').css('color', '#000');
this.htmlDoms.move_block.animate({'left': '0px'}, 'fast');
this.htmlDoms.left_bar.animate({'width': parseInt(this.setSize.bar_height)}, 'fast');
this.htmlDoms.left_bar.css({'border-color': '#ddd'});
this.htmlDoms.move_block.css('background-color', '#fff');
this.htmlDoms.icon.css('color', '#000');
this.htmlDoms.icon.removeClass('fa-close');
this.htmlDoms.icon.addClass('fa-chevron-right');
this.$element.find('.verify-msg:eq(0)').text(this.options.explain);
this.isEnd = false;
// 由于需要获取用户信息,后端修改了request参数,直接传对象会报错,需要多包裹一层
let pictureParam = {
captchaVO: {captchaType: "blockPuzzle"}
};
getPictrue(pictureParam, this.options.baseUrl).then(res => {
res = JSON.parse(res);
console.log(res)
if (res.repCode == "0000") {
this.$element.find(".backImg")[0].src = 'data:image/png;base64,' + res.repData.originalImageBase64
this.$element.find(".bock-backImg")[0].src = 'data:image/png;base64,' + res.repData.jigsawImageBase64
this.secretKey = res.repData.secretKey
this.backToken = res.repData.token
}
});
this.htmlDoms.sub_block.css('left', "0px");
},
};
//定义Points的构造函数
var Points = function (ele, opt) {
this.$element = ele,
this.backToken = null,
this.secretKey = '',
this.defaults = {
baseUrl: "/",
captchaType: "clickWord",
containerId: '',
mode: 'fixed', //弹出式pop,固定fixed
checkNum: 3, //校对的文字数量
vSpace: 5, //间隔
imgSize: {
width: '310px',
height: '155px',
},
barSize: {
width: '310px',
height: '50px',
},
beforeCheck() {
return true
},
ready: function () {
},
success: function () {
},
error: function () {
}
},
this.options = $.extend({}, this.defaults, opt)
};
//定义Points的方法
Points.prototype = {
init: function () {
var _this = this;
//加载页面
_this.loadDom();
_this.refresh();
_this.options.ready();
this.$element[0].onselectstart = document.body.ondrag = function () {
return false;
};
if (this.options.mode == 'pop') {
_this.$element.find('.verifybox-close').on('click', function () {
_this.$element.find(".mask").css("display", "none");
});
let clickBtn = document.getElementById(this.options.containerId);
clickBtn && (clickBtn.onclick = function () {
if (_this.options.beforeCheck()) {
_this.$element.find(".mask").css("display", "block");
}
})
}
// 注册点击验证事件
_this.$element.find('.back-img').on('click', function (e) {
_this.checkPosArr.push(_this.getMousePos(this, e));
if (_this.num == _this.options.checkNum) {
_this.num = _this.createPoint(_this.getMousePos(this, e));
//按比例转换坐标值
_this.checkPosArr = _this.pointTransfrom(_this.checkPosArr, _this.setSize);
setTimeout(() => {
let data = {
captchaVO:
{
captchaType: _this.options.captchaType,
pointJson: _this.secretKey ? aesEncrypt(JSON.stringify(_this.checkPosArr), _this.secretKey) : JSON.stringify(_this.checkPosArr),
token: _this.backToken
}
}
var captchaVerification = _this.secretKey ? aesEncrypt(_this.backToken + '---' + JSON.stringify(_this.checkPosArr), _this.secretKey) : _this.backToken + '---' + JSON.stringify(_this.checkPosArr)
checkPictrue(data, _this.options.baseUrl).then(res => {
res = JSON.parse(res)
if (res.repCode == "0000") {
_this.$element.find('.verify-bar-area').css({'color': '#4cae4c', 'border-color': '#5cb85c'});
_this.$element.find('.verify-msg').text('验证成功');
// _this.$element.find('.verify-refresh').hide();
_this.$element.find('.verify-img-panel').unbind('click');
setTimeout(res => {
_this.$element.find(".mask").css("display", "none");
_this.refresh();
}, 1000)
_this.options.success({captchaVerification});
} else {
_this.options.error(_this);
_this.$element.find('.verify-bar-area').css({'color': '#d9534f', 'border-color': '#d9534f'});
_this.$element.find('.verify-msg').text('验证失败');
setTimeout(function () {
_this.$element.find('.verify-bar-area').css({'color': '#000', 'border-color': '#ddd'});
_this.refresh();
}, 400);
}
})
}, 400);
}
if (_this.num < _this.options.checkNum) {
_this.num = _this.createPoint(_this.getMousePos(this, e));
}
});
//刷新
_this.$element.find('.verify-refresh').on('click', function () {
_this.refresh();
});
},
//加载页面
loadDom: function () {
this.fontPos = []; //选中的坐标信息
this.checkPosArr = []; //用户点击的坐标
this.num = 1; //点击的记数
var panelHtml = '';
var wrapStartHtml = '';
var wrapEndHtml = '';
this.setSize = Slide.prototype.resetSize(this); //重新设置宽度高度
wrapStartHtml = `
请完成安全验证
`
if (this.options.mode == 'pop') {
panelHtml = wrapStartHtml
}
panelHtml += `
`;
wrapEndHtml = `
`
if (this.options.mode == 'pop') {
panelHtml += wrapEndHtml
}
this.$element.append(panelHtml);
this.htmlDoms = {
back_img: this.$element.find('.back-img'),
out_panel: this.$element.find('.verify-img-out'),
img_panel: this.$element.find('.verify-img-panel'),
bar_area: this.$element.find('.verify-bar-area'),
msg: this.$element.find('.verify-msg'),
};
this.$element.css('position', 'relative');
this.htmlDoms.out_panel.css('height', parseInt(this.setSize.img_height) + this.options.vSpace + 'px');
this.htmlDoms.img_panel.css({
'width': this.setSize.img_width,
'height': this.setSize.img_height,
'background-size': this.setSize.img_width + ' ' + this.setSize.img_height,
'margin-bottom': this.options.vSpace + 'px'
});
this.htmlDoms.bar_area.css({
'width': this.setSize.img_width,
'height': this.setSize.bar_height,
'line-height': this.setSize.bar_height
});
},
//获取坐标
getMousePos: function (obj, event) {
var e = event || window.event;
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
var x = e.clientX - ($(obj).offset().left - $(window).scrollLeft());
var y = e.clientY - ($(obj).offset().top - $(window).scrollTop());
return {'x': x, 'y': y};
},
//创建坐标点
createPoint: function (pos) {
this.htmlDoms.img_panel.append(`${this.num}
`);
return ++this.num;
},
//刷新
refresh: function () {
var _this = this;
this.$element.find('.point-area').remove();
this.fontPos = [];
this.checkPosArr = [];
this.num = 1;
// 由于需要获取用户信息,后端修改了request参数,直接传对象会报错,需要多包裹一层
let pictureParam = {
captchaVO: {captchaType: "clickWord"}
};
getPictrue(pictureParam, _this.options.baseUrl).then(res => {
console.log('222222222222222222222222')
res = JSON.parse(res);
console.log(res)
if (res.repCode == "0000") {
this.htmlDoms.back_img[0].src = 'data:image/png;base64,' + res.repData.originalImageBase64
this.backToken = res.repData.token
this.secretKey = res.repData.secretKey
let text = '请依次点击【' + res.repData.wordList.join(",") + '】'
_this.$element.find('.verify-msg').text(text);
}
})
},
pointTransfrom: function (pointArr, imgSize) {
var newPointArr = pointArr.map(p => {
let x = Math.round(310 * p.x / parseInt(imgSize.img_width))
let y = Math.round(155 * p.y / parseInt(imgSize.img_height))
return {x, y}
})
return newPointArr
}
};
$.fn.slideVerify = function (options, callbacks) {
var slide = new Slide(this, options);
if (slide.options.mode == "pop") {
slide.init();
} else if (slide.options.mode == "fixed") {
slide.init();
}
return slide;
};
//在插件中使用clickVerify对象
$.fn.pointsVerify = function (options, callbacks) {
var points = new Points(this, options);
if (points.options.mode == "pop") {
points.init();
} else if (points.options.mode == "fixed") {
points.init();
}
return points;
};
})(jQuery, window, document);