feat: 自定义主题基本功能

This commit is contained in:
fit2cloud-chenyw 2021-10-31 02:01:52 +08:00
parent cf3f02ad39
commit 50ff8d5b44
22 changed files with 135 additions and 44 deletions

View File

@ -42,6 +42,10 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap.put("/index.html", ANON);
filterChainDefinitionMap.put("/link.html", ANON);
//获取主题信息
filterChainDefinitionMap.put("/plugin/theme/themes", ANON);
filterChainDefinitionMap.put("/plugin/theme/items/**", ANON);
//验证链接
filterChainDefinitionMap.put("/api/link/validate**", ANON);
filterChainDefinitionMap.put("/api/map/areaEntitys/**", ANON);

View File

@ -0,0 +1,50 @@
package io.dataease.plugins.server;
import java.util.List;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.dataease.plugins.config.SpringContextUtil;
import io.dataease.plugins.xpack.theme.dto.ThemeDto;
import io.dataease.plugins.xpack.theme.dto.ThemeItem;
import io.dataease.plugins.xpack.theme.dto.ThemeRequest;
import io.dataease.plugins.xpack.theme.service.ThemeXpackService;
@RequestMapping("/plugin/theme")
@RestController
public class ThemeServer {
@PostMapping("/themes")
public List<ThemeDto> themes(){
ThemeXpackService themeXpackService = SpringContextUtil.getBean(ThemeXpackService.class);
return themeXpackService.themes();
}
@PostMapping("/items/{themeId}")
public List<ThemeItem> themeItems(@PathVariable("themeId") int themeId) {
ThemeXpackService themeXpackService = SpringContextUtil.getBean(ThemeXpackService.class);
return themeXpackService.queryItems(themeId);
}
@PostMapping("/save")
public void save(@RequestPart("request") ThemeRequest request, @RequestPart(value = "file", required = false) MultipartFile bodyFile) {
ThemeXpackService themeXpackService = SpringContextUtil.getBean(ThemeXpackService.class);
themeXpackService.save(request, bodyFile);
}
@PostMapping("/delete/{themeId}")
public void save(@PathVariable("themeId") int themeId) {
ThemeXpackService themeXpackService = SpringContextUtil.getBean(ThemeXpackService.class);
themeXpackService.deleteTheme(themeId);
}
}

View File

