Browse Source

refactor(watermark): 移除布局中的暗色模式处理并集中到水印钩子中

将暗色模式相关的颜色处理逻辑从各布局组件中移除,统一在use-watermark钩子中处理。
添加对主题变化的监听,自动更新水印颜色。
pull/7842/head
Lgf 4 months ago
parent
commit
b35d2f4f3b
  1. 23
      apps/web-antd/src/layouts/basic.vue
  2. 23
      apps/web-antdv-next/src/layouts/basic.vue
  3. 23
      apps/web-ele/src/layouts/basic.vue
  4. 23
      apps/web-naive/src/layouts/basic.vue
  5. 23
      apps/web-tdesign/src/layouts/basic.vue
  6. 137
      packages/effects/hooks/src/use-watermark.ts
  7. 23
      playground/src/layouts/basic.vue

23
apps/web-antd/src/layouts/basic.vue

@ -14,7 +14,7 @@ import {
Notification,
UserDropdown,
} from '@vben/layouts';
import { preferences, usePreferences } from '@vben/preferences';
import { preferences } from '@vben/preferences';
import { useAccessStore, useUserStore } from '@vben/stores';
import { openWindow } from '@vben/utils';
@ -80,7 +80,6 @@ const userStore = useUserStore();
const authStore = useAuthStore();
const accessStore = useAccessStore();
const { destroyWatermark, updateWatermark } = useWatermark();
const { isDark } = usePreferences();
const showDot = computed(() =>
notifications.value.some((item) => !item.isRead),
);
@ -180,28 +179,10 @@ watch(
() => ({
enable: preferences.app.watermark,
content: preferences.app.watermarkContent,
isDark: isDark.value,
}),
async ({ enable, content, isDark: isDarkValue }) => {
async ({ enable, content }) => {
if (enable) {
const watermarkColor = isDarkValue
? 'rgba(255, 255, 255, 0.12)'
: 'rgba(0, 0, 0, 0.12)';
await updateWatermark({
advancedStyle: {
colorStops: [
{
color: watermarkColor,
offset: 0,
},
{
color: watermarkColor,
offset: 1,
},
],
type: 'linear',
},
content:
content ||
`${userStore.userInfo?.username} - ${userStore.userInfo?.realName}`,

23
apps/web-antdv-next/src/layouts/basic.vue

@ -14,7 +14,7 @@ import {
Notification,
UserDropdown,
} from '@vben/layouts';
import { preferences, usePreferences } from '@vben/preferences';
import { preferences } from '@vben/preferences';
import { useAccessStore, useUserStore } from '@vben/stores';
import { openWindow } from '@vben/utils';
@ -80,7 +80,6 @@ const userStore = useUserStore();
const authStore = useAuthStore();
const accessStore = useAccessStore();
const { destroyWatermark, updateWatermark } = useWatermark();
const { isDark } = usePreferences();
const showDot = computed(() =>
notifications.value.some((item) => !item.isRead),
);
@ -180,28 +179,10 @@ watch(
() => ({
enable: preferences.app.watermark,
content: preferences.app.watermarkContent,
isDark: isDark.value,
}),
async ({ enable, content, isDark: isDarkValue }) => {
async ({ enable, content }) => {
if (enable) {
const watermarkColor = isDarkValue
? 'rgba(255, 255, 255, 0.12)'
: 'rgba(0, 0, 0, 0.12)';
await updateWatermark({
advancedStyle: {
colorStops: [
{
color: watermarkColor,
offset: 0,
},
{
color: watermarkColor,
offset: 1,
},
],
type: 'linear',
},
content:
content ||
`${userStore.userInfo?.username} - ${userStore.userInfo?.realName}`,

23
apps/web-ele/src/layouts/basic.vue

@ -14,7 +14,7 @@ import {
Notification,
UserDropdown,
} from '@vben/layouts';
import { preferences, usePreferences } from '@vben/preferences';
import { preferences } from '@vben/preferences';
import { useAccessStore, useUserStore } from '@vben/stores';
import { openWindow } from '@vben/utils';
@ -80,7 +80,6 @@ const userStore = useUserStore();
const authStore = useAuthStore();
const accessStore = useAccessStore();
const { destroyWatermark, updateWatermark } = useWatermark();
const { isDark } = usePreferences();
const showDot = computed(() =>
notifications.value.some((item) => !item.isRead),
);
@ -180,28 +179,10 @@ watch(
() => ({
enable: preferences.app.watermark,
content: preferences.app.watermarkContent,
isDark: isDark.value,
}),
async ({ enable, content, isDark: isDarkValue }) => {
async ({ enable, content }) => {
if (enable) {
const watermarkColor = isDarkValue
? 'rgba(255, 255, 255, 0.12)'
: 'rgba(0, 0, 0, 0.12)';
await updateWatermark({
advancedStyle: {
colorStops: [
{
color: watermarkColor,
offset: 0,
},
{
color: watermarkColor,
offset: 1,
},
],
type: 'linear',
},
content:
content ||
`${userStore.userInfo?.username} - ${userStore.userInfo?.realName}`,

23
apps/web-naive/src/layouts/basic.vue

@ -14,7 +14,7 @@ import {
Notification,
UserDropdown,
} from '@vben/layouts';
import { preferences, usePreferences } from '@vben/preferences';
import { preferences } from '@vben/preferences';
import { useAccessStore, useUserStore } from '@vben/stores';
import { openWindow } from '@vben/utils';
@ -80,7 +80,6 @@ const userStore = useUserStore();
const authStore = useAuthStore();
const accessStore = useAccessStore();
const { destroyWatermark, updateWatermark } = useWatermark();
const { isDark } = usePreferences();
const showDot = computed(() =>
notifications.value.some((item) => !item.isRead),
);
@ -180,28 +179,10 @@ watch(
() => ({
enable: preferences.app.watermark,
content: preferences.app.watermarkContent,
isDark: isDark.value,
}),
async ({ enable, content, isDark: isDarkValue }) => {
async ({ enable, content }) => {
if (enable) {
const watermarkColor = isDarkValue
? 'rgba(255, 255, 255, 0.12)'
: 'rgba(0, 0, 0, 0.12)';
await updateWatermark({
advancedStyle: {
colorStops: [
{
color: watermarkColor,
offset: 0,
},
{
color: watermarkColor,
offset: 1,
},
],
type: 'linear',
},
content:
content ||
`${userStore.userInfo?.username} - ${userStore.userInfo?.realName}`,

23
apps/web-tdesign/src/layouts/basic.vue

@ -14,7 +14,7 @@ import {
Notification,
UserDropdown,
} from '@vben/layouts';
import { preferences, usePreferences } from '@vben/preferences';
import { preferences } from '@vben/preferences';
import { useAccessStore, useUserStore } from '@vben/stores';
import { openWindow } from '@vben/utils';
@ -80,7 +80,6 @@ const userStore = useUserStore();
const authStore = useAuthStore();
const accessStore = useAccessStore();
const { destroyWatermark, updateWatermark } = useWatermark();
const { isDark } = usePreferences();
const showDot = computed(() =>
notifications.value.some((item) => !item.isRead),
);
@ -180,28 +179,10 @@ watch(
() => ({
enable: preferences.app.watermark,
content: preferences.app.watermarkContent,
isDark: isDark.value,
}),
async ({ enable, content, isDark: isDarkValue }) => {
async ({ enable, content }) => {
if (enable) {
const watermarkColor = isDarkValue
? 'rgba(255, 255, 255, 0.12)'
: 'rgba(0, 0, 0, 0.12)';
await updateWatermark({
advancedStyle: {
colorStops: [
{
color: watermarkColor,
offset: 0,
},
{
color: watermarkColor,
offset: 1,
},
],
type: 'linear',
},
content:
content ||
`${userStore.userInfo?.username} - ${userStore.userInfo?.realName}`,

137
packages/effects/hooks/src/use-watermark.ts

@ -1,43 +1,84 @@
import type { Watermark, WatermarkOptions } from 'watermark-js-plus';
import { nextTick, onUnmounted, readonly, ref } from 'vue';
import { nextTick, onUnmounted, readonly, ref, watch } from 'vue';
import { usePreferences } from '@vben/preferences';
const watermark = ref<Watermark>();
const unmountedHooked = ref<boolean>(false);
const cachedOptions = ref<Partial<WatermarkOptions>>({
advancedStyle: {
colorStops: [
{
color: 'gray',
offset: 0,
},
{
color: 'gray',
offset: 1,
},
],
type: 'linear',
},
// fontSize: '20px',
content: '',
contentType: 'multi-line-text',
globalAlpha: 0.25,
gridLayoutOptions: {
cols: 2,
gap: [20, 20],
matrix: [
[1, 0],
[0, 1],
],
rows: 2,
},
height: 200,
layout: 'grid',
rotate: 30,
width: 160,
});
const themeWatcherHooked = ref<boolean>(false);
function getDefaultWatermarkColor(isDark: boolean): string {
return isDark ? 'rgba(255, 255, 255, 0.12)' : 'rgba(0, 0, 0, 0.12)';
}
function getDefaultOptions(isDark: boolean): Partial<WatermarkOptions> {
const color = getDefaultWatermarkColor(isDark);
return {
advancedStyle: {
colorStops: [
{
color,
offset: 0,
},
{
color,
offset: 1,
},
],
type: 'linear',
},
content: '',
contentType: 'multi-line-text',
globalAlpha: 0.25,
gridLayoutOptions: {
cols: 2,
gap: [20, 20],
matrix: [
[1, 0],
[0, 1],
],
rows: 2,
},
height: 200,
layout: 'grid',
rotate: 30,
width: 160,
};
}
const cachedOptions = ref<Partial<WatermarkOptions>>({});
export function useWatermark() {
const { isDark } = usePreferences();
function mergeOptionsWithTheme(
options: Partial<WatermarkOptions>,
isDarkValue: boolean,
): Partial<WatermarkOptions> {
const defaultOpts = getDefaultOptions(isDarkValue);
if (options.advancedStyle?.colorStops) {
return {
...defaultOpts,
...cachedOptions.value,
...options,
};
}
return {
...defaultOpts,
...cachedOptions.value,
...options,
advancedStyle: {
...defaultOpts.advancedStyle,
...cachedOptions.value?.advancedStyle,
...options?.advancedStyle,
colorStops: defaultOpts.advancedStyle?.colorStops,
},
};
}
async function initWatermark(options: Partial<WatermarkOptions>) {
const { Watermark } = await import('watermark-js-plus');
@ -45,17 +86,23 @@ export function useWatermark() {
...cachedOptions.value,
...options,
};
watermark.value = new Watermark(cachedOptions.value);
const mergedOptions = mergeOptionsWithTheme(options, isDark.value);
watermark.value = new Watermark(mergedOptions);
await watermark.value?.create();
}
async function updateWatermark(options: Partial<WatermarkOptions>) {
if (watermark.value) {
await nextTick();
await watermark.value?.changeOptions({
cachedOptions.value = {
...cachedOptions.value,
...options,
});
};
const mergedOptions = mergeOptionsWithTheme(options, isDark.value);
await watermark.value?.changeOptions(mergedOptions);
} else {
await initWatermark(options);
}
@ -68,7 +115,23 @@ export function useWatermark() {
}
}
// 只在第一次调用时注册卸载钩子,防止重复注册以致于在路由切换时销毁了水印
if (!themeWatcherHooked.value) {
themeWatcherHooked.value = true;
watch(
() => isDark.value,
() => {
if (watermark.value) {
const mergedOptions = mergeOptionsWithTheme(
cachedOptions.value,
isDark.value,
);
watermark.value.changeOptions(mergedOptions);
}
},
);
}
if (!unmountedHooked.value) {
unmountedHooked.value = true;
onUnmounted(() => {

23
playground/src/layouts/basic.vue

@ -14,7 +14,7 @@ import {
Notification,
UserDropdown,
} from '@vben/layouts';
import { preferences, usePreferences } from '@vben/preferences';
import { preferences } from '@vben/preferences';
import { useAccessStore, useTabbarStore, useUserStore } from '@vben/stores';
import { openWindow } from '@vben/utils';
@ -93,7 +93,6 @@ const userStore = useUserStore();
const authStore = useAuthStore();
const accessStore = useAccessStore();
const { destroyWatermark, updateWatermark } = useWatermark();
const { isDark } = usePreferences();
const showDot = computed(() =>
notifications.value.some((item) => !item.isRead),
);
@ -195,28 +194,10 @@ watch(
() => ({
enable: preferences.app.watermark,
content: preferences.app.watermarkContent,
isDark: isDark.value,
}),
async ({ enable, content, isDark: isDarkValue }) => {
async ({ enable, content }) => {
if (enable) {
const watermarkColor = isDarkValue
? 'rgba(255, 255, 255, 0.12)'
: 'rgba(0, 0, 0, 0.12)';
await updateWatermark({
advancedStyle: {
colorStops: [
{
color: watermarkColor,
offset: 0,
},
{
color: watermarkColor,
offset: 1,
},
],
type: 'linear',
},
content:
content ||
`${userStore.userInfo?.username} - ${userStore.userInfo?.realName}`,

Loading…
Cancel
Save