|
|
@@ -0,0 +1,156 @@
|
|
|
+<template>
|
|
|
+ <!-- 水印容器:根据传入的 props 适配全局/局部水印 -->
|
|
|
+ <div
|
|
|
+ class="watermark-wrapper"
|
|
|
+ :style="{
|
|
|
+ position: position,
|
|
|
+ top: 0,
|
|
|
+ left: 0,
|
|
|
+ width: width,
|
|
|
+ height: height,
|
|
|
+ zIndex: zIndex,
|
|
|
+ pointerEvents: 'none' // 核心:不遮挡交互
|
|
|
+ }"
|
|
|
+ ></div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, onMounted, onUnmounted, watch } from 'vue';
|
|
|
+// import {useUserInfoHook} from '@/hooks/useUserInfoHook'
|
|
|
+
|
|
|
+// 定义组件 props
|
|
|
+const props = defineProps({
|
|
|
+ // 定位方式:fixed(全局)/ absolute(局部)
|
|
|
+ position: {
|
|
|
+ type: String,
|
|
|
+ default: 'fixed',
|
|
|
+ validator: (val) => ['fixed', 'absolute'].includes(val)
|
|
|
+ },
|
|
|
+ // 宽度:全局用 100vw,局部用 100%
|
|
|
+ width: {
|
|
|
+ type: String,
|
|
|
+ default: '100vw'
|
|
|
+ },
|
|
|
+ // 高度:全局用 100vh,局部用 100%
|
|
|
+ height: {
|
|
|
+ type: String,
|
|
|
+ default: '100vh'
|
|
|
+ },
|
|
|
+ // 层级:默认 999(低于 el-dialog 的 2000)
|
|
|
+ zIndex: {
|
|
|
+ type: Number,
|
|
|
+ default: 999
|
|
|
+ },
|
|
|
+ // 是否固定屏幕模式(适配你的业务逻辑)
|
|
|
+ isFixedScreen: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ username:{
|
|
|
+ type: String,
|
|
|
+ },
|
|
|
+ realname:{
|
|
|
+ type: String,
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+// 移除水印的方法引用
|
|
|
+let removeWatermarkFn = null;
|
|
|
+
|
|
|
+// 获取用户仓库
|
|
|
+
|
|
|
+// const {realname,staffNo} = useUserInfoHook();
|
|
|
+// 生成水印的核心方法
|
|
|
+const createWatermark = () => {
|
|
|
+
|
|
|
+ // 未登录/无用户信息时不生成水印
|
|
|
+ if (!props.username || !props.realname) return;
|
|
|
+
|
|
|
+ // 拼接水印文本
|
|
|
+ const watermarkText = `${props.username}-${props.realname}`;
|
|
|
+
|
|
|
+ // 1. 创建 Canvas 绘制水印
|
|
|
+ const canvas = document.createElement('canvas');
|
|
|
+ const ctx = canvas.getContext('2d');
|
|
|
+ if (!ctx) return;
|
|
|
+
|
|
|
+ // 配置水印样式
|
|
|
+ const font = '16px Microsoft YaHei';
|
|
|
+ const color = 'rgba(64, 158, 255, 0.15)';
|
|
|
+ const rotate = -15;
|
|
|
+
|
|
|
+ // 计算文本尺寸
|
|
|
+ ctx.font = font;
|
|
|
+ const textWidth = ctx.measureText(watermarkText).width;
|
|
|
+ canvas.width = textWidth + 120; // 水平间距
|
|
|
+ canvas.height = textWidth + 80; // 垂直间距
|
|
|
+
|
|
|
+ // 绘制水印
|
|
|
+ ctx.font = font;
|
|
|
+ ctx.fillStyle = color;
|
|
|
+ ctx.rotate((rotate * Math.PI) / 180); // 角度转弧度
|
|
|
+ ctx.fillText(watermarkText, 0, canvas.height / 2);
|
|
|
+
|
|
|
+ // 2. 生成 Base64 图片
|
|
|
+ const watermarkBase64 = canvas.toDataURL('image/png');
|
|
|
+
|
|
|
+ // 3. 给水印容器设置背景
|
|
|
+ const wrapper = document.querySelector('.watermark-wrapper');
|
|
|
+ if (wrapper) {
|
|
|
+ wrapper.style.backgroundImage = `url(${watermarkBase64})`;
|
|
|
+ wrapper.style.backgroundRepeat = 'repeat';
|
|
|
+ wrapper.style.backgroundSize = `${canvas.width}px ${canvas.height}px`;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 移除水印
|
|
|
+const removeWatermark = () => {
|
|
|
+ const wrapper = document.querySelector('.watermark-wrapper');
|
|
|
+ if (wrapper) {
|
|
|
+ wrapper.style.backgroundImage = 'none';
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 监听用户信息变化(登录/退出时重新生成水印)
|
|
|
+// watch(
|
|
|
+// () => userId,
|
|
|
+// () => {
|
|
|
+// removeWatermark();
|
|
|
+// createWatermark();
|
|
|
+// },
|
|
|
+// { immediate: true, deep: true }
|
|
|
+// );
|
|
|
+
|
|
|
+// 监听 isFixedScreen 变化,适配布局
|
|
|
+// watch(
|
|
|
+// () => props.isFixedScreen,
|
|
|
+// () => {
|
|
|
+// removeWatermark();
|
|
|
+// createWatermark();
|
|
|
+// }
|
|
|
+// );
|
|
|
+
|
|
|
+// 页面挂载时生成水印
|
|
|
+onMounted(() => {
|
|
|
+ createWatermark();
|
|
|
+});
|
|
|
+
|
|
|
+// 页面销毁时移除水印
|
|
|
+onUnmounted(() => {
|
|
|
+ removeWatermark();
|
|
|
+ if (removeWatermarkFn) {
|
|
|
+ removeWatermarkFn();
|
|
|
+ }
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.watermark-wrapper {
|
|
|
+ width: 100vw;
|
|
|
+ height: 100vh;
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ border: none;
|
|
|
+ background: transparent;
|
|
|
+}
|
|
|
+</style>
|