fix: 水印插件兼容微前端场景,应用唯一

This commit is contained in:
wanchun 2023-03-15 17:55:21 +08:00
parent caf630071a
commit b0ff6ee7e1
6 changed files with 69 additions and 49 deletions

View File

@ -46,6 +46,7 @@
"@fesjs/fes": "^3.0.0-rc.0", "@fesjs/fes": "^3.0.0-rc.0",
"@fesjs/builder-webpack": "^3.0.0-rc.5", "@fesjs/builder-webpack": "^3.0.0-rc.5",
"@fesjs/plugin-qiankun": "3.0.0-rc.0", "@fesjs/plugin-qiankun": "3.0.0-rc.0",
"@fesjs/plugin-watermark": "3.0.0-rc.0",
"vue": "^3.2.37", "vue": "^3.2.37",
"@fesjs/fes-design": "^0.7.0" "@fesjs/fes-design": "^0.7.0"
}, },

View File

@ -1,4 +1,4 @@
import { access as accessApi } from '@fesjs/fes'; import { access as accessApi, createWatermark } from '@fesjs/fes';
import PageLoading from '@/components/PageLoading.vue'; import PageLoading from '@/components/PageLoading.vue';
export const beforeRender = { export const beforeRender = {
@ -10,6 +10,7 @@ export const beforeRender = {
setRole('admin'); setRole('admin');
resolve(); resolve();
}, 1000); }, 1000);
createWatermark();
}); });
}, },
}; };

View File

@ -46,6 +46,7 @@
"@fesjs/fes": "^3.0.0-rc.0", "@fesjs/fes": "^3.0.0-rc.0",
"@fesjs/builder-webpack": "^3.0.0-rc.5", "@fesjs/builder-webpack": "^3.0.0-rc.5",
"@fesjs/plugin-qiankun": "3.0.0-rc.0", "@fesjs/plugin-qiankun": "3.0.0-rc.0",
"@fesjs/plugin-watermark": "3.0.0-rc.0",
"vue": "^3.2.37", "vue": "^3.2.37",
"@fesjs/fes-design": "^0.7.0" "@fesjs/fes-design": "^0.7.0"
}, },

View File

