mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-13 09:28:14 +08:00
♻️ geetest 组件函数化调用
This commit is contained in:
33
src/components/func/geetest.ts
Normal file
33
src/components/func/geetest.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* @file component func geetest.ts
|
||||||
|
* @description 封装自定义 geetest 组件,通过函数调用的方式,简化 geetest 的使用,使用时需要在 main.ts 中引入 geetest.js
|
||||||
|
* @since Beta v0.3.3
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { h, render, type VNode } from "vue";
|
||||||
|
import geetest from "./geetest.vue";
|
||||||
|
|
||||||
|
const geetestId = "tg-func-geetest";
|
||||||
|
|
||||||
|
const renderBox = (): VNode => {
|
||||||
|
const container = document.createElement("div");
|
||||||
|
container.id = geetestId;
|
||||||
|
const boxVNode: VNode = h(geetest);
|
||||||
|
render(boxVNode, container);
|
||||||
|
document.body.appendChild(container);
|
||||||
|
return boxVNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
let geetestInstance: VNode;
|
||||||
|
|
||||||
|
const showGeetest = async (): Promise<string | boolean> => {
|
||||||
|
if (geetestInstance) {
|
||||||
|
const boxVue = geetestInstance.component;
|
||||||
|
return boxVue?.exposeProxy?.displayBox();
|
||||||
|
} else {
|
||||||
|
geetestInstance = renderBox();
|
||||||
|
return await showGeetest();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default showGeetest;
|
||||||
189
src/components/func/geetest.vue
Normal file
189
src/components/func/geetest.vue
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
<template>
|
||||||
|
<transition name="func-geetest-outer">
|
||||||
|
<div v-show="show || showOuter" class="geetest-overlay" @click.self.prevent="handleOuter">
|
||||||
|
<transition name="func-geetest-inner">
|
||||||
|
<div v-show="showInner" class="geetest-box">
|
||||||
|
<div class="geetest-top">
|
||||||
|
<div class="geetest-title">请完成如下极验测试</div>
|
||||||
|
</div>
|
||||||
|
<div id="verify" class="geetest-mid">
|
||||||
|
<div id="geetest" ref="geetestRef"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
import showSnackbar from "./snackbar";
|
||||||
|
import { useUserStore } from "../../store/modules/user";
|
||||||
|
import TGRequest from "../../web/request/TGRequest";
|
||||||
|
|
||||||
|
const show = ref<boolean>(false);
|
||||||
|
const showOuter = ref<boolean>(false);
|
||||||
|
const showInner = ref<boolean>(false);
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const geetestRef = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
|
watch(show, () => {
|
||||||
|
if (show.value) {
|
||||||
|
showOuter.value = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
showInner.value = true;
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
showInner.value = false;
|
||||||
|
}, 100);
|
||||||
|
setTimeout(() => {
|
||||||
|
showOuter.value = false;
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function displayBox(): Promise<void> {
|
||||||
|
const cookie = userStore.getCookieGroup3();
|
||||||
|
const res = await TGRequest.User.verification.get(cookie.ltoken, cookie.ltuid);
|
||||||
|
if ("retcode" in res) {
|
||||||
|
showSnackbar({
|
||||||
|
text: `[${res.retcode}]${res.message}`,
|
||||||
|
color: "error",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
show.value = true;
|
||||||
|
// @ts-expect-error Cannot find name 'initGeetest'.
|
||||||
|
initGeetest(
|
||||||
|
{
|
||||||
|
gt: res.gt,
|
||||||
|
challenge: res.challenge,
|
||||||
|
offline: false,
|
||||||
|
new_captcha: true,
|
||||||
|
product: "custom",
|
||||||
|
area: "#verify",
|
||||||
|
width: "250px",
|
||||||
|
},
|
||||||
|
(captchaObj: TGApp.BBS.Geetest.GeetestCaptcha) => {
|
||||||
|
geetestRef.value = document.getElementById("geetest");
|
||||||
|
if (geetestRef.value === null) throw new Error("Cannot find element with id 'geetest'.");
|
||||||
|
geetestRef.value.innerHTML = "";
|
||||||
|
captchaObj.appendTo("#geetest");
|
||||||
|
captchaObj
|
||||||
|
.onReady(() => {
|
||||||
|
console.log("ready");
|
||||||
|
})
|
||||||
|
.onSuccess(() => {
|
||||||
|
const validate = captchaObj.getValidate();
|
||||||
|
(async () => {
|
||||||
|
await TGRequest.User.verification.verify(userStore.cookie, validate);
|
||||||
|
show.value = false;
|
||||||
|
})().catch(() => {}); // 防止报错
|
||||||
|
})
|
||||||
|
.onError(() => {
|
||||||
|
console.log("error");
|
||||||
|
})
|
||||||
|
.onClose(() => {
|
||||||
|
console.log("close");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleOuter(): void {
|
||||||
|
show.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
displayBox,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="css" scoped>
|
||||||
|
.func-geetest-outer-enter-active,
|
||||||
|
.func-geetest-outer-leave-active,
|
||||||
|
.func-geetest-inner-enter-active {
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.func-geetest-inner-leave-active {
|
||||||
|
transition: all 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.func-geetest-inner-enter-from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.func-geetest-inner-enter-to,
|
||||||
|
.func-geetest-inner-leave-from {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.func-geetest-outer-enter-to,
|
||||||
|
.func-geetest-outer-leave-from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.func-geetest-outer-enter-from,
|
||||||
|
.func-geetest-outer-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.func-geetest-inner-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.geetest-overlay {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 100;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
background: rgb(0 0 0 / 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.geetest-box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: var(--box-bg-1);
|
||||||
|
color: var(--app-page-content);
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geetest-top {
|
||||||
|
border-bottom: 1px solid var(--common-shadow-4);
|
||||||
|
font-family: var(--font-title);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geetest-title {
|
||||||
|
color: var(--common-text-title);
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.geetest-mid {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: var(--box-bg-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#verify {
|
||||||
|
width: 256px;
|
||||||
|
height: 320px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
<template>
|
|
||||||
<TOverlay v-model="visible" hide blur-val="20px">
|
|
||||||
<div class="tog-box">
|
|
||||||
<div class="tog-top">
|
|
||||||
<div class="tog-title">请完成如下极验测试</div>
|
|
||||||
</div>
|
|
||||||
<div id="verify" class="tog-mid">
|
|
||||||
<div id="geetest"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TOverlay>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
// vue
|
|
||||||
import { computed, watch } from "vue";
|
|
||||||
import showSnackbar from "../func/snackbar";
|
|
||||||
import TOverlay from "../main/t-overlay.vue";
|
|
||||||
// store
|
|
||||||
import { useUserStore } from "../../store/modules/user";
|
|
||||||
// utils
|
|
||||||
import TGRequest from "../../web/request/TGRequest";
|
|
||||||
|
|
||||||
interface ToGeetestProps {
|
|
||||||
modelValue: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
type ToGeetestEmits = (e: "update:modelValue", value: boolean) => void;
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<ToGeetestProps>(), {
|
|
||||||
modelValue: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const emits = defineEmits<ToGeetestEmits>();
|
|
||||||
|
|
||||||
const visible = computed({
|
|
||||||
get: () => props.modelValue,
|
|
||||||
set: (value) => {
|
|
||||||
emits("update:modelValue", value);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(visible, async (value) => {
|
|
||||||
if (value) {
|
|
||||||
await getChallenge();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const userStore = useUserStore();
|
|
||||||
|
|
||||||
// 获取极验验证码
|
|
||||||
async function getChallenge(): Promise<void> {
|
|
||||||
const cookie = userStore.getCookieGroup3();
|
|
||||||
const res = await TGRequest.User.verification.get(cookie.ltoken, cookie.ltuid);
|
|
||||||
if ("retcode" in res) {
|
|
||||||
showSnackbar({
|
|
||||||
text: res.message,
|
|
||||||
color: "error",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// @ts-expect-error Cannot find name 'initGeetest'.ts(2304)
|
|
||||||
initGeetest(
|
|
||||||
{
|
|
||||||
gt: res.gt,
|
|
||||||
challenge: res.challenge,
|
|
||||||
offline: false,
|
|
||||||
new_captcha: true,
|
|
||||||
|
|
||||||
product: "custom", // 产品形式,包括:float,popup, bind
|
|
||||||
area: "#verify", // 选择验证码展示的位置
|
|
||||||
width: "250px",
|
|
||||||
},
|
|
||||||
(captchaObj: TGApp.BBS.Geetest.GeetestCaptcha) => {
|
|
||||||
captchaObj.appendTo("#geetest");
|
|
||||||
captchaObj
|
|
||||||
.onReady(() => {
|
|
||||||
console.log("ready");
|
|
||||||
})
|
|
||||||
.onSuccess(() => {
|
|
||||||
const validate = captchaObj.getValidate();
|
|
||||||
(async () => {
|
|
||||||
await doVerify(validate);
|
|
||||||
})().catch(() => {}); // 防止报错
|
|
||||||
})
|
|
||||||
.onError(() => {
|
|
||||||
console.log("error");
|
|
||||||
})
|
|
||||||
.onClose(() => {
|
|
||||||
console.log("close");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function doVerify(data: TGApp.BBS.Geetest.GeetestValidate): Promise<void> {
|
|
||||||
await TGRequest.User.verification.verify(userStore.cookie, data);
|
|
||||||
emits("update:modelValue", false);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="css" scoped>
|
|
||||||
.tog-box {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: 5px;
|
|
||||||
background-color: var(--box-bg-1);
|
|
||||||
color: var(--app-page-content);
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tog-top {
|
|
||||||
border-bottom: 1px solid var(--common-shadow-4);
|
|
||||||
font-family: var(--font-title);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tog-title {
|
|
||||||
color: var(--common-text-title);
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tog-mid {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: 5px;
|
|
||||||
background: var(--box-bg-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#verify {
|
|
||||||
width: 256px;
|
|
||||||
height: 320px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -17,12 +17,11 @@
|
|||||||
<div class="btn-list">
|
<div class="btn-list">
|
||||||
<v-btn class="test-btn" @click="getGC">获取极验</v-btn>
|
<v-btn class="test-btn" @click="getGC">获取极验</v-btn>
|
||||||
</div>
|
</div>
|
||||||
<to-geetest v-model="visible"></to-geetest>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import ToGeetest from "../../components/overlay/to-geetest.vue";
|
import showGeetest from "../../components/func/geetest";
|
||||||
|
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref<boolean>(false);
|
||||||
|
|
||||||
@@ -30,8 +29,8 @@ onMounted(async () => {
|
|||||||
visible.value = false;
|
visible.value = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
function getGC(): void {
|
async function getGC(): Promise<void> {
|
||||||
visible.value = true;
|
await showGeetest();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="css" scoped>
|
<style lang="css" scoped>
|
||||||
|
|||||||
Reference in New Issue
Block a user