瀏覽代碼

feat:添加演示角色水印和禁止开发者模式

liuyuedi 2 年之前
父節點
當前提交
a159718c25
共有 4 個文件被更改,包括 264 次插入22 次删除
  1. 28 0
      src/components/WaterMark/index.vue
  2. 73 0
      src/components/WaterMark/js/devtools.js
  3. 132 0
      src/components/WaterMark/js/waterMark.js
  4. 31 22
      src/layout/index.vue

+ 28 - 0
src/components/WaterMark/index.vue

@@ -0,0 +1,28 @@
+<template>
+  <div class="water-mark" ref="waterMark"></div>
+</template>
+<script>
+import { watermarkText } from './js/waterMark';
+import './js/devtools';
+
+export default {
+  mounted() {
+    watermarkText(this.$refs.waterMark, '云飞科技', {
+      width: 200,
+      start: -30
+    });
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.water-mark {
+  position: fixed;
+  width: 100%;
+  height: 100vh;
+  left: 0;
+  top: 0;
+  pointer-events: none;
+  z-index: 1000;
+}
+</style>

+ 73 - 0
src/components/WaterMark/js/devtools.js

@@ -0,0 +1,73 @@
+(() => {
+  function block() {
+    if (
+      window.outerHeight - window.innerHeight > 200 ||
+      window.outerWidth - window.innerWidth > 200
+    ) {
+      document.body.innerHTML = '检测到非法调试,请关闭后刷新重试!';
+    }
+    // setInterval(() => {
+    //   (function () {
+    //     return false;
+    //   })
+    //     ['constructor']('debugger')
+    //     ['call']();
+    // }, 50);
+
+    setInterval(() => {
+      Function('debugger')();
+    }, 50);
+  }
+  try {
+    window.onkeydown =
+      window.onkeyup =
+      window.onkeypress =
+        function (event) {
+          // 判断是否按下F12,F12键码为123
+          if (event.keyCode === 123) {
+            event.preventDefault(); // 阻止默认事件行为
+            window.event.returnValue = false;
+          }
+        };
+
+    window.oncontextmenu = function () {
+      event.preventDefault(); // 阻止默认事件行为
+      return false;
+    };
+
+    block();
+  } catch (err) {}
+})();
+
+!(function () {
+  var _0x1cbb = ['tor', 'struc', 'call', 'ger', 'con', 'bug', 'de', 'apply'];
+  setInterval(check, 2e3);
+  function check() {
+    function doCheck(_0x1834ff) {
+      if (
+        ('' + _0x1834ff / _0x1834ff)['length'] !== 0x1 ||
+        _0x1834ff % 0x14 === 0x0
+      ) {
+        (function () {
+          return !![];
+        })
+          [_0x1cbb[0x4] + _0x1cbb[0x1] + _0x1cbb[0x0]](
+            _0x1cbb[0x6] + _0x1cbb[0x5] + _0x1cbb[0x3]
+          )
+          [_0x1cbb[0x2]]();
+      } else {
+        (function () {
+          return ![];
+        })
+          [_0x1cbb[0x4] + _0x1cbb[0x1] + _0x1cbb[0x0]](
+            _0x1cbb[0x6] + _0x1cbb[0x5] + _0x1cbb[0x3]
+          )
+          [_0x1cbb[0x7]]();
+      }
+      doCheck(++_0x1834ff);
+    }
+    try {
+      doCheck(0);
+    } catch (err) {}
+  }
+})();

+ 132 - 0
src/components/WaterMark/js/waterMark.js

@@ -0,0 +1,132 @@
+// 创建画布
+function createCanvas(width, height) {
+  // 创建一个画布
+  let canvas = document.createElement('canvas');
+  // 设置画布的宽高
+  canvas.width = width;
+  canvas.height = height;
+
+  return {
+    canvas,
+    ctx: canvas.getContext('2d')
+  };
+}
+
+// 填充水印
+function fillMark(canvas, html) {
+  html.style.pointerEvents = 'none';
+  html.style.background =
+    'url(' + canvas.toDataURL('image/png') + ') left top repeat';
+}
+
+// 文字水印生成
+export function watermarkText(html, str, options = {}) {
+  let {
+    fontSize = 18, // 设置字体大小
+    fontFamily = 'Vedana', // 设置字体
+    width = str.length * fontSize, // 设置画布的宽
+    height = 320, // 设置画布的高
+    color = 'rgba(0, 0, 0, 0.3)', // 设置填充绘画的颜色/渐变模式
+    angle = -25, // 旋转角度
+    textAlign = 'left', // 设置文本内容的对齐方式
+    font, // 设置字体及大小
+    textBaseline = 'Middle', // 设置文本基线
+    start = 0, // 开始绘制文本的X坐标位置
+    end = height / 1.2 // 开始绘制文本的Y坐标位置
+  } = options;
+
+  // 创建画布
+  let cans = createCanvas(width, height);
+  let canvas = cans.canvas;
+  let ctx = cans.ctx;
+  ctx.rotate((angle * Math.PI) / 180);
+  ctx.font = font || fontSize + 'px ' + fontFamily;
+  ctx.fillStyle = color;
+  ctx.textAlign = textAlign;
+  ctx.textBaseline = textBaseline;
+  // 在画布上绘制填色的文本(输出的文本,开始绘制文本的X坐标位置,开始绘制文本的Y坐标位置)
+  ctx.fillText(str, start, end);
+  // 填充水印
+  fillMark(canvas, html);
+}
+
+// 图片水印生成
+export function watermarkImg(html, options = {}) {
+  let {
+    width = 200, // 设置画布的宽
+    height = 120, // 设置画布的高
+    angle = -25, // 旋转角度
+    x = 0, // 放置图像的x坐标
+    y = height / 1.5, // 放置图像的y坐标
+    src = '' // 图片地址
+  } = options;
+
+  // 创建画布
+  let cans = createCanvas(width, height);
+  let canvas = cans.canvas;
+  let ctx = cans.ctx;
+  ctx.rotate((angle * Math.PI) / 180);
+  let img = new Image(); // 创建图片
+  img.onload = function (e) {
+    // 监听图片加载完成
+    ctx.drawImage(img, x, y, this.width, this.height);
+    // 填充水印
+    fillMark(canvas, html);
+  };
+  img.src = src;
+}
+
+export class SvgWay {
+  constructor(watermark) {
+    this.watermark = watermark;
+  }
+
+  render() {
+    const { txt, x, y, width, height, color, font, fontSize, alpha, angle } =
+      this.watermark;
+    const svgStr = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}px" height="${height}px">
+                <text x="${x}px" y="${y}px" dy="${fontSize}px"
+                    text-anchor="start"
+                    stroke="${color}"
+                    stroke-opacity="${alpha}"
+                    fill="none"
+                    transform="rotate(${angle},${x} ${y})"
+                    font-weight="100"
+                    font-size="${fontSize}"
+                    font-family="${font}"
+                    >
+                    ${txt}
+                </text>
+            </svg>`;
+    return `data:image/svg+xml;base64,${window.btoa(
+      unescape(encodeURIComponent(svgStr))
+    )}`;
+  }
+}
+
+export class CanvasWay {
+  constructor(watermark) {
+    this.watermark = watermark;
+    const { width, height } = watermark;
+    this.canvas = document.createElement('canvas');
+    this.canvas.setAttribute('width', width);
+    this.canvas.setAttribute('height', height);
+  }
+
+  render() {
+    const { txt, x, y, width, height, font, color, fontSize, alpha, angle } =
+      this.watermark;
+    const ctx = this.canvas.getContext('2d');
+    ctx.clearRect(0, 0, width, height);
+    ctx.textBaseline = 'top';
+    ctx.textAlign = 'left';
+    ctx.fillStyle = color;
+    ctx.globalAlpha = alpha;
+    ctx.font = `${fontSize}px ${font}`;
+    ctx.translate(x, y);
+    ctx.rotate((Math.PI / 180) * angle);
+    ctx.translate(-x, -y - fontSize);
+    ctx.fillText(txt, x, y + fontSize);
+    return this.canvas.toDataURL();
+  }
+}

+ 31 - 22
src/layout/index.vue

@@ -1,27 +1,30 @@
 <template>
-  <div
-    :class="classObj"
-    class="app-wrapper"
-    :style="{ '--current-color': theme }"
-  >
+  <div>
+    <WaterMark v-if="userRegion == 'EXPERIENCE'" />
     <div
-      v-if="device === 'mobile' && sidebar.opened"
-      class="drawer-bg"
-      @click="handleClickOutside"
-    />
-    <sidebar v-if="!sidebar.hide" class="sidebar-container" />
-    <div
-      :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }"
-      class="main-container"
+      :class="classObj"
+      class="app-wrapper"
+      :style="{ '--current-color': theme }"
     >
-      <div :class="{ 'fixed-header': fixedHeader }">
-        <navbar />
-        <tags-view v-if="needTagsView" />
+      <div
+        v-if="device === 'mobile' && sidebar.opened"
+        class="drawer-bg"
+        @click="handleClickOutside"
+      />
+      <sidebar v-if="!sidebar.hide" class="sidebar-container" />
+      <div
+        :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }"
+        class="main-container"
+      >
+        <div :class="{ 'fixed-header': fixedHeader }">
+          <navbar />
+          <tags-view v-if="needTagsView" />
+        </div>
+        <app-main />
+        <right-panel>
+          <settings />
+        </right-panel>
       </div>
-      <app-main />
-      <right-panel>
-        <settings />
-      </right-panel>
     </div>
   </div>
 </template>
@@ -32,6 +35,7 @@ import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components';
 import ResizeMixin from './mixin/ResizeHandler';
 import { mapState } from 'vuex';
 import variables from '@/assets/styles/variables.scss';
+import WaterMark from '@/components/WaterMark';
 
 export default {
   name: 'Layout',
@@ -41,7 +45,8 @@ export default {
     RightPanel,
     Settings,
     Sidebar,
-    TagsView
+    TagsView,
+    WaterMark
   },
   mixins: [ResizeMixin],
   computed: {
@@ -51,7 +56,8 @@ export default {
       sidebar: (state) => state.app.sidebar,
       device: (state) => state.app.device,
       needTagsView: (state) => state.settings.tagsView,
-      fixedHeader: (state) => state.settings.fixedHeader
+      fixedHeader: (state) => state.settings.fixedHeader,
+      userInfo: (state) => state.user.userInfo
     }),
     classObj() {
       return {
@@ -65,6 +71,9 @@ export default {
       return variables;
     }
   },
+  created() {
+    this.userRegion = this.userInfo.userRegion;
+  },
   methods: {
     handleClickOutside() {
       this.$store.dispatch('app/closeSideBar', { withoutAnimation: false });