149 lines
4.6 KiB
Vue
149 lines
4.6 KiB
Vue
<template>
|
||
<div class="w-full auth-fade-in">
|
||
<div class="text-center mb-6">
|
||
<h2 class="auth-title">注册账号</h2>
|
||
<p class="auth-subtitle">填写邀请码与手机号,完成账号注册</p>
|
||
</div>
|
||
|
||
<form class="space-y-4" @submit.prevent="onRegister">
|
||
<div>
|
||
<label class="auth-label">邀请码 <span class="text-red-500">*</span></label>
|
||
<el-input v-model="form.inviteToken" placeholder="请输入邀请码" size="large" clearable :disabled="loading"
|
||
class="auth-input" />
|
||
</div>
|
||
<div>
|
||
<label class="auth-label">手机号</label>
|
||
<el-input v-model="form.phone" maxlength="11" placeholder="手机号" size="large" :disabled="loading" class="auth-input" />
|
||
</div>
|
||
<div>
|
||
<label class="auth-label">验证码</label>
|
||
<div class="flex gap-3">
|
||
<el-input v-model="form.code" maxlength="6" placeholder="短信验证码" size="large" :disabled="loading" class="auth-input" />
|
||
<el-button type="primary" size="large" :disabled="!canSendCode || loading" :loading="sendingCode"
|
||
class="auth-button !min-w-[120px]" @click="sendCode">
|
||
{{ countdown > 0 ? `${countdown}s` : '获取验证码' }}
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label class="auth-label">密码</label>
|
||
<el-input v-model="form.password" type="password" show-password size="large" :disabled="loading" class="auth-input" />
|
||
</div>
|
||
<div>
|
||
<label class="auth-label">确认密码</label>
|
||
<el-input v-model="form.confirmPassword" type="password" show-password size="large" :disabled="loading"
|
||
class="auth-input" />
|
||
</div>
|
||
<div class="text-center">
|
||
<router-link to="/sub/auth/login" class="auth-link text-sm">返回登录</router-link>
|
||
</div>
|
||
<el-button type="primary" size="large" class="auth-button w-full !h-12" native-type="submit" :loading="loading"
|
||
:disabled="!canSubmit">
|
||
注册
|
||
</el-button>
|
||
</form>
|
||
|
||
<p class="mt-4 text-xs text-center text-slate-400">
|
||
请确认邀请码来源可信,避免账号安全风险
|
||
</p>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { subPortalApi } from '@/api'
|
||
import { useAliyunCaptcha } from '@/composables/useAliyunCaptcha'
|
||
import { useUserStore } from '@/stores/user'
|
||
import { ElMessage } from 'element-plus'
|
||
|
||
const route = useRoute()
|
||
const router = useRouter()
|
||
const userStore = useUserStore()
|
||
const { runWithCaptcha } = useAliyunCaptcha()
|
||
|
||
const form = ref({
|
||
inviteToken: '',
|
||
phone: '',
|
||
code: '',
|
||
password: '',
|
||
confirmPassword: ''
|
||
})
|
||
const loading = ref(false)
|
||
const sendingCode = ref(false)
|
||
const countdown = ref(0)
|
||
let timer = null
|
||
|
||
// 与主站同仓同构建:链接 ?invite= 或主账号复制的完整 URL 均会打开本页并预填邀请码
|
||
watch(
|
||
() => route.query.invite,
|
||
(inv) => {
|
||
if (typeof inv === 'string' && inv) {
|
||
form.value.inviteToken = inv
|
||
}
|
||
},
|
||
{ immediate: true }
|
||
)
|
||
|
||
const canSendCode = computed(
|
||
() => form.value.phone?.length === 11 && countdown.value === 0
|
||
)
|
||
const canSubmit = computed(
|
||
() =>
|
||
form.value.inviteToken &&
|
||
form.value.phone?.length === 11 &&
|
||
form.value.code?.length === 6 &&
|
||
form.value.password?.length >= 6 &&
|
||
form.value.password === form.value.confirmPassword
|
||
)
|
||
|
||
const sendCode = async () => {
|
||
if (!canSendCode.value) return
|
||
sendingCode.value = true
|
||
try {
|
||
await runWithCaptcha(
|
||
async (captcha) => userStore.sendCode(form.value.phone, 'register', captcha),
|
||
(res) => {
|
||
if (res.success) {
|
||
ElMessage.success('验证码已发送')
|
||
countdown.value = 60
|
||
timer = setInterval(() => {
|
||
countdown.value--
|
||
if (countdown.value <= 0) clearInterval(timer)
|
||
}, 1000)
|
||
} else {
|
||
ElMessage.error(res?.error?.message || '发送失败')
|
||
}
|
||
}
|
||
)
|
||
} finally {
|
||
sendingCode.value = false
|
||
}
|
||
}
|
||
|
||
const onRegister = async () => {
|
||
if (!canSubmit.value) return
|
||
loading.value = true
|
||
try {
|
||
const res = await subPortalApi.register({
|
||
phone: form.value.phone,
|
||
password: form.value.password,
|
||
confirm_password: form.value.confirmPassword,
|
||
code: form.value.code,
|
||
invite_token: form.value.inviteToken
|
||
})
|
||
if (res?.success) {
|
||
ElMessage.success('注册成功,请登录')
|
||
router.push('/sub/auth/login')
|
||
}
|
||
} catch (e) {
|
||
ElMessage.error(e?.response?.data?.message || e?.message || '注册失败')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
onUnmounted(() => {
|
||
if (timer) clearInterval(timer)
|
||
})
|
||
</script>
|
||
|