f
This commit is contained in:
148
src/pages/sub-portal/SubRegister.vue
Normal file
148
src/pages/sub-portal/SubRegister.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user