add
This commit is contained in:
@@ -176,11 +176,19 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<script>
|
||||||
|
window.AliyunCaptchaConfig = { region: "cn", prefix: "12zxnj" };
|
||||||
|
</script>
|
||||||
|
<script
|
||||||
|
type="text/javascript"
|
||||||
|
src="https://o.alicdn.com/captcha-frontend/aliyunCaptcha/AliyunCaptcha.js"
|
||||||
|
></script>
|
||||||
<div id="app-loading">
|
<div id="app-loading">
|
||||||
<div class="loading-spinner"></div>
|
<div class="loading-spinner"></div>
|
||||||
<div class="loading-text">加载中</div>
|
<div class="loading-text">加载中</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
<div id="captcha-element"></div>
|
||||||
|
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
1
src/auto-imports.d.ts
vendored
1
src/auto-imports.d.ts
vendored
@@ -117,6 +117,7 @@ declare global {
|
|||||||
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
|
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
|
||||||
const useAgent: typeof import('./composables/useAgent.js')['useAgent']
|
const useAgent: typeof import('./composables/useAgent.js')['useAgent']
|
||||||
const useAgentStore: typeof import('./stores/agentStore.js')['useAgentStore']
|
const useAgentStore: typeof import('./stores/agentStore.js')['useAgentStore']
|
||||||
|
const useAliyunCaptcha: typeof import('./composables/useAliyunCaptcha.js')['default']
|
||||||
const useAnimate: typeof import('@vueuse/core')['useAnimate']
|
const useAnimate: typeof import('@vueuse/core')['useAnimate']
|
||||||
const useApiFetch: typeof import('./composables/useApiFetch.js')['default']
|
const useApiFetch: typeof import('./composables/useApiFetch.js')['default']
|
||||||
const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference']
|
const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference']
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ const router = useRouter();
|
|||||||
const show = defineModel("show");
|
const show = defineModel("show");
|
||||||
import { useCascaderAreaData } from "@vant/area-data";
|
import { useCascaderAreaData } from "@vant/area-data";
|
||||||
import { showToast } from "vant"; // 引入 showToast 方法
|
import { showToast } from "vant"; // 引入 showToast 方法
|
||||||
|
import { useAliyunCaptcha } from "@/composables/useAliyunCaptcha";
|
||||||
const emit = defineEmits(); // 确保 emit 可以正确使用
|
const emit = defineEmits(); // 确保 emit 可以正确使用
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
ancestor: {
|
ancestor: {
|
||||||
@@ -150,6 +151,7 @@ const loadingSms = ref(false); // 控制验证码按钮的loading状态
|
|||||||
const isCountingDown = ref(false);
|
const isCountingDown = ref(false);
|
||||||
const isAgreed = ref(false);
|
const isAgreed = ref(false);
|
||||||
const countdown = ref(60);
|
const countdown = ref(60);
|
||||||
|
const { runWithCaptcha } = useAliyunCaptcha();
|
||||||
const onFinish = ({ selectedOptions }) => {
|
const onFinish = ({ selectedOptions }) => {
|
||||||
showCascader.value = false;
|
showCascader.value = false;
|
||||||
form.value.region = selectedOptions.map((option) => option.text).join("/");
|
form.value.region = selectedOptions.map((option) => option.text).join("/");
|
||||||
@@ -171,20 +173,25 @@ const getSmsCode = async () => {
|
|||||||
|
|
||||||
loadingSms.value = true;
|
loadingSms.value = true;
|
||||||
|
|
||||||
const { data, error } = await useApiFetch("auth/sendSms")
|
await runWithCaptcha(
|
||||||
.post({ mobile: form.value.mobile, actionType: "agentApply" })
|
(captchaVerifyParam) =>
|
||||||
.json();
|
useApiFetch("auth/sendSms")
|
||||||
|
.post({
|
||||||
loadingSms.value = false;
|
mobile: form.value.mobile,
|
||||||
|
actionType: "agentApply",
|
||||||
if (data.value && !error.value) {
|
captchaVerifyParam,
|
||||||
if (data.value.code === 200) {
|
})
|
||||||
showToast({ message: "获取成功" });
|
.json(),
|
||||||
startCountdown(); // 启动倒计时
|
(res) => {
|
||||||
} else {
|
loadingSms.value = false;
|
||||||
showToast(data.value.msg);
|
if (res.code === 200) {
|
||||||
}
|
showToast({ message: "获取成功" });
|
||||||
}
|
startCountdown();
|
||||||
|
} else {
|
||||||
|
showToast(res.msg || "获取失败");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
let timer = null;
|
let timer = null;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, nextTick } from "vue";
|
import { ref, computed, nextTick } from "vue";
|
||||||
import { useDialogStore } from "@/stores/dialogStore";
|
import { useDialogStore } from "@/stores/dialogStore";
|
||||||
|
import { useAliyunCaptcha } from "@/composables/useAliyunCaptcha";
|
||||||
|
|
||||||
const emit = defineEmits(['bind-success'])
|
const emit = defineEmits(['bind-success'])
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -13,6 +14,7 @@ const isCountingDown = ref(false);
|
|||||||
const countdown = ref(60);
|
const countdown = ref(60);
|
||||||
const isAgreed = ref(false);
|
const isAgreed = ref(false);
|
||||||
let timer = null;
|
let timer = null;
|
||||||
|
const { runWithCaptcha } = useAliyunCaptcha();
|
||||||
|
|
||||||
// 聚焦状态变量
|
// 聚焦状态变量
|
||||||
const phoneFocused = ref(false);
|
const phoneFocused = ref(false);
|
||||||
@@ -36,25 +38,30 @@ async function sendVerificationCode() {
|
|||||||
showToast({ message: "请输入有效的手机号" });
|
showToast({ message: "请输入有效的手机号" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { data, error } = await useApiFetch("auth/sendSms")
|
await runWithCaptcha(
|
||||||
.post({ mobile: phoneNumber.value, actionType: "bindMobile" })
|
(captchaVerifyParam) =>
|
||||||
.json();
|
useApiFetch("auth/sendSms")
|
||||||
|
.post({
|
||||||
if (data.value && !error.value) {
|
mobile: phoneNumber.value,
|
||||||
if (data.value.code === 200) {
|
actionType: "bindMobile",
|
||||||
showToast({ message: "获取成功" });
|
captchaVerifyParam,
|
||||||
startCountdown();
|
})
|
||||||
// 聚焦到验证码输入框
|
.json(),
|
||||||
nextTick(() => {
|
(res) => {
|
||||||
const verificationCodeInput = document.getElementById('verificationCode');
|
if (res.code === 200) {
|
||||||
if (verificationCodeInput) {
|
showToast({ message: "获取成功" });
|
||||||
verificationCodeInput.focus();
|
startCountdown();
|
||||||
}
|
nextTick(() => {
|
||||||
});
|
const verificationCodeInput = document.getElementById('verificationCode');
|
||||||
} else {
|
if (verificationCodeInput) {
|
||||||
showToast(data.value.msg);
|
verificationCodeInput.focus();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
} else {
|
||||||
|
showToast(res.msg || "获取失败");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function startCountdown() {
|
function startCountdown() {
|
||||||
|
|||||||
@@ -283,6 +283,7 @@ import { useUserStore } from "@/stores/userStore";
|
|||||||
import { useDialogStore } from "@/stores/dialogStore";
|
import { useDialogStore } from "@/stores/dialogStore";
|
||||||
import { useEnv } from "@/composables/useEnv";
|
import { useEnv } from "@/composables/useEnv";
|
||||||
import { showConfirmDialog } from "vant";
|
import { showConfirmDialog } from "vant";
|
||||||
|
import { useAliyunCaptcha } from "@/composables/useAliyunCaptcha";
|
||||||
|
|
||||||
import Payment from "@/components/Payment.vue";
|
import Payment from "@/components/Payment.vue";
|
||||||
import BindPhoneDialog from "@/components/BindPhoneDialog.vue";
|
import BindPhoneDialog from "@/components/BindPhoneDialog.vue";
|
||||||
@@ -316,6 +317,7 @@ const { feature } = toRefs(props);
|
|||||||
|
|
||||||
// Emits
|
// Emits
|
||||||
const emit = defineEmits(['submit-success']);
|
const emit = defineEmits(['submit-success']);
|
||||||
|
const { runWithCaptcha } = useAliyunCaptcha();
|
||||||
|
|
||||||
// 动态导入产品背景图片的函数
|
// 动态导入产品背景图片的函数
|
||||||
const loadProductBackground = async (productType) => {
|
const loadProductBackground = async (productType) => {
|
||||||
@@ -630,23 +632,30 @@ async function sendVerificationCode() {
|
|||||||
showToast({ message: "请输入有效的手机号" });
|
showToast({ message: "请输入有效的手机号" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
await runWithCaptcha(
|
||||||
const { data, error } = await useApiFetch("/auth/sendSms")
|
(captchaVerifyParam) =>
|
||||||
.post({ mobile: formData.mobile, actionType: "query" })
|
useApiFetch("/auth/sendSms")
|
||||||
.json();
|
.post({
|
||||||
|
mobile: formData.mobile,
|
||||||
if (!error.value && data.value.code === 200) {
|
actionType: "query",
|
||||||
showToast({ message: "验证码发送成功", type: "success" });
|
captchaVerifyParam,
|
||||||
startCountdown();
|
})
|
||||||
nextTick(() => {
|
.json(),
|
||||||
const verificationCodeInput = document.getElementById('verificationCode');
|
(res) => {
|
||||||
if (verificationCodeInput) {
|
if (res.code === 200) {
|
||||||
verificationCodeInput.focus();
|
showToast({ message: "验证码发送成功", type: "success" });
|
||||||
|
startCountdown();
|
||||||
|
nextTick(() => {
|
||||||
|
const verificationCodeInput = document.getElementById('verificationCode');
|
||||||
|
if (verificationCodeInput) {
|
||||||
|
verificationCodeInput.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
showToast({ message: res.msg || "验证码发送失败,请重试" });
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
} else {
|
);
|
||||||
showToast({ message: "验证码发送失败,请重试" });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let timer = null;
|
let timer = null;
|
||||||
@@ -776,4 +785,4 @@ button:active {
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { showToast } from "vant";
|
|||||||
import ClickCaptcha from "@/components/ClickCaptcha.vue";
|
import ClickCaptcha from "@/components/ClickCaptcha.vue";
|
||||||
import { useDialogStore } from "@/stores/dialogStore";
|
import { useDialogStore } from "@/stores/dialogStore";
|
||||||
import { useUserStore } from "@/stores/userStore";
|
import { useUserStore } from "@/stores/userStore";
|
||||||
|
import { useAliyunCaptcha } from "@/composables/useAliyunCaptcha";
|
||||||
|
|
||||||
const emit = defineEmits(["login-success"]);
|
const emit = defineEmits(["login-success"]);
|
||||||
const dialogStore = useDialogStore();
|
const dialogStore = useDialogStore();
|
||||||
@@ -17,6 +18,7 @@ const isAgreed = ref(false);
|
|||||||
const isCountingDown = ref(false);
|
const isCountingDown = ref(false);
|
||||||
const countdown = ref(60);
|
const countdown = ref(60);
|
||||||
let timer = null;
|
let timer = null;
|
||||||
|
const { runWithCaptcha } = useAliyunCaptcha();
|
||||||
|
|
||||||
// 验证组件状态
|
// 验证组件状态
|
||||||
const showCaptcha = ref(false);
|
const showCaptcha = ref(false);
|
||||||
@@ -46,26 +48,31 @@ async function sendVerificationCode() {
|
|||||||
showToast({ message: "请输入有效的手机号" });
|
showToast({ message: "请输入有效的手机号" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { data, error } = await useApiFetch("auth/sendSms")
|
await runWithCaptcha(
|
||||||
.post({ mobile: phoneNumber.value, actionType: "login" })
|
(captchaVerifyParam) =>
|
||||||
.json();
|
useApiFetch("auth/sendSms")
|
||||||
|
.post({
|
||||||
if (data.value && !error.value) {
|
mobile: phoneNumber.value,
|
||||||
if (data.value.code === 200) {
|
actionType: "login",
|
||||||
showToast({ message: "获取成功" });
|
captchaVerifyParam,
|
||||||
startCountdown();
|
})
|
||||||
// 聚焦到验证码输入框
|
.json(),
|
||||||
nextTick(() => {
|
(res) => {
|
||||||
const verificationCodeInput =
|
if (res.code === 200) {
|
||||||
document.getElementById("verificationCode");
|
showToast({ message: "获取成功" });
|
||||||
if (verificationCodeInput) {
|
startCountdown();
|
||||||
verificationCodeInput.focus();
|
nextTick(() => {
|
||||||
}
|
const verificationCodeInput =
|
||||||
});
|
document.getElementById("verificationCode");
|
||||||
} else {
|
if (verificationCodeInput) {
|
||||||
showToast(data.value.msg);
|
verificationCodeInput.focus();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
} else {
|
||||||
|
showToast(res.msg || "获取失败");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function startCountdown() {
|
function startCountdown() {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const dialogStore = useDialogStore();
|
|||||||
const agentStore = useAgentStore();
|
const agentStore = useAgentStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
import { showToast } from "vant";
|
import { showToast } from "vant";
|
||||||
|
import { useAliyunCaptcha } from "@/composables/useAliyunCaptcha";
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const realName = ref("");
|
const realName = ref("");
|
||||||
const idCard = ref("");
|
const idCard = ref("");
|
||||||
@@ -17,6 +18,7 @@ const isAgreed = ref(false);
|
|||||||
const isCountingDown = ref(false);
|
const isCountingDown = ref(false);
|
||||||
const countdown = ref(60);
|
const countdown = ref(60);
|
||||||
let timer = null;
|
let timer = null;
|
||||||
|
const { runWithCaptcha } = useAliyunCaptcha();
|
||||||
|
|
||||||
// 聚焦状态变量
|
// 聚焦状态变量
|
||||||
const nameFocused = ref(false);
|
const nameFocused = ref(false);
|
||||||
@@ -54,18 +56,24 @@ async function sendVerificationCode() {
|
|||||||
showToast({ message: "请输入有效的手机号" });
|
showToast({ message: "请输入有效的手机号" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { data, error } = await useApiFetch("auth/sendSms")
|
await runWithCaptcha(
|
||||||
.post({ mobile: phoneNumber.value, actionType: "realName" })
|
(captchaVerifyParam) =>
|
||||||
.json();
|
useApiFetch("auth/sendSms")
|
||||||
|
.post({
|
||||||
if (data.value && !error.value) {
|
mobile: phoneNumber.value,
|
||||||
if (data.value.code === 200) {
|
actionType: "realName",
|
||||||
showToast({ message: "获取成功" });
|
captchaVerifyParam,
|
||||||
startCountdown();
|
})
|
||||||
} else {
|
.json(),
|
||||||
showToast(data.value.msg);
|
(res) => {
|
||||||
}
|
if (res.code === 200) {
|
||||||
}
|
showToast({ message: "获取成功" });
|
||||||
|
startCountdown();
|
||||||
|
} else {
|
||||||
|
showToast(res.msg || "获取失败");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function startCountdown() {
|
function startCountdown() {
|
||||||
|
|||||||
155
src/composables/useAliyunCaptcha.js
Normal file
155
src/composables/useAliyunCaptcha.js
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
import { showToast, showLoadingToast, closeToast } from "vant";
|
||||||
|
import useApiFetch from "@/composables/useApiFetch";
|
||||||
|
|
||||||
|
const ALIYUN_CAPTCHA_SCENE_ID = "wynt39to";
|
||||||
|
const ENABLE_ENCRYPTED = false;
|
||||||
|
|
||||||
|
let captchaInitialised = false;
|
||||||
|
let captchaReadyPromise = null;
|
||||||
|
let captchaReadyResolve = null;
|
||||||
|
|
||||||
|
async function ensureCaptchaInit() {
|
||||||
|
if (captchaInitialised || typeof window === "undefined") return;
|
||||||
|
if (typeof window.initAliyunCaptcha !== "function") return;
|
||||||
|
|
||||||
|
captchaInitialised = true;
|
||||||
|
window.captcha = null;
|
||||||
|
window.__lastBizResponse = null;
|
||||||
|
window.__onCaptchaBizSuccess = null;
|
||||||
|
captchaReadyPromise = new Promise((resolve) => {
|
||||||
|
captchaReadyResolve = resolve;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!ENABLE_ENCRYPTED) {
|
||||||
|
window.initAliyunCaptcha({
|
||||||
|
SceneId: ALIYUN_CAPTCHA_SCENE_ID,
|
||||||
|
mode: "popup",
|
||||||
|
element: "#captcha-element",
|
||||||
|
getInstance(instance) {
|
||||||
|
window.captcha = instance;
|
||||||
|
if (typeof captchaReadyResolve === "function") {
|
||||||
|
captchaReadyResolve();
|
||||||
|
captchaReadyResolve = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
captchaVerifyCallback(param) {
|
||||||
|
return typeof window.__captchaVerifyCallback === "function"
|
||||||
|
? window.__captchaVerifyCallback(param)
|
||||||
|
: Promise.resolve({
|
||||||
|
captchaResult: false,
|
||||||
|
bizResult: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onBizResultCallback(bizResult) {
|
||||||
|
if (typeof window.__onBizResultCallback === "function") {
|
||||||
|
window.__onBizResultCallback(bizResult);
|
||||||
|
}
|
||||||
|
window.__lastBizResponse = null;
|
||||||
|
window.__onCaptchaBizSuccess = null;
|
||||||
|
},
|
||||||
|
slideStyle: { width: 360, height: 40 },
|
||||||
|
language: "cn",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data, error } = await useApiFetch("/captcha/encryptedSceneId")
|
||||||
|
.post()
|
||||||
|
.json();
|
||||||
|
const resp = data?.value;
|
||||||
|
const encryptedSceneId = resp?.data?.encryptedSceneId;
|
||||||
|
if (error?.value || !encryptedSceneId) {
|
||||||
|
showToast({ message: "获取验证码参数失败,请稍后重试" });
|
||||||
|
captchaInitialised = false;
|
||||||
|
captchaReadyPromise = null;
|
||||||
|
captchaReadyResolve = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.initAliyunCaptcha({
|
||||||
|
SceneId: ALIYUN_CAPTCHA_SCENE_ID,
|
||||||
|
EncryptedSceneId: encryptedSceneId,
|
||||||
|
mode: "popup",
|
||||||
|
element: "#captcha-element",
|
||||||
|
getInstance(instance) {
|
||||||
|
window.captcha = instance;
|
||||||
|
if (typeof captchaReadyResolve === "function") {
|
||||||
|
captchaReadyResolve();
|
||||||
|
captchaReadyResolve = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
captchaVerifyCallback(param) {
|
||||||
|
return typeof window.__captchaVerifyCallback === "function"
|
||||||
|
? window.__captchaVerifyCallback(param)
|
||||||
|
: Promise.resolve({ captchaResult: false, bizResult: false });
|
||||||
|
},
|
||||||
|
onBizResultCallback(bizResult) {
|
||||||
|
if (typeof window.__onBizResultCallback === "function") {
|
||||||
|
window.__onBizResultCallback(bizResult);
|
||||||
|
}
|
||||||
|
window.__lastBizResponse = null;
|
||||||
|
window.__onCaptchaBizSuccess = null;
|
||||||
|
},
|
||||||
|
slideStyle: { width: 360, height: 40 },
|
||||||
|
language: "cn",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAliyunCaptcha() {
|
||||||
|
async function runWithCaptcha(bizVerify, onSuccess) {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
showToast({ message: "验证码仅支持浏览器环境" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const loading = showLoadingToast({
|
||||||
|
message: "安全验证加载中...",
|
||||||
|
forbidClick: true,
|
||||||
|
duration: 0,
|
||||||
|
loadingType: "spinner",
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
window.__captchaVerifyCallback = async (captchaVerifyParam) => {
|
||||||
|
window.__lastBizResponse = null;
|
||||||
|
const { data, error } = await bizVerify(captchaVerifyParam);
|
||||||
|
const result = data?.value ?? data;
|
||||||
|
if (error?.value || !result) {
|
||||||
|
return { captchaResult: false, bizResult: false };
|
||||||
|
}
|
||||||
|
window.__lastBizResponse = result;
|
||||||
|
const captchaOk = result.captchaVerifyResult !== false;
|
||||||
|
const bizOk = result.code === 200;
|
||||||
|
return { captchaResult: captchaOk, bizResult: bizOk };
|
||||||
|
};
|
||||||
|
|
||||||
|
window.__onBizResultCallback = (bizResult) => {
|
||||||
|
if (
|
||||||
|
bizResult === true &&
|
||||||
|
window.__lastBizResponse &&
|
||||||
|
typeof window.__onCaptchaBizSuccess === "function"
|
||||||
|
) {
|
||||||
|
window.__onCaptchaBizSuccess(window.__lastBizResponse);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await ensureCaptchaInit();
|
||||||
|
|
||||||
|
if (captchaReadyPromise) {
|
||||||
|
await captchaReadyPromise;
|
||||||
|
captchaReadyPromise = null;
|
||||||
|
}
|
||||||
|
if (!window.captcha) {
|
||||||
|
showToast({ message: "验证码未加载,请刷新页面重试" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.__onCaptchaBizSuccess = onSuccess;
|
||||||
|
window.captcha.show();
|
||||||
|
} finally {
|
||||||
|
closeToast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { runWithCaptcha };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useAliyunCaptcha;
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
import { ref, computed, onUnmounted, nextTick } from "vue";
|
import { ref, computed, onUnmounted, nextTick } from "vue";
|
||||||
import { showToast } from "vant";
|
import { showToast } from "vant";
|
||||||
import ClickCaptcha from "@/components/ClickCaptcha.vue";
|
import ClickCaptcha from "@/components/ClickCaptcha.vue";
|
||||||
|
import { useAliyunCaptcha } from "@/composables/useAliyunCaptcha";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const phoneNumber = ref("");
|
const phoneNumber = ref("");
|
||||||
@@ -12,6 +13,7 @@ const isAgreed = ref(false);
|
|||||||
const isCountingDown = ref(false);
|
const isCountingDown = ref(false);
|
||||||
const countdown = ref(60);
|
const countdown = ref(60);
|
||||||
let timer = null;
|
let timer = null;
|
||||||
|
const { runWithCaptcha } = useAliyunCaptcha();
|
||||||
|
|
||||||
// 验证组件状态
|
// 验证组件状态
|
||||||
const showCaptcha = ref(false);
|
const showCaptcha = ref(false);
|
||||||
@@ -41,26 +43,31 @@ async function sendVerificationCode() {
|
|||||||
showToast({ message: "请输入有效的手机号" });
|
showToast({ message: "请输入有效的手机号" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { data, error } = await useApiFetch("auth/sendSms")
|
await runWithCaptcha(
|
||||||
.post({ mobile: phoneNumber.value, actionType: "login" })
|
(captchaVerifyParam) =>
|
||||||
.json();
|
useApiFetch("auth/sendSms")
|
||||||
|
.post({
|
||||||
if (data.value && !error.value) {
|
mobile: phoneNumber.value,
|
||||||
if (data.value.code === 200) {
|
actionType: "login",
|
||||||
showToast({ message: "获取成功" });
|
captchaVerifyParam,
|
||||||
startCountdown();
|
})
|
||||||
// 聚焦到验证码输入框
|
.json(),
|
||||||
nextTick(() => {
|
(res) => {
|
||||||
const verificationCodeInput =
|
if (res.code === 200) {
|
||||||
document.getElementById("verificationCode");
|
showToast({ message: "获取成功" });
|
||||||
if (verificationCodeInput) {
|
startCountdown();
|
||||||
verificationCodeInput.focus();
|
nextTick(() => {
|
||||||
}
|
const verificationCodeInput =
|
||||||
});
|
document.getElementById("verificationCode");
|
||||||
} else {
|
if (verificationCodeInput) {
|
||||||
showToast(data.value.msg);
|
verificationCodeInput.focus();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
} else {
|
||||||
|
showToast(res.msg || "获取失败");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function startCountdown() {
|
function startCountdown() {
|
||||||
|
|||||||
Reference in New Issue
Block a user