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

232 lines
7.0 KiB
React

import { Outlet, Link, useHref, useNavigate, useLocation, NavLink } from "react-router-dom";
import { useEffect, useState } from 'react';
import { observer } from "mobx-react";
import { toJS } from "mobx";
import { Layout, Menu, ConfigProvider, theme, Dropdown, Space, Row, Col, Badge, Typography, Modal, Input, Button, 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 { useStore } from "@/stores/StoreContext.js";
import * as config from "@/config";
import Language from "../i18n/LanguageSwitcher";
import { useTranslation } from 'react-i18next';
import i18n from '@/i18n/index';
import zhLocale from 'antd/locale/zh_CN';
import enLocale from 'antd/locale/en_US';
import 'dayjs/locale/zh-cn';
const { Header, Content, Footer } = Layout;
const { Title } = Typography;
// const { t } = useTranslation();
let items = [];
const useItemDefault = () => {
const [data, setData] = useState([]);
const { t, i18n } = useTranslation();
useEffect(() => {
const newData = [
{ label: <Link to='/account/change-password'>{t('loginAction.ChangePassword')}</Link>, key: '0' },
{ label: <Link to='/account/profile'>{t('loginAction.Profile')}</Link>, key: '1' },
{ type: 'divider' },
{ label: <Link to='/login?out'>{t('loginAction.Logout')}</Link>, key: '3' },
];
setData(newData);
}, [i18n.language]);
return data;
};
const useItemManager = () => {
const items_default = useItemDefault();
const [data, setData] = useState(items_default);
const { t, i18n } = useTranslation();
useEffect(() => {
const newData = [
{ label: <Link to='/account/change-password'>{t('loginAction.ChangePassword')}</Link>, key: '0' },
{ label: <Link to='/account/profile'>{t('loginAction.Profile')}</Link>, key: '1' },
{ type: 'divider' },
{ label: <Link to='/login?out'>{t('loginAction.Logout')}</Link>, key: '3' },
{ label: <Link to='/account/change-vendor'>{t('loginAction.ChangeVendor')}</Link>, key: '4' },
];
setData(newData);
}, [i18n.language]);
return data;
};
function App() {
const { t } = useTranslation();
const items_default = useItemDefault();
const item_manager = useItemManager();
const [password, setPassword] = useState('');
2 years ago
const { authStore, noticeStore } = useStore();
const { notification } = AntApp.useApp();
const login = toJS(authStore.login);
2 years ago
const { noticeUnRead } = noticeStore;
const href = useHref();
const loginToken = login.token;
const navigate = useNavigate();
const location = useLocation();
const arrManager = config.arrManager; // ["testzp","testzac","testycc","testlyj","testqqs","testjjh","testhn"];//特定账号加修改所属供应商的菜单 zp
if (arrManager.includes(authStore.login.username)){
items = item_manager;
}else{
items = items_default;
}
useEffect(() => {
if (href !== '/login' && isEmpty(loginToken)) {
navigate('/login');
}
}, [href]);
useEffect(() => {
window.gtag('event', 'page_view', { page_location: window.location.href });
}, [location]);
const onSubmit = () => {
authStore.valdateUserPassword(login.username, password)
.then(() => {
authStore.fetchUserDetail()
.catch(ex => {
notification.error({
message: `Notification`,
description: 'Failed to get user information.',
placement: 'top',
duration: 4,
});
});
})
.catch(ex => {
notification.error({
message: `Notification`,
description: ex.message,
placement: 'top',
duration: 4,
});
});
setPassword('');
};
const splitPath = href.split("/");
let defaultPath = "reservation";
if (splitPath.length > 1) {
defaultPath = splitPath[1];
}
const {
token: { colorBgContainer },
} = theme.useToken();
const [antdLng, setAntdLng] = useState(enLocale);
useEffect(() => {
setAntdLng(i18n.language === 'en' ? enLocale : zhLocale);
}, [i18n.language]);
return (
<ConfigProvider locale={antdLng}
theme={{
token: {
colorPrimary: "#00b96b",
},
algorithm: theme.defaultAlgorithm,
}}>
<AntApp>
<Modal
centered
closable={false}
maskClosable={false}
footer={null}
open={login.timeout}
>
<Title level={3}>{t('loginAction.LoginTimeout')}</Title>
<div>{t('loginAction.LoginTimeoutTip')}</div>
<Space direction="horizontal">
<Input.Password value={password}
onChange={(e) => setPassword(e.target.value)}
onPressEnter={() => onSubmit()}
addonBefore={login.username} />
<Button
onClick={() => onSubmit()}
>{t('common.Submit')}</Button></Space>
</Modal>
<Layout
style={{
minHeight: "100vh",
}}>
<Header className="header" style={{ position: "sticky", top: 0, zIndex: 1, width: "100%" }}>
2 years ago
<Row gutter={{ md: 24 }} justify="end" align="middle">
<Col span={16}>
<NavLink to="/">
<img src={AppLogo} className="logo" alt="App logo" />
</NavLink>
<Menu
theme="dark"
mode="horizontal"
selectedKeys={[defaultPath]}
items={[
{ key: "reservation", label: <Link to="/reservation/newest">{t('menu.Reservation')}</Link> },
{ key: "invoice", label: <Link to="/invoice">{t('menu.Invoice')}</Link> },
{ key: "feedback", label: <Link to="/feedback">{t('menu.Feedback')}</Link> },
// { key: "report", label: <Link to="/report">Report</Link> },
2 years ago
{
key: "notice",
label: (
<Link to="/notice">
{t('menu.Notice')}
2 years ago
{noticeUnRead ? <Badge dot /> : ""}
</Link>
),
},
]}
/>
</Col>
<Col span={4}>
2 years ago
<Title level={3} style={{ color: "white", marginBottom: "0", display: "flex", justifyContent: "end" }}>
{authStore.login.travelAgencyName}
</Title>
</Col>
<Col span={2}>
<Dropdown
menu={{
items,
}}
trigger={['click']}
>
<a onClick={e => e.preventDefault()}>
<Space>
{authStore.login.username}
<DownOutlined />
</Space>
</a>
</Dropdown>
</Col>
<Col span={2}>
<Language />
</Col>
</Row>
</Header>
<Content
style={{
padding: 24,
margin: 0,
minHeight: 280,
background: colorBgContainer,
}}>
<Outlet />
</Content>
<Footer></Footer>
</Layout>
</AntApp>
</ConfigProvider>
);
}
export default observer(App);