yuang-framework-ui-pc
Version:
yuang-framework-ui-pc Library
284 lines (283 loc) • 10.8 kB
JavaScript
;
const vue = require("vue");
const httpConfig = require("yuang-framework-ui-common/lib/config/httpConfig");
const iconsVue = require("@element-plus/icons-vue");
const icons = require("../../icons");
const _hoisted_1 = { class: "yu-framework-slider-captcha" };
const _hoisted_2 = { class: "yu-framework-slider-captcha-title" };
const _hoisted_3 = ["width", "height"];
const _hoisted_4 = { class: "slider-hint" };
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
...{ name: "SliderCaptcha" },
__name: "SliderCaptcha",
props: {
blockLength: { default: 42 },
blockRadius: { default: 10 },
canvasWidth: { default: 320 },
canvasHeight: { default: 155 },
sliderHint: { default: "向右滑动" },
accuracy: { default: 3 },
imageList: { default: [] }
},
emits: ["success", "fail", "close"],
setup(__props, { emit: __emit }) {
const props = __props;
const emit = __emit;
const canvas = vue.ref(null);
const block = vue.ref(null);
const isVerifyActive = vue.ref(false);
const isVerifySuccess = vue.ref(false);
const isVerifyFail = vue.ref(false);
vue.ref(null);
vue.ref(null);
vue.ref(props.blockLength * 2);
vue.ref(void 0);
vue.ref(void 0);
const originX = vue.ref(void 0);
const originY = vue.ref(void 0);
const dragDistanceList = vue.ref([]);
const sliderBoxWidth = vue.ref(0);
const sliderButtonLeft = vue.ref(0);
const isMouseDown = vue.ref(false);
const isLoading = vue.ref(true);
const timestamp = vue.ref(null);
const successHint = vue.ref("");
const key = vue.ref(void 0);
const isSliderSlide = vue.ref(false);
vue.onMounted(() => {
init();
});
const init = () => {
initDom();
bindEvents();
};
const initDom = () => {
getCaptcha();
};
const getCaptcha = () => {
httpConfig.http.post(`/framework-api/core/framework-captcha/createSliderCaptcha`, {}).then((res) => {
key.value = res.data.data.key;
block.value.src = res.data.data.blockSrc;
block.value.style.top = res.data.data.blockY + "px";
canvas.value.src = res.data.data.canvasSrc;
setTimeout(() => {
isLoading.value = false;
}, 200);
});
};
const bindEvents = () => {
var _a, _b, _c;
(_a = document.getElementById("slider-button")) == null ? void 0 : _a.addEventListener("mousedown", (event) => {
startEvent(event.clientX, event.clientY);
updateSliderButtonImage("slide");
});
document.addEventListener("mousemove", (event) => {
moveEvent(event.clientX, event.clientY);
});
document.addEventListener("mouseup", (event) => {
endEvent(event.clientX);
});
(_b = document.getElementById("slider-button")) == null ? void 0 : _b.addEventListener("click", (event) => {
updateSliderButtonImage("init");
});
(_c = document.getElementById("slider-button")) == null ? void 0 : _c.addEventListener("touchstart", (event) => {
startEvent(event.changedTouches[0].pageX, event.changedTouches[0].pageY);
});
document.addEventListener("touchmove", (event) => {
moveEvent(event.changedTouches[0].pageX, event.changedTouches[0].pageY);
});
document.addEventListener("touchend", (event) => {
endEvent(event.changedTouches[0].pageX);
});
};
const updateSliderButtonImage = (type) => {
if (type == "init") {
isSliderSlide.value = false;
} else if (type == "slide") {
isSliderSlide.value = true;
}
};
const checkImgSrc = () => {
return !!canvas.value.src;
};
const startEvent = (clientX, clientY) => {
if (!checkImgSrc() || isLoading.value || isVerifySuccess.value) {
return;
}
originX.value = clientX;
originY.value = clientY;
isMouseDown.value = true;
timestamp.value = +/* @__PURE__ */ new Date();
updateSliderButtonImage("slide");
};
const moveEvent = (clientX, clientY) => {
if (!isMouseDown.value) {
return false;
}
const moveX = clientX - originX.value;
const moveY = clientY - originY.value;
if (moveX < 0 || moveX + 40 >= props.canvasWidth) {
return false;
}
sliderButtonLeft.value = moveX > props.canvasWidth - 56 ? props.canvasWidth - 56 : moveX;
let blockLeft = (props.canvasWidth - 40 - 20) / (props.canvasWidth - 40) * moveX;
block.value.style.left = (blockLeft > props.canvasWidth - 56 - 18 - 7 ? props.canvasWidth - 56 - 18 - 7 : blockLeft) + "px";
isVerifyActive.value = true;
sliderBoxWidth.value = moveX + 28;
dragDistanceList.value.push(moveY);
};
const endEvent = (clientX) => {
if (!isMouseDown.value) {
return false;
}
isMouseDown.value = false;
if (clientX === originX.value) {
return false;
}
isLoading.value = true;
isVerifyActive.value = false;
timestamp.value = +/* @__PURE__ */ new Date() - timestamp.value;
const moveLength = parseInt(block.value.style.left);
if (timestamp.value > 1e4) {
verifyFailEvent();
} else {
if (!turingTest()) {
verifyFailEvent();
} else {
let data = {
key: key.value,
captcha: moveLength
};
httpConfig.http.post(`/framework-api/core/framework-captcha/validateSliderCaptcha`, data).then((res) => {
verifySuccessEvent();
setTimeout(() => {
emit("success", { key: key.value, value: moveLength });
}, 500);
}).catch((ex) => {
verifyFailEvent();
console.error(ex);
});
}
}
updateSliderButtonImage("init");
};
const turingTest = () => {
const arr = dragDistanceList.value;
const average = arr.reduce(calcSum) / arr.length;
const deviations = arr.map((x) => x - average);
const stdDev = Math.sqrt(deviations.map(calcSquare).reduce(calcSum) / arr.length);
return average !== stdDev;
};
const verifySuccessEvent = () => {
isLoading.value = false;
isVerifySuccess.value = true;
const elapsedTime = (timestamp.value / 1e3).toFixed(1);
if (elapsedTime < 1) {
successHint.value = `仅仅${elapsedTime}S,你的速度快如闪电`;
} else if (elapsedTime < 2) {
successHint.value = `只用了${elapsedTime}S,这速度简直完美`;
} else {
successHint.value = `耗时${elapsedTime}S,争取下次再快一点`;
}
};
const verifyFailEvent = () => {
isVerifyFail.value = true;
emit("fail", {});
refresh();
};
const refresh = () => {
setTimeout(() => {
isVerifyFail.value = false;
}, 300);
isLoading.value = true;
isVerifyActive.value = false;
isVerifySuccess.value = false;
block.value.style.left = 0;
sliderBoxWidth.value = 0;
sliderButtonLeft.value = 0;
vue.nextTick(() => {
getCaptcha();
});
};
const close = () => {
emit("close");
};
const calcSum = (x, y) => {
return x + y;
};
const calcSquare = (x) => {
return x * x;
};
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
vue.createElementVNode("div", _hoisted_2, [
_cache[0] || (_cache[0] = vue.createTextVNode(" 完成拼图验证 ")),
vue.createElementVNode("div", {
onClick: refresh,
class: "yu-framework-slider-captcha-refresh-icon"
}, [
vue.createVNode(vue.unref(iconsVue.RefreshRight))
]),
vue.createElementVNode("div", {
onClick: close,
class: "yu-framework-slider-captcha-close-icon"
}, [
vue.createVNode(vue.unref(iconsVue.CircleClose))
])
]),
vue.createElementVNode("div", {
class: "yu-framework-slider-captcha",
style: vue.normalizeStyle({ width: _ctx.canvasWidth + "px" }),
onselectstart: "return false;"
}, [
isLoading.value ? (vue.openBlock(), vue.createElementBlock("div", {
key: 0,
class: vue.normalizeClass({ "yu-framework-slider-captcha-img-loading": isLoading.value }),
style: vue.normalizeStyle({ height: _ctx.canvasHeight + "px" })
}, null, 6)) : vue.createCommentVNode("", true),
isVerifySuccess.value ? (vue.openBlock(), vue.createElementBlock("div", {
key: 1,
class: "success-hint",
style: vue.normalizeStyle({ height: _ctx.canvasHeight + "px" })
}, vue.toDisplayString(successHint.value), 5)) : vue.createCommentVNode("", true),
vue.createElementVNode("img", {
ref_key: "canvas",
ref: canvas,
class: "yu-framework-slider-captcha-canvas",
width: _ctx.canvasWidth,
height: _ctx.canvasHeight
}, null, 8, _hoisted_3),
vue.createElementVNode("img", {
ref_key: "block",
ref: block,
class: vue.normalizeClass(["yu-framework-slider-captcha-block", { "is-verify-fail": isVerifyFail.value }])
}, null, 2),
vue.createElementVNode("div", {
class: vue.normalizeClass(["yu-framework-slider-captcha-slider", { "is-verify-active": isVerifyActive.value, "is-verify-success": isVerifySuccess.value, "is-verify-fail": isVerifyFail.value }])
}, [
vue.createElementVNode("div", {
class: "yu-framework-slider-captcha-slider-box",
style: vue.normalizeStyle({ width: sliderBoxWidth.value + "px" })
}, [
vue.createElementVNode("div", {
class: "yu-framework-slider-captcha-slider-button",
id: "slider-button",
style: vue.normalizeStyle({ left: sliderButtonLeft.value + "px" })
}, [
!isSliderSlide.value ? (vue.openBlock(), vue.createBlock(vue.unref(icons.SliderArrowStatic), {
key: 0,
class: "yu-framework-slider-captcha-slider-button-icon yu-color-primary"
})) : (vue.openBlock(), vue.createBlock(vue.unref(icons.SliderArrowSlide), {
key: 1,
class: "yu-framework-slider-captcha-slider-button-icon yu-color-primary"
}))
], 4)
], 4),
vue.createElementVNode("span", _hoisted_4, vue.toDisplayString(_ctx.sliderHint), 1)
], 2)
], 4)
]);
};
}
});
module.exports = _sfc_main;