This commit is contained in:
nanguaboss
2026-08-03 00:07:01 +08:00
commit 71c6e8d9c1
112 changed files with 7815 additions and 0 deletions
File diff suppressed because one or more lines are too long
+45
View File
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

+120
View File
@@ -0,0 +1,120 @@
/**
* slider.js - 滑块验证组件(纯前端实现)
* 用法:
* <div id="slider"></div>
* var slider = new SliderVerify('#slider', function(token){ ... }); // 拖动成功回调
* slider.reset(); // 重置
* 说明:拖动到目标位置后生成 slider_token(含随机数+偏移校验和),
* 提交登录时携带该 token;服务端校验 token 非空且长度合法。
* 如需更高安全性,可后续改为服务端签发 token(接口生成背景图+缺口位置)。
*/
(function (window) {
'use strict';
function SliderVerify(selector, onSuccess) {
this.el = typeof selector === 'string' ? document.querySelector(selector) : selector;
this.onSuccess = onSuccess || function () {};
this.passed = false;
this.init();
}
SliderVerify.prototype.init = function () {
var self = this;
var html =
'<div class="slider-box">' +
' <div class="slider-bg"></div>' +
' <div class="slider-text">请按住滑块,拖动到最右边</div>' +
' <div class="slider-btn">⟶</div>' +
'</div>';
this.el.innerHTML = html;
this.box = this.el.querySelector('.slider-box');
this.bg = this.el.querySelector('.slider-bg');
this.text = this.el.querySelector('.slider-text');
this.btn = this.el.querySelector('.slider-btn');
this.boxWidth = this.box.offsetWidth || 300;
this.dragging = false;
this.startX = 0;
this.offset = 0;
this.btn.addEventListener('mousedown', function (e) { self.startDrag(e); });
this.btn.addEventListener('touchstart', function (e) { self.startDrag(e.touches[0]); }, { passive: true });
document.addEventListener('mousemove', function (e) { self.moveDrag(e); });
document.addEventListener('touchmove', function (e) { self.moveDrag(e.touches[0]); }, { passive: false });
document.addEventListener('mouseup', function () { self.endDrag(); });
document.addEventListener('touchend', function () { self.endDrag(); });
};
SliderVerify.prototype.startDrag = function (e) {
if (this.passed) return;
e.preventDefault && e.preventDefault();
this.dragging = true;
this.startX = e.clientX;
};
SliderVerify.prototype.moveDrag = function (e) {
if (!this.dragging) return;
e.preventDefault && e.preventDefault();
var dx = e.clientX - this.startX;
this.offset = Math.max(0, Math.min(dx, this.boxWidth - 50));
this.btn.style.left = this.offset + 'px';
this.bg.style.width = this.offset + 50 + 'px';
if (this.offset >= this.boxWidth - 60) {
this.endDrag(true);
}
};
SliderVerify.prototype.endDrag = function (force) {
if (!this.dragging) return;
this.dragging = false;
if (force || this.offset >= this.boxWidth - 60) {
// 验证通过
this.passed = true;
this.btn.style.left = (this.boxWidth - 50) + 'px';
this.bg.style.width = '100%';
this.text.innerHTML = '✓ 验证通过';
this.text.className = 'slider-text slider-success';
var token = this.makeToken();
if (this.onSuccess) this.onSuccess(token);
} else {
// 复位
var self = this;
this.btn.style.transition = 'left .3s';
this.bg.style.transition = 'width .3s';
this.btn.style.left = '0px';
this.bg.style.width = '50px';
setTimeout(function () {
self.btn.style.transition = '';
self.bg.style.transition = '';
}, 320);
}
};
/** 生成滑块 token:时间戳+随机数+偏移校验和 */
SliderVerify.prototype.makeToken = function () {
var rand = Math.random().toString(36).substr(2, 8);
var ts = Date.now().toString(36);
var offset = this.offset;
var checksum = (offset * 7 + ts.length * 13).toString(36);
return 'sl_' + ts + '_' + rand + '_' + checksum + '_' + offset;
};
SliderVerify.prototype.reset = function () {
this.passed = false;
this.offset = 0;
this.btn.style.left = '0px';
this.bg.style.width = '50px';
this.text.innerHTML = '请按住滑块,拖动到最右边';
this.text.className = 'slider-text';
};
SliderVerify.prototype.isPassed = function () {
return this.passed;
};
window.SliderVerify = SliderVerify;
})(window);
File diff suppressed because one or more lines are too long