334 lines
7.7 KiB
Vue
334 lines
7.7 KiB
Vue
<template>
|
||
<div v-if="visible" class="popup-overlay">
|
||
<div class="popup-content">
|
||
<div class="register-container relative">
|
||
<el-icon class="absolute! right-0 top-0 cursor-pointer" @click="onClose()"><Close /></el-icon>
|
||
<!-- 左侧插图 -->
|
||
<div class="register-left">
|
||
<img src="~/assets/images/login-illustration.png" alt="register" class="register-img" />
|
||
</div>
|
||
|
||
<!-- 右侧注册表单 -->
|
||
<div class="register-right">
|
||
<h2 class="register-title">快速注册</h2>
|
||
|
||
<!-- 注册表单 -->
|
||
<el-form ref="formRef" :model="registerForm" :rules="rules" class="register-form">
|
||
<!-- 手机号输入 -->
|
||
<el-form-item prop="phone">
|
||
<div class="phone-input">
|
||
<div class="area-code">+86</div>
|
||
<el-input v-model="registerForm.phone" placeholder="请输入注册手机号" class="phone-number w-280px!" />
|
||
</div>
|
||
</el-form-item>
|
||
|
||
<!-- 验证码输入 -->
|
||
<el-form-item prop="code">
|
||
<div class="verify-code-input">
|
||
<el-input v-model="registerForm.code" placeholder="请输入短信验证码" />
|
||
<el-button type="primary" class="get-code-btn" :disabled="counting > 0" @click="handleSendCode">
|
||
{{ counting > 0 ? `${counting}s后重新获取` : '获取验证码' }}
|
||
</el-button>
|
||
</div>
|
||
</el-form-item>
|
||
|
||
<!-- 注册按钮 -->
|
||
<el-button type="primary" class="register-button" @click="handleRegister"> 立即注册 </el-button>
|
||
|
||
<!-- 用户协议 -->
|
||
<div class="agreement">
|
||
<el-checkbox v-model="registerForm.agreement"> 我已阅读并同意<span class="link">《多多用户协议》</span> </el-checkbox>
|
||
</div>
|
||
|
||
<!-- 登录入口 -->
|
||
<div class="login-link"> 已有账号?<span class="link" @click="goToLogin">点击登录</span> </div>
|
||
</el-form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, reactive } from 'vue'
|
||
import type { FormInstance } from 'element-plus'
|
||
import { Close } from '@element-plus/icons-vue'
|
||
import { sendSms } from '~/api/common/index'
|
||
import { loginByMobile } from '~/api/login/index'
|
||
const { $openLogin } = useNuxtApp()
|
||
|
||
import REFRESHTOKEN from '~/utils/RefreshToken'
|
||
import useUserStore from '~/store/user'
|
||
const userStore = useUserStore()
|
||
|
||
const props = defineProps({
|
||
visible: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
onClose: {
|
||
type: Function,
|
||
default: () => ({}),
|
||
},
|
||
})
|
||
const formRef = ref<FormInstance>()
|
||
const counting = ref(0)
|
||
|
||
const registerForm = reactive({
|
||
phone: '',
|
||
code: '',
|
||
agreement: false,
|
||
})
|
||
|
||
// 表单验证规则
|
||
const rules = {
|
||
phone: [
|
||
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' },
|
||
],
|
||
code: [
|
||
{ required: true, message: '请输入验证码', trigger: 'blur' },
|
||
{ len: 6, message: '验证码长度应为6位', trigger: 'blur' },
|
||
],
|
||
}
|
||
|
||
// 发送验证码
|
||
const handleSendCode = async () => {
|
||
if (counting.value > 0) return
|
||
|
||
// 验证手机号
|
||
try {
|
||
await formRef.value?.validateField('phone')
|
||
} catch (error) {
|
||
return
|
||
}
|
||
|
||
// TODO: 调用发送验证码接口
|
||
const res = await sendSms({
|
||
mobile: registerForm.phone,
|
||
scene: 1, // 场景值,根据实际情况设置
|
||
})
|
||
if (res.code !== 0) return
|
||
if (res.code === 0) {
|
||
ElMessage.success('验证码发送成功')
|
||
}
|
||
|
||
// 开始倒计时
|
||
counting.value = 60
|
||
const timer = setInterval(() => {
|
||
counting.value--
|
||
if (counting.value <= 0) {
|
||
clearInterval(timer)
|
||
}
|
||
}, 1000)
|
||
}
|
||
|
||
// 注册处理
|
||
const handleRegister = async () => {
|
||
if (!registerForm.agreement) {
|
||
ElMessage.warning('请先同意用户协议')
|
||
return
|
||
}
|
||
|
||
try {
|
||
await formRef.value?.validate()
|
||
// TODO: 调用注册接口
|
||
const res = await loginByMobile({
|
||
mobile: registerForm.phone,
|
||
code: registerForm.code,
|
||
})
|
||
if (res.code === 0) {
|
||
const data = res.data
|
||
REFRESHTOKEN.setToken(data.accessToken, data.refreshToken)
|
||
REFRESHTOKEN.setUserId(data.userId.toString())
|
||
REFRESHTOKEN.setUserName(registerForm.phone)
|
||
userStore.setToken(data.accessToken)
|
||
userStore.setUserId(data.userId.toString())
|
||
userStore.setUserName(registerForm.phone)
|
||
userStore.setRefreshToken(data.refreshToken)
|
||
ElMessage.success('注册成功')
|
||
props.onClose()
|
||
}
|
||
} catch (error) {
|
||
return
|
||
}
|
||
}
|
||
|
||
// 跳转到登录
|
||
const goToLogin = () => {
|
||
props.onClose()
|
||
// TODO: 触发切换到登录页面的事件
|
||
// emit('switch-to-login')
|
||
$openLogin && $openLogin()
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.register-dialog {
|
||
.el-dialog {
|
||
border-radius: 12px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.el-dialog__header {
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
.el-dialog__body {
|
||
padding: 0 !important;
|
||
}
|
||
}
|
||
</style>
|
||
|
||
<style scoped lang="scss">
|
||
.popup-overlay {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background-color: rgba(0, 0, 0, 0.5);
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
z-index: 10;
|
||
.popup-content {
|
||
background-color: white;
|
||
padding: 20px;
|
||
border-radius: 5px;
|
||
}
|
||
}
|
||
.register-container {
|
||
display: flex;
|
||
height: 508px;
|
||
}
|
||
|
||
.register-left {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: #f9faff;
|
||
width: 480px;
|
||
|
||
.register-img {
|
||
width: 438px;
|
||
height: 258px;
|
||
}
|
||
}
|
||
|
||
.register-right {
|
||
padding: 22px 25px;
|
||
box-sizing: border-box;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
|
||
.register-title {
|
||
font-size: 20px;
|
||
color: #333;
|
||
text-align: center;
|
||
margin-bottom: 40px;
|
||
font-weight: normal;
|
||
}
|
||
|
||
.register-form {
|
||
width: 320px;
|
||
margin: 0 auto;
|
||
|
||
.phone-input {
|
||
display: flex;
|
||
align-items: center;
|
||
background: #f5f5f5;
|
||
border-radius: 4px;
|
||
|
||
.area-code {
|
||
padding: 0 12px;
|
||
color: #333;
|
||
font-size: 14px;
|
||
border-right: 1px solid #dcdfe6;
|
||
}
|
||
|
||
.phone-number {
|
||
flex: 1;
|
||
|
||
:deep(.el-input__wrapper) {
|
||
background: transparent;
|
||
box-shadow: none !important;
|
||
}
|
||
}
|
||
}
|
||
|
||
.verify-code-input {
|
||
display: flex;
|
||
gap: 12px;
|
||
|
||
.el-input {
|
||
flex: 1;
|
||
|
||
:deep(.el-input__wrapper) {
|
||
background: #f5f5f5;
|
||
box-shadow: none !important;
|
||
}
|
||
}
|
||
|
||
.get-code-btn {
|
||
width: 120px;
|
||
height: 40px;
|
||
padding: 0;
|
||
border-radius: 4px;
|
||
|
||
&:disabled {
|
||
color: #999;
|
||
background-color: #f5f5f5;
|
||
border-color: #dcdfe6;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.register-button {
|
||
width: 100%;
|
||
height: 40px;
|
||
margin-top: 24px;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.agreement {
|
||
margin: 16px 0;
|
||
font-size: 14px;
|
||
color: #666;
|
||
text-align: left;
|
||
|
||
.link {
|
||
color: #1677ff;
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
|
||
.login-link {
|
||
text-align: right;
|
||
font-size: 14px;
|
||
color: #666;
|
||
margin-top: 20px;
|
||
|
||
.link {
|
||
color: #1677ff;
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
|
||
:deep(.el-form-item) {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
:deep(.el-input__wrapper) {
|
||
background: #f5f5f5;
|
||
box-shadow: none !important;
|
||
}
|
||
|
||
:deep(.el-input__inner) {
|
||
height: 40px;
|
||
}
|
||
</style>
|