This commit is contained in:
none 2023-03-23 17:29:43 +08:00
parent 9f90bd75d3
commit 89b6307e2d
16 changed files with 163 additions and 161 deletions

View File

@ -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}>

View File

@ -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");

View File

@ -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}

View File

@ -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";

View File

@ -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);

View File

@ -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;

View File

@ -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("/");
});

View File

@ -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 = () => {

View File

@ -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: "/",

View File

@ -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
View 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;

View File

@ -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;

View 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 };

View 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 };

View File

@ -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,
};
};

View File

@ -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;
}
};