diff --git a/src/App.tsx b/src/App.tsx index cf35203..3039332 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,7 +3,7 @@ import { initI18n } from '@/i18n.ts' import { appAtom, appStore, changeLanguage } from '@/store/system.ts' import { IAppData } from '@/global' import { ConfigProvider } from '@/components/config-provider' -import { Provider, useAtom } from 'jotai' +import { Provider } from 'jotai' import './App.css' import { useEffect } from 'react' import { RootProvider } from './routes.tsx' @@ -11,27 +11,25 @@ import { RootProvider } from './routes.tsx' function App() { - const [ appData, ] = useAtom(appAtom) - useEffect(() => { - initI18n() - }, []) + useEffect(() => { + initI18n() + }, []) - - return ( - - - - - - - - ) + return ( + + { + return appStore.get(appAtom) as IAppData + }, + changeLanguage + }}> + + + + + + ) } export default App diff --git a/src/components/avatar/index.tsx b/src/components/avatar/index.tsx index bba548d..be5ec9c 100644 --- a/src/components/avatar/index.tsx +++ b/src/components/avatar/index.tsx @@ -4,60 +4,62 @@ import { currentUserAtom, logoutAtom } from '@/store/system/user.ts' import { Avatar as AntAvatar, Dropdown, Spin } from 'antd' import { useAtomValue } from 'jotai' import { useNavigate } from '@tanstack/react-router' +import { useStyle } from './style' const Avatar = () => { - const { t } = useTranslation() - const { data, isLoading } = useAtomValue(currentUserAtom) - const { mutate: logout } = useAtomValue(logoutAtom) - const navigate = useNavigate() + const { styles } = useStyle() + const { t } = useTranslation() + const { data, isLoading } = useAtomValue(currentUserAtom) + const { mutate: logout } = useAtomValue(logoutAtom) + const navigate = useNavigate() - return ( -
- , - label: {t('app.header.logout')}, - }, - ], - onClick: (e) => { - if (e.key === 'logout') { - logout() - navigate({ - to: '/login', search: { - redirect: window.location.pathname - } - }) - } - }, - }} - > - - - {!data?.avatar && data?.nickname?.substring(0, 1)} - - + return ( +
+ , + label: {t('app.header.logout')}, + }, + ], + onClick: (e) => { + if (e.key === 'logout') { + logout() + navigate({ + to: '/login', search: { + redirect: window.location.pathname + } + }) + } + }, + }} + > + + + {!data?.avatar && data?.nickname?.substring(0, 1)} + + {data?.nickname} - - -
- ) +
+
+
+ ) } export default Avatar \ No newline at end of file diff --git a/src/components/avatar/style.ts b/src/components/avatar/style.ts new file mode 100644 index 0000000..f96bab9 --- /dev/null +++ b/src/components/avatar/style.ts @@ -0,0 +1,13 @@ +import { createStyles } from '@/theme' + +export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) => { + const prefix = `${prefixCls}-${token?.proPrefix}-avatar-component` + + const container = css` + padding-inline: 10px; + ` + + return { + container: cx(prefix, props?.className, container), + } +}) \ No newline at end of file diff --git a/src/components/config-provider/index.tsx b/src/components/config-provider/index.tsx index 1292222..7f16af5 100644 --- a/src/components/config-provider/index.tsx +++ b/src/components/config-provider/index.tsx @@ -47,6 +47,7 @@ export const ConfigProvider: FC = ({ children, componentTok // 以下都是自定义主题 theme={createProAntdTheme} customToken={getProToken} + > {children} diff --git a/src/components/icon/picker/IconRender.tsx b/src/components/icon/picker/IconRender.tsx index ef05f67..d6da028 100644 --- a/src/components/icon/picker/IconRender.tsx +++ b/src/components/icon/picker/IconRender.tsx @@ -2,6 +2,7 @@ import type { FC } from 'react' import { memo } from 'react' import { AntdIcon, ParkIcon, ALL_ICON_KEYS } from './icons.ts' import { IconType } from '@icon-park/react/es/all' +import { cx } from 'antd-style' export interface IconRenderProps { type: 'antd' | 'park'; @@ -32,7 +33,7 @@ const Render: FC = memo( if (ALL_ICON_KEYS.indexOf(componentName as IconType) < 0) { return null } - return + return default: { return null } diff --git a/src/components/select-lang/index.tsx b/src/components/select-lang/index.tsx index 33c3a0b..b877e77 100644 --- a/src/components/select-lang/index.tsx +++ b/src/components/select-lang/index.tsx @@ -1,6 +1,6 @@ import { useAppContext } from '@/context' import { Dropdown, DropDownProps } from 'antd' -import React, { memo, useState } from 'react' +import React, { memo } from 'react' interface LocalData { @@ -43,22 +43,22 @@ const defaultLangUConfigMap = { export interface HeaderDropdownProps extends DropDownProps { overlayClassName?: string; placement?: - | 'bottomLeft' - | 'bottomRight' - | 'topLeft' - | 'topCenter' - | 'topRight' - | 'bottomCenter'; + | 'bottomLeft' + | 'bottomRight' + | 'topLeft' + | 'topCenter' + | 'topRight' + | 'bottomCenter'; } const HeaderDropdown: React.FC = ({ overlayClassName: cls, ...restProps }) => ( - + ) export const SelectLang = memo((props: SelectLangProps) => { @@ -74,37 +74,36 @@ export const SelectLang = memo((props: SelectLangProps) => { reload, ...restProps } = props - const [ selectedLang, setSelectedLang ] = useState(() => ctx.appData.language) + const changeLang = ({ key }: ClickParam): void => { ctx.changeLanguage(key, reload) - setSelectedLang(key) } const defaultLangUConfig = Object.values(defaultLangUConfigMap) const allLangUIConfig = - postLocalesData?.(defaultLangUConfig) || defaultLangUConfig + postLocalesData?.(defaultLangUConfig) || defaultLangUConfig const handleClick = onItemClick - ? (params: ClickParam) => onItemClick(params) - : changeLang + ? (params: ClickParam) => onItemClick(params) + : changeLang const menuItemStyle = { minWidth: '160px' } const menuItemIconStyle = { marginRight: '8px' } - + const language = ctx.appData().language const langMenu = { - selectedKeys: [ selectedLang ], + selectedKeys: [ language ], onClick: handleClick, items: allLangUIConfig.map((localeObj) => ({ key: localeObj.lang || localeObj.key, style: menuItemStyle, label: ( - <> + <> {localeObj?.icon || '🌐'} - {localeObj?.label || 'zh-CN'} - + {localeObj?.label || 'zh-CN'} + ), })), } @@ -123,29 +122,29 @@ export const SelectLang = memo((props: SelectLangProps) => { } return ( - + - + {icon ? - icon : ( - - )} + icon : ( + + )} - + ) }) diff --git a/src/components/table/Table.tsx b/src/components/table/Table.tsx index f32f1a0..dd6da13 100644 --- a/src/components/table/Table.tsx +++ b/src/components/table/Table.tsx @@ -81,6 +81,7 @@ export const Table = = any, D = any>(props: Table {...props.cardProps} bodyStyle={{ paddingBlockStart: 0, + paddingBlockEnd: 0, }} >
{domList.toolbar}
diff --git a/src/components/table/style.ts b/src/components/table/style.ts index c27fd12..b121843 100644 --- a/src/components/table/style.ts +++ b/src/components/table/style.ts @@ -1,19 +1,38 @@ import { createStyles } from '@/theme' +import { useScrollStyle } from '@/hooks/useScrollStyle.ts' export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) => { const prefix = `${prefixCls}-${token?.proPrefix}-my-table` + const { scrollbar } = useScrollStyle() const container = css` --toolbar-height: 65px; --alter-height: 0px; - --padding: 37px; + --padding: 23px; --table-body-height: calc(var(--toolbar-height, 65px) + var(--alter-height, 0px) + var(--header-height, 56px) + var(--padding, 20px) * 4); .ant-table-body { overflow: auto scroll; max-height: calc(100vh - var(--table-body-height)) !important; height: calc(100vh - var(--table-body-height)) !important; + + } + + + .ant-table-wrapper .ant-table{ + scrollbar-color: unset; + } + .ant-table-body{ + + ${scrollbar} + + } + .ant-table-pagination.ant-pagination { + border-top: 1px solid #ebeef5; + height: 51px; + margin: 0; + align-content: center; } ` diff --git a/src/context.ts b/src/context.ts index 7bade70..e64beb0 100644 --- a/src/context.ts +++ b/src/context.ts @@ -3,7 +3,7 @@ import React, { createContext, ProviderProps, useContext } from 'react' import { t } from 'i18next' export interface IAppContextValue { - get appData(): IAppData + appData: () => IAppData changeLanguage: (lang: string, reload?: boolean) => void diff --git a/src/hooks/useScrollStyle.ts b/src/hooks/useScrollStyle.ts index 812b629..7020436 100644 --- a/src/hooks/useScrollStyle.ts +++ b/src/hooks/useScrollStyle.ts @@ -67,8 +67,57 @@ export const useScrollStyle = () => { ${scrollbar} ` + const darkScrollbar = css` + &::-webkit-scrollbar { + width: 9px; + height: 9px; + } + + &::-webkit-scrollbar-track { + border-radius: 8px; + background-color: transparent; + + &:hover { + background-color: rgba(255, 255, 255, 0.06); + -webkit-box-shadow: -1px 0 0 #000 inset, 1px 0 0 hsla(0, 0%, 0%, 0.9) inset, 0 -1px 0 hsla(0, 0%, 0%, 0.9) inset, 0 1px 0 hsla(0, 0%, 0%, 0.9) inset; + } + + &:active { + background-color: rgba(255, 255, 255, 0.1); + } + } + + &::-webkit-scrollbar-thumb { + border-radius: 8px; + background-color: rgba(255, 255, 255, 0.1); + -webkit-box-shadow: -2px 0 0 #000 inset, 1px 0 0 #000 inset, 0 -1px 0 hsl(0deg 0% 0% / 90%) inset, 0 1px 0 hsl(0deg 0% 0% / 90%) inset; + + &:hover { + background-color: rgba(255, 255, 255, 0.4); + } + + &:active { + background: rgba(255, 255, 255, 0.6); + } + } +`; + + const darkScrollbarBackground = css` + background: linear-gradient(#000 30%, hsla(0, 0%, 0%, 0)), + linear-gradient(hsla(0, 0%, 0%, 0), #000 70%) 0 100%, + radial-gradient(farthest-side at 50% 0, rgba(255, 255, 255, 0.1), transparent), + radial-gradient(farthest-side at 50% 100%, rgba(255, 255, 255, 0.1), transparent) 0 100%; + background-repeat: no-repeat; + background-size: 100% 40px, 100% 40px, 100% 14px, 100% 14px; + background-attachment: local, local, scroll, scroll; + + ${darkScrollbar} +`; + return { scrollbarBackground, scrollbar, + darkScrollbarBackground, + darkScrollbar, } } \ No newline at end of file diff --git a/src/index.css b/src/index.css index f1e0f45..8cc074b 100644 --- a/src/index.css +++ b/src/index.css @@ -1,8 +1,14 @@ +html, body{ + height: 100%; margin: 0; padding: 0; font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif; } body.login { overflow: hidden; +} + +#root{ + height: 100%; } \ No newline at end of file diff --git a/src/layout/ListPageLayout.tsx b/src/layout/ListPageLayout.tsx index f0cc0de..0caa39d 100644 --- a/src/layout/ListPageLayout.tsx +++ b/src/layout/ListPageLayout.tsx @@ -9,7 +9,7 @@ interface IListPageLayoutProps extends PageContainerProps { const ListPageLayout: React.FC = ( { - children, authHeight = true, ...props + className, children, authHeight = true, ...props }) => { const { styles, cx } = useStyle({ className: 'two-col' }) @@ -18,7 +18,7 @@ const ListPageLayout: React.FC = ( <> diff --git a/src/layout/RootLayout.tsx b/src/layout/RootLayout.tsx index 289d617..b81afb4 100644 --- a/src/layout/RootLayout.tsx +++ b/src/layout/RootLayout.tsx @@ -7,7 +7,7 @@ import { userMenuDataAtom } from '@/store/system/user.ts' import { MenuItem } from '@/global' import { ProConfigProvider, ProLayout, } from '@ant-design/pro-components' import { zhCNIntl, enUSIntl } from '@ant-design/pro-provider/es/intl' -import { CatchBoundary, Link, Outlet } from '@tanstack/react-router' +import { CatchBoundary, Link, Outlet, useNavigate } from '@tanstack/react-router' import { ConfigProvider } from '@/components/config-provider' import { useEffect, useRef, useState } from 'react' import { useAtomValue } from 'jotai' @@ -15,7 +15,9 @@ import { useStyle } from '@/layout/style.ts' import zh from 'antd/locale/zh_CN' import en from 'antd/locale/en_US' import type { MenuDataItem } from '@ant-design/pro-layout/es/typing' -import { flattenTree } from '@/utils' +import { convertToMenu, flattenTree } from '@/utils' +import { Flex, Menu, Space } from 'antd' +import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons' //根据menuData生成Breadcrumb所需的数据 const getBreadcrumbData = (menuData: MenuItem[], pathname: string) => { @@ -41,11 +43,14 @@ const getBreadcrumbData = (menuData: MenuItem[], pathname: string) => { export default () => { + const navigate = useNavigate() const { styles } = useStyle() const { data: menuData = [], isLoading } = useAtomValue(userMenuDataAtom) const { language } = useAtomValue(appAtom) const items = getBreadcrumbData(menuData, location.pathname) const [ pathname, setPathname ] = useState(location.pathname) + const [ openMenuKeys, setOpenKeys ] = useState([]) + const [ collapsed, setCollapsed ] = useState(false) const menusFlatten = useRef() if (!menusFlatten.current) { @@ -59,10 +64,12 @@ export default () => { return item ? item.parentName : [] }) const childMenuRef = useRef([]) - - childMenuRef.current = menuData.find(item => { + const currentMenu = menuData.find(item => { return item.key === rootMenuKeys?.[0] - })?.children || [] + }) + + childMenuRef.current = currentMenu?.children || [] + useEffect(() => { const item = menusFlatten.current?.find(item => item.path === location.pathname) @@ -71,13 +78,12 @@ export default () => { } }, [ location.pathname ]) - return (
@@ -97,16 +103,25 @@ export default () => { header: { colorBgMenuItemSelected: 'rgba(0,0,0,0.04)', }, + sider: { + colorMenuBackground: '#222b45', + } }} - fixedHeader={true} - headerContentRender={() => } + className={styles.myLayout} + // fixedHeader={true} + headerContentRender={false} + headerTitleRender={false} + menuHeaderRender={() => { + return <> + + + }} + headerRender={false} title="Crazy Pro" - layout={'mix'} + // layout={'mix'} fixSiderbar={true} - siderWidth={100} + siderWidth={65} collapsedButtonRender={false} // collapsed={false} postMenuData={() => { @@ -137,40 +152,100 @@ export default () => { }} menuItemRender={(item: MenuDataItem) => { - return { + return ( { setRootMenuKeys([ (item as any).key || 'dashboard' ]) setPathname(item.path || '/dashboard') }} > - - {item.icon} - {item.name} - - - }} - avatarProps={{ - // src: 'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg', - render: () => { - return ( - - ) - }, - }} - actionsRender={(props) => { - if (props.isMobile) return [] - if (typeof window === 'undefined') return [] - return [ - , - ] + + {item.icon} + {item.name} + + ) }} + avatarProps={false} + actionsRender={false} menuProps={{ className: styles.mySiderMenu, selectedKeys: rootMenuKeys, + theme: 'dark', }} - // navTheme={'light'} + loading={isLoading} contentStyle={{ paddingBlock: 0, paddingInline: 0 }} + { + ...{ + // "fixSiderbar": true, + // "layout": "side", + 'splitMenus': false, + 'navTheme': 'realDark', + 'contentWidth': 'Fluid', + 'colorPrimary': '#1677FF', + // "menuHeaderRender": false + } + } > - + { + !collapsed &&
+

{currentMenu?.title}

+
+ } + + { + setOpenKeys(keys) + }} + onClick={(menu) => { + const info = menusFlatten.current?.find(item => item.path === menu.key) + if (info) { + setOpenKeys([ info.path as string ]) + navigate({ + to: info.path, + }) + } + + }} + items={convertToMenu((childMenuRef.current || []), (item => { + return { + ...item, + key: item.path, + label: item.title, + } + })) as any} + style={!collapsed ? { width: 210 } : {}} + /> +
{ + setCollapsed(!collapsed) + }}> + { + collapsed ? : + } +
+ + +
+ + + <> + + + + + +
+ +
+ {/* { // layout: 'side', }} > - - + */} diff --git a/src/layout/TwoColPageLayout.tsx b/src/layout/TwoColPageLayout.tsx index 1f3cd52..193d3d1 100644 --- a/src/layout/TwoColPageLayout.tsx +++ b/src/layout/TwoColPageLayout.tsx @@ -16,7 +16,7 @@ export const TwoColPageLayout: React.FC = (props) => { return ( diff --git a/src/layout/style.ts b/src/layout/style.ts index b715707..f0f850c 100644 --- a/src/layout/style.ts +++ b/src/layout/style.ts @@ -5,11 +5,12 @@ import { useScrollStyle } from '@/hooks/useScrollStyle' export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) => { const prefix = `${prefixCls}-${token?.proPrefix}-layout` - const { scrollbar } = useScrollStyle() + const { scrollbar,darkScrollbar,scrollbarBackground } = useScrollStyle() const container = { [prefix]: css` + height: 100%; .ant-pro-global-header-logo, .ant-pro-layout-bg-list { @@ -20,17 +21,7 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) //padding-inline-start: 0; } - .ant-table-scroll-bar { - } - - .ant-table-wrapper .ant-table{ - scrollbar-color: unset; - } - .ant-table-body{ - - ${scrollbar} - - } + .ant-pro-layout-content{ padding: 20px; @@ -41,24 +32,41 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) } .ant-pro-page-container-children-container{ - padding-inline: 20px; - padding-block-end: 20px; + padding-inline: 0px; + padding-block: 0px; } .ant-page-header-no-children { - height: 20px; - } - + height: 0px; + } .ant-pro-card{ - height: calc(100vh - 100px)!important; - min-height: calc(100vh - 100px)!important; + height: 100%; + .ant-pro-card-header{ + padding-block: 16px; + } } - + .ant-pro-card-body{ + padding-block-start: 0; + overflow: auto; + height: calc(100vh - 100px); + min-height: calc(100vh - 100px); + ${scrollbarBackground} + } + + `, } const pageCard = css` + .ant-pro-grid-content, + .ant-pro-grid-content-children, + .ant-pro-page-container-children-container, + .layoutkit-flexbox + { + height: 100%; + } + ` const pageContext = css` @@ -71,6 +79,107 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) } ` + const myLayout = css` + + height: 100%; + .ant-pro-layout-content{ + flex-direction: row; + } + + .ant-pro-sider-light{ + //background-color: #222b45!important; + } + .ant-pro-sider .ant-layout-sider-children{ + padding-inline: 0; + } + + .ant-layout-sider-children > div:nth-child(2){ + + ${darkScrollbar} + + } + + .ant-pro-sider-logo{ + padding-block-start: 10px; + padding-block-end: 0; + max-height: 50px; + overflow: hidden; + } + .ant-pro-layout-content, + .ant-pro-layout-container{ + width: calc(100vw - 65px); + overflow: hidden; + height: 100vh; + } + + ` + + const childMenus = css` + + background: #fff; + box-shadow: 2px 0 8px 0 rgba(29, 35, 41, .05); + border-right: 1px solid #e6e6e6; + // transition: width .3s; + overflow: hidden; + height: 100vh; + + display: flex; + flex-direction: column; + + .i-icon{ + display: inline-flex; + } + + .ant-menu{ + flex: 1; + border-inline-end: 0!important; + overflow: auto; + ${scrollbar} + + .ant-menu-item{ + border-radius: 0; + margin: 0; + width: 100%; + } + .ant-menu-item-selected{ + } + } + + .ant-menu-inline-collapsed >.ant-menu-item{ + padding-inline: calc(50% - 8px); + } + .ant-menu-inline .ant-menu-submenu-title{ + margin-inline: 0; + margin-block: 0; + width: 100%; + border-radius: 0; + } + + ` + + + const childMenuTop = css` + overflow: hidden; + border-bottom: 1px solid #ebeef5; + height: var(--bodyHeader, 50px); + line-height: var(--bodyHeader, 50px); + + h2{ + padding: 0 20px; + font-size: 17px; + color: #3c4a54; + margin: 0; + } + ` + + const childMenuBottom = css ` + border-top: 1px solid #ebeef5; + height: 51px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + ` const mySider = css` .ant-layout-sider-children{ @@ -82,7 +191,7 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) } ` const mySiderMenu = css` - + padding-top: 10px; .ant-menu-item{ @@ -109,6 +218,67 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) align-items: center; } } + + .ant-pro-layout .ant-layout-sider.ant-pro-sider{ + background: none; + } + + + &.ant-menu-inline .ant-menu-item{ + margin-inline: 0; + margin-block: 0; + width: 65px; + border-radius: 0; + color: white!important; + } + + .ant-menu-item:not(.ant-menu-item-selected):hover{ + background-color: hsla(0,0%,100%,.1) !important; + color: white!important; + } + + .ant-menu-item-selected{ + background-color: #409eff; + color: white; + } + + ` + + const body = css` + overflow: hidden; + --bodyHeader: 50px; + + .ant-pro-page-container { + width: 100%; + flex: 1; + overflow: hidden; + height: calc(100vh - var(--bodyHeader, 50px)); + + } + ` + + const bodyHeader = css` + padding-block-end: 0; + padding-block-start: 0; + border-bottom: 1px solid #ebeef5; + background-color: white; + padding-inline: 15px; + height: var(--bodyHeader, 50px); + line-height: var(--bodyHeader, 50px); + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + box-shadow: 0 1px 4px rgba(0,21,41,.08); + ` + + const headerRight = css` + .ant-space-item{ + cursor: pointer; + &:hover{ + background-color: ${token.colorBgTextHover}; + } + } ` const box = css` @@ -119,8 +289,19 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) background-color: ${token.colorBgContainer}; .ant-pro-draggable-panel-fixed{ - height: calc(100vh - 100px)!important; - min-height: calc(100vh - 100px)!important; + //height: calc(100vh - 100px)!important; + //min-height: calc(100vh - 100px)!important; + } + + + ` + + const layoutTable = css` + .ant-pro-table{ + .ant-pro-card-body{ + height: calc(100vh - 50px); + min-height: calc(100vh - 50px); + } } ` @@ -133,6 +314,14 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) mySider, mySiderMenu, pageCard, + myLayout, + childMenuTop, + childMenus, + childMenuBottom, + body, + bodyHeader, + headerRight, + layoutTable, } }) \ No newline at end of file diff --git a/src/pages/cms/category/index.tsx b/src/pages/cms/category/index.tsx index cecdfcd..3c13bfd 100644 --- a/src/pages/cms/category/index.tsx +++ b/src/pages/cms/category/index.tsx @@ -48,7 +48,9 @@ const Category = () => { return ( - + diff --git a/src/pages/cms/category/style.ts b/src/pages/cms/category/style.ts index b033703..06250c6 100644 --- a/src/pages/cms/category/style.ts +++ b/src/pages/cms/category/style.ts @@ -68,6 +68,14 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }) => { min-height: calc(100vh - 122px); background-color: ${token.colorBgContainer}; ` + + const card = css` + .ant-pro-card-body{ + height: calc(100% - 100px)!important; + min-height: calc(100% - 100px)!important; + } + ` + return { container: cx(prefix), authHeight, @@ -76,6 +84,7 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }) => { emptyForm, tree, treeNode, - treeActions + treeActions, + card, } }) \ No newline at end of file diff --git a/src/routes.tsx b/src/routes.tsx index 398e713..d60395a 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -26,7 +26,7 @@ import { import { memo, useEffect, useRef } from 'react' import RootLayout from './layout/RootLayout' import { IRootContext, MenuItem } from './global' -import { DevTools } from 'jotai-devtools' +// import { DevTools } from 'jotai-devtools' import { useAtomValue } from 'jotai' import { userMenuDataAtom } from '@/store/system/user.ts' @@ -51,7 +51,7 @@ const rootRoute = createRootRouteWithContext()({ <> - + {/**/} {/**/} ), @@ -209,6 +209,7 @@ const generateDynamicRoutes = (menuData: MenuItem[], parentRoute: AnyRoute) => { } else { if (!path) { console.log(`${menu.name}没有设置视图`) + options.id = menu.meta.name } else { options.path = path } diff --git a/src/store/cms/video.ts b/src/store/cms/video.ts index 0a49554..ed5973e 100644 --- a/src/store/cms/video.ts +++ b/src/store/cms/video.ts @@ -25,13 +25,10 @@ export const videoIdsAtom = atom([]) export const videoAtom = atom(undefined as unknown as Cms.IVideo) export const videoSearchAtom = atom({ - key: '' -} as SearchParams) - -export const videoPageAtom = atom({ - pageSize: 10, + key: '', + pageSize: 20, page: 1, -}) +} as SearchParams) export const videosAtom = atomWithQuery((get) => { return { diff --git a/src/store/system.ts b/src/store/system.ts index 1695103..3398b41 100644 --- a/src/store/system.ts +++ b/src/store/system.ts @@ -9,45 +9,43 @@ import { changeLanguage as setLang } from 'i18next' export const appStore = createStore() export const appAtom = atomWithStorage>('app', { - name: 'Crazy Pro', - version: '1.0.0', - language: 'zh-CN', + name: 'Crazy Pro', + version: '1.0.0', + language: 'zh-CN', }) appStore.sub(appAtom, () => { - // const token = appStore.get(appAtom).token - + // const token = appStore.get(appAtom).token + // console.log('切换 ',appStore.get(appAtom).language) }) export const getAppData = () => { - return appStore.get(appAtom) + return appStore.get(appAtom) } export const changeLanguage = (lang: string, reload?: boolean) => { - if (appStore.get(appAtom).language !== lang) { - setLang(lang) - updateAppData({ language: lang }) - if (reload) { - window.location.reload() - } - } + setLang(lang) + updateAppData({ language: lang }) + if (reload) { + window.location.reload() + } } export const updateAppData = (app: Partial) => { - appStore.set(appAtom, (prev) => { - return { - ...prev, - ...app, - } - }) + appStore.set(appAtom, (prev) => { + return { + ...prev, + ...app, + } + }) } export const getToken = () => { - return appStore.get(appAtom).token + return appStore.get(appAtom).token } export const setToken = (token: string) => { - console.log('settoken', token) - updateAppData({ token }) + console.log('settoken', token) + updateAppData({ token }) } diff --git a/src/theme/themes/darkAlgorithm.ts b/src/theme/themes/darkAlgorithm.ts index e32dc24..3a0306a 100644 --- a/src/theme/themes/darkAlgorithm.ts +++ b/src/theme/themes/darkAlgorithm.ts @@ -12,7 +12,9 @@ export const proDarkAlgorithm: MappingAlgorithm = (seedToken, mapToken) => { return { ...mergeToken, - colorBgLayout: '#20252b', + + // colorBgLayout: '#20252b', + colorBgLayout: '#222b45', colorBgContainer: '#282c34', colorBgElevated: '#32363e', } diff --git a/src/utils/index.ts b/src/utils/index.ts index f113f20..f79f948 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,7 +1,7 @@ import { IMenu } from '@/types/system/menus' import { FiledNames, FlattenData, MenuItem } from '@/global' import { getIcon } from '@/components/icon' -import { TreeDataNode } from 'antd' +import { TreeDataNode, MenuItemProps } from 'antd' //vite环境变量, 判断是否是开发环境 export const isDev = import.meta.env.MODE === 'development' @@ -59,6 +59,24 @@ export const formatterMenuData = (data: MenuItem[]): TreeDataNode[] => { return result } +//将tree转成Menu结构 +export const convertToMenu = (data: any[], format?: (item: any) => any) => { + const result: MenuItemProps[] = [] + format = format ?? ((item: any) => item) + for (const item of data) { + const _item = format(item) + if (_item.children && _item.children.length) { + result.push( { + ..._item, + children: convertToMenu(_item.children, format), + }) + }else { + result.push(_item) + } + } + return result +} + //把tree转成平铺数组 const defaultTreeFieldNames: FiledNames = { key: 'id',