diff --git a/packages/@core/preferences/src/config.ts b/packages/@core/preferences/src/config.ts index c39366a75..c3147edb9 100644 --- a/packages/@core/preferences/src/config.ts +++ b/packages/@core/preferences/src/config.ts @@ -32,6 +32,7 @@ const defaultPreferences: Preferences = { preferencesButtonPosition: 'auto', watermark: false, watermarkContent: '', + watermarkOpacity: 0.25, zIndex: 200, }, breadcrumb: { diff --git a/packages/@core/preferences/src/types.ts b/packages/@core/preferences/src/types.ts index 50aefa6e0..5a495c652 100644 --- a/packages/@core/preferences/src/types.ts +++ b/packages/@core/preferences/src/types.ts @@ -163,6 +163,10 @@ interface AppPreferences { * @zh_CN 水印文案 */ watermarkContent: string; + /** + * @zh_CN 水印透明度 + */ + watermarkOpacity: number; /** z-index */ zIndex: number; } diff --git a/packages/effects/layouts/src/basic/layout.vue b/packages/effects/layouts/src/basic/layout.vue index aba886990..fb14a452e 100644 --- a/packages/effects/layouts/src/basic/layout.vue +++ b/packages/effects/layouts/src/basic/layout.vue @@ -7,14 +7,19 @@ import type { MenuRecordRaw } from '@vben/types'; import { computed, onMounted, useSlots, watch } from 'vue'; import { useRoute } from 'vue-router'; -import { useRefresh } from '@vben/hooks'; +import { useRefresh, useWatermark } from '@vben/hooks'; import { $t, i18n } from '@vben/locales'; import { preferences, updatePreferences, usePreferences, } from '@vben/preferences'; -import { useAccessStore, useTabbarStore, useTimezoneStore } from '@vben/stores'; +import { + useAccessStore, + useTabbarStore, + useTimezoneStore, + useUserStore, +} from '@vben/stores'; import { cloneDeep, mapTree } from '@vben/utils'; import { VbenAdminLayout } from '@vben-core/layout-ui'; @@ -53,7 +58,18 @@ const { } = usePreferences(); const accessStore = useAccessStore(); const timezoneStore = useTimezoneStore(); +const userStore = useUserStore(); const { refresh } = useRefresh(); +const { destroyWatermark, updateWatermark } = useWatermark(); + +const watermarkContent = computed(() => { + const customContent = preferences.app.watermarkContent; + if (customContent && customContent.trim()) { + return customContent; + } + const username = userStore.userInfo?.username; + return username || 'Unauthorized'; +}); const sidebarTheme = computed(() => { const dark = isDark.value || preferences.theme.semiDarkSidebar; @@ -193,6 +209,25 @@ watch( }, ); +watch( + [ + () => preferences.app.watermark, + () => preferences.app.watermarkOpacity, + watermarkContent, + ], + ([isEnabled, opacity, content]) => { + if (isEnabled) { + updateWatermark({ + content, + globalAlpha: opacity as number, + }); + } else { + destroyWatermark(); + } + }, + { immediate: true }, +); + const tabbarStore = useTabbarStore(); function refreshAll() { diff --git a/packages/effects/layouts/src/widgets/preferences/blocks/general/general.vue b/packages/effects/layouts/src/widgets/preferences/blocks/general/general.vue index 857902924..bf2eee0b2 100644 --- a/packages/effects/layouts/src/widgets/preferences/blocks/general/general.vue +++ b/packages/effects/layouts/src/widgets/preferences/blocks/general/general.vue @@ -1,7 +1,17 @@