提交 7692ffb9 编写于 作者: V vben

feat: new menu and top bar color selection color matching

上级 bda3e5da
......@@ -4,6 +4,7 @@
- 表单项的`componentsProps`支持函数类型
- 菜单新增 tag 显示
- 新增菜单及顶栏颜色选择配色
### ⚡ Performance Improvements
......
......@@ -43,7 +43,7 @@
.app-loading .g-loading {
display: block;
width: 64px;
width: 48px;
margin: 30px auto;
-webkit-animation: load 1.2s linear infinite;
animation: load 1.2s linear infinite;
......
import type { MenuState } from './types';
import type { Menu as MenuType } from '/@/router/types';
import { computed, defineComponent, unref, reactive, toRef, watch, onMounted, ref } from 'vue';
import { computed, defineComponent, unref, reactive, watch, onMounted, ref, toRefs } from 'vue';
import { Menu } from 'ant-design-vue';
import SearchInput from './SearchInput.vue';
import MenuContent from './MenuContent';
......@@ -40,8 +40,10 @@ export default defineComponent({
});
const { currentRoute } = useRouter();
const { items, flatItems, isAppMenu, mode, accordion } = toRefs(props);
const { handleInputChange, handleInputClick } = useSearchInput({
flatMenusRef: toRef(props, 'flatItems'),
flatMenusRef: flatItems,
emit: emit,
menuState,
handleMenuChange,
......@@ -49,11 +51,11 @@ export default defineComponent({
const { handleOpenChange, resetKeys, setOpenKeys } = useOpenKeys(
menuState,
toRef(props, 'items'),
toRef(props, 'flatItems'),
toRef(props, 'isAppMenu'),
toRef(props, 'mode'),
toRef(props, 'accordion')
items,
flatItems,
isAppMenu,
mode,
accordion
);
const getOpenKeys = computed(() => {
......@@ -98,6 +100,8 @@ export default defineComponent({
return cls;
});
const showTitle = computed(() => props.collapsedShowTitle && menuStore.getCollapsedState);
watch(
() => currentRoute.value.name,
(name: string) => {
......@@ -130,9 +134,7 @@ export default defineComponent({
const { beforeClickFn } = props;
if (beforeClickFn && isFunction(beforeClickFn)) {
const flag = await beforeClickFn(menu);
if (!flag) {
return;
}
if (!flag) return;
}
const { path } = menu;
menuState.selectedKeys = [path];
......@@ -141,9 +143,7 @@ export default defineComponent({
function handleMenuChange() {
const { flatItems } = props;
if (!unref(flatItems) || flatItems.length === 0) {
return;
}
if (!unref(flatItems) || flatItems.length === 0) return;
const findMenu = flatItems.find((menu) => menu.path === unref(currentRoute).path);
if (findMenu) {
if (menuState.mode !== MenuModeEnum.HORIZONTAL) {
......@@ -155,10 +155,6 @@ export default defineComponent({
}
}
const showTitle = computed(() => {
return props.collapsedShowTitle && menuStore.getCollapsedState;
});
// render menu item
function renderMenuItem(menuList?: MenuType[], index = 1) {
if (!menuList) return;
......@@ -183,6 +179,7 @@ export default defineComponent({
<MenuContent
item={menu}
level={index}
isTop={props.isTop}
showTitle={unref(showTitle)}
searchValue={menuState.searchValue}
/>,
......@@ -198,6 +195,7 @@ export default defineComponent({
showTitle={unref(showTitle)}
item={menu}
level={index}
isTop={props.isTop}
searchValue={menuState.searchValue}
/>,
],
......
......@@ -26,6 +26,10 @@ export default defineComponent({
type: Number as PropType<number>,
default: 0,
},
isTop: {
type: Boolean as PropType<boolean>,
default: true,
},
},
setup(props) {
/**
......@@ -56,14 +60,16 @@ export default defineComponent({
if (!props.item) {
return null;
}
const { showTitle } = props;
const { showTitle, isTop } = props;
const { name, icon } = props.item;
const searchValue = props.searchValue || '';
const index = name.indexOf(searchValue);
const beforeStr = name.substr(0, index);
const afterStr = name.substr(index + searchValue.length);
const cls = showTitle ? 'show-title' : 'basic-menu__name';
let cls = showTitle ? ['show-title'] : ['basic-menu__name'];
isTop && !showTitle && (cls = []);
return (
<>
{renderIcon(icon!)}
......
......@@ -102,7 +102,7 @@
.set-bg() {
color: #fff;
background: @input-dark-bg-color;
background: @sider-dark-lighten-1-bg-color;
border: 0;
outline: none;
}
......
......@@ -52,10 +52,11 @@
// collapsed show title end
.ant-menu-submenu-title {
> .basic-menu__name {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
.basic-menu__tag {
float: right;
margin-top: @app-menu-item-height / 2;
transform: translate(0%, -50%);
}
}
}
......@@ -254,7 +255,7 @@
// 层级样式
&.ant-menu-dark:not(.basic-menu__sidebar-hor) {
overflow-x: hidden;
background: @menu-item-dark-bg-color;
background: @sider-dark-bg-color;
.active-menu-style();
.ant-menu-item.ant-menu-item-selected.basic-menu-menu-item__level1,
......@@ -263,21 +264,20 @@
}
.basic-menu-item__level1 {
background-color: @menu-item-dark-bg-color;
background-color: @sider-dark-bg-color;
> .ant-menu-sub > li {
background-color: lighten(@menu-item-dark-bg-color, 6%);
background-color: @sider-dark-lighten-1-bg-color;
}
}
.basic-menu-item__level2:not(.ant-menu-item-selected),
.ant-menu-sub {
background-color: lighten(@menu-item-dark-bg-color, 6%);
// background-color: @sub-menu-item-dark-bg-color;
background-color: @sider-dark-lighten-1-bg-color;
}
.basic-menu-item__level3:not(.ant-menu-item-selected) {
background-color: lighten(@menu-item-dark-bg-color, 10%);
background-color: @sider-dark-lighten-2-bg-color;
}
.ant-menu-submenu-title {
......@@ -290,7 +290,7 @@
&.ant-menu-inline-collapsed {
.ant-menu-submenu-selected,
.ant-menu-item-selected {
background: darken(@menu-item-dark-bg-color, 6%) !important;
background: @sider-dark-darken-bg-color !important;
}
}
}
......@@ -359,7 +359,7 @@
.ant-menu-dark {
&.ant-menu-submenu-popup {
> ul {
background: @menu-item-dark-bg-color;
background: @sider-dark-bg-color;
}
.active-menu-style();
......
:root {
// header
--header-bg-color: #394664;
--header-bg-hover-color: #273352;
--header-active-menu-bg-color: #273352;
// sider
--sider-dark-bg-color: #273352;
--sider-dark-darken-bg-color: #273352;
--sider-dark-lighten-1-bg-color: #273352;
--sider-dark-lighten-2-bg-color: #273352;
--sider-dark-lighten-3-bg-color: #273352;
}
@white: #fff;
@info-color: @primary-color;
......@@ -53,21 +67,24 @@
// ==============Header=============
// =================================
@header-dark-bg-color: #394664;
@header-dark-bg-hover-color: #273352;
@header-dark-bg-color: var(--header-bg-color);
@header-dark-bg-hover-color: var(--header-bg-hover-color);
@header-light-bg-hover-color: #f6f6f6;
@header-light-desc-color: #7c8087;
@header-light-bottom-border-color: #eee;
// top-menu
@top-menu-active-bg-color: var(--header-active-menu-bg-color);
// =================================
// ==============Menu============
// =================================
// let -menu
@menu-item-dark-bg-color: #273352;
// top-menu
@top-menu-active-bg-color: #273352;
@sider-dark-bg-color: var(--sider-dark-bg-color);
@sider-dark-darken-bg-color: var(--sider-dark-darken-bg-color);
@sider-dark-lighten-1-bg-color: var(--sider-dark-lighten-1-bg-color);
@sider-dark-lighten-2-bg-color: var(--sider-dark-lighten-2-bg-color);
@sider-dark-lighten-3-bg-color: var(--sider-dark-lighten-3-bg-color);
// trigger
@trigger-dark-hover-bg-color: rgba(255, 255, 255, 0.2);
......
......@@ -79,9 +79,8 @@ export default defineComponent({
});
const showHeaderTrigger = computed(() => {
const { show, trigger, hidden } = unref(getProjectConfigRef).menuSetting;
if (!show || !hidden) return false;
const { show, trigger, hidden, type } = unref(getProjectConfigRef).menuSetting;
if (type === MenuTypeEnum.TOP_MENU || !show || !hidden) return false;
return trigger === TriggerEnum.HEADER;
});
......
......@@ -41,7 +41,7 @@
background-size: 100% 100%;
&.ant-layout-sider-dark {
background: @menu-item-dark-bg-color;
background: @sider-dark-bg-color;
}
&:not(.ant-layout-sider-dark) {
......
......@@ -25,13 +25,9 @@ export default defineComponent({
const { getFullContent } = useFullContent();
const getProjectConfigRef = computed(() => {
return appStore.getProjectConfig;
});
const getProjectConfigRef = computed(() => appStore.getProjectConfig);
const getLockMainScrollStateRef = computed(() => {
return appStore.getLockMainScrollState;
});
const getLockMainScrollStateRef = computed(() => appStore.getLockMainScrollState);
const showHeaderRef = computed(() => {
const {
......@@ -47,6 +43,12 @@ export default defineComponent({
return type !== MenuTypeEnum.SIDEBAR && unref(showHeaderRef);
});
const getIsLockRef = computed(() => {
const { getLockInfo } = appStore;
const { isLock } = getLockInfo;
return isLock;
});
const showSideBarRef = computed(() => {
const {
menuSetting: { show, mode, split },
......@@ -54,59 +56,74 @@ export default defineComponent({
return split || (show && mode !== MenuModeEnum.HORIZONTAL && !unref(getFullContent));
});
function getTarget(): any {
const {
headerSetting: { fixed },
} = unref(getProjectConfigRef);
return document.querySelector(`.default-layout__${fixed ? 'main' : 'content'}`);
}
const showFullHeaderRef = computed(() => {
return !unref(getFullContent) && unref(isShowMixHeaderRef) && unref(showHeaderRef);
});
return () => {
const { getLockInfo } = appStore;
const showInsetHeaderRef = computed(() => {
return !unref(getFullContent) && !unref(isShowMixHeaderRef) && unref(showHeaderRef);
});
const fixedHeaderClsRef = computed(() => {
const {
useOpenBackTop,
showSettingButton,
multiTabsSetting: { show: showTabs },
headerSetting: { fixed },
menuSetting: { split, hidden },
} = unref(getProjectConfigRef);
const fixedHeaderCls = fixed
? 'fixed' + (unref(getLockMainScrollStateRef) ? ' lock' : '')
: '';
return fixedHeaderCls;
});
const { isLock } = getLockInfo;
const showTabsRef = computed(() => {
const {
multiTabsSetting: { show },
} = unref(getProjectConfigRef);
return show && !unref(getFullContent);
});
const showClassSideBarRef = computed(() => {
const {
menuSetting: { split, hidden },
} = unref(getProjectConfigRef);
return split ? hidden : true;
});
const showSideBar = split ? hidden : true;
function getTarget(): any {
const {
headerSetting: { fixed },
} = unref(getProjectConfigRef);
return document.querySelector(`.default-layout__${fixed ? 'main' : 'content'}`);
}
return () => {
const { useOpenBackTop, showSettingButton } = unref(getProjectConfigRef);
return (
<Layout class="default-layout relative">
{() => (
<>
{/* lock page */}
{isLock && <LockPage />}
{unref(getIsLockRef) && <LockPage />}
{/* back top */}
{useOpenBackTop && <BackTop target={getTarget} />}
{/* open setting drawer */}
{showSettingButton && <SettingBtn />}
{!unref(getFullContent) && unref(isShowMixHeaderRef) && unref(showHeaderRef) && (
<LayoutHeader />
)}
{unref(showFullHeaderRef) && <LayoutHeader />}
<Layout>
{() => (
<>
{unref(showSideBarRef) && <LayoutSideBar class={showSideBar ? '' : 'hidden'} />}
<Layout class={[`default-layout__content`, fixedHeaderCls]}>
{unref(showSideBarRef) && (
<LayoutSideBar class={unref(showClassSideBarRef) ? '' : 'hidden'} />
)}
<Layout class={[`default-layout__content`, unref(fixedHeaderClsRef)]}>
{() => (
<>
{!unref(getFullContent) &&
!unref(isShowMixHeaderRef) &&
unref(showHeaderRef) && <LayoutHeader />}
{unref(showInsetHeaderRef) && <LayoutHeader />}
{showTabs && !unref(getFullContent) && <MultipleTabs />}
{unref(showTabsRef) && <MultipleTabs />}
<LayoutContent class={fixedHeaderCls} />
<LayoutContent class={unref(fixedHeaderClsRef)} />
</>
)}
</Layout>
......
......@@ -20,12 +20,12 @@ import { updateColorWeak, updateGrayMode } from '/@/setup/theme';
import { baseHandler } from './handler';
import {
HandlerEnum,
themeOptions,
contentModeOptions,
topMenuAlignOptions,
menuTriggerOptions,
routerTransitionOptions,
} from './const';
import { HEADER_PRESET_BG_COLOR_LIST, SIDE_BAR_BG_COLOR_LIST } from '/@/settings/colorSetting';
interface SwitchOptions {
config?: DeepPartial<ProjectConfig>;
......@@ -41,6 +41,11 @@ interface SelectConfig {
handler?: Fn;
}
interface ThemeOptions {
def?: string;
handler?: Fn;
}
export default defineComponent({
name: 'SettingDrawer',
setup(_, { attrs }) {
......@@ -98,8 +103,7 @@ export default defineComponent({
function renderSidebar() {
const {
headerSetting: { theme: headerTheme },
menuSetting: { type, theme: menuTheme, split },
menuSetting: { type, split },
} = unref(getProjectConfigRef);
const typeList = ref([
......@@ -154,22 +158,22 @@ export default defineComponent({
def: split,
disabled: !unref(getShowMenuRef) || type !== MenuTypeEnum.MIX,
}),
renderSelectItem('顶栏主题', {
handler: (e) => {
baseHandler(HandlerEnum.HEADER_THEME, e);
},
def: headerTheme,
options: themeOptions,
disabled: !unref(getShowHeaderRef),
}),
renderSelectItem('菜单主题', {
handler: (e) => {
baseHandler(HandlerEnum.MENU_THEME, e);
},
def: menuTheme,
options: themeOptions,
disabled: !unref(getShowMenuRef),
}),
// renderSelectItem('顶栏主题', {
// handler: (e) => {
// baseHandler(HandlerEnum.HEADER_THEME, e);
// },
// def: headerTheme,
// options: themeOptions,
// disabled: !unref(getShowHeaderRef),
// }),
// renderSelectItem('菜单主题', {
// handler: (e) => {
// baseHandler(HandlerEnum.MENU_THEME, e);
// },
// def: menuTheme,
// options: themeOptions,
// disabled: !unref(getShowMenuRef),
// }),
];
}
/**
......@@ -413,7 +417,6 @@ export default defineComponent({
return (
<div class={`setting-drawer__cell-item`}>
<span>{text}</span>
{/* @ts-ignore */}
<Select
{...opt}
disabled={disabled}
......@@ -447,6 +450,50 @@ export default defineComponent({
);
}
function renderTheme() {
const { headerBgColor, menuBgColor } = unref(getProjectConfigRef);
return (
<>
<Divider>{() => '顶栏主题'}</Divider>
{renderThemeItem(HEADER_PRESET_BG_COLOR_LIST, {
def: headerBgColor,
handler: (e) => {
baseHandler(HandlerEnum.HEADER_THEME, e);
},
})}
<Divider>{() => '菜单主题'}</Divider>
{renderThemeItem(SIDE_BAR_BG_COLOR_LIST, {
def: menuBgColor,
handler: (e) => {
baseHandler(HandlerEnum.MENU_THEME, e);
},
})}
</>
);
}
function renderThemeItem(colorList: string[], opt: ThemeOptions) {
const { def, handler } = opt;
return (
<div class={`setting-drawer__theme-item`}>
{colorList.map((item) => {
return (
<span
onClick={() => handler && handler(item)}
key={item}
class={[def === item ? 'active' : '']}
style={{
background: item,
}}
>
<CheckOutlined class="icon" />
</span>
);
})}
</div>
);
}
return () => (
<BasicDrawer {...attrs} title="项目配置" width={300} wrapClassName="setting-drawer">
{{
......@@ -454,6 +501,9 @@ export default defineComponent({
<>
<Divider>{() => '导航栏模式'}</Divider>
{renderSidebar()}
{renderTheme()}
<Divider>{() => '界面功能'}</Divider>
{renderFeatures()}
<Divider>{() => '界面显示'}</Divider>
......
import { HandlerEnum } from './const';
import { MenuThemeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
import { updateColorWeak, updateGrayMode } from '/@/setup/theme';
// import { MenuThemeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
import {
updateColorWeak,
updateGrayMode,
updateHeaderBgColor,
updateSidebarBgColor,
} from '/@/setup/theme';
import { appStore } from '/@/store/modules/app';
import { ProjectConfig } from '/@/types/config';
......@@ -14,12 +19,12 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
case HandlerEnum.CHANGE_LAYOUT:
const { mode, type, split } = value;
const splitOpt = split === undefined ? { split } : {};
let headerSetting = {};
if (type === MenuTypeEnum.TOP_MENU) {
headerSetting = {
theme: MenuThemeEnum.DARK,
};
}
// let headerSetting = {};
// if (type === MenuTypeEnum.TOP_MENU) {
// headerSetting = {
// theme: MenuThemeEnum.DARK,
// };
// }
return {
menuSetting: {
mode,
......@@ -28,7 +33,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
show: true,
...splitOpt,
},
headerSetting,
// headerSetting,
};
case HandlerEnum.MENU_HAS_DRAG:
......@@ -81,10 +86,12 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
},
};
case HandlerEnum.MENU_THEME:
updateSidebarBgColor(value);
return {
menuSetting: {
theme: value,
},
menuBgColor: value,
// menuSetting: {
// theme: value,
// },
};
case HandlerEnum.MENU_SPLIT:
return {
......@@ -150,7 +157,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
showQuick: value,
},
};
case HandlerEnum.TABS_SHOW_QUICK:
case HandlerEnum.TABS_SHOW_ICON:
return {
multiTabsSetting: {
showIcon: value,
......@@ -163,10 +170,9 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
},
};
case HandlerEnum.HEADER_THEME:
updateHeaderBgColor(value);
return {
headerSetting: {
theme: value,
},
headerBgColor: value,
};
case HandlerEnum.HEADER_FIXED:
return {
......
......@@ -20,25 +20,26 @@
display: flex;
flex-wrap: wrap;
margin: 16px 0;
justify-content: space-around;
span {
display: inline-block;
> span {
width: 20px;
height: 20px;
margin-top: 10px;
margin-right: 10px;
cursor: pointer;
border-radius: 4px;
border: 1px solid #ddd;
border-radius: 2px;
svg {
display: none;
}
&.active {
border: 1px solid lighten(@primary-color, 10%);
svg {
display: inline-block;
margin-left: 4px;
font-size: 0.8em;
margin: 0 0 3px 3px;
font-size: 12px;
fill: @white;
}
}
......
......@@ -41,13 +41,12 @@ export default defineComponent({
// No longer show animations that are already in the tab
const name = route.meta.inTab ? 'fade' : null;
// TODO add key?
const Content = openCache ? (
<KeepAlive max={max} include={cacheTabs}>
<Component key={route.path} />
<Component key={route.fullPath} />
</KeepAlive>
) : (
<Component key={route.path} />
<Component key={route.fullPath} />
);
return openRouterTransition ? (
<Transition
......
......@@ -3,7 +3,7 @@ import type { App } from 'vue';
import { createRouter, createWebHashHistory } from 'vue-router';
import { scrollWaiter } from '../utils/scrollWaiter';
import { scrollWaiter } from './scrollWaiter';
import { createGuard } from './guard/';
......@@ -13,6 +13,7 @@ import { basicRoutes } from './routes/';
const router = createRouter({
history: createWebHashHistory(),
routes: basicRoutes as RouteRecordRaw[],
strict: true,
scrollBehavior: async (to, from, savedPosition) => {
await scrollWaiter.wait();
if (savedPosition) {
......
// see https://github.com/vuejs/vue-router-next/blob/master/playground/scrollWaiter.ts
class ScrollQueue {
private resolve: (() => void) | null = null;
private promise: Promise<any> | null = null;
......
// header preset color
export const HEADER_PRESET_BG_COLOR_LIST: string[] = [
'#ffffff',
'#009688',
'#18bc9c',
'#1E9FFF',
'#018ffb',
'#409eff',
'#4e73df',
'#e74c3c',
'#f39c12',
'#394664',
'#001529',
];
// sider preset color
export const SIDE_BAR_BG_COLOR_LIST: string[] = [
'#273352',
'#ffffff',
'#001529',
'#304156',
'#28333E',
'#344058',
];
......@@ -7,6 +7,16 @@ import { isProdMode } from '/@/utils/env';
// ! You need to clear the browser cache after the change
const setting: ProjectConfig = {
// color
// TODO 主题色
themeColor: primaryColor,
// header bg color
headerBgColor: '#ffffff',
// sidebar menu bg color
menuBgColor: '#273352',
// Whether to show the configuration button
showSettingButton: true,
// 权限模式
......@@ -15,8 +25,7 @@ const setting: ProjectConfig = {
grayMode: false,
// 色弱模式
colorWeak: false,
// 主题色
themeColor: primaryColor,
// 是否取消菜单,顶部,多标签页显示, 用于可能内嵌在别的系统内
fullContent: false,
// content mode
......
import useCssVar from '/@/hooks/web/useCssVar';
import { isHexColor, colorIsDark, lighten, darken } from '/@/utils/color';
import { appStore } from '/@/store/modules/app';
import { MenuThemeEnum } from '/@/enums/menuEnum';
const HEADER_BG_COLOR_VAR = '--header-bg-color';
const HEADER_BG_HOVER_COLOR_VAR = '--header-bg-hover-color';
const HEADER_MENU_ACTIVE_BG_COLOR_VAR = '--header-active-menu-bg-color';
const SIDER_DARK_BG_COLOR = '--sider-dark-bg-color';
const SIDER_DARK_DARKEN_BG_COLOR = '--sider-dark-darken-bg-color';
const SIDER_LIGHTEN_1_BG_COLOR = '--sider-dark-lighten-1-bg-color';
const SIDER_LIGHTEN_2_BG_COLOR = '--sider-dark-lighten-2-bg-color';
function toggleClass(flag: boolean, clsName: string) {
const body = document.body;
let { className } = body;
className = className.replace(clsName, '');
document.body.className = flag ? `${className} ${clsName} ` : className;
}
export const updateColorWeak = (colorWeak: boolean) => {
toggleClass(colorWeak, 'color-weak');
};
......@@ -11,3 +26,46 @@ export const updateColorWeak = (colorWeak: boolean) => {
export const updateGrayMode = (gray: boolean) => {
toggleClass(gray, 'gray-mode');
};
export function updateHeaderBgColor(color: string) {
if (!isHexColor(color)) return;
const bgColorRef = useCssVar(HEADER_BG_COLOR_VAR);
const bgHoverColorRef = useCssVar(HEADER_BG_HOVER_COLOR_VAR);
const topMenuActiveBgColorRef = useCssVar(HEADER_MENU_ACTIVE_BG_COLOR_VAR);
// bg color
bgColorRef.value = color;
// hover color
const hoverColor = lighten(color, 6);
bgHoverColorRef.value = hoverColor;
topMenuActiveBgColorRef.value = hoverColor;
const isDark = colorIsDark(color);
appStore.commitProjectConfigState({
headerSetting: {
theme: isDark ? MenuThemeEnum.DARK : MenuThemeEnum.LIGHT,
},
});
}
export function updateSidebarBgColor(color: string) {
if (!isHexColor(color)) return;
const siderBgColor = useCssVar(SIDER_DARK_BG_COLOR);
const darkenBgColor = useCssVar(SIDER_DARK_DARKEN_BG_COLOR);
const lighten1Color = useCssVar(SIDER_LIGHTEN_1_BG_COLOR);
const lighten2Color = useCssVar(SIDER_LIGHTEN_2_BG_COLOR);
siderBgColor.value = color;
darkenBgColor.value = darken(color, 6);
lighten1Color.value = lighten(color, 4);
lighten2Color.value = lighten(color, 8);
// only #ffffff is light
const isLight = ['#fff', '#ffffff'].includes(color.toLowerCase());
appStore.commitProjectConfigState({
menuSetting: {
theme: isLight ? MenuThemeEnum.LIGHT : MenuThemeEnum.DARK,
},
});
}
......@@ -55,6 +55,10 @@ export interface HeaderSetting {
showNotice: boolean;
}
export interface ProjectConfig {
// header背景色
headerBgColor: string;
// 左侧菜单背景色
menuBgColor: string;
// 是否显示配置按钮
showSettingButton: boolean;
// 权限模式
......
......@@ -9,7 +9,12 @@ import { PROJ_CFG_KEY } from '/@/enums/cacheEnum';
import projectSetting from '/@/settings/projectSetting';
import { getLocal } from '/@/utils/helper/persistent';
import { isUnDef, isNull } from '/@/utils/is';
import { updateGrayMode, updateColorWeak } from '/@/setup/theme';
import {
updateGrayMode,
updateColorWeak,
updateHeaderBgColor,
updateSidebarBgColor,
} from '/@/setup/theme';
import { appStore } from '/@/store/modules/app';
import { useNetWork } from '/@/hooks/web/useNetWork';
......@@ -48,7 +53,7 @@ export function useInitAppConfigStore() {
if (!projCfg) {
projCfg = projectSetting;
}
const { colorWeak, grayMode } = projCfg;
const { colorWeak, grayMode, headerBgColor, menuBgColor } = projCfg;
try {
// if (
// themeColor !== primaryColor &&
......@@ -57,6 +62,8 @@ export function useInitAppConfigStore() {
// ) {
// updateTheme(themeColor);
// }
headerBgColor && updateHeaderBgColor(headerBgColor);
menuBgColor && updateSidebarBgColor(menuBgColor);
grayMode && updateGrayMode(grayMode);
colorWeak && updateColorWeak(colorWeak);
} catch (error) {
......
......@@ -31,13 +31,31 @@ export const rgbToHex = function (r: number, g: number, b: number) {
* @returns The RGB representation of the passed color
*/
export const hexToRGB = function (hex: string) {
return (
parseInt(hex.substring(0, 2), 16) +
',' +
parseInt(hex.substring(2, 4), 16) +
',' +
parseInt(hex.substring(4, 6), 16)
);
let sHex = hex.toLowerCase();
if (isHexColor(hex)) {
if (sHex.length === 4) {
let sColorNew = '#';
for (let i = 1; i < 4; i += 1) {
sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1));
}
sHex = sColorNew;
}
const sColorChange = [];
for (let i = 1; i < 7; i += 2) {
sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2)));
}
return 'RGB(' + sColorChange.join(',') + ')';
}
return sHex;
};
export const colorIsDark = (color: string) => {
if (!isHexColor(color)) return;
const [r, g, b] = hexToRGB(color)
.replace(/(?:\(|\)|rgb|RGB)*/g, '')
.split(',')
.map((item) => Number(item));
return r * 0.299 + g * 0.578 + b * 0.114 < 192;
};
/**
......@@ -89,7 +107,7 @@ const addLight = (color: string, amount: number) => {
* @param {number} g green
* @param {number} b blue
*/
const luminanace = (r: stri, g: number, b: number) => {
const luminanace = (r: number, g: number, b: number) => {
const a = [r, g, b].map((v) => {
v /= 255;
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
......@@ -103,7 +121,7 @@ const luminanace = (r: stri, g: number, b: number) => {
* @param {string} rgb2 rgb color 2
*/
const contrast = (rgb1: string[], rgb2: number[]) =>
(luminanace(rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) /
(luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) /
(luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05);
/**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册