diff --git a/frontend/src/features/auth/views/LoginView.vue b/frontend/src/features/auth/views/LoginView.vue index a1dbc66..c317b91 100644 --- a/frontend/src/features/auth/views/LoginView.vue +++ b/frontend/src/features/auth/views/LoginView.vue @@ -1,17 +1,30 @@ diff --git a/frontend/src/features/auth/views/MobileLoginView.vue b/frontend/src/features/auth/views/MobileLoginView.vue index 1bdebcd..4eff0e0 100644 --- a/frontend/src/features/auth/views/MobileLoginView.vue +++ b/frontend/src/features/auth/views/MobileLoginView.vue @@ -27,7 +27,16 @@ const form = reactive({ const { countDown, sending, handleSendCode } = useSmsCountdown() -onMounted(loadCaptcha) +onMounted(() => { + if (route.query.tab === 'register' || route.query.invite_code || route.query.code) { + void router.replace({ + path: '/m/register', + query: route.query, + }) + return + } + void loadCaptcha() +}) function switchToPassword() { loginMode.value = 'password' diff --git a/frontend/src/features/auth/views/MobileRegisterView.vue b/frontend/src/features/auth/views/MobileRegisterView.vue index 24a288d..ebd7d4f 100644 --- a/frontend/src/features/auth/views/MobileRegisterView.vue +++ b/frontend/src/features/auth/views/MobileRegisterView.vue @@ -13,10 +13,15 @@ const router = useRouter() const route = useRoute() const session = useSessionStore() const siteStore = useDistributionSiteStore() + const loading = ref(false) const agreed = ref(false) const captchaLoading = ref(false) const captcha = ref(null) +const isInviteLocked = ref(false) +const showPassword = ref(false) +const showConfirmPassword = ref(false) + const form = reactive({ phone: '', captchaCode: '', @@ -28,7 +33,14 @@ const form = reactive({ const { countDown, sending, handleSendCode } = useSmsCountdown() -onMounted(loadCaptcha) +onMounted(async () => { + await loadCaptcha() + const qInviteCode = (route.query.invite_code || route.query.code) as string | undefined + if (qInviteCode && qInviteCode.trim()) { + form.inviteCode = qInviteCode.trim() + isInviteLocked.value = true + } +}) async function loadCaptcha() { captchaLoading.value = true @@ -54,11 +66,20 @@ async function sendCode() { } async function handleRegister() { - if (!agreed.value) { - showToast({ - message: '请先阅读并同意用户协议和隐私政策', - icon: 'warning-o', - }) + if (!form.phone.trim()) { + showToast({ message: '请输入手机号', icon: 'warning-o' }) + return + } + if (!/^1[3-9]\d{9}$/.test(form.phone.trim())) { + showToast({ message: '请输入正确的11位手机号码', icon: 'warning-o' }) + return + } + if (!form.captchaCode.trim()) { + showToast({ message: '请输入图形验证码', icon: 'warning-o' }) + return + } + if (!form.code.trim()) { + showToast({ message: '请输入短信验证码', icon: 'warning-o' }) return } if (!form.password) { @@ -73,14 +94,27 @@ async function handleRegister() { showToast({ message: '两次输入的密码不一致', icon: 'warning-o' }) return } + if (!agreed.value) { + showToast({ + message: '请先阅读并同意用户协议和隐私政策', + icon: 'warning-o', + }) + return + } loading.value = true try { - await session.register(form.phone, form.code, form.password) + await session.register( + form.phone.trim(), + form.code.trim(), + form.password, + form.inviteCode.trim() || undefined + ) + showToast({ message: '注册成功', icon: 'success' }) const redirect = typeof route.query.redirect === 'string' ? route.query.redirect : '/m/profile' await router.replace(redirect) - } catch { - showToast({ message: '注册失败,请检查手机号和验证码', icon: 'cross' }) + } catch (error) { + showToast({ message: readError(error, '注册失败,请核对信息'), icon: 'cross' }) } finally { loading.value = false } @@ -90,12 +124,13 @@ async function handleRegister() {