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 @@
@@ -44,6 +71,29 @@ const appEnableCopyPreferences = defineModel(
>
{{ $t('preferences.watermarkContent') }}
+
+
+ {{ $t('preferences.watermarkOpacity') }}
+
+
+
+
+
+
+
+
+
+
+
{{ $t('preferences.checkUpdates') }}
diff --git a/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue b/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue
index d0e5ba2a6..37613d8e0 100644
--- a/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue
+++ b/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue
@@ -72,6 +72,7 @@ const appColorWeakMode = defineModel('appColorWeakMode');
const appContentCompact = defineModel('appContentCompact');
const appWatermark = defineModel('appWatermark');
const appWatermarkContent = defineModel('appWatermarkContent');
+const appWatermarkOpacity = defineModel('appWatermarkOpacity');
const appEnableCheckUpdates = defineModel('appEnableCheckUpdates');
const appEnableCopyPreferences = defineModel(
'appEnableCopyPreferences',
@@ -360,6 +361,7 @@ function handleCustomPreferencesUpdate(updates: CustomPreferencesRecord) {
v-model:app-locale="appLocale"
v-model:app-watermark="appWatermark"
v-model:app-watermark-content="appWatermarkContent"
+ v-model:app-watermark-opacity="appWatermarkOpacity"
/>