Files
front-pc/components/kl-register/index.vue

334 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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 as REFRESHTOKEN } from '~/utils/axios'
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>