From 9497450d58a0240916271e5a9f167bacee2e7d1e Mon Sep 17 00:00:00 2001 From: wangjiahao <1522128093@qq.com> Date: Mon, 8 Jan 2024 18:34:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8F=AF=E8=A7=86=E5=8C=96=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E6=94=AF=E6=8C=81=E6=98=BE=E7=A4=BA=E6=B0=B4=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/core-frontend/src/api/user.ts | 2 + .../data-visualization/canvas/DePreview.vue | 33 ++- .../src/components/watermark/watermark.ts | 195 ++++++++++++++++++ .../io/dataease/api/system/SystemInfoApi.java | 8 + .../api/permissions/user/vo/UserFormVO.java | 3 + 5 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 core/core-frontend/src/components/watermark/watermark.ts create mode 100644 sdk/api/api-base/src/main/java/io/dataease/api/system/SystemInfoApi.java diff --git a/core/core-frontend/src/api/user.ts b/core/core-frontend/src/api/user.ts index d02e0a227a..21299075ea 100644 --- a/core/core-frontend/src/api/user.ts +++ b/core/core-frontend/src/api/user.ts @@ -77,3 +77,5 @@ export const defaultPwdApi = () => request.get({ url: '/user/defaultPwd' }) export const resetPwdApi = uid => request.post({ url: `/user/resetPwd/${uid}` }) export const switchEnableApi = data => request.post({ url: '/user/enable', data }) + +export const userLoginInfo = () => request.get({ url: '/user/userLoginInfo' }) diff --git a/core/core-frontend/src/components/data-visualization/canvas/DePreview.vue b/core/core-frontend/src/components/data-visualization/canvas/DePreview.vue index 684da1ad21..39a92dcb26 100644 --- a/core/core-frontend/src/components/data-visualization/canvas/DePreview.vue +++ b/core/core-frontend/src/components/data-visualization/canvas/DePreview.vue @@ -2,7 +2,7 @@ import { getCanvasStyle, getShapeItemStyle } from '@/utils/style' import ComponentWrapper from './ComponentWrapper.vue' import { changeStyleWithScale } from '@/utils/translate' -import { computed, nextTick, onMounted, ref, toRefs, watch, onBeforeUnmount } from 'vue' +import { computed, nextTick, ref, toRefs, watch, onBeforeUnmount, onMounted } from 'vue' import { changeRefComponentsSizeWithScale } from '@/utils/changeComponentsSizeWithScale' import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain' import { storeToRefs } from 'pinia' @@ -10,6 +10,8 @@ import elementResizeDetectorMaker from 'element-resize-detector' import UserViewEnlarge from '@/components/visualization/UserViewEnlarge.vue' import CanvasOptBar from '@/components/visualization/CanvasOptBar.vue' import { isMainCanvas } from '@/utils/canvasUtils' +import { activeWatermark } from '@/components/watermark/watermark' +import { userLoginInfo } from '@/api/user' const dvMainStore = dvMainStoreWithOut() const { pcMatrixCount, curComponent } = storeToRefs(dvMainStore) @@ -68,6 +70,7 @@ const cellHeight = ref(10) const userViewEnlargeRef = ref(null) const searchCount = ref(0) const refreshTimer = ref(null) +const userInfo = ref(null) const dashboardActive = computed(() => { return dvInfo.value.type === 'dashboard' @@ -172,6 +175,33 @@ const initRefreshTimer = () => { } } +const initWatermark = () => { + if (dvInfo.value.watermarkInfo) { + nextTick(() => { + if (userInfo.value) { + activeWatermark( + dvInfo.value.watermarkInfo.settingContent, + userInfo.value, + 'canvasInfo-main', + canvasId.value, + dvInfo.value.watermarkOpen + ) + } else { + userLoginInfo().then(res => { + userInfo.value = res.data + activeWatermark( + dvInfo.value.watermarkInfo.settingContent, + userInfo.value, + 'canvasInfo-main', + canvasId.value, + dvInfo.value.watermarkOpen + ) + }) + } + }) + } +} + onMounted(() => { initRefreshTimer() restore() @@ -180,6 +210,7 @@ onMounted(() => { erd.listenTo(document.getElementById(domId), () => { restore() }) + initWatermark() }) onBeforeUnmount(() => { diff --git a/core/core-frontend/src/components/watermark/watermark.ts b/core/core-frontend/src/components/watermark/watermark.ts new file mode 100644 index 0000000000..a179606ae2 --- /dev/null +++ b/core/core-frontend/src/components/watermark/watermark.ts @@ -0,0 +1,195 @@ +// 动态创建水印元素的封装函数 + +export function watermark(settings, domId) { + const watermarkDom = document.getElementById(domId) + // 默认设置 + const defaultSettings = { + watermark_txt: '', + watermark_x: 20, // 水印起始位置x轴坐标 + watermark_y: 20, // 水印起始位置Y轴坐标 + watermark_rows: 20, // 水印行数 + watermark_cols: 20, // 水印列数 + watermark_x_space: 100, // 水印x轴间隔 + watermark_y_space: 50, // 水印y轴间隔 + watermark_color: '#aaa', // 水印字体颜色 + watermark_alpha: 0.4, // 水印透明度 + watermark_fontsize: '15px', // 水印字体大小 + watermark_font: '微软雅黑', // 水印字体 + watermark_width: 210, // 水印宽度 + watermark_height: 80, // 水印长度 + watermark_angle: 20 // 水印倾斜度数 + } + // 根据函数的入参调整设置 + if (settings && typeof settings === 'object') { + const src = settings || {} + for (const key in src) { + if (src[key] && defaultSettings[key] && src[key] === defaultSettings[key]) { + continue + } else if (src[key]) defaultSettings[key] = src[key] + } + } + // 创建虚拟节点对象,在该节点对象中可以放元素,最后只需在页面中添加该节点对象即可。可提高性能 + const oTemp = document.createElement('p') + // 获取页面最大宽度 + let page_width = watermarkDom.clientWidth + const cutWidth = page_width * 0.015 + page_width = page_width - cutWidth + // 获取页面最大高度 + let page_height = watermarkDom.clientHeight - 56 + page_height = page_height < 400 ? 400 : page_height + // page_height = Math.max(page_height, window.innerHeight - 30) + // 如果将水印列数设置为0,或水印列数设置过大,超过页面最大宽度,则重新计算水印列数和水印x轴间隔 + if ( + defaultSettings.watermark_cols === 0 || + parseInt( + defaultSettings.watermark_x + + defaultSettings.watermark_width * defaultSettings.watermark_cols + + defaultSettings.watermark_x_space * (defaultSettings.watermark_cols - 1) + ) > page_width + ) { + defaultSettings.watermark_cols = parseInt( + (page_width - defaultSettings.watermark_x + defaultSettings.watermark_x_space) / + (defaultSettings.watermark_width + defaultSettings.watermark_x_space) + ) + defaultSettings.watermark_x_space = parseInt( + (page_width - + defaultSettings.watermark_x - + defaultSettings.watermark_width * defaultSettings.watermark_cols) / + (defaultSettings.watermark_cols - 1) + ) + } + // 如果将水印行数设置为0,或水印行数设置过大,超过页面最大长度,则重新计算水印行数和水印y轴间隔 + if ( + defaultSettings.watermark_rows === 0 || + parseInt( + defaultSettings.watermark_y + + defaultSettings.watermark_height * defaultSettings.watermark_rows + + defaultSettings.watermark_y_space * (defaultSettings.watermark_rows - 1) + ) > page_height + ) { + defaultSettings.watermark_rows = parseInt( + (defaultSettings.watermark_y_space + page_height - defaultSettings.watermark_y) / + (defaultSettings.watermark_height + defaultSettings.watermark_y_space) + ) + defaultSettings.watermark_y_space = parseInt( + (page_height - + defaultSettings.watermark_y - + defaultSettings.watermark_height * defaultSettings.watermark_rows) / + (defaultSettings.watermark_rows - 1) + ) + } + defaultSettings.watermark_rows = + defaultSettings.watermark_rows < 2 ? 2 : defaultSettings.watermark_rows + defaultSettings.watermark_cols = + defaultSettings.watermark_cols < 2 ? 2 : defaultSettings.watermark_cols + let x + let y + for (let i = 0; i < defaultSettings.watermark_rows; i++) { + y = + defaultSettings.watermark_y + + (defaultSettings.watermark_y_space + defaultSettings.watermark_height) * i + for (let j = 0; j < defaultSettings.watermark_cols; j++) { + x = + defaultSettings.watermark_x + + (defaultSettings.watermark_width + defaultSettings.watermark_x_space) * j + const mask_div = document.createElement('div') + mask_div.id = 'mask_div' + i + j + mask_div.className = 'mask_div' + mask_div.appendChild(document.createTextNode(defaultSettings.watermark_txt)) + // 设置水印div倾斜显示 + mask_div.style.webkitTransform = 'rotate(-' + defaultSettings.watermark_angle + 'deg)' + mask_div.style.MozTransform = 'rotate(-' + defaultSettings.watermark_angle + 'deg)' + mask_div.style.msTransform = 'rotate(-' + defaultSettings.watermark_angle + 'deg)' + mask_div.style.OTransform = 'rotate(-' + defaultSettings.watermark_angle + 'deg)' + mask_div.style.transform = 'rotate(-' + defaultSettings.watermark_angle + 'deg)' + mask_div.style.visibility = '' + mask_div.style.position = 'absolute' + mask_div.style.left = x + 'px' + mask_div.style.top = y + 'px' + mask_div.style.overflow = 'hidden' + mask_div.style.zIndex = '10' + // 让水印不遮挡页面的点击事件 + mask_div.style.pointerEvents = 'none' + mask_div.style.opacity = defaultSettings.watermark_alpha + mask_div.style.fontSize = defaultSettings.watermark_fontsize + mask_div.style.fontFamily = defaultSettings.watermark_font + mask_div.style.color = defaultSettings.watermark_color + mask_div.style.textAlign = 'center' + mask_div.style.width = defaultSettings.watermark_width + 'px' + mask_div.style.height = defaultSettings.watermark_height + 'px' + mask_div.style.display = 'block' + oTemp.appendChild(mask_div) + } + } + oTemp.setAttribute('id', 'de-watermark-server') + watermarkDom.appendChild(oTemp) +} + +export function getNow() { + const d = new Date() + const year = d.getFullYear() + const month = change(d.getMonth() + 1) + const day = change(d.getDate()) + const hour = change(d.getHours()) + const minute = change(d.getMinutes()) + + function change(t) { + if (t < 10) { + return '0' + t + } else { + return t + } + } + + const time = year + '-' + month + '-' + day + ' ' + hour + ':' + minute + return time +} + +export function activeWatermark(watermarkForm, userLoginInfo, domId, canvasId, watermarkOpen) { + // 清理历史水印 + const historyWatermarkDom = document.getElementById('de-watermark-server') + if (historyWatermarkDom) { + historyWatermarkDom.remove() + } + if ( + !( + canvasId === 'canvas-main' && + ((watermarkForm.enable && !watermarkForm.enablePanelCustom) || + (watermarkForm.enable && watermarkOpen)) + ) + ) { + return + } + let watermark_txt + let watermark_width = 120 + if (watermarkForm.type === 'custom') { + watermark_txt = watermarkForm.content + watermark_txt = watermark_txt.replaceAll('${ip}', userLoginInfo.ip) + watermark_txt = watermark_txt.replaceAll('${username}', userLoginInfo.userInfo.username) + watermark_txt = watermark_txt.replaceAll('${nickName}', userLoginInfo.userInfo.nickName) + watermark_txt = watermark_txt.replaceAll('${time}', getNow()) + watermark_width = watermark_txt.length * watermarkForm.watermark_fontsize * 0.75 + watermark_width = watermark_width > 350 ? 350 : watermark_width + } else if (watermarkForm.type === 'nickName') { + watermark_txt = userLoginInfo.userInfo.nickName + } else if (watermarkForm.type === 'ip') { + watermark_txt = userLoginInfo.ip + watermark_width = 150 + } else if (watermarkForm.type === 'time') { + watermark_txt = getNow() + watermark_width = 200 + } else { + watermark_txt = userLoginInfo.userInfo.username + } + const settings = { + watermark_txt: watermark_txt, + watermark_width: watermark_width, + watermark_color: watermarkForm.watermark_color, + watermark_x_space: watermarkForm.watermark_x_space, + watermark_y_space: watermarkForm.watermark_y_space, + watermark_fontsize: watermarkForm.watermark_fontsize + 'px' + } + watermark(settings, domId) +} + +export default { watermark, getNow, activeWatermark } diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/system/SystemInfoApi.java b/sdk/api/api-base/src/main/java/io/dataease/api/system/SystemInfoApi.java new file mode 100644 index 0000000000..8997c0f90a --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/system/SystemInfoApi.java @@ -0,0 +1,8 @@ +package io.dataease.api.system; + +/** + * @author : WangJiaHao + * @date : 2024/1/8 18:12 + */ +public class SystemInfoApi { +} diff --git a/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/user/vo/UserFormVO.java b/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/user/vo/UserFormVO.java index a525097ac5..71ac75fb92 100644 --- a/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/user/vo/UserFormVO.java +++ b/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/user/vo/UserFormVO.java @@ -36,4 +36,7 @@ public class UserFormVO implements Serializable { @Schema(description = "电话") private String phone; + + @Schema(description = "IP") + private String ip; }