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 2/4] 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); + }; } /** From c4279acdae78fc178685bda21ff5458eee9ac256 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Apr 2026 13:56:41 +0000 Subject: [PATCH 3/4] fix: address code review feedback for background feature - Use SETTINGS_CHANGED_EVENT constant to prevent typos - Enforce 2MB image size limit (block upload instead of warn) - Fix resetAll to force re-render SettingItem for enabled toggle - Optimize watchSettings callback to only reload on relevant key changes 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 | 11 +++++++---- .../settings/cards/BackgroundSettingsCard.vue | 8 ++++++-- src/utils/settings.js | 17 ++++++++++------- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/App.vue b/src/App.vue index 1771bc8..56d4c98 100644 --- a/src/App.vue +++ b/src/App.vue @@ -67,10 +67,13 @@ onMounted(() => { loadBgSettings(); - unwatchSettings = watchSettings(() => { - loadBgSettings(); - // Reapply theme on settings change too - theme.global.name.value = getSetting("theme.mode"); + 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"); + } }); window.addEventListener('beforeinstallprompt', (e) => { diff --git a/src/components/settings/cards/BackgroundSettingsCard.vue b/src/components/settings/cards/BackgroundSettingsCard.vue index d6d0ab7..d011b50 100644 --- a/src/components/settings/cards/BackgroundSettingsCard.vue +++ b/src/components/settings/cards/BackgroundSettingsCard.vue @@ -1,7 +1,7 @@