Refine login glass effect and plugin menu icon

This commit is contained in:
jxxghp
2026-06-30 20:23:23 +08:00
parent c848b90599
commit 624b55576d
3 changed files with 16 additions and 17 deletions
+12 -3
View File
@@ -68,9 +68,7 @@ const activeImageIndex = ref(0)
const previousImageIndex = ref<number | null>(null)
const isTransparentTheme = computed(() => globalTheme.name.value === 'transparent')
const isLoginWallpaperRoute = computed(() => !isLogin.value && route.path === LOGIN_WALLPAPER_ROUTE)
const shouldUseTransparentBackgroundTreatment = computed(
() => (Boolean(isLogin.value) && isTransparentTheme.value) || isLoginWallpaperRoute.value,
)
const shouldUseTransparentBackgroundTreatment = computed(() => Boolean(isLogin.value) && isTransparentTheme.value)
const shouldLoadBackgroundImages = computed(
() => isLoginWallpaperRoute.value || (Boolean(isLogin.value) && isTransparentTheme.value),
)
@@ -89,6 +87,7 @@ let backgroundRequestController: AbortController | null = null
let backgroundCrossfadeTimer: number | null = null
let authenticatedStateTimer: number | null = null
// 读取并同步透明主题背景设置到根组件响应式状态。
function applyTransparentBackgroundSettings() {
const settings = applyStoredTransparencySettings()
@@ -96,6 +95,7 @@ function applyTransparentBackgroundSettings() {
transparencyGlassQuality.value = settings.glassQuality
}
// 响应透明主题设置变更事件,刷新背景模糊和玻璃质量。
function handleTransparencySettingsChanged(event: Event) {
const { backgroundBlur, glassQuality } = (event as CustomEvent<TransparencySettings>).detail
@@ -143,6 +143,7 @@ function updateHtmlThemeAttribute(themeName: string) {
syncRootLaunchPalette()
}
// 从本地存储重新同步主题偏好、DOM 主题属性和相关外观配置。
function syncThemePreferenceFromStorage() {
themeValue = localStorage.getItem('theme') || 'auto'
@@ -166,22 +167,26 @@ function syncThemePreferenceFromStorage() {
})
}
// 系统配色变化时,在自动主题模式下刷新当前实际主题。
function handleSystemThemeChange() {
if ((localStorage.getItem('theme') || 'auto') === 'auto') {
syncThemePreferenceFromStorage()
}
}
// 页面重新可见时同步主题,修复后台期间设置被外部修改后的外观漂移。
function handleVisibilityThemeSync() {
if (document.visibilityState === 'visible') {
syncThemePreferenceFromStorage()
}
}
// 页面从缓存或重新聚焦恢复时刷新主题偏好。
function handlePageShowThemeSync() {
syncThemePreferenceFromStorage()
}
// 清理背景图交叉淡入淡出定时器。
function clearBackgroundCrossfadeTimer() {
if (backgroundCrossfadeTimer) {
window.clearTimeout(backgroundCrossfadeTimer)
@@ -189,6 +194,7 @@ function clearBackgroundCrossfadeTimer() {
}
}
// 重置背景图交叉淡入淡出状态。
function resetBackgroundCrossfade() {
clearBackgroundCrossfadeTimer()
previousImageIndex.value = null
@@ -256,6 +262,7 @@ function startBackgroundRotation() {
}
}
// 停止登录页或透明主题背景图加载、重试和轮播。
function stopBackgroundLoading() {
backgroundRequestController?.abort()
backgroundRequestController = null
@@ -269,6 +276,7 @@ function stopBackgroundLoading() {
removeBackgroundTimer('background-rotation')
}
// 初始化登录后的全局设置和用户设置状态。
async function initializeAuthenticatedState() {
if (!isLogin.value) return
@@ -281,6 +289,7 @@ async function initializeAuthenticatedState() {
}
}
// 延迟初始化登录态数据,避开登录成功后的即时路由跳转窗口。
function scheduleAuthenticatedStateInitialization() {
if (authenticatedStateTimer) {
window.clearTimeout(authenticatedStateTimer)
+3 -13
View File
@@ -8,7 +8,6 @@ import logo from '@images/logo.png'
import { bufferToBase64Url, base64UrlToUint8Array, urlBase64ToUint8Array } from '@/@core/utils/navigator'
import { SUPPORTED_LOCALES, SupportedLocale } from '@/types/i18n'
import { getCurrentLocale, setI18nLanguage } from '@/plugins/i18n'
import { useTheme } from 'vuetify'
import { getNavMenus } from '@/router/i18n-menu'
import { buildUserPermissionContext, filterMenusByPermission } from '@/utils/permission'
import type { ApiResponse } from '@/api/types'
@@ -65,14 +64,6 @@ const langMenu = ref(false)
// 当前语言
const currentLocale = ref(getCurrentLocale())
// 当前主题
const vuetifyTheme = useTheme()
// 判断是否为透明主题
const isTransparentTheme = computed(() => {
return vuetifyTheme.name.value === 'transparent'
})
// 可用的语言列表
const locales = Object.values(SUPPORTED_LOCALES)
@@ -279,6 +270,7 @@ interface PassKeyFinishResponse {
wizard: boolean
}
// 执行 PassKey WebAuthn 认证并返回登录完成信息。
async function authenticateWithPassKey(options: PassKeyAuthOptions = {}): Promise<PassKeyFinishResponse> {
const { username, isConditional = false, signal } = options
@@ -734,8 +726,7 @@ onUnmounted(() => {
<!-- 登录表单 -->
<div v-if="!mfaDialog" class="auth-wrapper d-flex align-center justify-center">
<VCard
class="auth-card login-card pa-7 pa-sm-9 w-full h-full login-card--enter"
:class="{ 'glass-effect': !isTransparentTheme }"
class="auth-card login-card glass-effect pa-7 pa-sm-9 w-full h-full login-card--enter"
max-width="24rem"
flat
>
@@ -997,7 +988,6 @@ onUnmounted(() => {
z-index: 3;
border: 1px solid rgba(var(--v-border-color), calc(var(--v-border-opacity) * 0.6));
border-radius: 999px;
backdrop-filter: blur(12px) saturate(140%);
background: rgba(var(--v-theme-surface), 0.6);
inset-block-start: calc(env(safe-area-inset-top, 0px) + 16px);
inset-inline-end: calc(env(safe-area-inset-right, 0px) + 16px);
@@ -1047,7 +1037,7 @@ onUnmounted(() => {
}
}
/* 非透明主题:磨砂玻璃卡片 */
/* 登录卡片自身承载固定磨砂效果,避免跟随透明主题设置变化。 */
.glass-effect {
backdrop-filter: blur(28px) saturate(170%) !important;
background: rgba(var(--v-theme-surface), 0.75) !important;
+1 -1
View File
@@ -115,7 +115,7 @@ export function getNavMenus(t: Composer['t']): NavMenu[] {
},
{
title: t('navItems.pluginManager'),
icon: 'mdi-apps',
icon: 'mdi-puzzle-outline',
to: '/plugins',
header: t('menu.system'),
admin: true,