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