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

1. App.vue

javascript 复制代码
<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

javascript 复制代码
/* 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

javascript 复制代码
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.实现效果

相关推荐
zx132321 分钟前
chrome提示https不安全, 不能记住账号密码怎么办? 可以利用js输入账号
开发语言·javascript·ecmascript
巴巴_羊44 分钟前
React Redux
开发语言·前端·javascript
Mintopia1 小时前
Node.js 中的this
前端·javascript·node.js
Mintopia1 小时前
深入理解 Three.js 中 Shader 的使用及示例
前端·javascript·three.js
爱生活的前端狗1 小时前
一次大批量处理视频文件的性能优化记录
前端·javascript·vue.js
Riesenzahn1 小时前
React Hooks 的优势和使用场景
前端·javascript
韩振方1 小时前
为什么 scroll 事件无法被 e.preventDefault 阻止?
前端·javascript·css
HuaHua的世界1 小时前
watch和watchEffect的区别?
前端·vue.js
叶小秋1 小时前
每日前端小技巧 - 客户端缓存封装
前端·javascript
wangyongquan1 小时前
js 数据类型判断底层逻辑是如何实现的
javascript·面试