style: side menu style

This commit is contained in:
jialin
2025-06-23 15:13:49 +08:00
parent 6be7140a47
commit fd3d7a6f29
13 changed files with 169 additions and 127 deletions
+21 -7
View File
@@ -5,13 +5,17 @@ export default [
name: 'dashboard', name: 'dashboard',
path: '/dashboard', path: '/dashboard',
key: 'dashboard', key: 'dashboard',
icon: 'AppstoreOutlined', icon: 'icon-dashboard',
selectedIcon: 'icon-dashboard-filled',
defaultIcon: 'icon-dashboard',
access: 'canSeeAdmin', access: 'canSeeAdmin',
component: './dashboard' component: './dashboard'
}, },
{ {
name: 'playground', name: 'playground',
icon: 'ExperimentOutlined', icon: 'icon-experiment',
selectedIcon: 'icon-experiment-filled',
defaultIcon: 'icon-experiment',
path: '/playground', path: '/playground',
key: 'playground', key: 'playground',
routes: [ routes: [
@@ -65,7 +69,9 @@ export default [
name: 'modelCatalog', name: 'modelCatalog',
path: '/models/catalog', path: '/models/catalog',
key: 'modelsCatalog', key: 'modelsCatalog',
icon: 'icon-catalog', icon: 'icon-layers',
selectedIcon: 'icon-layers-filled',
defaultIcon: 'icon-layers',
access: 'canSeeAdmin', access: 'canSeeAdmin',
component: './llmodels/catalog' component: './llmodels/catalog'
}, },
@@ -73,7 +79,9 @@ export default [
name: 'models', name: 'models',
path: '/models/list', path: '/models/list',
key: 'models', key: 'models',
icon: 'Block', icon: 'icon-model',
selectedIcon: 'icon-model-filled',
defaultIcon: 'icon-model',
access: 'canSeeAdmin', access: 'canSeeAdmin',
component: './llmodels/index' component: './llmodels/index'
}, },
@@ -81,7 +89,9 @@ export default [
name: 'resources', name: 'resources',
path: '/resources', path: '/resources',
key: 'resources', key: 'resources',
icon: 'CloudServer', icon: 'icon-resources',
selectedIcon: 'icon-resources-filled',
defaultIcon: 'icon-resources',
access: 'canSeeAdmin', access: 'canSeeAdmin',
component: './resources' component: './resources'
}, },
@@ -89,14 +99,18 @@ export default [
name: 'apikeys', name: 'apikeys',
path: '/api-keys', path: '/api-keys',
key: 'apikeys', key: 'apikeys',
icon: 'KeyOutlined', selectedIcon: 'icon-key-filled',
icon: 'icon-key',
defaultIcon: 'icon-key',
component: './api-keys' component: './api-keys'
}, },
{ {
name: 'users', name: 'users',
path: '/users', path: '/users',
key: 'users', key: 'users',
icon: 'Team', icon: 'icon-users',
selectedIcon: 'icon-users-filled',
defaultIcon: 'icon-users',
access: 'canSeeAdmin', access: 'canSeeAdmin',
component: './users' component: './users'
}, },
+4
View File
@@ -204,6 +204,10 @@
font-size: 20px; font-size: 20px;
} }
.font-size-18 {
font-size: 18px;
}
.font-size-24 { .font-size-24 {
font-size: 24px; font-size: 24px;
} }
+1 -1
View File
@@ -2,7 +2,7 @@ import { createFromIconfontCN } from '@ant-design/icons';
// import './iconfont/iconfont.js'; // import './iconfont/iconfont.js';
const IconFont = createFromIconfontCN({ const IconFont = createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/c/font_4613488_njee9tsv0mp.js' scriptUrl: '//at.alicdn.com/t/c/font_4613488_w50kuuord8o.js'
}); });
export default IconFont; export default IconFont;
+1 -1
View File
@@ -33,7 +33,7 @@ export default {
iconMarginInlineEnd: 12, iconMarginInlineEnd: 12,
itemBorderRadius: 4, itemBorderRadius: 4,
itemSelectedColor: '#007BFF', itemSelectedColor: '#007BFF',
itemHeight: 44, itemHeight: 36,
groupTitleColor: 'rgba(0,0,0,1)', groupTitleColor: 'rgba(0,0,0,1)',
itemHoverColor: 'rgba(0,0,0,1)', itemHoverColor: 'rgba(0,0,0,1)',
itemColor: 'rgba(0,0,0,1)', itemColor: 'rgba(0,0,0,1)',
+9 -8
View File
@@ -313,19 +313,20 @@ body {
.ant-menu { .ant-menu {
.ant-menu-item { .ant-menu-item {
color: var(--ant-color-text) !important; // color: var(--ant-color-text) !important;
&:active { &:active {
background-color: var(--ant-menu-item-selected-bg); // background-color: var(--ant-menu-item-selected-bg);
} }
} }
.ant-menu-item:not(.ant-menu-item-selected) { .ant-menu-item:not(.ant-menu-item-selected) {
color: var(--ant-color-text); // color: var(--ant-color-text);
} }
.ant-menu-item.ant-menu-item-selected { .ant-menu-item.ant-menu-item-selected {
color: var(--ant-color-primary) !important; // color: var(--ant-color-primary) !important;
font-weight: 400;
} }
} }
} }
@@ -368,7 +369,7 @@ body {
.ant-menu { .ant-menu {
.ant-menu-submenu-title { .ant-menu-submenu-title {
color: var(--ant-color-text) !important; // color: var(--ant-color-text) !important;
} }
} }
@@ -376,7 +377,7 @@ body {
.user-avatar.ant-menu-submenu { .user-avatar.ant-menu-submenu {
.ant-menu-submenu-title { .ant-menu-submenu-title {
padding-left: 10px; padding-left: 10px;
color: var(--ant-color-text) !important; // color: var(--ant-color-text) !important;
} }
} }
@@ -385,7 +386,7 @@ body {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
color: var(--ant-color-text) !important; // color: var(--ant-color-text) !important;
padding-inline: unset !important; padding-inline: unset !important;
width: 100%; width: 100%;
margin-inline: 0 !important; margin-inline: 0 !important;
@@ -412,7 +413,7 @@ body {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
color: var(--ant-color-text) !important; // color: var(--ant-color-text) !important;
} }
} }
+110 -94
View File
@@ -3,6 +3,7 @@
import { routeCacheAtom, setRouteCache } from '@/atoms/route-cache'; import { routeCacheAtom, setRouteCache } from '@/atoms/route-cache';
import { GPUStackVersionAtom, UpdateCheckAtom, userAtom } from '@/atoms/user'; import { GPUStackVersionAtom, UpdateCheckAtom, userAtom } from '@/atoms/user';
import DarkMask from '@/components/dark-mask'; import DarkMask from '@/components/dark-mask';
import IconFont from '@/components/icon-font';
import ShortCuts, { import ShortCuts, {
modalConfig as ShortCutsConfig modalConfig as ShortCutsConfig
} from '@/components/short-cuts'; } from '@/components/short-cuts';
@@ -14,7 +15,6 @@ import useUserSettings from '@/hooks/use-user-settings';
import { logout } from '@/pages/login/apis'; import { logout } from '@/pages/login/apis';
import { useAccessMarkedRoutes } from '@@/plugin-access'; import { useAccessMarkedRoutes } from '@@/plugin-access';
import { useModel } from '@@/plugin-model'; import { useModel } from '@@/plugin-model';
import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';
import { ProLayout } from '@ant-design/pro-components'; import { ProLayout } from '@ant-design/pro-components';
import { import {
Link, Link,
@@ -32,7 +32,7 @@ import { Button, ConfigProvider, Modal, theme } from 'antd';
import 'driver.js/dist/driver.css'; import 'driver.js/dist/driver.css';
import { useAtom } from 'jotai'; import { useAtom } from 'jotai';
import 'overlayscrollbars/overlayscrollbars.css'; import 'overlayscrollbars/overlayscrollbars.css';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import Exception from './Exception'; import Exception from './Exception';
import './Layout.css'; import './Layout.css';
import { LogoIcon, SLogoIcon } from './Logo'; import { LogoIcon, SLogoIcon } from './Logo';
@@ -256,53 +256,51 @@ export default (props: any) => {
return () => clearTimeout(timeout); return () => clearTimeout(timeout);
}, [initializeMenu, matchedRoute, location]); }, [initializeMenu, matchedRoute, location]);
const renderMenuHeader = useCallback( const renderMenuHeader = (logo, title) => {
(logo, title) => { return (
return ( <>
<> {logo}
{logo} <div className="collapse-wrap" onClick={handleToggleCollapse}>
<div className="collapse-wrap" onClick={handleToggleCollapse}> <Button
<Button style={{ marginRight: collapsed ? 0 : -14 }}
style={{ marginRight: collapsed ? 0 : -14 }} size="small"
size="small" type={collapsed ? 'default' : 'text'}
type={collapsed ? 'default' : 'text'} >
> <>
<> <IconFont
<MenuUnfoldOutlined type="icon-expand-left"
style={{ display: collapsed ? 'block' : 'none' }} className="font-size-18 text-secondary"
/> style={{ display: collapsed ? 'block' : 'none' }}
<MenuFoldOutlined />
style={{ display: !collapsed ? 'block' : 'none' }} <IconFont
/> type="icon-expand-right"
</> className="font-size-18 text-secondary"
</Button> style={{ display: !collapsed ? 'block' : 'none' }}
</div> />
</> </>
); </Button>
}, </div>
[collapsed] </>
); );
};
const actionRender = useCallback( const actionRender = (layoutProps) => {
(layoutProps) => { const dom = getRightRenderContent({
const dom = getRightRenderContent({ runtimeConfig,
runtimeConfig, loading,
loading, initialState,
initialState, setInitialState,
setInitialState, intl,
intl, isDarkTheme: userSettings.isDarkTheme,
isDarkTheme: userSettings.isDarkTheme, siderWidth: layoutProps.siderWidth,
siderWidth: layoutProps.siderWidth, collapsed: layoutProps.collapsed,
collapsed: layoutProps.collapsed, showUpgrade
showUpgrade });
});
return dom; return dom;
}, };
[intl, showUpgrade, userSettings.theme, userSettings.isDarkTheme]
);
const itemRender = useCallback((route, _, routes) => { const itemRender = (route, _, routes) => {
const { breadcrumbName, title, path } = route; const { breadcrumbName, title, path } = route;
const label = title || breadcrumbName; const label = title || breadcrumbName;
const last = routes[routes.length - 1]; const last = routes[routes.length - 1];
@@ -312,63 +310,81 @@ export default (props: any) => {
} }
} }
return <Link to={path}>{label}</Link>; return <Link to={path}>{label}</Link>;
}, []); };
const menuItemRender = useCallback( const menuItemRender = (menuItemProps, defaultDom) => {
(menuItemProps, defaultDom) => { if (menuItemProps.isUrl || menuItemProps.children) {
if (menuItemProps.isUrl || menuItemProps.children) { return defaultDom;
return defaultDom; }
} if (menuItemProps.path && location.pathname !== menuItemProps.path) {
if (menuItemProps.path && location.pathname !== menuItemProps.path) { return (
return ( <Link
<Link to={menuItemProps.path.replace('/*', '')}
to={menuItemProps.path.replace('/*', '')} target={menuItemProps.target}
target={menuItemProps.target} >
> {defaultDom}
{defaultDom} </Link>
</Link> );
}
return <>{defaultDom}</>;
};
const menuDataRender = (menuData) => {
const currentItem = menuData.find((s) => location.pathname === s.path);
return menuData.map((item) => {
const newItem = { ...item };
const selected =
location.pathname === newItem.path ||
location.pathname.indexOf(newItem.path) > -1;
if (newItem.icon) {
newItem.icon = selected ? (
<IconFont type={newItem.selectedIcon} />
) : (
<IconFont type={newItem.defaultIcon} />
); );
} }
return <>{defaultDom}</>; if (newItem.children) {
}, newItem.children = menuDataRender(newItem.children);
[location.pathname]
);
const onPageChange = useCallback( if (selected) {
(route) => { newItem.icon = <IconFont type={newItem.selectedIcon} />;
const { location } = history; }
const { pathname } = location;
initRouteCacheValue(pathname);
dropRouteCache(pathname);
// if user is not change password, redirect to change password page
if (
location.pathname !== loginPath &&
userInfo?.require_password_change
) {
history.push(loginPath);
return;
} }
return newItem;
});
};
// if user is not logged in, redirect to login page const onPageChange = (route) => {
if (!initialState?.currentUser && location.pathname !== loginPath) { const { location } = history;
history.push(loginPath); const { pathname } = location;
} else if (location.pathname === '/') {
const pathname = initialState?.currentUser?.is_admin
? '/dashboard'
: '/playground';
history.push(pathname);
}
},
[userInfo?.require_password_change, initialState?.currentUser]
);
const onMenuHeaderClick = useCallback((e) => { initRouteCacheValue(pathname);
dropRouteCache(pathname);
// if user is not change password, redirect to change password page
if (location.pathname !== loginPath && userInfo?.require_password_change) {
history.push(loginPath);
return;
}
// if user is not logged in, redirect to login page
if (!initialState?.currentUser && location.pathname !== loginPath) {
history.push(loginPath);
} else if (location.pathname === '/') {
const pathname = initialState?.currentUser?.is_admin
? '/dashboard'
: '/playground';
history.push(pathname);
}
};
const onMenuHeaderClick = (e) => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
navigate('/dashboard'); navigate('/dashboard');
}, []); };
const onCollapse = (value) => { const onCollapse = (value) => {
setCollapsed(value); setCollapsed(value);
@@ -417,7 +433,6 @@ export default (props: any) => {
: theme.defaultAlgorithm, : theme.defaultAlgorithm,
...themeData ...themeData
}; };
console.log('currentTheme====', data);
return data; return data;
}, [userSettings.isDarkTheme, themeData]); }, [userSettings.isDarkTheme, themeData]);
@@ -461,6 +476,7 @@ export default (props: any) => {
logo={collapsed ? SLogoIcon : LogoIcon} logo={collapsed ? SLogoIcon : LogoIcon}
menuItemRender={menuItemRender} menuItemRender={menuItemRender}
itemRender={itemRender} itemRender={itemRender}
menuDataRender={menuDataRender}
disableContentMargin disableContentMargin
fixSiderbar fixSiderbar
fixedHeader fixedHeader
+5 -6
View File
@@ -6,12 +6,11 @@ import langConfigMap from '@/locales/lang-config-map';
import { import {
DiscordOutlined, DiscordOutlined,
GithubOutlined, GithubOutlined,
GlobalOutlined,
HomeOutlined, HomeOutlined,
InfoCircleOutlined, InfoCircleOutlined,
LogoutOutlined, LogoutOutlined,
MoonOutlined, MoonOutlined,
QuestionCircleOutlined, MoreOutlined,
ReadOutlined, ReadOutlined,
SettingOutlined, SettingOutlined,
SunOutlined SunOutlined
@@ -140,7 +139,7 @@ export const getRightRenderContent = (opts: {
items: [ items: [
{ {
key: 'help', key: 'help',
icon: <QuestionCircleOutlined />, icon: <IconFont type="icon-help" />,
label: ( label: (
<span className="sub-title "> <span className="sub-title ">
<span className="flex-center"> <span className="flex-center">
@@ -213,7 +212,7 @@ export const getRightRenderContent = (opts: {
items: [ items: [
{ {
key: 'lang', key: 'lang',
icon: <GlobalOutlined />, icon: <IconFont type="icon-language" />,
label: ( label: (
<span className="sub-title"> <span className="sub-title">
{intl?.formatMessage?.({ id: 'common.settings.language' })} {intl?.formatMessage?.({ id: 'common.settings.language' })}
@@ -265,7 +264,7 @@ export const getRightRenderContent = (opts: {
? 'user-menu-container user-menu-collapsed' ? 'user-menu-container user-menu-collapsed'
: 'user-menu-container', : 'user-menu-container',
mode: 'vertical', mode: 'vertical',
expandIcon: false, expandIcon: collapsed ? false : <MoreOutlined />,
// inlineCollapsed: collapsed, // inlineCollapsed: collapsed,
triggerSubMenuAction: 'hover', triggerSubMenuAction: 'hover',
items: [ items: [
@@ -274,7 +273,7 @@ export const getRightRenderContent = (opts: {
key: 'user', key: 'user',
className: 'user-avatar', className: 'user-avatar',
icon: ( icon: (
<span> <span className="avatar-container">
<Avatar <Avatar
size={28} size={28}
style={{ style={{
@@ -1,5 +1,6 @@
import { ExportOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Col, DatePicker, Row, Select } from 'antd'; import { Button, Col, DatePicker, Row, Select, Tooltip } from 'antd';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { FC, memo, useContext, useState } from 'react'; import { FC, memo, useContext, useState } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
@@ -107,6 +108,14 @@ const UsageInner: FC<{ paddingRight: string }> = ({ paddingRight }) => {
})} })}
style={{ width: 160 }} style={{ width: 160 }}
></Select> ></Select>
<Tooltip
title={intl.formatMessage({ id: 'common.button.export' })}
>
<Button
icon={<ExportOutlined />}
onClick={handleExport}
></Button>
</Tooltip>
</div> </div>
</FilterWrapper> </FilterWrapper>
</div> </div>
@@ -1,7 +1,6 @@
import CardWrapper from '@/components/card-wrapper'; import CardWrapper from '@/components/card-wrapper';
import { SimpleCard } from '@/components/card-wrapper/simple-card'; import { SimpleCard } from '@/components/card-wrapper/simple-card';
import MixLineBar from '@/components/echarts/mix-line-bar'; import MixLineBar from '@/components/echarts/mix-line-bar';
import { ExportOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Button } from 'antd'; import { Button } from 'antd';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
@@ -79,14 +78,14 @@ const RequestTokenInner: React.FC<RequestTokenInnerProps> = (props) => {
return ( return (
<CardWrapperBox> <CardWrapperBox>
<CardWrapper style={{ width: '100%', position: 'relative' }}> <CardWrapper style={{ width: '100%', position: 'relative' }}>
<DownloadButton {/* <DownloadButton
type="link" type="link"
icon={<ExportOutlined />} icon={<ExportOutlined />}
size="small" size="small"
onClick={onExport} onClick={onExport}
> >
{intl.formatMessage({ id: 'common.button.export' })} {intl.formatMessage({ id: 'common.button.export' })}
</DownloadButton> </DownloadButton> */}
<SimpleCard dataList={dataList} height={80}></SimpleCard> <SimpleCard dataList={dataList} height={80}></SimpleCard>
<MixLineBar <MixLineBar
chartData={{ chartData={{
@@ -174,7 +174,7 @@ const ContentItem: React.FC<MessageItemProps> = ({
<IconFont <IconFont
type="icon-assistant-filled" type="icon-assistant-filled"
className="font-size-16 m-r-5" className="font-size-16 m-r-5"
style={{ color: 'var(--ant-blue-5)' }} style={{ color: 'var(--ant-blue-6)' }}
/> />
); );
} }
@@ -288,7 +288,7 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef((props, ref) => {
></Button> ></Button>
</Dropdown> </Dropdown>
<Popover <Popover
placement="bottomRight" autoAdjustOverflow={true}
overlayInnerStyle={{ width: 384, paddingInline: 0 }} overlayInnerStyle={{ width: 384, paddingInline: 0 }}
content={ content={
<OverlayScroller <OverlayScroller
+1 -1
View File
@@ -93,7 +93,7 @@
right: 32px; right: 32px;
bottom: 0; bottom: 0;
height: 1px; height: 1px;
background-color: var(--ant-color-split); border-bottom: 1px solid var(--ant-color-split);
} }
} }
} }
@@ -10,10 +10,10 @@
.think-content { .think-content {
margin-bottom: 8px; margin-bottom: 8px;
padding: 12px; padding: 0 12px;
border-left: 2px solid var(--ant-color-fill-secondary); border-left: 2px solid var(--ant-color-fill-secondary);
background-color: var(--ant-color-fill-tertiary); // background-color: var(--ant-color-fill-tertiary);
color: var(--ant-color-text-tertiary); color: var(--ant-color-text-tertiary);
border-radius: var(--border-radius-base); // border-radius: var(--border-radius-base);
} }
} }