index.tsx 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. import React, {
  2. useCallback,
  3. useEffect,
  4. useMemo,
  5. useRef,
  6. useState,
  7. } from "react";
  8. import { CaretUpOutlined, CaretDownOutlined } from "@ant-design/icons";
  9. import styles from "./index.module.scss";
  10. import SpinLoding from "@/components/SpinLoding";
  11. import { Route, Switch, useLocation } from "react-router-dom";
  12. import AuthRoute from "@/components/AuthRoute";
  13. import classNames from "classnames";
  14. import history from "@/utils/history";
  15. import { Button, Form, Input, Modal, Popconfirm } from "antd";
  16. import { Base64 } from "js-base64";
  17. import encodeStr from "@/utils/pass";
  18. import { passWordEditAPI } from "@/store/action/layout";
  19. import { getTokenInfo, removeTokenInfo } from "@/utils/storage";
  20. import { useDispatch, useSelector } from "react-redux";
  21. import inco1 from "@/assets/img/inco1.png";
  22. import inco3 from "@/assets/img/inco3.png";
  23. import logonImg from "@/assets/img/logo-white.png";
  24. import { MessageFu } from "@/utils/message";
  25. import { RouterType } from "@/types";
  26. import { RootState } from "@/store";
  27. const NotFound = React.lazy(() => import("@/components/NotFound"));
  28. function Layout() {
  29. const dispatch = useDispatch();
  30. const listTemp = useMemo(() => {
  31. const arr: RouterType = [
  32. {
  33. id: 100,
  34. name: "分享管理",
  35. path: "/",
  36. Com: React.lazy(() => import("../A2Share")),
  37. inco: inco1,
  38. done: true,
  39. },
  40. ];
  41. return arr;
  42. }, []);
  43. // 从仓库中获取页面权限数据
  44. const authPageArr = useSelector(
  45. (state: RootState) => state.A0Layout.authPageArr
  46. );
  47. useEffect(() => {
  48. // 如果是超级管理员
  49. const userInfo = getTokenInfo().user;
  50. if (userInfo.isAdmin === 1) {
  51. listTemp.push({
  52. id: 300,
  53. name: "用户管理",
  54. path: "/user",
  55. Com: React.lazy(() => import("../A3User")),
  56. inco: inco3,
  57. done: true,
  58. });
  59. }
  60. }, [listTemp]);
  61. // 权限的数据和页面判断
  62. useEffect(() => {
  63. if (authPageArr && authPageArr.length) {
  64. authPageArr.forEach((v) => {
  65. if (v.authority) {
  66. listTemp.forEach((v2) => {
  67. if (v.id === v2.id) v2.done = true;
  68. });
  69. }
  70. });
  71. const newList = listTemp.filter((v) => v.done);
  72. setList(newList);
  73. }
  74. }, [authPageArr, listTemp]);
  75. const [list, setList] = useState(listTemp);
  76. // 进页面看看第一个页面有权限的是哪一个
  77. useEffect(() => {
  78. const userInfo = getTokenInfo().user;
  79. if (userInfo.isAdmin !== 1) {
  80. if (list[0] && list[0].id !== 100) history.replace(list[0].path);
  81. }
  82. }, [list]);
  83. // 进页面获取所有下拉信息和权限信息
  84. useEffect(() => {
  85. // dispatch(getDictListAPI());
  86. // dispatch(getPermissionsAPI());
  87. }, [dispatch]);
  88. // 点击跳转
  89. const pathCutFu = useCallback((path: string) => {
  90. history.push(path);
  91. }, []);
  92. // 当前路径选中的左侧菜单
  93. const location = useLocation();
  94. const [path, setPath] = useState("");
  95. useEffect(() => {
  96. const arr = location.pathname.split("/");
  97. let pathTemp = "/";
  98. if (arr[1]) pathTemp = "/" + arr[1];
  99. setPath(pathTemp);
  100. }, [location]);
  101. const userInfo = useMemo(() => {
  102. return getTokenInfo().user;
  103. }, []);
  104. // 修改密码相关
  105. const [open, setOpen] = useState(false);
  106. // 拿到新密码的输入框的值
  107. const oldPasswordValue = useRef("");
  108. const checkPassWord = (rule: any, value: any = "") => {
  109. if (value !== oldPasswordValue.current)
  110. return Promise.reject("新密码不一致!");
  111. else return Promise.resolve(value);
  112. };
  113. const onFinish = async (values: any) => {
  114. // 通过校验之后发送请求
  115. if (values.oldPassword === values.newPassword)
  116. return MessageFu.warning("新旧密码不能相同!");
  117. const obj = {
  118. oldPassword: encodeStr(Base64.encode(values.oldPassword)),
  119. newPassword: encodeStr(Base64.encode(values.newPassword)),
  120. };
  121. const res: any = await passWordEditAPI(obj);
  122. if (res.code === 0) {
  123. MessageFu.success("修改成功!");
  124. loginExit();
  125. }
  126. };
  127. // 点击退出登录
  128. const loginExit = () => {
  129. removeTokenInfo();
  130. history.push("/login");
  131. };
  132. return (
  133. <div className={styles.Layout}>
  134. <div className="top">
  135. <div className="iconBox">
  136. <img src={logonImg} alt="" />
  137. </div>
  138. <div className="layoutRightTop">
  139. {/* 用户相关 */}
  140. <div className="user">
  141. {userInfo.realName}
  142. <div className="userInco userInco1">
  143. <CaretUpOutlined />
  144. </div>
  145. <div className="userInco userInco2">
  146. <CaretDownOutlined />
  147. </div>
  148. <div className="userSet">
  149. <span onClick={() => setOpen(true)}>修改密码</span>
  150. <Popconfirm
  151. placement="bottom"
  152. title="确定退出吗?"
  153. okText="确定"
  154. cancelText="取消"
  155. onConfirm={loginExit}
  156. >
  157. 退出登录
  158. </Popconfirm>
  159. </div>
  160. </div>
  161. </div>
  162. </div>
  163. <div className="bottom">
  164. {/* 左边 */}
  165. <div className="layoutLeft">
  166. {/* 左边主体 */}
  167. <div className="layoutLeftMain">
  168. {list.map((v) => (
  169. <div
  170. hidden={!v.done}
  171. key={v.id}
  172. onClick={() => pathCutFu(v.path)}
  173. className={classNames(
  174. "mainBoxL2Row",
  175. v.path === path ? "active" : ""
  176. )}
  177. >
  178. <div className="txt">{v.name}</div>
  179. </div>
  180. ))}
  181. </div>
  182. </div>
  183. {/* 右边 */}
  184. <div className="layoutRight">
  185. {/* 右边主体 */}
  186. <div className="layoutRightMain">
  187. {/* 二级路由页面 */}
  188. <div className="mainBoxR">
  189. <React.Suspense fallback={<SpinLoding />}>
  190. <Switch>
  191. {list.map((v) => (
  192. <AuthRoute
  193. key={v.id}
  194. exact
  195. path={v.path}
  196. component={v.Com}
  197. />
  198. ))}
  199. <Route path="*" component={NotFound} />
  200. </Switch>
  201. </React.Suspense>
  202. </div>
  203. </div>
  204. </div>
  205. {/* 点击修改密码打开的对话框 */}
  206. <Modal
  207. destroyOnClose
  208. open={open}
  209. title="修改密码"
  210. onCancel={() => setOpen(false)}
  211. footer={
  212. [] // 设置footer为空,去掉 取消 确定默认按钮
  213. }
  214. >
  215. <Form
  216. name="basic"
  217. labelCol={{ span: 5 }}
  218. wrapperCol={{ span: 16 }}
  219. onFinish={onFinish}
  220. autoComplete="off"
  221. >
  222. <Form.Item
  223. label="旧密码"
  224. name="oldPassword"
  225. rules={[{ required: true, message: "不能为空!" }]}
  226. >
  227. <Input.Password maxLength={15} />
  228. </Form.Item>
  229. <Form.Item
  230. label="新密码"
  231. name="newPassword"
  232. rules={[
  233. { required: true, message: "不能为空!" },
  234. { min: 6, max: 15, message: "密码长度为6-15个字符!" },
  235. ]}
  236. >
  237. <Input.Password
  238. maxLength={15}
  239. onChange={(e) => (oldPasswordValue.current = e.target.value)}
  240. />
  241. </Form.Item>
  242. <Form.Item
  243. label="确定新密码"
  244. name="checkPass"
  245. rules={[{ validator: checkPassWord }]}
  246. >
  247. <Input.Password maxLength={15} />
  248. </Form.Item>
  249. <Form.Item wrapperCol={{ offset: 14, span: 16 }}>
  250. <Button onClick={() => setOpen(false)}>取消</Button>
  251. &emsp;
  252. <Button type="primary" htmlType="submit">
  253. 确定
  254. </Button>
  255. </Form.Item>
  256. </Form>
  257. </Modal>
  258. </div>
  259. </div>
  260. );
  261. }
  262. // 使用 React.memo 来优化组件,避免组件的无效更新,类似 类组件里面的PureComponent
  263. const MemoLayout = React.memo(Layout);
  264. export default MemoLayout;