From 6d96c5b94747235af9ed57f9f3bc7b9a63cb3071 Mon Sep 17 00:00:00 2001 From: gaoziman <2942894660@qq.com> Date: Thu, 6 Nov 2025 00:42:53 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E7=99=BB=E5=BD=95=E9=A1=B5):=20=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E8=AE=BE=E8=AE=A1=E7=99=BB=E5=BD=95=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 采用居中卡片布局设计 - 左侧展示品牌区域和认证动画 - 右侧提供登录表单 - 使用灰白色背景提升视觉体验 - 添加响应式设计支持移动端 - 优化表单交互和动画效果 --- src/pages/login/form.tsx | 53 +-- src/pages/login/index.tsx | 58 ++- src/pages/login/style/index.module.less | 552 ++++++++++++++++++++---- 3 files changed, 537 insertions(+), 126 deletions(-) diff --git a/src/pages/login/form.tsx b/src/pages/login/form.tsx index 3ff0f1a..27319c4 100644 --- a/src/pages/login/form.tsx +++ b/src/pages/login/form.tsx @@ -5,6 +5,7 @@ import { Link, Button, Space, + Message, } from '@arco-design/web-react'; import { FormInstance } from '@arco-design/web-react/es/Form'; import { IconLock, IconUser } from '@arco-design/web-react/icon'; @@ -75,11 +76,12 @@ export default function LoginForm() { return (
-
{t['login.form.title']}
-
- {t['login.form.title']} -
-
{errorMessage}
+
账号登录
+ + {errorMessage && ( +
{errorMessage}
+ )} +
} placeholder={t['login.form.userName.placeholder']} onPressEnter={onSubmitClick} + size="large" /> + } placeholder={t['login.form.password.placeholder']} onPressEnter={onSubmitClick} + size="large" /> - -
- - {t['login.form.rememberPassword']} - - {t['login.form.forgetPassword']} -
- - -
+ +
+ + {t['login.form.rememberPassword']} + + {t['login.form.forgetPassword']} +
+ +
); diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index b959ceb..894314c 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -1,8 +1,5 @@ import React, { useEffect } from 'react'; -import Footer from '@/components/Footer'; -import Logo from '@/assets/logo.svg'; import LoginForm from './form'; -import LoginBanner from './banner'; import styles from './style/index.module.less'; function Login() { @@ -12,26 +9,53 @@ function Login() { return (
-
- -
Arco Design Pro
-
-
-
- +
+ {/* 左侧插画区域 */} +
+
+ {/* Logo */} +
+ Coder Admin +
+ + {/* 插画区域 */} +
+
+ {/* 认证卡片 */} +
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* 人物剪影 */} +
+
+
+
-
-
-
- -
-
-
); } + Login.displayName = 'LoginPage'; export default Login; diff --git a/src/pages/login/style/index.module.less b/src/pages/login/style/index.module.less index 6176224..8f0880a 100644 --- a/src/pages/login/style/index.module.less +++ b/src/pages/login/style/index.module.less @@ -1,120 +1,504 @@ +// 登录页面容器 .container { display: flex; - height: 100vh; - - .banner { - width: 550px; - background: linear-gradient(163.85deg, #1d2129 0%, #00308f 100%); - } - - .content { - flex: 1; - position: relative; - padding-bottom: 40px; - } - - .footer { - width: 100%; - position: absolute; - bottom: 0; - right: 0; - } + align-items: center; + justify-content: center; + width: 100%; + min-height: 100vh; + background: #f0f2f5; + padding: 40px 20px; + position: relative; + overflow: hidden; } -.logo { - position: fixed; - top: 24px; - left: 22px; - display: inline-flex; - align-items: center; +// 登录卡片包装器 +.login-card-wrapper { + display: flex; + background: #fff; + border-radius: 16px; + box-shadow: 0 20px 60px rgba(0, 0, 0, 30%); + overflow: hidden; + max-width: 1000px; + width: 100%; + position: relative; z-index: 1; - - &-text { - margin-left: 4px; - margin-right: 4px; - font-size: 20px; - color: var(--color-fill-1); - } + animation: fade-in-up 0.6s ease-out; } +// 左侧插画区域 .banner { + flex: 0 0 500px; display: flex; - justify-content: center; align-items: center; + justify-content: center; + background: linear-gradient(135deg, #6b8aff 0%, #5470ff 100%); + position: relative; + overflow: hidden; + padding: 60px 40px; +} - &-inner { - height: 100%; - flex: 1; +.banner-inner { + width: 100%; + position: relative; + z-index: 2; +} + +// Logo 区域 +.logo { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 40px; + + .logo-text { + font-size: 24px; + font-weight: 600; + color: #fff; + letter-spacing: 1px; } } -.content { +// 插画区域 +.illustration-wrapper { display: flex; - justify-content: center; align-items: center; + justify-content: center; + min-height: 400px; } -.carousel { - height: 100%; +.illustration { + position: relative; + width: 100%; + max-width: 400px; + display: flex; + flex-direction: column; + align-items: center; + gap: 40px; +} - &-item { +// 认证卡片 +.auth-card { + width: 200px; + height: 260px; + background: rgba(255, 255, 255, 95%); + border-radius: 16px; + padding: 20px; + box-shadow: 0 20px 60px rgba(0, 0, 0, 15%); + position: relative; + animation: float 3s ease-in-out infinite; + + &-header { + position: relative; + height: 60px; + border-radius: 8px; + background: linear-gradient(135deg, #e8eeff 0%, #f5f7ff 100%); + overflow: hidden; + margin-bottom: 16px; + + .scan-line { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, transparent, #5470ff, transparent); + animation: scan 2s linear infinite; + } + } + + &-avatar { + display: flex; + justify-content: center; + margin-bottom: 16px; + + .avatar-circle { + width: 80px; + height: 80px; + border-radius: 50%; + background: linear-gradient(135deg, #6b8aff 0%, #5470ff 100%); + border: 4px solid rgba(84, 112, 255, 20%); + box-shadow: 0 4px 12px rgba(84, 112, 255, 30%); + } + } + + &-info { display: flex; flex-direction: column; - justify-content: center; + gap: 8px; + + .info-line { + height: 12px; + background: #e8eeff; + border-radius: 6px; + } + + .info-line-short { + height: 12px; + width: 60%; + background: #e8eeff; + border-radius: 6px; + } + } + + .check-icon { + position: absolute; + top: -12px; + right: -12px; + width: 40px; + height: 40px; + border-radius: 50%; + background: linear-gradient(135deg, #52c41a 0%, #389e0d 100%); + color: #fff; + display: flex; align-items: center; - height: 100%; + justify-content: center; + font-size: 24px; + font-weight: bold; + box-shadow: 0 4px 12px rgba(82, 196, 26, 40%); + animation: check-pulse 2s ease-in-out infinite; + } +} + +// 人物剪影 +.person-silhouette { + width: 120px; + height: 140px; + background: rgba(255, 255, 255, 30%); + border-radius: 60px 60px 80px 80px; + position: relative; + animation: float 3s ease-in-out infinite reverse; + + &::before { + content: ''; + position: absolute; + top: 20px; + left: 50%; + transform: translateX(-50%); + width: 50px; + height: 50px; + border-radius: 50%; + background: rgba(255, 255, 255, 50%); } - &-title { - font-weight: 500; - font-size: 20px; - line-height: 28px; - color: var(--color-fill-1); + &::after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%); + width: 60px; + height: 8px; + border-radius: 50%; + background: rgba(0, 0, 0, 10%); + filter: blur(4px); } +} - &-sub-title { - margin-top: 8px; - font-size: 14px; - line-height: 22px; - color: var(--color-text-3); - } +// 右侧表单区域 +.content { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 60px 50px; + background: #fff; + position: relative; +} - &-image { - margin-top: 30px; - width: 320px; - } +.content-wrapper { + width: 100%; + max-width: 400px; +} + +// 登录表单 +.login-form-wrapper { + width: 100%; +} + +.login-form-title { + font-size: 24px; + font-weight: 600; + color: #1d2129; + margin-bottom: 32px; + text-align: center; +} + +.login-form-error-msg { + padding: 12px 16px; + background: #ffece8; + border: 1px solid #ffccc7; + border-radius: 8px; + color: #f53f3f; + font-size: 14px; + margin-bottom: 20px; + animation: shake 0.5s ease; } .login-form { - &-wrapper { - width: 320px; - } + :global { + .arco-form-item { + margin-bottom: 20px; + } - &-title { - font-size: 24px; - font-weight: 500; - color: var(--color-text-1); - line-height: 32px; - } + .arco-input-wrapper, + .arco-input-password { + border-radius: 8px; + height: 44px; + transition: all 0.3s ease; - &-sub-title { - font-size: 16px; - line-height: 24px; - color: var(--color-text-3); - } + &:hover { + border-color: #5470ff; + } + } - &-error-msg { - height: 32px; - line-height: 32px; - color: rgb(var(--red-6)); - } + .arco-input-wrapper.arco-input-focus, + .arco-input-password.arco-input-focus { + border-color: #5470ff; + box-shadow: 0 0 0 2px rgba(84, 112, 255, 10%); + } - &-password-actions { - display: flex; - justify-content: space-between; - } - - &-register-btn { - color: var(--color-text-3) !important; + .arco-input { + height: 44px; + font-size: 14px; + } + } +} + +.login-form-actions { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 24px; + + :global { + .arco-checkbox-text { + color: #4e5969; + font-size: 14px; + } + + .arco-link { + color: #5470ff; + font-size: 14px; + + &:hover { + color: #6b8aff; + } + } + } +} + +.login-btn { + height: 44px; + font-size: 16px; + font-weight: 500; + background: linear-gradient(135deg, #5470ff 0%, #6b8aff 100%); + border: none; + border-radius: 8px; + transition: all 0.3s ease; + + &:hover { + transform: translateY(-2px); + box-shadow: 0 6px 16px rgba(84, 112, 255, 40%); + background: linear-gradient(135deg, #6b8aff 0%, #7d9aff 100%); + } + + &:active { + transform: translateY(0); + } + + &:global(.arco-btn-primary):not(:global(.arco-btn-disabled)) { + background: linear-gradient(135deg, #5470ff 0%, #6b8aff 100%); + + &:hover { + background: linear-gradient(135deg, #6b8aff 0%, #7d9aff 100%); + } + } +} + +// 底部版权 +.footer { + margin-top: 40px; + text-align: center; + font-size: 12px; + color: #86909c; +} + +// 动画定义 +@keyframes float { + 0%, + 100% { + transform: translateY(0); + } + + 50% { + transform: translateY(-20px); + } +} + +@keyframes scan { + 0% { + transform: translateY(0); + } + + 100% { + transform: translateY(60px); + } +} + +@keyframes check-pulse { + 0%, + 100% { + transform: scale(1); + box-shadow: 0 4px 12px rgba(82, 196, 26, 40%); + } + + 50% { + transform: scale(1.1); + box-shadow: 0 4px 20px rgba(82, 196, 26, 60%); + } +} + +@keyframes rotate { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +@keyframes fade-in-up { + from { + opacity: 0; + transform: translateY(30px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes shake { + 0%, + 100% { + transform: translateX(0); + } + + 10%, + 30%, + 50%, + 70%, + 90% { + transform: translateX(-5px); + } + + 20%, + 40%, + 60%, + 80% { + transform: translateX(5px); + } +} + +// 响应式设计 +@media (max-width: 1024px) { + .login-card-wrapper { + flex-direction: column; + max-width: 500px; + } + + .banner { + flex: 0 0 auto; + padding: 40px 30px; + } + + .illustration-wrapper { + min-height: auto; + } + + .auth-card { + width: 150px; + height: 200px; + padding: 15px; + + &-header { + height: 40px; + } + + &-avatar { + margin-bottom: 12px; + + .avatar-circle { + width: 60px; + height: 60px; + } + } + + .check-icon { + width: 32px; + height: 32px; + font-size: 18px; + } + } + + .person-silhouette { + width: 80px; + height: 100px; + + &::before { + width: 35px; + height: 35px; + } + } + + .content { + padding: 40px 30px; + } +} + +@media (max-width: 768px) { + .container { + padding: 20px; + } + + .login-card-wrapper { + max-width: 100%; + } + + .banner { + padding: 30px 20px; + } + + .logo { + margin-bottom: 30px; + + .logo-text { + font-size: 20px; + } + } + + .illustration-wrapper { + min-height: 250px; + } + + .auth-card { + width: 120px; + height: 160px; + } + + .person-silhouette { + width: 60px; + height: 80px; + } + + .content { + padding: 30px 20px; + } + + .login-form-title { + font-size: 20px; } }