refactor: 可视化资源树水印等样式逻辑调整

This commit is contained in:
wangjiahao 2024-01-11 10:40:40 +08:00
parent 60e9d88ba9
commit 1ce8f6418c
11 changed files with 461 additions and 2 deletions

View File

@ -0,0 +1,41 @@
package io.dataease.visualization.server;
import io.dataease.api.visualization.VisualizationWatermarkApi;
import io.dataease.api.visualization.request.VisualizationWatermarkRequest;
import io.dataease.api.visualization.vo.VisualizationWatermarkVO;
import io.dataease.utils.BeanUtils;
import io.dataease.visualization.dao.auto.entity.VisualizationWatermark;
import io.dataease.visualization.dao.auto.mapper.VisualizationWatermarkMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author : WangJiaHao
* @date : 2024/1/10 16:59
*/
@RestController
@RequestMapping("/watermark")
public class VisualizationWatermarkService implements VisualizationWatermarkApi {
private final static String DEFAULT_ID ="system_default";
@Resource
private VisualizationWatermarkMapper watermarkMapper;
@Override
public VisualizationWatermarkVO getWatermarkInfo() {
VisualizationWatermark watermark = watermarkMapper.selectById(DEFAULT_ID);
VisualizationWatermarkVO watermarkVO = new VisualizationWatermarkVO();
return BeanUtils.copyBean(watermarkVO,watermark);
}
@Override
public void saveWatermarkInfo(VisualizationWatermarkRequest watermarkRequest) {
VisualizationWatermark watermark = new VisualizationWatermark();
BeanUtils.copyBean(watermark,watermarkRequest);
watermark.setId(DEFAULT_ID);
watermarkMapper.updateById(watermark);
}
}

View File

@ -0,0 +1,12 @@
DROP TABLE IF EXISTS `visualization_watermark`;
CREATE TABLE `visualization_watermark` (
`id` varchar(50) NOT NULL COMMENT '主键',
`version` varchar(255) DEFAULT NULL COMMENT '版本号',
`setting_content` longtext COMMENT '设置内容',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`create_time` bigint(13) DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) COMMENT='仪表板水印设置表';
INSERT INTO `visualization_watermark` (`id`, `version`, `setting_content`, `create_by`, `create_time`) VALUES ('system_default', '1.0', '{\"enable\":false,\"enablePanelCustom\":true,\"type\":\"custom\",\"content\":\"水印\",\"watermark_color\":\"#DD1010\",\"watermark_x_space\":12,\"watermark_y_space\":36,\"watermark_fontsize\":15}', 'admin', NULL);

View File

@ -0,0 +1,12 @@
DROP TABLE IF EXISTS `visualization_watermark`;
CREATE TABLE `visualization_watermark` (
`id` varchar(50) NOT NULL COMMENT '主键',
`version` varchar(255) DEFAULT NULL COMMENT '版本号',
`setting_content` longtext COMMENT '设置内容',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`create_time` bigint(13) DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) COMMENT='仪表板水印设置表';
INSERT INTO `visualization_watermark` (`id`, `version`, `setting_content`, `create_by`, `create_time`) VALUES ('system_default', '1.0', '{\"enable\":false,\"enablePanelCustom\":true,\"type\":\"custom\",\"content\":\"水印\",\"watermark_color\":\"#DD1010\",\"watermark_x_space\":12,\"watermark_y_space\":36,\"watermark_fontsize\":15}', 'admin', NULL);

View File

@ -1,4 +1,5 @@
import request from '@/config/axios'
export const searchRoleApi = (keyword: string) =>
request.post({ url: '/role/query', data: { keyword } })
export const watermarkSave = params => request.post({ url: '/watermark/save', data: params })
export const watermarkFind = () => request.get({ url: 'watermark/find' })

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

View File

@ -2131,5 +2131,24 @@ export default {
template_manage: {
name_already_exists_type: '分类名称已存在',
the_same_category: '同一分类下该模板名称已存在'
},
watermark: {
support_params: '当前支持的参数',
enable: '启用水印',
enable_panel_custom: '允许仪表板单独打开或者关闭水印',
content: '水印内容',
custom_content: '自定义公式',
account: '账号',
nick_name: '昵称',
ip: 'IP',
now: '当前时间',
watermark_color: '水印颜色',
watermark_font_size: '水印字号',
watermark_space: '水印间距',
horizontal: '横向间距',
vertical: '纵向间距',
reset: '重置',
preview: '预览',
save: '保存'
}
}

View File

@ -0,0 +1,33 @@
<template>
<div class="tips-class">
<el-tooltip class="item" effect="dark" placement="bottom">
<template #content>
<div>
<span>{{ t('watermark.support_params') }}</span
><br />
<span>${username}-{{ t('watermark.account') }}</span
><br />
<span>${nickName}-{{ t('watermark.nick_name') }}</span
><br />
<span>${time}-{{ t('watermark.now') }}</span
><br />
<span>${ip}-IP</span><br />
</div>
</template>
<span><i class="el-icon-warning" /></span>
</el-tooltip>
</div>
</template>
<script setup lang="ts">
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
</script>
<style scoped lang="less">
.tips-class {
position: absolute;
right: 10px;
z-index: 10;
}
</style>

