Add new components for login and comment functionality
This commit is contained in:
333
components/kl-register/index.vue
Normal file
333
components/kl-register/index.vue
Normal file
@ -0,0 +1,333 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user