@ -8,8 +8,14 @@
} }
</config> </config>
<script> <script>
import { onBeforeUnmount } from 'vue';
import { createWatermark, destroyWatermark } from '@fesjs/fes';
export default { export default {
setup() { setup() {
createWatermark();
onBeforeUnmount(destroyWatermark);
return { return {
bigData: new Array(5 * 1024 * 1024), bigData: new Array(5 * 1024 * 1024),
}; };

View File

@ -30,31 +30,37 @@ function timeFormat(date, format = 'YYYY-MM-DD') {
return format.replace(/Y+|M+|D+|H+|h+|m+|s+|S+|Q/g, (str) => String(map[str])); return format.replace(/Y+|M+|D+|H+|h+|m+|s+|S+|Q/g, (str) => String(map[str]));
} }
let _wmContainerMo = null; // MutationObserver let wmContainerObx = null; // MutationObserver
let _wmMo = null; // MutationObserver let wmObx = null; // MutationObserver
let _wmTimer = null; // timestamp let wmTimer = null; // timestamp
let watermarkDiv = null;
// 销毁水印 // 销毁水印
export function destroyWatermark() { export function destroyWatermark() {
// 监听器关闭 // 监听器关闭
_wmMo?.disconnect(); wmObx?.disconnect();
_wmMo = null; wmObx = null;
_wmContainerMo?.disconnect(); wmContainerObx?.disconnect();
_wmContainerMo = null; wmContainerObx = null;
// 清除timer // 清除timer
if (_wmTimer) { if (wmTimer) {
window.clearTimeout(_wmTimer); window.clearTimeout(wmTimer);
_wmTimer = null; wmTimer = null;
} }
// 删除水印元素 // 删除水印元素
let __wm = document.querySelector('.__wm'); watermarkDiv?.parentNode?.removeChild(watermarkDiv);
__wm?.parentNode?.removeChild(__wm); watermarkDiv = null;
__wm = null;
} }
function _createWatermark(param) { function innerCreateWatermark(param) {
const { content, container, width, height, textAlign, textBaseline, fontSize, fontFamily, fillStyle, rotate, zIndex, timestamp, watch } = param; const { content, container, width, height, textAlign, textBaseline, fontSize, fontFamily, fillStyle, rotate, zIndex, timestamp, watch } = param;
if (!container) {
return console.warn('createWatermark配置的container不能为空');
}
destroyWatermark();
const canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');
canvas.setAttribute('width', `${width}px`); canvas.setAttribute('width', `${width}px`);
canvas.setAttribute('height', `${height}px`); canvas.setAttribute('height', `${height}px`);
@ -67,9 +73,13 @@ function _createWatermark(param) {
ctx.translate(width / 2, height / 2); ctx.translate(width / 2, height / 2);
ctx.rotate(-(Math.PI / 180) * rotate); ctx.rotate(-(Math.PI / 180) * rotate);
ctx.fillText(`${content}`, 0, 0); ctx.fillText(`${content}`, 0, 0);
timestamp && ctx.fillText(`${timeFormat(new Date(), timestamp)}`, 0, parseInt(fontSize) + 5); if (timestamp) {
ctx.fillText(`${timeFormat(new Date(), timestamp)}`, 0, parseInt(fontSize) + 5);
}
const watermarkDiv = document.querySelector('.__wm') || document.createElement('div'); const CLASS_NAME = `wm_${Date.now()}`;
watermarkDiv = document.createElement('div');
const styleStr = ` const styleStr = `
position: ${container === document.body ? 'fixed' : 'absolute'}; position: ${container === document.body ? 'fixed' : 'absolute'};
user-select: none; user-select: none;
@ -81,9 +91,8 @@ function _createWatermark(param) {
pointer-events: none !important; pointer-events: none !important;
background-repeat: repeat; background-repeat: repeat;
background-image: url('${canvas.toDataURL()}')`; background-image: url('${canvas.toDataURL()}')`;
watermarkDiv.setAttribute('style', styleStr); watermarkDiv.setAttribute('style', styleStr);
watermarkDiv.classList.add('__wm'); watermarkDiv.classList.add(CLASS_NAME);
if (container.firstChild) { if (container.firstChild) {
container.insertBefore(watermarkDiv, container.firstChild); container.insertBefore(watermarkDiv, container.firstChild);
@ -91,26 +100,25 @@ function _createWatermark(param) {
container.appendChild(watermarkDiv); container.appendChild(watermarkDiv);
} }
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver; const MutationObserver = window.MutationObserver;
if (watch && MutationObserver) { if (watch && MutationObserver) {
_wmContainerMo = new MutationObserver(() => { wmContainerObx = new MutationObserver(() => {
const __wm = container.querySelector('.__wm'); if (!container.querySelector(`.${CLASS_NAME}`)) {
if ((__wm && __wm.getAttribute('style') !== styleStr) || !__wm) { innerCreateWatermark(param);
destroyWatermark();
_createWatermark(param);
} }
}); });
_wmContainerMo.observe(container, { wmContainerObx.observe(container, {
childList: true, childList: true,
}); });
_wmMo = new MutationObserver(() => { wmObx = new MutationObserver(() => {
destroyWatermark(); if (watermarkDiv.getAttribute('style') !== styleStr) {
_createWatermark(param); innerCreateWatermark(param);
}
}); });
_wmMo.observe(watermarkDiv, { wmObx.observe(watermarkDiv, {
attributes: true, attributes: true,
}); });
} }
@ -125,9 +133,8 @@ function _createWatermark(param) {
timeout = 1000 * 60 * 60; timeout = 1000 * 60 * 60;
} }
_wmTimer = window.setTimeout(() => { wmTimer = window.setTimeout(() => {
destroyWatermark(); innerCreateWatermark(param);
_createWatermark(param);
}, timeout); }, timeout);
} }
} }
@ -155,10 +162,7 @@ export function createWatermark(option) {
watch: true, watch: true,
}; };
// 为避免多次调用 createWatermark 触发重复监听,这里先执行销毁水印操作 innerCreateWatermark({
destroyWatermark();
_createWatermark({
...defaultOption, ...defaultOption,
...option, ...option,
}); });

View File

@ -1,18 +1,25 @@
import '@fesjs/fes'; import '@fesjs/fes';
interface WatermarkParam { interface WatermarkParam {
content: string; content?: string;
container: HTMLElement; container?: HTMLElement;
width: number; width?: number;
height: number; height?: number;
textAlign: 'left' | 'right' | 'center' | 'start' | 'end'; textAlign?: 'center' | 'end' | 'left' | 'right' | 'start';
textBaseline: 'top' | 'hanging' | 'middle' | 'alphabetic' | 'ideographic' | 'bottom'; textBaseline?:
fontSize: string; | 'alphabetic'
fontFamily: string; | 'bottom'
fillStyle: string; | 'hanging'
rotate: number; | 'ideographic'
zIndex: number; | 'middle'
timestamp: string; | 'top';
fontSize?: string;
fontFamily?: string;
fillStyle?: string;
rotate?: number;
zIndex?: number;
timestamp?: string | false;
watch?: boolean;
} }
export function createWatermark(param: WatermarkParam): void; export function createWatermark(param: WatermarkParam): void;
export function destroyWatermark(): void; export function destroyWatermark(): void;