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.
159 lines
5.8 KiB
JavaScript
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
|