Separate official website page

This commit is contained in:
2023-12-28 17:50:26 +08:00
parent 81d6f0ac29
commit 0b8df09336
33 changed files with 125 additions and 980 deletions

View File

@@ -1,223 +0,0 @@
import React from 'react'
import Icon from '@ant-design/icons'
import '@/assets/css/pages/home-framework.scss'
import { COLOR_FONT_SECONDARY } from '@/constants/common.constants'
import { getRouter } from '@/router'
import FullscreenLoadingMask from '@/components/common/FullscreenLoadingMask'
import HideScrollbar, { HideScrollbarElement } from '@/components/common/HideScrollbar'
export const HomeFrameworkContext = createContext<{
navbarHiddenState: {
navbarHidden: boolean
setNavbarHidden: (newValue: boolean) => void
}
preventScrollState: {
preventScroll: boolean
setPreventScroll: (newValue: boolean) => void
}
showVerticalScrollbarState: {
showVerticalScrollbar: boolean
setShowVerticalScrollbar: (newValue: boolean) => void
}
showHorizontalScrollbarState: {
showHorizontalScrollbar: boolean
setShowHorizontalScrollbar: (newValue: boolean) => void
}
showDropdownMenuState: {
showDropdownMenu: boolean
setShowDropdownMenu: (newValue: boolean) => void
}
hideScrollbarRef: React.RefObject<HideScrollbarElement>
}>({
navbarHiddenState: {
navbarHidden: false,
setNavbarHidden: () => undefined
},
preventScrollState: {
preventScroll: false,
setPreventScroll: () => undefined
},
showVerticalScrollbarState: {
showVerticalScrollbar: false,
setShowVerticalScrollbar: () => undefined
},
showHorizontalScrollbarState: {
showHorizontalScrollbar: false,
setShowHorizontalScrollbar: () => undefined
},
showDropdownMenuState: {
showDropdownMenu: false,
setShowDropdownMenu: () => undefined
},
hideScrollbarRef: createRef()
})
const HomeFramework: React.FC = () => {
const routeId = useMatches()[1].id
const routeChildren = getRouter().routes[0].children?.find((value) => value.id === routeId)
?.children
const pathname = useLocation().pathname
const hideScrollbarRef = useRef<HideScrollbarElement>(null)
const [navbarHidden, setNavbarHidden] = useState(true)
const [preventScroll, setPreventScroll] = useState(false)
const [showVerticalScrollbar, setShowVerticalScrollbar] = useState(false)
const [showHorizontalScrollbar, setShowHorizontalScrollbar] = useState(false)
const [showDropdownMenu, setShowDropdownMenu] = useState(false)
useEffect(() => {
setNavbarHidden(false)
}, [pathname])
const handleMenuDropdownButtonClick = () => {
setShowDropdownMenu(!showDropdownMenu)
}
return (
<>
<HideScrollbar
data-component={'home-framework'}
ref={hideScrollbarRef}
isPreventVerticalScroll={preventScroll}
isShowHorizontalScrollbar={true}
minWidth={900}
>
<div className={'body'}>
<div>
<header className={`nav${navbarHidden ? ' hide' : ''}`}>
<a className={'logo'} href={'https://fatweb.top'}>
<span className={'title'}>FatWeb</span>
</a>
<nav>
<ul className={'menu'}>
{routeChildren?.map((route) => {
return (route.handle as RouteHandle).menu ? (
<li className={'item'} key={route.id}>
<NavLink
to={route.path ?? ''}
className={({ isActive, isPending }) =>
isPending
? 'pending'
: isActive
? 'active'
: ''
}
>
{(route.handle as RouteHandle).name}
</NavLink>
{route.children ? (
<ul className={'submenu'}>
{route.children.map((subRoute) => {
return (subRoute.handle as RouteHandle)
.menu ? (
<li
className={'item'}
key={subRoute.id}
>
<NavLink
to={`${route.path ?? ''}/${
subRoute.path ?? ''
}`}
className={({
isActive,
isPending
}) =>
isPending
? 'pending'
: isActive
? 'active'
: ''
}
>
{
(
subRoute.handle as RouteHandle
).name
}
</NavLink>
</li>
) : (
<></>
)
})}
</ul>
) : (
<></>
)}
</li>
) : (
<></>
)
})}
</ul>
<div
className={`dropdown-menu-button${
showDropdownMenu ? ' active' : ''
}`}
>
<Icon
component={IconFatwebMenu}
style={{ fontSize: '2.6em', color: COLOR_FONT_SECONDARY }}
onClick={handleMenuDropdownButtonClick}
/>
</div>
</nav>
</header>
<div className={`dropdown-menu-content${showDropdownMenu ? ' show' : ''}`}>
<ul>
{routeChildren?.map((route) => {
return (
<li className={'item'} key={route.id}>
<NavLink
to={route.path ?? ''}
className={({ isActive, isPending }) =>
isPending ? 'pending' : isActive ? 'active' : ''
}
>
{(route.handle as RouteHandle).name}
</NavLink>
</li>
)
})}
</ul>
</div>
</div>
<HomeFrameworkContext.Provider
value={{
navbarHiddenState: { navbarHidden, setNavbarHidden },
preventScrollState: { preventScroll, setPreventScroll },
showVerticalScrollbarState: {
showVerticalScrollbar,
setShowVerticalScrollbar
},
showHorizontalScrollbarState: {
showHorizontalScrollbar,
setShowHorizontalScrollbar
},
showDropdownMenuState: {
showDropdownMenu,
setShowDropdownMenu
},
hideScrollbarRef
}}
>
<Suspense
fallback={
<>
<FullscreenLoadingMask />
</>
}
>
<Outlet />
</Suspense>
</HomeFrameworkContext.Provider>
</div>
</HideScrollbar>
</>
)
}
export default HomeFramework