View File

@ -0,0 +1,304 @@
<template xmlns:el-col="http://www.w3.org/1999/html">
<p class="router-title">水印管理</p>
<el-row class="watermark-table__content">
<el-row class="watermark-main-outer">
<el-col class="main-col-left" :span="12">
<el-form ref="watermarkForm" :model="state.watermarkForm" label-width="120px" size="middle">
<el-form-item :label="t('watermark.enable')" style="text-align: left">
<el-switch
size="middle"
v-model="state.watermarkForm.enable"
@change="enableChange"
></el-switch>
</el-form-item>
<el-form-item label="" style="text-align: left">
<el-checkbox
:disabled="!state.watermarkForm.enable"
v-model="state.watermarkForm.enablePanelCustom"
></el-checkbox>
{{ t('watermark.enable_panel_custom') }}
</el-form-item>
<el-form-item :label="t('watermark.content')" style="text-align: left">
<el-select :disabled="!state.watermarkForm.enable" v-model="state.watermarkForm.type">
<el-option :label="t('watermark.custom_content')" value="custom" />
<el-option :label="t('watermark.account')" value="userName" />
<el-option :label="t('watermark.nick_name')" value="nickName" />
<el-option :label="t('watermark.ip')" value="ip" />
<el-option :label="t('watermark.now')" value="time" />
</el-select>
</el-form-item>
<el-form-item
label=""
v-show="state.watermarkForm.type === 'custom'"
style="text-align: left"
>
<params-tips></params-tips>
<el-input
:disabled="!state.watermarkForm.enable"
v-model="state.watermarkForm.content"
type="textarea"
:autosize="{ minRows: 4, maxRows: 4 }"
/>
</el-form-item>
<el-form-item :label="t('watermark.watermark_color')" style="text-align: left">
<el-color-picker
:disabled="!state.watermarkForm.enable"
v-model="state.watermarkForm.watermark_color"
:predefine="state.predefineColors"
size="middle"
/>
</el-form-item>
<el-form-item :label="t('watermark.watermark_font_size')" style="text-align: left">
<el-input-number
:disabled="!state.watermarkForm.enable"
v-model="state.watermarkForm.watermark_fontsize"
:min="12"
:max="32"
size="middle"
/>
px
</el-form-item>
<el-form-item :label="t('watermark.horizontal')" style="text-align: left">
<el-input-number
:disabled="!state.watermarkForm.enable"
v-model="state.watermarkForm.watermark_x_space"
:min="10"
:max="400"
/>
px
</el-form-item>
<el-form-item :label="t('watermark.vertical')" style="text-align: left">
<el-input-number
:disabled="!state.watermarkForm.enable"
v-model="state.watermarkForm.watermark_y_space"
:min="10"
:max="400"
/>
px
</el-form-item>
</el-form>
<el-row style="margin-left: 53px; text-align: left">
<el-button size="middle" type="i" @click="cancel">{{ t('watermark.reset') }} </el-button>
<el-button size="middle" type="info" @click="preview"
>{{ t('watermark.preview') }}
</el-button>
<el-button type="primary" size="middle" @click="save"
>{{ t('watermark.save') }}
</el-button>
</el-row>
</el-col>
<el-col :span="12" style="height: 100%">
<div
id="watermark-demo"
style="position: relative; width: 100%; height: 100%; padding: 20px"
>
<div class="demo-preview">
<img style="height: 100%" src="@/assets/img/watermark-demo-light.png" />
</div>
<div class="demo-preview" style="margin-top: 15px">
<img style="height: 100%" src="@/assets/img/watermark-demo-dark.png" />
</div>
</div>
</el-col>
</el-row>
</el-row>
</template>
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { watermarkFind, watermarkSave } from '@/api/watermark'
import { ElMessage } from 'element-plus-secondary/es'
import { personInfoApi } from '@/api/user'
import { getNow, watermark } from '@/components/watermark/watermark'
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
const state = reactive({
userLoginInfo: {
username: '',
nickName: '',
ip: ''
},
cmOption: {
tabSize: 2,
styleActiveLine: true,
lineNumbers: true,
line: true,
mode: 'text/x-textile',
theme: 'solarized',
hintOptions: {
//
completeSingle: false //
}
},
watermarkFormSource: null,
predefineColors: [
'#ff4500',
'#ff8c00',
'#ffd700',
'#90ee90',
'#00ced1',
'#1e90ff',
'#c71585',
'#999999',
'#000000',
'#FFFFFF'
],
watermarkForm: {
enable: false,
enablePanelCustom: false,
type: 'userName',
content: '${time}-${ip}-${nickName}',
watermark_color: '#999999',
watermark_x_space: 100,
watermark_y_space: 100,
watermark_fontsize: 20
}
})
const enableChange = val => {
initWatermark()
}
const preview = () => {
initWatermark()
}
const cancel = () => {
state.watermarkForm = { ...state.watermarkFormSource }
const params = {
settingContent: JSON.stringify(state.watermarkForm)
}
watermarkSave(params).then(rsp => {
//ignore
})
initWatermark()
}
const save = () => {
const params = {
settingContent: JSON.stringify(state.watermarkForm)
}
watermarkSave(params).then(rsp => {
ElMessage.success('保存成功')
})
}
const findData = callback => {
watermarkFind().then(rsp => {
callback(rsp)
})
}
const findUserData = callback => {
personInfoApi().then(rsp => {
callback(rsp)
})
}
const initData = () => {
findData(res => {
state.watermarkForm = JSON.parse(res.data.settingContent)
state.watermarkFormSource = { ...state.watermarkForm }
initWatermark()
})
}
const initWatermark = () => {
let watermark_txt
let watermark_width = 120
if (state.watermarkForm.type === 'custom') {
watermark_txt = state.watermarkForm.content
watermark_txt = watermark_txt.replaceAll('${ip}', state.userLoginInfo.ip)
watermark_txt = watermark_txt.replaceAll('${username}', state.userLoginInfo.name)
watermark_txt = watermark_txt.replaceAll('${nickName}', state.userLoginInfo.account)
watermark_txt = watermark_txt.replaceAll('${time}', getNow())
watermark_width = watermark_txt.length * state.watermarkForm.watermark_fontsize * 0.75
watermark_width = watermark_width > 350 ? 350 : watermark_width
} else if (state.watermarkForm.type === 'nickName') {
watermark_txt = state.userLoginInfo.account
} else if (state.watermarkForm.type === 'ip') {
watermark_txt = state.userLoginInfo.ip
watermark_width = watermark_txt.length * state.watermarkForm.watermark_fontsize + 30
} else if (state.watermarkForm.type === 'time') {
watermark_txt = getNow()
watermark_width = 200
} else {
watermark_txt = state.userLoginInfo.name
}
const settings = {
watermark_enable: state.watermarkForm.enable,
watermark_txt: watermark_txt,
watermark_width: watermark_width,
watermark_color: state.watermarkForm.watermark_color,
watermark_x_space: state.watermarkForm.watermark_x_space,
watermark_y_space: state.watermarkForm.watermark_y_space,
watermark_fontsize: state.watermarkForm.watermark_fontsize + 'px'
}
//
const historyWatermarkDom = document.getElementById('de-watermark-server')
if (historyWatermarkDom) {
historyWatermarkDom.remove()
}
if (state.watermarkForm.enable) {
watermark(settings, 'watermark-demo')
}
}
onMounted(() => {
findUserData(res => {
state.userLoginInfo = res.data
initData()
})
})
</script>
<style lang="less" scoped>
.demo-preview {
height: calc(50vh - 130px);
width: 100%;
float: left;
overflow-x: auto;
overflow-y: hidden;
text-align: center;
}
.main-col-left {
overflow-y: auto;
min-width: 240px;
padding-right: 20px;
padding-top: 20px;
height: 100%;
border-right: 1px solid gainsboro;
}
.watermark-main-outer {
border: 1px solid gainsboro;
height: calc(100vh - 180px);
min-width: 800px;
min-height: 500px;
overflow-y: hidden;
}
.router-title {
color: #1f2329;
font-feature-settings: 'clig' off, 'liga' off;
font-family: PingFang SC;
font-size: 20px;
font-style: normal;
font-weight: 500;
line-height: 28px;
}
.watermark-table__content {
padding: 24px;
width: 100%;
background: var(--ContentBG, #ffffff);
height: calc(100% - 40px) !important;
box-sizing: border-box;
margin-top: 12px;
overflow-x: auto;
border-radius: 4px;
}
</style>

View File

@ -0,0 +1,27 @@
package io.dataease.api.visualization;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.api.visualization.request.VisualizationSubjectRequest;
import io.dataease.api.visualization.request.VisualizationWatermarkRequest;
import io.dataease.api.visualization.vo.VisualizationSubjectVO;
import io.dataease.api.visualization.vo.VisualizationWatermarkVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "可视化管理:水印")
@ApiSupport(order = 994)
public interface VisualizationWatermarkApi {
@ResponseBody
@GetMapping("/find")
VisualizationWatermarkVO getWatermarkInfo();
@ResponseBody
@PostMapping("/save")
void saveWatermarkInfo(@RequestBody VisualizationWatermarkRequest watermarkRequest);
}

View File

@ -0,0 +1,10 @@
package io.dataease.api.visualization.request;
import io.dataease.api.visualization.vo.VisualizationWatermarkVO;
/**
* @author : WangJiaHao
* @date : 2024/1/10 17:02
*/
public class VisualizationWatermarkRequest extends VisualizationWatermarkVO {
}