diff --git a/ruoyi-ui/src/assets/styles/ruoyi.scss b/ruoyi-ui/src/assets/styles/ruoyi.scss index e3912cec..2e4c30dd 100644 --- a/ruoyi-ui/src/assets/styles/ruoyi.scss +++ b/ruoyi-ui/src/assets/styles/ruoyi.scss @@ -1,273 +1,269 @@ - /** - * 通用css样式布局处理 - * Copyright (c) 2019 ruoyi - */ - - /** 基础通用 **/ -.pt5 { - padding-top: 5px; -} -.pr5 { - padding-right: 5px; -} -.pb5 { - padding-bottom: 5px; -} -.mt5 { - margin-top: 5px; -} -.mr5 { - margin-right: 5px; -} -.mb5 { - margin-bottom: 5px; -} -.mb8 { - margin-bottom: 8px; -} -.ml5 { - margin-left: 5px; -} -.mt10 { - margin-top: 10px; -} -.mr10 { - margin-right: 10px; -} -.mb10 { - margin-bottom: 10px; -} -.ml10 { - margin-left: 10px; -} -.mt20 { - margin-top: 20px; -} -.mr20 { - margin-right: 20px; -} -.mb20 { - margin-bottom: 20px; -} -.ml20 { - margin-left: 20px; -} - -.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { - font-family: inherit; - font-weight: 500; - line-height: 1.1; - color: inherit; -} - -.el-dialog:not(.is-fullscreen) { - margin-top: 6vh !important; -} - -.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body { - overflow: auto; - overflow-x: hidden; - max-height: 70vh; - padding: 10px 20px 0; -} - -.el-table { - .el-table__header-wrapper, .el-table__fixed-header-wrapper { - th { - word-break: break-word; - background-color: #f8f8f9; - color: #515a6e; - height: 40px; - font-size: 13px; - } - } - .el-table__body-wrapper { - .el-button [class*="el-icon-"] + span { - margin-left: 1px; - } - } -} - -/** 表单布局 **/ -.form-header { - font-size:15px; - color:#6379bb; - border-bottom:1px solid #ddd; - margin:8px 10px 25px 10px; - padding-bottom:5px -} - -/** 表格布局 **/ -.pagination-container { - position: relative; - height: 25px; - margin-bottom: 10px; - margin-top: 15px; - padding: 10px 20px !important; -} - -/* tree border */ -.tree-border { - margin-top: 5px; - border: 1px solid #e5e6e7; - background: #FFFFFF none; - border-radius:4px; -} - -.pagination-container .el-pagination { - right: 0; - position: absolute; -} - -@media ( max-width : 768px) { - .pagination-container .el-pagination > .el-pagination__jump { - display: none !important; - } - .pagination-container .el-pagination > .el-pagination__sizes { - display: none !important; - } -} - -.el-table .fixed-width .el-button--mini { - padding-left: 0; - padding-right: 0; - width: inherit; -} - -/** 表格更多操作下拉样式 */ -.el-table .el-dropdown-link { - cursor: pointer; - color: #409EFF; - margin-left: 5px; -} - -.el-table .el-dropdown, .el-icon-arrow-down { - font-size: 12px; -} - -.el-tree-node__content > .el-checkbox { - margin-right: 8px; -} - -.list-group-striped > .list-group-item { - border-left: 0; - border-right: 0; - border-radius: 0; - padding-left: 0; - padding-right: 0; -} - -.list-group { - padding-left: 0px; - list-style: none; -} - -.list-group-item { - border-bottom: 1px solid #e7eaec; - border-top: 1px solid #e7eaec; - margin-bottom: -1px; - padding: 11px 0px; - font-size: 13px; -} - -.pull-right { - float: right !important; -} - -.el-card__header { - padding: 14px 15px 7px; - min-height: 40px; -} - -.el-card__body { - padding: 15px 20px 20px 20px; -} - -.card-box { - padding-right: 15px; - padding-left: 15px; - margin-bottom: 10px; -} - -/* button color */ -.el-button--cyan.is-active, -.el-button--cyan:active { - background: #20B2AA; - border-color: #20B2AA; - color: #FFFFFF; -} - -.el-button--cyan:focus, -.el-button--cyan:hover { - background: #48D1CC; - border-color: #48D1CC; - color: #FFFFFF; -} - -.el-button--cyan { - background-color: #20B2AA; - border-color: #20B2AA; - color: #FFFFFF; -} - -/* text color */ -.text-navy { - color: #1ab394; -} - -.text-primary { - color: inherit; -} - -.text-success { - color: #1c84c6; -} - -.text-info { - color: #23c6c8; -} - -.text-warning { - color: #f8ac59; -} - -.text-danger { - color: #ed5565; -} - -.text-muted { - color: #888888; -} - -/* image */ -.img-circle { - border-radius: 50%; -} - -.img-lg { - width: 120px; - height: 120px; -} - -.avatar-upload-preview { - position: absolute; - top: 50%; - transform: translate(50%, -50%); - width: 200px; - height: 200px; - border-radius: 50%; - box-shadow: 0 0 4px #ccc; - overflow: hidden; -} - -/* 拖拽列样式 */ -.sortable-ghost{ - opacity: .8; - color: #fff!important; - background: #42b983!important; -} - -.top-right-btn { - position: relative; - float: right; -} + /** + * 通用css样式布局处理 + * Copyright (c) 2019 ruoyi + */ + + /** 基础通用 **/ +.pt5 { + padding-top: 5px; +} +.pr5 { + padding-right: 5px; +} +.pb5 { + padding-bottom: 5px; +} +.mt5 { + margin-top: 5px; +} +.mr5 { + margin-right: 5px; +} +.mb5 { + margin-bottom: 5px; +} +.mb8 { + margin-bottom: 8px; +} +.ml5 { + margin-left: 5px; +} +.mt10 { + margin-top: 10px; +} +.mr10 { + margin-right: 10px; +} +.mb10 { + margin-bottom: 10px; +} +.ml10 { + margin-left: 10px; +} +.mt20 { + margin-top: 20px; +} +.mr20 { + margin-right: 20px; +} +.mb20 { + margin-bottom: 20px; +} +.ml20 { + margin-left: 20px; +} + +.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} + +.el-dialog:not(.is-fullscreen) { + margin-top: 6vh !important; +} + +.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body { + overflow: auto; + overflow-x: hidden; + max-height: 70vh; + padding: 10px 20px 0; +} + +.el-table { + .el-table__header-wrapper, .el-table__fixed-header-wrapper { + th { + word-break: break-word; + background-color: #f8f8f9; + color: #515a6e; + height: 40px; + font-size: 13px; + } + } + .el-table__body-wrapper { + .el-button [class*="el-icon-"] + span { + margin-left: 1px; + } + } +} + +/** 表单布局 **/ +.form-header { + font-size:15px; + color:#6379bb; + border-bottom:1px solid #ddd; + margin:8px 10px 25px 10px; + padding-bottom:5px +} + +/** 表格布局 **/ +.pagination-container { + position: relative; + height: 25px; + margin-bottom: 10px; + margin-top: 15px; + padding: 10px 20px !important; +} + +/* tree border */ +.tree-border { + margin-top: 5px; + border: 1px solid #e5e6e7; + background: #FFFFFF none; + border-radius:4px; +} + +.pagination-container .el-pagination { + right: 0; + position: absolute; +} + +@media ( max-width : 768px) { + .pagination-container .el-pagination > .el-pagination__jump { + display: none !important; + } + .pagination-container .el-pagination > .el-pagination__sizes { + display: none !important; + } +} + +.el-table .fixed-width .el-button--mini { + padding-left: 0; + padding-right: 0; + width: inherit; +} + +/** 表格更多操作下拉样式 */ +.el-button+.el-dropdown{margin-left: 10px;} + +.el-table .el-dropdown, .el-icon-arrow-down { + font-size: 12px; +} + +.el-tree-node__content > .el-checkbox { + margin-right: 8px; +} + +.list-group-striped > .list-group-item { + border-left: 0; + border-right: 0; + border-radius: 0; + padding-left: 0; + padding-right: 0; +} + +.list-group { + padding-left: 0px; + list-style: none; +} + +.list-group-item { + border-bottom: 1px solid #e7eaec; + border-top: 1px solid #e7eaec; + margin-bottom: -1px; + padding: 11px 0px; + font-size: 13px; +} + +.pull-right { + float: right !important; +} + +.el-card__header { + padding: 14px 15px 7px; + min-height: 40px; +} + +.el-card__body { + padding: 15px 20px 20px 20px; +} + +.card-box { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 10px; +} + +/* button color */ +.el-button--cyan.is-active, +.el-button--cyan:active { + background: #20B2AA; + border-color: #20B2AA; + color: #FFFFFF; +} + +.el-button--cyan:focus, +.el-button--cyan:hover { + background: #48D1CC; + border-color: #48D1CC; + color: #FFFFFF; +} + +.el-button--cyan { + background-color: #20B2AA; + border-color: #20B2AA; + color: #FFFFFF; +} + +/* text color */ +.text-navy { + color: #1ab394; +} + +.text-primary { + color: inherit; +} + +.text-success { + color: #1c84c6; +} + +.text-info { + color: #23c6c8; +} + +.text-warning { + color: #f8ac59; +} + +.text-danger { + color: #ed5565; +} + +.text-muted { + color: #888888; +} + +/* image */ +.img-circle { + border-radius: 50%; +} + +.img-lg { + width: 120px; + height: 120px; +} + +.avatar-upload-preview { + position: absolute; + top: 50%; + transform: translate(50%, -50%); + width: 200px; + height: 200px; + border-radius: 50%; + box-shadow: 0 0 4px #ccc; + overflow: hidden; +} + +/* 拖拽列样式 */ +.sortable-ghost{ + opacity: .8; + color: #fff!important; + background: #42b983!important; +} + +.top-right-btn { + position: relative; + float: right; +} diff --git a/ruoyi-ui/src/components/ThemePicker/index.vue b/ruoyi-ui/src/components/ThemePicker/index.vue index 4ba9bd27..30f0863f 100644 --- a/ruoyi-ui/src/components/ThemePicker/index.vue +++ b/ruoyi-ui/src/components/ThemePicker/index.vue @@ -1,173 +1,56 @@ - - - - - + + + + + diff --git a/ruoyi-ui/src/store/modules/settings.js b/ruoyi-ui/src/store/modules/settings.js index d08d8c2c..1c1fa751 100644 --- a/ruoyi-ui/src/store/modules/settings.js +++ b/ruoyi-ui/src/store/modules/settings.js @@ -1,42 +1,164 @@ -import defaultSettings from '@/settings' - -const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings - -const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' -const state = { - title: '', - theme: storageSetting.theme || '#409EFF', - sideTheme: storageSetting.sideTheme || sideTheme, - showSettings: showSettings, - topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav, - tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView, - fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader, - sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo, - dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle -} -const mutations = { - CHANGE_SETTING: (state, { key, value }) => { - if (state.hasOwnProperty(key)) { - state[key] = value - } - } -} - -const actions = { - // 修改布局设置 - changeSetting({ commit }, data) { - commit('CHANGE_SETTING', data) - }, - // 设置网页标题 - setTitle({ commit }, title) { - state.title = title - } -} - -export default { - namespaced: true, - state, - mutations, - actions -} - +import defaultSettings from '@/settings' + +const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings + +const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' + +import Vue from 'vue' +storageSetting.theme&&setThemeColor(storageSetting.theme) + +const state = { + title: '', + theme: storageSetting.theme || '#409EFF', + sideTheme: storageSetting.sideTheme || sideTheme, + showSettings: showSettings, + topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav, + tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView, + fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader, + sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo, + dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle +} +const mutations = { + CHANGE_SETTING: (state, { key, value }) => { + if (state.hasOwnProperty(key)) { + state[key] = value + if(key==='theme'){ + setThemeColor(value) + } + } + } +} + +const actions = { + // 修改布局设置 + changeSetting({ commit }, data) { + commit('CHANGE_SETTING', data) + }, + // 设置网页标题 + setTitle({ commit }, title) { + state.title = title + } +} + +function setThemeColor(val,oldColor){ + let chalk='' + let theme='' + const ORIGINAL_THEME = '#409EFF' + const version = require('element-ui/package.json').version + setTheme(val) + async function setTheme(val) { + const oldVal = chalk ? theme : ORIGINAL_THEME + if (typeof val !== 'string') return + const themeCluster = getThemeCluster(val.replace('#', '')) + const originalCluster = getThemeCluster(oldVal.replace('#', '')) + + const getHandler = (variable, id) => { + return () => { + const originalCluster = getThemeCluster(ORIGINAL_THEME.replace('#', '')) + const newStyle = updateStyle(Vue[variable], originalCluster, themeCluster) + + let styleTag = document.getElementById(id) + if (!styleTag) { + styleTag = document.createElement('style') + styleTag.setAttribute('id', id) + document.head.appendChild(styleTag) + } + styleTag.innerText = newStyle + } + } + + if (!chalk) { + const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css` + await getCSSString(url, 'chalk') + } + const chalkHandler = getHandler('chalk', 'chalk-style') + + chalkHandler() + const styles = [].slice.call(document.querySelectorAll('style')) + .filter(style => { + const text = style.innerText + return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text) + }) + styles.forEach(style => { + const { innerText } = style + if (typeof innerText !== 'string') return + style.innerText = updateStyle(innerText, originalCluster, themeCluster) + }) + } + + function updateStyle(style, oldCluster, newCluster) { + let newStyle = style + oldCluster.forEach((color, index) => { + newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index]) + }) + return newStyle + } + + function getCSSString(url, variable) { + return new Promise(resolve => { + const xhr = new XMLHttpRequest() + xhr.onreadystatechange = () => { + if (xhr.readyState === 4 && xhr.status === 200) { + Vue[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '') + resolve() + } + } + xhr.open('GET', url) + xhr.send() + }) + } + + function getThemeCluster(theme) { + const tintColor = (color, tint) => { + let red = parseInt(color.slice(0, 2), 16) + let green = parseInt(color.slice(2, 4), 16) + let blue = parseInt(color.slice(4, 6), 16) + + if (tint === 0) { // when primary color is in its rgb space + return [red, green, blue].join(',') + } else { + red += Math.round(tint * (255 - red)) + green += Math.round(tint * (255 - green)) + blue += Math.round(tint * (255 - blue)) + + red = red.toString(16) + green = green.toString(16) + blue = blue.toString(16) + + return `#${red}${green}${blue}` + } + } + + const shadeColor = (color, shade) => { + let red = parseInt(color.slice(0, 2), 16) + let green = parseInt(color.slice(2, 4), 16) + let blue = parseInt(color.slice(4, 6), 16) + + red = Math.round((1 - shade) * red) + green = Math.round((1 - shade) * green) + blue = Math.round((1 - shade) * blue) + + red = red.toString(16) + green = green.toString(16) + blue = blue.toString(16) + + return `#${red}${green}${blue}` + } + + const clusters = [theme] + for (let i = 0; i <= 9; i++) { + clusters.push(tintColor(theme, Number((i / 10).toFixed(2)))) + } + clusters.push(shadeColor(theme, 0.1)) + return clusters + } +} + + +export default { + namespaced: true, + state, + mutations, + actions +} + diff --git a/ruoyi-ui/src/views/monitor/job/index.vue b/ruoyi-ui/src/views/monitor/job/index.vue index 258eb4a1..71767b2e 100644 --- a/ruoyi-ui/src/views/monitor/job/index.vue +++ b/ruoyi-ui/src/views/monitor/job/index.vue @@ -1,515 +1,513 @@ - - - \ No newline at end of file + + + diff --git a/ruoyi-ui/src/views/system/role/index.vue b/ruoyi-ui/src/views/system/role/index.vue index 0681d3d2..796743be 100644 --- a/ruoyi-ui/src/views/system/role/index.vue +++ b/ruoyi-ui/src/views/system/role/index.vue @@ -1,607 +1,605 @@ - - - \ No newline at end of file + + + diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue index a26a33f8..6b515470 100644 --- a/ruoyi-ui/src/views/system/user/index.vue +++ b/ruoyi-ui/src/views/system/user/index.vue @@ -1,669 +1,667 @@ - - - \ No newline at end of file + + +