Feat addtheme (#1864)

* feat: 删除没用的css文件

* feat: 添加修改主题组件

* feat: 设置全局css变量

* feat: 替换修改主题方法

* perf: 修改 bg color

* perf: 修改 left bar css

* perf: 修改 element

* perf: 暂存与喜爱

* feat: 添加颜色转换方法

* perf: 修改一些

* perf: 修改颜色

* feat: 修改默认elemet-ui样式

* feat: 暂存

* feat: 添加切换菜单栏颜色方法

* feat: 调整配置颜色

* feat: 调整主题相关配色
1、修复弹窗出现黑屏问题
2、修复左侧菜单展开、折叠出现白色闪动问题
3、迁移element-ui.scss文件内容到extra.css文件里

* feat: 调整styles下文件结构;升级sass插件修复构建提示语法错误问题

* feat: 拆分主题配置文件;添加设置到基本设置里

* feat: 修复public-fonts目录下文件内容

* fix: 解决冲突

* feat: 修改颜色配置

Co-authored-by: ibuler <ibuler@qq.com>
This commit is contained in:
huailei
2022-07-05 20:06:28 +08:00
committed by GitHub
parent be842a3e3a
commit ab4b4d5230
38 changed files with 836 additions and 446 deletions

View File

@@ -26,6 +26,7 @@
"axios-retry": "^3.1.9",
"cron-parser": "^4.0.0",
"crypto-js": "^4.1.1",
"css-color-function": "^1.3.3",
"deepmerge": "^4.2.2",
"echarts": "^4.7.0",
"element-ui": "2.13.2",
@@ -96,7 +97,7 @@
"lint-staged": "^10.1.2",
"mockjs": "1.0.1-beta3",
"runjs": "^4.3.2",
"sass": "^1.26.10",
"sass": "~1.32.6",
"sass-loader": "^7.1.0",
"script-ext-html-webpack-plugin": "2.1.3",
"script-loader": "0.7.2",

Binary file not shown.

Binary file not shown.

View File

@@ -9,23 +9,7 @@
<meta http-equiv="Cache" content="no-cache">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title><%= webpackConfig.name %></title>
<style>
::-webkit-scrollbar {
width:14px;
}
::-webkit-scrollbar-track {
border-radius:10px;
}
::-webkit-scrollbar-thumb {
border-radius: 8px;
box-shadow: 8px 10px 20px #C6C6C6 inset;
border: 3px solid rgba(0, 0, 0, 0);
}
::-webkit-scrollbar-thumb:hover {
box-shadow: 8px 10px 20px #878787 inset;
}
</style>
<link rel="stylesheet" href="<%= BASE_URL %>theme/index.css">
</head>
<body>
<noscript>

23
public/theme/README.md Normal file
View File

@@ -0,0 +1,23 @@
# 主题颜色
```
alpha-1: "rgba(64, 158, 255, 0.1)"
alpha-2: "rgba(64, 158, 255, 0.2)"
alpha-3: "rgba(64, 158, 255, 0.3)"
alpha-4: "rgba(64, 158, 255, 0.4)"
alpha-5: "rgba(64, 158, 255, 0.5)"
alpha-6: "rgba(64, 158, 255, 0.6)"
alpha-7: "rgba(64, 158, 255, 0.7)"
alpha-8: "rgba(64, 158, 255, 0.8)"
alpha-9: "rgba(64, 158, 255, 0.9)"
light-1: "#53a8ff"
light-2: "#66b1ff"
light-3: "#79bbff"
light-4: "#8cc5ff"
light-5: "#a0cfff"
light-6: "#b3d8ff"
light-7: "#c6e2ff"
light-8: "#d9ecff"
light-9: "#ecf5ff"
primary: "#409EFF"
```
primary是初始主题颜色其他颜色均属于primary的系列颜色

412
public/theme/extra.css Normal file
View File

@@ -0,0 +1,412 @@
/* 这里只写element-variables里面改不动的、且和主题系列颜色相关的样式 */
/* 主题相关看该文件夹下的README.md */
.el-alert--info.is-light {
background-color: light-9;
color: light-2;
border: 1px solid;
}
.el-alert--info .el-alert__description {
color: light-2;
}
.el-select-dropdown__item.hover, .el-select-dropdown__item:hover {
background-color: primary;
color: white!important;
}
.el-pagination.is-background .el-pager li:not(.disabled):hover {
color: white;
background-color: primary;
}
.el-pagination.is-background .btn-next, .el-pagination.is-background .btn-prev, .el-pagination.is-background .el-pager li {
margin: 0 5px;
background-color: white;
color: #606266;
min-width: 28px;
border-radius: 2px;
border: 1px solid #DCDFE6;
font-size: 12px;
line-height: 26px;
font-weight: 400;
}
.el-breadcrumb__inner,
.el-breadcrumb__inner a {
font-weight: 400 !important;
}
.el-upload input[type="file"] {
display: none !important;
}
.el-upload__input {
display: none;
}
.upload-container .el-upload {
width: 100%;
}
.upload-container .el-upload .el-upload-dragger {
width: 100%;
height: 200px;
}
.el-dropdown-menu a {
display: block
}
.el-table th > .cell {
color: rgb(104, 106, 108);
}
.el-range-separator {
box-sizing: content-box;
}
td .el-button.el-button--mini {
padding: 1px 5px;
line-height: 1.5;
}
.el-tabs__item.is-active, .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active {
color: #555555;
}
.el-tabs--border-card>.el-tabs__header .el-tabs__item:not(.is-disabled):hover {
color: #555555;
}
.main-container {
background-color: #f3f3f4;
}
.el-dropdown:hover {
cursor: pointer;
}
.el-dropdown-menu__item:focus, .el-dropdown-menu__item:not(.is-disabled):hover {
background-color: #f5f5f5;
color: inherit;
}
.el-tabs__item:hover {
color: inherit;
}
.el-tabs__item.is-active {
font-weight: 600;
}
.el-button.el-button--default:hover:not(.is-disabled) {
color: #606266;
border-color: #d2d2d2;
background-color: #e6e6e6;
}
.el-button-group>.el-dropdown>.el-button {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-left-color: rgb(220, 223, 230);
}
.el-alert__content {
line-height: 1.5;
}
.el-card__header {
padding: 10px 15px;
font-size: 14px;
line-height: 18.5px;
font-weight: normal;
color: #333;
}
.el-card.primary > .el-card__header {
background-color: primary;
border-color: primary;
color: white;
}
.el-card.success > .el-card__header {
background-color: success;
border-color: success;
color: #ffffff;
}
.el-card.info > .el-card__header {
background-color: info;
border-color: info;
color: #ffffff;
}
.el-card.warning > .el-card__header {
background-color: warning;
border-color: warning;
color: #ffffff;
}
.el-card.danger > .el-card__header {
background-color: danger;
border-color: danger;
color: #ffffff;
}
.el-input__inner {
background-color: #FFFFFF;
background-image: none;
border: 1px solid #e5e6e7;
border-radius: 1px;
color: inherit;
display: block;
padding: 6px 12px;
transition: border-color 0.15s ease-in-out 0s, box-shadow 0.15s ease-in-out 0s;
width: 100%;
font-size: 14px;
line-height: 1.5;
height: 34px;
}
.el-input--small .el-input__inner {
height: 34px;
}
.el-input--small .el-input__icon {
line-height: 34px;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected {
color: #606266;
background-color: #ddd;
font-weight: 400;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected {
color: #606266;
background-color: #ddd;
font-weight: 400;
}
.el-select-dropdown__item.hover, .el-select-dropdown__item:hover {
background-color: primary;
color: white!important;
}
.el-select-dropdown__item.is-disabled:hover{
color:#c0c4cc;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after {
color: primary;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover {
color: white;
background-color: primary;
}
.el-tag.el-tag--info {
background-color: #f1f1f1!important;
border-color: #e5e6e7!important;
color: #333333!important;
}
.el-tag.el-tag--info .el-tag__close {
color: #333333!important;
background-color: inherit;
}
.el-tag.el-tag--info.is-hit {
border-color: #e5e6e7!important;
}
.el-tag.el-tag--info .el-tag__close:hover {
color: #000000;
font-weight: 600;
background-color: inherit;
}
.el-table .ascending .sort-caret.ascending {
border-bottom-color: #676a6c;
}
.el-table .descending .sort-caret.descending {
border-top-color: #676a6c;
}
.text-danger {
color: danger;
}
.text-primary {
color: primary;
}
.text-info {
color: info;
}
.text-warning {
color: warning;
}
.text-success {
color: success;
}
.el-radio__input.is-checked+.el-radio__label {
color: inherit;
}
.el-textarea__inner {
border-radius: 0;
}
.el-pagination.is-background .number {
padding: 0;
}
.el-card.primary .el-card__header {
background-color: primary;
}
.el-card.success .el-card__header {
background-color: success;
}
.el-card.info .el-card__header {
background-color: info;
}
.el-card.warning .el-card__header {
background-color: warning;
}
.el-card.danger .el-card__header {
background-color: danger;
}
.el-message-box__headerbtn .el-message-box__close {
color: #606266;
}
.el-tooltip__popper.is-light {
background: #FFF;
border: 1px solid #e7eaec;
}
.el-tooltip__popper.is-light .popper__arrow {
border-bottom-color: #e7eaec !important;
}
.el-dialog__headerbtn .el-dialog__close {
color: #000;
opacity: .2;
}
.el-table__header thead tr th {
border-bottom: 1px solid #e7e7e7 !important;
}
.el-table .cell, .el-table--border td:first-child .cell, .el-table--border th:first-child .cell {
padding-left: 10px;
padding-right: 14px;
}
.el-tag--default.el-tag--dark {
background-color: #d1dade;
color: #5e5e5e;
border: none;
}
.el-card {
color: #676a6c;
}
.el-table__empty-block {
width: 100% !important;
}
.el-dialog__headerbtn .el-dialog__close {
font-size: 21px;
font-weight: 700;
color: #000;
text-shadow: 0 1px 0 #fff;
}
.el-dialog__headerbtn:focus .el-dialog__close, .el-dialog__headerbtn:hover .el-dialog__close {
color: #000;
font-size: 22px;
font-weight: 800;
}
.el-tag--default.el-tag--dark {
background-color: #d1dade;
color: #5e5e5e;
border: none;
}
.el-card {
color: #676a6c;
}
.el-table__empty-block {
width: 100% !important;
}
.el-dialog__headerbtn .el-dialog__close {
font-size: 21px;
font-weight: 700;
color: #000;
text-shadow: 0 1px 0 #fff;
}
.el-dialog__headerbtn:focus .el-dialog__close, .el-dialog__headerbtn:hover .el-dialog__close {
color: #000;
font-size: 22px;
font-weight: 800;
}
.el-button--danger.is-plain {
color: danger;
background: #ffffff;
border-color: danger;
}
.el-alert .el-alert__description {
margin: 1px 0 0;
}
.el-table {
font-size: 13px;
}
.el-dialog {
position: absolute;
top: 50%;
left: 50%;
margin: 0 !important;
transform: translate(-50%, -50%);
max-height: calc(100% - 30px);
max-width: calc(100% - 30px);
display: flex;
flex-direction: column;
}
.el-dialog .el-dialog__body {
max-height: 90vh;
overflow: auto;
}
.el-cascader {
line-height: 34px;
}
.el-input__icon {
line-height: 34px;
}

1
public/theme/index.css Normal file

File diff suppressed because one or more lines are too long

View File

@@ -9,3 +9,19 @@ export default {
name: 'App'
}
</script>
<style>
:root {
--color-primary: #1ab394;
--color-success: #1c84c6;
--color-info: #23c6c8;
--color-warning: #f8ac59;
--color-danger: #ed5565;
--menu-bg: #2f4050;
--menu-text: #a7b1c2;
--menu-hover: '#293846';
--submenu-bg: '#1f2d3d';
--submenu-hover: '#3b4c5b';
--menu-active-left: #1ab394;
}
</style>

View File

@@ -67,8 +67,8 @@ export default {
display: none;
}
&>>> .jsoneditor-menu {
background: $--color-primary;
border-bottom: 1px solid $--color-primary;
background: var(--color-primary);
border-bottom: 1px solid var(--color-primary);
}
}
</style>

View File

@@ -108,14 +108,13 @@ export default {
</script>
<style lang="scss" scoped>
@import "~@/styles/variables";
.mini-button{
width: 12px;
float: right;
text-align: center;
padding: 5px 0;
background-color: $--color-primary;
border-color: $--color-primary;
background-color: var(--color-primary);
border-color: var(--color-primary);
color: #FFFFFF;
border-radius: 3px;
line-height: 1.428;

View File

@@ -28,3 +28,4 @@ export { default as AssetRelationCard } from './AssetRelationCard'
export { default as UserConfirmDialog } from './UserConfirmDialog'
export { default as Announcement } from './Announcement'
export { default as CronTab } from './CronTab'
export { default as ThemePicker } from './ThemePicker'

View File

@@ -1522,6 +1522,9 @@
"technologyConsult": "Technology Consult",
"RegularlyPerform": "Regularly perform",
"CyclePerform": "Cycle perform",
"ModifyTheme": "Modify theme",
"ClassicGreen": "Classic green",
"ChinaRed": "China red",
"HelpText": {
"CrontabOfCreateUpdatePage": "For example: every Sunday at 03:05 execute <5 3 * * 0> <br/> Using the 5-bit Linux crontab expression <minute hour day month week> (<a href=\"https://tool.lu/crontab/\" target=\"_blank\"> Online tool </a>) <br/> If both regularly perform and cycle perform execution are set, use regularly perform first",
"IntervalOfCreateUpdatePage": "Unit: hour",

View File

@@ -1569,6 +1569,9 @@
"technologyConsult": "技術コンサルティング",
"RegularlyPerform": "定期的に実行する",
"CyclePerform": "サイクル実行",
"ModifyTheme": "テーマを変更",
"ClassicGreen": "クラシックグリーン",
"ChinaRed": "チャイナレッド",
"HelpText": {
"CrontabOfCreateUpdatePage": "例: 毎週日曜日03:05に <5 3 * * 0> <br/> 5桁のLinux crontab式を使用して、時分割日月曜日> (<a href = \"https://tool.lu/crontab/\" target = \"_ ツール </a>) <br/> 定期実行とサイクル実行を同時に設定している場合は、優先的に定期実行を使って",
"IntervalOfCreateUpdatePage": "単位: 時",

View File

@@ -1571,6 +1571,9 @@
"technologyConsult": "技术咨询",
"RegularlyPerform": "定期执行",
"CyclePerform": "周期执行",
"ModifyTheme": "修改主题",
"ClassicGreen": "经典绿",
"ChinaRed": "中国红",
"HelpText": {
"CrontabOfCreateUpdatePage": "例如:每周日 03:05 执行 <5 3 * * 0> <br/> 使用5位 Linux crontab 表达式 <分 时 日 月 星期> <a href=\"https://tool.lu/crontab/\" target=\"_blank\">在线工具</a> <br/> 如果同时设置了定期执行和周期执行,优先使用定期执行",
"IntervalOfCreateUpdatePage": "单位:时",

View File

@@ -14,6 +14,12 @@ import i18n from './i18n/i18n'
import '@/icons' // icon
import '@/guards' // permission control
import '@/directive'
import { getIndexStyle } from '@/utils/theme/index'
// 初始化主题样式
getIndexStyle().then(() => {
store.dispatch('settings/changeThemeStyle')
})
/**
* If you don't want to use mock-server

View File

@@ -1,5 +1,7 @@
import defaultSettings from '@/settings'
import { getPublicSettings } from '@/api/settings'
import { writeNewStyle } from '@/utils/theme/index'
import { matchColor, defaultThemeColor } from '@/utils/theme/color'
const { showSettings, fixedHeader, sidebarLogo, tagsView } = defaultSettings
@@ -9,7 +11,8 @@ const state = {
sidebarLogo: sidebarLogo,
tagsView: tagsView,
publicSettings: null,
hasValidLicense: false
hasValidLicense: false,
themeColor: localStorage.getItem('themeColor') || defaultThemeColor
}
const mutations = {
@@ -19,11 +22,17 @@ const mutations = {
}
},
SET_PUBLIC_SETTINGS: (state, settings) => {
const color = settings.INTERFACE?.theme
state.publicSettings = settings
state.themeColor = matchColor[color] || defaultThemeColor
if (settings['XPACK_ENABLED']) {
state.hasValidLicense = settings['XPACK_LICENSE_IS_VALID']
}
},
setTheme(state, data) {
state.themeColor = data
localStorage.setItem('themeColor', state.themeColor)
}
}
@@ -57,6 +66,9 @@ const actions = {
reject(error)
})
})
},
changeThemeStyle({ state }) {
writeNewStyle(state.themeColor)
}
}

View File

@@ -1,105 +1,7 @@
@import "./variables";
$--font-path: '~element-ui/lib/theme-chalk/fonts';
// $--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";
.el-breadcrumb__inner,
.el-breadcrumb__inner a {
font-weight: 400 !important;
}
.el-upload {
input[type="file"] {
display: none !important;
}
}
.el-upload__input {
display: none;
}
// to fixed https://github.com/ElemeFE/element/issues/2461
.el-dialog {
transform: none;
left: 0;
position: relative;
margin: 0 auto;
}
// refine element ui upload
.upload-container {
.el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
height: 200px;
}
}
}
// dropdown
.el-dropdown-menu {
a {
display: block
}
}
.el-table th > .cell {
color: rgb(104, 106, 108);
}
// to fix el-date-picker css style
.el-range-separator {
box-sizing: content-box;
}
td .el-button.el-button--mini {
padding: 1px 5px;
line-height: 1.5;
}
.el-tabs__item.is-active, .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active {
color: #555555;
}
.el-tabs--border-card>.el-tabs__header .el-tabs__item:not(.is-disabled):hover {
color: #555555;
}
.main-container {
background-color: #f3f3f4;
}
.el-dropdown:hover {
cursor: pointer;
}
.el-dropdown-menu__item:focus, .el-dropdown-menu__item:not(.is-disabled):hover {
background-color: #f5f5f5;
color: inherit;
}
.el-tabs__item:hover {
color: inherit;
}
.el-tabs__item.is-active {
font-weight: 600;
}
.el-button.el-button--default:hover:not(.is-disabled) {
color: #606266;
border-color: #d2d2d2;
background-color: #e6e6e6;
}
.el-button-group>.el-dropdown>.el-button {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-left-color: rgb(220, 223, 230);
}
.el-alert--success.is-light {
border: $--color-success-light 1px solid;
}
@@ -108,161 +10,12 @@ td .el-button.el-button--mini {
border: $--color-info-light 1px solid;
}
.el-alert__content {
line-height: 1.5;
}
.el-card__header {
padding: 10px 15px;
font-size: 14px;
line-height: 18.5px;
font-weight: normal;
color: #333;
}
.el-card.primary > .el-card__header {
background-color: $--color-primary;
border-color: $--color-primary;
color: white;
}
.el-card.success > .el-card__header {
background-color: $--color-success;
border-color: $--color-success;
color: #ffffff;
}
.el-card.info > .el-card__header {
background-color: $--color-info;
border-color: $--color-info;
color: #ffffff;
}
.el-card.warning > .el-card__header {
background-color: $--color-warning;
border-color: $--color-warning;
color: #ffffff;
}
.el-card.danger > .el-card__header {
background-color: $--color-danger;
border-color: $--color-danger;
color: #ffffff;
}
.el-input__inner {
background-color: #FFFFFF;
background-image: none;
border: 1px solid #e5e6e7;
border-radius: 1px;
color: inherit;
display: block;
padding: 6px 12px;
transition: border-color 0.15s ease-in-out 0s, box-shadow 0.15s ease-in-out 0s;
width: 100%;
font-size: 14px;
line-height: 1.5;
height: 34px;
}
.el-input--small .el-input__inner {
height: 34px;
}
.el-input--small .el-input__icon {
line-height: 34px;
}
.el-select-dropdown__item.selected {
font-weight: 400;
color: $--color-text-primary;
background-color: #ddd;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected {
color: #606266;
background-color: #ddd;
font-weight: 400;
}
//.el-select-dropdown.is-multiple .el-select-dropdown__item.selected {
// color: #606266;
// background-color: #ddd;
// font-weight: 400;
//}
.el-select-dropdown__item.hover, .el-select-dropdown__item:hover {
background-color: $--color-primary;
color: white;
}
.el-select-dropdown__item.is-disabled:hover{
color:#c0c4cc;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after {
color: $--color-primary;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover {
color: white;
background-color: $--color-primary;
}
.el-tag.el-tag--info {
background-color: #f1f1f1;
border-color: #e5e6e7;
color: #333333;
}
.el-tag.el-tag--info .el-tag__close {
color: #333333;
background-color: inherit;
}
.el-tag.el-tag--info.is-hit {
border-color: #e5e6e7;
}
.el-tag.el-tag--info .el-tag__close:hover {
color: #000000;
font-weight: 600;
background-color: inherit;
}
.el-table .ascending .sort-caret.ascending {
border-bottom-color: #676a6c;
}
.el-table .descending .sort-caret.descending {
border-top-color: #676a6c;
}
.text-danger {
color: $--color-danger;
}
.text-primary {
color: $--color-primary;
}
.text-info {
color: $--color-info;
}
.text-warning {
color: $--color-warning;
}
.text-success {
color: $--color-success;
}
.el-radio__input.is-checked+.el-radio__label {
color: inherit;
}
.el-radio__input.is-checked .el-radio__inner {
border-color: #409EFF;
background-color: #409EFF;
@@ -277,10 +30,6 @@ td .el-button.el-button--mini {
border-color: #409EFF;
}
.el-textarea__inner {
border-radius: 0;
}
.el-checkbox__input.is-checked .el-checkbox__inner, .el-checkbox__input.is-indeterminate .el-checkbox__inner {
border-color: #409EFF;
background-color: #409EFF;
@@ -298,129 +47,12 @@ td .el-button.el-button--mini {
border-color: #409EFF;
}
.el-pagination.is-background .btn-next, .el-pagination.is-background .btn-prev, .el-pagination.is-background .el-pager li {
margin: 0 5px;
background-color: white;
color: #606266;
min-width: 28px;
border-radius: 2px;
border: 1px solid #DCDFE6;
font-size: 12px;
line-height: 26px;
font-weight: 400;
}
.el-pagination.is-background .el-pager li:not(.disabled):hover {
color: white;
background-color: $--color-primary;
}
.el-pagination.is-background .number {
padding: 0;
}
.el-message-box__headerbtn .el-message-box__close {
color: #606266;
}
.el-card.primary {
.el-card__header {
background-color: $--color-primary;
}
}
.el-card.success {
.el-card__header {
background-color: $--color-success;
}
}
.el-card.info {
.el-card__header {
background-color: $--color-info;
}
}
.el-card.warning {
.el-card__header {
background-color: $--color-warning;
}
}
.el-card.danger {
.el-card__header {
background-color: $--color-danger;
}
}
.el-tooltip__popper.is-light {
background: #FFF;
border: 1px solid #e7eaec;
}
.el-tooltip__popper.is-light .popper__arrow {
border-bottom-color: #e7eaec !important;
}
.el-dialog__headerbtn .el-dialog__close {
color: #000;
opacity: .2;
}
.el-table__header thead tr th {
border-bottom: 1px solid #e7e7e7 !important;
}
.el-table .cell, .el-table--border td:first-child .cell, .el-table--border th:first-child .cell {
padding-left: 10px;
padding-right: 14px;
}
.el-tag--dark.el-tag--info {
background-color: #23c6c8;
border-color: #23c6c8;
color: #fff;
}
.el-tag--default.el-tag--dark {
background-color: #d1dade;
color: #5e5e5e;
border: none;
}
.el-card {
color: #676a6c;
}
.el-table__empty-block {
width: 100% !important;
}
.el-dialog__headerbtn .el-dialog__close {
font-size: 21px;
font-weight: 700;
color: #000;
text-shadow: 0 1px 0 #fff;
}
.el-dialog__headerbtn:focus .el-dialog__close, .el-dialog__headerbtn:hover .el-dialog__close {
color: #000;
font-size: 22px;
font-weight: 800;
//color: red;
}
.el-button--danger.is-plain {
color: $--color-danger;
background: #ffffff;
border-color: $--color-danger;
}
.el-alert .el-alert__description {
margin: 1px 0 0;
}
.el-input-group__prepend div.el-select .el-input__inner {
color: $--color-text-primary;
}
@@ -429,35 +61,10 @@ td .el-button.el-button--mini {
color: $--color-text-primary;
}
.el-table {
font-size: 13px;
}
.el-table-filter__list-item:hover {
color: $--color-text-primary;
}
.el-dialog {
// 居中弹框
position: absolute;
top: 50%;
left: 50%;
margin: 0 !important;
transform: translate(-50%, -50%);
// 防止超出视窗
max-height: calc(100% - 30px);
max-width: calc(100% - 30px);
//实现body内部滚动
display: flex;
flex-direction: column;
.el-dialog__body {
max-height: 90vh;
overflow: auto;
}
}
.el-button--text {
color: $--color-link;
padding: 5px;
@@ -467,11 +74,3 @@ td .el-button.el-button--mini {
color: $--color-link-highlight;
background-color: rgba(0,0,0,.05)
}
.el-cascader {
line-height: 34px;
}
.el-input__icon {
line-height: 34px;
}

View File

@@ -1,18 +1,30 @@
@import './mixin.scss';
@import './transition.scss';
@import './variables.scss';
@import './sidebar.scss';
@import './element-ui.scss';
@import './menu.scss';
@import './font-awesome/font-awesome.min.css';
::-webkit-scrollbar {
width:14px;
}
::-webkit-scrollbar-track {
border-radius:10px;
}
::-webkit-scrollbar-thumb {
border-radius: 8px;
box-shadow: 8px 10px 20px #C6C6C6 inset;
border: 3px solid rgba(0, 0, 0, 0);
}
::-webkit-scrollbar-thumb:hover {
box-shadow: 8px 10px 20px #878787 inset;
}
body {
height: 100%;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: auto;
//text-rendering: optimizeLegibility;
color: #676a6c;
//font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 13px;
line-height: 1.428;

View File

@@ -1,5 +1,8 @@
@import "./variables";
.left-menu.el-menu {
.el-menu--inline {
background-color: $subMenuBg;
}
.el-menu-item, .el-submenu {
font-weight: 600;
}

View File

@@ -5,8 +5,13 @@ $--color-info: #f06f06;
$--color-warning: #b17b4e;
$--color-danger: #122b58;
// Text
$--color-text-primary: #303133;
$--color-text-regular: #606266;
// Menu
$menuBg: #b4312b;
$menuActiveLeft: #fff1d9;
$menuText: #fff1d9;
$menuActiveText: white;
$subMenuActiveText: white;

View File

@@ -5,8 +5,13 @@ $--color-info: #23c6c8;
$--color-warning: #f8ac59;
$--color-danger: #ed5565;
// Text
$--color-text-primary: #303133;
$--color-text-regular: #606266;
// Menu
$menuText: #a7b1c2;
$menuActiveLeft: $--color-primary;
$menuText: var(--menu-text);
$menuActiveLeft: var(--menu-active-left);
$menuActiveText: white;
$menuBg: #2f4050;
$subMenuActiveText: #f4f4f5;
$menuBg: var(--menu-bg);

View File

@@ -0,0 +1,17 @@
// ElementUI
$--color-primary: #1ab394;
$--color-success: #1c84c6;
$--color-info: #23c6c8;
$--color-warning: #f8ac59;
$--color-danger: #ed5565;
// Text
$--color-text-primary: #303133;
$--color-text-regular: #606266;
// Menu
$menuText: var(--menu-text);
$menuActiveLeft: var(--menu-active-left);
$menuActiveText: white;
$subMenuActiveText: #f4f4f5;
$menuBg: var(--menu-bg);

11
src/styles/var.scss Normal file
View File

@@ -0,0 +1,11 @@
/* 参考根目录下的 element-variables */
/* 切记此处不修改配置以element-variables为准可适当增加自定义配置 */
/* 如果要修改element-variables请执行npm run build_theme更新主题 */
@import "./element-variables.scss";
:export {
name: "scss";
themeColor: $--color-primary;
themeInfo: $--color-info;
themeSuccess:$--color-success;
}

View File

@@ -1,5 +1,5 @@
@import "./themes/chinese_red";
//@import "./themes/default";
// @import "src/styles/themes/chinese_red";
@import "./themes/default";
$--color-text-primary: #303133;
$--color-text-regular: #606266;
@@ -10,9 +10,9 @@ $--color-link: $--color-text-primary;
$--color-link-highlight: #23527c;
$menuTextWeight: 600;
$menuHover: mix($--color-black, $menuBg, 10%);
$subMenuBg: mix($--color-black, $menuBg, 20%);
$subMenuHover: mix($--color-black, $menuBg, 30%);
$menuHover: var(--menu-hover);
$subMenuBg: var(--submenu-bg);
$subMenuHover: var(--submenu-hover);
$sideBarWidth: 220px;
:export {

89
src/utils/theme/color.js Normal file
View File

@@ -0,0 +1,89 @@
import color from 'css-color-function'
import formula from './formula.json'
import themeOptions from './themeOptions.js'
import defaultThemeConfig from './themeConfigs/default.js'
const [defaultThemeConfigKey, defaultThemeConfigValue] = Object.entries(defaultThemeConfig)[0]
export const defaultThemeColor = defaultThemeConfigKey
export const matchColor = {
classic: '#1ab394',
chinese_red: '#bd1a2d',
tech_blue: '#174779',
deep_black: '#0576b9'
}
export function generateColors(primary) {
const colors = {}
const otherColor = themeOptions[primary] || defaultThemeConfigValue || {}
Object.keys(formula).forEach((key) => {
let value
const valueKey = formula[key]
if (valueKey.includes('primary')) {
value = valueKey.replace(/primary/g, primary)
}
if (valueKey.includes('success')) {
value = valueKey.replace(/success/g, otherColor['--color-success'])
}
if (valueKey.includes('info')) {
value = valueKey.replace(/info/g, otherColor['--color-info'])
}
if (valueKey.includes('warning')) {
value = valueKey.replace(/warning/g, otherColor['--color-warning'])
}
if (valueKey.includes('danger')) {
value = valueKey.replace(/danger/g, otherColor['--color-danger'])
}
if (value) {
const c = color.convert(value)
colors[key] = c.indexOf('rgba') > -1 ? c : colorRgbToHex(c)
}
})
return colors
}
/* 将rgb颜色转成hex */
export function colorRgbToHex(rgb) {
const [r, g, b] = rgb.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
return '#' + ((1 << 24) + (Number(r) << 16) + (Number(g) << 8) + Number(b)).toString(16).slice(1)
}
export function mix(color_1, color_2, weight) {
function d2h(d) { return d.toString(16) }
function h2d(h) { return parseInt(h, 16) }
weight = (typeof weight !== 'undefined') ? weight : 50
let color = '#'
for (var i = 0; i <= 5; i += 2) {
const v1 = h2d(color_1.substr(i, 2))
const v2 = h2d(color_2.substr(i, 2))
let val = d2h(Math.floor(v2 + (v1 - v2) * (weight / 100.0)))
while (val.length < 2) { val = '0' + val }
color += val
}
return color
}
export function changeSidebarColor(primary) {
const colors = themeOptions[primary] || defaultThemeConfigValue || {}
const elementStyle = document.documentElement.style
for (const key in colors) {
const currentColor = colors[key]
const changeColor = currentColor.replace(/#/g, '')
elementStyle.setProperty(key, currentColor)
if (key === '--menu-text') {
elementStyle.setProperty('--menu-hover', mix('000000', changeColor, 10))
elementStyle.setProperty('--submenu-bg', mix('000000', changeColor, 20))
elementStyle.setProperty('--submenu-hover', mix('000000', changeColor, 30))
}
elementStyle.setProperty('--color-primary', primary)
}
}

View File

@@ -0,0 +1,34 @@
{
"primary": "color(primary)",
"success": "color(success)",
"info": "color(info)",
"warning": "color(warning)",
"danger": "color(danger)",
"shade-1": "color(primary shade(10%))",
"shade-2": "color(primary shade(20%))",
"shade-3": "color(primary shade(30%))",
"shade-4": "color(primary shade(40%))",
"shade-5": "color(primary shade(50%))",
"shade-6": "color(primary shade(60%))",
"shade-7": "color(primary shade(70%))",
"shade-8": "color(primary shade(80%))",
"shade-9": "color(primary shade(90%))",
"alpha-1": "color(primary alpha(.1))",
"alpha-2": "color(primary alpha(.2))",
"alpha-3": "color(primary alpha(.3))",
"alpha-4": "color(primary alpha(.4))",
"alpha-5": "color(primary alpha(.5))",
"alpha-6": "color(primary alpha(.6))",
"alpha-7": "color(primary alpha(.7))",
"alpha-8": "color(primary alpha(.8))",
"alpha-9": "color(primary alpha(.9))",
"light-1": "color(primary tint(10%))",
"light-2": "color(primary tint(20%))",
"light-3": "color(primary tint(30%))",
"light-4": "color(primary tint(40%))",
"light-5": "color(primary tint(50%))",
"light-6": "color(primary tint(60%))",
"light-7": "color(primary tint(70%))",
"light-8": "color(primary tint(80%))",
"light-9": "color(primary tint(90%))"
}

60
src/utils/theme/index.js Normal file
View File

@@ -0,0 +1,60 @@
import { generateColors, changeSidebarColor } from './color'
import axios from 'axios'
import formula from './formula.json'
import variables from '@/styles/var.scss'
let originalStyle = ''
export function writeNewStyle(themeColor) {
const colors = generateColors(themeColor)
let cssText = originalStyle
let colorsCssText = ''
Object.keys(colors).forEach((key) => {
cssText = cssText.replace(new RegExp('(:|\\s+)' + key, 'g'), '$1' + `${colors[key]}`)
colorsCssText += `
.color-${key}{color: ${colors[key]}!important;}
.bg-${key}{background-color: ${colors[key]}!important;}
.border-${key}{border-color: ${colors[key]}!important;}
`
})
let styleTag = document.getElementById('themeStyle')
if (!styleTag) {
styleTag = document.createElement('style')
styleTag.setAttribute('id', 'themeStyle')
document.head.appendChild(styleTag)
}
changeSidebarColor(themeColor)
styleTag.innerText = cssText + colorsCssText
}
export function getIndexStyle() {
return new Promise((resolve) => {
if (!originalStyle) {
axios.all([axios.get('/theme/index.css'), axios.get('/theme/extra.css')]).then(
axios.spread((file, extraFile) => {
const fileData = file.data
const extraFileData = extraFile.data.replace(/[\r\n]/g, '')
originalStyle = getStyleTemplate(fileData + extraFileData)
resolve()
})
)
} else {
resolve()
}
})
}
export function getStyleTemplate(data) {
const colors = generateColors(variables.themeColor)
const colorMap = new Map()
Object.keys(formula).forEach((key) => {
colorMap.set(colors[key], key)
})
for (const [key, value] of colorMap) {
data = data.replace(new RegExp(key, 'ig'), value)
}
return data
}

View File

@@ -0,0 +1,16 @@
const config = {
'#bd1a2d': {
'--color-success': '#E98737',
'--color-info': '#f06f06',
'--color-warning': '#f82ed3',
'--color-danger': '#074bdc',
'--menu-bg': '#b4312b',
'--menu-text': '#fff1d9',
'--menu-hover': '#a22c27',
'--submenu-bg': '#902722',
'--submenu-hover': '#7e221e',
'--menu-active-left': 'rgb(241, 212, 174)'
}
}
export default config

View File

@@ -0,0 +1,16 @@
const config = {
'#0576b9': {
'--color-success': '#2cb57e',
'--color-info': '#47bce8',
'--color-warning': '#f5bd58',
'--color-danger': '#f56e50',
'--menu-bg': '#121e2d',
'--menu-text': '#8fa6bf',
'--menu-hover': '#101b29',
'--submenu-bg': '#0e1824',
'--submenu-hover': '#0d1520',
'--menu-active-left': '#0576b9'
}
}
export default config

View File

@@ -0,0 +1,16 @@
const config = {
'#1ab394': {
'--color-success': '#1c84c6',
'--color-info': '#23c6c8',
'--color-warning': '#f8ac59',
'--color-danger': '#ed5565',
'--menu-bg': '#2f4050',
'--menu-text': '#a7b1c2',
'--menu-hover': '#293846',
'--submenu-bg': '#1f2d3d',
'--submenu-hover': '#3b4c5b',
'--menu-active-left': '#1ab394'
}
}
export default config

View File

@@ -0,0 +1,16 @@
const config = {
'#174779': {
'--color-success': '#174779',
'--color-info': '#17a2b8',
'--color-warning': '#ffc107',
'--color-danger': '#dc3545',
'--menu-bg': '#174779',
'--menu-text': '#e9ecef',
'--menu-hover': '#123961',
'--submenu-bg': '#123961',
'--submenu-hover': '#103255',
'--menu-active-left': 'white'
}
}
export default config

View File

@@ -0,0 +1,9 @@
let themeOptions = {}
const optionFiles = require.context('./themeConfigs', false, /\.js$/)
optionFiles.keys().forEach(item => {
const config = optionFiles(item).default || optionFiles(item)
themeOptions = { ...themeOptions, ...config }
})
export default themeOptions

View File

@@ -57,7 +57,6 @@ export default {
</script>
<style lang="scss" scoped>
@import '~@/styles/variables';
.asset-table ::v-deep .row-clicked, .asset-user-table ::v-deep .row-background-color {
background-color: #f5f7fa;
}
@@ -81,8 +80,8 @@ export default {
margin-right: 10px;
text-align: center;
padding: 9px 0;
background-color: $--color-primary;
border-color: $--color-primary;
background-color: var(--color-primary);
border-color: var(--color-primary);
color: #FFFFFF;
border-radius: 5px;
line-height: 1.428;

View File

@@ -53,7 +53,6 @@ export default {
</script>
<style lang="scss" scoped>
@import '~@/styles/variables';
.asset-table ::v-deep .row-clicked, .asset-user-table ::v-deep .row-background-color {
background-color: #f5f7fa;
}
@@ -77,8 +76,8 @@ export default {
margin-right: 10px;
text-align: center;
padding: 9px 0;
background-color: $--color-primary;
border-color: $--color-primary;
background-color: var(--color-primary);
border-color: var(--color-primary);
color: #FFFFFF;
border-radius: 5px;
line-height: 1.428;

View File

@@ -249,14 +249,13 @@ export default {
</script>
<style lang="scss" scoped>
@import "~@/styles/variables.scss";
.mini-button{
width: 12px;
float: right;
text-align: center;
padding: 5px 0;
background-color: $--color-primary;
border-color: $--color-primary;
background-color: var(--color-primary);
border-color: var(--color-primary);
color: #FFFFFF;
border-radius: 3px;
}

View File

@@ -21,6 +21,7 @@ import { Page } from '@/layout/components'
import { IBox, UploadField } from '@/components'
import GenericCreateUpdateForm from '@/layout/components/GenericCreateUpdateForm'
import { getInterfaceInfo, updateInterface, restoreInterface } from '@/api/interface'
import { matchColor, defaultThemeColor } from '@/utils/theme/color'
export default {
name: 'InterfaceSettings',
@@ -46,6 +47,15 @@ export default {
label: this.$t('xpack.loginTitle'),
helpText: this.$t('xpack.loginTitleTip')
},
theme: {
on: {
change: ([value]) => {
const color = matchColor[value] || defaultThemeColor
this.$store.commit('settings/setTheme', color)
this.$store.dispatch('settings/changeThemeStyle')
}
}
},
login_image: {
component: UploadField,
label: this.$t('xpack.loginImage'),

View File

@@ -76,6 +76,17 @@ module.exports = {
},
after: require('./mock/mock-server.js')
},
css: {
loaderOptions: {
sass: {
prependData: (content, loaderContext) => {
const { resourcePath } = loaderContext
if (resourcePath.endsWith('var.scss')) return content
return `@import "@/styles/var.scss"; ${content}`
}
}
}
},
configureWebpack: {
// provide the app's title in webpack's name field, so that
// it can be accessed in index.html to inject the correct title.