View File

@@ -142,7 +142,7 @@ const SignUp: React.FC = () => {
]}
>
<AntdInput
prefix={<Icon component={IconFatwebUser} />}
prefix={<Icon component={IconOxygenUser} />}
placeholder={'用户名'}
maxLength={39}
showCount={true}
@@ -158,7 +158,7 @@ const SignUp: React.FC = () => {
>
<AntdInput
type={'email'}
prefix={<Icon component={IconFatwebEmail} />}
prefix={<Icon component={IconOxygenEmail} />}
placeholder={'邮箱'}
disabled={isSigningUp}
/>
@@ -172,7 +172,7 @@ const SignUp: React.FC = () => {
]}
>
<AntdInput.Password
prefix={<Icon component={IconFatwebPassword} />}
prefix={<Icon component={IconOxygenPassword} />}
placeholder={'密码'}
disabled={isSigningUp}
/>
@@ -194,7 +194,7 @@ const SignUp: React.FC = () => {
]}
>
<AntdInput.Password
prefix={<Icon component={IconFatwebPassword} />}
prefix={<Icon component={IconOxygenPassword} />}
placeholder={'确认密码'}
disabled={isSigningUp}
/>
@@ -531,7 +531,7 @@ const Forget: React.FC = () => {
]}
>
<AntdInput
prefix={<Icon component={IconFatwebEmail} />}
prefix={<Icon component={IconOxygenEmail} />}
placeholder={'邮箱'}
disabled={isSending}
/>
@@ -724,7 +724,7 @@ const SignIn: React.FC = () => {
rules={[{ required: true, message: '请输入账号' }]}
>
<AntdInput
prefix={<Icon component={IconFatwebUser} />}
prefix={<Icon component={IconOxygenUser} />}
placeholder={'邮箱/用户名'}
disabled={isSigningIn}
/>
@@ -734,7 +734,7 @@ const SignIn: React.FC = () => {
rules={[{ required: true, message: '请输入密码' }]}
>
<AntdInput.Password
prefix={<Icon component={IconFatwebPassword} />}
prefix={<Icon component={IconOxygenPassword} />}
placeholder={'密码'}
disabled={isSigningIn}
/>

View File

@@ -20,15 +20,11 @@ const ToolsFramework: React.FC = () => {
{hasPathPermission('/system') ? (
<SidebarItem
path={'/system'}
icon={IconFatwebSetting}
icon={IconOxygenSetting}
text={'系统配置'}
/>
) : undefined}
<SidebarItem
path={'/tools'}
icon={IconFatwebBack}
text={'回到氧工具'}
/>
<SidebarItem path={'/'} icon={IconOxygenBack} text={'回到氧工具'} />
</SidebarItemList>
}
>

View File

@@ -1,174 +0,0 @@
import React from 'react'
import '@/assets/css/components/home/home.scss'
import { HomeFrameworkContext } from '@/pages/HomeFramework'
import FitFullscreen from '@/components/common/FitFullscreen'
import Slogan from '@/components/home/Slogan'
import OxygenToolbox from '@/components/home/OxygenToolbox'
import Indicator from '@/components/common/Indicator'
import Footer from '@/components/home/Footer'
const Home: React.FC = () => {
const {
hideScrollbarRef,
navbarHiddenState: { navbarHidden, setNavbarHidden },
showDropdownMenuState: { setShowDropdownMenu },
preventScrollState: { setPreventScroll }
} = useContext(HomeFrameworkContext)
const fitFullScreenRef = useRef<HTMLDivElement>(null)
const scrollTimeout = useRef(0)
const clickStart = useRef(0)
const [currentContent, setCurrentContent] = useState(0)
useEffect(() => {
setTimeout(() => {
setNavbarHidden(true)
setPreventScroll(true)
})
}, [setNavbarHidden, setPreventScroll])
useLayoutEffect(() => {
const handleWindowResize = () => {
handleScrollToContent(currentContent)()
}
window.addEventListener('resize', handleWindowResize)
return () => window.removeEventListener('resize', handleWindowResize)
})
const handleScrollToContent = (index: number) => {
return () => {
setShowDropdownMenu(false)
if (!index) {
setNavbarHidden(true)
hideScrollbarRef.current?.scrollY(0)
} else {
hideScrollbarRef.current?.scrollY(
(fitFullScreenRef.current?.offsetHeight ?? 0) * index
)
setNavbarHidden(false)
}
}
}
const handleScrollUp = () => {
if (currentContent <= 0) {
return
}
handleScrollToContent(currentContent - 1)()
clearTimeout(scrollTimeout.current)
scrollTimeout.current = setTimeout(() => {
setCurrentContent(currentContent - 1)
}, 500)
}
const handleScrollDown = () => {
if (currentContent >= content.length - 1) {
return
}
handleScrollToContent(currentContent + 1)()
clearTimeout(scrollTimeout.current)
scrollTimeout.current = setTimeout(() => {
setCurrentContent(currentContent + 1)
}, 500)
}
const handleWheel = (event: React.WheelEvent) => {
if (event.altKey || event.ctrlKey || event.shiftKey || event.deltaY === 0) {
return
}
if (event.deltaY > 0) {
handleScrollDown()
} else {
handleScrollUp()
}
}
const handleTouchStart = (event: React.TouchEvent) => {
clickStart.current = event.touches[0].clientY
}
const handleTouchEnd = (event: React.TouchEvent) => {
const moveLength = clickStart.current - event.changedTouches[0].clientY
if (Math.abs(moveLength) < 100) {
return
}
if (moveLength > 0) {
handleScrollDown()
} else {
handleScrollUp()
}
}
const handleMouseDown = (event: React.MouseEvent) => {
clickStart.current = event.clientY
}
const handleMouseUp = (event: React.MouseEvent) => {
const moveLength = clickStart.current - event.clientY
if (Math.abs(moveLength) < 100) {
return
}
if (moveLength > 0) {
handleScrollDown()
} else {
handleScrollUp()
}
}
const handleKeyDown = (event: React.KeyboardEvent) => {
if (event.key === 'ArrowUp') {
handleScrollUp()
}
if (event.key === 'ArrowDown') {
handleScrollDown()
}
}
const handleIndicatorSwitch = (index: number) => {
setCurrentContent(index)
handleScrollToContent(index)()
}
const content = [
{
backgroundColor: '#FBFBFB',
ref: fitFullScreenRef,
children: <Slogan onClickScrollDown={handleScrollDown} />
},
{ children: <OxygenToolbox /> },
{ children: <Footer /> }
]
return (
<>
<div
data-component={'home'}
tabIndex={0}
onWheel={handleWheel}
onTouchStart={handleTouchStart}
onTouchEnd={handleTouchEnd}
onMouseDown={handleMouseDown}
onMouseUp={handleMouseUp}
onKeyDown={handleKeyDown}
>
{content.map((element, index) => {
return <FitFullscreen key={index} {...element} />
})}
</div>
<div data-component={'home'} hidden={navbarHidden} className={'indicator'}>
<Indicator
total={content.length}
current={currentContent}
onSwitch={handleIndicatorSwitch}
/>
</div>
</>
)
}
export default Home

View File

@@ -503,7 +503,7 @@ const Group: React.FC = () => {
style={{ padding: '4px 8px' }}
onClick={handleOnAddBtnClick}
>
<Icon component={IconFatwebPlus} style={{ fontSize: '1.2em' }} />
<Icon component={IconOxygenPlus} style={{ fontSize: '1.2em' }} />
</AntdButton>
</Card>
</Permission>
@@ -512,7 +512,7 @@ const Group: React.FC = () => {
style={{ overflow: 'inherit', flex: '0 0 auto' }}
>
<AntdButton style={{ padding: '4px 8px' }} onClick={handleOnListDeleteBtnClick}>
<Icon component={IconFatwebDelete} style={{ fontSize: '1.2em' }} />
<Icon component={IconOxygenDelete} style={{ fontSize: '1.2em' }} />
</AntdButton>
</Card>
<Card style={{ overflow: 'inherit' }}>
@@ -577,7 +577,7 @@ const Group: React.FC = () => {
<AntdSpace>
<AntdTooltip title={'刷新角色列表'}>
<AntdButton onClick={getRoleData} disabled={isSubmitting}>
<Icon component={IconFatwebRefresh} />
<Icon component={IconOxygenRefresh} />
</AntdButton>
</AntdTooltip>
<AntdButton onClick={handleOnDrawerClose} disabled={isSubmitting}>

View File

@@ -512,7 +512,7 @@ const Role: React.FC = () => {
style={{ padding: '4px 8px' }}
onClick={handleOnAddBtnClick}
>
<Icon component={IconFatwebPlus} style={{ fontSize: '1.2em' }} />
<Icon component={IconOxygenPlus} style={{ fontSize: '1.2em' }} />
</AntdButton>
</Card>
</Permission>
@@ -521,7 +521,7 @@ const Role: React.FC = () => {
style={{ overflow: 'inherit', flex: '0 0 auto' }}
>
<AntdButton style={{ padding: '4px 8px' }} onClick={handleOnListDeleteBtnClick}>
<Icon component={IconFatwebDelete} style={{ fontSize: '1.2em' }} />
<Icon component={IconOxygenDelete} style={{ fontSize: '1.2em' }} />
</AntdButton>
</Card>
<Card style={{ overflow: 'inherit' }}>
@@ -586,7 +586,7 @@ const Role: React.FC = () => {
<AntdSpace>
<AntdTooltip title={'刷新权限列表'}>
<AntdButton onClick={getPowerTreeData} disabled={isSubmitting}>
<Icon component={IconFatwebRefresh} />
<Icon component={IconOxygenRefresh} />
</AntdButton>
</AntdTooltip>
<AntdButton onClick={handleOnDrawerClose} disabled={isSubmitting}>

View File

@@ -37,10 +37,10 @@ const SettingsCard: React.FC<SettingsCardProps> = (props) => {
<Permission operationCode={props.modifyOperationCode}>
{props.expand}
<AntdButton onClick={props.onReset} title={'重置'}>
<Icon component={IconFatwebBack} />
<Icon component={IconOxygenBack} />
</AntdButton>
<AntdButton className={'bt-save'} onClick={props.onSave} title={'保存'}>
<Icon component={IconFatwebSave} />
<Icon component={IconOxygenSave} />
</AntdButton>
</Permission>
) : undefined}
@@ -145,7 +145,7 @@ const MailSettings: React.FC = () => {
return (
<>
<SettingsCard
icon={IconFatwebEmail}
icon={IconOxygenEmail}
title={'邮件'}
loading={loading}
onReset={handleOnReset}
@@ -153,7 +153,7 @@ const MailSettings: React.FC = () => {
modifyOperationCode={'system:settings:modify:mail'}
expand={
<AntdButton onClick={handleOnTest} title={'测试'}>
<Icon component={IconFatwebTest} />
<Icon component={IconOxygenTest} />
</AntdButton>
}
>
@@ -238,7 +238,7 @@ const BaseSettings: React.FC = () => {
return (
<>
<SettingsCard
icon={IconFatwebEmail}
icon={IconOxygenEmail}
title={'基础'}
loading={loading}
onReset={handleOnReset}

View File

@@ -267,7 +267,7 @@ const OnlineInfo: React.FC = () => {
return (
<CommonCard
icon={IconFatwebOnline}
icon={IconOxygenOnline}
title={
<>
<FlexBox gap={10} direction={'horizontal'}>
@@ -298,7 +298,7 @@ const OnlineInfo: React.FC = () => {
<AntdSelect.Option key={'ALL'}></AntdSelect.Option>
</AntdSelect>
<AntdButton title={'刷新'} onClick={handleOnRefresh} disabled={isLoading}>
<Icon component={IconFatwebRefresh} />
<Icon component={IconOxygenRefresh} />
</AntdButton>
</>
}
@@ -452,7 +452,7 @@ const ActiveInfo: React.FC = () => {
return (
<CommonCard
icon={IconFatwebAnalysis}
icon={IconOxygenAnalysis}
title={
<>
<FlexBox gap={10} direction={'horizontal'}>
@@ -479,7 +479,7 @@ const ActiveInfo: React.FC = () => {
<AntdSelect.Option key={'ALL'}></AntdSelect.Option>
</AntdSelect>
<AntdButton title={'刷新'} onClick={handleOnRefresh} disabled={isLoading}>
<Icon component={IconFatwebRefresh} />
<Icon component={IconOxygenRefresh} />
</AntdButton>
</>
}
@@ -507,7 +507,7 @@ const SoftwareInfo: React.FC = () => {
return (
<CommonCard
icon={IconFatwebSoftware}
icon={IconOxygenSoftware}
title={'软件信息'}
loading={softwareInfoData === undefined}
>
@@ -569,7 +569,7 @@ const HardwareInfo: React.FC = () => {
return (
<CommonCard
icon={IconFatwebHardware}
icon={IconOxygenHardware}
title={'硬件信息'}
loading={hardwareInfoData === undefined}
>
@@ -745,7 +745,7 @@ const CPUInfo: React.FC = () => {
return (
<>
<CommonCard
icon={IconFatwebCpu}
icon={IconOxygenCpu}
title={'CPU 信息'}
loading={isLoading}
expand={
@@ -931,7 +931,7 @@ const StorageInfo: React.FC = () => {
return (
<>
<CommonCard
icon={IconFatwebMemory}
icon={IconOxygenMemory}
title={'内存信息'}
loading={isLoading}
expand={

View File

@@ -89,7 +89,7 @@ const User: React.FC = () => {
<AntdAvatar
src={
<AntdImage
preview={{ mask: <Icon component={IconFatwebEye}></Icon> }}
preview={{ mask: <Icon component={IconOxygenEye}></Icon> }}
src={`data:image/png;base64,${value}`}
alt={'Avatar'}
/>
@@ -333,7 +333,7 @@ const User: React.FC = () => {
<>
<Icon
style={{ color: COLOR_PRODUCTION, marginRight: 10 }}
component={IconFatwebSetting}
component={IconOxygenSetting}
/>
{value.username}
</>
@@ -913,7 +913,7 @@ const User: React.FC = () => {
style={{ padding: '4px 8px' }}
onClick={handleOnAddBtnClick}
>
<Icon component={IconFatwebPlus} style={{ fontSize: '1.2em' }} />
<Icon component={IconOxygenPlus} style={{ fontSize: '1.2em' }} />
</AntdButton>
</Card>
</Permission>
@@ -922,7 +922,7 @@ const User: React.FC = () => {
style={{ overflow: 'inherit', flex: '0 0 auto' }}
>
<AntdButton style={{ padding: '4px 8px' }} onClick={handleOnListDeleteBtnClick}>
<Icon component={IconFatwebDelete} style={{ fontSize: '1.2em' }} />
<Icon component={IconOxygenDelete} style={{ fontSize: '1.2em' }} />
</AntdButton>
</Card>
<Card style={{ overflow: 'inherit' }}>
@@ -992,7 +992,7 @@ const User: React.FC = () => {
<AntdSpace>
<AntdTooltip title={'刷新角色和用户组列表'}>
<AntdButton onClick={handleOnDrawerRefresh} disabled={isDrawerSubmitting}>
<Icon component={IconFatwebRefresh} />
<Icon component={IconOxygenRefresh} />
</AntdButton>
</AntdTooltip>
<AntdButton onClick={handleOnDrawerClose} disabled={isDrawerSubmitting}>

View File

@@ -66,32 +66,32 @@ const System: React.FC = () => {
<HideScrollbar isShowVerticalScrollbar autoHideWaitingTime={500}>
<FlexBox direction={'horizontal'} className={'root-content'}>
<Permission path={'/system/statistics'}>
<CommonCard icon={IconFatwebAnalysis} url={'statistics'}>
<CommonCard icon={IconOxygenAnalysis} url={'statistics'}>
</CommonCard>
</Permission>
<Permission path={'/system/settings'}>
<CommonCard icon={IconFatwebOption} url={'settings'}>
<CommonCard icon={IconOxygenOption} url={'settings'}>
</CommonCard>
</Permission>
<Permission path={'/system/user'}>
<CommonCard icon={IconFatwebUser} url={'user'}>
<CommonCard icon={IconOxygenUser} url={'user'}>
</CommonCard>
</Permission>
<Permission path={'/system/role'}>
<CommonCard icon={IconFatwebRole} url={'role'}>
<CommonCard icon={IconOxygenRole} url={'role'}>
</CommonCard>
</Permission>
<Permission path={'/system/group'}>
<CommonCard icon={IconFatwebGroup} url={'group'}>
<CommonCard icon={IconOxygenGroup} url={'group'}>
</CommonCard>
</Permission>
<Permission path={'/system/log'}>
<CommonCard icon={IconFatwebLog} url={'log'}>
<CommonCard icon={IconOxygenLog} url={'log'}>
</CommonCard>
</Permission>