Browse Source

feat(page): add register view with validation

main
Mohan 1 month ago
parent
commit
bfeeb5e1b1
  1. 6
      src/router/index.ts
  2. 2
      src/views/LoginView.vue
  3. 140
      src/views/RegisterView.vue

6
src/router/index.ts

@ -25,6 +25,12 @@ const router = createRouter({
component: () => import('@/views/LoginView.vue'),
meta: { guestOnly: true }
},
{
path: '/register',
name: 'Register',
component: () => import('@/views/RegisterView.vue'),
meta: { guestOnly: true }
},
{
path: '/admin',
component: () => import('@/views/admin/AdminLayout.vue'),

2
src/views/LoginView.vue

@ -43,7 +43,7 @@ async function onSubmit() {
{{ loading ? '登录中...' : '登录' }}
</button>
<p class="register-hint">
还没有账号<router-link to="/login?register=1">去注册</router-link>
还没有账号<router-link to="/register">去注册</router-link>
</p>
</form>
</div>

140
src/views/RegisterView.vue

@ -0,0 +1,140 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
const router = useRouter()
const auth = useAuthStore()
const username = ref('')
const password = ref('')
const confirmPassword = ref('')
const email = ref('')
const loading = ref(false)
const error = ref<string | null>(null)
async function onSubmit() {
const name = username.value.trim()
if (name.length < 3 || name.length > 50) {
error.value = '用户名长度需为 3-50 字符'
return
}
if (password.value.length < 6 || password.value.length > 100) {
error.value = '密码长度需为 6-100 字符'
return
}
if (password.value !== confirmPassword.value) {
error.value = '两次输入的密码不一致'
return
}
loading.value = true
error.value = null
try {
await auth.register({
username: name,
password: password.value,
email: email.value.trim() || undefined
})
router.push('/admin')
} catch (e) {
console.error(e)
error.value = '注册失败,用户名可能已被占用'
} finally {
loading.value = false
}
}
</script>
<template>
<div class="register-wrap">
<form class="register-form" @submit.prevent="onSubmit">
<h1 class="register-title">注册</h1>
<p v-if="error" class="error-text">{{ error }}</p>
<label class="form-label" for="username">用户名</label>
<input id="username" v-model="username" class="form-input" type="text" autocomplete="username" />
<label class="form-label" for="password">密码</label>
<input id="password" v-model="password" class="form-input" type="password" autocomplete="new-password" />
<label class="form-label" for="confirmPassword">确认密码</label>
<input
id="confirmPassword"
v-model="confirmPassword"
class="form-input"
type="password"
autocomplete="new-password"
/>
<label class="form-label" for="email">邮箱可选</label>
<input id="email" v-model="email" class="form-input" type="email" autocomplete="email" />
<button class="register-btn" type="submit" :disabled="loading">
{{ loading ? '注册中...' : '注册' }}
</button>
<p class="login-hint">
已有账号<router-link to="/login">去登录</router-link>
</p>
</form>
</div>
</template>
<style scoped>
.register-wrap {
display: flex;
justify-content: center;
padding-top: 60px;
}
.register-form {
width: 100%;
max-width: 360px;
background: #fff;
border: 1px solid #e5e5ea;
border-radius: 8px;
padding: 28px;
}
.register-title {
text-align: center;
margin: 0 0 20px;
}
.form-label {
display: block;
margin: 14px 0 6px;
font-size: 14px;
color: #5c6470;
}
.form-input {
width: 100%;
padding: 10px 12px;
border: 1px solid #d3d8e0;
border-radius: 6px;
font-size: 14px;
}
.register-btn {
width: 100%;
margin-top: 20px;
padding: 11px;
border: none;
border-radius: 6px;
background: #3b82f6;
color: #fff;
font-size: 15px;
cursor: pointer;
}
.register-btn:disabled {
opacity: 0.6;
}
.login-hint {
text-align: center;
margin-top: 16px;
font-size: 13px;
color: #8a93a3;
}
.error-text {
color: #d33c3c;
font-size: 13px;
}
</style>
Loading…
Cancel
Save