| | |
| | | <template> |
| | | <div class="login-page"> |
| | | <div class="login-card"> |
| | | <div class="card-header"> |
| | | <div class="logo"> |
| | | <svg-icon icon-class="user" /> |
| | | <div class="login-container"> |
| | | <!-- 左侧品牌区域 --> |
| | | <div class="brand-section"> |
| | | <div class="brand-content"> |
| | | <div class="brand-icon"> |
| | | <el-icon :size="48" color="#fff"><Box /></el-icon> |
| | | </div> |
| | | <h1>客户关系管理系统</h1> |
| | | <p>高效管理客户资源,驱动业务增长</p> |
| | | <h1 class="brand-title">仓储物流管理系统</h1> |
| | | <p class="brand-desc">智能化仓储管理 · 高效物流配送 · 全程可视追踪</p> |
| | | <div class="brand-features"> |
| | | <div class="feature-item"> |
| | | <div class="feature-icon"> |
| | | <el-icon :size="28" color="#fff"><Goods /></el-icon> |
| | | </div> |
| | | <span>库存精准管理</span> |
| | | </div> |
| | | <div class="feature-item"> |
| | | <div class="feature-icon"> |
| | | <el-icon :size="28" color="#fff"><Van /></el-icon> |
| | | </div> |
| | | <span>物流实时追踪</span> |
| | | </div> |
| | | <div class="feature-item"> |
| | | <div class="feature-icon"> |
| | | <el-icon :size="28" color="#fff"><TrendCharts /></el-icon> |
| | | </div> |
| | | <span>数据智能分析</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-form ref="loginRef" :model="loginForm" :rules="loginRules"> |
| | | <el-form-item prop="username"> |
| | | <el-input |
| | | v-model="loginForm.username" |
| | | type="text" |
| | | size="large" |
| | | auto-complete="off" |
| | | placeholder="请输入账号" |
| | | > |
| | | <template #prefix><el-icon><User /></el-icon></template> |
| | | </el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item prop="password"> |
| | | <el-input |
| | | v-model="loginForm.password" |
| | | type="password" |
| | | size="large" |
| | | auto-complete="off" |
| | | placeholder="请输入密码" |
| | | show-password |
| | | @keyup.enter="handleLogin" |
| | | > |
| | | <template #prefix><el-icon><Lock /></el-icon></template> |
| | | </el-input> |
| | | </el-form-item> |
| | | |
| | | <div class="form-options"> |
| | | <el-checkbox v-model="loginForm.rememberMe">记住密码</el-checkbox> |
| | | <router-link v-if="register" :to="'/register'">立即注册</router-link> |
| | | </div> |
| | | |
| | | <el-button |
| | | :loading="loading" |
| | | size="large" |
| | | type="primary" |
| | | class="login-btn" |
| | | @click.prevent="handleLogin" |
| | | > |
| | | <span v-if="!loading">登 录</span> |
| | | <span v-else>登录中...</span> |
| | | </el-button> |
| | | </el-form> |
| | | <div class="brand-decoration"> |
| | | <div class="deco-circle"></div> |
| | | <div class="deco-line"></div> |
| | | <div class="deco-box"></div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="bg-pattern"> |
| | | <div class="pattern-item"></div> |
| | | <div class="pattern-item"></div> |
| | | <div class="pattern-item"></div> |
| | | <!-- 右侧登录区域 --> |
| | | <div class="login-section"> |
| | | <div class="login-box"> |
| | | <div class="login-header"> |
| | | <h2>欢迎登录</h2> |
| | | <p>请使用您的账号密码登录系统</p> |
| | | </div> |
| | | |
| | | <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form"> |
| | | <el-form-item prop="username"> |
| | | <div class="input-label">账号</div> |
| | | <el-input |
| | | v-model="loginForm.username" |
| | | type="text" |
| | | size="large" |
| | | auto-complete="off" |
| | | placeholder="请输入账号" |
| | | > |
| | | <template #prefix> |
| | | <el-icon><User /></el-icon> |
| | | </template> |
| | | </el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item prop="password"> |
| | | <div class="input-label">密码</div> |
| | | <el-input |
| | | v-model="loginForm.password" |
| | | type="password" |
| | | size="large" |
| | | auto-complete="off" |
| | | placeholder="请输入密码" |
| | | show-password |
| | | @keyup.enter="handleLogin" |
| | | > |
| | | <template #prefix> |
| | | <el-icon><Lock /></el-icon> |
| | | </template> |
| | | </el-input> |
| | | </el-form-item> |
| | | |
| | | <div class="form-options"> |
| | | <el-checkbox v-model="loginForm.rememberMe">记住密码</el-checkbox> |
| | | <router-link v-if="register" :to="'/register'">注册账号</router-link> |
| | | </div> |
| | | |
| | | <el-button |
| | | :loading="loading" |
| | | size="large" |
| | | type="primary" |
| | | class="login-btn" |
| | | @click.prevent="handleLogin" |
| | | > |
| | | <span v-if="!loading">登 录</span> |
| | | <span v-else>登录中...</span> |
| | | </el-button> |
| | | </el-form> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .login-page { |
| | | .login-container { |
| | | min-height: 100vh; |
| | | display: flex; |
| | | background: #f8fafc; |
| | | } |
| | | |
| | | // 左侧品牌区域 |
| | | .brand-section { |
| | | flex: 1; |
| | | background: linear-gradient(145deg, var(--el-color-primary-dark-2) 0%, var(--el-color-primary) 50%, var(--el-color-primary-dark-2) 100%); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | background: linear-gradient(135deg, var(--el-color-primary-light-9) 0%, var(--el-color-primary-light-8) 50%, var(--el-color-primary-light-9) 100%); |
| | | position: relative; |
| | | overflow: hidden; |
| | | |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: |
| | | radial-gradient(circle at 20% 80%, var(--el-color-primary-light-5) 0%, transparent 50%), |
| | | radial-gradient(circle at 80% 20%, var(--el-color-primary-light-7) 0%, transparent 50%); |
| | | } |
| | | } |
| | | |
| | | .bg-pattern { |
| | | .brand-content { |
| | | text-align: center; |
| | | color: #fff; |
| | | z-index: 1; |
| | | padding: 40px; |
| | | } |
| | | |
| | | .brand-icon { |
| | | width: 100px; |
| | | height: 100px; |
| | | margin: 0 auto 32px; |
| | | background: rgba(255, 255, 255, 0.1); |
| | | border-radius: 24px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | backdrop-filter: blur(10px); |
| | | border: 1px solid rgba(255, 255, 255, 0.2); |
| | | |
| | | :deep(svg) { |
| | | width: 48px; |
| | | height: 48px; |
| | | color: #fff; |
| | | } |
| | | } |
| | | |
| | | .brand-title { |
| | | font-size: 36px; |
| | | font-weight: 700; |
| | | margin: 0 0 16px; |
| | | letter-spacing: 2px; |
| | | } |
| | | |
| | | .brand-desc { |
| | | font-size: 16px; |
| | | color: rgba(255, 255, 255, 0.7); |
| | | margin: 0 0 48px; |
| | | letter-spacing: 1px; |
| | | } |
| | | |
| | | .brand-features { |
| | | display: flex; |
| | | justify-content: center; |
| | | gap: 48px; |
| | | } |
| | | |
| | | .feature-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 12px; |
| | | |
| | | .feature-icon { |
| | | width: 56px; |
| | | height: 56px; |
| | | background: rgba(255, 255, 255, 0.1); |
| | | border-radius: 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | backdrop-filter: blur(10px); |
| | | border: 1px solid rgba(255, 255, 255, 0.15); |
| | | |
| | | :deep(svg) { |
| | | width: 28px; |
| | | height: 28px; |
| | | color: #fff; |
| | | } |
| | | } |
| | | |
| | | span { |
| | | font-size: 14px; |
| | | color: rgba(255, 255, 255, 0.8); |
| | | } |
| | | } |
| | | |
| | | .brand-decoration { |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | |
| | | bottom: 0; |
| | | pointer-events: none; |
| | | |
| | | .pattern-item { |
| | | .deco-circle { |
| | | position: absolute; |
| | | width: 400px; |
| | | height: 400px; |
| | | border: 1px solid rgba(255, 255, 255, 0.05); |
| | | border-radius: 50%; |
| | | background: linear-gradient(135deg, var(--el-color-primary-light-7), var(--el-color-primary-light-9)); |
| | | } |
| | | |
| | | .pattern-item:nth-child(1) { |
| | | width: 500px; |
| | | height: 500px; |
| | | top: -150px; |
| | | top: -100px; |
| | | right: -100px; |
| | | } |
| | | |
| | | .pattern-item:nth-child(2) { |
| | | width: 350px; |
| | | height: 350px; |
| | | bottom: -100px; |
| | | left: -80px; |
| | | } |
| | | |
| | | .pattern-item:nth-child(3) { |
| | | width: 200px; |
| | | .deco-line { |
| | | position: absolute; |
| | | width: 2px; |
| | | height: 200px; |
| | | top: 40%; |
| | | left: 15%; |
| | | background: linear-gradient(135deg, var(--el-color-primary-light-8), var(--el-color-primary-light-9)); |
| | | background: linear-gradient(to bottom, transparent, rgba(255, 255, 255, 0.1), transparent); |
| | | bottom: 10%; |
| | | left: 20%; |
| | | } |
| | | |
| | | .deco-box { |
| | | position: absolute; |
| | | width: 60px; |
| | | height: 60px; |
| | | border: 1px solid rgba(255, 255, 255, 0.08); |
| | | bottom: 20%; |
| | | right: 15%; |
| | | transform: rotate(15deg); |
| | | } |
| | | } |
| | | |
| | | .login-card { |
| | | width: 420px; |
| | | padding: 48px 40px; |
| | | background: rgba(255, 255, 255, 0.95); |
| | | border-radius: 20px; |
| | | box-shadow: |
| | | 0 4px 6px -1px rgba(0, 0, 0, 0.05), |
| | | 0 10px 15px -3px rgba(0, 0, 0, 0.08), |
| | | 0 20px 25px -5px rgba(0, 0, 0, 0.05); |
| | | backdrop-filter: blur(10px); |
| | | position: relative; |
| | | z-index: 1; |
| | | // 右侧登录区域 |
| | | .login-section { |
| | | width: 480px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | background: #fff; |
| | | box-shadow: -10px 0 40px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .card-header { |
| | | text-align: center; |
| | | margin-bottom: 36px; |
| | | .login-box { |
| | | width: 360px; |
| | | padding: 40px 0; |
| | | } |
| | | |
| | | .logo { |
| | | width: 72px; |
| | | height: 72px; |
| | | margin: 0 auto 20px; |
| | | background: linear-gradient(135deg, var(--el-color-primary) 0%, var(--el-color-primary-light-3) 100%); |
| | | border-radius: 18px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 8px 20px var(--el-color-primary-light-5); |
| | | .login-header { |
| | | margin-bottom: 40px; |
| | | |
| | | :deep(svg) { |
| | | width: 36px; |
| | | height: 36px; |
| | | color: #fff; |
| | | } |
| | | } |
| | | |
| | | h1 { |
| | | font-size: 24px; |
| | | h2 { |
| | | font-size: 28px; |
| | | font-weight: 600; |
| | | color: #1f2937; |
| | | color: #1e293b; |
| | | margin: 0 0 8px; |
| | | } |
| | | |
| | | p { |
| | | font-size: 14px; |
| | | color: #6b7280; |
| | | color: #64748b; |
| | | margin: 0; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-form-item) { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | :deep(.el-input__wrapper) { |
| | | border-radius: 12px; |
| | | box-shadow: 0 0 0 1px #e5e7eb; |
| | | padding: 0 16px; |
| | | height: 48px; |
| | | transition: all 0.2s; |
| | | |
| | | &:hover { |
| | | box-shadow: 0 0 0 1px var(--el-color-primary-light-5); |
| | | .login-form { |
| | | .input-label { |
| | | font-size: 14px; |
| | | color: #374151; |
| | | margin-bottom: 8px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | &:focus-within { |
| | | box-shadow: 0 0 0 2px var(--el-color-primary); |
| | | :deep(.el-form-item) { |
| | | margin-bottom: 24px; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-input__inner) { |
| | | height: 48px; |
| | | font-size: 15px; |
| | | color: #374151; |
| | | :deep(.el-input__wrapper) { |
| | | border-radius: 10px; |
| | | box-shadow: 0 0 0 1px #e2e8f0; |
| | | padding: 0 16px; |
| | | height: 48px; |
| | | transition: all 0.3s; |
| | | background: #f8fafc; |
| | | |
| | | &::placeholder { |
| | | color: #9ca3af; |
| | | &:hover { |
| | | box-shadow: 0 0 0 1px #cbd5e1; |
| | | } |
| | | |
| | | &:focus-within { |
| | | box-shadow: 0 0 0 2px var(--el-color-primary); |
| | | background: #fff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | :deep(.el-input__prefix) { |
| | | color: #9ca3af; |
| | | font-size: 18px; |
| | | :deep(.el-input__inner) { |
| | | height: 48px; |
| | | font-size: 15px; |
| | | color: #1e293b; |
| | | |
| | | &::placeholder { |
| | | color: #94a3b8; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-input__prefix) { |
| | | color: #64748b; |
| | | font-size: 18px; |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | |
| | | .form-options { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin: 8px 0 24px; |
| | | margin: 8px 0 32px; |
| | | |
| | | :deep(.el-checkbox__label) { |
| | | color: #6b7280; |
| | | color: #64748b; |
| | | font-size: 14px; |
| | | } |
| | | |
| | |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | text-decoration: none; |
| | | transition: color 0.2s; |
| | | |
| | | &:hover { |
| | | color: var(--el-color-primary-light-3); |
| | | color: var(--el-color-primary-dark-2); |
| | | } |
| | | } |
| | | } |
| | |
| | | .login-btn { |
| | | width: 100%; |
| | | height: 48px; |
| | | border-radius: 12px; |
| | | border-radius: 10px; |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | background: linear-gradient(135deg, var(--el-color-primary) 0%, var(--el-color-primary-light-3) 100%); |
| | | font-weight: 600; |
| | | letter-spacing: 2px; |
| | | background: linear-gradient(135deg, var(--el-color-primary) 0%, var(--el-color-primary-dark-2) 100%); |
| | | border: none; |
| | | box-shadow: 0 4px 14px var(--el-color-primary-light-5); |
| | | transition: all 0.2s; |
| | | box-shadow: 0 4px 16px var(--el-color-primary-light-5); |
| | | transition: all 0.3s; |
| | | |
| | | &:hover { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 6px 20px var(--el-color-primary-light-4); |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 6px 20px var(--el-color-primary-light-3); |
| | | } |
| | | } |
| | | |
| | | .login-footer { |
| | | margin-top: 48px; |
| | | text-align: center; |
| | | |
| | | p { |
| | | color: #94a3b8; |
| | | font-size: 13px; |
| | | margin: 0; |
| | | } |
| | | } |
| | | |
| | | // 响应式 |
| | | @media (max-width: 992px) { |
| | | .brand-section { |
| | | display: none; |
| | | } |
| | | |
| | | .login-section { |
| | | width: 100%; |
| | | box-shadow: none; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 480px) { |
| | | .login-card { |
| | | .login-box { |
| | | width: 90%; |
| | | padding: 36px 24px; |
| | | padding: 20px 0; |
| | | } |
| | | |
| | | .card-header { |
| | | h1 { |
| | | font-size: 20px; |
| | | .login-header { |
| | | h2 { |
| | | font-size: 24px; |
| | | } |
| | | } |
| | | } |