mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 07:28:37 +08:00
fix:首次登录不显示背景
This commit is contained in:
+48
-59
@@ -3,6 +3,7 @@ import { useTheme } from 'vuetify'
|
|||||||
import { checkPrefersColorSchemeIsDark } from '@/@core/utils'
|
import { checkPrefersColorSchemeIsDark } from '@/@core/utils'
|
||||||
import { ensureRenderComplete, removeEl } from './@core/utils/dom'
|
import { ensureRenderComplete, removeEl } from './@core/utils/dom'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
|
import { useAuthStore } from '@/stores/auth'
|
||||||
|
|
||||||
// 生效主题
|
// 生效主题
|
||||||
const { global: globalTheme } = useTheme()
|
const { global: globalTheme } = useTheme()
|
||||||
@@ -13,22 +14,56 @@ globalTheme.name.value = themeValue === 'auto' ? autoTheme : themeValue
|
|||||||
// 从 provide 中获取全局设置
|
// 从 provide 中获取全局设置
|
||||||
const globalSettings: any = inject('globalSettings')
|
const globalSettings: any = inject('globalSettings')
|
||||||
|
|
||||||
// 更新data-theme属性以便CSS选择器能正确匹配
|
|
||||||
function updateHtmlThemeAttribute(themeName: string) {
|
|
||||||
document.documentElement.setAttribute('data-theme', themeName)
|
|
||||||
// 确保body元素也有相同的主题属性,以便更好地选择弹出窗口
|
|
||||||
document.body.setAttribute('data-theme', themeName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示状态
|
// 显示状态
|
||||||
const show = ref(false)
|
const show = ref(false)
|
||||||
|
|
||||||
|
// 检查是否登录
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
const isLogin = computed(() => authStore.token)
|
||||||
|
|
||||||
// 背景图片
|
// 背景图片
|
||||||
const backgroundImages = ref<string[]>([])
|
const backgroundImages = ref<string[]>([])
|
||||||
const activeImageIndex = ref(0)
|
const activeImageIndex = ref(0)
|
||||||
const isTransparentTheme = computed(() => globalTheme.name.value === 'transparent')
|
const isTransparentTheme = computed(() => globalTheme.name.value === 'transparent')
|
||||||
let backgroundRotationTimer: NodeJS.Timeout | null = null
|
let backgroundRotationTimer: NodeJS.Timeout | null = null
|
||||||
|
|
||||||
|
// ApexCharts 全局配置
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
Apex: any
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.Apex) {
|
||||||
|
// 数据标签
|
||||||
|
window.Apex.dataLabels = {
|
||||||
|
formatter: function (_: number, { seriesIndex, w }: { seriesIndex: number; w: any }) {
|
||||||
|
// 如果有小数点,保留两位小数,否则保留整数
|
||||||
|
const data = w.config.series[seriesIndex]
|
||||||
|
return data.toFixed(data % 1 === 0 ? 0 : 1)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// 图例
|
||||||
|
window.Apex.legend = {
|
||||||
|
labels: {
|
||||||
|
useSeriesColors: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// 标题
|
||||||
|
window.Apex.title = {
|
||||||
|
style: {
|
||||||
|
color: 'rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity))',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新data-theme属性以便CSS选择器能正确匹配
|
||||||
|
function updateHtmlThemeAttribute(themeName: string) {
|
||||||
|
document.documentElement.setAttribute('data-theme', themeName)
|
||||||
|
// 确保body元素也有相同的主题属性,以便更好地选择弹出窗口
|
||||||
|
document.body.setAttribute('data-theme', themeName)
|
||||||
|
}
|
||||||
|
|
||||||
// 获取背景图片
|
// 获取背景图片
|
||||||
async function fetchBackgroundImages() {
|
async function fetchBackgroundImages() {
|
||||||
try {
|
try {
|
||||||
@@ -62,7 +97,7 @@ function getImgUrl(url: string) {
|
|||||||
|
|
||||||
// 处理页面可见性变化
|
// 处理页面可见性变化
|
||||||
function handleVisibilityChange() {
|
function handleVisibilityChange() {
|
||||||
if (document.visibilityState === 'visible' && isTransparentTheme.value) {
|
if (document.visibilityState === 'visible') {
|
||||||
// 如果已有背景图片数据,直接重启轮换
|
// 如果已有背景图片数据,直接重启轮换
|
||||||
if (backgroundImages.value.length > 0) {
|
if (backgroundImages.value.length > 0) {
|
||||||
startBackgroundRotation()
|
startBackgroundRotation()
|
||||||
@@ -74,54 +109,6 @@ function handleVisibilityChange() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听主题变化
|
|
||||||
watch(
|
|
||||||
() => globalTheme.name.value,
|
|
||||||
async newTheme => {
|
|
||||||
// 更新HTML属性
|
|
||||||
updateHtmlThemeAttribute(newTheme)
|
|
||||||
|
|
||||||
if (newTheme === 'transparent' && backgroundImages.value.length === 0) {
|
|
||||||
await fetchBackgroundImages()
|
|
||||||
startBackgroundRotation()
|
|
||||||
} else if (newTheme !== 'transparent' && backgroundRotationTimer) {
|
|
||||||
clearInterval(backgroundRotationTimer)
|
|
||||||
backgroundRotationTimer = null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
)
|
|
||||||
|
|
||||||
// ApexCharts 全局配置
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
Apex: any
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.Apex) {
|
|
||||||
// 数据标签
|
|
||||||
window.Apex.dataLabels = {
|
|
||||||
formatter: function (_: number, { seriesIndex, w }: { seriesIndex: number; w: any }) {
|
|
||||||
// 如果有小数点,保留两位小数,否则保留整数
|
|
||||||
const data = w.config.series[seriesIndex]
|
|
||||||
return data.toFixed(data % 1 === 0 ? 0 : 1)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// 图例
|
|
||||||
window.Apex.legend = {
|
|
||||||
labels: {
|
|
||||||
useSeriesColors: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// 标题
|
|
||||||
window.Apex.title = {
|
|
||||||
style: {
|
|
||||||
color: 'rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity))',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加logo动画效果并延迟移除加载界面
|
// 添加logo动画效果并延迟移除加载界面
|
||||||
function animateAndRemoveLoader() {
|
function animateAndRemoveLoader() {
|
||||||
const loadingBg = document.querySelector('#loading-bg') as HTMLElement
|
const loadingBg = document.querySelector('#loading-bg') as HTMLElement
|
||||||
@@ -144,14 +131,16 @@ onMounted(() => {
|
|||||||
// 初始化data-theme属性
|
// 初始化data-theme属性
|
||||||
updateHtmlThemeAttribute(globalTheme.name.value)
|
updateHtmlThemeAttribute(globalTheme.name.value)
|
||||||
|
|
||||||
|
// 加载背景图片并开始轮换
|
||||||
|
fetchBackgroundImages().then(() => startBackgroundRotation())
|
||||||
|
|
||||||
// 添加页面可见性变化监听
|
// 添加页面可见性变化监听
|
||||||
document.addEventListener('visibilitychange', handleVisibilityChange)
|
document.addEventListener('visibilitychange', handleVisibilityChange)
|
||||||
|
|
||||||
ensureRenderComplete(() => {
|
ensureRenderComplete(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// 不再添加脉冲动画
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 移除加载动画(使用新的动画方法)
|
// 移除加载动画
|
||||||
animateAndRemoveLoader()
|
animateAndRemoveLoader()
|
||||||
}, 1500)
|
}, 1500)
|
||||||
})
|
})
|
||||||
@@ -173,7 +162,7 @@ onUnmounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-wrapper">
|
<div class="app-wrapper">
|
||||||
<!-- 透明主题背景 -->
|
<!-- 透明主题背景 -->
|
||||||
<template v-if="isTransparentTheme && backgroundImages.length > 0">
|
<template v-if="backgroundImages.length > 0 && (isTransparentTheme || !isLogin)">
|
||||||
<div class="background-container">
|
<div class="background-container">
|
||||||
<div
|
<div
|
||||||
v-for="(imageUrl, index) in backgroundImages"
|
v-for="(imageUrl, index) in backgroundImages"
|
||||||
|
|||||||
+7
-53
@@ -35,28 +35,12 @@ const isPasswordVisible = ref(false)
|
|||||||
// 错误信息
|
// 错误信息
|
||||||
const errorMessage = ref('')
|
const errorMessage = ref('')
|
||||||
|
|
||||||
// 背景图片 URL 和预加载 URL
|
|
||||||
const backgroundImages = ref<string[]>([])
|
|
||||||
const activeImageIndex = ref(0)
|
|
||||||
|
|
||||||
// 是否开启双重验证
|
// 是否开启双重验证
|
||||||
const isOTP = ref(false)
|
const isOTP = ref(false)
|
||||||
|
|
||||||
// 用户名称输入框
|
// 用户名称输入框
|
||||||
const usernameInput = ref()
|
const usernameInput = ref()
|
||||||
|
|
||||||
// Interval定时器
|
|
||||||
let intervalTimer: NodeJS.Timeout | null = null
|
|
||||||
|
|
||||||
// 获取背景图片
|
|
||||||
async function fetchBackgroundImage() {
|
|
||||||
try {
|
|
||||||
backgroundImages.value = await api.get('/login/wallpapers')
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询是否开启双重验证
|
// 查询是否开启双重验证
|
||||||
const fetchOTP = debounce(async () => {
|
const fetchOTP = debounce(async () => {
|
||||||
const userid = usernameInput.value?.value
|
const userid = usernameInput.value?.value
|
||||||
@@ -180,13 +164,6 @@ function login() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化背景图片轮循
|
|
||||||
function startBackgroundRotation() {
|
|
||||||
intervalTimer = setInterval(() => {
|
|
||||||
activeImageIndex.value = (activeImageIndex.value + 1) % backgroundImages.value.length
|
|
||||||
}, 5000) // 每5秒切换一次图片
|
|
||||||
}
|
|
||||||
|
|
||||||
// 自动登录
|
// 自动登录
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// 获取token和remember状态
|
// 获取token和remember状态
|
||||||
@@ -196,39 +173,20 @@ onMounted(async () => {
|
|||||||
// 如果token存在,且保持登录状态为true,则跳转到首页
|
// 如果token存在,且保持登录状态为true,则跳转到首页
|
||||||
if (token && remember) {
|
if (token && remember) {
|
||||||
router.push('/')
|
router.push('/')
|
||||||
} else {
|
|
||||||
// 获取背景图片
|
|
||||||
await fetchBackgroundImage()
|
|
||||||
if (backgroundImages.value.length > 1) {
|
|
||||||
startBackgroundRotation()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (intervalTimer) clearInterval(intervalTimer)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!-- 当前背景图片 -->
|
<!-- 登录页面容器 -->
|
||||||
<div class="relative flex min-h-screen flex-col bg-gray-900 items-center justify-center">
|
<div class="relative flex min-h-screen flex-col items-center justify-center">
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
v-for="(imageUrl, index) in backgroundImages"
|
|
||||||
class="absolute-top-shift absolute inset-0 bg-cover bg-center transition-opacity duration-300 ease-in"
|
|
||||||
:class="{ 'opacity-100': index === activeImageIndex, 'opacity-0': index !== activeImageIndex }"
|
|
||||||
>
|
|
||||||
<VImg :src="imageUrl" class="absolute inset-0 transition-opacity duration-1000" cover position="center top" />
|
|
||||||
<div
|
|
||||||
class="absolute inset-0"
|
|
||||||
style="background-image: linear-gradient(rgba(45, 55, 72, 47%) 0%, rgb(26, 32, 46) 100%)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- 登录表单 -->
|
<!-- 登录表单 -->
|
||||||
<div class="auth-wrapper d-flex align-center justify-center">
|
<div class="auth-wrapper d-flex align-center justify-center">
|
||||||
<VCard class="auth-card px-7 py-3 w-full h-full opacity-85" max-width="24rem">
|
<VCard
|
||||||
|
class="auth-card px-7 py-3 w-full h-full"
|
||||||
|
:class="{ 'opacity-75': globalTheme.name.value !== 'transparent' }"
|
||||||
|
max-width="24rem"
|
||||||
|
>
|
||||||
<VCardItem class="justify-center">
|
<VCardItem class="justify-center">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<div class="d-flex pe-0">
|
<div class="d-flex pe-0">
|
||||||
@@ -295,10 +253,6 @@ onUnmounted(() => {
|
|||||||
padding-inline-end: 0 !important;
|
padding-inline-end: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.absolute-top-shift {
|
|
||||||
inset-block-start: calc(-4rem - env(safe-area-inset-top));
|
|
||||||
}
|
|
||||||
|
|
||||||
.auth-wrapper {
|
.auth-wrapper {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
block-size: auto;
|
block-size: auto;
|
||||||
|
|||||||
Reference in New Issue
Block a user