You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
GHHub/src/views/App.jsx

159 lines
5.8 KiB
JavaScript

import { Outlet, Link, useHref, useNavigate, NavLink } from 'react-router-dom'
import { useEffect, useState } from 'react'
import { Layout, Menu, ConfigProvider, theme, Dropdown, FloatButton, Space, Row, Col, Badge, App as AntApp } from 'antd'
import { DownOutlined } from '@ant-design/icons'
import 'antd/dist/reset.css'
import AppLogo from '@/assets/logo-gh.png'
import { isEmpty } from '@/utils/commons'
import { useTranslation } from 'react-i18next'
import zhLocale from 'antd/locale/zh_CN'
import enLocale from 'antd/locale/en_US'
import 'dayjs/locale/zh-cn'
import { BugOutlined } from "@ant-design/icons"
import ErrorBoundary from '@/components/ErrorBoundary'
import { BUILD_VERSION, } from '@/config'
import useNoticeStore from '@/stores/Notice'
import useAuthStore from '@/stores/Auth'
import { useThemeContext } from '@/stores/ThemeContext'
import { usingStorage } from '@/hooks/usingStorage'
import { useDefaultLgc } from '@/i18n/LanguageSwitcher'
import { appendRequestParams } from '@/utils/request'
import { PERM_ACCOUNT_MANAGEMENT, PERM_ROLE_NEW, PERM_OVERSEA, PERM_AIR_TICKET, PERM_PRODUCTS_MANAGEMENT } from '@/config'
const { Header, Content, Footer } = Layout
function App() {
const { t, i18n } = useTranslation()
const { colorPrimary } = useThemeContext()
const [isPermitted, currentUser] = useAuthStore(
(state) => [state.isPermitted, state.currentUser])
const { loginToken } = usingStorage()
const { message, notification } = AntApp.useApp()
const noticeUnRead = useNoticeStore((state) => state.noticeUnRead)
const href = useHref()
const navigate = useNavigate()
const needToLogin = href !== '/login' && isEmpty(loginToken)
useEffect(() => {
if (needToLogin) {
navigate('/login')
}
}, [href])
const splitPath = href.split('/')
let defaultPath = 'notice'
if (splitPath.length > 1) {
defaultPath = splitPath[1]
}
const { language } = useDefaultLgc()
const [antdLng, setAntdLng] = useState(enLocale)
useEffect(() => {
setAntdLng(i18n.language === 'en' ? enLocale : zhLocale)
appendRequestParams('lgc', language)
}, [i18n.language])
const uploadLog = () => {
if (window.$pageSpy) {
window.$pageSpy.triggerPlugins('onOfflineLog', 'upload')
alert('Success.')
} else {
alert('Failure.')
}
}
return (
<ConfigProvider locale={antdLng}
theme={{
token: {
colorPrimary: colorPrimary,
// "sizeStep": 3,
// "sizeUnit": 3,
},
algorithm: theme.defaultAlgorithm,
}}>
<AntApp>
<FloatButton icon={<BugOutlined />} onClick={() => uploadLog()} />
<ErrorBoundary>
<Layout className='min-h-screen'>
<Header className='sticky top-0 z-10 w-full'>
<Row gutter={{ md: 24 }} justify='end' align='middle'>
<Col span={15}>
<NavLink to='/'>
<img src={AppLogo} className='float-left h-9 my-4 mr-6 ml-0 bg-white/30' alt='App logo' />
</NavLink>
<Menu
theme='dark'
mode='horizontal'
selectedKeys={[defaultPath]}
items={[
isPermitted(PERM_OVERSEA) ? { key: 'reservation', label: <Link to='/reservation/newest'>{t('menu.Reservation')}</Link> } : null,
isPermitted(PERM_OVERSEA) ? { key: 'invoice', label: <Link to='/invoice'>{t('menu.Invoice')}</Link> } : null,
isPermitted(PERM_OVERSEA) ? { key: 'feedback', label: <Link to='/feedback'>{t('menu.Feedback')}</Link> } : null,
isPermitted(PERM_OVERSEA) ? { key: 'report', label: <Link to='/report'>{t('menu.Report')}</Link> } : null,
isPermitted(PERM_AIR_TICKET) ? { key: 'airticket', label: <Link to='/airticket'>{t('menu.Airticket')}</Link> } : null,
isPermitted(PERM_PRODUCTS_MANAGEMENT) ? { key: 'products', label: <Link to='/products'>{t('menu.Products')}</Link> } : { key: 'products', label: <Link to='/products/edit'>{t('menu.Products')}</Link> },
{
key: 'notice',
label: (
<Link to='/notice'>
{t('menu.Notice')}
{noticeUnRead ? <Badge dot /> : ''}
</Link>
),
},
]}
/>
</Col>
<Col span={7}>
<h3 className='text-white mb-0 line-clamp-1 text-end'>
{currentUser?.travelAgencyName}
</h3>
</Col>
<Col span={2}>
<Dropdown
menu={{
items: [...[
{ label: <Link to='/account/change-password'>{t('ChangePassword')}</Link>, key: '0' },
{ label: <Link to='/account/profile'>{t('Profile')}</Link>, key: '1' },
isPermitted(PERM_ACCOUNT_MANAGEMENT) ? { label: <Link to='/account/management'>{t('account:accountList')}</Link>, key: '3' } : null,
isPermitted(PERM_ROLE_NEW) ? { label: <Link to='/account/role-list'>{t('account:roleList')}</Link>, key: '4' } : null,
{ type: 'divider' },
{ label: <Link to='/logout'>{t('Logout')}</Link>, key: '99' },
]
],
}}
trigger={['click']}
>
<a onClick={e => e.preventDefault()}>
<Space>
<div className='line-clamp-1'>{currentUser?.realname}</div>
<DownOutlined />
</Space>
</a>
</Dropdown>
</Col>
</Row>
</Header>
<Content className='p-6 m-0 min-h-72 bg-white'>
{needToLogin ? <>login...</> : <Outlet />}
</Content>
<Footer>China Highlights International Travel Service Co., LTD, Version: {BUILD_VERSION}</Footer>
</Layout>
</ErrorBoundary>
</AntApp>
</ConfigProvider>
)
}
export default App