mirror of
https://github.com/PlayEdu/backend
synced 2025-06-21 17:42:47 +08:00
重构
This commit is contained in:
parent
9f90bd75d3
commit
89b6307e2d
21
src/App.tsx
21
src/App.tsx
@ -2,32 +2,11 @@ import { Suspense } from "react";
|
||||
import styles from "./App.module.less";
|
||||
import { useRoutes } from "react-router-dom";
|
||||
import routes from "./routes";
|
||||
import { getToken } from "./utils/index";
|
||||
import { login } from "./api/index";
|
||||
import { useDispatch } from "react-redux";
|
||||
import {
|
||||
IsLoginActionCreator,
|
||||
SetUserActionCreator,
|
||||
SetPermisssionsActionCreator,
|
||||
} from "./store/user/userActions";
|
||||
import LoadingPage from "./pages/loading";
|
||||
|
||||
function App() {
|
||||
const Views = () => useRoutes(routes);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const getUser = () => {
|
||||
login.getUser().then((res: any) => {
|
||||
const data = res.data;
|
||||
dispatch(IsLoginActionCreator());
|
||||
dispatch(SetUserActionCreator(data.user));
|
||||
dispatch(SetPermisssionsActionCreator(data.permissions));
|
||||
});
|
||||
};
|
||||
if (getToken()) {
|
||||
getUser();
|
||||
}
|
||||
|
||||
return (
|
||||
<Suspense fallback={<LoadingPage />}>
|
||||
<div className={styles.App}>
|
||||
|
@ -1,19 +1,19 @@
|
||||
import React from "react";
|
||||
import styles from "./index.module.less";
|
||||
import { Button, Dropdown, MenuProps } from "antd";
|
||||
import { useSelector } from "../../store/hooks";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { LoginOutActionCreator } from "../../store/user/userActions";
|
||||
import avatar from "../../assets/images/commen/avatar.png";
|
||||
import { logoutAction } from "../../store/user/loginUserSlice";
|
||||
|
||||
export const Header: React.FC = () => {
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const user = useSelector((state: any) => state.user);
|
||||
const user = useSelector((state: any) => state.loginUser.value.user);
|
||||
|
||||
const onClick: MenuProps["onClick"] = ({ key }) => {
|
||||
if (key === "login_out") {
|
||||
dispatch(LoginOutActionCreator());
|
||||
dispatch(logoutAction());
|
||||
navigate("/login");
|
||||
} else if (key === "change_password") {
|
||||
navigate("/change-password");
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Button } from "antd";
|
||||
import { useSelector } from "../../store/hooks";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
interface PropInterface {
|
||||
type: "link" | "text" | "primary" | "default";
|
||||
@ -12,16 +12,18 @@ interface PropInterface {
|
||||
}
|
||||
|
||||
export const PerButton = (props: PropInterface) => {
|
||||
const permisssions = useSelector((state: any) => state.permisssions);
|
||||
const through = () => {
|
||||
if (!permisssions) {
|
||||
const permissions = useSelector(
|
||||
(state: any) => state.loginUser.value.permissions
|
||||
);
|
||||
const isThrough = () => {
|
||||
if (!permissions) {
|
||||
return false;
|
||||
}
|
||||
return typeof permisssions[props.p] !== "undefined";
|
||||
return typeof permissions[props.p] !== "undefined";
|
||||
};
|
||||
return (
|
||||
<>
|
||||
{through() && props.type === "link" && (
|
||||
{isThrough() && props.type === "link" && (
|
||||
<Button
|
||||
className={props.class}
|
||||
type="link"
|
||||
@ -35,7 +37,7 @@ export const PerButton = (props: PropInterface) => {
|
||||
{props.text}
|
||||
</Button>
|
||||
)}
|
||||
{through() && props.type !== "link" && (
|
||||
{isThrough() && props.type !== "link" && (
|
||||
<Button
|
||||
className={props.class}
|
||||
type={props.type}
|
||||
|
@ -4,7 +4,7 @@ import App from "./App";
|
||||
import reportWebVitals from "./reportWebVitals";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import { Provider } from "react-redux";
|
||||
import store from "./store/store";
|
||||
import store from "./store";
|
||||
import { ConfigProvider } from "antd";
|
||||
import zhCN from "antd/locale/zh_CN";
|
||||
|
||||
|
@ -7,8 +7,8 @@ import { PerButton } from "../../compenents";
|
||||
import type { DataNode, TreeProps } from "antd/es/tree";
|
||||
import { DepartmentCreate } from "./compenents/create";
|
||||
import { DepartmentUpdate } from "./compenents/update";
|
||||
import { useSelector } from "../../store/hooks";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
const { confirm } = Modal;
|
||||
|
||||
@ -20,7 +20,9 @@ interface Option {
|
||||
|
||||
const DepartmentPage = () => {
|
||||
const navigate = useNavigate();
|
||||
const permisssions = useSelector((state: any) => state.permisssions);
|
||||
const permissions = useSelector(
|
||||
(state: any) => state.loginUser.value.permissions
|
||||
);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const [treeData, setTreeData] = useState<any>([]);
|
||||
@ -36,15 +38,15 @@ const DepartmentPage = () => {
|
||||
};
|
||||
|
||||
const through = (p: string) => {
|
||||
if (!permisssions) {
|
||||
if (!permissions) {
|
||||
return false;
|
||||
}
|
||||
return typeof permisssions[p] !== "undefined";
|
||||
return typeof permissions[p] !== "undefined";
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getData();
|
||||
}, [refresh, permisssions]);
|
||||
}, [refresh, permissions]);
|
||||
|
||||
const getData = () => {
|
||||
setLoading(true);
|
||||
|
@ -1,7 +1,22 @@
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Outlet } from "react-router-dom";
|
||||
import { loginAction } from "../../store/user/loginUserSlice";
|
||||
|
||||
const InitPage = () => {
|
||||
return <><Outlet /></>
|
||||
interface Props {
|
||||
loginData: any | null;
|
||||
}
|
||||
|
||||
const InitPage = (props: Props) => {
|
||||
const dispatch = useDispatch();
|
||||
if (props.loginData) {
|
||||
dispatch(loginAction(props.loginData));
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Outlet />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default InitPage;
|
||||
|
@ -4,15 +4,11 @@ import { Spin, Input, Button, message } from "antd";
|
||||
import { login, system } from "../../api/index";
|
||||
import { setToken } from "../../utils/index";
|
||||
import { useDispatch } from "react-redux";
|
||||
import {
|
||||
IsLoginActionCreator,
|
||||
SetUserActionCreator,
|
||||
SetPermisssionsActionCreator,
|
||||
} from "../../store/user/userActions";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import banner from "../../assets/images/login/banner.png";
|
||||
import icon from "../../assets/images/login/icon.png";
|
||||
import "./login.less";
|
||||
import { loginAction } from "../../store/user/loginUserSlice";
|
||||
|
||||
const LoginPage = () => {
|
||||
const dispatch = useDispatch();
|
||||
@ -75,9 +71,7 @@ const LoginPage = () => {
|
||||
const getUser = () => {
|
||||
login.getUser().then((res: any) => {
|
||||
const data = res.data;
|
||||
dispatch(IsLoginActionCreator());
|
||||
dispatch(SetUserActionCreator(data.user));
|
||||
dispatch(SetPermisssionsActionCreator(data.permissions));
|
||||
dispatch(loginAction(data));
|
||||
setLoading(false);
|
||||
navigate("/");
|
||||
});
|
||||
|
@ -7,8 +7,8 @@ import { PerButton } from "../../../compenents";
|
||||
import type { DataNode, TreeProps } from "antd/es/tree";
|
||||
import { ResourceCategoryCreate } from "./compenents/create";
|
||||
import { ResourceCategoryUpdate } from "./compenents/update";
|
||||
import { useSelector } from "../../../store/hooks";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
const { confirm } = Modal;
|
||||
|
||||
@ -20,7 +20,9 @@ interface Option {
|
||||
|
||||
const ResourceCategoryPage = () => {
|
||||
const navigate = useNavigate();
|
||||
const permisssions = useSelector((state: any) => state.permisssions);
|
||||
const permissions = useSelector(
|
||||
(state: any) => state.loginUser.value.permissions
|
||||
);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const [treeData, setTreeData] = useState<any>([]);
|
||||
@ -32,17 +34,17 @@ const ResourceCategoryPage = () => {
|
||||
|
||||
useEffect(() => {
|
||||
getData();
|
||||
}, [refresh, permisssions]);
|
||||
}, [refresh, permissions]);
|
||||
|
||||
const onSelect = (selectedKeys: any, info: any) => {
|
||||
setSelectKey(selectedKeys);
|
||||
};
|
||||
|
||||
const through = (p: string) => {
|
||||
if (!permisssions) {
|
||||
if (!permissions) {
|
||||
return false;
|
||||
}
|
||||
return typeof permisssions[p] !== "undefined";
|
||||
return typeof permissions[p] !== "undefined";
|
||||
};
|
||||
|
||||
const getData = () => {
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { lazy } from "react";
|
||||
import { RouteObject } from "react-router-dom";
|
||||
import { login } from "../api";
|
||||
|
||||
import InitPage from "../pages/init";
|
||||
import { getToken } from "../utils";
|
||||
|
||||
// 异步加载页面
|
||||
const LoginPage = lazy(() => import("../pages/login"));
|
||||
const HomePage = lazy(() => import("../pages/home"));
|
||||
const DashboardPage = lazy(() => import("../pages/dashboard"));
|
||||
@ -24,10 +27,33 @@ const ResourceCategoryPage = lazy(
|
||||
const ResourceVideosPage = lazy(() => import("../pages/resource/videos"));
|
||||
const SystemConfigPage = lazy(() => import("../pages/system/config"));
|
||||
|
||||
let RootPage: any = null;
|
||||
if (getToken()) {
|
||||
RootPage = lazy(async () => {
|
||||
return new Promise<any>((resolve) => {
|
||||
let userLoginToken = getToken();
|
||||
if (!userLoginToken) {
|
||||
resolve({
|
||||
default: InitPage,
|
||||
});
|
||||
return;
|
||||
}
|
||||
login.getUser().then((res: any) => {
|
||||
resolve({
|
||||
default: <InitPage loginData={res.data} />,
|
||||
});
|
||||
});
|
||||
// todo token过期处理
|
||||
});
|
||||
});
|
||||
} else {
|
||||
RootPage = <InitPage loginData={null} />;
|
||||
}
|
||||
|
||||
const routes: RouteObject[] = [
|
||||
{
|
||||
path: "/",
|
||||
element: <InitPage />,
|
||||
element: RootPage,
|
||||
children: [
|
||||
{
|
||||
path: "/",
|
||||
|
@ -1,7 +0,0 @@
|
||||
import {
|
||||
useSelector as useReduxSelector,
|
||||
TypedUseSelectorHook,
|
||||
} from "react-redux";
|
||||
import { RootState } from "./store";
|
||||
|
||||
export const useSelector: TypedUseSelectorHook<RootState> = useReduxSelector;
|
12
src/store/index.ts
Normal file
12
src/store/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { configureStore } from "@reduxjs/toolkit";
|
||||
import systemConfigReducer from "./system/systemConfigSlice";
|
||||
import loginUserReducer from "./user/loginUserSlice";
|
||||
|
||||
const store = configureStore({
|
||||
reducer: {
|
||||
loginUser: loginUserReducer,
|
||||
systemConfig: systemConfigReducer,
|
||||
},
|
||||
});
|
||||
|
||||
export default store;
|
@ -1,7 +0,0 @@
|
||||
import { createStore, applyMiddleware } from "redux";
|
||||
import userReducer from "./user/userReducer";
|
||||
import thunk from "redux-thunk";
|
||||
|
||||
const store = createStore(userReducer, applyMiddleware(thunk));
|
||||
export type RootState = ReturnType<typeof store.getState>;
|
||||
export default store;
|
34
src/store/system/systemConfigSlice.ts
Normal file
34
src/store/system/systemConfigSlice.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
type SystemConfigStoreInterface = {
|
||||
systemApiUrl: string;
|
||||
systemPcUrl: string;
|
||||
systemH5Url: string;
|
||||
systemLogo: string;
|
||||
systemName: string;
|
||||
};
|
||||
|
||||
let defaultValue: SystemConfigStoreInterface = {
|
||||
systemApiUrl: "",
|
||||
systemPcUrl: "",
|
||||
systemH5Url: "",
|
||||
systemLogo: "",
|
||||
systemName: "",
|
||||
};
|
||||
|
||||
const systemConfigSlice = createSlice({
|
||||
name: "systemConfig",
|
||||
initialState: {
|
||||
value: defaultValue,
|
||||
},
|
||||
reducers: {
|
||||
saveConfigAction(stage, e) {
|
||||
stage.value = e.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default systemConfigSlice.reducer;
|
||||
export const { saveConfigAction } = systemConfigSlice.actions;
|
||||
|
||||
export type { SystemConfigStoreInterface };
|
42
src/store/user/loginUserSlice.ts
Normal file
42
src/store/user/loginUserSlice.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
type UserInterface = {
|
||||
id: number;
|
||||
name: string;
|
||||
email: string;
|
||||
};
|
||||
|
||||
type UserStoreInterface = {
|
||||
user: UserInterface | null;
|
||||
isLogin: boolean;
|
||||
permissions: string[];
|
||||
};
|
||||
|
||||
let defaultValue: UserStoreInterface = {
|
||||
user: null,
|
||||
isLogin: false,
|
||||
permissions: [],
|
||||
};
|
||||
|
||||
const loginUserSlice = createSlice({
|
||||
name: "loginUser",
|
||||
initialState: {
|
||||
value: defaultValue,
|
||||
},
|
||||
reducers: {
|
||||
loginAction(stage, e) {
|
||||
stage.value.user = e.payload.user;
|
||||
stage.value.permissions = e.payload.permissions;
|
||||
stage.value.isLogin = true;
|
||||
},
|
||||
logoutAction(stage) {
|
||||
stage.value.user = null;
|
||||
stage.value.isLogin = false;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default loginUserSlice.reducer;
|
||||
export const { loginAction, logoutAction } = loginUserSlice.actions;
|
||||
|
||||
export type { UserStoreInterface };
|
@ -1,59 +0,0 @@
|
||||
import { message } from "antd";
|
||||
|
||||
export const IS_LOGIN = "IS_LOGIN";
|
||||
export const LOGIN_OUT = "LOGIN_OUT";
|
||||
export const SET_USER = "SET_USER";
|
||||
export const SET_PERMISSSIONS = "SET_PERMISSSIONS";
|
||||
|
||||
interface IsLoginAction {
|
||||
type: typeof IS_LOGIN;
|
||||
}
|
||||
|
||||
interface LoginOutAction {
|
||||
type: typeof LOGIN_OUT;
|
||||
}
|
||||
|
||||
interface SetUserAction {
|
||||
type: typeof SET_USER;
|
||||
payload: any;
|
||||
}
|
||||
|
||||
interface SetPermisssionsAction {
|
||||
type: typeof SET_PERMISSSIONS;
|
||||
payload: any;
|
||||
}
|
||||
|
||||
export type UserLoginAction =
|
||||
| IsLoginAction
|
||||
| LoginOutAction
|
||||
| SetUserAction
|
||||
| SetPermisssionsAction;
|
||||
|
||||
export const IsLoginActionCreator = (): IsLoginAction => {
|
||||
return {
|
||||
type: IS_LOGIN,
|
||||
};
|
||||
};
|
||||
|
||||
export const LoginOutActionCreator = (): LoginOutAction => {
|
||||
message.success("已退出登录");
|
||||
return {
|
||||
type: LOGIN_OUT,
|
||||
};
|
||||
};
|
||||
|
||||
export const SetUserActionCreator = (data: any): SetUserAction => {
|
||||
return {
|
||||
type: SET_USER,
|
||||
payload: data,
|
||||
};
|
||||
};
|
||||
|
||||
export const SetPermisssionsActionCreator = (
|
||||
data: any
|
||||
): SetPermisssionsAction => {
|
||||
return {
|
||||
type: SET_PERMISSSIONS,
|
||||
payload: data,
|
||||
};
|
||||
};
|
@ -1,33 +0,0 @@
|
||||
import {
|
||||
UserLoginAction,
|
||||
IS_LOGIN,
|
||||
LOGIN_OUT,
|
||||
SET_USER,
|
||||
SET_PERMISSSIONS,
|
||||
} from "./userActions";
|
||||
|
||||
interface UserState {
|
||||
permisssions: any[];
|
||||
user: any[];
|
||||
isLogin: boolean;
|
||||
}
|
||||
export const defaultState: UserState = {
|
||||
isLogin: false,
|
||||
permisssions: [],
|
||||
user: [],
|
||||
};
|
||||
|
||||
export default (state = defaultState, action: UserLoginAction) => {
|
||||
switch (action.type) {
|
||||
case IS_LOGIN:
|
||||
return { ...state, isLogin: true };
|
||||
case LOGIN_OUT:
|
||||
return { ...state, isLogin: false, user: [], permisssions: [] };
|
||||
case SET_USER:
|
||||
return { ...state, user: action.payload };
|
||||
case SET_PERMISSSIONS:
|
||||
return { ...state, permisssions: action.payload };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user