From 4063a4f08adc3b375447de389e40325f308a9204 Mon Sep 17 00:00:00 2001 From: iczer <1126263215@qq.com> Date: Mon, 6 Jul 2020 21:52:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20add=20global=20night=20mode;=20:star2:?= =?UTF-8?q?=20=E6=96=B0=E5=A2=9E=EF=BC=9A=E5=85=A8=E5=B1=80=E5=A4=9C?= =?UTF-8?q?=E6=99=9A=E6=A8=A1=E5=BC=8F=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.vue | 8 +- src/components/card/ChartCard.vue | 3 +- src/components/chart/RankingList.vue | 8 +- src/components/exception/ExceptionPage.vue | 2 +- src/components/menu/SideMenu.vue | 43 +-------- src/components/menu/index.less | 37 ++++++++ src/components/menu/menu.js | 5 +- .../page/{ => header}/PageHeader.vue | 43 +-------- src/components/page/header/index.less | 42 +++++++++ src/components/result/Result.vue | 8 +- src/components/setting/Setting.vue | 3 +- src/components/setting/i18n.js | 3 + src/components/task/TaskGroup.vue | 4 +- src/components/task/TaskItem.vue | 1 - src/components/tool/DetailList.vue | 8 +- src/components/tool/Drawer.vue | 6 +- src/components/tool/FooterToolBar.vue | 4 +- src/components/tool/HeadInfo.vue | 4 +- src/config/config.js | 1 + src/config/default/index.js | 3 +- src/config/default/theme.js | 64 +++++++++++++ src/layouts/CommonLayout.vue | 7 +- src/layouts/PageLayout.vue | 4 +- src/layouts/header/AdminHeader.vue | 94 ++----------------- src/layouts/header/HeaderNotice.vue | 18 ++-- src/layouts/header/index.less | 84 +++++++++++++++++ src/pages/dashboard/analysis/HotSearch.vue | 6 +- src/pages/dashboard/workplace/WorkPlace.vue | 87 +---------------- src/pages/dashboard/workplace/index.less | 59 ++++++++++++ src/pages/detail/BasicDetail.vue | 2 +- src/pages/form/advance/AdvancedForm.vue | 2 +- src/pages/list/CardList.vue | 1 - src/pages/list/StandardList.vue | 2 +- src/pages/list/search/SearchLayout.vue | 4 +- src/pages/login/Login.vue | 6 +- src/pages/result/Error.vue | 2 +- src/theme/default/color.less | 18 ++++ src/utils/colors.js | 42 ++++++++- src/utils/themeUtil.js | 70 +++++++++----- 39 files changed, 480 insertions(+), 328 deletions(-) create mode 100644 src/components/menu/index.less rename src/components/page/{ => header}/PageHeader.vue (63%) create mode 100644 src/components/page/header/index.less create mode 100644 src/config/default/theme.js create mode 100644 src/layouts/header/index.less create mode 100644 src/pages/dashboard/workplace/index.less diff --git a/src/App.vue b/src/App.vue index 8b7bb64..d97b438 100644 --- a/src/App.vue +++ b/src/App.vue @@ -33,9 +33,15 @@ export default { lang(val) { this.setLanguage(val) }, + theme(val) { + let closeMessage = this.$message.loading(`您选择了主题模式 ${val}, 正在切换...`) + themeUtil.changeThemeColor(this.themeColor, val).then(() => { + setTimeout(closeMessage, 1000) + }) + }, themeColor(val) { let closeMessage = this.$message.loading(`您选择了主题色 ${val}, 正在切换...`) - themeUtil.changeThemeColor(val).then(() => { + themeUtil.changeThemeColor(val, this.theme).then(() => { setTimeout(closeMessage, 1000) }) } diff --git a/src/components/card/ChartCard.vue b/src/components/card/ChartCard.vue index fc0ae7f..43cca3f 100644 --- a/src/components/card/ChartCard.vue +++ b/src/components/card/ChartCard.vue @@ -27,7 +27,7 @@ export default { } </script> -<style scoped> +<style scoped lang="less"> .chart-card-header{ position: relative; overflow: hidden; @@ -52,7 +52,6 @@ export default { text-overflow: ellipsis; word-break: break-all; white-space: nowrap; - color: #000; margin-top: 4px; margin-bottom: 0; font-size: 30px; diff --git a/src/components/chart/RankingList.vue b/src/components/chart/RankingList.vue index f34a726..1ff989f 100644 --- a/src/components/chart/RankingList.vue +++ b/src/components/chart/RankingList.vue @@ -30,12 +30,12 @@ export default { li { margin-top: 16px; span { - color: rgba(0,0,0,.65); + color: @text-color-second; font-size: 14px; line-height: 22px; } span:first-child { - background-color: #f5f5f5; + background-color: @bg-color; border-radius: 20px; display: inline-block; font-size: 12px; @@ -47,8 +47,8 @@ export default { text-align: center; } span.active { - background-color: #314659; - color: #fff; + background-color: #314659 !important; + color: #fff !important; } span:last-child { float: right; diff --git a/src/components/exception/ExceptionPage.vue b/src/components/exception/ExceptionPage.vue index e4ffe6c..c3f87d3 100644 --- a/src/components/exception/ExceptionPage.vue +++ b/src/components/exception/ExceptionPage.vue @@ -34,7 +34,7 @@ export default { display: flex; justify-content: center; align-items: center; - background-color: white; + background-color: @base-bg-color; .img{ padding-right: 52px; zoom: 1; diff --git a/src/components/menu/SideMenu.vue b/src/components/menu/SideMenu.vue index 010cbf0..06a7e36 100644 --- a/src/components/menu/SideMenu.vue +++ b/src/components/menu/SideMenu.vue @@ -1,5 +1,5 @@ <template> - <a-layout-sider :theme="theme" :class="['side-menu', isMobile ? null : 'shadow']" width="256px" :collapsible="collapsible" v-model="collapsed" :trigger="null"> + <a-layout-sider :theme="sideTheme" :class="['side-menu', isMobile ? null : 'shadow']" width="256px" :collapsible="collapsible" v-model="collapsed" :trigger="null"> <div :class="['logo', theme]"> <router-link to="/dashboard/workplace"> <img src="@/assets/img/logo.png"> @@ -39,6 +39,9 @@ export default { } }, computed: { + sideTheme() { + return this.theme == 'light' ? this.theme : 'dark' + }, ...mapState('setting', ['isMobile', 'systemName']) }, methods: { @@ -51,41 +54,5 @@ export default { </script> <style lang="less" scoped> - .shadow{ - box-shadow: 2px 0 6px rgba(0, 21, 41, .35); - } - .side-menu{ - min-height: 100%; - z-index: 10; - .logo{ - height: 64px; - position: relative; - line-height: 64px; - padding-left: 24px; - -webkit-transition: all .3s; - transition: all .3s; - overflow: hidden; - background-color: @layout-trigger-background; - &.light{ - background-color: #fff; - h1{ - color: @primary-color; - } - } - h1{ - color: #fff; - font-size: 20px; - margin: 0 0 0 12px; - display: inline-block; - vertical-align: middle; - } - img{ - width: 32px; - vertical-align: middle; - } - } - } - .menu{ - padding: 16px 0; - } +@import "index"; </style> diff --git a/src/components/menu/index.less b/src/components/menu/index.less new file mode 100644 index 0000000..171897f --- /dev/null +++ b/src/components/menu/index.less @@ -0,0 +1,37 @@ +.shadow{ + box-shadow: 2px 0 6px rgba(0, 21, 41, .35); +} +.side-menu{ + min-height: 100%; + z-index: 10; + .logo{ + height: 64px; + position: relative; + line-height: 64px; + padding-left: 24px; + -webkit-transition: all .3s; + transition: all .3s; + overflow: hidden; + background-color: @layout-trigger-background; + &.light{ + background-color: #fff; + h1{ + color: @primary-color; + } + } + h1{ + color: @menu-dark-highlight-color; + font-size: 20px; + margin: 0 0 0 12px; + display: inline-block; + vertical-align: middle; + } + img{ + width: 32px; + vertical-align: middle; + } + } +} +.menu{ + padding: 16px 0; +} diff --git a/src/components/menu/menu.js b/src/components/menu/menu.js index 638493b..f3e5a49 100644 --- a/src/components/menu/menu.js +++ b/src/components/menu/menu.js @@ -73,6 +73,9 @@ export default { keys.push(item.path) }) return keys + }, + menuTheme() { + return this.theme == 'light' ? this.theme : 'dark' } }, beforeMount() { @@ -212,7 +215,7 @@ export default { Menu, { props: { - theme: this.$props.theme, + theme: this.menuTheme, mode: this.$props.mode, openKeys: this.openKeys, selectedKeys: this.selectedKeys diff --git a/src/components/page/PageHeader.vue b/src/components/page/header/PageHeader.vue similarity index 63% rename from src/components/page/PageHeader.vue rename to src/components/page/header/PageHeader.vue index 5920abb..2ae5e85 100644 --- a/src/components/page/PageHeader.vue +++ b/src/components/page/header/PageHeader.vue @@ -57,46 +57,5 @@ export default { </script> <style lang="less" scoped> - .page-header{ - background: #fff; - padding: 16px 24px; - border-bottom: 1px solid #e8e8e8; - .page-header-wide{ - &.head{ - margin: auto; - max-width: 1400px; - } - &.side{ - } - .breadcrumb{ - margin-bottom: 20px; - } - .detail{ - display: flex; - .row { - display: flex; - flex-wrap: wrap; - justify-content: space-between; - } - .avatar { - margin:0 24px 0 0; - } - .main{ - width: 100%; - .title{ - font-size: 20px; - color: rgba(0,0,0,.85); - margin-bottom: 16px; - } - .content{ - display: flex; - flex-wrap: wrap; - } - .extra{ - display: flex; - } - } - } - } - } + @import "index"; </style> diff --git a/src/components/page/header/index.less b/src/components/page/header/index.less new file mode 100644 index 0000000..ba5b1d5 --- /dev/null +++ b/src/components/page/header/index.less @@ -0,0 +1,42 @@ +.page-header{ + background: @base-bg-color; + padding: 16px 24px; + .page-header-wide{ + &.head{ + margin: auto; + max-width: 1400px; + } + &.side{ + } + .breadcrumb{ + margin-bottom: 20px; + } + .detail{ + display: flex; + .row { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + } + .avatar { + margin:0 24px 0 0; + } + .main{ + width: 100%; + .title{ + font-size: 20px; + color: @title-color; + margin-bottom: 16px; + } + .content{ + display: flex; + flex-wrap: wrap; + color: @text-color-second; + } + .extra{ + display: flex; + } + } + } + } +} diff --git a/src/components/result/Result.vue b/src/components/result/Result.vue index c0d0238..58d1a7a 100644 --- a/src/components/result/Result.vue +++ b/src/components/result/Result.vue @@ -35,11 +35,11 @@ export default { color: @success-color; } .error { - color: red; + color: @error-color; } .title{ font-size: 24px; - color: rgba(0,0,0,.85); + color: @title-color; font-weight: 500; line-height: 32px; margin-bottom: 16px; @@ -47,11 +47,11 @@ export default { .desc{ font-size: 14px; line-height: 22px; - color: rgba(0, 0, 0, 0.45); + color: @text-color-second; margin-bottom: 24px; } .content{ - background: #fafafa; + background-color: @background-color-light; padding: 24px 40px; border-radius: 2px; text-align: left; diff --git a/src/components/setting/Setting.vue b/src/components/setting/Setting.vue index ab6b60f..8cd02d9 100644 --- a/src/components/setting/Setting.vue +++ b/src/components/setting/Setting.vue @@ -4,6 +4,7 @@ <img-checkbox-group @change="values => setTheme(values[0])" :default-values="[theme]"> <img-checkbox :title="$t('theme.dark')" img="https://gw.alipayobjects.com/zos/rmsportal/LCkqqYNmvBEbokSDscrm.svg" value="dark"/> <img-checkbox :title="$t('theme.light')" img="https://gw.alipayobjects.com/zos/rmsportal/jpRkZQMyYRryryPNtyIC.svg" value="light"/> + <img-checkbox :title="$t('theme.night')" img="https://gw.alipayobjects.com/zos/antfincdn/hmKaLQvmY2/LCkqqYNmvBEbokSDscrm.svg" value="night"/> </img-checkbox-group> </setting-item> <setting-item :title="$t('theme.color')"> @@ -136,7 +137,7 @@ export default { <style lang="less" scoped> .side-setting{ min-height: 100%; - background-color: #fff; + background-color: @base-bg-color; padding: 24px; font-size: 14px; line-height: 1.5; diff --git a/src/components/setting/i18n.js b/src/components/setting/i18n.js index bb15608..7480645 100644 --- a/src/components/setting/i18n.js +++ b/src/components/setting/i18n.js @@ -5,6 +5,7 @@ module.exports = { title: '整体风格设置', light: '亮色菜单风格', dark: '暗色菜单风格', + night: '深夜模式', color: '主题色' }, navigate: { @@ -36,6 +37,7 @@ module.exports = { title: '整體風格設置', light: '亮色菜單風格', dark: '暗色菜單風格', + night: '深夜模式', color: '主題色' }, navigate: { @@ -67,6 +69,7 @@ module.exports = { title: 'Page Style Setting', light: 'Light Style', dark: 'Dark Style', + night: 'Night Style', color: 'Theme Color' }, navigate: { diff --git a/src/components/task/TaskGroup.vue b/src/components/task/TaskGroup.vue index aa3cfb8..db4fafb 100644 --- a/src/components/task/TaskGroup.vue +++ b/src/components/task/TaskGroup.vue @@ -49,9 +49,9 @@ export default { .task-group{ width: 33.33%; padding: 8px 8px; - background-color: #e1e4e8; + background-color: @background-color-light; border-radius: 6px; - border: 1px solid #d1d4d8; + border: 1px solid @shadow-color; .task-head{ margin-bottom: 8px; .title{ diff --git a/src/components/task/TaskItem.vue b/src/components/task/TaskItem.vue index a703c08..2c929f9 100644 --- a/src/components/task/TaskItem.vue +++ b/src/components/task/TaskItem.vue @@ -16,7 +16,6 @@ export default { margin-bottom: 16px; box-shadow: 0 1px 1px rgba(27,31,35,0.1); border-radius: 6px; - color: #24292e; & :hover{ cursor: move; box-shadow: 0 1px 1px rgba(27,31,35,0.15); diff --git a/src/components/tool/DetailList.vue b/src/components/tool/DetailList.vue index e1797ab..2772764 100644 --- a/src/components/tool/DetailList.vue +++ b/src/components/tool/DetailList.vue @@ -102,7 +102,7 @@ export default { .detail-list{ .title { font-size: 16px; - color: rgba(0,0,0,.85); + color: @title-color; font-weight: bolder; margin-bottom: 16px; } @@ -111,7 +111,7 @@ export default { line-height: 20px; padding-bottom: 16px; margin-right: 8px; - color: rgba(0,0,0,.85); + color: @title-color; white-space: nowrap; display: table-cell; &:after { @@ -125,13 +125,13 @@ export default { line-height: 22px; width: 100%; padding-bottom: 16px; - color: rgba(0,0,0,.65); + color: @text-color; display: table-cell; } &.small{ .title{ font-size: 14px; - color: rgba(0,0,0,.65); + color: @text-color; font-weight: normal; margin-bottom: 12px; } diff --git a/src/components/tool/Drawer.vue b/src/components/tool/Drawer.vue index ff7432a..c0ca5d1 100644 --- a/src/components/tool/Drawer.vue +++ b/src/components/tool/Drawer.vue @@ -76,7 +76,7 @@ export default { right: 0; bottom: 0; top: 0; - background-color: rgba(0, 0, 0, 0.2); + background-color: @shadow-color; transition: all 0.5s; z-index: 100; &.open{ @@ -133,9 +133,9 @@ export default { .handler { height: 40px; width: 40px; - background-color: #fff; + background-color: @base-bg-color; font-size: 26px; - box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15); + box-shadow: 0 2px 8px @shadow-color; line-height: 40px; } &.left{ diff --git a/src/components/tool/FooterToolBar.vue b/src/components/tool/FooterToolBar.vue index d82cfb0..3f56d68 100644 --- a/src/components/tool/FooterToolBar.vue +++ b/src/components/tool/FooterToolBar.vue @@ -22,8 +22,8 @@ export default { bottom: 0; right: 0; box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.03); - background: #fff; - border-top: 1px solid #e8e8e8; + background: @base-bg-color; + border-top: 1px solid @border-color-split; padding: 12px 24px; z-index: 9; } diff --git a/src/components/tool/HeadInfo.vue b/src/components/tool/HeadInfo.vue index d46872e..d3f4944 100644 --- a/src/components/tool/HeadInfo.vue +++ b/src/components/tool/HeadInfo.vue @@ -20,13 +20,13 @@ export default { flex-shrink: 0; align-self: center; span{ - color: rgba(0,0,0,.45); + color: @text-color-second; display: inline-block; font-size: 14px; margin-bottom: 4px; } p{ - color: rgba(0,0,0,.85); + color: @text-color; font-size: 24px; margin: 0; } diff --git a/src/config/config.js b/src/config/config.js index 6b8bfd4..20a6462 100644 --- a/src/config/config.js +++ b/src/config/config.js @@ -1,4 +1,5 @@ // 自定义配置,参考 ./default/setting.js,需要自定义的属性在这里配置即可 module.exports = { themeColor: '#13c2c2', + theme: 'night' } diff --git a/src/config/default/index.js b/src/config/default/index.js index 1fbce98..ae28f68 100644 --- a/src/config/default/index.js +++ b/src/config/default/index.js @@ -1,4 +1,5 @@ const animates = require('./animates') const setting = require('./setting') +const theme = require('./theme') -module.exports = {setting, animates} +module.exports = {setting, animates, theme} diff --git a/src/config/default/theme.js b/src/config/default/theme.js new file mode 100644 index 0000000..21af6e2 --- /dev/null +++ b/src/config/default/theme.js @@ -0,0 +1,64 @@ +// 亮色模式 +const light = { + 'layout-body-background': '#f0f2f5', + 'body-background': '#fff', + 'component-background': '#fff', + 'heading-color': 'rgba(0, 0, 0, 0.85)', + 'text-color': 'rgba(0, 0, 0, 0.65)', + 'text-color-inverse': '#fff', + 'text-color-secondary': 'rgba(0, 0, 0, 0.45)', + 'shadow-color': 'rgba(0, 0, 0, 0.15)', + 'border-color-split': '#f0f0f0', + 'background-color-light': '#fafafa', + 'table-selected-row-bg': '#fafafa', + 'checkbox-check-color': '#fff', + 'disabled-color': 'rgba(0, 0, 0, 0.25)', + 'menu-dark-color': 'rgba(1, 1, 1, 0.65)', + 'menu-dark-highlight-color': '#fefefe', + 'menu-dark-arrow-color': '#fefefe', + 'btn-primary-color': '#fff', +} + +// 暗色模式 +const dark = { + 'layout-body-background': '#f0f2f5', + 'body-background': '#fff', + 'component-background': '#fff', + 'heading-color': 'rgba(0, 0, 0, 0.85)', + 'text-color': 'rgba(0, 0, 0, 0.65)', + 'text-color-inverse': '#fff', + 'text-color-secondary': 'rgba(0, 0, 0, 0.45)', + 'shadow-color': 'rgba(0, 0, 0, 0.15)', + 'border-color-split': '#f0f0f0', + 'background-color-light': '#fafafa', + 'table-selected-row-bg': '#fafafa', + 'checkbox-check-color': '#fff', + 'disabled-color': 'rgba(0, 0, 0, 0.25)', + 'menu-dark-color': 'rgba(254, 254, 254, 0.65)', + 'menu-dark-highlight-color': '#fefefe', + 'menu-dark-arrow-color': '#fefefe', + 'btn-primary-color': '#fff', +} + +// 黑夜模式 +const night = { + 'layout-body-background': '#000', + 'body-background': '#141414', + 'component-background': '#141414', + 'heading-color': 'rgba(255, 255, 255, 0.85)', + 'text-color': 'rgba(255, 255, 255, 0.85)', + 'text-color-inverse': '#141414', + 'text-color-secondary': 'rgba(255, 255, 255, 0.45)', + 'shadow-color': 'rgba(255, 255, 255, 0.15)', + 'border-color-split': '#303030', + 'background-color-light': '#404040', + 'table-selected-row-bg': '#404040', + 'checkbox-check-color': '#141414', + 'disabled-color': 'rgba(255, 255, 255, 0.25)', + 'menu-dark-color': 'rgba(254, 254, 254, 0.65)', + 'menu-dark-highlight-color': '#fefefe', + 'menu-dark-arrow-color': '#fefefe', + 'btn-primary-color': '#141414', +} + +module.exports = {light, dark, night} diff --git a/src/layouts/CommonLayout.vue b/src/layouts/CommonLayout.vue index df32482..4bc9be6 100644 --- a/src/layouts/CommonLayout.vue +++ b/src/layouts/CommonLayout.vue @@ -24,12 +24,17 @@ export default { flex-direction: column; height: 100vh; overflow: auto; - background: #f0f2f5 url('https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg') no-repeat center 110px; + background-color: @layout-body-background; + background-image: url('https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg'); + background-repeat: no-repeat; + background-position-x: center; + background-position-y: 110px; background-size: 100%; .content{ padding: 32px 0; flex: 1; @media (min-width: 768px){ + padding: 112px 0 24px; } } diff --git a/src/layouts/PageLayout.vue b/src/layouts/PageLayout.vue index a4b038e..18b9bd0 100644 --- a/src/layouts/PageLayout.vue +++ b/src/layouts/PageLayout.vue @@ -20,7 +20,7 @@ </template> <script> -import PageHeader from '../components/page/PageHeader' +import PageHeader from '@/components/page/header/PageHeader' import {mapState} from 'vuex' export default { name: 'PageLayout', @@ -81,7 +81,7 @@ export default { } </script> -<style lang="less" scoped> +<style lang="less"> .page-header{ margin: -24px -24px 0; } diff --git a/src/layouts/header/AdminHeader.vue b/src/layouts/header/AdminHeader.vue index a933463..8cccef5 100644 --- a/src/layouts/header/AdminHeader.vue +++ b/src/layouts/header/AdminHeader.vue @@ -8,7 +8,7 @@ <a-divider v-if="isMobile" type="vertical" /> <a-icon v-if="layout === 'side'" class="trigger" :type="collapsed ? 'menu-unfold' : 'menu-fold'" @click="toggleCollapse"/> <div v-if="layout == 'head' && !isMobile" class="admin-header-menu"> - <i-menu style="height: 64px; line-height: 64px;" @i18nComplete="setRoutesI18n" :i18n="menuI18n" :theme="headerTheme" mode="horizontal" :options="menuData" @select="onSelect"/> + <i-menu class="head-menu" style="height: 64px; line-height: 64px;box-shadow: none" @i18nComplete="setRoutesI18n" :i18n="menuI18n" :theme="headerTheme" mode="horizontal" :options="menuData" @select="onSelect"/> </div> <div :class="['admin-header-right', headerTheme]"> <header-search class="header-item" /> @@ -56,7 +56,11 @@ export default { computed: { ...mapState('setting', ['theme', 'isMobile', 'layout', 'systemName', 'lang']), headerTheme () { - return (this.layout == 'side' && !this.isMobile) ? 'light' : this.theme + if (this.layout == 'side' && this.theme == 'dark' && !this.isMobile) { + return 'light' + } + return this.theme + // return (this.layout == 'side' && !this.isMobile && this.theme != 'night') ? 'light' : this.theme }, langAlias() { let lang = this.langList.find(item => item.key == this.lang) @@ -76,89 +80,5 @@ export default { </script> <style lang="less" scoped> - .trigger { - font-size: 20px; - line-height: 64px; - padding: 0 24px; - cursor: pointer; - transition: color .3s; - &:hover{ - color: @primary-color; - } - } - .admin-header{ - padding: 0; - -webkit-box-shadow: 0 1px 4px rgba(0,21,41,.08); - box-shadow: 0 1px 4px rgba(0,21,41,.08); - z-index: 1; - position: relative; - &.light{ - background: #fff; - } - &.dark{ - .trigger{ - color: white; - } - } - .admin-header-wide{ - &.head{ - max-width: 1400px; - margin: auto; - } - &.side{ - padding-right: 12px; - } - .logo { - height: 64px; - line-height: 58px; - vertical-align: top; - display: inline-block; - padding: 0 12px 0 24px; - cursor: pointer; - font-size: 20px; - &.pc{ - padding: 0 12px 0 0; - } - img { - display: inline-block; - vertical-align: middle; - } - h1{ - display: inline-block; - font-size: 16px; - } - &.dark h1{ - color: #fff; - } - } - .admin-header-menu{ - display: inline-block; - } - .admin-header-right{ - float: right; - display: flex; - &.dark{ - color: #fff; - a, i{ - color: #fff !important; - } - .header-item:hover{ - background-color: @primary-color; - } - } - .header-item{ - padding: 0 12px; - cursor: pointer; - align-self: center; - &:hover{ - background-color: @gray-3; - } - i{ - font-size: 16px; - color: rgba(0,0,0,.65); - } - } - } - } - } +@import "index"; </style> diff --git a/src/layouts/header/HeaderNotice.vue b/src/layouts/header/HeaderNotice.vue index 7fd3f66..9fd10ce 100644 --- a/src/layouts/header/HeaderNotice.vue +++ b/src/layouts/header/HeaderNotice.vue @@ -2,7 +2,7 @@ <a-dropdown :trigger="['click']" v-model="show"> <div slot="overlay"> <a-spin :spinning="loading"> - <a-tabs class="dropdown-tabs" :tabBarStyle="{textAlign: 'center'}" :style="{backgroundColor: 'white', width: '297px'}"> + <a-tabs class="dropdown-tabs" :tabBarStyle="{textAlign: 'center'}" :style="{width: '297px'}"> <a-tab-pane tab="通知" key="1"> <a-list class="tab-pane"> <a-list-item> @@ -32,7 +32,7 @@ </a-spin> </div> <span @click="fetchNotice" class="header-notice"> - <a-badge count="12"> + <a-badge class="notice-badge" count="12"> <a-icon :class="['header-notice-icon']" type="bell" /> </a-badge> </span> @@ -65,20 +65,24 @@ export default { } </script> -<style lang="less" scoped> +<style lang="less"> .header-notice{ display: inline-block; transition: all 0.3s; span { vertical-align: initial; } - .header-notice-icon{ - font-size: 16px; - padding: 4px; + .notice-badge{ + color: inherit; + .header-notice-icon{ + font-size: 16px; + padding: 4px; + } } } .dropdown-tabs{ - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + background-color: @base-bg-color; + box-shadow: 0 2px 8px @shadow-color; border-radius: 4px; .tab-pane{ padding: 0 24px 12px; diff --git a/src/layouts/header/index.less b/src/layouts/header/index.less new file mode 100644 index 0000000..ad60faf --- /dev/null +++ b/src/layouts/header/index.less @@ -0,0 +1,84 @@ +.admin-header{ + padding: 0; + z-index: 2; + box-shadow: @shadow-down; + position: relative; + background: @base-bg-color; + &.dark{ + background: @header-bg-color-dark; + color: white; + } + &.night{ + .head-menu{ + background: @base-bg-color; + } + } + .admin-header-wide{ + &.head{ + max-width: 1400px; + margin: auto; + } + &.side{ + padding-right: 12px; + } + .logo { + height: 64px; + line-height: 58px; + vertical-align: top; + display: inline-block; + padding: 0 12px 0 24px; + cursor: pointer; + font-size: 20px; + color: inherit; + &.pc{ + padding: 0 12px 0 0; + } + img { + vertical-align: middle; + } + h1{ + color: inherit; + display: inline-block; + font-size: 16px; + } + } + .trigger { + font-size: 20px; + line-height: 64px; + padding: 0 24px; + cursor: pointer; + transition: color .3s; + &:hover{ + color: @primary-color; + } + } + .admin-header-menu{ + display: inline-block; + } + .admin-header-right{ + float: right; + display: flex; + color: inherit; + .header-item{ + color: inherit; + padding: 0 12px; + cursor: pointer; + align-self: center; + a{ + color: inherit; + i{ + font-size: 16px; + } + } + } + each(@theme-list, { + &.@{value} .header-item{ + &:hover{ + @class: ~'hover-bg-color-@{value}'; + background-color: @@class; + } + } + }) + } + } +} diff --git a/src/pages/dashboard/analysis/HotSearch.vue b/src/pages/dashboard/analysis/HotSearch.vue index 533033b..1a212c9 100644 --- a/src/pages/dashboard/analysis/HotSearch.vue +++ b/src/pages/dashboard/analysis/HotSearch.vue @@ -107,7 +107,7 @@ export default { <style lang="less" scoped> .num-info{ .title{ - color: rgba(0,0,0,.45); + color: @text-color-second; font-size: 14px; height: 22px; line-height: 22px; @@ -118,7 +118,7 @@ export default { } .value{ .total{ - color: rgba(0,0,0,.85); + color: @title-color; display: inline-block; line-height: 32px; height: 32px; @@ -126,7 +126,7 @@ export default { margin-right: 32px; } .subtotal{ - color: rgba(0,0,0,.45); + color: @text-color-second; font-size: 16px; vertical-align: top; margin-right: 0; diff --git a/src/pages/dashboard/workplace/WorkPlace.vue b/src/pages/dashboard/workplace/WorkPlace.vue index f30fe13..e346022 100644 --- a/src/pages/dashboard/workplace/WorkPlace.vue +++ b/src/pages/dashboard/workplace/WorkPlace.vue @@ -9,7 +9,7 @@ <head-info class="split-right" :title="$t('ranking')" content="8/24"/> <head-info class="split-right" :title="$t('visit')" content="2,223"/> </template> - <div> + <template> <a-row style="margin: 0 -12px"> <a-col style="padding: 0 12px" :xl="16" :lg="24" :md="24" :sm="24" :xs="24"> <a-card class="project-list" :loading="loading" style="margin-bottom: 24px;" :bordered="false" :title="$t('progress')" :body-style="{padding: 0}"> @@ -20,11 +20,11 @@ <a-card-meta :description="item.desc"> <div slot="title" class="card-title"> <a-avatar size="small" :src="item.logo" /> - <a>Alipay</a> + <span>Alipay</span> </div> </a-card-meta> <div class="project-item"> - <a href="/#/">科学搬砖组</a> + <a class="group" href="/#/">科学搬砖组</a> <span class="datetime">9小时前</span> </div> </a-card> @@ -74,7 +74,7 @@ </a-card> </a-col> </a-row> - </div> + </template> </page-layout> </template> @@ -146,82 +146,5 @@ export default { </script> <style lang="less"> - .project-list { - .card-title { - font-size: 0; - a { - color: rgba(0, 0, 0, 0.85); - margin-left: 12px; - line-height: 24px; - height: 24px; - display: inline-block; - vertical-align: top; - font-size: 14px; - &:hover { - color: @primary-color; - } - } - } - .project-item { - display: flex; - margin-top: 8px; - overflow: hidden; - font-size: 12px; - height: 20px; - line-height: 20px; - a { - color: rgba(0, 0, 0, 0.45); - display: inline-block; - flex: 1 1 0; - &:hover { - color: @primary-color; - } - } - .datetime { - color: rgba(0, 0, 0, 0.25); - flex: 0 0 auto; - float: right; - } - } - .ant-card-meta-description { - color: rgba(0, 0, 0, 0.45); - height: 44px; - line-height: 22px; - overflow: hidden; - } - } - .item-group{ - padding: 20px 0 8px 24px; - font-size: 0; - a{ - color: rgba(0, 0, 0, 0.65); - display: inline-block; - font-size: 14px; - margin-bottom: 13px; - width: 25%; - } - } - .members { - a { - display: block; - margin: 12px 0; - line-height: 24px; - height: 24px; - .member { - font-size: 14px; - color: rgba(0,0,0,.65); - line-height: 24px; - max-width: 100px; - vertical-align: top; - margin-left: 12px; - transition: all 0.3s; - display: inline-block; - } - &:hover { - span { - color: @primary-color; - } - } - } - } +@import "index"; </style> diff --git a/src/pages/dashboard/workplace/index.less b/src/pages/dashboard/workplace/index.less new file mode 100644 index 0000000..c684c26 --- /dev/null +++ b/src/pages/dashboard/workplace/index.less @@ -0,0 +1,59 @@ +.project-list { + .card-title { + span{ + vertical-align: middle; + &:last-child{ + margin-left: 12px; + } + } + } + .project-item { + display: flex; + justify-content: space-between; + margin-top: 8px; + overflow: hidden; + font-size: 12px; + color: inherit; + .group{ + color: @text-color; + flex: 1 1 0; + &:hover { + color: @primary-color; + } + } + .datetime { + color: @text-color-second; + flex: 0 0 auto; + } + } + .ant-card-meta-description { + height: 44px; + line-height: 22px; + overflow: hidden; + } +} +.item-group{ + padding: 20px 0 8px 24px; + font-size: 0; + a{ + color: inherit; + display: inline-block; + font-size: 14px; + margin-bottom: 13px; + width: 25%; + } +} +.members { + a { + display: block; + margin: 12px 0; + color: @text-color; + &:hover { + color: @primary-color; + } + .member { + vertical-align: middle; + margin-left: 12px; + } + } +} diff --git a/src/pages/detail/BasicDetail.vue b/src/pages/detail/BasicDetail.vue index c93fda2..567b907 100644 --- a/src/pages/detail/BasicDetail.vue +++ b/src/pages/detail/BasicDetail.vue @@ -199,7 +199,7 @@ export default { <style lang="less" scoped> .title { - color: rgba(0,0,0,.85); + color: @title-color; font-size: 16px; font-weight: 500; margin-bottom: 16px; diff --git a/src/pages/form/advance/AdvancedForm.vue b/src/pages/form/advance/AdvancedForm.vue index 5a01cf2..294d1b7 100644 --- a/src/pages/form/advance/AdvancedForm.vue +++ b/src/pages/form/advance/AdvancedForm.vue @@ -19,7 +19,7 @@ import RepositoryForm from './RepositoryForm' import TaskForm from './TaskForm' import UserForm from './UserForm' -import FooterToolBar from '../../../components/tool/FooterToolBar' +import FooterToolBar from '@/components/tool/FooterToolBar' export default { name: 'AdvancedForm', diff --git a/src/pages/list/CardList.vue b/src/pages/list/CardList.vue index 52fcce8..d1f3096 100644 --- a/src/pages/list/CardList.vue +++ b/src/pages/list/CardList.vue @@ -63,7 +63,6 @@ export default { border-radius: 48px; } .new-btn{ - background-color: #fff; border-radius: 2px; width: 100%; height: 187px; diff --git a/src/pages/list/StandardList.vue b/src/pages/list/StandardList.vue index 0f30fc9..fe00ff1 100644 --- a/src/pages/list/StandardList.vue +++ b/src/pages/list/StandardList.vue @@ -70,7 +70,7 @@ export default { <style lang="less" scoped> .list-content-item{ - color: rgba(0,0,0,.45); + color: @text-color-second; display: inline-block; vertical-align: middle; font-size: 14px; diff --git a/src/pages/list/search/SearchLayout.vue b/src/pages/list/search/SearchLayout.vue index f851f71..82cd728 100644 --- a/src/pages/list/search/SearchLayout.vue +++ b/src/pages/list/search/SearchLayout.vue @@ -2,7 +2,7 @@ <div> <div class="search-head"> <div class="search-input"> - <a-input-search style="width: 522px" placeholder="请输入..." size="large" enterButton="搜索" /> + <a-input-search class="search-ipt" style="width: 522px" placeholder="请输入..." size="large" enterButton="搜索" /> </div> <div style="padding: 0 24px"> <a-tabs :tabBarStyle="{margin: 0}" @change="navigate" :activeKey="activeKey"> @@ -57,7 +57,7 @@ export default { <style lang="less" scoped> .search-head{ - background-color: #fff; + background-color: @base-bg-color; margin: -25px -24px -24px; .search-input{ text-align: center; diff --git a/src/pages/login/Login.vue b/src/pages/login/Login.vue index e378fe4..fff47c0 100644 --- a/src/pages/login/Login.vue +++ b/src/pages/login/Login.vue @@ -130,7 +130,7 @@ export default { } .title { font-size: 33px; - color: rgba(0,0,0,.85); + color: @title-color; font-family: 'Myriad Pro', 'Helvetica Neue', Arial, Helvetica, sans-serif; font-weight: 600; position: relative; @@ -139,7 +139,7 @@ export default { } .desc { font-size: 14px; - color: rgba(0,0,0,.45); + color: @text-color-second; margin-top: 12px; margin-bottom: 40px; } @@ -157,7 +157,7 @@ export default { } .icon { font-size: 24px; - color: rgba(0, 0, 0, 0.2); + color: @text-color-second; margin-left: 16px; vertical-align: middle; cursor: pointer; diff --git a/src/pages/result/Error.vue b/src/pages/result/Error.vue index 7193a9f..62e1f5f 100644 --- a/src/pages/result/Error.vue +++ b/src/pages/result/Error.vue @@ -5,7 +5,7 @@ <a-button type="primary" >返回修改</a-button> </template> <div> - <div style="fontSize: 16px; color: rgba(0, 0, 0, 0.85); fontWeight: 500; marginBottom: 16px"> + <div style="fontSize: 16px; fontWeight: 500; marginBottom: 16px"> 您提交的内容有如下错误: </div> <div style="margin-bottom: 16px"> diff --git a/src/theme/default/color.less b/src/theme/default/color.less index b5f22df..4aeb66c 100644 --- a/src/theme/default/color.less +++ b/src/theme/default/color.less @@ -14,3 +14,21 @@ @gray-11: #1f1f1f; @gray-12: #141414; @gray-13: #000000; + +@title-color: @heading-color; +@text-color: @text-color; +@text-color-second: @text-color-secondary; +@base-bg-color: @body-background; +@bg-color: @layout-body-background; +@hover-bg-color: rgba(0, 0, 0, 0.025); +@hover-bg-color-light: @hover-bg-color; +@hover-bg-color-dark: @primary-7; +@hover-bg-color-night: rgba(255, 255, 255, 0.025); +@header-bg-color-dark: @layout-header-background; + +@shadow-down: @shadow-1-down; +@shadow-up: @shadow-1-up; +@shadow-left: @shadow-1-left; +@shadow-right: @shadow-1-right; + +@theme-list: light, dark, night; diff --git a/src/utils/colors.js b/src/utils/colors.js index 1c607d1..a8a2e03 100644 --- a/src/utils/colors.js +++ b/src/utils/colors.js @@ -3,8 +3,13 @@ const varyColor = require('webpack-theme-color-replacer/client/varyColor') const antPrimaryColor = '#1890ff' // ant design vue 默认dark主题色,若主题色为默认主题色则返回此 dark 主题色系 const antDarkColors = ['#000c17', '#001529', '#002140'] +const nightColors = ['#151515', '#1f1f1f', '#1f1f1f'] -function getDarkColors(color) { + +function getDarkColors(color, theme) { + if (theme == 'night') { + return nightColors + } if (color == antPrimaryColor) { return antDarkColors } @@ -13,4 +18,37 @@ function getDarkColors(color) { return darkColors } -module.exports = {getDarkColors} +function getBgColors(theme) { + return theme == 'light' ? ['#f0f2f5', '#ffffff'] : ['#000000', '#141414'] +} + +function toNum3(color) { + if (isHex(color)) { + return varyColor.toNum3(color) + } + let colorStr = '' + if (isRgb(color)) { + colorStr = color.slice(5, color.length) + } else if (isRgba(color)) { + colorStr = color.slice(6, color.lastIndexOf(',')) + } + let rgb = colorStr.split(',') + const r = parseInt(rgb[0]) + const g = parseInt(rgb[1]) + const b = parseInt(rgb[2]) + return [r, g, b] +} + +function isHex(color) { + return color.length >= 4 && color[0] == '#' +} + +function isRgb(color) { + return color.length >= 10 && color.slice(0, 3) == 'rgb' +} + +function isRgba(color) { + return color.length >= 13 && color.slice(0, 4) == 'rgba' +} + +module.exports = {getDarkColors, getBgColors, isHex, isRgb, isRgba, toNum3} diff --git a/src/utils/themeUtil.js b/src/utils/themeUtil.js index 677d289..6da2bae 100644 --- a/src/utils/themeUtil.js +++ b/src/utils/themeUtil.js @@ -1,39 +1,44 @@ // const varyColor = require('webpack-theme-color-replacer/client/varyColor') const client = require('webpack-theme-color-replacer/client') const generate = require('@ant-design/colors/lib/generate').default -const themeColor = require('../config').themeColor -const getDarkColors = require('../utils/colors').getDarkColors +const {theme, themeColor} = require('../config') +const {getDarkColors, isHex, toNum3} = require('../utils/colors') +const themeCfg = require('../config/default').theme module.exports = { primaryColor: themeColor, - getThemeColors(color) { - const palettes = generate(color) - const darkBgColors = getDarkColors(color) - return palettes.concat(darkBgColors) + getThemeColors(color, $theme) { + let _theme = $theme || theme + let opts = (_theme == 'night') ? {theme: 'dark'} : undefined + let palettes = generate(color, opts) + const primary = palettes[5] + palettes = palettes.concat(generate(primary)) + console.log(palettes) + const darkBgColors = getDarkColors(color, _theme) + const _themeCfg = themeCfg[_theme] + const bgColors = Object.keys(_themeCfg) + .map(key => _themeCfg[key]) + .map(color => isHex(color) ? color : toNum3(color).join(',')) + let rgb = toNum3(primary).join(',') + return palettes.concat(darkBgColors).concat(bgColors).concat(rgb) }, - changeThemeColor (newColor) { - let lastColor = this.lastColor || this.primaryColor + changeThemeColor (newColor, $theme) { let options = { - oldColors: this.getThemeColors(lastColor), - newColors: this.getThemeColors(newColor) + newColors: this.getThemeColors(newColor, $theme) } let promise = client.changer.changeColor(options) - this.lastColor = lastColor return promise }, changeSelector (selector) { switch (selector) { case '.ant-layout-sider': return '.ant-layout-sider-dark' - case '.ant-calendar-today .ant-calendar-date': - return ':not(.ant-calendar-selected-date):not(.ant-calendar-selected-day)' + selector - case '.ant-btn:focus,.ant-btn:hover': - return '.ant-btn:focus:not(.ant-btn-primary):not(.ant-btn-danger),.ant-btn:hover:not(.ant-btn-primary):not(.ant-btn-danger)' - case '.ant-btn.active,.ant-btn:active': - return '.ant-btn.active:not(.ant-btn-primary):not(.ant-btn-danger),.ant-btn:active:not(.ant-btn-primary):not(.ant-btn-danger)' - case '.ant-steps-item-process .ant-steps-item-icon > .ant-steps-icon': - case '.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon': - return ':not(.ant-steps-item-process)' + selector + case '.ant-menu-dark .ant-menu-inline.ant-menu-sub': + return '.ant-menu-dark .ant-menu-inline:not(.ant-menu-sub)' + case '.ant-checkbox-checked .ant-checkbox-inner::after': + return '.ant-checkbox-checked :not(.ant-checkbox-inner)::after' + case '.side-menu .logo h1': + return '.side-menu .logo :not(h1)' case '.ant-menu-horizontal>.ant-menu-item-active,.ant-menu-horizontal>.ant-menu-item-open,.ant-menu-horizontal>.ant-menu-item-selected,.ant-menu-horizontal>.ant-menu-item:hover,.ant-menu-horizontal>.ant-menu-submenu-active,.ant-menu-horizontal>.ant-menu-submenu-open,.ant-menu-horizontal>.ant-menu-submenu-selected,.ant-menu-horizontal>.ant-menu-submenu:hover': case '.ant-menu-horizontal > .ant-menu-item-active,.ant-menu-horizontal > .ant-menu-item-open,.ant-menu-horizontal > .ant-menu-item-selected,.ant-menu-horizontal > .ant-menu-item:hover,.ant-menu-horizontal > .ant-menu-submenu-active,.ant-menu-horizontal > .ant-menu-submenu-open,.ant-menu-horizontal > .ant-menu-submenu-selected,.ant-menu-horizontal > .ant-menu-submenu:hover': return '.ant-menu-horizontal > .ant-menu-item-active,.ant-menu-horizontal > .ant-menu-item-open,.ant-menu-horizontal > .ant-menu-item-selected,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-item:hover,.ant-menu-horizontal > .ant-menu-submenu-active,.ant-menu-horizontal > .ant-menu-submenu-open,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-submenu-selected,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-submenu:hover' @@ -48,14 +53,29 @@ module.exports = { } }, modifyVars(color) { - let darkColors = getDarkColors(color) + let opts = (theme == 'night') ? {theme: 'dark'} : undefined + const darkColors = getDarkColors(color, theme) + const palettes = generate(color, opts) return { - 'primary-color': color, - 'info-color': color, - 'processing-color': color, + 'primary-color': palettes[5], + 'primary-1': palettes[0], + 'primary-2': palettes[1], + 'primary-3': palettes[2], + 'primary-4': palettes[3], + 'primary-5': palettes[4], + 'primary-6': palettes[5], + 'primary-7': palettes[6], + 'primary-8': palettes[7], + 'primary-9': palettes[8], + 'primary-10': palettes[9], + 'info-color': palettes[5], + 'alert-info-bg-color': palettes[0], + 'alert-info-border-color': palettes[3], + 'processing-color': palettes[5], 'menu-dark-submenu-bg': darkColors[0], 'layout-header-background': darkColors[1], - 'layout-trigger-background': darkColors[2] + 'layout-trigger-background': darkColors[2], + ...themeCfg[theme] } } }