/** 邮件/手机验证码发送:复用人机验证,成功后倒计时,组件销毁清理定时器。 */ import { onScopeDispose } from "vue"; import { ref } from "vue"; import { useApi } from "~/lib/auth.js"; import { t as interval_t } from "~/lib/interval.js"; function i(i) { let a = useApi(), o = ref(!1), s = ref(0), c = null, l = !1; function u() { c &&= (clearInterval(c), null); } // 默认为 60 秒;重复启动先清旧定时器,防止多次递减造成提前结束。 function d() { l || (u(), (s.value = i.seconds ?? 60), (c = interval_t(() => { (--s.value, s.value <= 0 && u()); }, 1e3))); } onScopeDispose(() => { ((l = !0), u()); }); /** e 为 email 或手机场景,t 为收件账号,n 为账号缺失提示;发送中/倒计时中直接忽略。 */ async function f(e, t, n) { if (l || o.value || s.value > 0) return; if (((i.error.value = ``), !t)) { i.error.value = n; return; } let r = i.captcha.validationError(); if (r) { i.error.value = r; return; } o.value = !0; try { let n = { action: i.action, captcha: i.captcha.value.value.trim(), token: i.captcha.token.value, }; if (e === `email`) await a.post(`/email/code`, { ...n, email: t, }); else { // 此发送器只服务新输入手机号;已保存号码的安全验证走原后端账号契约,不在这里改写。 await a.post(`/phone/code`, { ...n, phone_code: 86, phone: t, }); } // 发送成功才开始倒计时;已消费的人机验证失效/刷新,不能在下一次发送时复用。 (d(), !l && i.captcha.needed.value && (i.captcha.provider.value === `geetest` ? i.captcha.invalidate() : i.captcha.load())); } catch (e) { if (l) return; ((i.error.value = e instanceof Error ? e.message : `验证码发送失败`), await i.captcha.handleError(e)); } finally { o.value = !1; } } return { sending: o, countdown: s, send: f, start: d, stop: u, }; } export { i as t };