Browse Source

💗 修复主题色动态切换

pull/12/head
boliang 3 years ago
parent
commit
b4522841ba
  1. 5
      package.json
  2. 92
      pnpm-lock.yaml
  3. 6
      src/App.vue
  4. 1
      src/assets/theme/blue.less
  5. 1
      src/assets/theme/green.less
  6. 1
      src/assets/theme/purple.less
  7. 1
      src/assets/theme/red.less
  8. 1
      src/assets/theme/yellow.less
  9. 13
      src/configure/pear.config.js
  10. 19
      src/layout/module/setup/index.vue
  11. 1
      src/main.js
  12. 95
      src/store/modules/app.js
  13. 24
      src/tools/storage.js
  14. 16
      src/view/dashboard/console.vue
  15. 41
      vite.config.js

5
package.json

@ -3,7 +3,6 @@
"version": "2.0.1-Release",
"private": true,
"scripts": {
"//": "开发预览",
"serve": "vite",
"build": "vite build",
"build-prod": "vite build --mode production",
@ -20,6 +19,7 @@
"lodash.get": "^4.4.2",
"moment": "^2.27.0",
"nprogress": "^0.2.0",
"path": "^0.12.7",
"rollup-plugin-visualizer": "^5.5.2",
"vue": "^3.2.12",
"vue-i18n": "^9.1.7",
@ -27,9 +27,10 @@
"vuex": "^4.0.2"
},
"devDependencies": {
"@babel/eslint-parser": "^7.15.8",
"@types/node": "^14.17.9",
"@vue/compiler-sfc": "^3.2.12",
"@babel/eslint-parser": "^7.15.8",
"@zougt/vite-plugin-theme-preprocessor": "^1.3.12",
"babel-plugin-import": "^1.13.3",
"eslint": "^6.8.0",
"eslint-plugin-vue": "^7.18.0",

92
pnpm-lock.yaml

@ -8,6 +8,7 @@ specifiers:
'@types/node': ^14.17.9
'@vitejs/plugin-vue': ^1.6.2
'@vue/compiler-sfc': ^3.2.12
'@zougt/vite-plugin-theme-preprocessor': ^1.3.12
ant-design-vue: ^2.2.8
axios: ^0.21.1
babel-plugin-import: ^1.13.3
@ -21,6 +22,7 @@ specifiers:
moment: ^2.27.0
node-sass: ^6.0.0
nprogress: ^0.2.0
path: ^0.12.7
rollup-plugin-analyzer: ^4.0.0
rollup-plugin-visualizer: ^5.5.2
sass-loader: ^10.0.2
@ -41,6 +43,7 @@ dependencies:
lodash.get: 4.4.2
moment: 2.29.1
nprogress: 0.2.0
path: 0.12.7
rollup-plugin-visualizer: 5.5.2
vue: 3.2.20
vue-i18n: 9.1.9_vue@3.2.20
@ -51,6 +54,7 @@ devDependencies:
'@babel/eslint-parser': 7.15.8_eslint@6.8.0
'@types/node': 14.17.32
'@vue/compiler-sfc': 3.2.20
'@zougt/vite-plugin-theme-preprocessor': 1.3.12_less@3.13.1
babel-plugin-import: 1.13.3
eslint: 6.8.0
eslint-plugin-vue: 7.20.0_eslint@6.8.0
@ -510,6 +514,30 @@ packages:
/@vue/shared/3.2.20:
resolution: {integrity: sha512-FbpX+hD5BvXCQerEYO7jtAGHlhAkhTQ4KIV73kmLWNlawWhTiVuQxizgVb0BOkX5oG9cIRZ42EG++d/k/Efp0w==}
/@zougt/some-loader-utils/1.3.4_less@3.13.1:
resolution: {integrity: sha512-HjlSsEVcpuDrOlUXRMZzLdoWvWAdhign3uNhuSBd4ydfoOnWBRcWNBWyt5ZvIT+CcqIRLli4LfQ3K6xSJxc6NA==}
engines: {node: '>= 10.13.0'}
peerDependencies:
less: ^3.13.1 || ^4.1.1
sass: ^1.32.8
dependencies:
less: 3.13.1
parse-color: 1.0.0
postcss: 8.3.11
dev: true
/@zougt/vite-plugin-theme-preprocessor/1.3.12_less@3.13.1:
resolution: {integrity: sha512-QvHx6lDgzOvunZ2jG5Xerb/GDfvxrEPPwfK3GmcHbsvDuXy68nS66ezls2YM1qETp2lChaHYx1eynhdHqQhtzQ==}
engines: {node: '>= 12.0.0'}
dependencies:
'@zougt/some-loader-utils': 1.3.4_less@3.13.1
fs-extra: 9.1.0
string-hash: 1.1.3
transitivePeerDependencies:
- less
- sass
dev: true
/abbrev/1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
dev: true
@ -669,6 +697,11 @@ packages:
resolution: {integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k=}
dev: true
/at-least-node/1.0.0:
resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
engines: {node: '>= 4.0.0'}
dev: true
/aws-sign2/0.7.0:
resolution: {integrity: sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=}
dev: true
@ -806,6 +839,10 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/color-convert/0.5.3:
resolution: {integrity: sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=}
dev: true
/color-convert/1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
@ -1426,6 +1463,16 @@ packages:
mime-types: 2.1.33
dev: true
/fs-extra/9.1.0:
resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
engines: {node: '>=10'}
dependencies:
at-least-node: 1.0.0
graceful-fs: 4.2.8
jsonfile: 6.1.0
universalify: 2.0.0
dev: true
/fs-minipass/2.1.0:
resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
engines: {node: '>= 8'}
@ -1653,6 +1700,10 @@ packages:
wrappy: 1.0.2
dev: true
/inherits/2.0.3:
resolution: {integrity: sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=}
dev: false
/inherits/2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: true
@ -1804,6 +1855,14 @@ packages:
minimist: 1.2.5
dev: true
/jsonfile/6.1.0:
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
dependencies:
universalify: 2.0.0
optionalDependencies:
graceful-fs: 4.2.8
dev: true
/jsprim/1.4.1:
resolution: {integrity: sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=}
engines: {'0': node >=0.6.0}
@ -2254,6 +2313,12 @@ packages:
callsites: 3.1.0
dev: true
/parse-color/1.0.0:
resolution: {integrity: sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=}
dependencies:
color-convert: 0.5.3
dev: true
/parse-json/5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
@ -2293,6 +2358,13 @@ packages:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true
/path/0.12.7:
resolution: {integrity: sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=}
dependencies:
process: 0.11.10
util: 0.10.4
dev: false
/performance-now/2.1.0:
resolution: {integrity: sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=}
dev: true
@ -2323,6 +2395,11 @@ packages:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
dev: true
/process/0.11.10:
resolution: {integrity: sha1-czIwDoQBYb2j5podHZGn1LwW8YI=}
engines: {node: '>= 0.6.0'}
dev: false
/progress/2.0.3:
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
engines: {node: '>=0.4.0'}
@ -2712,6 +2789,10 @@ packages:
readable-stream: 2.3.7
dev: true
/string-hash/1.1.3:
resolution: {integrity: sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=}
dev: true
/string-width/1.0.2:
resolution: {integrity: sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=}
engines: {node: '>=0.10.0'}
@ -2900,6 +2981,11 @@ packages:
engines: {node: '>=8'}
dev: true
/universalify/2.0.0:
resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==}
engines: {node: '>= 10.0.0'}
dev: true
/uri-js/4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
dependencies:
@ -2910,6 +2996,12 @@ packages:
resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=}
dev: true
/util/0.10.4:
resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==}
dependencies:
inherits: 2.0.3
dev: false
/uuid/3.4.0:
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.

