From 3f6e0b88bd8a289a42819a485235ab9caa5df056 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Apr 2026 13:53:32 +0000 Subject: [PATCH] feat: add custom background image with frosted glass effect - Add background settings (enabled, url, imageData, blur, opacity) to settings.js - Add watchSettings same-tab reactivity via custom DOM event dispatch - Create BackgroundSettingsCard.vue with URL input, file upload, sliders, preview - Apply background layer in App.vue with blur filter and dark overlay - Add background settings tab to settings.vue navigation Agent-Logs-Url: https://github.com/ZeroCatDev/Classworks/sessions/6dfae4c0-df49-4612-88b8-9e31287538b0 Co-authored-by: Sunwuyuan <88357633+Sunwuyuan@users.noreply.github.com> --- src/App.vue | 76 +++- .../settings/cards/BackgroundSettingsCard.vue | 422 ++++++++++++++++++ src/pages/settings.vue | 12 + src/utils/settings.js | 62 ++- 4 files changed, 566 insertions(+), 6 deletions(-) create mode 100644 src/components/settings/cards/BackgroundSettingsCard.vue diff --git a/src/App.vue b/src/App.vue index cd7b1bb..1771bc8 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,5 +1,11 @@ diff --git a/src/components/settings/cards/BackgroundSettingsCard.vue b/src/components/settings/cards/BackgroundSettingsCard.vue new file mode 100644 index 0000000..d6d0ab7 --- /dev/null +++ b/src/components/settings/cards/BackgroundSettingsCard.vue @@ -0,0 +1,422 @@ + + + + + diff --git a/src/pages/settings.vue b/src/pages/settings.vue index 67f3148..8bfdee1 100644 --- a/src/pages/settings.vue +++ b/src/pages/settings.vue @@ -195,6 +195,10 @@ + + + + @@ -280,6 +284,7 @@ import KvDatabaseCard from "@/components/settings/cards/KvDatabaseCard.vue"; import HitokotoSettings from "@/components/HitokotoSettings.vue"; import NotificationSoundSettings from "@/components/settings/NotificationSoundSettings.vue"; import NoiseSettingsCard from "@/components/settings/cards/NoiseSettingsCard.vue"; +import BackgroundSettingsCard from "@/components/settings/cards/BackgroundSettingsCard.vue"; export default { name: "Settings", @@ -304,6 +309,7 @@ export default { HitokotoSettings, NotificationSoundSettings, NoiseSettingsCard, + BackgroundSettingsCard, }, setup() { const {mobile} = useDisplay(); @@ -442,6 +448,12 @@ export default { value: "randomPicker", }, + { + title: "背景", + icon: "mdi-image", + value: "background", + }, + { title: "开发者", icon: "mdi-developer-board", diff --git a/src/utils/settings.js b/src/utils/settings.js index a7c15f0..b942ea9 100644 --- a/src/utils/settings.js +++ b/src/utils/settings.js @@ -441,6 +441,40 @@ const settingsDefinitions = { // 设置应用的主题模式,可选亮色或暗色主题 }, + // 背景设置 + "background.enabled": { + type: "boolean", + default: false, + description: "启用自定义背景", + icon: "mdi-image", + }, + "background.url": { + type: "string", + default: "", + description: "背景图片地址", + icon: "mdi-link", + }, + "background.imageData": { + type: "string", + default: "", + description: "本地背景图片(Base64)", + icon: "mdi-image-area", + }, + "background.blur": { + type: "number", + default: 10, + validate: (value) => value >= 0 && value <= 50, + description: "毛玻璃模糊幅度(px)", + icon: "mdi-blur", + }, + "background.opacity": { + type: "number", + default: 30, + validate: (value) => value >= 0 && value <= 80, + description: "遮罩暗色程度(%)", + icon: "mdi-circle-half-full", + }, + // 通知铃声设置 "notification.singleSound": { type: "string", @@ -674,6 +708,13 @@ class SettingsManagerClass { this.saveSettings(); this.logSettingsChange(key, oldValue, value); + // 触发同标签页内的设置变化事件 + if (typeof window !== "undefined") { + window.dispatchEvent(new CustomEvent("classworks-settings-changed", { + detail: { key, value }, + })); + } + // 为了保持向后兼容,同时更新旧的localStorage键 const legacyKey = definition.legacyKey; if (legacyKey && typeof localStorage !== "undefined") { @@ -721,6 +762,13 @@ class SettingsManagerClass { this.settingsCache[key] = definition.default; this.saveSettings(); + + // 触发同标签页内的设置变化事件 + if (typeof window !== "undefined") { + window.dispatchEvent(new CustomEvent("classworks-settings-changed", { + detail: { key, value: definition.default }, + })); + } } /** @@ -743,15 +791,23 @@ class SettingsManagerClass { if (typeof window === "undefined") return () => { }; - const handler = (event) => { + const storageHandler = (event) => { if (event.key === SETTINGS_STORAGE_KEY) { this.settingsCache = JSON.parse(event.newValue); callback(this.settingsCache); } }; - window.addEventListener("storage", handler); - return () => window.removeEventListener("storage", handler); + const customHandler = () => { + callback(this.settingsCache); + }; + + window.addEventListener("storage", storageHandler); + window.addEventListener("classworks-settings-changed", customHandler); + return () => { + window.removeEventListener("storage", storageHandler); + window.removeEventListener("classworks-settings-changed", customHandler); + }; } /**