style:element 换肤
Showing
6 changed files
with
190 additions
and
23 deletions
| 1 | import dialogBox from '@/components/DialogBox/dialogBox.vue' | 1 | import dialogBox from '@/components/DialogBox/dialogBox.vue' |
| 2 | import lbTable from '@/components/lb-table/lb-table.vue' | 2 | import lbTable from '@/components/lb-table/lb-table.vue' |
| 3 | import Theme from '@/components/Theme/theme.vue' | ||
| 3 | export default { | 4 | export default { |
| 4 | install: (Vue) => { | 5 | install: (Vue) => { |
| 5 | Vue.component('dialogBox', dialogBox); | 6 | Vue.component('dialogBox', dialogBox); |
| 6 | Vue.component('lbTable', lbTable); | 7 | Vue.component('lbTable', lbTable); |
| 8 | Vue.component('Theme', Theme); | ||
| 7 | } | 9 | } |
| 8 | } | 10 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
src/components/Theme/theme.vue
0 → 100644
| 1 | <template> | ||
| 2 | <el-color-picker v-model="theme" | ||
| 3 | :predefine="['#409EFF', '#1890ff', '#304156', '#212121', '#11a983', '#13c2c2', '#6959CD', '#f5222d',]" | ||
| 4 | class="theme-picker" popper-class="theme-picker-dropdown" /> | ||
| 5 | </template> | ||
| 6 | |||
| 7 | <script> | ||
| 8 | const version = require('element-ui/package.json').version // element-ui version from node_modules | ||
| 9 | const ORIGINAL_THEME = '#409EFF' // default color | ||
| 10 | |||
| 11 | export default { | ||
| 12 | data () { | ||
| 13 | return { | ||
| 14 | chalk: '', // content of theme-chalk css | ||
| 15 | theme: '' | ||
| 16 | } | ||
| 17 | }, | ||
| 18 | computed: { | ||
| 19 | defaultTheme () { | ||
| 20 | return this.$store.state.app.theme | ||
| 21 | } | ||
| 22 | }, | ||
| 23 | watch: { | ||
| 24 | defaultTheme: { | ||
| 25 | handler: function (val, oldVal) { | ||
| 26 | this.theme = val | ||
| 27 | }, | ||
| 28 | immediate: true | ||
| 29 | }, | ||
| 30 | async theme (val) { | ||
| 31 | const oldVal = this.chalk ? this.theme : ORIGINAL_THEME | ||
| 32 | if (typeof val !== 'string') return | ||
| 33 | const themeCluster = this.getThemeCluster(val.replace('#', '')) | ||
| 34 | const originalCluster = this.getThemeCluster(oldVal.replace('#', '')) | ||
| 35 | console.log(themeCluster, originalCluster) | ||
| 36 | |||
| 37 | const $message = this.$message({ | ||
| 38 | message: ' Compiling the theme', | ||
| 39 | customClass: 'theme-message', | ||
| 40 | type: 'success', | ||
| 41 | duration: 0, | ||
| 42 | iconClass: 'el-icon-loading' | ||
| 43 | }) | ||
| 44 | |||
| 45 | const getHandler = (variable, id) => { | ||
| 46 | return () => { | ||
| 47 | const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', '')) | ||
| 48 | const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster) | ||
| 49 | |||
| 50 | let styleTag = document.getElementById(id) | ||
| 51 | if (!styleTag) { | ||
| 52 | styleTag = document.createElement('style') | ||
| 53 | styleTag.setAttribute('id', id) | ||
| 54 | document.head.appendChild(styleTag) | ||
| 55 | } | ||
| 56 | styleTag.innerText = newStyle | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | if (!this.chalk) { | ||
| 61 | const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css` | ||
| 62 | await this.getCSSString(url, 'chalk') | ||
| 63 | } | ||
| 64 | |||
| 65 | const chalkHandler = getHandler('chalk', 'chalk-style') | ||
| 66 | |||
| 67 | chalkHandler() | ||
| 68 | |||
| 69 | const styles = [].slice.call(document.querySelectorAll('style')) | ||
| 70 | .filter(style => { | ||
| 71 | const text = style.innerText | ||
| 72 | return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text) | ||
| 73 | }) | ||
| 74 | styles.forEach(style => { | ||
| 75 | const { innerText } = style | ||
| 76 | if (typeof innerText !== 'string') return | ||
| 77 | style.innerText = this.updateStyle(innerText, originalCluster, themeCluster) | ||
| 78 | }) | ||
| 79 | |||
| 80 | this.$emit('change', val) | ||
| 81 | |||
| 82 | $message.close() | ||
| 83 | } | ||
| 84 | }, | ||
| 85 | |||
| 86 | methods: { | ||
| 87 | updateStyle (style, oldCluster, newCluster) { | ||
| 88 | let newStyle = style | ||
| 89 | oldCluster.forEach((color, index) => { | ||
| 90 | newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index]) | ||
| 91 | }) | ||
| 92 | return newStyle | ||
| 93 | }, | ||
| 94 | |||
| 95 | getCSSString (url, variable) { | ||
| 96 | return new Promise(resolve => { | ||
| 97 | const xhr = new XMLHttpRequest() | ||
| 98 | xhr.onreadystatechange = () => { | ||
| 99 | if (xhr.readyState === 4 && xhr.status === 200) { | ||
| 100 | this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '') | ||
| 101 | resolve() | ||
| 102 | } | ||
| 103 | } | ||
| 104 | xhr.open('GET', url) | ||
| 105 | xhr.send() | ||
| 106 | }) | ||
| 107 | }, | ||
| 108 | |||
| 109 | getThemeCluster (theme) { | ||
| 110 | const tintColor = (color, tint) => { | ||
| 111 | let red = parseInt(color.slice(0, 2), 16) | ||
| 112 | let green = parseInt(color.slice(2, 4), 16) | ||
| 113 | let blue = parseInt(color.slice(4, 6), 16) | ||
| 114 | |||
| 115 | if (tint === 0) { // when primary color is in its rgb space | ||
| 116 | return [red, green, blue].join(',') | ||
| 117 | } else { | ||
| 118 | red += Math.round(tint * (255 - red)) | ||
| 119 | green += Math.round(tint * (255 - green)) | ||
| 120 | blue += Math.round(tint * (255 - blue)) | ||
| 121 | |||
| 122 | red = red.toString(16) | ||
| 123 | green = green.toString(16) | ||
| 124 | blue = blue.toString(16) | ||
| 125 | |||
| 126 | return `#${red}${green}${blue}` | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | const shadeColor = (color, shade) => { | ||
| 131 | let red = parseInt(color.slice(0, 2), 16) | ||
| 132 | let green = parseInt(color.slice(2, 4), 16) | ||
| 133 | let blue = parseInt(color.slice(4, 6), 16) | ||
| 134 | |||
| 135 | red = Math.round((1 - shade) * red) | ||
| 136 | green = Math.round((1 - shade) * green) | ||
| 137 | blue = Math.round((1 - shade) * blue) | ||
| 138 | |||
| 139 | red = red.toString(16) | ||
| 140 | green = green.toString(16) | ||
| 141 | blue = blue.toString(16) | ||
| 142 | |||
| 143 | return `#${red}${green}${blue}` | ||
| 144 | } | ||
| 145 | |||
| 146 | const clusters = [theme] | ||
| 147 | for (let i = 0; i <= 9; i++) { | ||
| 148 | clusters.push(tintColor(theme, Number((i / 10).toFixed(2)))) | ||
| 149 | } | ||
| 150 | clusters.push(shadeColor(theme, 0.1)) | ||
| 151 | return clusters | ||
| 152 | } | ||
| 153 | } | ||
| 154 | } | ||
| 155 | </script> | ||
| 156 | |||
| 157 | <style> | ||
| 158 | .theme-message, | ||
| 159 | .theme-picker-dropdown { | ||
| 160 | z-index: 99999 !important; | ||
| 161 | } | ||
| 162 | |||
| 163 | .theme-picker .el-color-picker__trigger { | ||
| 164 | height: 26px !important; | ||
| 165 | width: 26px !important; | ||
| 166 | padding: 2px; | ||
| 167 | } | ||
| 168 | |||
| 169 | .theme-picker-dropdown .el-color-dropdown__link-btn { | ||
| 170 | display: none; | ||
| 171 | } | ||
| 172 | </style> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -3,7 +3,9 @@ | ... | @@ -3,7 +3,9 @@ |
| 3 | <div class="logo"> | 3 | <div class="logo"> |
| 4 | <img v-if="logo" :src="logo" class="header-logo"> | 4 | <img v-if="logo" :src="logo" class="header-logo"> |
| 5 | </div> | 5 | </div> |
| 6 | <div class="backdrop"></div> | 6 | <div class="backdrop"> |
| 7 | <theme style="float: right;height: 26px;width: 26px;margin-top: 26px;" @change="themeChange" /> | ||
| 8 | </div> | ||
| 7 | <div class="right-menu"> | 9 | <div class="right-menu"> |
| 8 | <el-dropdown class="avatar-container right-menu-item hover-effect" @command="handleCommand"> | 10 | <el-dropdown class="avatar-container right-menu-item hover-effect" @command="handleCommand"> |
| 9 | <div class="avatar-wrapper"> | 11 | <div class="avatar-wrapper"> |
| ... | @@ -31,6 +33,9 @@ export default { | ... | @@ -31,6 +33,9 @@ export default { |
| 31 | } | 33 | } |
| 32 | }, | 34 | }, |
| 33 | methods: { | 35 | methods: { |
| 36 | themeChange (val) { | ||
| 37 | this.$store.dispatch('app/updateTheme', val) | ||
| 38 | }, | ||
| 34 | searchMessageCenter () { | 39 | searchMessageCenter () { |
| 35 | this.$router.push({ name: 'messagecenter' }) | 40 | this.$router.push({ name: 'messagecenter' }) |
| 36 | }, | 41 | }, | ... | ... |
| ... | @@ -5,7 +5,7 @@ import App from './App' | ... | @@ -5,7 +5,7 @@ import App from './App' |
| 5 | import 'normalize.css/normalize.css' // a modern alternative to CSS resets | 5 | import 'normalize.css/normalize.css' // a modern alternative to CSS resets |
| 6 | import Element from 'element-ui' | 6 | import Element from 'element-ui' |
| 7 | import './styles/element-variables.scss' | 7 | import './styles/element-variables.scss' |
| 8 | import '@/styles/index.scss' // global css | 8 | import '@/styles/index.scss' |
| 9 | import Base from './components/Base/base' | 9 | import Base from './components/Base/base' |
| 10 | 10 | ||
| 11 | import './image/icons' // icon | 11 | import './image/icons' // icon | ... | ... |
| 1 | import Cookies from 'js-cookie' | 1 | import Cookies from 'js-cookie' |
| 2 | 2 | ||
| 3 | const state = { | 3 | const state = { |
| 4 | size: 'small' | 4 | size: 'small', |
| 5 | theme: '#409EFF' | ||
| 5 | } | 6 | } |
| 6 | 7 | ||
| 7 | const mutations = { | 8 | const mutations = { |
| 8 | SET_SIZE: (state, size) => { | 9 | SET_SIZE: (state, size) => { |
| 9 | state.size = size | 10 | state.size = size |
| 10 | Cookies.set('size', size) | 11 | Cookies.set('size', size) |
| 11 | } | 12 | }, |
| 13 | UPDATE_THEME (state, val) { | ||
| 14 | state.theme = val; | ||
| 15 | }, | ||
| 12 | } | 16 | } |
| 13 | 17 | ||
| 14 | const actions = { | 18 | const actions = { |
| 15 | closeSideBar ({ commit }, { withoutAnimation }) { | ||
| 16 | commit('CLOSE_SIDEBAR', withoutAnimation) | ||
| 17 | }, | ||
| 18 | setSize ({ commit }, size) { | 19 | setSize ({ commit }, size) { |
| 19 | commit('SET_SIZE', size) | 20 | commit('SET_SIZE', size) |
| 21 | }, | ||
| 22 | updateTheme ({ commit }, val) { | ||
| 23 | commit('UPDATE_THEME', val) | ||
| 20 | } | 24 | } |
| 21 | } | 25 | } |
| 22 | 26 | ... | ... |
| ... | @@ -326,19 +326,3 @@ input[type="number"] { | ... | @@ -326,19 +326,3 @@ input[type="number"] { |
| 326 | position: absolute; | 326 | position: absolute; |
| 327 | right: 25px; | 327 | right: 25px; |
| 328 | } | 328 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 329 | |||
| 330 | // 表格分页 | ||
| 331 | .el-pagination.is-background .btn-prev, | ||
| 332 | .el-pagination.is-background .btn-next, | ||
| 333 | .el-pagination.is-background .el-pager li, | ||
| 334 | .el-pagination .el-select .el-input .el-input__inner { | ||
| 335 | background-color: #fff !important; | ||
| 336 | border: 1px solid #E4EBF4 !important; | ||
| 337 | border-radius: 5px !important; | ||
| 338 | } | ||
| 339 | |||
| 340 | .el-pagination.is-background .el-pager li.active { | ||
| 341 | background-color: #0F93F6 !important; | ||
| 342 | border: 1px solid #0F93F6 !important; | ||
| 343 | color: #fff !important; | ||
| 344 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or sign in to post a comment