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 | ... | ... |
... | @@ -325,20 +325,4 @@ input[type="number"] { | ... | @@ -325,20 +325,4 @@ input[type="number"] { |
325 | .el-date-editor.el-date-editor--daterange .el-icon-circle-close { | 325 | .el-date-editor.el-date-editor--daterange .el-icon-circle-close { |
326 | position: absolute; | 326 | position: absolute; |
327 | right: 25px; | 327 | right: 25px; |
328 | } | ||
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 | } | 328 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or sign in to post a comment