diff --git a/packages/@core/preferences/src/preferences.ts b/packages/@core/preferences/src/preferences.ts index 26f1d711..23c5f8be 100644 --- a/packages/@core/preferences/src/preferences.ts +++ b/packages/@core/preferences/src/preferences.ts @@ -2,14 +2,16 @@ import type { DeepPartial } from '@vben-core/typings'; import type { InitialOptions, Preferences } from './types'; +import { markRaw, reactive, readonly, watch } from 'vue'; + import { StorageManager } from '@vben-core/shared/cache'; import { isMacOs, merge } from '@vben-core/shared/utils'; + import { breakpointsTailwind, useBreakpoints, useDebounceFn, } from '@vueuse/core'; -import { markRaw, reactive, readonly, watch } from 'vue'; import { defaultPreferences } from './config'; import { updateCSSVariables } from './update-css-variables'; @@ -37,6 +39,90 @@ class PreferenceManager { ); } + clearCache() { + [STORAGE_KEY, STORAGE_KEY_LOCALE, STORAGE_KEY_THEME].forEach((key) => { + this.cache?.removeItem(key); + }); + } + + public getInitialPreferences() { + return this.initialPreferences; + } + + public getPreferences() { + return readonly(this.state); + } + + /** + * 覆盖偏好设置 + * overrides 要覆盖的偏好设置 + * namespace 命名空间 + */ + public async initPreferences({ namespace, overrides }: InitialOptions) { + // 是否初始化过 + if (this.isInitialized) { + return; + } + // 初始化存储管理器 + this.cache = new StorageManager({ prefix: namespace }); + // 合并初始偏好设置 + this.initialPreferences = merge({}, overrides, defaultPreferences); + + // 加载并合并当前存储的偏好设置 + const mergedPreference = merge( + {}, + // overrides, + this.loadCachedPreferences() || {}, + this.initialPreferences, + ); + + // 更新偏好设置 + this.updatePreferences(mergedPreference); + + this.setupWatcher(); + + this.initPlatform(); + // 标记为已初始化 + this.isInitialized = true; + } + + /** + * 重置偏好设置 + * 偏好设置将被重置为初始值,并从 localStorage 中移除。 + * + * @example + * 假设 initialPreferences 为 { theme: 'light', language: 'en' } + * 当前 state 为 { theme: 'dark', language: 'fr' } + * this.resetPreferences(); + * 调用后,state 将被重置为 { theme: 'light', language: 'en' } + * 并且 localStorage 中的对应项将被移除 + */ + resetPreferences() { + // 将状态重置为初始偏好设置 + Object.assign(this.state, this.initialPreferences); + // 保存重置后的偏好设置 + this.savePreferences(this.state); + // 从存储中移除偏好设置项 + [STORAGE_KEY, STORAGE_KEY_THEME, STORAGE_KEY_LOCALE].forEach((key) => { + this.cache?.removeItem(key); + }); + this.updatePreferences(this.state); + } + + /** + * 更新偏好设置 + * @param updates - 要更新的偏好设置 + */ + public updatePreferences(updates: DeepPartial) { + const mergedState = merge({}, updates, markRaw(this.state)); + + Object.assign(this.state, mergedState); + + // 根据更新的键值执行相应的操作 + this.handleUpdates(updates); + this.savePreferences(this.state); + } + /** * 保存偏好设置 * @param {Preferences} preference - 需要保存的偏好设置 @@ -112,9 +198,16 @@ class PreferenceManager { window .matchMedia('(prefers-color-scheme: dark)') .addEventListener('change', ({ matches: isDark }) => { - this.updatePreferences({ - theme: { mode: isDark ? 'dark' : 'light' }, - }); + // 如果偏好设置中主题模式为auto,则跟随系统更新 + if (this.state.theme.mode === 'auto') { + this.updatePreferences({ + theme: { mode: isDark ? 'dark' : 'light' }, + }); + // 恢复为auto模式 + this.updatePreferences({ + theme: { mode: 'auto' }, + }); + } }); } @@ -136,90 +229,6 @@ class PreferenceManager { : dom.classList.remove(COLOR_GRAY); } } - - clearCache() { - [STORAGE_KEY, STORAGE_KEY_LOCALE, STORAGE_KEY_THEME].forEach((key) => { - this.cache?.removeItem(key); - }); - } - - public getInitialPreferences() { - return this.initialPreferences; - } - - public getPreferences() { - return readonly(this.state); - } - - /** - * 覆盖偏好设置 - * overrides 要覆盖的偏好设置 - * namespace 命名空间 - */ - public async initPreferences({ namespace, overrides }: InitialOptions) { - // 是否初始化过 - if (this.isInitialized) { - return; - } - // 初始化存储管理器 - this.cache = new StorageManager({ prefix: namespace }); - // 合并初始偏好设置 - this.initialPreferences = merge({}, overrides, defaultPreferences); - - // 加载并合并当前存储的偏好设置 - const mergedPreference = merge( - {}, - // overrides, - this.loadCachedPreferences() || {}, - this.initialPreferences, - ); - - // 更新偏好设置 - this.updatePreferences(mergedPreference); - - this.setupWatcher(); - - this.initPlatform(); - // 标记为已初始化 - this.isInitialized = true; - } - - /** - * 重置偏好设置 - * 偏好设置将被重置为初始值,并从 localStorage 中移除。 - * - * @example - * 假设 initialPreferences 为 { theme: 'light', language: 'en' } - * 当前 state 为 { theme: 'dark', language: 'fr' } - * this.resetPreferences(); - * 调用后,state 将被重置为 { theme: 'light', language: 'en' } - * 并且 localStorage 中的对应项将被移除 - */ - resetPreferences() { - // 将状态重置为初始偏好设置 - Object.assign(this.state, this.initialPreferences); - // 保存重置后的偏好设置 - this.savePreferences(this.state); - // 从存储中移除偏好设置项 - [STORAGE_KEY, STORAGE_KEY_THEME, STORAGE_KEY_LOCALE].forEach((key) => { - this.cache?.removeItem(key); - }); - this.updatePreferences(this.state); - } - - /** - * 更新偏好设置 - * @param updates - 要更新的偏好设置 - */ - public updatePreferences(updates: DeepPartial) { - const mergedState = merge({}, updates, markRaw(this.state)); - - Object.assign(this.state, mergedState); - - // 根据更新的键值执行相应的操作 - this.handleUpdates(updates); - this.savePreferences(this.state); - } } const preferencesManager = new PreferenceManager(); diff --git a/packages/@core/ui-kit/popup-ui/src/alert/alert.vue b/packages/@core/ui-kit/popup-ui/src/alert/alert.vue index 8c7c4541..5c02ed2a 100644 --- a/packages/@core/ui-kit/popup-ui/src/alert/alert.vue +++ b/packages/@core/ui-kit/popup-ui/src/alert/alert.vue @@ -138,7 +138,7 @@ async function handleOpenChange(val: boolean) {
{{ $t(title) }} - +
- + {{ cancelText || $t('cancel') }} - + ({ default: 'default' }); const themeColorPrimary = defineModel('themeColorPrimary'); +const updateThemeColorPrimary = useThrottleFn( + (value: string) => { + themeColorPrimary.value = value; + }, + 300, + true, + true, +); + const inputValue = computed(() => { return new TinyColor(themeColorPrimary.value || '').toHexString(); }); @@ -84,7 +95,7 @@ function handleSelect(theme: BuiltinThemePreset) { function handleInputChange(e: Event) { const target = e.target as HTMLInputElement; - themeColorPrimary.value = convertToHsl(target.value); + updateThemeColorPrimary(convertToHsl(target.value)); } function selectColor() { diff --git a/packages/effects/plugins/src/vxe-table/init.ts b/packages/effects/plugins/src/vxe-table/init.ts index 11488f46..00e9d8ab 100644 --- a/packages/effects/plugins/src/vxe-table/init.ts +++ b/packages/effects/plugins/src/vxe-table/init.ts @@ -1,8 +1,11 @@ import type { SetupVxeTable } from './types'; +import { defineComponent, watch } from 'vue'; + import { usePreferences } from '@vben/preferences'; + import { useVbenForm } from '@vben-core/form-ui'; -import { defineComponent, watch } from 'vue'; + import { VxeButton, VxeCheckbox, @@ -103,7 +106,7 @@ export function setupVbenVxeTable(setupOptions: SetupVxeTable) { initVxeTable(); useTableForm = useVbenForm; - const preference = usePreferences(); + const { isDark, locale } = usePreferences(); const localMap = { 'zh-CN': zhCN, @@ -111,11 +114,11 @@ export function setupVbenVxeTable(setupOptions: SetupVxeTable) { }; watch( - [() => preference.theme.value, () => preference.locale.value], - ([theme, locale]) => { - VxeUI.setTheme(theme === 'dark' ? 'dark' : 'light'); - VxeUI.setI18n(locale, localMap[locale]); - VxeUI.setLanguage(locale); + [() => isDark.value, () => locale.value], + ([isDarkValue, localeValue]) => { + VxeUI.setTheme(isDarkValue ? 'dark' : 'light'); + VxeUI.setI18n(localeValue, localMap[localeValue]); + VxeUI.setLanguage(localeValue); }, { immediate: true, diff --git a/playground/src/views/examples/modal/index.vue b/playground/src/views/examples/modal/index.vue index 5674843e..2137227b 100644 --- a/playground/src/views/examples/modal/index.vue +++ b/playground/src/views/examples/modal/index.vue @@ -261,6 +261,9 @@ async function openPrompt() { +

通过快捷方法创建动态提示弹窗,适合一些轻量的提示和确认、输入等