Files
bishengWeb/src/App.tsx
zhangkai fb39b66431 1
2024-06-13 15:11:41 +08:00

224 lines
6.2 KiB
TypeScript

import uniqueId from "lodash-es/uniqueId";
import cloneDeep from "lodash-es/cloneDeep";
import { useContext, useEffect, useState } from "react";
import { RouterProvider, useSearchParams } from "react-router-dom";
import "reactflow/dist/style.css";
import "./App.css";
import ErrorAlert from "./alerts/error";
import NoticeAlert from "./alerts/notice";
import SuccessAlert from "./alerts/success";
import { Toaster } from "./components/bs-ui/toast";
import { alertContext } from "./contexts/alertContext";
import { locationContext } from "./contexts/locationContext";
import { userContext } from "./contexts/userContext";
import { LoginPage } from "./pages/login";
import router from "./routes";
import routesM from "./routesM";
import { useTranslation } from "react-i18next";
import i18next from "i18next";
// 是否为手机端
const ISMOBILE = function () {
let flag = navigator.userAgent.match(
/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
);
return flag;
};
export default function App() {
let { setCurrent, setShowSideBar, setIsStackedOpen } = useContext(locationContext);
// let location = useLocation();
useEffect(() => {
setCurrent(location.pathname.replace(/\/$/g, "").split("/"));
setShowSideBar(true);
setIsStackedOpen(true);
}, [setCurrent, setIsStackedOpen, setShowSideBar]);
const {
errorData,
errorOpen,
setErrorOpen,
noticeData,
noticeOpen,
setNoticeOpen,
successData,
successOpen,
setErrorData,
setSuccessOpen,
} = useContext(alertContext);
// Initialize state variable for the list of alerts
const [alertsList, setAlertsList] = useState<
Array<{
type: string;
data: { title: string; list?: Array<string>; link?: string };
id: string;
}>
>([]);
// Use effect hook to update alertsList when a new alert is added
useEffect(() => {
// If there is an error alert open with data, add it to the alertsList
if (errorOpen && errorData) {
if (
alertsList.length > 0 &&
JSON.stringify(alertsList[alertsList.length - 1].data) ===
JSON.stringify(errorData)
) {
return;
}
setErrorOpen(false);
setAlertsList((old) => {
let newAlertsList = [
...old,
{ type: "error", data: cloneDeep(errorData), id: uniqueId() },
];
return newAlertsList;
});
}
// If there is a notice alert open with data, add it to the alertsList
else if (noticeOpen && noticeData) {
if (
alertsList.length > 0 &&
JSON.stringify(alertsList[alertsList.length - 1].data) ===
JSON.stringify(noticeData)
) {
return;
}
setNoticeOpen(false);
setAlertsList((old) => {
let newAlertsList = [
...old,
{ type: "notice", data: cloneDeep(noticeData), id: uniqueId() },
];
return newAlertsList;
});
}
// If there is a success alert open with data, add it to the alertsList
else if (successOpen && successData) {
if (
alertsList.length > 0 &&
JSON.stringify(alertsList[alertsList.length - 1].data) ===
JSON.stringify(successData)
) {
return;
}
setSuccessOpen(false);
setAlertsList((old) => {
let newAlertsList = [
...old,
{ type: "success", data: cloneDeep(successData), id: uniqueId() },
];
return newAlertsList;
});
}
}, [
errorData,
errorOpen,
noticeData,
noticeOpen,
setErrorOpen,
setNoticeOpen,
setSuccessOpen,
successData,
successOpen,
]);
/**
* 暴露弹窗全局使用
**/
useEffect(() => {
window.errorAlerts = (errorList: string[]) => {
setAlertsList((old) => {
let newAlertsList = [
...old,
{ type: "error", data: { title: '', list: errorList }, id: uniqueId() },
];
return newAlertsList;
})
}
}, [])
const removeAlert = (id: string) => {
setAlertsList((prevAlertsList) =>
prevAlertsList.filter((alert) => alert.id !== id)
);
};
const { user, setUser } = useContext(userContext);
// 退出
useEffect(() => {
const handleKeyDown = (event) => {
if (event.ctrlKey && event.keyCode === 81) {
setUser(null)
localStorage.setItem('UUR_INFO', '')
}
};
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
};
}, []);
// i18n title
const { t } = useTranslation()
useEffect(() => {
document.title = t('title')
}, [t])
// init language
useEffect(() => {
const lang = user?.user_id ? localStorage.getItem('language-' + user.user_id) : null
if (lang) {
i18next.changeLanguage(lang)
}
}, [user])
// 免登录列表
const noAuthPages = ['chat']
const path = location.pathname.split('/')?.[1] || ''
return (
//need parent component with width and height
<div className="flex h-full flex-col">
{(user?.user_id || noAuthPages.includes(path)) ? <RouterProvider router={ISMOBILE()?routesM:router} />
: user ? <div className="loading"></div>
: <LoginPage></LoginPage>}
<div></div>
<div className="app-div" style={{ zIndex: 1000 }}>
{alertsList.map((alert) => (
<div key={alert.id}>
{alert.type === "error" ? (
<ErrorAlert
key={alert.id}
title={alert.data.title}
list={alert.data.list}
id={alert.id}
removeAlert={removeAlert}
/>
) : alert.type === "notice" ? (
<NoticeAlert
key={alert.id}
title={alert.data.title}
link={alert.data.link}
id={alert.id}
removeAlert={removeAlert}
/>
) : (
<SuccessAlert
key={alert.id}
title={alert.data.title}
id={alert.id}
removeAlert={removeAlert}
/>
)}
</div>
))}
</div>
{/* 新弹窗 */}
<Toaster></Toaster>
</div>
);
}