mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-02 07:20:24 +08:00
refactor: 系统水印重构
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
"countup.js": "^2.7.0",
|
||||
"cropperjs": "^1.5.11",
|
||||
"echarts": "^5.4.0",
|
||||
"element-plus": "^2.3.14",
|
||||
"element-plus": "^2.4.0",
|
||||
"jsencrypt": "^3.3.1",
|
||||
"lodash": "^4.17.21",
|
||||
"mitt": "^3.0.1",
|
||||
@@ -23,14 +23,14 @@
|
||||
"monaco-sql-languages": "^0.11.0",
|
||||
"monaco-themes": "^0.4.4",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.1.6",
|
||||
"pinia": "^2.1.7",
|
||||
"qrcode.vue": "^3.4.0",
|
||||
"screenfull": "^6.0.2",
|
||||
"sortablejs": "^1.15.0",
|
||||
"sql-formatter": "^12.1.2",
|
||||
"vue": "^3.3.4",
|
||||
"vue-clipboard3": "^1.0.1",
|
||||
"vue-router": "^4.2.4",
|
||||
"vue-router": "^4.2.5",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-fit": "^0.8.0",
|
||||
"xterm-addon-search": "^0.13.0",
|
||||
|
||||
@@ -1,21 +1,32 @@
|
||||
<template>
|
||||
<router-view v-show="themeConfig.lockScreenTime !== 0" />
|
||||
<el-watermark
|
||||
:zIndex="10000000"
|
||||
:width="200"
|
||||
v-if="themeConfig.isWartermark"
|
||||
:font="{ color: 'rgba(180, 180, 180, 0.5)' }"
|
||||
:content="state.watermarkContent"
|
||||
>
|
||||
<router-view v-show="themeConfig.lockScreenTime !== 0" />
|
||||
</el-watermark>
|
||||
<router-view v-if="!themeConfig.isWartermark" v-show="themeConfig.lockScreenTime !== 0" />
|
||||
|
||||
<LockScreen v-if="themeConfig.isLockScreen" />
|
||||
<Setings ref="setingsRef" v-show="themeConfig.lockScreenTime !== 0" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="app">
|
||||
import { ref, onBeforeMount, onMounted, onUnmounted, nextTick, watch } from 'vue';
|
||||
import { ref, reactive, onBeforeMount, onMounted, onUnmounted, nextTick, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
// import { useTagsViewRoutes } from '@/store/tagsViewRoutes';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '@/store/themeConfig';
|
||||
import { getLocal } from '@/common/utils/storage';
|
||||
import LockScreen from '@/layout/lockScreen/index.vue';
|
||||
import Setings from '@/layout/navBars/breadcrumb/setings.vue';
|
||||
import Watermark from '@/common/utils/wartermark';
|
||||
import mittBus from '@/common/utils/mitt';
|
||||
import { getThemeConfig } from './common/utils/storage';
|
||||
import { dateFormat2 } from '@/common/utils/date';
|
||||
import { useWartermark } from '@/common/sysconfig';
|
||||
import { useUserInfo } from '@/store/userInfo';
|
||||
|
||||
const setingsRef = ref();
|
||||
const route = useRoute();
|
||||
@@ -23,6 +34,11 @@ const route = useRoute();
|
||||
const themeConfigStores = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(themeConfigStores);
|
||||
|
||||
const state = reactive({
|
||||
useWatermark: false,
|
||||
watermarkContent: [] as any,
|
||||
});
|
||||
|
||||
// 布局配置弹窗打开
|
||||
const openSetingsDrawer = () => {
|
||||
setingsRef.value.openDrawer();
|
||||
@@ -39,6 +55,11 @@ onBeforeMount(() => {
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
// 是否开启水印
|
||||
useWartermark().then((res) => {
|
||||
themeConfigStores.setWatermarkConfig(res);
|
||||
});
|
||||
|
||||
// 监听布局配置弹窗点击打开
|
||||
mittBus.on('openSetingsDrawer', () => {
|
||||
openSetingsDrawer();
|
||||
@@ -55,8 +76,52 @@ onMounted(() => {
|
||||
});
|
||||
});
|
||||
|
||||
// 监听 themeConfig isWartermark配置文件的变化
|
||||
watch(
|
||||
() => themeConfig.value.isWartermark,
|
||||
(val) => {
|
||||
if (val) {
|
||||
setTimeout(() => {
|
||||
setWatermarkContent();
|
||||
refreshWatermarkTime();
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const setWatermarkContent = () => {
|
||||
const userinfo = useUserInfo().userInfo;
|
||||
if (!userinfo) {
|
||||
themeConfig.value.isWartermark = false;
|
||||
return;
|
||||
}
|
||||
state.watermarkContent = [`${userinfo.username}(${userinfo.name})`, dateFormat2('yyyy-MM-dd HH:mm:ss', new Date())];
|
||||
// 存在额外水印信息,则追加水印信息
|
||||
if (themeConfig.value.wartermarkText?.trim()) {
|
||||
state.watermarkContent.push(themeConfig.value.wartermarkText);
|
||||
}
|
||||
};
|
||||
|
||||
let refreshWatermarkTimeInterval: any = null;
|
||||
/**
|
||||
* 刷新水印时间
|
||||
*/
|
||||
const refreshWatermarkTime = () => {
|
||||
if (refreshWatermarkTimeInterval) {
|
||||
clearInterval(refreshWatermarkTimeInterval);
|
||||
}
|
||||
refreshWatermarkTimeInterval = setInterval(() => {
|
||||
if (themeConfig.value.isWartermark) {
|
||||
state.watermarkContent[1] = dateFormat2('yyyy-MM-dd HH:mm:ss', new Date());
|
||||
} else {
|
||||
clearInterval(refreshWatermarkTimeInterval);
|
||||
}
|
||||
}, 10000);
|
||||
};
|
||||
|
||||
// 页面销毁时,关闭监听布局配置
|
||||
onUnmounted(() => {
|
||||
clearInterval(refreshWatermarkTimeInterval);
|
||||
mittBus.off('openSetingsDrawer', () => {});
|
||||
});
|
||||
|
||||
@@ -65,8 +130,6 @@ watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
nextTick(() => {
|
||||
// 路由变化更新水印
|
||||
Watermark.use();
|
||||
document.title = `${route.meta.title} - ${themeConfig.value.globalTitle}` || themeConfig.value.globalTitle;
|
||||
});
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 39 KiB |
1
mayfly_go_web/src/assets/image/401.svg
Normal file
1
mayfly_go_web/src/assets/image/401.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB |
1
mayfly_go_web/src/assets/image/404.svg
Normal file
1
mayfly_go_web/src/assets/image/404.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 13 KiB |
@@ -11,7 +11,7 @@ const config = {
|
||||
baseWsUrl: `${(window as any).globalConfig.BaseWsUrl || `${location.protocol == 'https:' ? 'wss:' : 'ws:'}//${getBaseApiUrl()}`}/api`,
|
||||
|
||||
// 系统版本
|
||||
version: 'v1.5.2',
|
||||
version: 'v1.5.3',
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
||||
@@ -53,12 +53,21 @@ export async function useLoginCaptcha(): Promise<boolean> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否启用水印
|
||||
* 是否启用水印信息配置
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
export async function useWartermark(): Promise<boolean> {
|
||||
return await getBoolConfigValue(UseWartermarkConfigKey, true);
|
||||
export async function useWartermark(): Promise<any> {
|
||||
const value = await getConfigValue(UseWartermarkConfigKey);
|
||||
if (!value) {
|
||||
return {
|
||||
isUse: true,
|
||||
};
|
||||
}
|
||||
const jsonValue = JSON.parse(value);
|
||||
// 将字符串转为bool
|
||||
jsonValue.isUse = convertBool(jsonValue.isUse, true);
|
||||
return jsonValue;
|
||||
}
|
||||
|
||||
function convertBool(value: string, defaultValue: boolean) {
|
||||
@@ -77,4 +86,3 @@ export async function getLdapEnabled(): Promise<any> {
|
||||
const value = await openApi.getLdapEnabled();
|
||||
return convertBool(value, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,15 +30,6 @@ export function getThemeConfig() {
|
||||
return getLocal('themeConfig');
|
||||
}
|
||||
|
||||
// 获取是否开启水印
|
||||
export function getUseWatermark() {
|
||||
return getLocal('useWatermark');
|
||||
}
|
||||
|
||||
export function saveUseWatermark(useWatermark: boolean) {
|
||||
setLocal('useWatermark', useWatermark);
|
||||
}
|
||||
|
||||
// 清除用户相关的用户信息
|
||||
export function clearUser() {
|
||||
removeLocal(TokenKey);
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
import { getUseWatermark, getUser } from '@/common/utils/storage';
|
||||
import { dateFormat2 } from '@/common/utils/date';
|
||||
|
||||
// 页面添加水印效果
|
||||
const setWatermark = (str: any) => {
|
||||
const id = '1.23452384164.123412416';
|
||||
if (document.getElementById(id) !== null) document.body.removeChild(document.getElementById(id) as any);
|
||||
const can = document.createElement('canvas');
|
||||
can.width = 400;
|
||||
can.height = 250;
|
||||
const cans: any = can.getContext('2d');
|
||||
cans.rotate((-20 * Math.PI) / 180);
|
||||
cans.font = '14px Vedana';
|
||||
cans.fillStyle = 'rgba(200, 200, 200, 0.35)';
|
||||
cans.textAlign = 'left';
|
||||
cans.textBaseline = 'Middle';
|
||||
// cans.fillText('mayfly go', can.width / 4, can.height )
|
||||
cans.fillText(str, can.width / 8, can.height / 2);
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.id = id;
|
||||
div.style.pointerEvents = 'none';
|
||||
div.style.top = '30px';
|
||||
div.style.left = '0px';
|
||||
div.style.position = 'fixed';
|
||||
div.style.zIndex = '10000000';
|
||||
div.style.width = document.documentElement.clientWidth + 'px';
|
||||
div.style.height = document.documentElement.clientHeight + 'px';
|
||||
div.style.background = `url(${can.toDataURL('image/png')}) left top repeat`;
|
||||
document.body.appendChild(div);
|
||||
return id;
|
||||
};
|
||||
|
||||
function set(str: any) {
|
||||
let id = setWatermark(str);
|
||||
if (document.getElementById(id) === null) id = setWatermark(str);
|
||||
}
|
||||
|
||||
function del() {
|
||||
let id = '1.23452384164.123412416';
|
||||
if (document.getElementById(id) !== null) document.body.removeChild(document.getElementById(id) as any);
|
||||
}
|
||||
|
||||
const watermark = {
|
||||
use: () => {
|
||||
const userinfo = getUser();
|
||||
if (!userinfo) {
|
||||
del();
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (getUseWatermark()) {
|
||||
set(`${userinfo.username} ${dateFormat2('yyyy-MM-dd HH:mm:ss', new Date())}`);
|
||||
} else {
|
||||
del();
|
||||
}
|
||||
}, 1500);
|
||||
},
|
||||
// 设置水印
|
||||
set: (str: any) => {
|
||||
set(str);
|
||||
},
|
||||
// 删除水印
|
||||
del: () => {
|
||||
del();
|
||||
},
|
||||
};
|
||||
|
||||
export default watermark;
|
||||
@@ -89,8 +89,8 @@ export const useThemeConfig = defineStore('themeConfig', {
|
||||
isInvert: false,
|
||||
// 是否开启水印
|
||||
isWartermark: false,
|
||||
// 水印文案
|
||||
wartermarkText: 'mayfly',
|
||||
// 额外水印文案
|
||||
wartermarkText: '',
|
||||
|
||||
/* 其它设置
|
||||
------------------------------- */
|
||||
@@ -152,5 +152,10 @@ export const useThemeConfig = defineStore('themeConfig', {
|
||||
this.themeConfig.editorTheme = 'SolarizedLight';
|
||||
}
|
||||
},
|
||||
// 设置水印配置信息
|
||||
setWatermarkConfig(useWatermarkConfig: any) {
|
||||
this.themeConfig.isWartermark = useWatermarkConfig.isUse;
|
||||
this.themeConfig.wartermarkText = useWatermarkConfig.content;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<img src="@/assets/image/401.png" />
|
||||
<img src="@/assets/image/401.svg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { useRouter } from 'vue-router';
|
||||
import { clearSession } from '@/common/utils/storage.ts';
|
||||
import { clearSession } from '@/common/utils/storage';
|
||||
export default {
|
||||
name: '401',
|
||||
setup() {
|
||||
@@ -39,7 +39,7 @@ export default {
|
||||
<style scoped lang="scss">
|
||||
.error {
|
||||
height: 100%;
|
||||
background-color: white;
|
||||
background-color: var(--bg-main-color);
|
||||
display: flex;
|
||||
.error-flex {
|
||||
margin: auto;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<img src="@/assets/image/404.png" />
|
||||
<img src="@/assets/image/404.svg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -37,7 +37,7 @@ export default {
|
||||
<style scoped lang="scss">
|
||||
.error {
|
||||
height: 100%;
|
||||
background-color: white;
|
||||
background-color: var(--bg-main-color);
|
||||
display: flex;
|
||||
.error-flex {
|
||||
margin: auto;
|
||||
|
||||
@@ -132,7 +132,7 @@ import { nextTick, onMounted, ref, toRefs, reactive, computed } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { initRouter } from '@/router/index';
|
||||
import { saveToken, saveUser, saveUseWatermark } from '@/common/utils/storage';
|
||||
import { saveToken, saveUser } from '@/common/utils/storage';
|
||||
import { formatAxis } from '@/common/utils/format';
|
||||
import openApi from '@/common/openApi';
|
||||
import { RsaEncrypt } from '@/common/rsa';
|
||||
@@ -142,7 +142,8 @@ import { useUserInfo } from '@/store/userInfo';
|
||||
import QrcodeVue from 'qrcode.vue';
|
||||
import { personApi } from '@/views/personal/api';
|
||||
import { AccountUsernamePattern } from '@/common/pattern';
|
||||
import { getToken } from '../../../common/utils/storage';
|
||||
import { getToken } from '@/common/utils/storage';
|
||||
import { useThemeConfig } from '@/store/themeConfig';
|
||||
|
||||
const rules = {
|
||||
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
||||
@@ -150,6 +151,9 @@ const rules = {
|
||||
captcha: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
|
||||
};
|
||||
|
||||
// 定义变量内容
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const loginFormRef: any = ref(null);
|
||||
@@ -405,7 +409,8 @@ const toIndex = async () => {
|
||||
// 关闭 loading
|
||||
state.loading.signIn = true;
|
||||
ElMessage.success(`${currentTimeInfo},欢迎回来!`);
|
||||
saveUseWatermark(await useWartermark());
|
||||
// 水印信息配置
|
||||
storesThemeConfig.setWatermarkConfig(await useWartermark());
|
||||
}, 300);
|
||||
};
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ const getThemeConfig = computed(() => {
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
getThemeConfig.value.isWartermark = false;
|
||||
state.oauth2LoginConfig = await openApi.oauth2LoginConfig();
|
||||
});
|
||||
|
||||
|
||||
@@ -195,15 +195,6 @@
|
||||
操作
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-link
|
||||
@click="downloadFile(scope.row)"
|
||||
v-if="scope.row.type == '-'"
|
||||
v-auth="'machine:file:write'"
|
||||
type="primary"
|
||||
icon="download"
|
||||
:underline="false"
|
||||
></el-link>
|
||||
|
||||
<el-link
|
||||
@click="deleteFile([scope.row])"
|
||||
v-if="!dontOperate(scope.row)"
|
||||
@@ -211,7 +202,18 @@
|
||||
type="danger"
|
||||
icon="delete"
|
||||
:underline="false"
|
||||
title="删除"
|
||||
></el-link>
|
||||
|
||||
<el-link
|
||||
@click="downloadFile(scope.row)"
|
||||
v-if="scope.row.type == '-'"
|
||||
v-auth="'machine:file:write'"
|
||||
type="primary"
|
||||
icon="download"
|
||||
:underline="false"
|
||||
class="ml10"
|
||||
title="下载"
|
||||
></el-link>
|
||||
|
||||
<el-popover placement="top-start" :title="`${scope.row.path}-文件详情`" :width="520" trigger="click" @show="showFileStat(scope.row)">
|
||||
|
||||
@@ -773,10 +773,10 @@ echarts@^5.4.0:
|
||||
tslib "2.3.0"
|
||||
zrender "5.4.0"
|
||||
|
||||
element-plus@^2.3.14:
|
||||
version "2.3.14"
|
||||
resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.3.14.tgz#302a23916b0c3375fcf4b927d7b94483dac13e1b"
|
||||
integrity sha512-9yvxUaU4jXf2ZNPdmIxoj/f8BG8CDcGM6oHa9JIqxLjQlfY4bpzR1E5CjNimnOX3rxO93w1TQ0jTVt0RSxh9kA==
|
||||
element-plus@^2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.4.0.tgz#e79249ac4c0a606d377c2f31ad553aa992286fe3"
|
||||
integrity sha512-yJEa8LXkGOOgkfkeqMMEdeX/Dc8EH9qPcRuX91dlhSXxgCKKbp9tH3QFTOG99ibZsrN/Em62nh7ddvbc7I1frw==
|
||||
dependencies:
|
||||
"@ctrl/tinycolor" "^3.4.1"
|
||||
"@element-plus/icons-vue" "^2.0.6"
|
||||
@@ -1502,10 +1502,10 @@ picomatch@^2.2.3:
|
||||
resolved "https://registry.nlark.com/picomatch/download/picomatch-2.3.0.tgz?cache=0&sync_timestamp=1621648246651&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpicomatch%2Fdownload%2Fpicomatch-2.3.0.tgz"
|
||||
integrity sha1-8fBh3o9qS/AiiS4tEoI0+5gwKXI=
|
||||
|
||||
pinia@^2.1.6:
|
||||
version "2.1.6"
|
||||
resolved "https://registry.npmmirror.com/pinia/-/pinia-2.1.6.tgz#e88959f14b61c4debd9c42d0c9944e2875cbe0fa"
|
||||
integrity sha512-bIU6QuE5qZviMmct5XwCesXelb5VavdOWKWaB17ggk++NUwQWWbP5YnsONTk3b752QkW9sACiR81rorpeOMSvQ==
|
||||
pinia@^2.1.7:
|
||||
version "2.1.7"
|
||||
resolved "https://registry.npmmirror.com/pinia/-/pinia-2.1.7.tgz#4cf5420d9324ca00b7b4984d3fbf693222115bbc"
|
||||
integrity sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==
|
||||
dependencies:
|
||||
"@vue/devtools-api" "^6.5.0"
|
||||
vue-demi ">=0.14.5"
|
||||
@@ -1835,10 +1835,10 @@ vue-eslint-parser@^9.3.1:
|
||||
lodash "^4.17.21"
|
||||
semver "^7.3.6"
|
||||
|
||||
vue-router@^4.2.4:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.2.4.tgz#382467a7e2923e6a85f015d081e1508052c191b9"
|
||||
integrity sha512-9PISkmaCO02OzPVOMq2w82ilty6+xJmQrarYZDkjZBfl4RvYAlt4PKnEX21oW4KTtWfa9OuO/b3qk1Od3AEdCQ==
|
||||
vue-router@^4.2.5:
|
||||
version "4.2.5"
|
||||
resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.2.5.tgz#b9e3e08f1bd9ea363fdd173032620bc50cf0e98a"
|
||||
integrity sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==
|
||||
dependencies:
|
||||
"@vue/devtools-api" "^6.5.0"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import "fmt"
|
||||
|
||||
const (
|
||||
AppName = "mayfly-go"
|
||||
Version = "v1.5.2"
|
||||
Version = "v1.5.3"
|
||||
)
|
||||
|
||||
func GetAppInfo() string {
|
||||
|
||||
Binary file not shown.
7
server/resources/script/sql/v1.5.3.sql
Normal file
7
server/resources/script/sql/v1.5.3.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
UPDATE `t_sys_config`
|
||||
SET
|
||||
`params` = '[{"name":"是否启用","model":"isUse","placeholder":"是否启用水印","options":"true,false"},{"name":"自定义信息","model":"content","placeholder":"额外添加的水印内容,可添加公司名称等"}]',
|
||||
`value` = '',
|
||||
`remark` = '水印信息配置'
|
||||
WHERE
|
||||
`key` = 'UseWartermark';
|
||||
Reference in New Issue
Block a user