refactor(frontend): Rework home layout and user interactions

This commit is contained in:
2026-04-22 16:45:00 +08:00
parent 79f255bf6c
commit 59e87faba9
84 changed files with 8299 additions and 2181 deletions
@@ -1,80 +1,155 @@
<template>
<div class="register-page">
<div class="register-container">
<div class="register-header">
<h1 class="logo">HAOVP</h1>
<p class="slogan">创建账号,保存你的观看与创作记录</p>
</div>
<van-form @submit="handleRegister">
<van-cell-group inset>
<van-field
v-model="form.username"
name="username"
label="用户名"
placeholder="请输入用户名"
:rules="[{ required: true, message: '请输入用户名' }]"
/>
<van-field
v-model="form.email"
name="email"
label="邮箱"
placeholder="请输入邮箱"
:rules="[{ required: true, message: '请输入邮箱' }]"
/>
<van-field
v-model="form.phone"
name="phone"
label="手机号"
placeholder="请输入手机号"
/>
<van-field
v-model="form.password"
type="password"
name="password"
label="密码"
placeholder="请输入密码"
:rules="[{ required: true, message: '请输入密码' }, { pattern: /^.{6,}$/, message: '密码至少6位' }]"
/>
<van-field
v-model="form.confirmPassword"
type="password"
name="confirmPassword"
label="确认密码"
placeholder="请再次输入密码"
:rules="[{ required: true, message: '请确认密码' }, { validator: validatePassword, message: '两次密码不一致' }]"
/>
<van-field
v-model="form.captcha"
name="captcha"
label="验证码"
placeholder="请输入验证码"
:rules="[{ required: true, message: '请输入验证码' }]"
>
<template #button>
<van-image :src="captchaImage" fit="contain" class="captcha-btn" @click="refreshCaptcha" />
</template>
</van-field>
</van-cell-group>
<div class="register-actions">
<van-button round block type="primary" native-type="submit" :loading="loading" color="#00a1d6">
注册
</van-button>
<div class="auth-page">
<div class="auth-shell">
<section class="auth-showcase">
<div class="showcase-copy">
<p class="eyebrow">
New Account
</p>
<h1>创建账号,进入你的创作与互动空间</h1>
<p class="lead">
注册成功后可以保存观看记录、创建收藏夹、进入消息中心,并继续使用上传、审核与播放联调后的完整链路。
</p>
</div>
</van-form>
<div class="register-footer">
<router-link to="/login" class="link">已有账号?去登录</router-link>
</div>
<div class="showcase-board">
<div class="board-card">
<strong>保存记录</strong>
<span>同步个人资料、播放历史、收藏夹和消息通知。</span>
</div>
<div class="board-card">
<strong>参与互动</strong>
<span>评论、回复、关注、私信和通知都依赖注册后的个人身份。</span>
</div>
<div class="board-card">
<strong>开始创作</strong>
<span>上传视频并进入个人主页,逐步搭建自己的创作者空间。</span>
</div>
</div>
</section>
<section class="auth-panel">
<div class="panel-top">
<button
class="back-home"
@click="router.push('/')"
>
返回首页
</button>
<div class="brand-lockup">
<h1 class="logo">
HAOVP
</h1>
<p class="slogan">
创建账号,保存你的观看与创作记录
</p>
</div>
</div>
<van-form @submit="handleRegister">
<div class="captcha-banner">
<div>
<strong>注册验证</strong>
<span>当前注册同样要求验证码,点击图片可以刷新。</span>
</div>
<van-image
:src="captchaImage"
fit="contain"
class="captcha-image"
@click="refreshCaptcha"
/>
</div>
<van-cell-group inset>
<van-field
v-model="form.username"
name="username"
label="用户名"
placeholder="请输入用户名"
:rules="[{ required: true, message: '请输入用户名' }]"
/>
<van-field
v-model="form.email"
name="email"
label="邮箱"
placeholder="请输入邮箱"
:rules="[{ required: true, message: '请输入邮箱' }]"
/>
<van-field
v-model="form.phone"
name="phone"
label="手机号"
placeholder="请输入手机号"
/>
<van-field
v-model="form.password"
type="password"
name="password"
label="密码"
placeholder="请输入密码"
:rules="[{ required: true, message: '请输入密码' }, { pattern: /^.{6,}$/, message: '密码至少6位' }]"
/>
<van-field
v-model="form.confirmPassword"
type="password"
name="confirmPassword"
label="确认密码"
placeholder="请再次输入密码"
:rules="[{ required: true, message: '请确认密码' }, { validator: validatePassword, message: '两次密码不一致' }]"
/>
<van-field
v-model="form.captcha"
name="captcha"
label="验证码"
placeholder="请输入验证码"
:rules="[{ required: true, message: '请输入验证码' }]"
>
<template #button>
<van-image
:src="captchaImage"
fit="contain"
class="captcha-btn"
@click="refreshCaptcha"
/>
</template>
</van-field>
</van-cell-group>
<div class="tips-row">
<span>注册成功后将跳转到登录页,请使用刚创建的账号继续登录。</span>
</div>
<div class="register-actions">
<van-button
round
block
type="primary"
native-type="submit"
:loading="loading"
class="submit-btn"
>
注册
</van-button>
</div>
</van-form>
<div class="register-footer">
<router-link
to="/login"
class="link"
>
已有账号?去登录
</router-link>
</div>
</section>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { onMounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { showToast, showSuccessToast } from 'vant'
import { showSuccessToast, showToast } from 'vant'
import { authApi, type CaptchaResult } from '@/api/auth.ts'
const router = useRouter()
@@ -91,9 +166,7 @@ const form = reactive({
captcha: ''
})
const validatePassword = () => {
return form.password === form.confirmPassword
}
const validatePassword = () => form.password === form.confirmPassword
const refreshCaptcha = async () => {
try {
@@ -138,63 +211,235 @@ onMounted(() => {
</script>
<style scoped lang="scss">
.register-page {
.auth-page {
min-height: 100vh;
background:
radial-gradient(circle at top left, rgba(34, 197, 94, 0.22), transparent 28%),
radial-gradient(circle at bottom right, rgba(59, 130, 246, 0.24), transparent 26%),
linear-gradient(135deg, #0b1323 0%, #1d3557 55%, #0f766e 100%);
radial-gradient(circle at 18% 18%, rgba(34, 197, 94, 0.16), transparent 24%),
radial-gradient(circle at 82% 82%, rgba(59, 130, 246, 0.2), transparent 22%),
linear-gradient(135deg, #08111f 0%, #12345b 52%, #0f766e 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
padding: 28px 20px;
}
.register-container {
width: 100%;
max-width: 430px;
background: rgba(255, 255, 255, 0.96);
border-radius: 28px;
padding: 34px 28px 28px;
.auth-shell {
width: min(1180px, 100%);
display: grid;
grid-template-columns: minmax(0, 1.15fr) 460px;
gap: 20px;
}
.auth-showcase,
.auth-panel {
border-radius: 30px;
overflow: hidden;
}
.auth-showcase {
padding: 34px 32px;
color: #fff;
background:
radial-gradient(circle at top right, rgba(255, 255, 255, 0.2), transparent 28%),
linear-gradient(135deg, rgba(15, 23, 42, 0.92), rgba(15, 118, 110, 0.92));
box-shadow: 0 24px 80px rgba(4, 16, 33, 0.34);
display: grid;
align-content: space-between;
}
.register-header {
text-align: center;
margin-bottom: 24px;
.eyebrow {
margin: 0 0 12px;
font-size: 12px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: rgba(255, 255, 255, 0.68);
}
.logo {
font-size: 32px;
font-weight: bold;
color: #00a1d6;
margin: 0;
.showcase-copy {
h1 {
margin: 0 0 12px;
font-size: 40px;
line-height: 1.18;
}
.slogan {
margin-top: 10px;
color: #64748b;
.lead {
margin: 0;
max-width: 620px;
color: rgba(255, 255, 255, 0.82);
line-height: 1.8;
}
}
.showcase-board {
display: grid;
gap: 12px;
margin-top: 28px;
}
.board-card {
padding: 18px 20px;
border-radius: 20px;
background: rgba(255, 255, 255, 0.08);
backdrop-filter: blur(12px);
strong {
display: block;
margin-bottom: 6px;
font-size: 16px;
}
span {
color: rgba(255, 255, 255, 0.76);
font-size: 13px;
line-height: 1.7;
}
}
.auth-panel {
background: rgba(255, 255, 255, 0.96);
padding: 28px 26px 26px;
box-shadow: 0 24px 80px rgba(4, 16, 33, 0.34);
}
.panel-top {
margin-bottom: 22px;
}
.back-home {
border: none;
background: #f8fafc;
color: #475569;
padding: 8px 12px;
border-radius: 999px;
font-size: 12px;
cursor: pointer;
}
.brand-lockup {
margin-top: 16px;
}
.logo {
margin: 0;
font-size: 34px;
font-weight: 800;
color: #00a1d6;
}
.slogan {
margin: 10px 0 0;
color: #64748b;
font-size: 13px;
line-height: 1.7;
}
.captcha-banner {
display: flex;
justify-content: space-between;
gap: 12px;
align-items: center;
margin-bottom: 16px;
padding: 14px 16px;
border-radius: 18px;
background: #f8fafc;
strong {
display: block;
margin-bottom: 4px;
color: #18191c;
font-size: 14px;
}
span {
color: #64748b;
font-size: 12px;
line-height: 1.6;
}
}
.captcha-image,
.captcha-btn {
flex-shrink: 0;
cursor: pointer;
}
.captcha-image {
width: 120px;
height: 40px;
}
.captcha-btn {
width: 100px;
height: 32px;
}
:deep(.van-cell-group--inset) {
margin: 0;
border-radius: 20px;
overflow: hidden;
box-shadow: inset 0 0 0 1px #eef2f7;
}
:deep(.van-field) {
padding: 14px 16px;
}
.tips-row {
margin-top: 12px;
color: #64748b;
font-size: 12px;
}
.register-actions {
margin-top: 20px;
margin-top: 22px;
}
.submit-btn {
:deep(.van-button) {
background: linear-gradient(135deg, #fb7299, #ff8fab);
border: none;
box-shadow: 0 14px 28px rgba(251, 114, 153, 0.24);
}
}
.register-footer {
text-align: center;
margin-top: 20px;
margin-top: 22px;
}
.link {
color: #00a1d6;
font-size: 14px;
text-decoration: none;
.link {
color: #00a1d6;
font-size: 14px;
text-decoration: none;
}
@media (max-width: 960px) {
.auth-shell {
grid-template-columns: 1fr;
}
.auth-showcase {
display: none;
}
}
.captcha-btn {
height: 32px;
cursor: pointer;
@media (max-width: 768px) {
.auth-page {
padding: 16px 12px;
}
.auth-panel {
padding: 22px 18px 20px;
border-radius: 24px;
}
.captcha-banner {
flex-direction: column;
align-items: flex-start;
}
.logo {
font-size: 30px;
}
}
</style>