mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-27 09:18:33 +08:00
feat: Feature/pro docs (#70)
* chore: merge main * feat: update docs * feat: remove coze-assistant * feat: add watermark plugin * feat: update preferences * feat: update docs --------- Co-authored-by: vince <vince292007@gmail.com>
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
export * from './unmount-global-loading';
|
||||
export * from './use-app-config';
|
||||
export * from './use-content-maximize';
|
||||
export * from './use-refresh';
|
||||
export * from './use-tabs';
|
||||
export * from './use-watermark';
|
||||
export * from '@vben-core/hooks';
|
||||
|
30
packages/effects/hooks/src/unmount-global-loading.ts
Normal file
30
packages/effects/hooks/src/unmount-global-loading.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 移除并销毁loading
|
||||
* 放在这里是而不是放在 index.html 的app标签内,是因为这样比较不会生硬,渲染过快可能会有闪烁
|
||||
* 通过先添加css动画隐藏,在动画结束后在移除loading节点来改善体验
|
||||
* 不好的地方是会增加一些代码量
|
||||
*/
|
||||
export function unmountGlobalLoading() {
|
||||
// 查找全局 loading 元素
|
||||
const loadingElement = document.querySelector('#__app-loading__');
|
||||
|
||||
if (loadingElement) {
|
||||
// 添加隐藏类,触发过渡动画
|
||||
loadingElement.classList.add('hidden');
|
||||
|
||||
// 查找所有需要移除的注入 loading 元素
|
||||
const injectLoadingElements = document.querySelectorAll(
|
||||
'[data-app-loading^="inject"]',
|
||||
);
|
||||
|
||||
// 当过渡动画结束时,移除 loading 元素和所有注入的 loading 元素
|
||||
loadingElement.addEventListener(
|
||||
'transitionend',
|
||||
() => {
|
||||
loadingElement.remove(); // 移除 loading 元素
|
||||
injectLoadingElements.forEach((el) => el.remove()); // 移除所有注入的 loading 元素
|
||||
},
|
||||
{ once: true },
|
||||
); // 确保事件只触发一次
|
||||
}
|
||||
}
|
24
packages/effects/hooks/src/use-app-config.ts
Normal file
24
packages/effects/hooks/src/use-app-config.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import type {
|
||||
ApplicationConfig,
|
||||
VbenAdminProAppConfigRaw,
|
||||
} from '@vben/types/global';
|
||||
|
||||
/**
|
||||
* 由 vite-inject-app-config 注入的全局配置
|
||||
*/
|
||||
export function useAppConfig(
|
||||
env: Record<string, any>,
|
||||
isProduction: boolean,
|
||||
): ApplicationConfig {
|
||||
// 生产环境下,直接使用 window._VBEN_ADMIN_PRO_APP_CONF_ 全局变量
|
||||
const config = isProduction
|
||||
? window._VBEN_ADMIN_PRO_APP_CONF_
|
||||
: (env as VbenAdminProAppConfigRaw);
|
||||
|
||||
const { VITE_GLOB_API_URL, VITE_GLOB_APP_TITLE } = config;
|
||||
|
||||
return {
|
||||
apiURL: VITE_GLOB_API_URL,
|
||||
appTitle: VITE_GLOB_APP_TITLE,
|
||||
};
|
||||
}
|
88
packages/effects/hooks/src/use-watermark.ts
Normal file
88
packages/effects/hooks/src/use-watermark.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import type { Watermark, WatermarkOptions } from 'watermark-js-plus';
|
||||
|
||||
import { nextTick, onUnmounted, ref, watch } from 'vue';
|
||||
|
||||
import { preferences } from '@vben/preferences';
|
||||
|
||||
const watermark = ref<Watermark>();
|
||||
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,
|
||||
});
|
||||
|
||||
export function useWatermark() {
|
||||
async function initWatermark(options: Partial<WatermarkOptions>) {
|
||||
const { Watermark } = await import('watermark-js-plus');
|
||||
|
||||
cachedOptions.value = {
|
||||
...cachedOptions.value,
|
||||
...options,
|
||||
};
|
||||
watermark.value = new Watermark(cachedOptions.value);
|
||||
|
||||
watermark.value?.create();
|
||||
}
|
||||
|
||||
async function updateWatermark(options: Partial<WatermarkOptions>) {
|
||||
if (!watermark.value || !watermark.value?.check()) {
|
||||
await initWatermark(options);
|
||||
} else {
|
||||
await nextTick();
|
||||
watermark.value?.changeOptions({
|
||||
...cachedOptions.value,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function destroyWatermark() {
|
||||
watermark.value?.destroy();
|
||||
}
|
||||
|
||||
watch(
|
||||
() => preferences.app.watermark,
|
||||
(enable) => {
|
||||
if (!enable) {
|
||||
destroyWatermark();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
onUnmounted(() => {
|
||||
destroyWatermark();
|
||||
});
|
||||
|
||||
return {
|
||||
destroyWatermark,
|
||||
updateWatermark,
|
||||
watermark,
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user