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 @@ - + + + + + + + @@ -12,24 +18,71 @@ 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 @@ + + + + + + + + + + + + + + 背景预览 + + + + + mdi-image-search + 图片来源 + + + + + 网络地址 + 本地上传 + + + + + + + + {{ preset.label }} + + + + + + + + mdi-image-plus + 点击或拖拽图片到此处上传 + 支持 JPG、PNG、WebP、GIF(建议小于 2MB) + + + + + {{ uploadWarning }} + + + + + 已上传本地图片 + + + 清除 + + + + + + + + + mdi-blur + 毛玻璃效果 + + + + + 模糊幅度 + {{ localBlur }}px + + + + mdi-blur-off + + + mdi-blur + + + + + + + 遮罩暗色程度 + {{ localOpacity }}% + + + + mdi-brightness-7 + + + mdi-brightness-2 + + + + + + + + + + 重置 + + + 保存设置 + + + + + + + + + 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 @@ - + @@ -221,6 +221,7 @@ export default { saving: false, uploadWarning: '', urlPresets: URL_PRESETS, + settingItemKey: 0, }; }, @@ -332,7 +333,8 @@ export default { const sizeMB = file.size / 1024 / 1024; if (sizeMB > MAX_IMAGE_SIZE_MB) { - this.uploadWarning = `图片大小为 ${sizeMB.toFixed(1)}MB,超过 ${MAX_IMAGE_SIZE_MB}MB 建议大小,可能影响性能`; + this.uploadWarning = `图片大小为 ${sizeMB.toFixed(1)}MB,超过 ${MAX_IMAGE_SIZE_MB}MB 限制,请压缩后重试`; + return; } const reader = new FileReader(); @@ -379,6 +381,8 @@ export default { this.localOpacity = getSetting('background.opacity') ?? 30; this.imageSource = 'url'; this.uploadWarning = ''; + // Force re-render of SettingItem to reflect reset enabled state + this.settingItemKey++; }, }, }; diff --git a/src/utils/settings.js b/src/utils/settings.js index b942ea9..4760992 100644 --- a/src/utils/settings.js +++ b/src/utils/settings.js @@ -62,6 +62,9 @@ async function initializeStorage() { // 存储所有设置的localStorage键名 const SETTINGS_STORAGE_KEY = "Classworks_settings"; +// 同标签页设置变化事件名 +const SETTINGS_CHANGED_EVENT = "classworks:settings:changed"; + // 新增: Classworks云端存储的默认设置 const classworksCloudDefaults = { @@ -710,7 +713,7 @@ class SettingsManagerClass { // 触发同标签页内的设置变化事件 if (typeof window !== "undefined") { - window.dispatchEvent(new CustomEvent("classworks-settings-changed", { + window.dispatchEvent(new CustomEvent(SETTINGS_CHANGED_EVENT, { detail: { key, value }, })); } @@ -765,7 +768,7 @@ class SettingsManagerClass { // 触发同标签页内的设置变化事件 if (typeof window !== "undefined") { - window.dispatchEvent(new CustomEvent("classworks-settings-changed", { + window.dispatchEvent(new CustomEvent(SETTINGS_CHANGED_EVENT, { detail: { key, value: definition.default }, })); } @@ -794,19 +797,19 @@ class SettingsManagerClass { const storageHandler = (event) => { if (event.key === SETTINGS_STORAGE_KEY) { this.settingsCache = JSON.parse(event.newValue); - callback(this.settingsCache); + callback(this.settingsCache, null); } }; - const customHandler = () => { - callback(this.settingsCache); + const customHandler = (event) => { + callback(this.settingsCache, event); }; window.addEventListener("storage", storageHandler); - window.addEventListener("classworks-settings-changed", customHandler); + window.addEventListener(SETTINGS_CHANGED_EVENT, customHandler); return () => { window.removeEventListener("storage", storageHandler); - window.removeEventListener("classworks-settings-changed", customHandler); + window.removeEventListener(SETTINGS_CHANGED_EVENT, customHandler); }; } From 1f33d6d6370c05036a8aac81723a4aaf2dfbbda0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Apr 2026 13:58:41 +0000 Subject: [PATCH 4/4] fix: use MAX_IMAGE_SIZE_MB constant consistently in template and error messages 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/components/settings/cards/BackgroundSettingsCard.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/settings/cards/BackgroundSettingsCard.vue b/src/components/settings/cards/BackgroundSettingsCard.vue index d011b50..d6363a5 100644 --- a/src/components/settings/cards/BackgroundSettingsCard.vue +++ b/src/components/settings/cards/BackgroundSettingsCard.vue @@ -74,7 +74,7 @@ > mdi-image-plus 点击或拖拽图片到此处上传 - 支持 JPG、PNG、WebP、GIF(建议小于 2MB) + 支持 JPG、PNG、WebP、GIF(建议小于 {{ maxImageSizeMB }}MB)