feat(player): 接入创蓝短信手机注册与登录页优化

新增 SMS 验证码注册、8 国手机号选择与 Redis 频控;优化登录/注册 UI 及图形验证码样式。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-12 10:25:59 +08:00
parent 168aecfd5c
commit db28390be9
39 changed files with 1521 additions and 107 deletions

View File

@@ -0,0 +1,63 @@
import { ref, onUnmounted } from 'vue';
import api from '../api';
const COOLDOWN_SECONDS = 60;
export function useSmsCode() {
const sessionId = ref<string | null>(null);
const countdown = ref(0);
const sending = ref(false);
const error = ref<string | null>(null);
let timer: ReturnType<typeof setInterval> | null = null;
function clearTimer() {
if (timer) {
clearInterval(timer);
timer = null;
}
}
function startCountdown() {
clearTimer();
countdown.value = COOLDOWN_SECONDS;
timer = setInterval(() => {
if (countdown.value <= 1) {
clearTimer();
countdown.value = 0;
} else {
countdown.value -= 1;
}
}, 1000);
}
async function send(phone: string, countryCode: string) {
if (countdown.value > 0 || sending.value) return;
const trimmed = phone.trim();
const dial = countryCode.replace(/\D/g, '');
if (!trimmed || !dial) {
error.value = 'phone_required';
return;
}
sending.value = true;
error.value = null;
try {
const locale = localStorage.getItem('locale') || 'zh-CN';
const { data } = await api.post('/player/sms/send', {
phone: trimmed,
countryCode: dial,
locale,
});
sessionId.value = data.data.sessionId;
startCountdown();
} catch (e: unknown) {
const msg = (e as { response?: { data?: { error?: string } } })?.response?.data?.error;
error.value = msg || 'send_failed';
} finally {
sending.value = false;
}
}
onUnmounted(clearTimer);
return { sessionId, countdown, sending, error, send };
}