Files
FlashSaleSystem/flash-sale-frontend/src/pages/user/register.vue
YoVinchen c4582655d9 feat: 删除JSP视图层,完善评价和通知系统,新增拼团模块
- 删除所有 JSP 页面(20个文件),前端完全迁移至 Vue 3 SPA
- 完善评价系统:ReviewDialog 组件、用户评价历史页、评价状态检查API
- 新增通知系统:Notification 实体/仓库/服务/控制器,NotificationCenter 接入真实API
- 新增拼团模块:GroupBuying 全套后端和前端页面
- 修复 review check API 参数双重包装导致请求格式错误
- 修复通知 API 路径缺少 /api 前缀和响应格式处理
- MessageListenerService 集成 NotificationService 创建持久化通知

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 16:40:26 +08:00

209 lines
5.8 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 class="register-page min-h-screen flex items-center justify-center bg-gray-50">
<div class="max-w-md w-full">
<div class="register-panel bg-white p-8">
<!-- Logo -->
<div class="text-center mb-8">
<el-icon :size="48" class="page-mark mb-4">
<Lightning />
</el-icon>
<h1 class="text-2xl font-bold text-gray-900">创建账号</h1>
<p class="text-gray-600 mt-2">加入秒杀系统</p>
</div>
<!-- 注册表单 -->
<el-form
ref="formRef"
:model="registerForm"
:rules="rules"
@submit.prevent
>
<el-form-item prop="username">
<el-input
v-model="registerForm.username"
size="large"
placeholder="请输入用户名"
prefix-icon="User"
clearable
/>
</el-form-item>
<el-form-item prop="email">
<el-input
v-model="registerForm.email"
size="large"
placeholder="请输入邮箱"
prefix-icon="Message"
clearable
/>
</el-form-item>
<el-form-item prop="phone">
<el-input
v-model="registerForm.phone"
size="large"
placeholder="请输入手机号(选填)"
prefix-icon="Phone"
clearable
/>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="registerForm.password"
type="password"
size="large"
placeholder="请输入密码"
prefix-icon="Lock"
show-password
/>
</el-form-item>
<el-form-item prop="confirmPassword">
<el-input
v-model="registerForm.confirmPassword"
type="password"
size="large"
placeholder="请确认密码"
prefix-icon="Lock"
show-password
@keyup.enter="handleRegister"
/>
</el-form-item>
<el-form-item prop="agreement">
<el-checkbox v-model="registerForm.agreement">
我已阅读并同意
<el-link type="primary" :underline="false">用户协议</el-link>
<el-link type="primary" :underline="false">隐私政策</el-link>
</el-checkbox>
</el-form-item>
<el-form-item>
<el-button
type="primary"
size="large"
class="w-full"
:loading="loading"
@click="handleRegister"
>
</el-button>
</el-form-item>
<div class="text-center">
<span class="text-gray-600">已有账号</span>
<router-link to="/login" class="text-primary-500 hover:underline">
立即登录
</router-link>
</div>
</el-form>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElForm } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { useUserStore } from '@/stores/user'
const router = useRouter()
const userStore = useUserStore()
const formRef = ref<FormInstance>()
const loading = ref(false)
const registerForm = reactive({
username: '',
email: '',
phone: '',
password: '',
confirmPassword: '',
agreement: false
})
const validatePassword = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== registerForm.password) {
callback(new Error('两次输入密码不一致'))
} else {
callback()
}
}
const validateAgreement = (rule: any, value: any, callback: any) => {
if (!value) {
callback(new Error('请同意用户协议'))
} else {
callback()
}
}
const rules: FormRules = {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 20, message: '用户名长度在 3 到 20 个字符', trigger: 'blur' },
{ pattern: /^[a-zA-Z0-9_]+$/, message: '用户名只能包含字母、数字和下划线', trigger: 'blur' }
],
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
],
phone: [
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 20, message: '密码长度在 6 到 20 个字符', trigger: 'blur' }
],
confirmPassword: [
{ required: true, validator: validatePassword, trigger: 'blur' }
],
agreement: [
{ required: true, validator: validateAgreement, trigger: 'change' }
]
}
// 注册
const handleRegister = async () => {
if (!formRef.value) return
await formRef.value.validate(async (valid) => {
if (valid) {
loading.value = true
try {
const { confirmPassword, agreement, ...params } = registerForm
const success = await userStore.register(params)
if (success) {
// 注册成功跳转到登录页已在store中处理
}
} finally {
loading.value = false
}
}
})
}
</script>
<style scoped lang="scss">
.register-page {
background: transparent;
}
.page-mark {
color: #171715;
}
.register-panel {
border: 1px solid #d8cebf;
border-radius: 24px;
background: #fffaf2;
box-shadow: 0 14px 34px rgba(23, 22, 20, 0.06);
}
</style>