feat(theme): 尝试适配 1.0.5 更新,实现背景自定义功能

- 新增主题配置项,允许用户通过 Komari 后台自定义背景图片、切换时间和过渡效果。
- 更新 GitHub Actions 发布流程,改用 `softprops/action-gh-release@v2` 以简化发布和资产上传步骤。
- 为国旗图片添加懒加载(`loading="lazy"`),优化页面加载性能。
This commit is contained in:
Montia37
2025-08-15 04:46:19 +08:00
parent f6db5cbd64
commit 2e4f2a8a98
9 changed files with 170 additions and 21 deletions

View File

@@ -0,0 +1,99 @@
import { useEffect, useState, useMemo } from "react";
import { BACKGROUND } from "@/config/default";
import type { PublicInfo } from "@/types/node.d";
/**
* 动态背景组件
* 根据设定的时间间隔自动切换背景图片
* 并预加载所有图片以提高用户体验
* 支持自定义过渡效果和切换时间
*/
interface ThemeSettings {
backgroundImage?: string; // 逗号分隔的背景图片URL列表
switchTime?: number; // 背景切换时间间隔(秒)
transition?: string; // CSS过渡效果
}
interface BackgroundProps {
publicSettings: PublicInfo;
}
function DynamicPseudoBackground({ publicSettings }: BackgroundProps) {
const theme = (publicSettings?.theme_settings as ThemeSettings) || {};
// 使用 useMemo 缓存背景图片列表,避免每次渲染时重新计算
const imageList = useMemo(() => {
return theme.backgroundImage
? theme.backgroundImage.split(",").map((url) => url.trim())
: [BACKGROUND.backgroundImage];
}, [theme.backgroundImage]);
// 将切换时间从秒转换为毫秒
const switchTime = useMemo(() => {
return (theme.switchTime || BACKGROUND.switchTime) * 1000;
}, [theme.switchTime]);
const transition = useMemo(() => {
return theme.transition || BACKGROUND.transition;
}, [theme.transition]);
const [currentImageIndex, setCurrentImageIndex] = useState(0);
const currentImageUrl = imageList[currentImageIndex];
// 预加载指定的图片
const preloadImage = (url: string) => {
if (!url) return;
const img = new Image();
img.src = url;
};
// 预加载所有图片,只在组件初始化或图片列表变化时执行一次
useEffect(() => {
// 只有当有多张图片时才设置过渡效果
if (imageList.length > 1) {
document.body.style.setProperty(
"--body-background-transition",
transition
);
// 预加载所有图片以提高用户体验
imageList.forEach((url) => {
preloadImage(url);
});
}
// 组件卸载时清理
return () => {
document.body.style.removeProperty("--body-background-transition");
};
}, [imageList, transition]);
// 背景切换逻辑
useEffect(() => {
// 当当前图片URL变化时更新CSS变量
document.body.style.setProperty(
"--body-background-url",
`url(${currentImageUrl})`
);
// 只有当有多张图片时才设置定时器进行轮换
let intervalId: number | undefined;
if (imageList.length > 1) {
intervalId = window.setInterval(() => {
setCurrentImageIndex((prevIndex) => (prevIndex + 1) % imageList.length);
}, switchTime);
}
// 清理函数,组件卸载或依赖项变化时执行
return () => {
if (intervalId) {
clearInterval(intervalId);
}
};
}, [currentImageUrl, imageList, switchTime]);
// 此组件不渲染任何可见内容
return null;
}
export default DynamicPseudoBackground;

View File

@@ -93,6 +93,7 @@ const Flag = React.memo(({ flag, size }: FlagProps) => {
src={imgSrc}
alt={altText}
style={{ width: "100%", height: "100%", objectFit: "contain" }}
loading="lazy"
/>
</Box>
);