feat: 优化登录页面和认证布局设计
- 重构认证页面布局,优化视觉效果和用户体验 - 更新登录页面UI组件和交互逻辑 - 新增原始认证布局备份文件 - 导出登录插图组件供使用
This commit is contained in:
26
apps/web-antd/src/layouts/auth-original.vue
Normal file
26
apps/web-antd/src/layouts/auth-original.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { AuthPageLayout } from '@vben/layouts';
|
||||
import { preferences } from '@vben/preferences';
|
||||
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const appName = computed(() => preferences.app.name);
|
||||
const logo = computed(() => preferences.logo.source);
|
||||
const logoDark = computed(() => preferences.logo.sourceDark);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthPageLayout
|
||||
:app-name="appName"
|
||||
:logo="logo"
|
||||
:logo-dark="logoDark"
|
||||
:page-description="$t('authentication.pageDesc')"
|
||||
:page-title="$t('authentication.pageTitle')"
|
||||
>
|
||||
<!-- 自定义工具栏 -->
|
||||
<!-- <template #toolbar></template> -->
|
||||
</AuthPageLayout>
|
||||
</template>
|
||||
|
||||
@@ -1,25 +1,174 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { AuthPageLayout } from '@vben/layouts';
|
||||
import { preferences } from '@vben/preferences';
|
||||
|
||||
import { $t } from '#/locales';
|
||||
import {
|
||||
LanguageToggle,
|
||||
LoginIllustration,
|
||||
ThemeToggle,
|
||||
} from '@vben/layouts';
|
||||
import { preferences, usePreferences } from '@vben/preferences';
|
||||
|
||||
const appName = computed(() => preferences.app.name);
|
||||
const logo = computed(() => preferences.logo.source);
|
||||
const logoDark = computed(() => preferences.logo.sourceDark);
|
||||
const { isDark } = usePreferences();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthPageLayout
|
||||
:app-name="appName"
|
||||
:logo="logo"
|
||||
:logo-dark="logoDark"
|
||||
:page-description="$t('authentication.pageDesc')"
|
||||
:page-title="$t('authentication.pageTitle')"
|
||||
<div
|
||||
:class="[isDark ? 'dark' : '']"
|
||||
class="relative flex h-screen w-full overflow-hidden font-sans"
|
||||
>
|
||||
<!-- 自定义工具栏 -->
|
||||
<!-- <template #toolbar></template> -->
|
||||
</AuthPageLayout>
|
||||
<!-- 橙色渐变背景 + SVG 贴图预留 -->
|
||||
<div class="absolute inset-0 z-0 size-full">
|
||||
<!-- 橙色渐变背景 - 从左到右依次变淡 -->
|
||||
<div
|
||||
class="absolute inset-0 size-full bg-gradient-to-r from-[rgb(218,125,68)] via-[#FFA00A]/30 to-[#FFA00A]/8 dark:from-[rgb(218,125,68)] dark:via-[#FFA00A]/40 dark:to-[#FFA00A]/12"
|
||||
>
|
||||
<!-- 浮动插图 - 左侧区域 -->
|
||||
<div
|
||||
class="absolute -left-[5%] top-1/2 hidden h-[48rem] w-[65%] -translate-y-1/2 lg:block"
|
||||
>
|
||||
<LoginIllustration :alt="appName" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 左上角品牌标识 -->
|
||||
<div
|
||||
class="absolute left-4 top-4 z-20 flex items-center gap-3 lg:left-6 lg:top-6"
|
||||
@click.prevent
|
||||
>
|
||||
<div class="flex size-12 items-center justify-center lg:size-14">
|
||||
<img v-if="logo" :src="logo" :alt="appName" class="size-8 lg:size-10" />
|
||||
<span v-else class="text-xl text-[#FFA00A] lg:text-2xl">💡</span>
|
||||
</div>
|
||||
<span
|
||||
class="relative top-[1px] text-xl font-semibold tracking-tight text-white drop-shadow-[0_2px_4px_rgba(0,0,0,0.3)] lg:top-[2px] lg:text-2xl"
|
||||
>
|
||||
{{ appName }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 右上角 Toolbar -->
|
||||
<div
|
||||
class="bg-accent absolute right-2 top-4 z-20 flex items-center gap-1 rounded-3xl px-3 py-1 lg:right-6 lg:top-6"
|
||||
>
|
||||
<LanguageToggle v-if="preferences.widget.languageToggle" />
|
||||
<ThemeToggle v-if="preferences.widget.themeToggle" />
|
||||
</div>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div
|
||||
class="relative z-10 flex w-full flex-1 items-center justify-center px-6 py-5 lg:justify-end lg:px-12"
|
||||
>
|
||||
<!-- 登录卡片 - 响应式居中/靠右 -->
|
||||
<div class="w-full md:w-[480px] lg:mr-[10%]">
|
||||
<div
|
||||
class="bg-background relative overflow-hidden rounded-[2.5rem] p-8 shadow-[0_30px_60px_-15px_rgba(255,160,10,0.2)] dark:shadow-[0_30px_60px_-15px_rgba(255,160,10,0.3)]"
|
||||
>
|
||||
<!-- 登录表单 - RouterView 渲染实际的登录组件 -->
|
||||
<div class="login-form-container">
|
||||
<RouterView v-slot="{ Component, route }">
|
||||
<Transition appear mode="out-in" name="fade">
|
||||
<KeepAlive :include="['Login']">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</KeepAlive>
|
||||
</Transition>
|
||||
</RouterView>
|
||||
</div>
|
||||
|
||||
<!-- 遇到问题 -->
|
||||
<div class="mt-6 text-center">
|
||||
<span class="text-muted-foreground text-xs">
|
||||
{{ $t('authentication.contactSupport') }}
|
||||
<a
|
||||
href="#"
|
||||
class="ml-1 font-bold text-[#FFA00A] hover:underline"
|
||||
@click.prevent
|
||||
>
|
||||
{{ $t('authentication.support') }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* 登录表单容器样式覆盖 */
|
||||
:deep(.login-form-container) {
|
||||
/* 标题靠左对齐 */
|
||||
.mb-7,
|
||||
.mb-7 h2,
|
||||
.mb-7 p {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
/* 输入框样式 */
|
||||
.vben-input,
|
||||
.vben-input-password input {
|
||||
@apply rounded-2xl border-slate-100 bg-slate-50 px-6 py-4 text-sm transition-all;
|
||||
@apply focus:border-[#FFA00A]/30 focus:bg-white focus:ring-4 focus:ring-[#FFA00A]/10;
|
||||
}
|
||||
|
||||
/* 深色模式输入框 */
|
||||
.dark .vben-input,
|
||||
.dark .vben-input-password input {
|
||||
@apply border-slate-700 bg-slate-800;
|
||||
@apply focus:border-[#FFA00A]/50 focus:bg-slate-900 focus:ring-[#FFA00A]/20;
|
||||
}
|
||||
|
||||
/* 选择框样式 */
|
||||
.vben-select .vben-input {
|
||||
@apply rounded-2xl border-slate-100 bg-slate-50 px-6 py-4 text-sm;
|
||||
}
|
||||
|
||||
.dark .vben-select .vben-input {
|
||||
@apply border-slate-700 bg-slate-800;
|
||||
}
|
||||
|
||||
/* 登录按钮样式 */
|
||||
.vben-button[aria-label='login'] {
|
||||
@apply w-full rounded-2xl bg-[#FFA00A] py-4 text-base font-bold tracking-wide text-white shadow-lg shadow-[#FFA00A]/30;
|
||||
@apply transition-all hover:-translate-y-1 hover:bg-[#ff8c00] active:translate-y-0;
|
||||
}
|
||||
|
||||
.dark .vben-button[aria-label='login'] {
|
||||
@apply shadow-[#FFA00A]/40;
|
||||
}
|
||||
|
||||
/* 记住我和忘记密码 */
|
||||
.vben-checkbox label {
|
||||
@apply text-xs text-slate-400 dark:text-slate-500;
|
||||
}
|
||||
|
||||
.vben-link {
|
||||
@apply text-xs text-slate-400 transition-colors hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-400;
|
||||
}
|
||||
}
|
||||
|
||||
/* 过渡动画 - 快速响应 */
|
||||
.fade-enter-active {
|
||||
transition:
|
||||
opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.fade-leave-active {
|
||||
transition:
|
||||
opacity 0.15s cubic-bezier(0.4, 0, 1, 1),
|
||||
transform 0.15s cubic-bezier(0.4, 0, 1, 1);
|
||||
}
|
||||
|
||||
.fade-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -170,17 +170,97 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="custom-login-wrapper">
|
||||
<AuthenticationLogin
|
||||
ref="loginRef"
|
||||
:form-schema="formSchema"
|
||||
:loading="authStore.loginLoading"
|
||||
:show-code-login="false"
|
||||
:show-qrcode-login="false"
|
||||
@submit="handleLogin"
|
||||
@third-login="handleThirdLogin"
|
||||
/>
|
||||
|
||||
<!-- 自定义其他登录方式 -->
|
||||
<div class="mt-8">
|
||||
<div class="relative mb-6 flex justify-center text-xs text-slate-400">
|
||||
<span
|
||||
class="bg-background dark:bg-slate-900 relative z-10 px-3 font-medium"
|
||||
>
|
||||
{{ $t('authentication.otherLoginMethods') }}
|
||||
</span>
|
||||
<div class="absolute inset-0 flex items-center">
|
||||
<div class="w-full border-t border-slate-100 dark:border-slate-700"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center gap-8">
|
||||
<!-- 手机登录 -->
|
||||
<button
|
||||
class="flex size-12 items-center justify-center rounded-2xl border border-slate-100 bg-slate-50 text-xl text-slate-400 transition-all hover:scale-110 hover:bg-white hover:text-slate-600 hover:shadow-md dark:border-slate-700 dark:bg-slate-800 dark:hover:bg-slate-700"
|
||||
title="手机登录"
|
||||
type="button"
|
||||
@click="$router.push('/auth/code-login')"
|
||||
>
|
||||
<svg
|
||||
class="size-5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<rect height="18" rx="2" width="11" x="6.5" y="3" />
|
||||
<path d="M12 18h.01" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- 二维码登录 -->
|
||||
<button
|
||||
class="flex size-12 items-center justify-center rounded-2xl border border-slate-100 bg-slate-50 text-xl text-slate-400 transition-all hover:scale-110 hover:bg-white hover:text-slate-600 hover:shadow-md dark:border-slate-700 dark:bg-slate-800 dark:hover:bg-slate-700"
|
||||
title="二维码登录"
|
||||
type="button"
|
||||
@click="$router.push('/auth/qrcode-login')"
|
||||
>
|
||||
<svg
|
||||
class="size-6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<rect x="3" y="3" width="7" height="7" rx="1" />
|
||||
<rect x="14" y="3" width="7" height="7" rx="1" />
|
||||
<rect x="3" y="14" width="7" height="7" rx="1" />
|
||||
<path d="M14 17h7" />
|
||||
<path d="M17 14v7" />
|
||||
<circle cx="6.5" cy="6.5" r="1" fill="currentColor" />
|
||||
<circle cx="17.5" cy="6.5" r="1" fill="currentColor" />
|
||||
<circle cx="6.5" cy="17.5" r="1" fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- 微信扫码登录 -->
|
||||
<!-- <button
|
||||
class="flex size-12 items-center justify-center rounded-2xl border border-slate-100 bg-slate-50 text-xl text-slate-400 transition-all hover:scale-110 hover:bg-white hover:text-[#46AF35] hover:shadow-md dark:border-slate-700 dark:bg-slate-800 dark:hover:bg-slate-700"
|
||||
title="微信扫码登录"
|
||||
type="button"
|
||||
@click="handleThirdLogin(30)"
|
||||
>
|
||||
<svg
|
||||
class="size-6"
|
||||
viewBox="0 0 1024 1024"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M712.149333 352.234667c5.184 0 10.282667 0.064 15.381334 0.341333-26.944-146.837333-178.602667-259.2-361.642667-259.2-202.090667 0-365.888 137.002667-365.888 306.005333 0 99.093333 56.298667 187.178667 143.637333 243.093334l3.349334 2.133333-35.349334 110.72 132.266667-67.370667 6.229333 1.792a431.296 431.296 0 0 0 140.330667 14.848 237.141333 237.141333 0 0 1-11.626667-73.002666c0.021333-154.282667 149.290667-279.36 333.312-279.36z m-218.901333-107.968c28.373333 0 51.349333 22.250667 51.349333 49.728 0 27.456-22.976 49.770667-51.349333 49.770666-28.416 0-51.370667-22.293333-51.370667-49.770666-0.021333-27.498667 22.954667-49.728 51.370667-49.728z m-254.677333 99.477333c-28.394667 0-51.370667-22.293333-51.370667-49.770667 0-27.477333 22.997333-49.728 51.370667-49.728 28.394667 0 51.434667 22.250667 51.434666 49.728s-23.04 49.770667-51.434666 49.770667z" />
|
||||
<path d="M405.76 633.408c0 142.805333 138.453333 258.56 309.162667 258.56a363.392 363.392 0 0 0 103.04-14.762667l111.701333 56.96-29.866667-93.589333 2.816-1.792c73.770667-47.232 121.344-121.621333 121.344-205.397333 0-142.741333-138.389333-258.496-309.056-258.496-170.688 0.042667-309.141333 115.776-309.141333 258.517333z m373.312-89.045333c0-23.168 19.413333-41.962667 43.370667-41.962667 24.021333 0 43.413333 18.816 43.413333 41.962667 0 23.253333-19.413333 42.090667-43.413333 42.090666-23.957333 0-43.370667-18.858667-43.370667-42.090666z m-215.146667 0c0-23.168 19.456-41.962667 43.413334-41.962667 23.978667 0 43.413333 18.816 43.413333 41.962667 0 23.253333-19.434667 42.090667-43.413333 42.090666-23.957333 0-43.413333-18.858667-43.413334-42.090666z" />
|
||||
</svg>
|
||||
</button> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Verification
|
||||
ref="verifyRef"
|
||||
v-if="captchaEnable"
|
||||
ref="verifyRef"
|
||||
:captcha-type="captchaType"
|
||||
:check-captcha-api="checkCaptcha"
|
||||
:get-captcha-api="getCaptcha"
|
||||
@@ -190,3 +270,10 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* 确保表单容器宽度 */
|
||||
.custom-login-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export { default as AuthPageLayout } from './authentication.vue';
|
||||
export { default as LoginIllustration } from './icons/login-illustration.vue';
|
||||
export * from './types';
|
||||
|
||||
Reference in New Issue
Block a user