@ -1,14 +1,16 @@
<template>
<div id="app">
<router-view />
<plugin-com v-show="false" ref="de-theme" component-name="ThemeSetting" />
</div>
</template>
<script>
import PluginCom from '@/views/system/plugin/PluginCom'
export default {
name: 'App',
components: { PluginCom },
beforeCreate() {
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -435,7 +435,7 @@ export default {
},
settings: {
title: '系统布局配置',
theme: '主题',
theme: '主题',
tagsView: '开启 Tags-View',
fixedHeader: '固定 Header',
sidebarLogo: '侧边栏 Logo'

View File

@ -62,7 +62,6 @@
</el-dropdown-menu>
</el-dropdown>
</div>
<theme-picker v-show="false" ref="de-theme" />
</div>
</template>
@ -76,20 +75,22 @@ import Notification from '@/components/Notification'
import bus from '@/utils/bus'
import LangSelect from '@/components/LangSelect'
import { getSysUI } from '@/utils/auth'
import ThemePicker from '@/components/ThemePicker'
import { pluginLoaded } from '@/api/user'
import { initTheme } from '@/utils/ThemeUtil'
export default {
name: 'Topbar',
components: {
AppLink,
Notification,
LangSelect,
ThemePicker
LangSelect
},
data() {
return {
uiInfo: null,
logoUrl: null,
axiosFinished: false
axiosFinished: false,
isPluginLoaded: false
}
},
@ -147,7 +148,6 @@ export default {
mounted() {
this.initCurrentRoutes()
bus.$on('set-theme-info', this.setThemeInfo)
bus.$on('set-top-menu-info', this.setTopMenuInfo)
bus.$on('set-top-menu-active-info', this.setTopMenuActiveInfo)
bus.$on('set-top-text-info', this.setTopTextInfo)
@ -156,6 +156,12 @@ export default {
created() {
this.loadUiInfo()
},
beforeCreate() {
pluginLoaded().then(res => {
this.isPluginLoaded = res.success && res.data
if (this.isPluginLoaded) { initTheme() }
})
},
methods: {
// store
initCurrentRoutes() {
@ -259,20 +265,17 @@ export default {
})
}
if (this.uiInfo['ui.themeStr'] && this.uiInfo['ui.themeStr'].paramValue) {
/* if (this.uiInfo['ui.themeStr'] && this.uiInfo['ui.themeStr'].paramValue) {
if (this.uiInfo['ui.themeStr'].paramValue === 'dark') {
document.body.className = 'blackTheme'
} else if (this.uiInfo['ui.themeStr'].paramValue === 'light') {
document.body.className = ''
}
}
} */
this.axiosFinished = true
})
},
setThemeInfo(val) {
// console.log('' + val)
this.$refs['de-theme'] && this.$refs['de-theme'].switch && this.$refs['de-theme'].switch(val)
},
setTopMenuInfo(val) {
this.loadUiInfo()
},

View File

@ -80,7 +80,7 @@ export default {
position: relative;
height: 100%;
// height: $contentHeight;
background-color: var(--MainContentBG);
background-color: var(--ContentBG);
width: 100%;
&.mobile.openSidebar{
position: fixed;

View File

@ -22,7 +22,6 @@ router.beforeEach(async(to, from, next) => {
// determine whether the user has logged in
const hasToken = getToken()
// bus.$emit('set-theme-info', store.state.settings.theme)
if (hasToken) {
if (to.path === '/login') {
// if is logged in, redirect to the home page

View File

@ -1,14 +1,11 @@
$--font-path: '~element-ui/lib/theme-chalk/fonts';
/* $--font-path: '~element-ui/lib/theme-chalk/fonts'; */
/* .defaultTheme {
@import './theme/default.scss';
@import "~element-ui/packages/theme-chalk/src/index";
} */
.blackTheme {
/* .blackTheme {
@import './theme/dark.scss';
@import "~element-ui/packages/theme-chalk/src/index";
}
} */
@ -460,7 +457,7 @@ div:focus {
color: var(--TableColor) !important;
}
.blackTheme .el-tag.el-tag--info {
background-color: var(--MainContentBG);
background-color: var(--ContentBG);
border-color: var(--TableBorderColor);
color: var(--TableColor) !important; ;
}
@ -575,7 +572,7 @@ div:focus {
color: var(--TextPrimary) ;
}
.blackTheme .el-drawer__body {
background-color: var(--MainContentBG);
background-color: var(--ContentBG);
}
.blackTheme .el-select-dropdown__item.hover {

View File

@ -26,15 +26,11 @@ $--background-color-base: #171b22;
// 与CSS原生变量映射
#app {
--Main:#2681ff;
--test:#FF9227;
--color-primary: #000;
--MainBG: #171b22;
--ContentBG: #1b2a32;
--MainBorderColor: #2681ff;
--TextActive: #FFFFFF;
--TextPrimary: #F2F6FC;
--border-color-input: #303640;
--border-color-input-hovor: #303640;
--TopBG: #00364d;
@ -47,11 +43,10 @@ $--background-color-base: #171b22;
--SiderBG: #17242b;
--SiderTextColor: #acbac3;
--MainContentBG: #1b2a32;
--TableBG: #21333b;
--TableColor: #acbac3;
--TableBorder: .05rem solid #495865;
// --TableBorder: .05rem solid #495865;
--TableBorderColor: #495865;
--background-color-base: #171b22;

View File

@ -0,0 +1,27 @@
const styleId = 'dataease-wggznb'
export function initTheme() {
const json = localStorage.getItem('theme-css-text')
if (!json) return
const { cssText, themeId } = JSON.parse(json)
if (!themeId) return
let style = document.getElementById(styleId)
if (themeId === 1) {
document.body.className = ''
style && document.getElementById(styleId).parentNode.removeChild(document.getElementById(styleId))
return
}
document.body.className = 'blackTheme'
if (style) {
style.innerText = cssText
} else {
style = document.createElement('style')
style.id = styleId
style.innerText = cssText
document.head.appendChild(style)
}
}

View File

@ -436,7 +436,7 @@ export default {
}
.el-header {
background-color: var(--MainContentBG, rgb(241, 243, 248));
background-color: var(--ContentBG, rgb(241, 243, 248));
color: var(--TextActive, #333);
line-height: 30px;
}

View File

@ -1,5 +1,5 @@
<template>
<div class="login-background">
<div class="login-background" :v-show="themeLoaded">
<div class="login-container">
<el-row v-loading="loading" type="flex">
<el-col :span="12">
@ -57,6 +57,7 @@
</el-row>
</div>
<plugin-com v-if="loginTypes.includes(2) && loginForm.loginType === 2" ref="SSOComponent" component-name="SSOComponent" />
</div>
</template>
@ -65,6 +66,7 @@
import { encrypt } from '@/utils/rsaEncrypt'
import { ldapStatus, oidcStatus } from '@/api/user'
import { getSysUI } from '@/utils/auth'
import { initTheme } from '@/utils/ThemeUtil'
import PluginCom from '@/views/system/plugin/PluginCom'
import Cookies from 'js-cookie'
export default {
@ -88,7 +90,8 @@ export default {
loginImageUrl: null,
loginLogoUrl: null,
axiosFinished: false,
loginTypes: [0]
loginTypes: [0],
themeLoaded: false
}
},
computed: {
@ -105,6 +108,8 @@ export default {
}
},
beforeCreate() {
initTheme()
this.themeLoaded = true
ldapStatus().then(res => {
if (res.success && res.data) {
this.loginTypes.push(1)
@ -117,6 +122,11 @@ export default {
}
})
},
mounted() {
// this.loading = false
},
created() {
this.$store.dispatch('user/getUI').then(() => {
// const uiLists = this.$store.state.user.uiInfo
@ -133,6 +143,7 @@ export default {
}
this.clearOidcMsg()
},
methods: {
clearOidcMsg() {
Cookies.remove('OidcError')
@ -146,14 +157,13 @@ export default {
if (this.uiInfo['ui.loginLogo'] && this.uiInfo['ui.loginLogo'].paramValue) {
this.loginLogoUrl = '/system/ui/image/' + this.uiInfo['ui.loginLogo'].paramValue
}
if (this.uiInfo['ui.themeStr'] && this.uiInfo['ui.themeStr'].paramValue) {
// this.loginLogoUrl = '/system/ui/image/' + this.uiInfo['ui.loginLogo'].paramValue
/* if (this.uiInfo['ui.themeStr'] && this.uiInfo['ui.themeStr'].paramValue) {
if (this.uiInfo['ui.themeStr'].paramValue === 'dark') {
document.body.className = 'blackTheme'
} else if (this.uiInfo['ui.themeStr'].paramValue === 'light') {
document.body.className = ''
}
}
} */
},
handleLogin() {
@ -208,7 +218,7 @@ export default {
min-width: 900px;
width: 1280px;
height: 520px;
background-color: var(--MainContentBG, #FFFFFF);
background-color: var(--ContentBG, #FFFFFF);
@media only screen and (max-width: 1280px) {
width: 900px;
height: 380px;

View File

@ -921,7 +921,7 @@ export default {
overflow-y: auto;
}
.button-show{
background-color: var(--MainContentBG, #ebf2fe)!important;
background-color: var(--ContentBG, #ebf2fe)!important;
}
.button-closed{

View File

@ -68,7 +68,7 @@
</el-row>
</el-col>
<el-col v-if="panelInfo.name.length===0" style="height: 100%;">
<el-row style="height: 100%; background-color: var(--MainContentBG);" class="custom-position">
<el-row style="height: 100%; background-color: var(--ContentBG);" class="custom-position">
{{ $t('panel.select_panel_from_left') }}
</el-row>
</el-col>

View File

@ -6,19 +6,23 @@
<basic-setting />
</el-tab-pane>
<el-tab-pane :lazy="true" :label="$t('system_parameter_setting.mailbox_service_settings')" name="first">
<!-- <el-tab-pane :lazy="true" :label="$t('system_parameter_setting.mailbox_service_settings')" name="first">
<email-setting />
</el-tab-pane>
</el-tab-pane> -->
<el-tab-pane v-if="isPluginLoaded" :lazy="true" :label="$t('sysParams.display')" name="second">
<plugin-com v-if="isPluginLoaded" ref="DisplaySetting" component-name="DisplaySetting" />
</el-tab-pane>
<el-tab-pane v-if="isPluginLoaded" :lazy="true" :label="$t('sysParams.ldap')" name="third">
<el-tab-pane v-if="isPluginLoaded" :lazy="true" :label="$t('sysParams.theme')" name="third">
<plugin-com v-if="isPluginLoaded" ref="ThemeSetting" component-name="ThemeSetting" />
</el-tab-pane>
<el-tab-pane v-if="isPluginLoaded" :lazy="true" :label="$t('sysParams.ldap')" name="fourth">
<plugin-com v-if="isPluginLoaded" ref="DisplaySetting" component-name="LdapSetting" />
</el-tab-pane>
<el-tab-pane v-if="isPluginLoaded" :lazy="true" :label="$t('sysParams.oidc')" name="fourth">
<el-tab-pane v-if="isPluginLoaded" :lazy="true" :label="$t('sysParams.oidc')" name="five">
<plugin-com v-if="isPluginLoaded" ref="DisplaySetting" component-name="SsoSetting" />
</el-tab-pane>

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB