Unverified 提交 87c5b209 authored 作者: fit2cloud-chenyw's avatar fit2cloud-chenyw 提交者: GitHub

Merge pull request #1064 from dataease/pr@dev@custom_theme

Pr@dev@custom theme
...@@ -42,6 +42,10 @@ public class ShiroServiceImpl implements ShiroService { ...@@ -42,6 +42,10 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap.put("/index.html", ANON); filterChainDefinitionMap.put("/index.html", ANON);
filterChainDefinitionMap.put("/link.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/link/validate**", ANON);
filterChainDefinitionMap.put("/api/map/areaEntitys/**", ANON); filterChainDefinitionMap.put("/api/map/areaEntitys/**", ANON);
......
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);
}
}
...@@ -79,6 +79,12 @@ upload.file.path=/opt/dataease/data/kettle/ ...@@ -79,6 +79,12 @@ upload.file.path=/opt/dataease/data/kettle/
dataease.sqlinjection.whitelists=/dataset/table/sqlPreview,/dataset/table/update dataease.sqlinjection.whitelists=/dataset/table/sqlPreview,/dataset/table/update
#开启压缩 提高响应速度 减少带宽压力
server.compression.enabled=true
server.compression.mime-types=application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
server.compression.min-response-size=1024
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
"@tinymce/tinymce-vue": "^3.2.8", "@tinymce/tinymce-vue": "^3.2.8",
"axios": "^0.21.1", "axios": "^0.21.1",
"core-js": "^2.6.5", "core-js": "^2.6.5",
"css-color-function": "^1.3.3",
"echarts": "^5.0.1", "echarts": "^5.0.1",
"element-resize-detector": "^1.2.3", "element-resize-detector": "^1.2.3",
"element-ui": "2.15.6", "element-ui": "2.15.6",
......
<template> <template>
<div id="app"> <div id="app">
<router-view /> <router-view />
<plugin-com v-show="false" ref="de-theme" component-name="ThemeSetting" />
</div> </div>
</template> </template>
<script> <script>
import PluginCom from '@/views/system/plugin/PluginCom'
export default { export default {
name: 'App', name: 'App',
components: { PluginCom },
beforeCreate() { beforeCreate() {
} }
......
...@@ -176,6 +176,7 @@ export default { ...@@ -176,6 +176,7 @@ export default {
annotation: '注释', annotation: '注释',
clear: '清空', clear: '清空',
save: '保存', save: '保存',
otherSave: '另存为',
update: '更新', update: '更新',
save_success: '保存成功', save_success: '保存成功',
delete_success: '删除成功', delete_success: '删除成功',
...@@ -341,7 +342,8 @@ export default { ...@@ -341,7 +342,8 @@ export default {
ok: '确认', ok: '确认',
cancel: '取消' cancel: '取消'
}, },
ukey_title: 'API Keys' ukey_title: 'API Keys',
thumbnail: '缩略图'
}, },
documentation: { documentation: {
documentation: '文档', documentation: '文档',
...@@ -433,7 +435,7 @@ export default { ...@@ -433,7 +435,7 @@ export default {
}, },
settings: { settings: {
title: '系统布局配置', title: '系统布局配置',
theme: '主题', theme: '主题',
tagsView: '开启 Tags-View', tagsView: '开启 Tags-View',
fixedHeader: '固定 Header', fixedHeader: '固定 Header',
sidebarLogo: '侧边栏 Logo' sidebarLogo: '侧边栏 Logo'
...@@ -441,7 +443,8 @@ export default { ...@@ -441,7 +443,8 @@ export default {
sysParams: { sysParams: {
display: '显示设置', display: '显示设置',
ldap: 'LDAP设置', ldap: 'LDAP设置',
oidc: 'OIDC设置' oidc: 'OIDC设置',
theme: '主题设置'
}, },
license: { license: {
i18n_no_license_record: '没有 License 记录', i18n_no_license_record: '没有 License 记录',
......
...@@ -62,7 +62,6 @@ ...@@ -62,7 +62,6 @@
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</div> </div>
<theme-picker v-show="false" ref="de-theme" />
</div> </div>
</template> </template>
...@@ -76,20 +75,22 @@ import Notification from '@/components/Notification' ...@@ -76,20 +75,22 @@ import Notification from '@/components/Notification'
import bus from '@/utils/bus' import bus from '@/utils/bus'
import LangSelect from '@/components/LangSelect' import LangSelect from '@/components/LangSelect'
import { getSysUI } from '@/utils/auth' import { getSysUI } from '@/utils/auth'
import ThemePicker from '@/components/ThemePicker' import { pluginLoaded } from '@/api/user'
import { initTheme } from '@/utils/ThemeUtil'
export default { export default {
name: 'Topbar', name: 'Topbar',
components: { components: {
AppLink, AppLink,
Notification, Notification,
LangSelect, LangSelect
ThemePicker
}, },
data() { data() {
return { return {
uiInfo: null, uiInfo: null,
logoUrl: null, logoUrl: null,
axiosFinished: false axiosFinished: false,
isPluginLoaded: false
} }
}, },
...@@ -147,7 +148,6 @@ export default { ...@@ -147,7 +148,6 @@ export default {
mounted() { mounted() {
this.initCurrentRoutes() this.initCurrentRoutes()
bus.$on('set-theme-info', this.setThemeInfo)
bus.$on('set-top-menu-info', this.setTopMenuInfo) bus.$on('set-top-menu-info', this.setTopMenuInfo)
bus.$on('set-top-menu-active-info', this.setTopMenuActiveInfo) bus.$on('set-top-menu-active-info', this.setTopMenuActiveInfo)
bus.$on('set-top-text-info', this.setTopTextInfo) bus.$on('set-top-text-info', this.setTopTextInfo)
...@@ -156,6 +156,12 @@ export default { ...@@ -156,6 +156,12 @@ export default {
created() { created() {
this.loadUiInfo() this.loadUiInfo()
}, },
beforeCreate() {
pluginLoaded().then(res => {
this.isPluginLoaded = res.success && res.data
if (this.isPluginLoaded) { initTheme() }
})
},
methods: { methods: {
// 通过当前路径找到二级菜单对应项,存到store,用来渲染左侧菜单 // 通过当前路径找到二级菜单对应项,存到store,用来渲染左侧菜单
initCurrentRoutes() { initCurrentRoutes() {
...@@ -259,20 +265,17 @@ export default { ...@@ -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') { if (this.uiInfo['ui.themeStr'].paramValue === 'dark') {
document.body.className = 'blackTheme' document.body.className = 'blackTheme'
} else if (this.uiInfo['ui.themeStr'].paramValue === 'light') { } else if (this.uiInfo['ui.themeStr'].paramValue === 'light') {
document.body.className = '' document.body.className = ''
} }
} } */
this.axiosFinished = true 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) { setTopMenuInfo(val) {
this.loadUiInfo() this.loadUiInfo()
}, },
......
...@@ -80,7 +80,7 @@ export default { ...@@ -80,7 +80,7 @@ export default {
position: relative; position: relative;
height: 100%; height: 100%;
// height: $contentHeight; // height: $contentHeight;
background-color: var(--MainContentBG); background-color: var(--ContentBG);
width: 100%; width: 100%;
&.mobile.openSidebar{ &.mobile.openSidebar{
position: fixed; position: fixed;
......
...@@ -22,7 +22,6 @@ router.beforeEach(async(to, from, next) => { ...@@ -22,7 +22,6 @@ router.beforeEach(async(to, from, next) => {
// determine whether the user has logged in // determine whether the user has logged in
const hasToken = getToken() const hasToken = getToken()
// bus.$emit('set-theme-info', store.state.settings.theme)
if (hasToken) { if (hasToken) {
if (to.path === '/login') { if (to.path === '/login') {
// if is logged in, redirect to the home page // if is logged in, redirect to the home page
......
$--font-path: '~element-ui/lib/theme-chalk/fonts'; /* $--font-path: '~element-ui/lib/theme-chalk/fonts'; */
/* .defaultTheme {
@import './theme/default.scss'; /* .blackTheme {
@import "~element-ui/packages/theme-chalk/src/index";
} */
.blackTheme {
@import './theme/dark.scss'; @import './theme/dark.scss';
@import "~element-ui/packages/theme-chalk/src/index"; @import "~element-ui/packages/theme-chalk/src/index";
} } */
...@@ -439,10 +436,10 @@ div:focus { ...@@ -439,10 +436,10 @@ div:focus {
} }
} }
.el-pager li { /* .blackTheme .el-pager li {
color: var(--TableColor) !important; color: var(--TableColor) !important;
background-color: var(--MainBG) !important; background-color: var(--MainBG) !important;
} } */
/* .blackTheme .el-select-dropdown { /* .blackTheme .el-select-dropdown {
background-color: var(--MainBG) !important; background-color: var(--MainBG) !important;
...@@ -460,7 +457,7 @@ div:focus { ...@@ -460,7 +457,7 @@ div:focus {
color: var(--TableColor) !important; color: var(--TableColor) !important;
} }
.blackTheme .el-tag.el-tag--info { .blackTheme .el-tag.el-tag--info {
background-color: var(--MainContentBG); background-color: var(--ContentBG);
border-color: var(--TableBorderColor); border-color: var(--TableBorderColor);
color: var(--TableColor) !important; ; color: var(--TableColor) !important; ;
} }
...@@ -575,7 +572,7 @@ div:focus { ...@@ -575,7 +572,7 @@ div:focus {
color: var(--TextPrimary) ; color: var(--TextPrimary) ;
} }
.blackTheme .el-drawer__body { .blackTheme .el-drawer__body {
background-color: var(--MainContentBG); background-color: var(--ContentBG);
} }
.blackTheme .el-select-dropdown__item.hover { .blackTheme .el-select-dropdown__item.hover {
......
...@@ -26,15 +26,11 @@ $--background-color-base: #171b22; ...@@ -26,15 +26,11 @@ $--background-color-base: #171b22;
// 与CSS原生变量映射 // 与CSS原生变量映射
#app { #app {
--Main:#2681ff; --Main:#2681ff;
--test:#FF9227;
--color-primary: #000;
--MainBG: #171b22; --MainBG: #171b22;
--ContentBG: #1b2a32; --ContentBG: #1b2a32;
--MainBorderColor: #2681ff;
--TextActive: #FFFFFF; --TextActive: #FFFFFF;
--TextPrimary: #F2F6FC; --TextPrimary: #F2F6FC;
--border-color-input: #303640; --border-color-input: #303640;
--border-color-input-hovor: #303640;
--TopBG: #00364d; --TopBG: #00364d;
...@@ -47,11 +43,10 @@ $--background-color-base: #171b22; ...@@ -47,11 +43,10 @@ $--background-color-base: #171b22;
--SiderBG: #17242b; --SiderBG: #17242b;
--SiderTextColor: #acbac3; --SiderTextColor: #acbac3;
--MainContentBG: #1b2a32;
--TableBG: #21333b; --TableBG: #21333b;
--TableColor: #acbac3; --TableColor: #acbac3;
--TableBorder: .05rem solid #495865; // --TableBorder: .05rem solid #495865;
--TableBorderColor: #495865; --TableBorderColor: #495865;
--background-color-base: #171b22; --background-color-base: #171b22;
......
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)
}
}
...@@ -436,7 +436,7 @@ export default { ...@@ -436,7 +436,7 @@ export default {
} }
.el-header { .el-header {
background-color: var(--MainContentBG, rgb(241, 243, 248)); background-color: var(--ContentBG, rgb(241, 243, 248));
color: var(--TextActive, #333); color: var(--TextActive, #333);
line-height: 30px; line-height: 30px;
} }
......
<template> <template>
<div class="login-background"> <div class="login-background" :v-show="themeLoaded">
<div class="login-container"> <div class="login-container">
<el-row v-loading="loading" type="flex"> <el-row v-loading="loading" type="flex">
<el-col :span="12"> <el-col :span="12">
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
</el-row> </el-row>
</div> </div>
<plugin-com v-if="loginTypes.includes(2) && loginForm.loginType === 2" ref="SSOComponent" component-name="SSOComponent" /> <plugin-com v-if="loginTypes.includes(2) && loginForm.loginType === 2" ref="SSOComponent" component-name="SSOComponent" />
</div> </div>
</template> </template>
...@@ -65,6 +66,7 @@ ...@@ -65,6 +66,7 @@
import { encrypt } from '@/utils/rsaEncrypt' import { encrypt } from '@/utils/rsaEncrypt'
import { ldapStatus, oidcStatus, getPublicKey } from '@/api/user' import { ldapStatus, oidcStatus, getPublicKey } from '@/api/user'
import { getSysUI } from '@/utils/auth' import { getSysUI } from '@/utils/auth'
import { initTheme } from '@/utils/ThemeUtil'
import PluginCom from '@/views/system/plugin/PluginCom' import PluginCom from '@/views/system/plugin/PluginCom'
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import store from "@/store"; import store from "@/store";
...@@ -89,7 +91,8 @@ export default { ...@@ -89,7 +91,8 @@ export default {
loginImageUrl: null, loginImageUrl: null,
loginLogoUrl: null, loginLogoUrl: null,
axiosFinished: false, axiosFinished: false,
loginTypes: [0] loginTypes: [0],
themeLoaded: false
} }
}, },
computed: { computed: {
...@@ -106,6 +109,8 @@ export default { ...@@ -106,6 +109,8 @@ export default {
} }
}, },
beforeCreate() { beforeCreate() {
initTheme()
this.themeLoaded = true
ldapStatus().then(res => { ldapStatus().then(res => {
if (res.success && res.data) { if (res.success && res.data) {
this.loginTypes.push(1) this.loginTypes.push(1)
...@@ -124,6 +129,11 @@ export default { ...@@ -124,6 +129,11 @@ export default {
} }
}) })
}, },
mounted() {
// this.loading = false
},
created() { created() {
this.$store.dispatch('user/getUI').then(() => { this.$store.dispatch('user/getUI').then(() => {
// const uiLists = this.$store.state.user.uiInfo // const uiLists = this.$store.state.user.uiInfo
...@@ -140,6 +150,7 @@ export default { ...@@ -140,6 +150,7 @@ export default {
} }
this.clearOidcMsg() this.clearOidcMsg()
}, },
methods: { methods: {
clearOidcMsg() { clearOidcMsg() {
Cookies.remove('OidcError') Cookies.remove('OidcError')
...@@ -153,14 +164,13 @@ export default { ...@@ -153,14 +164,13 @@ export default {
if (this.uiInfo['ui.loginLogo'] && this.uiInfo['ui.loginLogo'].paramValue) { if (this.uiInfo['ui.loginLogo'] && this.uiInfo['ui.loginLogo'].paramValue) {
this.loginLogoUrl = '/system/ui/image/' + 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) { /* 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'].paramValue === 'dark') { if (this.uiInfo['ui.themeStr'].paramValue === 'dark') {
document.body.className = 'blackTheme' document.body.className = 'blackTheme'
} else if (this.uiInfo['ui.themeStr'].paramValue === 'light') { } else if (this.uiInfo['ui.themeStr'].paramValue === 'light') {
document.body.className = '' document.body.className = ''
} }
} } */
}, },
handleLogin() { handleLogin() {
...@@ -216,7 +226,7 @@ export default { ...@@ -216,7 +226,7 @@ export default {
min-width: 900px; min-width: 900px;
width: 1280px; width: 1280px;
height: 520px; height: 520px;
background-color: var(--MainContentBG, #FFFFFF); background-color: var(--ContentBG, #FFFFFF);
@media only screen and (max-width: 1280px) { @media only screen and (max-width: 1280px) {
width: 900px; width: 900px;
height: 380px; height: 380px;
......
...@@ -926,7 +926,7 @@ export default { ...@@ -926,7 +926,7 @@ export default {
overflow-y: auto; overflow-y: auto;
} }
.button-show{ .button-show{
background-color: var(--MainContentBG, #ebf2fe)!important; background-color: var(--ContentBG, #ebf2fe)!important;
} }
.button-closed{ .button-closed{
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
</el-row> </el-row>
</el-col> </el-col>
<el-col v-if="panelInfo.name.length===0" style="height: 100%;"> <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') }} {{ $t('panel.select_panel_from_left') }}
</el-row> </el-row>
</el-col> </el-col>
......
...@@ -6,19 +6,23 @@ ...@@ -6,19 +6,23 @@
<basic-setting /> <basic-setting />
</el-tab-pane> </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 /> <email-setting />
</el-tab-pane> </el-tab-pane> -->
<el-tab-pane v-if="isPluginLoaded" :lazy="true" :label="$t('sysParams.display')" name="second"> <el-tab-pane v-if="isPluginLoaded" :lazy="true" :label="$t('sysParams.display')" name="second">
<plugin-com v-if="isPluginLoaded" ref="DisplaySetting" component-name="DisplaySetting" /> <plugin-com v-if="isPluginLoaded" ref="DisplaySetting" component-name="DisplaySetting" />
</el-tab-pane> </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" /> <plugin-com v-if="isPluginLoaded" ref="DisplaySetting" component-name="LdapSetting" />
</el-tab-pane> </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" /> <plugin-com v-if="isPluginLoaded" ref="DisplaySetting" component-name="SsoSetting" />
</el-tab-pane> </el-tab-pane>
......
...@@ -3,6 +3,7 @@ const path = require('path') ...@@ -3,6 +3,7 @@ const path = require('path')
const defaultSettings = require('./src/settings.js') const defaultSettings = require('./src/settings.js')
const CopyWebpackPlugin = require('copy-webpack-plugin') const CopyWebpackPlugin = require('copy-webpack-plugin')
// const CompressionPlugin = require('compression-webpack-plugin')
function resolve(dir) { function resolve(dir) {
return path.join(__dirname, dir) return path.join(__dirname, dir)
...@@ -79,6 +80,14 @@ module.exports = { ...@@ -79,6 +80,14 @@ module.exports = {
.options({ .options({
symbolId: 'icon-[name]' symbolId: 'icon-[name]'
}) })
if (process.env.NODE_ENV === 'production') {
/* config.plugin('compressionPlugin').use(new CompressionPlugin({
test: /\.(js|css|less)$/, // 匹配文件名
threshold: 10240, // 对超过10k的数据压缩
minRatio: 0.8,
deleteOriginalAssets: true // 删除源文件
})) */
}
}, },
css: { css: {
loaderOptions: { loaderOptions: {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论