Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 76 additions & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<template>
<v-app>
<v-app :style="vAppStyle">
<!-- 自定义背景层 -->
<template v-if="bgEnabled">
<div class="app-background-image" :style="bgImageStyle" />
<div class="app-background-overlay" :style="bgOverlayStyle" />
</template>

<!-- 正常路由 -->
<router-view v-slot="{ Component, route }">
<transition mode="out-in" name="md3">
Expand All @@ -12,24 +18,74 @@
</template>

<script setup>
import { onMounted } from "vue";
import { ref, computed, onMounted, onUnmounted } from "vue";
import { useTheme } from "vuetify";
import { getSetting } from "@/utils/settings";
import { getSetting, watchSettings } from "@/utils/settings";
import RateLimitModal from "@/components/RateLimitModal.vue";

const theme = useTheme();

// Background reactive refs
const bgEnabled = ref(false);
const bgSrc = ref("");
const bgBlur = ref(10);
const bgOpacity = ref(30);

function loadBgSettings() {
bgEnabled.value = getSetting("background.enabled") || false;
const imageData = getSetting("background.imageData") || "";
const url = getSetting("background.url") || "";
bgSrc.value = imageData || url;
bgBlur.value = getSetting("background.blur") ?? 10;
bgOpacity.value = getSetting("background.opacity") ?? 30;
}

const vAppStyle = computed(() => {
if (!bgEnabled.value || !bgSrc.value) return {};
return { background: "transparent" };
});

const bgImageStyle = computed(() => ({
backgroundImage: `url(${bgSrc.value})`,
backgroundSize: "cover",
backgroundPosition: "center",
filter: `blur(${bgBlur.value}px)`,
// Scale slightly to hide blur edge artifacts
transform: "scale(1.05)",
}));

const bgOverlayStyle = computed(() => ({
background: `rgba(0, 0, 0, ${bgOpacity.value / 100})`,
}));

let unwatchSettings = null;

onMounted(() => {
// 应用保存的主题设置
const savedTheme = getSetting("theme.mode");
theme.global.name.value = savedTheme;

loadBgSettings();

unwatchSettings = watchSettings((_, event) => {
// If event detail is available (same-tab change), only reload on background keys
const changedKey = event?.detail?.key;
if (!changedKey || changedKey.startsWith("background.") || changedKey === "theme.mode") {
loadBgSettings();
theme.global.name.value = getSetting("theme.mode");
}
Comment on lines +70 to +76
});

window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
window.deferredPwaPrompt = e;
window.dispatchEvent(new Event('pwa-prompt-ready'));
});
});

onUnmounted(() => {
if (unwatchSettings) unwatchSettings();
});
</script>
<style>
/* 全局样式(从 index.vue 迁移,确保全局可用且仅加载一次) */
Expand All @@ -52,4 +108,21 @@ onMounted(() => {
opacity: 0;
transform: translateX(-0.5vw);
}

/* 自定义背景层 */
.app-background-image,
.app-background-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
pointer-events: none;
}

.app-background-image {
transform-origin: center center;
will-change: transform, filter;
}
</style>
Loading