当前位置: 首页 > news >正文

vue2添加背景水印-手动实现(无组件模式)

1. App.vue

<template>
  <div id="app" class="app">
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  mounted() {
    this.updateWatermark();
    // 监听路由变化
    this.$router.afterEach(() => {
      this.$nextTick(() => {
        this.ensureWatermarkAndTable();
      });
    });
    // 监听 DOM 变化,确保表格背景实时调整
    this.observeDOM();
  },
  data() {
    return {
      watermarkText: "",
      user: {},
    };
  },
  methods: {
    updateWatermark() {
      let curUser = sessionStorage.getItem("curUser");
      if (curUser) {
        try {
          const userData = JSON.parse(curUser);
          this.watermarkText = `${userData.systemUsers.nickname}(${userData.systemRoleList[0].name})`;
        } catch (e) {
          console.error("解析 curUser 失败:", e);
          this.watermarkText = "默认水印"; // 备用文本
        }
      } else {
        this.watermarkText = "默认水印"; // 无用户数据时使用默认值
      }
      console.log("水印文本:", this.watermarkText);
      this.addWatermark();
    },
    addWatermark() {
      const oldWatermark = document.querySelector(".watermark-layer");
      if (oldWatermark) oldWatermark.remove();

      const canvas = document.createElement("canvas");
      canvas.width = 200;
      canvas.height = 200;
      const ctx = canvas.getContext("2d");
      ctx.font = "16px Arial";
      ctx.fillStyle = "rgba(102, 102, 102, 0.5)";
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      ctx.rotate((-20 * Math.PI) / 180);
      ctx.fillText(this.watermarkText, canvas.width / 2, canvas.height / 2);
      const dataURL = canvas.toDataURL();

      const watermarkLayer = document.createElement("div");
      watermarkLayer.className = "watermark-layer";
      watermarkLayer.style.backgroundImage = `url(${dataURL})`;
      watermarkLayer.style.backgroundRepeat = "repeat";
      document.body.appendChild(watermarkLayer);
    },
    ensureWatermarkAndTable() {
      if (!document.querySelector(".watermark-layer")) {
        this.addWatermark();
      }
      this.adjustTableBackground();
    },
    adjustTableBackground() {
      const tables = document.querySelectorAll(".el-table");
      tables.forEach((table) => {
        table.style.backgroundColor = "rgba(255, 255, 255, 0.8)";
        const wrappers = table.querySelectorAll(".el-table__body-wrapper, .el-table__header-wrapper, .el-table__fixed, .el-table__fixed-right");
        wrappers.forEach((wrapper) => {
          wrapper.style.backgroundColor = "rgba(255, 255, 255, 0.8)";
        });
        const cells = table.querySelectorAll("th, td, tr");
        cells.forEach((cell) => {
          cell.style.backgroundColor = "transparent";
        });
      });
    },
    observeDOM() {
      const observer = new MutationObserver(() => {
        this.ensureWatermarkAndTable();
      });
      observer.observe(document.body, {
        childList: true,
        subtree: true,
      });
    },
  },
};
</script>

<style>
.app {
  width: 100vw;
  height: 100vh;
  position: relative;
  z-index: 1;
  color: #333;
}

.watermark-layer {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 0;
  pointer-events: none;
}

body {
  margin: 0;
  padding: 0;
  position: relative;
}

html,
body,
h3,
p {
  margin: 0;
  padding: 0;
}
</style>

2. src/assets/css/main.css

/* src/assets/css/main.css */
.el-table,
.el-table__body-wrapper,
.el-table__header-wrapper,
.el-table__fixed,
.el-table__fixed-right,
.el-table__body,
.el-table__header {
  background-color: rgba(255, 255, 255, 0.8) !important;
}

.el-table th,
.el-table tr,
.el-table td,
.el-table__cell {
  background-color: transparent !important;
}

.watermark-layer {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 0 !important;
  pointer-events: none;
}

3. main.js

import Vue from "vue";
import App from "./App.vue";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
import router from "./router/index";
import store from "./store/index";
import * as echarts from "echarts";
import JsonViewer from "vue-json-viewer";
import VueCron from "vue-cron";
import VideoPlayer from "vue-video-player/src";
import "vue-video-player/src/custom-theme.css";
import "video.js/dist/video-js.css";
import "./assets/css/content.css";
import "./assets/css/main.css"; // 确保引入

Vue.prototype.$echarts = echarts;
Vue.use(JsonViewer);
Vue.use(VueCron);
Vue.use(VideoPlayer);
Vue.use(ElementUI);

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  render: (h) => h(App),
  created() {
    store.commit("addMenu", router);
  },
}).$mount("#app");

4.实现效果

http://www.dtcms.com/a/123291.html

相关文章:

  • 4月10(信息差)
  • linux系统下如何提交git和调试
  • +++++背到厌倦。持续更新
  • python基础语法:缩进规则
  • netty中的ChannelPipeline详解
  • 认知风险→风险转移→保障未来
  • AUTOSAR图解=>AUTOSAR_SWS_TimeSyncOverEthernet
  • C++: unordered_map、unordered_set
  • 3DGS之光栅化
  • Python爬虫第10节-lxml解析库用 XPath 解析网页
  • 【Pandas】pandas DataFrame head
  • C#容器源码分析 --- List
  • Web前端之Vue+Element实现表格动态不同列合并多行、localeCompare、forEach、table、push、sort、Map
  • 每日算法-250410
  • 队列缓冲最新请求结合线程池的优化方案
  • STM32Cubemx-H7-14-Bootloader(上)-ST和串口烧录
  • django寻味美食分享与交流网站-计算机毕业设计源码74984
  • 重载和重写的区别
  • 年龄增长,特发性震颤为何愈发严重 ?
  • 详解如何从零用 Python复现类似 GPT-4o 的多模态模型
  • [ctfshow web入门] web38
  • 背包问题(java)实现
  • GPU通讯-基础篇
  • 跨境全域中台:前端独立站群+后端共享云仓的协同作战体系
  • 【云服务管理】
  • MySQL SQL Mode
  • Spring Boot MongoDB自定义连接池配置
  • 十分钟机器学习之--------------线性回归
  • 关于 Spring Boot 后端项目使用 Maven 打包命令、JAR/WAR 对比、内嵌服务器与第三方服务器对比,以及热部署配置的详细说明
  • 雷池WAF身份认证 - CAS