Files
emall-web/src/views/Register.vue

243 lines
5.7 KiB
Vue
Raw Normal View History

2025-10-16 09:59:34 +08:00
<template>
<div class="register-container">
<!-- 深空背景 -->
<div class="space-background">
<div class="stars" ref="stars"></div>
</div>
<div class="register-content">
<!-- Logo和标题 -->
<div class="logo-section">
<div class="logo">
<div class="time-capsule"></div>
</div>
<h1 class="app-title">加入 ChronoMail</h1>
<p class="app-slogan">开始你的时间之旅</p>
</div>
<!-- 注册表单 -->
<div class="register-form glass-card p-30">
<van-form @submit="onSubmit">
<van-field
v-model="username"
name="username"
placeholder="用户名"
:rules="[{ required: true, message: '请填写用户名' }]"
class="custom-field"
/>
<van-field
v-model="email"
name="email"
placeholder="邮箱"
:rules="[
{ required: true, message: '请填写邮箱' },
{ pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: '请输入正确的邮箱格式' }
]"
class="custom-field"
/>
<van-field
v-model="password"
type="password"
name="password"
placeholder="密码"
:rules="[
{ required: true, message: '请填写密码' },
{ pattern: /^(?=.*[a-zA-Z])(?=.*\d).{6,}$/, message: '密码至少6位包含字母和数字' }
]"
class="custom-field"
/>
<van-field
v-model="confirmPassword"
type="password"
name="confirmPassword"
placeholder="确认密码"
:rules="[
{ required: true, message: '请确认密码' },
{ validator: validatePassword }
]"
class="custom-field"
/>
<div class="form-actions">
<van-button round block type="primary" native-type="submit" class="register-button">
注册
</van-button>
<div class="login-link mt-20">
已有账号<span @click="goToLogin">立即登录</span>
</div>
</div>
</van-form>
</div>
</div>
</div>
</template>
<script>
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { showLoadingToast, showSuccessToast, showFailToast, closeToast } from 'vant'
import { userActions } from '../store'
export default {
name: 'Register',
setup() {
const router = useRouter()
const username = ref('')
const email = ref('')
const password = ref('')
const confirmPassword = ref('')
const stars = ref(null)
// 生成星空背景
const generateStars = () => {
if (!stars.value) return
const starsContainer = stars.value
const starCount = 100
for (let i = 0; i < starCount; i++) {
const star = document.createElement('div')
star.className = 'star'
// 随机位置
const left = Math.random() * 100
const top = Math.random() * 100
// 随机大小
const size = Math.random() * 3 + 1
// 随机动画延迟
const delay = Math.random() * 4
star.style.left = `${left}%`
star.style.top = `${top}%`
star.style.width = `${size}px`
star.style.height = `${size}px`
star.style.animationDelay = `${delay}s`
starsContainer.appendChild(star)
}
}
// 验证密码
const validatePassword = () => {
if (password.value !== confirmPassword.value) {
return '两次输入的密码不一致'
}
return true
}
// 注册处理
const onSubmit = async () => {
try {
showLoadingToast({
message: '注册中...',
forbidClick: true,
})
// 调用API进行注册
await userActions.register({
username: username.value,
email: email.value,
password: password.value
})
closeToast()
showSuccessToast('注册成功')
// 跳转到登录页
router.push('/login')
} catch (error) {
closeToast()
const errorMessage = error.response?.data?.message || '注册失败,请稍后再试'
showFailToast(errorMessage)
}
}
// 跳转到登录页
const goToLogin = () => {
router.push('/login')
}
onMounted(() => {
generateStars()
})
return {
username,
email,
password,
confirmPassword,
stars,
validatePassword,
onSubmit,
goToLogin
}
}
}
</script>
<style scoped>
.register-container {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
.register-content {
width: 90%;
max-width: 400px;
z-index: 1;
}
.logo-section {
text-align: center;
margin-bottom: 40px;
}
.logo {
display: flex;
justify-content: center;
margin-bottom: 20px;
}
.app-title {
font-size: 32px;
font-weight: bold;
margin-bottom: 10px;
background: linear-gradient(135deg, #00D4FF, #ffffff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.app-slogan {
font-size: 16px;
color: var(--text-secondary);
letter-spacing: 1px;
}
.register-form {
margin-top: 20px;
}
.register-button {
height: 50px;
font-size: 16px;
font-weight: bold;
margin-top: 20px;
}
.login-link {
text-align: center;
color: var(--text-secondary);
}
.login-link span {
color: var(--accent-color);
cursor: pointer;
font-weight: bold;
}
</style>