dark
7 months ago
6 changed files with 408 additions and 518 deletions
-
58src/App.tsx
-
87src/components/avatar/index.tsx
-
123src/pages/login/index.css
-
26src/pages/login/index.tsx
-
217src/request.ts
-
415src/routes.tsx
@ -1,51 +1,37 @@ |
|||||
import { AppContextProvider } from '@/context.ts' |
import { AppContextProvider } from '@/context.ts' |
||||
import { initI18n } from '@/i18n.ts' |
import { initI18n } from '@/i18n.ts' |
||||
import { appAtom, appStore, changeLanguage } from '@/store/system.ts' |
import { appAtom, appStore, changeLanguage } from '@/store/system.ts' |
||||
import { userMenuDataAtom } from '@/store/user.ts' |
|
||||
import { IAppData } from '@/global' |
import { IAppData } from '@/global' |
||||
import { ConfigProvider } from '@/components/config-provider' |
import { ConfigProvider } from '@/components/config-provider' |
||||
import { Provider, useAtom, useAtomValue } from 'jotai' |
|
||||
|
import { Provider, useAtom } from 'jotai' |
||||
import './App.css' |
import './App.css' |
||||
import { useEffect } from 'react' |
import { useEffect } from 'react' |
||||
import { RootProvider } from './routes.tsx' |
import { RootProvider } from './routes.tsx' |
||||
import PageLoading from '@/components/page-loading' |
|
||||
|
|
||||
|
|
||||
function App() { |
function App() { |
||||
|
|
||||
const [ appData, ] = useAtom(appAtom) |
|
||||
const { data = [], isLoading, isFetching, refetch } = useAtomValue(userMenuDataAtom) |
|
||||
|
|
||||
useEffect(() => { |
|
||||
initI18n() |
|
||||
}, []) |
|
||||
|
|
||||
|
|
||||
useEffect(() => { |
|
||||
if (appData.token) { |
|
||||
refetch().then() |
|
||||
} |
|
||||
}, [ appData.token ]) |
|
||||
|
|
||||
|
|
||||
if (isLoading || isFetching) { |
|
||||
return <PageLoading/> |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<ConfigProvider> |
|
||||
<AppContextProvider value={{ |
|
||||
get appData() { |
|
||||
return appData as IAppData |
|
||||
}, |
|
||||
changeLanguage |
|
||||
}}> |
|
||||
<Provider store={appStore}> |
|
||||
<RootProvider context={{ menuData: data }}/> |
|
||||
</Provider> |
|
||||
</AppContextProvider> |
|
||||
</ConfigProvider> |
|
||||
) |
|
||||
|
const [ appData, ] = useAtom(appAtom) |
||||
|
|
||||
|
useEffect(() => { |
||||
|
initI18n() |
||||
|
}, []) |
||||
|
|
||||
|
|
||||
|
return ( |
||||
|
<ConfigProvider> |
||||
|
<AppContextProvider value={{ |
||||
|
get appData() { |
||||
|
return appData as IAppData |
||||
|
}, |
||||
|
changeLanguage |
||||
|
}}> |
||||
|
<Provider store={appStore}> |
||||
|
<RootProvider context={{}}/> |
||||
|
</Provider> |
||||
|
</AppContextProvider> |
||||
|
</ConfigProvider> |
||||
|
) |
||||
} |
} |
||||
|
|
||||
export default App |
export default App |
@ -1,50 +1,63 @@ |
|||||
import Icon from '@/components/icon' |
import Icon from '@/components/icon' |
||||
import { useTranslation } from '@/i18n.ts' |
import { useTranslation } from '@/i18n.ts' |
||||
import { currentUserAtom } from '@/store/user.ts' |
|
||||
|
import { currentUserAtom, logoutAtom } from '@/store/user.ts' |
||||
import { Avatar as AntAvatar, Dropdown, Spin } from 'antd' |
import { Avatar as AntAvatar, Dropdown, Spin } from 'antd' |
||||
import { useAtomValue } from 'jotai' |
import { useAtomValue } from 'jotai' |
||||
|
import { useNavigate } from '@tanstack/react-router' |
||||
|
|
||||
const Avatar = () => { |
const Avatar = () => { |
||||
|
|
||||
const { t } = useTranslation() |
|
||||
const { data, isLoading } = useAtomValue(currentUserAtom) |
|
||||
|
const { t } = useTranslation() |
||||
|
const { data, isLoading } = useAtomValue(currentUserAtom) |
||||
|
const { mutate: logout } = useAtomValue(logoutAtom) |
||||
|
const navigate = useNavigate() |
||||
|
|
||||
return ( |
|
||||
<div> |
|
||||
<Dropdown |
|
||||
key={'user'} |
|
||||
placement="bottomRight" |
|
||||
menu={{ |
|
||||
items: [ |
|
||||
{ |
|
||||
key: 'logout', |
|
||||
icon: <Icon type={'park:Logout'}/>, |
|
||||
label: <span style={{ |
|
||||
marginInlineStart: 8, |
|
||||
userSelect: 'none' |
|
||||
}}>{t('app.header.logout')}</span>, |
|
||||
}, |
|
||||
], |
|
||||
}} |
|
||||
> |
|
||||
<Spin spinning={isLoading}> |
|
||||
<AntAvatar |
|
||||
key="avatar" |
|
||||
size={'small'} |
|
||||
src={data?.avatar || data?.nickname?.substring(0, 1)}> |
|
||||
{!data?.avatar && data?.nickname?.substring(0, 1)} |
|
||||
</AntAvatar> |
|
||||
<span key="name" |
|
||||
style={{ |
|
||||
marginInlineStart: 8, |
|
||||
userSelect: 'none' |
|
||||
}}> |
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Dropdown |
||||
|
key={'user'} |
||||
|
placement="bottomRight" |
||||
|
menu={{ |
||||
|
items: [ |
||||
|
{ |
||||
|
key: 'logout', |
||||
|
icon: <Icon type={'park:Logout'}/>, |
||||
|
label: <span style={{ |
||||
|
marginInlineStart: 8, |
||||
|
userSelect: 'none' |
||||
|
}}>{t('app.header.logout')}</span>, |
||||
|
}, |
||||
|
], |
||||
|
onClick: (e) => { |
||||
|
if (e.key === 'logout') { |
||||
|
logout() |
||||
|
navigate({ |
||||
|
to: '/login', search: { |
||||
|
redirect: window.location.pathname |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
}, |
||||
|
}} |
||||
|
> |
||||
|
<Spin spinning={isLoading}> |
||||
|
<AntAvatar |
||||
|
key="avatar" |
||||
|
size={'small'} |
||||
|
src={data?.avatar || data?.nickname?.substring(0, 1)}> |
||||
|
{!data?.avatar && data?.nickname?.substring(0, 1)} |
||||
|
</AntAvatar> |
||||
|
<span key="name" |
||||
|
style={{ |
||||
|
marginInlineStart: 8, |
||||
|
userSelect: 'none' |
||||
|
}}> |
||||
{data?.nickname} |
{data?.nickname} |
||||
</span> |
</span> |
||||
</Spin> |
|
||||
</Dropdown> |
|
||||
</div> |
|
||||
) |
|
||||
|
</Spin> |
||||
|
</Dropdown> |
||||
|
</div> |
||||
|
) |
||||
} |
} |
||||
|
|
||||
export default Avatar |
export default Avatar |
@ -1,123 +0,0 @@ |
|||||
body { |
|
||||
margin: 0; |
|
||||
padding: 0; |
|
||||
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif; |
|
||||
|
|
||||
overflow: hidden; |
|
||||
|
|
||||
.login-container { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
height: 100vh; |
|
||||
background-image: url("@/assets/login.png"); |
|
||||
background-repeat: no-repeat; |
|
||||
background-size: cover; |
|
||||
|
|
||||
|
|
||||
.language { |
|
||||
position: absolute; |
|
||||
top: 10px; |
|
||||
right: 10px; |
|
||||
color: #fff; |
|
||||
font-size: 14px; |
|
||||
cursor: pointer; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.loginBlock { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
padding: 40px 0; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
} |
|
||||
|
|
||||
.innerBlock { |
|
||||
width: 356px; |
|
||||
margin: 0 auto; |
|
||||
} |
|
||||
|
|
||||
.logo { |
|
||||
height: 30px; |
|
||||
} |
|
||||
|
|
||||
.infoLine { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: space-between; |
|
||||
margin: 0; |
|
||||
} |
|
||||
|
|
||||
.infoLeft { |
|
||||
color: #666; |
|
||||
font-size: 14px; |
|
||||
} |
|
||||
|
|
||||
.desc { |
|
||||
margin: 24px 0; |
|
||||
color: #999; |
|
||||
font-size: 16px; |
|
||||
cursor: pointer; |
|
||||
} |
|
||||
|
|
||||
.active { |
|
||||
color: #333; |
|
||||
font-weight: bold; |
|
||||
font-size: 24px; |
|
||||
} |
|
||||
|
|
||||
.line { |
|
||||
display: inline-block; |
|
||||
width: 1px; |
|
||||
height: 12px; |
|
||||
background: #999; |
|
||||
} |
|
||||
|
|
||||
.innerBeforeInput { |
|
||||
margin-left: 10px; |
|
||||
color: #999; |
|
||||
} |
|
||||
|
|
||||
.innerBeforeInput .line { |
|
||||
margin-left: 10px; |
|
||||
} |
|
||||
|
|
||||
.innerAfterInput { |
|
||||
margin-right: 10px; |
|
||||
color: #999; |
|
||||
} |
|
||||
|
|
||||
.innerAfterInput .line { |
|
||||
margin-right: 10px; |
|
||||
vertical-align: middle; |
|
||||
} |
|
||||
|
|
||||
.sendCode { |
|
||||
max-width: 65px; |
|
||||
margin-right: 10px; |
|
||||
} |
|
||||
|
|
||||
.otherLogin { |
|
||||
color: #666; |
|
||||
font-size: 14px; |
|
||||
} |
|
||||
|
|
||||
.icon { |
|
||||
margin-left: 10px; |
|
||||
} |
|
||||
|
|
||||
.link { |
|
||||
color: #5584ff; |
|
||||
font-size: 14px; |
|
||||
text-align: left; |
|
||||
} |
|
||||
|
|
||||
.submitBtn { |
|
||||
width: 100%; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue