feat(projects): 添加缓存主题色
This commit is contained in:
parent
1d63a83822
commit
37092974d3
@ -12,8 +12,7 @@ const routes: AuthRoute.Route[] = [
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '分析页',
|
title: '分析页',
|
||||||
requiresAuth: true,
|
requiresAuth: true
|
||||||
keepAlive: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -98,7 +97,6 @@ const routes: AuthRoute.Route[] = [
|
|||||||
title: '关于',
|
title: '关于',
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
singleLayout: 'basic',
|
singleLayout: 'basic',
|
||||||
keepAlive: true,
|
|
||||||
permissions: ['super', 'admin', 'test'],
|
permissions: ['super', 'admin', 'test'],
|
||||||
icon: 'fluent:book-information-24-regular',
|
icon: 'fluent:book-information-24-regular',
|
||||||
order: 7
|
order: 7
|
||||||
|
@ -34,8 +34,8 @@ function initSvgLogo(id) {
|
|||||||
|
|
||||||
function addThemeColorCssVars() {
|
function addThemeColorCssVars() {
|
||||||
const key = '__THEME_COLOR__';
|
const key = '__THEME_COLOR__';
|
||||||
const themeColor = '#1890ff';
|
const themeColor = window.localStorage.getItem(key) || '#1890ff';
|
||||||
const cssVars = window.localStorage.getItem(key) || `--primary-color: ${themeColor}`;
|
const cssVars = `--primary-color: ${themeColor}`;
|
||||||
document.documentElement.style.cssText = cssVars;
|
document.documentElement.style.cssText = cssVars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ export interface ThemeSetting {
|
|||||||
themeColorList: string[];
|
themeColorList: string[];
|
||||||
/** 其他颜色 */
|
/** 其他颜色 */
|
||||||
otherColor: ThemeOtherColor;
|
otherColor: ThemeOtherColor;
|
||||||
|
/** 是否自定义info的颜色(默认取比主题色深一级的颜色) */
|
||||||
|
isCustomizeInfoColor: boolean;
|
||||||
/** 固定头部和多页签 */
|
/** 固定头部和多页签 */
|
||||||
fixedHeaderAndTab: boolean;
|
fixedHeaderAndTab: boolean;
|
||||||
/** 显示重载按钮 */
|
/** 显示重载按钮 */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<soybean-layout
|
<soybean-layout
|
||||||
:mode="mode"
|
:mode="mode"
|
||||||
|
:min-width="theme.layout.minWidth"
|
||||||
:fixed-header-and-tab="theme.fixedHeaderAndTab"
|
:fixed-header-and-tab="theme.fixedHeaderAndTab"
|
||||||
:header-height="theme.header.height"
|
:header-height="theme.header.height"
|
||||||
:tab-visible="theme.tab.visible"
|
:tab-visible="theme.tab.visible"
|
||||||
|
@ -5,13 +5,17 @@
|
|||||||
<color-checkbox :color="color" :checked="color === theme.themeColor" @click="theme.setThemeColor(color)" />
|
<color-checkbox :color="color" :checked="color === theme.themeColor" @click="theme.setThemeColor(color)" />
|
||||||
</n-grid-item>
|
</n-grid-item>
|
||||||
</n-grid>
|
</n-grid>
|
||||||
<n-button :block="true" :type="otherColorBtnType" class="mt-12px" @click="openModal">更多颜色</n-button>
|
<n-space :vertical="true" class="pt-12px">
|
||||||
|
<n-color-picker :value="theme.themeColor" :show-alpha="false" @update-value="theme.setThemeColor" />
|
||||||
|
<n-button :block="true" :type="otherColorBtnType" @click="openModal">更多颜色</n-button>
|
||||||
|
</n-space>
|
||||||
<color-modal :visible="visible" @close="closeModal" />
|
<color-modal :visible="visible" @close="closeModal" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { NDivider, NGrid, NGridItem, NButton } from 'naive-ui';
|
import { NDivider, NGrid, NGridItem, NSpace, NButton, NColorPicker } from 'naive-ui';
|
||||||
|
import { isInTraditionColors } from '@/settings';
|
||||||
import { useThemeStore } from '@/store';
|
import { useThemeStore } from '@/store';
|
||||||
import { useBoolean } from '@/hooks';
|
import { useBoolean } from '@/hooks';
|
||||||
import { ColorCheckbox, ColorModal } from './components';
|
import { ColorCheckbox, ColorModal } from './components';
|
||||||
@ -20,7 +24,7 @@ const theme = useThemeStore();
|
|||||||
|
|
||||||
const { bool: visible, setTrue: openModal, setFalse: closeModal } = useBoolean();
|
const { bool: visible, setTrue: openModal, setFalse: closeModal } = useBoolean();
|
||||||
|
|
||||||
const isInOther = computed(() => !theme.themeColorList.includes(theme.themeColor));
|
const isInOther = computed(() => isInTraditionColors(theme.themeColor));
|
||||||
const otherColorBtnType = computed(() => (isInOther.value ? 'primary' : 'default'));
|
const otherColorBtnType = computed(() => (isInOther.value ? 'primary' : 'default'));
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -36,6 +36,7 @@ const style = computed(() => {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.soybean-layout__main {
|
.soybean-layout__main {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
width: 100%;
|
||||||
transition-property: padding-left;
|
transition-property: padding-left;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
v-bind="commonProps"
|
v-bind="commonProps"
|
||||||
:fixed="fixedHeaderAndTab"
|
:fixed="fixedHeaderAndTab"
|
||||||
:z-index="tabZIndex"
|
:z-index="tabZIndex"
|
||||||
|
:min-width="minWidth"
|
||||||
:top="headerHeight"
|
:top="headerHeight"
|
||||||
:height="tabHeight"
|
:height="tabHeight"
|
||||||
:padding-left="siderWidth"
|
:padding-left="siderWidth"
|
||||||
@ -46,6 +47,7 @@
|
|||||||
v-bind="commonProps"
|
v-bind="commonProps"
|
||||||
:fixed="fixedFooter"
|
:fixed="fixedFooter"
|
||||||
:z-index="footerZIndex"
|
:z-index="footerZIndex"
|
||||||
|
:min-width="minWidth"
|
||||||
:height="footerHeight"
|
:height="footerHeight"
|
||||||
:padding-left="siderWidth"
|
:padding-left="siderWidth"
|
||||||
:style="footerTransform"
|
:style="footerTransform"
|
||||||
|
@ -11,3 +11,10 @@ interface TraditionColor {
|
|||||||
|
|
||||||
/** 中国传统颜色 */
|
/** 中国传统颜色 */
|
||||||
export const traditionColors = colorJson as TraditionColor[];
|
export const traditionColors = colorJson as TraditionColor[];
|
||||||
|
|
||||||
|
export function isInTraditionColors(color: string) {
|
||||||
|
return traditionColors.some(item => {
|
||||||
|
const flag = item.data.some(v => v.color === color);
|
||||||
|
return flag;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -3,28 +3,29 @@ import type { ThemeSetting } from '@/interface';
|
|||||||
|
|
||||||
const themeColorList = [
|
const themeColorList = [
|
||||||
'#1890ff',
|
'#1890ff',
|
||||||
'#007AFF',
|
|
||||||
'#2d8cf0',
|
|
||||||
'#409EFF',
|
'#409EFF',
|
||||||
'#536dfe',
|
'#2d8cf0',
|
||||||
|
'#007AFF',
|
||||||
|
'#5ac8fa',
|
||||||
'#5856D6',
|
'#5856D6',
|
||||||
|
'#536dfe',
|
||||||
|
'#9c27b0',
|
||||||
|
'#AF52DE',
|
||||||
'#0096c7',
|
'#0096c7',
|
||||||
'#00C1D4',
|
'#00C1D4',
|
||||||
'#009688',
|
|
||||||
'#5AC8FA',
|
|
||||||
'#34C759',
|
'#34C759',
|
||||||
'#71EFA3',
|
'#43a047',
|
||||||
|
'#7cb342',
|
||||||
|
'#c0ca33',
|
||||||
'#78DEC7',
|
'#78DEC7',
|
||||||
'#FC5404',
|
'#e53935',
|
||||||
'#ee4f12',
|
'#d81b60',
|
||||||
'#FF9500',
|
'#f4511e',
|
||||||
'#fadb14',
|
'#fb8c00',
|
||||||
'#FFCC00',
|
'#ffb300',
|
||||||
'#FF3B30',
|
'#fdd835',
|
||||||
'#FF2D55',
|
'#6d4c41',
|
||||||
'#ff5c93',
|
'#546e7a'
|
||||||
'#9c27b0',
|
|
||||||
'#AF52DE'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const defaultThemeSetting: ThemeSetting = {
|
const defaultThemeSetting: ThemeSetting = {
|
||||||
@ -47,6 +48,7 @@ const defaultThemeSetting: ThemeSetting = {
|
|||||||
warning: '#faad14',
|
warning: '#faad14',
|
||||||
error: '#f5222d'
|
error: '#f5222d'
|
||||||
},
|
},
|
||||||
|
isCustomizeInfoColor: false,
|
||||||
fixedHeaderAndTab: true,
|
fixedHeaderAndTab: true,
|
||||||
showReload: true,
|
showReload: true,
|
||||||
header: {
|
header: {
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
import type { GlobalThemeOverrides } from 'naive-ui';
|
import type { GlobalThemeOverrides } from 'naive-ui';
|
||||||
import { kebabCase } from 'lodash-es';
|
import { cloneDeep, kebabCase } from 'lodash-es';
|
||||||
import { getColorPalette, addColorAlpha } from '@/utils';
|
import { themeSetting } from '@/settings';
|
||||||
|
import { getThemeColor, getColorPalette, addColorAlpha } from '@/utils';
|
||||||
|
|
||||||
|
/** 获取主题配置 */
|
||||||
|
export function getThemeSettings() {
|
||||||
|
const themeColor = getThemeColor() || themeSetting.themeColor;
|
||||||
|
const info = themeSetting.isCustomizeInfoColor ? themeSetting.otherColor.info : getColorPalette(themeColor, 7);
|
||||||
|
const otherColor = { ...themeSetting.otherColor, info };
|
||||||
|
const setting = cloneDeep({ ...themeSetting, themeColor, otherColor });
|
||||||
|
return setting;
|
||||||
|
}
|
||||||
|
|
||||||
type ColorType = 'primary' | 'info' | 'success' | 'warning' | 'error';
|
type ColorType = 'primary' | 'info' | 'success' | 'warning' | 'error';
|
||||||
type ColorScene = '' | 'Suppl' | 'Hover' | 'Pressed' | 'Active';
|
type ColorScene = '' | 'Suppl' | 'Hover' | 'Pressed' | 'Active';
|
||||||
@ -38,7 +48,10 @@ function getThemeColors(colors: [ColorType, string][]) {
|
|||||||
|
|
||||||
/** 获取naive的主题颜色 */
|
/** 获取naive的主题颜色 */
|
||||||
export function getNaiveThemeOverrides(colors: Record<ColorType, string>): GlobalThemeOverrides {
|
export function getNaiveThemeOverrides(colors: Record<ColorType, string>): GlobalThemeOverrides {
|
||||||
const { primary, info, success, warning, error } = colors;
|
const { primary, success, warning, error } = colors;
|
||||||
|
|
||||||
|
const info = themeSetting.isCustomizeInfoColor ? colors.info : getColorPalette(primary, 7);
|
||||||
|
|
||||||
const themeColors = getThemeColors([
|
const themeColors = getThemeColors([
|
||||||
['primary', primary],
|
['primary', primary],
|
||||||
['info', info],
|
['info', info],
|
||||||
@ -70,7 +83,7 @@ export function addThemeCssVarsToHtml(themeVars: ThemeVars) {
|
|||||||
style.push(`--${kebabCase(key)}: ${themeVars[key]}`);
|
style.push(`--${kebabCase(key)}: ${themeVars[key]}`);
|
||||||
});
|
});
|
||||||
const styleStr = style.join(';');
|
const styleStr = style.join(';');
|
||||||
document.documentElement.style.cssText = styleStr;
|
document.documentElement.style.cssText += styleStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** windicss 暗黑模式 */
|
/** windicss 暗黑模式 */
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { darkTheme } from 'naive-ui';
|
import { darkTheme } from 'naive-ui';
|
||||||
import { cloneDeep } from 'lodash-es';
|
|
||||||
import { themeSetting } from '@/settings';
|
|
||||||
import type {
|
import type {
|
||||||
ThemeSetting,
|
ThemeSetting,
|
||||||
ThemeLayoutMode,
|
ThemeLayoutMode,
|
||||||
@ -9,12 +7,12 @@ import type {
|
|||||||
ThemeHorizontalMenuPosition,
|
ThemeHorizontalMenuPosition,
|
||||||
ThemeAnimateMode
|
ThemeAnimateMode
|
||||||
} from '@/interface';
|
} from '@/interface';
|
||||||
import { getNaiveThemeOverrides, addThemeCssVarsToHtml } from './helpers';
|
import { getThemeSettings, getNaiveThemeOverrides, addThemeCssVarsToHtml } from './helpers';
|
||||||
|
|
||||||
type ThemeState = ThemeSetting;
|
type ThemeState = ThemeSetting;
|
||||||
|
|
||||||
export const useThemeStore = defineStore('theme-store', {
|
export const useThemeStore = defineStore('theme-store', {
|
||||||
state: (): ThemeState => cloneDeep(themeSetting),
|
state: (): ThemeState => getThemeSettings(),
|
||||||
getters: {
|
getters: {
|
||||||
/** naiveUI的主题配置 */
|
/** naiveUI的主题配置 */
|
||||||
naiveThemeOverrides(state) {
|
naiveThemeOverrides(state) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { watch, onUnmounted } from 'vue';
|
import { watch, onUnmounted } from 'vue';
|
||||||
import { useOsTheme } from 'naive-ui';
|
import { useOsTheme } from 'naive-ui';
|
||||||
import { useElementSize } from '@vueuse/core';
|
import { useElementSize } from '@vueuse/core';
|
||||||
import { EnumStorageKey } from '@/enum';
|
import { setThemeColor } from '@/utils';
|
||||||
import { useThemeStore } from '../modules';
|
import { useThemeStore } from '../modules';
|
||||||
|
|
||||||
/** 订阅theme store */
|
/** 订阅theme store */
|
||||||
@ -14,7 +14,7 @@ export default function subscribeThemeStore() {
|
|||||||
const stopThemeColor = watch(
|
const stopThemeColor = watch(
|
||||||
() => theme.themeColor,
|
() => theme.themeColor,
|
||||||
newValue => {
|
newValue => {
|
||||||
window.localStorage.setItem(EnumStorageKey['theme-color'], `--primary-color: ${newValue};`);
|
setThemeColor(newValue);
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
@ -136,3 +136,11 @@ export function addColorAlpha(color: string, alpha: number) {
|
|||||||
export function mixColor(firstColor: string, secondColor: string, ratio: number) {
|
export function mixColor(firstColor: string, secondColor: string, ratio: number) {
|
||||||
return colord(firstColor).mix(secondColor, ratio).toHex();
|
return colord(firstColor).mix(secondColor, ratio).toHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否是白颜色
|
||||||
|
* @param color - 颜色
|
||||||
|
*/
|
||||||
|
export function isWhiteColor(color: string) {
|
||||||
|
return colord(color).isEqual('#ffffff');
|
||||||
|
}
|
||||||
|
@ -5,3 +5,4 @@ export * from './number';
|
|||||||
export * from './object';
|
export * from './object';
|
||||||
export * from './icon';
|
export * from './icon';
|
||||||
export * from './design-pattern';
|
export * from './design-pattern';
|
||||||
|
export * from './theme';
|
||||||
|
16
src/utils/common/theme.ts
Normal file
16
src/utils/common/theme.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { EnumStorageKey } from '@/enum';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存主题颜色
|
||||||
|
* @param color
|
||||||
|
*/
|
||||||
|
export function setThemeColor(color: string) {
|
||||||
|
window.localStorage.setItem(EnumStorageKey['theme-color'], color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取缓存的主题颜色
|
||||||
|
*/
|
||||||
|
export function getThemeColor() {
|
||||||
|
return window.localStorage.getItem(EnumStorageKey['theme-color']);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user