6
src/App.vue

@ -7,9 +7,11 @@
import {computed, defineComponent, ref} from "vue";
import {useStore} from "vuex";
import {useI18n} from 'vue-i18n/index';
import { toggleTheme } from "@zougt/vite-plugin-theme-preprocessor/dist/browser-utils.js";
export default defineComponent({
name: 'App',
setup() {
const store = useStore()
const defaultLang = computed(() => store.getters['app/language'])
const color = computed(() => store.getters.color);
@ -21,6 +23,10 @@ export default defineComponent({
})
)
toggleTheme({
scopeName: color.value.scopeName,
});
return {
antdLocal
}

1
src/assets/theme/blue.less

@ -0,0 +1 @@
@primary-color: #2d8cf0;

1
src/assets/theme/green.less

@ -0,0 +1 @@
@primary-color: #36b368;

1
src/assets/theme/purple.less

@ -0,0 +1 @@
@primary-color: #3963bc;

1
src/assets/theme/red.less

@ -0,0 +1 @@
@primary-color: #f56c6c;

1
src/assets/theme/yellow.less

@ -0,0 +1 @@
@primary-color: #f6ad55;

13
src/configure/pear.config.js

@ -25,7 +25,7 @@ export default {
/**
* 参数 : 默认的主题
* theme-dark
* theme-default
* theme-light
* theme-night
* */
@ -95,13 +95,20 @@ export default {
* 参数: 主题颜色
* color - list
*/
color: "#36b368",
color: {key:1, scopeName: "theme-blue", color:'#2d8cf0'},
/**
* 参数: 可选的主题颜色列表
* color - key
* color - scopeName
* color - color
*/
colorList: ["#2d8cf0","#36b368","#f6ad55","#f56c6c","#3963bc","#13C2C2"],
colorList: [
{key:1,scopeName:"theme-blue",color:'#2d8cf0'},
{key:2,scopeName:"theme-green",color:'#36b368'},
{key:3,scopeName:"theme-yellow",color:'#f6ad55'},
{key:4,scopeName:"theme-red",color:'#f56c6c'},
{key:5,scopeName:"theme-purple",color:'#3963bc'}],
/**
* 参数: 路由动画

19
src/layout/module/setup/index.vue

@ -334,8 +334,8 @@
class="select-color-item"
:key="index"
@click="updateColor(colorItem)"
:style="{ 'background-color': colorItem }"
><CheckOutlined v-if="color === colorItem"
:style="{ 'background-color': colorItem.color }"
><CheckOutlined v-if="color.scopeName === colorItem.scopeName"
/></span>
</div>
</div>
@ -399,6 +399,7 @@
</a-drawer>
</template>
<script>
import { toggleTheme } from "@zougt/vite-plugin-theme-preprocessor/dist/browser-utils.js";
import { CheckOutlined } from "@ant-design/icons-vue";
import { computed } from "vue";
import { useStore } from "vuex";
@ -420,7 +421,7 @@ export default {
const colorList = computed(() => getters.colorList);
const routerAnimate = { key: computed(() => getters.routerAnimate) };
const tabType = { key: computed(() => getters.tabType).value };
const updateLayout = function (layout) {
commit("app/UPDATE_LAYOUT", layout);
};
@ -434,15 +435,13 @@ export default {
commit("app/TOGGLE_KEEP_ALIVE");
};
const updateColor = function (color) {
window.less.modifyVars({
"primary-color": color,
"btn-primary-bg": color,
})
toggleTheme({ scopeName: color.scopeName });
commit("app/UPDATE_COLOR", color);
};
const handleChange = function (value) {
commit("app/UPDATE_TAB_TYPE", value.key);
};
return {
tabType,
toggleKeepAlive,
@ -461,6 +460,7 @@ export default {
layout,
keepAlive,
theme,
color,
onChangeVisible: () => commit("app/TOGGLE_SETTING"),
onChangeLogo: () => commit("app/TOGGLE_LOGO"),
onChangeTab: () => commit("app/updateTab"),
@ -469,10 +469,7 @@ export default {
onChangeFixedHeader: () => commit("app/TOGGLE_FIXEDHEADER"),
onChangeLayout: () => commit("app/TOGGLE_LAYOUT"),
afterVisibleChange: () => {},
changeLanguage: (e) => {
commit("app/setLanguage", e.target.value);
},
color,
changeLanguage: (e) => commit("app/setLanguage", e.target.value),
};
},
};

1
src/main.js

@ -12,6 +12,7 @@ import "./mock";
import "./assets/css/index.less";
import "ant-design-vue/dist/antd.less";
const app = createApp(App);
app.use(Antd);
app.use(Pear);

95
src/store/modules/app.js

@ -1,19 +1,15 @@
import config from "../../configure/pear.config.js";
import { getStorage, setStorage, delStorage } from "../../tools/storage.js";
const state = {
/**
* 布局方式整体界面的排版方式
* layout-side -- 侧边布局
* layout-head -- 顶部菜单
* layout-comp -- 联动布局
* */
layout:
config.layout == null
? "layout-side"
: localStorage.getItem("layout") == null
? config.layout
: localStorage.getItem("layout"),
* 布局方式整体界面的排版方式
* layout-side -- 侧边布局
* layout-head -- 顶部菜单
* layout-comp -- 联动布局
* */
layout: getStorage('layout') != null ? getStorage('layout') : config.layout,
/**
* 系统主题整体色调
@ -21,82 +17,53 @@ const state = {
* dark -- 暗色主题
* night -- 夜间主题
*/
theme:
config.theme == null
? "theme-dark"
: localStorage.getItem("theme") == null
? config.theme
: localStorage.getItem("theme"),
theme: getStorage('theme') != null ? getStorage.getStorage('theme') : config.theme,
/**
* 主题颜色(主题颜色)
*/
color:
config.color == null
? "theme-green"
: localStorage.getItem("color") == null
? config.color
: localStorage.getItem("color"),
color: getStorage('color') != null ? getStorage('color') : config.color,
/**
* 侧边状态
* true -- 隐藏
* false -- 展开
* */
collapsed:
config.collapsed == null
? false
: localStorage.getItem("collapsed") == null
? config.collapsed
: localStorage.getItem("collapsed"),
collapsed: getStorage('collapsed') != null ? getStorage('collapsed') : config.collapsed,
/**
* 菜单头部
* true -- 隐藏
* false -- 展开
* */
logo:
config.logo == null
? true
: localStorage.getItem("logo") == null
? config.logo
: localStorage.getItem("logo"),
logo: getStorage('logo') != null ? getStorage('logo') : config.logo,
/**
* 是否开启多标签页
* true -- 隐藏
* false -- 展开
* */
tab:
config.tab == null
? true
: localStorage.getItem("tab") == null
? config.tab
: localStorage.getItem("tab"),
tab: getStorage('tab') != null ? getStorage('tab') : config.tab,
/**
* 保持状态
* true --
* false --
*/
keepAlive: config.keepAlive == null ? true : localStorage.getItem("keepAlive") == null ? config.keepAlive : localStorage.getItem("keepAlive"),
keepAlive: getStorage('keepAlive') != null ? getStorage('keepAlive') : config.keepAlive,
/**
* 多标签页样式
* pear-card-tab
* pear-dot-tab
*/
tabType:
config.tabType == null
? "pear-dot-tab"
: localStorage.getItem("tabType") == null
? config.tabType
: localStorage.getItem("tabType"),
tabType: getStorage('tabType') != null ? getStorage('tabType') : config.tabType,
/**
* 侧边菜单栏宽度
* 单位:px
* */
sideWitch: config.sideWidth == null ? 220 : config.sideWidth,
/**
* 侧边菜单栏宽度(折叠)
* 单位:px
@ -108,36 +75,21 @@ const state = {
* true
* false
*/
fixedHeader:
config.fixedHeader == null
? true
: localStorage.getItem("fixedHeader") == null
? config.fixedHeader
: localStorage.getItem("fixedHeader"),
fixedHeader: getStorage('fixedHeader') != null ? getStorage('fixedHeader') : config.fixedHeader,
/**
* 固定侧边
* true
* false
*/
fixedSide:
config.fixedSide == null
? true
: localStorage.getItem("fixedSide") == null
? config.fixedSide
: localStorage.getItem("fixedSide"),
fixedSide: getStorage('fixedSide') != null ? getStorage('fixedSide') : config.fixedHeader,
/**
* 路由动画
* fadeRight
* fadeTop
*/
routerAnimate:
config.routerAnimate == null
? ""
: localStorage.getItem("routerAnimate") == null
? config.routerAnimate
: localStorage.getItem("routerAnimate"),
routerAnimate: getStorage('routerAnimate') != null ? getStorage('routerAnimate') : config.routerAnimate,
/**
* 配色列表
@ -161,12 +113,8 @@ const state = {
// 是否是移动端
isMobile: false,
// 国际化
language:
config.defaultLanguage == null
? "zh-CN"
: localStorage.getItem("pear_lang") == null
? config.defaultLanguage
: localStorage.getItem("pear_lang"),
language: getStorage('language') != null ? getStorage('language') : config.defaultLanguage,
cancelToken: []
}
@ -201,14 +149,13 @@ const mutations = {
},
UPDATE_THEME(state, theme) {
state.theme = theme;
let element = document.querySelector('html');
theme === 'theme-night' ? element.setAttribute('data-doc-theme', 'dark') : element.removeAttribute('data-doc-theme');
},
UPDATE_ROUTER_ANIMATE(state, routerAnimate) {
state.routerAnimate = routerAnimate;
},
UPDATE_COLOR(state, color) {
state.color = color;
setStorage('color', color);
},
UPDATE_ROUTES(state, routes) {
state.routes = routes;

24
src/tools/storage.js

@ -0,0 +1,24 @@
/**
* 存储对象
* @param key
* @param value
*/
export const setStorage = function (key,value) {
localStorage.setItem(key, JSON.stringify(value))
}
/**
* 获取对象
* @param key
*/
export const getStorage = function (key) {
return JSON.parse(localStorage.getItem(key))
}
/**
* 删除对象
* @param key
*/
export const delStorage = function (key) {
localStorage.removeItem(key)
}

16
src/view/dashboard/console.vue

@ -11,9 +11,9 @@
speed="300"
/>
<a-progress
:show-info="false"
show-info="false"
style="margin-top: 16px"
:percent="30"
percent="30"
size="small"
/>
<a-divider />
@ -31,10 +31,10 @@
/>
<a-progress
style="margin-top: 16px"
:percent="50"
percent="50"
size="small"
status="active"
:show-info="false"
show-info="false"
/>
<a-divider />
<div class="card-left">销售量</div>
@ -50,9 +50,9 @@
speed="300"
/>
<a-progress
:show-info="false"
show-info="false"
style="margin-top: 16px"
:percent="30"
percent="30"
size="small"
/>
<a-divider />
@ -70,10 +70,10 @@
/>
<a-progress
style="margin-top: 16px"
:percent="50"
percent="50"
size="small"
status="active"
:show-info="false"
show-info="false"
/>
<a-divider />
<div class="card-left">用户量</div>

41
vite.config.js

@ -2,8 +2,34 @@ import { resolve } from 'path/posix';
import { defineConfig } from 'vite';
import vue from "@vitejs/plugin-vue";
import visualizer from "rollup-plugin-visualizer";
import path from 'path'
import themePreprocessorPlugin from "@zougt/vite-plugin-theme-preprocessor";
const plugins = [vue()];
const plugins = [vue(),
themePreprocessorPlugin({
less: {
// 各个主题文件的位置
multipleScopeVars: [
{
scopeName: "theme-blue",
path: path.resolve("src/assets/theme/blue.less"),
},{
scopeName: "theme-green",
path: path.resolve("src/assets/theme/green.less"),
}, {
scopeName: "theme-yellow",
path: path.resolve("src/assets/theme/yellow.less"),
}, {
scopeName: "theme-red",
path: path.resolve("src/assets/theme/red.less"),
}, {
scopeName: "theme-purple",
path: path.resolve("src/assets/theme/purple.less"),
}
],
},
})
];
if (process.env.vis) {
plugins.push(
@ -21,18 +47,19 @@ export default defineConfig({
port: 8080
},
resolve: {
alias: {
'@': resolve('src')
}
alias: {
'@': resolve('src')
}
},
// 开启less支持
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true,
javascriptEnabled: true
}
},
}
},
hmr: {
overlay: false
overlay: false
}
})
Loading…
Cancel
Save