| | |
| | | |
| | | defineOptions({ name: 'Login' }); |
| | | |
| | | // vite.config.ts 注入的公司 Logo 路径 |
| | | declare const __APP_LOGO__: string; |
| | | |
| | | const authStore = useAuthStore(); |
| | | const accessStore = useAccessStore(); |
| | | const tenantEnable = isTenantEnable(); |
| | |
| | | const verifyRef = ref(); |
| | | |
| | | const captchaType = 'blockPuzzle'; // 验证码类型:'blockPuzzle' | 'clickWord' |
| | | |
| | | /** 应用标题(登录页品牌文字) */ |
| | | const appTitle = import.meta.env.VITE_APP_TITLE || '江苏商贸'; |
| | | |
| | | /** 品牌徽标:复用 vite 注入的公司 Logo,缺省回落到内置图标 */ |
| | | const brandLogo = __APP_LOGO__ || '/logos/JSSM.svg'; |
| | | |
| | | /** 获取租户列表 */ |
| | | const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表 |
| | |
| | | { |
| | | component: 'VbenInput', |
| | | componentProps: { |
| | | autocomplete: 'username', |
| | | placeholder: $t('authentication.usernameTip'), |
| | | }, |
| | | hideLabel: false, |
| | | labelWidth: 44, |
| | | fieldName: 'username', |
| | | label: $t('authentication.username'), |
| | | rules: z |
| | |
| | | { |
| | | component: 'VbenInputPassword', |
| | | componentProps: { |
| | | autocomplete: 'current-password', |
| | | placeholder: $t('authentication.passwordTip'), |
| | | }, |
| | | hideLabel: false, |
| | | labelWidth: 44, |
| | | fieldName: 'password', |
| | | label: $t('authentication.password'), |
| | | rules: z |
| | |
| | | |
| | | <template> |
| | | <div class="academic-login-wrapper"> |
| | | <!-- 顶部品牌标识:徽标 + 平台名 + 金色分隔线 --> |
| | | <div class="academic-login-header"> |
| | | <img :alt="appTitle" :src="brandLogo" class="academic-brand-logo" /> |
| | | <h2 class="academic-brand-name">{{ appTitle }}</h2> |
| | | <div class="academic-decoration-line"></div> |
| | | </div> |
| | | |
| | | <AuthenticationLogin |
| | | ref="loginRef" |
| | | :form-schema="formSchema" |
| | |
| | | <!-- 自定义标题:覆盖欢迎语 --> |
| | | <template #title> |
| | | <div class="academic-title-area"> |
| | | <h3 class="academic-title">账号登录</h3> |
| | | <p class="academic-subtitle">{{ $t('authentication.loginSubtitle') }}</p> |
| | | <h2 class="academic-title">账号登录</h2> |
| | | <p class="academic-subtitle">欢迎回来,请使用您的账号登录</p> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | </template> |
| | | |
| | | <style scoped> |
| | | /* ========== 学术科研风格登录页样式 ========== */ |
| | | .academic-login-wrapper { |
| | | @apply relative flex flex-col w-full; |
| | | min-height: 460px; |
| | | } |
| | | |
| | | /* ---- 顶部品牌标识 ---- */ |
| | | .academic-login-header { |
| | | @apply flex flex-col items-center mb-8; |
| | | } |
| | | |
| | | .academic-brand-logo { |
| | | width: 52px; |
| | | height: 52px; |
| | | margin-bottom: 16px; |
| | | filter: drop-shadow(0 3px 10px rgba(15, 36, 64, 0.14)); |
| | | } |
| | | |
| | | .academic-brand-name { |
| | | font-size: 19px; |
| | | font-weight: 600; |
| | | letter-spacing: 5px; |
| | | /* 末字右侧会多出一份字距,用等量缩进抵消,视觉才真正居中 */ |
| | | text-indent: 5px; |
| | | color: #0f2440; |
| | | margin: 0 0 14px; |
| | | } |
| | | |
| | | .academic-decoration-line { |
| | | position: relative; |
| | | width: 58px; |
| | | height: 2px; |
| | | background: linear-gradient( |
| | | 90deg, |
| | | transparent, |
| | | #d4af37 32%, |
| | | #d4af37 68%, |
| | | transparent |
| | | ); |
| | | border-radius: 2px; |
| | | } |
| | | |
| | | /* 金线中央的菱形点缀 */ |
| | | .academic-decoration-line::after { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 50%; |
| | | left: 50%; |
| | | width: 6px; |
| | | height: 6px; |
| | | background: #d4af37; |
| | | border-radius: 1px; |
| | | transform: translate(-50%, -50%) rotate(45deg); |
| | | } |
| | | |
| | | /* ---- 自定义标题 ---- */ |
| | | .academic-title-area { |
| | | @apply text-left mb-6; |
| | | } |
| | | |
| | | .academic-title { |
| | | font-size: 26px; |
| | | font-weight: 600; |
| | | color: #0f2440; |
| | | letter-spacing: 2px; |
| | | margin: 0 0 8px 0; |
| | | line-height: 1.35; |
| | | } |
| | | |
| | | .academic-subtitle { |
| | | font-size: 13.5px; |
| | | color: #8a94a6; |
| | | margin: 0; |
| | | letter-spacing: 0.3px; |
| | | } |
| | | |
| | | /* ---- 覆盖默认标题 ---- */ |
| | | :deep(.academic-login-form .mb-7) { |
| | | display: none; |
| | | } |
| | | |
| | | /* ---- 输入框:暖白底 + 金色聚焦 ---- */ |
| | | :deep(.academic-login-form .vben-input) { |
| | | border-radius: 8px; |
| | | border-color: #e6e2d8; |
| | | background: #fdfcfa; |
| | | transition: all 0.25s ease; |
| | | height: 48px; |
| | | } |
| | | |
| | | :deep(.academic-login-form .vben-input:hover) { |
| | | border-color: #c9b77a; |
| | | } |
| | | |
| | | :deep(.academic-login-form .vben-input:focus-within) { |
| | | border-color: #d4af37; |
| | | background: #fff; |
| | | box-shadow: 0 0 0 3px rgba(212, 175, 55, 0.13); |
| | | } |
| | | |
| | | /* ---- 登录按钮:藏青渐变 + 金色描边与文字 ---- */ |
| | | :deep(.academic-login-form .w-full > button), |
| | | :deep(.academic-login-form button[aria-label="login"]) { |
| | | height: 48px; |
| | | border-radius: 8px; |
| | | background: linear-gradient(135deg, #1e4571, #0f2440) !important; |
| | | border: 1px solid rgba(212, 175, 55, 0.45) !important; |
| | | font-size: 15px; |
| | | font-weight: 600; |
| | | letter-spacing: 6px; |
| | | text-indent: 6px; |
| | | box-shadow: 0 6px 18px rgba(15, 36, 64, 0.22); |
| | | transition: all 0.3s ease; |
| | | color: #f5e7c0 !important; |
| | | } |
| | | |
| | | /* 悬停只加深描边与投影,不做位移,保持克制 */ |
| | | :deep(.academic-login-form .w-full > button:hover), |
| | | :deep(.academic-login-form button[aria-label="login"]:hover) { |
| | | box-shadow: |
| | | 0 8px 22px rgba(15, 36, 64, 0.26), |
| | | 0 0 0 1px rgba(212, 175, 55, 0.6); |
| | | } |
| | | |
| | | :deep(.academic-login-form .w-full > button:active), |
| | | :deep(.academic-login-form button[aria-label="login"]:active) { |
| | | box-shadow: 0 3px 12px rgba(15, 36, 64, 0.24); |
| | | } |
| | | |
| | | /* ---- 记住账号 / 忘记密码 ---- */ |
| | | :deep(.academic-login-form .vben-link) { |
| | | color: #b8901f; |
| | | font-weight: 500; |
| | | transition: color 0.2s; |
| | | } |
| | | |
| | | :deep(.academic-login-form .vben-link:hover) { |
| | | color: #8a6a12; |
| | | } |
| | | |
| | | /* ---- 第三方登录 ---- */ |
| | | .academic-third-party { |
| | | @apply mt-5; |
| | | } |
| | | |
| | | .academic-divider { |
| | | @apply flex items-center gap-3 mb-4; |
| | | } |
| | | |
| | | .academic-divider-line { |
| | | flex: 1; |
| | | height: 1px; |
| | | background: linear-gradient(90deg, transparent, #e2e8f0, transparent); |
| | | } |
| | | |
| | | .academic-divider-text { |
| | | @apply text-xs; |
| | | color: #94a3b8; |
| | | white-space: nowrap; |
| | | letter-spacing: 0.5px; |
| | | } |
| | | |
| | | .academic-wxcp-btn { |
| | | @apply w-full rounded-lg; |
| | | height: 44px; |
| | | border-color: #e6e2d8; |
| | | color: #44546a; |
| | | font-weight: 500; |
| | | transition: all 0.3s; |
| | | } |
| | | |
| | | .academic-wxcp-btn:hover { |
| | | border-color: #d4af37; |
| | | color: #0f2440; |
| | | background: rgba(212, 175, 55, 0.06); |
| | | } |
| | | |
| | | /* ---- 暗色适配 ---- */ |
| | | :root.dark .academic-title { |
| | | color: #f0ead8; |
| | | } |
| | | |
| | | :root.dark .academic-brand-name { |
| | | color: #f0ead8; |
| | | } |
| | | |
| | | :root.dark .academic-subtitle { |
| | | color: #8a94a6; |
| | | } |
| | | |
| | | :root.dark .academic-decoration-line { |
| | | background: linear-gradient(90deg, #8bb4f0, #4a7ad4); |
| | | } |
| | | |
| | | :root.dark .academic-footer-text { |
| | | color: #64748b; |
| | | } |
| | | .academic-login-wrapper { width: 100%; } |
| | | .academic-title-area { margin-bottom: 28px; } |
| | | .academic-title { margin: 0 0 10px; color: #18365a; font-size: 26px; font-weight: 750; line-height: 1.4; } |
| | | .academic-subtitle { margin: 0; color: #5c7187; font-size: 13px; line-height: 1.7; } |
| | | :deep(.academic-login-form label) { color: #294d70; font-size: 13px; font-weight: 600; } |
| | | :deep(.academic-login-form input:not([type=checkbox])) { min-height: 46px; border-radius: 6px; border-color: #d6e1ec; background: #f8fbfe; color: #18365a; font-size: 14px; } |
| | | :deep(.academic-login-form input::placeholder) { color: #5c7187; } |
| | | :deep(.academic-login-form input:focus-visible) { border-color: #3476b5; outline-color: #3476b5; background: #fff; } |
| | | :deep(.academic-login-form button[aria-label=login]) { height: 46px; border: 0; border-radius: 6px; color: #fff; background: #b7242d; font-size: 15px; font-weight: 650; letter-spacing: .16em; box-shadow: 0 4px 12px rgb(150 30 40 / 12%); } |
| | | :deep(.academic-login-form button[aria-label=login]:hover) { background: #9f1d27; } |
| | | :deep(.academic-login-form button[aria-label=login]:disabled) { opacity: .65; cursor: wait; } |
| | | :deep(.academic-login-form .vben-link) { color: #28659d; } |
| | | .academic-third-party { margin-top: 24px; } |
| | | .academic-divider { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; } |
| | | .academic-divider-line { height: 1px; flex: 1; background: #e4ecf3; } |
| | | .academic-divider-text { color: #5c7187; font-size: 12px; white-space: nowrap; } |
| | | .academic-wxcp-btn { width: 100%; height: 44px; border: 1px solid #d8e4ee; border-radius: 6px; color: #315777; background: #fff; font-size: 13px; } |
| | | .academic-wxcp-btn:hover { border-color: #8cb5d5; background: #f3f8fc; } |
| | | :deep(button:focus-visible) { outline: 2px solid #2c70b2; outline-offset: 3px; } |
| | | </style> |