修改注册界面
This commit is contained in:
parent
b4cc05bc1c
commit
b5a549669f
|
@ -18,57 +18,128 @@
|
||||||
|
|
||||||
<el-card class="login-card">
|
<el-card class="login-card">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<el-tabs v-model="activeTab" class="login-tabs">
|
||||||
<span>用户登录</span>
|
<el-tab-pane label="账号密码登录" name="account">
|
||||||
</div>
|
<el-form
|
||||||
|
ref="accountFormRef"
|
||||||
|
:model="accountForm"
|
||||||
|
:rules="accountRules"
|
||||||
|
label-width="0"
|
||||||
|
>
|
||||||
|
<el-form-item prop="username">
|
||||||
|
<el-input
|
||||||
|
v-model="accountForm.username"
|
||||||
|
placeholder="请输入用户名/手机号/邮箱"
|
||||||
|
:prefix-icon="User"
|
||||||
|
class="custom-input"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item prop="password">
|
||||||
|
<el-input
|
||||||
|
v-model="accountForm.password"
|
||||||
|
type="password"
|
||||||
|
placeholder="请输入密码"
|
||||||
|
:prefix-icon="Lock"
|
||||||
|
show-password
|
||||||
|
class="custom-input"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="手机号登录" name="phone">
|
||||||
|
<el-form
|
||||||
|
ref="phoneFormRef"
|
||||||
|
:model="phoneForm"
|
||||||
|
:rules="phoneRules"
|
||||||
|
label-width="0"
|
||||||
|
>
|
||||||
|
<el-form-item prop="phone">
|
||||||
|
<div class="verify-input">
|
||||||
|
<el-input
|
||||||
|
v-model="phoneForm.phone"
|
||||||
|
placeholder="请输入手机号"
|
||||||
|
:prefix-icon="Phone"
|
||||||
|
class="custom-input"
|
||||||
|
/>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="phoneCooldown > 0"
|
||||||
|
@click="sendPhoneCode"
|
||||||
|
>
|
||||||
|
{{ phoneCooldown > 0 ? `${phoneCooldown}s` : '获取验证码' }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item prop="code">
|
||||||
|
<el-input
|
||||||
|
v-model="phoneForm.code"
|
||||||
|
placeholder="请输入验证码"
|
||||||
|
:prefix-icon="Key"
|
||||||
|
class="custom-input"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="邮箱登录" name="email">
|
||||||
|
<el-form
|
||||||
|
ref="emailFormRef"
|
||||||
|
:model="emailForm"
|
||||||
|
:rules="emailRules"
|
||||||
|
label-width="0"
|
||||||
|
>
|
||||||
|
<el-form-item prop="email">
|
||||||
|
<div class="verify-input">
|
||||||
|
<el-input
|
||||||
|
v-model="emailForm.email"
|
||||||
|
placeholder="请输入邮箱"
|
||||||
|
:prefix-icon="Message"
|
||||||
|
class="custom-input"
|
||||||
|
/>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="emailCooldown > 0"
|
||||||
|
@click="sendEmailCode"
|
||||||
|
>
|
||||||
|
{{ emailCooldown > 0 ? `${emailCooldown}s` : '获取验证码' }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item prop="code">
|
||||||
|
<el-input
|
||||||
|
v-model="emailForm.code"
|
||||||
|
placeholder="请输入验证码"
|
||||||
|
:prefix-icon="Key"
|
||||||
|
class="custom-input"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-form
|
<div class="remember-forgot">
|
||||||
ref="loginFormRef"
|
<el-checkbox v-model="rememberMe">记住我</el-checkbox>
|
||||||
:model="loginForm"
|
<el-link type="primary" :underline="false" @click="forgotPassword">忘记密码?</el-link>
|
||||||
:rules="rules"
|
</div>
|
||||||
label-width="0"
|
|
||||||
@keyup.enter="handleLogin"
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
class="login-button"
|
||||||
|
:loading="loading"
|
||||||
|
@click="handleLogin"
|
||||||
>
|
>
|
||||||
<el-form-item prop="username">
|
{{ loading ? '登录中...' : '登录' }}
|
||||||
<el-input
|
</el-button>
|
||||||
v-model="loginForm.username"
|
|
||||||
placeholder="请输入用户名"
|
|
||||||
:prefix-icon="User"
|
|
||||||
class="custom-input"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item prop="password">
|
<div class="register-link">
|
||||||
<el-input
|
还没有账号?
|
||||||
v-model="loginForm.password"
|
<router-link to="/register" class="register-btn">立即注册</router-link>
|
||||||
type="password"
|
</div>
|
||||||
placeholder="请输入密码"
|
|
||||||
:prefix-icon="Lock"
|
|
||||||
show-password
|
|
||||||
class="custom-input"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<div class="remember-forgot">
|
|
||||||
<el-checkbox v-model="rememberMe">记住我</el-checkbox>
|
|
||||||
<el-link type="primary" @click="forgotPassword" :underline="false">忘记密码?</el-link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
class="login-button"
|
|
||||||
:loading="loading"
|
|
||||||
@click="handleLogin"
|
|
||||||
>
|
|
||||||
{{ loading ? '登录中...' : '登录' }}
|
|
||||||
</el-button>
|
|
||||||
|
|
||||||
<div class="register-link">
|
|
||||||
还没有账号?
|
|
||||||
<router-link to="/register" class="register-btn">立即注册</router-link>
|
|
||||||
</div>
|
|
||||||
</el-form>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
|
@ -82,35 +153,125 @@
|
||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive } from 'vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { User, Lock } from '@element-plus/icons-vue'
|
import { User, Lock, Phone, Message, Key } from '@element-plus/icons-vue'
|
||||||
import type { FormInstance } from 'element-plus'
|
import type { FormInstance } from 'element-plus'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const loginFormRef = ref<FormInstance>()
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const rememberMe = ref(false)
|
const rememberMe = ref(false)
|
||||||
|
const activeTab = ref('account')
|
||||||
|
|
||||||
const loginForm = reactive({
|
// 账号密码登录表单
|
||||||
|
const accountFormRef = ref<FormInstance>()
|
||||||
|
const accountForm = reactive({
|
||||||
username: '',
|
username: '',
|
||||||
password: ''
|
password: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
const rules = {
|
// 手机号登录表单
|
||||||
|
const phoneFormRef = ref<FormInstance>()
|
||||||
|
const phoneForm = reactive({
|
||||||
|
phone: '',
|
||||||
|
code: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 邮箱登录表单
|
||||||
|
const emailFormRef = ref<FormInstance>()
|
||||||
|
const emailForm = reactive({
|
||||||
|
email: '',
|
||||||
|
code: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 验证码倒计时
|
||||||
|
const phoneCooldown = ref(0)
|
||||||
|
const emailCooldown = ref(0)
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const accountRules = {
|
||||||
username: [
|
username: [
|
||||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
{ required: true, message: '请输入用户名/手机号/邮箱', trigger: 'blur' }
|
||||||
{ min: 3, message: '用户名长度不能小于3个字符', trigger: 'blur' }
|
|
||||||
],
|
],
|
||||||
password: [
|
password: [
|
||||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
{ required: true, message: '请输入密码', trigger: 'blur' }
|
||||||
{ min: 6, message: '密码长度不能小于6个字符', trigger: 'blur' }
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleLogin = async () => {
|
const phoneRules = {
|
||||||
if (!loginFormRef.value) return
|
phone: [
|
||||||
|
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||||||
|
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
code: [
|
||||||
|
{ required: true, message: '请输入验证码', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
await loginFormRef.value.validate(async (valid) => {
|
const emailRules = {
|
||||||
|
email: [
|
||||||
|
{ required: true, message: '请输入邮箱', trigger: 'blur' },
|
||||||
|
{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
code: [
|
||||||
|
{ required: true, message: '请输入验证码', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送验证码
|
||||||
|
const startCooldown = (type: 'phone' | 'email') => {
|
||||||
|
const cooldown = type === 'phone' ? phoneCooldown : emailCooldown
|
||||||
|
cooldown.value = 60
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
cooldown.value--
|
||||||
|
if (cooldown.value <= 0) {
|
||||||
|
clearInterval(timer)
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
const sendPhoneCode = async () => {
|
||||||
|
if (!phoneForm.phone) {
|
||||||
|
ElMessage.warning('请先输入手机号')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO: 调用发送验证码API
|
||||||
|
ElMessage.success('验证码已发送')
|
||||||
|
startCooldown('phone')
|
||||||
|
}
|
||||||
|
|
||||||
|
const sendEmailCode = async () => {
|
||||||
|
if (!emailForm.email) {
|
||||||
|
ElMessage.warning('请先输入邮箱')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO: 调用发送验证码API
|
||||||
|
ElMessage.success('验证码已发送')
|
||||||
|
startCooldown('email')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录处理
|
||||||
|
const handleLogin = async () => {
|
||||||
|
let formRef: FormInstance | undefined
|
||||||
|
let formData: any
|
||||||
|
|
||||||
|
switch (activeTab.value) {
|
||||||
|
case 'account':
|
||||||
|
formRef = accountFormRef.value
|
||||||
|
formData = accountForm
|
||||||
|
break
|
||||||
|
case 'phone':
|
||||||
|
formRef = phoneFormRef.value
|
||||||
|
formData = phoneForm
|
||||||
|
break
|
||||||
|
case 'email':
|
||||||
|
formRef = emailFormRef.value
|
||||||
|
formData = emailForm
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!formRef) return
|
||||||
|
|
||||||
|
await formRef.validate(async (valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
|
@ -120,7 +281,8 @@ const handleLogin = async () => {
|
||||||
// 保存token和用户信息
|
// 保存token和用户信息
|
||||||
localStorage.setItem('token', 'dummy-token')
|
localStorage.setItem('token', 'dummy-token')
|
||||||
if (rememberMe.value) {
|
if (rememberMe.value) {
|
||||||
localStorage.setItem('username', loginForm.username)
|
localStorage.setItem('loginType', activeTab.value)
|
||||||
|
localStorage.setItem('loginData', JSON.stringify(formData))
|
||||||
}
|
}
|
||||||
|
|
||||||
ElMessage.success('登录成功')
|
ElMessage.success('登录成功')
|
||||||
|
@ -129,7 +291,7 @@ const handleLogin = async () => {
|
||||||
const redirect = route.query.redirect as string
|
const redirect = route.query.redirect as string
|
||||||
router.push(redirect || '/')
|
router.push(redirect || '/')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ElMessage.error('登录失败,请检查用户名和密码')
|
ElMessage.error('登录失败,请检查输入信息')
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
@ -354,4 +516,59 @@ const forgotPassword = () => {
|
||||||
height: 80px;
|
height: 80px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 添加新样式 */
|
||||||
|
.login-tabs {
|
||||||
|
margin-bottom: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-tabs :deep(.el-tabs__header) {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-input {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-input .el-input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-input .el-button {
|
||||||
|
width: 120px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 优化输入框样式 */
|
||||||
|
.custom-input {
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-input :deep(.el-input__wrapper) {
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
box-shadow: none !important;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-input :deep(.el-input__wrapper:hover) {
|
||||||
|
border-color: #c0c4cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-input :deep(.el-input__wrapper.is-focus) {
|
||||||
|
border-color: #409EFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 优化按钮样式 */
|
||||||
|
.el-button {
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button:not(:disabled):hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -5,23 +5,23 @@
|
||||||
<div class="shape"></div>
|
<div class="shape"></div>
|
||||||
</div>
|
</div>
|
||||||
<el-card class="register-card" :body-style="{ padding: '30px' }">
|
<el-card class="register-card" :body-style="{ padding: '30px' }">
|
||||||
<div class="register-header">
|
<div class="register-content">
|
||||||
<div class="logo">
|
<div class="basic-info">
|
||||||
<el-icon :size="40" color="#409EFF"><Platform /></el-icon>
|
<div class="register-header">
|
||||||
</div>
|
<div class="logo">
|
||||||
<h2>智慧养老平台</h2>
|
<el-icon :size="40" color="#409EFF"><Platform /></el-icon>
|
||||||
<p class="subtitle">创建新账号</p>
|
</div>
|
||||||
</div>
|
<h2>智慧养老平台</h2>
|
||||||
|
<p class="subtitle">创建新账号</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<el-form
|
<el-form
|
||||||
ref="registerFormRef"
|
ref="registerFormRef"
|
||||||
:model="registerForm"
|
:model="registerForm"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
label-position="top"
|
label-position="top"
|
||||||
class="animated-form"
|
class="animated-form"
|
||||||
>
|
>
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="姓名" prop="username">
|
<el-form-item label="姓名" prop="username">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="registerForm.username"
|
v-model="registerForm.username"
|
||||||
|
@ -34,90 +34,146 @@
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
<el-form-item label="密码" prop="password">
|
||||||
<el-form-item label="手机号" prop="phone">
|
|
||||||
<el-input
|
<el-input
|
||||||
v-model="registerForm.phone"
|
v-model="registerForm.password"
|
||||||
|
type="password"
|
||||||
|
show-password
|
||||||
class="custom-input"
|
class="custom-input"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<div class="input-icon">
|
<div class="input-icon">
|
||||||
<el-icon><Phone /></el-icon>
|
<el-icon><Lock /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-form-item label="密码" prop="password">
|
<el-form-item label="确认密码" prop="confirmPassword">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="registerForm.password"
|
v-model="registerForm.confirmPassword"
|
||||||
type="password"
|
type="password"
|
||||||
show-password
|
show-password
|
||||||
class="custom-input"
|
class="custom-input"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<div class="input-icon">
|
<div class="input-icon">
|
||||||
<el-icon><Lock /></el-icon>
|
<el-icon><Lock /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
<el-form-item label="确认密码" prop="confirmPassword">
|
|
||||||
<el-input
|
|
||||||
v-model="registerForm.confirmPassword"
|
|
||||||
type="password"
|
|
||||||
show-password
|
|
||||||
class="custom-input"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<div class="input-icon">
|
|
||||||
<el-icon><Lock /></el-icon>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="验证码" prop="verifyCode">
|
|
||||||
<div class="verify-code-input">
|
|
||||||
<el-input
|
|
||||||
v-model="registerForm.verifyCode"
|
|
||||||
class="custom-input"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<div class="input-icon">
|
|
||||||
<el-icon><Message /></el-icon>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
:disabled="cooldown > 0"
|
|
||||||
@click="sendVerifyCode"
|
|
||||||
>
|
|
||||||
{{ cooldown > 0 ? `${cooldown}s` : '获取验证码' }}
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
class="register-button"
|
|
||||||
:loading="loading"
|
|
||||||
@click="handleRegister"
|
|
||||||
>
|
|
||||||
<span class="button-text">注 册</span>
|
|
||||||
<el-icon class="button-icon"><Right /></el-icon>
|
|
||||||
</el-button>
|
|
||||||
|
|
||||||
<div class="login-link">
|
|
||||||
已有账号?
|
|
||||||
<router-link to="/login" class="login-btn">立即登录</router-link>
|
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
|
||||||
|
<div class="verify-info">
|
||||||
|
<div class="divider">联系方式验证</div>
|
||||||
|
|
||||||
|
<div class="verify-section">
|
||||||
|
<div class="verify-title">
|
||||||
|
<el-icon><Phone /></el-icon>
|
||||||
|
<span>手机验证</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-form-item label="手机号" prop="phone">
|
||||||
|
<div class="verify-code-input">
|
||||||
|
<el-input
|
||||||
|
v-model="registerForm.phone"
|
||||||
|
placeholder="请输入手机号"
|
||||||
|
class="custom-input"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<div class="input-icon">
|
||||||
|
<el-icon><Phone /></el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="phoneCooldown > 0"
|
||||||
|
@click="sendPhoneCode"
|
||||||
|
>
|
||||||
|
{{ phoneCooldown > 0 ? `${phoneCooldown}s` : '获取验证码' }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="验证码" prop="phoneCode">
|
||||||
|
<el-input
|
||||||
|
v-model="registerForm.phoneCode"
|
||||||
|
placeholder="请输入手机验证码"
|
||||||
|
class="custom-input"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<div class="input-icon">
|
||||||
|
<el-icon><Key /></el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="verify-section">
|
||||||
|
<div class="verify-title">
|
||||||
|
<el-icon><Message /></el-icon>
|
||||||
|
<span>邮箱验证</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-form-item label="邮箱" prop="email">
|
||||||
|
<div class="verify-code-input">
|
||||||
|
<el-input
|
||||||
|
v-model="registerForm.email"
|
||||||
|
placeholder="请输入邮箱"
|
||||||
|
class="custom-input"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<div class="input-icon">
|
||||||
|
<el-icon><Message /></el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="emailCooldown > 0 || !registerForm.email"
|
||||||
|
@click="sendEmailCode"
|
||||||
|
>
|
||||||
|
{{ emailCooldown > 0 ? `${emailCooldown}s` : '获取验证码' }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="验证码" prop="emailCode">
|
||||||
|
<el-input
|
||||||
|
v-model="registerForm.emailCode"
|
||||||
|
placeholder="请输入邮箱验证码"
|
||||||
|
class="custom-input"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<div class="input-icon">
|
||||||
|
<el-icon><Key /></el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
class="register-button"
|
||||||
|
:loading="loading"
|
||||||
|
@click="handleRegister"
|
||||||
|
>
|
||||||
|
<span class="button-text">注 册</span>
|
||||||
|
<el-icon class="button-icon"><Right /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<div class="login-link">
|
||||||
|
已有账号?
|
||||||
|
<router-link to="/login" class="login-btn">立即登录</router-link>
|
||||||
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -125,7 +181,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { User, Lock, Phone, Message, Platform, Right } from '@element-plus/icons-vue'
|
import { User, Lock, Phone, Message, Platform, Right, Key } from '@element-plus/icons-vue'
|
||||||
import type { FormInstance } from 'element-plus'
|
import type { FormInstance } from 'element-plus'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
@ -138,7 +194,9 @@ const registerForm = reactive({
|
||||||
phone: '',
|
phone: '',
|
||||||
password: '',
|
password: '',
|
||||||
confirmPassword: '',
|
confirmPassword: '',
|
||||||
verifyCode: ''
|
phoneCode: '',
|
||||||
|
email: '',
|
||||||
|
emailCode: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
const validatePass = (rule: any, value: string, callback: any) => {
|
const validatePass = (rule: any, value: string, callback: any) => {
|
||||||
|
@ -151,6 +209,14 @@ const validatePass = (rule: any, value: string, callback: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const validateEmail = (rule: any, value: string, callback: any) => {
|
||||||
|
if (value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
|
||||||
|
callback(new Error('请输入正确的邮箱地址'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
username: [
|
username: [
|
||||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||||
|
@ -168,8 +234,14 @@ const rules = {
|
||||||
{ required: true, message: '请再次输入密码', trigger: 'blur' },
|
{ required: true, message: '请再次输入密码', trigger: 'blur' },
|
||||||
{ validator: validatePass, trigger: 'blur' }
|
{ validator: validatePass, trigger: 'blur' }
|
||||||
],
|
],
|
||||||
verifyCode: [
|
phoneCode: [
|
||||||
{ required: true, message: '请输入验证码', trigger: 'blur' }
|
{ required: true, message: '请输入验证码', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
email: [
|
||||||
|
{ validator: validateEmail, trigger: 'blur' }
|
||||||
|
],
|
||||||
|
emailCode: [
|
||||||
|
{ required: true, message: '请输入邮箱验证码', trigger: 'blur' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,22 +270,45 @@ const handleRegister = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加验证码相关逻辑
|
// 添加验证码相关逻辑
|
||||||
const cooldown = ref(0)
|
const phoneCooldown = ref(0)
|
||||||
const startCooldown = () => {
|
const emailCooldown = ref(0)
|
||||||
cooldown.value = 60
|
|
||||||
|
// 手机验证码倒计时
|
||||||
|
const startPhoneCooldown = () => {
|
||||||
|
phoneCooldown.value = 60
|
||||||
const timer = setInterval(() => {
|
const timer = setInterval(() => {
|
||||||
cooldown.value--
|
phoneCooldown.value--
|
||||||
if (cooldown.value <= 0) {
|
if (phoneCooldown.value <= 0) {
|
||||||
clearInterval(timer)
|
clearInterval(timer)
|
||||||
}
|
}
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendVerifyCode = () => {
|
// 邮箱验证码倒计时
|
||||||
if (cooldown.value > 0) return
|
const startEmailCooldown = () => {
|
||||||
|
emailCooldown.value = 60
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
emailCooldown.value--
|
||||||
|
if (emailCooldown.value <= 0) {
|
||||||
|
clearInterval(timer)
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送手机验证码
|
||||||
|
const sendPhoneCode = () => {
|
||||||
|
if (phoneCooldown.value > 0) return
|
||||||
// 这里添加发送验证码的逻辑
|
// 这里添加发送验证码的逻辑
|
||||||
ElMessage.success('验证码已发送')
|
ElMessage.success('手机验证码已发送')
|
||||||
startCooldown()
|
startPhoneCooldown()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送邮箱验证码
|
||||||
|
const sendEmailCode = () => {
|
||||||
|
if (emailCooldown.value > 0 || !registerForm.email) return
|
||||||
|
// 这里添加发送验证码的逻辑
|
||||||
|
ElMessage.success('邮箱验证码已发送')
|
||||||
|
startEmailCooldown()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -272,7 +367,7 @@ const sendVerifyCode = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.register-card {
|
.register-card {
|
||||||
width: 500px;
|
width: 1100px;
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
background: rgba(255, 255, 255, 0.9);
|
background: rgba(255, 255, 255, 0.9);
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
|
@ -322,11 +417,22 @@ const sendVerifyCode = () => {
|
||||||
.verify-code-input {
|
.verify-code-input {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-code-input .el-input {
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.verify-code-input .el-button {
|
.verify-code-input .el-button {
|
||||||
width: 120px;
|
width: 120px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-section .el-form-item:not(:first-child) .el-input {
|
||||||
|
width: calc(100% - 130px);
|
||||||
|
margin-left: 130px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.register-button {
|
.register-button {
|
||||||
|
@ -348,4 +454,131 @@ const sendVerifyCode = () => {
|
||||||
.login-link a:hover {
|
.login-link a:hover {
|
||||||
color: #66b1ff;
|
color: #66b1ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
text-align: center;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 20px 0;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider::before,
|
||||||
|
.divider::after {
|
||||||
|
content: '';
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
background: #dcdfe6;
|
||||||
|
margin: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-section {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
color: #409EFF;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-title .el-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-code-input {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-code-input .el-input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-code-input .el-button {
|
||||||
|
width: 120px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 优化输入框样式 */
|
||||||
|
.custom-input {
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-input :deep(.el-input__wrapper) {
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
box-shadow: none !important;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-input :deep(.el-input__wrapper:hover) {
|
||||||
|
border-color: #c0c4cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-input :deep(.el-input__wrapper.is-focus) {
|
||||||
|
border-color: #409EFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 优化按钮样式 */
|
||||||
|
.el-button {
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button:not(:disabled):hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-content {
|
||||||
|
display: flex;
|
||||||
|
gap: 30px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.basic-info {
|
||||||
|
flex: 1;
|
||||||
|
padding-right: 30px;
|
||||||
|
border-right: 1px solid #e4e7ed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-info {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式布局 */
|
||||||
|
@media (max-width: 992px) {
|
||||||
|
.register-card {
|
||||||
|
width: 95%;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-content {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.basic-info {
|
||||||
|
padding-right: 0;
|
||||||
|
border-right: none;
|
||||||
|
border-bottom: 1px solid #e4e7ed;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-section .el-form-item:not(:first-child) .el-input {
|
||||||
|
width: 100%;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue