shaogen1995 %!s(int64=2) %!d(string=hai) anos
pai
achega
0d6e9b8668

+ 13 - 0
houtai/src/pages/C1User/UserAdd/index.css

@@ -0,0 +1,13 @@
+.userAdd .ant-modal-close {
+  display: none;
+}
+.userAdd .userAddMain {
+  border-top: 1px solid #999999;
+  padding-top: 15px;
+  width: 100%;
+}
+.userAdd .userAddMain .passTit {
+  color: #ff4d4f;
+  font-size: 14px;
+  padding-left: 98px;
+}

+ 17 - 0
houtai/src/pages/C1User/UserAdd/index.less

@@ -0,0 +1,17 @@
+.userAdd {
+  .ant-modal-close {
+    display: none;
+  }
+
+  .userAddMain {
+    border-top: 1px solid #999999;
+    padding-top: 15px;
+    width: 100%;
+
+    .passTit {
+      color: #ff4d4f;
+      font-size: 14px;
+      padding-left: 98px;
+    }
+  }
+}

+ 151 - 0
houtai/src/pages/C1User/UserAdd/index.tsx

@@ -0,0 +1,151 @@
+import { RootState } from "@/store";
+import { getUserInfoByIdAPI, userSaveAPI } from "@/store/action/C1User";
+import { SaveUserType } from "@/types";
+import { MessageFu } from "@/utils/message";
+import { Button, Form, Input, Modal, Popconfirm, Select } from "antd";
+import React, { useCallback, useEffect, useRef } from "react";
+import { useSelector } from "react-redux";
+import "./index.css";
+
+type Props = {
+  id: any;
+  closePage: () => void;
+  upTableList: () => void;
+  addTableList: () => void;
+};
+
+function UserAdd({ id, closePage, upTableList, addTableList }: Props) {
+  // 设置表单初始数据(区分编辑和新增)
+  const FormBoxRef = useRef<any>({});
+
+  const getInfoInAPIFu = useCallback(async (id: number) => {
+    const res = await getUserInfoByIdAPI(id);
+    FormBoxRef.current.setFieldsValue(res.data);
+    console.log("是编辑,在这里发请求拿数据", res);
+  }, []);
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    // return MessageFu.warning("有表单不符号规则!");
+  }, []);
+
+  useEffect(() => {
+    if (id) getInfoInAPIFu(id);
+    else {
+      FormBoxRef.current.setFieldsValue({});
+    }
+  }, [getInfoInAPIFu, id]);
+
+  // 从仓库获取角色下拉列表信息
+  const roleList = useSelector(
+    (state: RootState) => state.userReducer.roleList
+  );
+
+  // 通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      const obj: SaveUserType = {
+        ...values,
+        id: id ? id : null,
+      };
+
+      const res: any = await userSaveAPI(obj);
+
+      if (res.code === 0) {
+        MessageFu.success(id ? "编辑成功!" : "新增成功!");
+        if (id) upTableList();
+        else addTableList();
+
+        closePage();
+      }
+      console.log("通过校验,点击确定");
+    },
+    [addTableList, closePage, id, upTableList]
+  );
+
+  return (
+    <Modal
+      wrapClassName="userAdd"
+      destroyOnClose
+      open={true}
+      title={id ? "编辑用户" : "新增用户"}
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className="userAddMain">
+        <Form
+          ref={FormBoxRef}
+          name="basic"
+          labelCol={{ span: 5 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete="off"
+        >
+          <Form.Item
+            label="账号名"
+            name="userName"
+            rules={[{ required: true, message: "请输入账号名!" }]}
+            getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+          >
+            <Input
+              disabled={id}
+              maxLength={15}
+              showCount
+              placeholder="请输入内容"
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="用户昵称"
+            name="nickName"
+            rules={[{ required: true, message: "请输入用户昵称!" }]}
+            getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+          >
+            <Input maxLength={8} showCount placeholder="请输入内容" />
+          </Form.Item>
+
+          <Form.Item
+            label="用户角色"
+            name="roleId"
+            rules={[{ required: true, message: "请选择角色!" }]}
+          >
+            <Select placeholder="请选择" options={roleList} />
+          </Form.Item>
+
+          <Form.Item
+            label="真实姓名"
+            name="realName"
+            rules={[{ required: true, message: "请输入真实姓名!" }]}
+            getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+          >
+            <Input maxLength={8} showCount placeholder="请输入内容" />
+          </Form.Item>
+
+          {id ? null : <div className="passTit">* 默认密码 123456</div>}
+
+          {/* 确定和取消按钮 */}
+          <br />
+          <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
+            <Button type="primary" htmlType="submit">
+              提交
+            </Button>
+            &emsp;
+            <Popconfirm
+              title="放弃编辑后,信息将不会保存!"
+              okText="放弃"
+              cancelText="取消"
+              onConfirm={closePage}
+            >
+              <Button>取消</Button>
+            </Popconfirm>
+          </Form.Item>
+        </Form>
+      </div>
+    </Modal>
+  );
+}
+
+const MemoUserAdd = React.memo(UserAdd);
+
+export default MemoUserAdd;

+ 30 - 3
houtai/src/pages/C1User/index.module.scss

@@ -1,5 +1,32 @@
-.User{
-  :global{
-    
+.User {
+  :global {
+    .selectBox {
+      border-radius: 10px;
+      padding: 20px 15px;
+      background-color: #fff;
+      display: flex;
+      .selectBoxRow{
+        margin-right: 30px;
+      }
+    }
+    .tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 20px;
+      height: calc(100% - 94px);
+      background-color: #fff;
+
+      .ant-table-body {
+        height: 620px;
+        overflow-y: auto !important;
+        overflow-y: overlay !important;
+
+        .ant-table-row {
+          .ant-table-cell {
+            padding: 10px;
+          }
+        }
+      }
+    }
   }
 }

+ 342 - 5
houtai/src/pages/C1User/index.tsx

@@ -1,12 +1,349 @@
-import React from "react";
+import { RootState } from "@/store";
+import {
+  getUserListAPI,
+  getUserRoleAPI,
+  userDisplayAPI,
+  userPassResetAPI,
+  userRemoveAPI,
+} from "@/store/action/C1User";
+import { UserTableAPIType, UserTableListType } from "@/types";
+import { MessageFu } from "@/utils/message";
+import { Input, DatePicker, Button, Table, Switch, Popconfirm } from "antd";
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import { useDispatch, useSelector } from "react-redux";
 import styles from "./index.module.scss";
- function User() {
-  
+import UserAdd from "./UserAdd";
+const { RangePicker } = DatePicker;
+
+function User() {
+  const dispatch = useDispatch();
+
+  const pageNumRef = useRef(1);
+  const pagePageRef = useRef(10);
+
+  // 顶部筛选
+  const [tableSelect, setTableSelect] = useState<UserTableAPIType>({
+    startTime: "",
+    endTime: "",
+    nickName: "",
+    pageNum: 1,
+    pageSize: 10,
+    realName: "",
+    searchKey: "",
+  });
+
+  // 进来用户管理页面获取角色的下拉列表
+  useEffect(() => {
+    dispatch(getUserRoleAPI());
+  }, [dispatch]);
+
+  // 封装发送请求的函数
+
+  const getList = useCallback(async () => {
+    const data = {
+      ...tableSelect,
+      pageNum: pageNumRef.current,
+    };
+    dispatch(getUserListAPI(data));
+  }, [dispatch, tableSelect]);
+
+  // 当前页码统一
+  useEffect(() => {
+    pageNumRef.current = tableSelect.pageNum;
+    pagePageRef.current = tableSelect.pageSize;
+  }, [tableSelect.pageNum, tableSelect.pageSize]);
+
+  // 防止发送了2次请求来对应页码
+
+  const getListRef = useRef(-1);
+
+  useEffect(() => {
+    clearTimeout(getListRef.current);
+    getListRef.current = window.setTimeout(() => {
+      getList();
+    }, 100);
+  }, [getList, tableSelect]);
+
+  // 用户昵称的输入
+  const nameTime = useRef(-1);
+  const nameChange = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>) => {
+      clearTimeout(nameTime.current);
+      nameTime.current = window.setTimeout(() => {
+        setTableSelect({
+          ...tableSelect,
+          nickName: e.target.value,
+          pageNum: 1,
+        });
+      }, 500);
+    },
+    [tableSelect]
+  );
+
+  // 真实姓名的输入
+  const realNameTime = useRef(-1);
+  const realNameChange = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>) => {
+      clearTimeout(realNameTime.current);
+      realNameTime.current = window.setTimeout(() => {
+        setTableSelect({
+          ...tableSelect,
+          realName: e.target.value,
+          pageNum: 1,
+        });
+      }, 500);
+    },
+    [tableSelect]
+  );
+
+  // 时间选择器改变
+  const timeChange = (date: any, dateString: any) => {
+    let startTime = "";
+    let endTime = "";
+    if (dateString[0] && dateString[1]) {
+      startTime = dateString[0] + " 00:00:00";
+      endTime = dateString[1] + " 23:59:59";
+    }
+    setTableSelect({ ...tableSelect, startTime, endTime, pageNum: 1 });
+  };
+
+  // 点击重置
+  const [inputKey, setInputKey] = useState(1);
+  const resetSelectFu = useCallback(() => {
+    // 把2个输入框和时间选择器清空
+    setInputKey(Date.now());
+    setTableSelect({
+      startTime: "",
+      endTime: "",
+      nickName: "",
+      pageNum: 1,
+      pageSize: 10,
+      realName: "",
+      searchKey: "",
+    });
+  }, []);
+
+  // 从仓库中获取表格数据
+  const tableInfo = useSelector(
+    (state: RootState) => state.userReducer.tableInfo
+  );
+
+  // 页码变化
+  const paginationChange = useCallback(
+    () => (pageNum: number, pageSize: number) => {
+      pageNumRef.current = pageNum;
+      pagePageRef.current = pageSize;
+      setTableSelect({ ...tableSelect, pageNum, pageSize });
+    },
+    [tableSelect]
+  );
+
+  // 切换表格中的启用停用状态
+  const isEnabledClickFu = useCallback(
+    async (val: boolean, id: number) => {
+      const isDisable = val ? 1 : 0;
+      const res: any = await userDisplayAPI(id, isDisable);
+      if (res.code === 0) getList();
+    },
+    [getList]
+  );
+
+  // 点击删除
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res: any = await userRemoveAPI(id);
+      if (res.code === 0) {
+        MessageFu.success("删除成功!");
+        getList();
+      }
+    },
+    [getList]
+  );
+
+  // 点击重置密码
+  const resetPassFu = useCallback(async (id: number) => {
+    const res: any = await userPassResetAPI(id);
+    if (res.code === 0) MessageFu.success("重置成功!");
+  }, []);
+
+  // 0------------点击新增或者编辑出来的页面
+  const [editPageShow, setEditPageShow] = useState(false);
+  const editId = useRef(0);
+
+  const openEditPageFu = useCallback(
+    (id: number) => {
+      if (id === 0 && tableInfo.list.length >= 50)
+        return MessageFu.warning("最多支持50个用户!");
+
+      editId.current = id;
+      setEditPageShow(true);
+    },
+    [tableInfo.list.length]
+  );
+
+  const columns = useMemo(() => {
+    return [
+      // {
+      //   width: 80,
+      //   title: "序号",
+      //   render: (text: any, record: any, index: any) =>
+      //     index + 1 + (pageNumRef.current - 1) * pagePageRef.current,
+      // },
+      {
+        title: "账号名",
+        dataIndex: "userName",
+      },
+      {
+        title: "用户昵称",
+        dataIndex: "nickName",
+      },
+      {
+        title: "用户角色",
+        dataIndex: "roleName",
+      },
+      {
+        title: "真实姓名",
+        dataIndex: "realName",
+      },
+      {
+        title: "注册时间",
+        dataIndex: "createTime",
+      },
+
+      {
+        title: "启用状态",
+        render: (item: UserTableListType) => (
+          <Switch
+            disabled={item.isAdmin === 1}
+            checkedChildren="启用"
+            unCheckedChildren="停用"
+            checked={item.isEnabled === 1}
+            onChange={(val) => isEnabledClickFu(val, item.id!)}
+          />
+        ),
+      },
+
+      {
+        title: "操作",
+        render: (item: UserTableListType) => {
+          return item.isAdmin === 1 ? (
+            "-"
+          ) : (
+            <>
+              <Popconfirm
+                title="密码重制后为123456,是否重置?"
+                okText="重置"
+                cancelText="取消"
+                onConfirm={() => resetPassFu(item.id!)}
+              >
+                <Button size="small" type="text">
+                  重置密码
+                </Button>
+              </Popconfirm>
+
+              <Button
+                size="small"
+                type="text"
+                onClick={() => openEditPageFu(item.id!)}
+              >
+                编辑
+              </Button>
+              <Popconfirm
+                title="删除后无法恢复,是否删除?"
+                okText="删除"
+                cancelText="取消"
+                onConfirm={() => delTableFu(item.id!)}
+              >
+                <Button size="small" type="text" danger>
+                  删除
+                </Button>
+              </Popconfirm>
+            </>
+          );
+        },
+      },
+    ];
+  }, [delTableFu, isEnabledClickFu, openEditPageFu, resetPassFu]);
+
   return (
     <div className={styles.User}>
-      <h1>User</h1>
+      <div className="userTop">
+        <div className="pageTitlt">用户管理</div>
+        <div className="selectBox">
+          <div className="selectBoxRow">
+            <span>用户昵称:</span>
+            <Input
+              key={inputKey}
+              maxLength={8}
+              style={{ width: 150 }}
+              placeholder="请输入"
+              allowClear
+              onChange={(e) => nameChange(e)}
+            />
+          </div>
+
+          <div className="selectBoxRow">
+            <span>真实姓名:</span>
+            <Input
+              key={inputKey}
+              maxLength={8}
+              style={{ width: 150 }}
+              placeholder="请输入"
+              allowClear
+              onChange={(e) => realNameChange(e)}
+            />
+          </div>
+
+          <div className="selectBoxRow">
+            <span>注册日期:</span>
+            <RangePicker key={inputKey} onChange={timeChange} />
+          </div>
+
+          <div className="selectBoxRow">
+            &emsp;&emsp;<Button onClick={resetSelectFu}>重置</Button>
+            &emsp;&emsp;
+            <Button type="primary" onClick={() => openEditPageFu(0)}>
+              新增
+            </Button>
+          </div>
+        </div>
+      </div>
+      {/* 表格主体 */}
+      <div className="tableBox">
+        <Table
+          scroll={{ y: 620 }}
+          dataSource={tableInfo.list}
+          columns={columns}
+          rowKey="id"
+          pagination={{
+            showQuickJumper: true,
+            position: ["bottomCenter"],
+            showSizeChanger: true,
+            current: tableSelect.pageNum,
+            pageSize: tableSelect.pageSize,
+            total: tableInfo.total,
+            onChange: paginationChange(),
+          }}
+        />
+      </div>
+
+      {/* 点击新增或者编辑 */}
+      {editPageShow ? (
+        <UserAdd
+          id={editId.current}
+          closePage={() => setEditPageShow(false)}
+          upTableList={getList}
+          addTableList={resetSelectFu}
+        />
+      ) : null}
     </div>
-  )
+  );
 }
 
 const MemoUser = React.memo(User);

+ 51 - 0
houtai/src/pages/C2Role/RoleAdd/index.css

@@ -0,0 +1,51 @@
+.roleAdd .ant-modal-close {
+  display: none;
+}
+.roleAdd .roleAddMain {
+  border-top: 1px solid #999999;
+  padding-top: 15px;
+  width: 100%;
+}
+.roleAdd .roleAddMain .row {
+  margin-bottom: 20px;
+  position: relative;
+  display: flex;
+  padding: 0 24px 0 0px;
+  text-align: right;
+}
+.roleAdd .roleAddMain .row .rowSpan {
+  display: inline-block;
+  width: 80px;
+  line-height: 32px;
+}
+.roleAdd .roleAddMain .row .rowSpan > span {
+  position: relative;
+  top: 2px;
+  color: #ff4d4f;
+}
+.roleAdd .roleAddMain .row .bs::before {
+  content: '*';
+  position: absolute;
+  top: 2px;
+  left: 1px;
+  z-index: 10;
+  color: #ff4d4f;
+}
+.roleAdd .roleAddMain .row .inputBox {
+  width: calc(100% - 90px);
+}
+.roleAdd .roleAddMain .row .inputBoxCheck {
+  width: 155px;
+}
+.roleAdd .roleAddMain .row .inputBoxCheck .rowCheck {
+  display: block;
+  display: flex;
+  margin-left: 4px;
+  margin-top: 5px;
+}
+.roleAdd .roleAddMain .roleAddButton {
+  text-align: center;
+}
+.roleAdd .lookRole .row {
+  pointer-events: none;
+}

+ 67 - 0
houtai/src/pages/C2Role/RoleAdd/index.less

@@ -0,0 +1,67 @@
+.roleAdd {
+  .ant-modal-close {
+    display: none;
+  }
+
+  .roleAddMain {
+    border-top: 1px solid #999999;
+    padding-top: 15px;
+    width: 100%;
+
+    .row {
+      margin-bottom: 20px;
+      position: relative;
+      display: flex;
+      padding: 0 24px 0 0px;
+      text-align: right;
+
+      .rowSpan {
+        display: inline-block;
+        width: 80px;
+        line-height: 32px;
+        &>span{
+          position: relative;
+          top: 2px;
+          color: #ff4d4f;
+        }
+      }
+
+      .bs {
+        &::before {
+          content: '*';
+          position: absolute;
+          top: 2px;
+          left: 1px;
+          z-index: 10;
+          color: #ff4d4f;
+        }
+      }
+
+      .inputBox {
+        width: calc(100% - 90px);
+
+      }
+
+      .inputBoxCheck {
+        width: 155px;
+
+        .rowCheck {
+          display: block;
+          display: flex;
+          margin-left: 4px;
+          margin-top: 5px;
+        }
+      }
+    }
+
+    .roleAddButton {
+      text-align: center;
+    }
+  }
+
+  .lookRole {
+    .row {
+      pointer-events: none;
+    }
+  }
+}

+ 214 - 0
houtai/src/pages/C2Role/RoleAdd/index.tsx

@@ -0,0 +1,214 @@
+import { getRoleInfoByIdAPI, roleSaveAPI } from "@/store/action/C2Role";
+
+import { Button, Checkbox, Input, Modal, Popconfirm } from "antd";
+import React, { useCallback, useEffect, useState } from "react";
+import classNames from "classnames";
+import "./index.css";
+import { AddRoleType, PermissionsAPIType, RoleTableType } from "@/types";
+import { MessageFu } from "@/utils/message";
+const { TextArea } = Input;
+
+type Props = {
+  id: any;
+  closePage: () => void;
+  upTableList: () => void;
+  addTableList: () => void;
+};
+
+function RoleAdd({ id, closePage, upTableList, addTableList }: Props) {
+  // 角色名称
+  const [roleName, setRoleName] = useState("");
+
+  // 角色描述
+  const [roleDesc, setRoleDesc] = useState("");
+
+  // 页面权限的选择
+  const [list, setList] = useState<PermissionsAPIType[]>([
+    {
+      id: 100,
+      name: "数据统计",
+      authority: true,
+      children: [{ id: 110, name: "热度统计", authority: true }],
+    },
+    {
+      id: 200,
+      name: "内容管理",
+      authority: true,
+      children: [
+        { id: 220, name: "场景管理", authority: true },
+        { id: 230, name: "馆藏管理", authority: true },
+        { id: 240, name: "万物墙管理", authority: true },
+        { id: 250, name: "弹幕管理", authority: true },
+        { id: 260, name: "题库管理", authority: true },
+        { id: 270, name: "智能导览管理", authority: true },
+      ],
+    },
+  ]);
+
+  const checkChangeFu = useCallback(
+    (checked: boolean, id: number) => {
+      const newList = [...list];
+      newList.forEach((v1) => {
+        v1.children?.forEach((v2) => {
+          if (v2.id === id) v2.authority = checked;
+        });
+      });
+
+      setList(newList);
+    },
+    [list]
+  );
+
+  const getRoleInfoByIdFu = useCallback(async (id: number) => {
+    const res = await getRoleInfoByIdAPI(id);
+    const info: RoleTableType = res.data.role;
+    const authPageArr: PermissionsAPIType[] = res.data.permission;
+    setRoleName(info.roleName);
+    setRoleDesc(info.roleDesc);
+    setList(authPageArr);
+  }, []);
+  // 如果是编辑
+  useEffect(() => {
+    if (id) getRoleInfoByIdFu(id);
+  }, [getRoleInfoByIdFu, id]);
+
+  // 点击提交
+  const btnOkFu = useCallback(async () => {
+    if (roleName === "") return MessageFu.warning("请输入角色名称!");
+
+    let temp1 = true;
+
+    const resources: number[] = [];
+
+    list.forEach((v1) => {
+      v1.children?.forEach((v2) => {
+        if (v2.authority) {
+          temp1 = false;
+          resources.push(v2.id);
+        }
+      });
+    });
+
+    if (temp1) return MessageFu.warning("至少勾选一个页面权限!");
+
+    const obj: AddRoleType = {
+      id: id ? id : null,
+      resources,
+      roleDesc: roleDesc,
+      roleName: roleName,
+    };
+    const res: any = await roleSaveAPI(obj);
+
+    if (res.code === 0) {
+      MessageFu.success(id ? "编辑成功!" : "新增成功!");
+      closePage();
+      if (id) addTableList();
+      else upTableList();
+    }
+  }, [addTableList, closePage, id, list, roleDesc, roleName, upTableList]);
+
+  return (
+    <Modal
+      wrapClassName="roleAdd"
+      destroyOnClose
+      open={true}
+      title={id ? (id === 1 ? "查看角色" : "编辑角色") : "新增角色"}
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className={classNames("roleAddMain", id === 1 ? "lookRole" : "")}>
+        <div className="row">
+          <span className="bs rowSpan">角色名称:</span>
+          <div className="inputBox">
+            <Input
+              maxLength={8}
+              value={roleName}
+              onChange={(e) => setRoleName(e.target.value.replace(/\s+/g, ""))}
+              showCount
+              placeholder="请输入内容"
+            />
+          </div>
+        </div>
+
+        <div className="row">
+          <span className="rowSpan">角色描述:</span>
+          <div className="inputBox">
+            <TextArea
+              rows={4}
+              placeholder="请输入内容"
+              maxLength={100}
+              showCount
+              value={roleDesc}
+              onChange={(e) => setRoleDesc(e.target.value.replace(/\s+/g, ""))}
+            />
+          </div>
+        </div>
+
+        {list.map((v1) => (
+          <div className="row" key={v1.id}>
+            <span className="rowSpan">
+              <span>*</span> {v1.name}:
+            </span>
+            <div className="inputBox inputBoxCheck">
+              {v1.children!.map((v2) => (
+                <Checkbox
+                  className="rowCheck"
+                  key={v2.id}
+                  checked={v2.authority}
+                  onChange={(e) => checkChangeFu(e.target.checked, v2.id)}
+                >
+                  {v2.name}
+                </Checkbox>
+              ))}
+            </div>
+          </div>
+        ))}
+
+        {id === 1 ? (
+          <div className="row">
+            <span className="rowSpan">
+              <span>*</span>系统管理:
+            </span>
+            <div className="inputBox inputBoxCheck">
+              <Checkbox className="rowCheck" defaultChecked={true}>
+                用户管理
+              </Checkbox>
+              <Checkbox className="rowCheck" defaultChecked={true}>
+                角色管理
+              </Checkbox>
+              <Checkbox className="rowCheck" defaultChecked={true}>
+                操作日志
+              </Checkbox>
+            </div>
+          </div>
+        ) : null}
+
+        <div className="roleAddButton">
+          {id !== 1 ? (
+            <>
+              <Button type="primary" onClick={btnOkFu}>
+                提交
+              </Button>
+              &emsp;
+              <Popconfirm
+                title="放弃编辑后,信息将不会保存!"
+                okText="放弃"
+                cancelText="取消"
+                onConfirm={closePage}
+              >
+                <Button>取消</Button>
+              </Popconfirm>
+            </>
+          ) : (
+            <Button onClick={closePage}>关闭</Button>
+          )}
+        </div>
+      </div>
+    </Modal>
+  );
+}
+
+const MemoRoleAdd = React.memo(RoleAdd);
+
+export default MemoRoleAdd;

+ 28 - 1
houtai/src/pages/C2Role/index.module.scss

@@ -1,5 +1,32 @@
 .Role{
   :global{
-    
+    .searchTop{
+      border-radius: 10px;
+      padding: 20px 15px;
+      background-color: #fff;
+      display: flex;
+      .searchTopRow{
+        margin-right: 30px;
+      }
+    }
+        .tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 20px;
+      height: calc(100% - 94px);
+      background-color: #fff;
+
+      .ant-table-body {
+        height: 620px;
+        overflow-y: auto !important;
+        overflow-y: overlay !important;
+
+        .ant-table-row {
+          .ant-table-cell {
+            padding: 10px;
+          }
+        }
+      }
+    }
   }
 }

+ 228 - 5
houtai/src/pages/C2Role/index.tsx

@@ -1,12 +1,235 @@
-import React from "react";
+import { RootState } from "@/store";
+import {
+  getRoleListAPI,
+  roleDisplayAPI,
+  roleRemoveAPI,
+} from "@/store/action/C2Role";
+import { RoleTableType } from "@/types";
+import { MessageFu } from "@/utils/message";
+import { Button, Input, Popconfirm, Switch, Table } from "antd";
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import { useDispatch, useSelector } from "react-redux";
 import styles from "./index.module.scss";
- function Role() {
-  
+import RoleAdd from "./RoleAdd";
+function Role() {
+  const dispatch = useDispatch();
+
+  // 顶部筛选
+
+  type TableListType = {
+    pageNum: number;
+    pageSize: number;
+    searchKey: string;
+  };
+
+  const [tableSelect, setTableSelect] = useState<TableListType>({
+    pageNum: 1,
+    pageSize: 10,
+    searchKey: "",
+  });
+
+  useEffect(() => {
+    dispatch(getRoleListAPI(tableSelect));
+  }, [dispatch, tableSelect]);
+
+  // 角色名的输入
+  const nameTime = useRef(-1);
+  const nameChange = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>) => {
+      clearTimeout(nameTime.current);
+      nameTime.current = window.setTimeout(() => {
+        setTableSelect({
+          ...tableSelect,
+          searchKey: e.target.value,
+          pageNum: 1,
+        });
+      }, 500);
+    },
+    [tableSelect]
+  );
+
+  // 角色名的重置
+  const [inputKey, setInputKey] = useState(1);
+  const resetSelectFu = useCallback(() => {
+    // 把2个输入框和时间选择器清空
+    setInputKey(Date.now());
+    setTableSelect({
+      pageNum: 1,
+      pageSize: 10,
+      searchKey: "",
+    });
+  }, []);
+
+  // 切换表格中的启用停用状态
+  const isEnabledClickFu = useCallback(
+    async (val: boolean, id: number) => {
+      const isDisable = val ? 1 : 0;
+      const res: any = await roleDisplayAPI(id, isDisable);
+      if (res.code === 0) dispatch(getRoleListAPI(tableSelect));
+    },
+    [dispatch, tableSelect]
+  );
+
+  // 点击删除
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res: any = await roleRemoveAPI(id);
+      if (res.code === 0) {
+        MessageFu.success("删除成功!");
+        dispatch(getRoleListAPI(tableSelect));
+      }
+    },
+    [dispatch, tableSelect]
+  );
+
+  // 点击新增和编辑
+  const [editPageShow, setEditPageShow] = useState(false);
+  const editId = useRef(0);
+  const openEditPageFu = useCallback((id: number) => {
+    editId.current = id;
+    setEditPageShow(true);
+  }, []);
+
+  // 从仓库中获取表格数据
+  const tableInfo = useSelector(
+    (state: RootState) => state.RoleReducer.tableInfo
+  );
+
+  // 页码变化
+  const paginationChange = useCallback(
+    () => (pageNum: number, pageSize: number) => {
+      setTableSelect({ ...tableSelect, pageNum, pageSize });
+    },
+    [tableSelect]
+  );
+
+  const columns = useMemo(() => {
+    return [
+      // {
+      //   width: 80,
+      //   title: "序号",
+      //   render: (text: any, record: any, index: any) =>
+      //     index + 1 + (pageNumRef.current - 1) * pagePageRef.current,
+      // },
+      {
+        title: "角色名称",
+        dataIndex: "roleName",
+      },
+      {
+        title: "角色描述",
+        render: (item: RoleTableType) =>
+          item.roleDesc ? item.roleDesc : "(空)",
+      },
+      {
+        title: "成员数量",
+        dataIndex: "count",
+      },
+      {
+        title: "最后编辑时间",
+        dataIndex: "updateTime",
+      },
+
+      {
+        title: "启用状态",
+        render: (item: RoleTableType) => (
+          <Switch
+            disabled={item.roleKey === "sys_admin"}
+            checkedChildren="启用"
+            unCheckedChildren="停用"
+            checked={item.isEnabled === 1}
+            onChange={(val) => isEnabledClickFu(val, item.id!)}
+          />
+        ),
+      },
+
+      {
+        title: "操作",
+        render: (item: RoleTableType) => {
+          return (
+            <>
+              <Button
+                size="small"
+                type="text"
+                onClick={() => openEditPageFu(item.id!)}
+              >
+                {item.roleKey === "sys_admin" ? "查看" : "编辑"}
+              </Button>
+              {item.roleKey !== "sys_admin" ? (
+                <Popconfirm
+                  title="删除后无法恢复,是否删除?"
+                  okText="删除"
+                  cancelText="取消"
+                  onConfirm={() => delTableFu(item.id!)}
+                >
+                  <Button size="small" type="text" danger>
+                    删除
+                  </Button>
+                </Popconfirm>
+              ) : null}
+            </>
+          );
+        },
+      },
+    ];
+  }, [delTableFu, isEnabledClickFu, openEditPageFu]);
+
   return (
     <div className={styles.Role}>
-      <h1>Role</h1>
+      <div className="pageTitlt">角色管理</div>
+      <div className="searchTop">
+        <div className="searchTopRow">
+          <span>角色名:</span>
+          <Input
+            key={inputKey}
+            maxLength={8}
+            style={{ width: 200 }}
+            placeholder="请输入"
+            allowClear
+            onChange={(e) => nameChange(e)}
+          />
+        </div>
+        <div className="searchTopRow">
+          &emsp;&emsp;
+          <Button type="primary" onClick={() => openEditPageFu(0)}>
+            新增
+          </Button>
+        </div>
+      </div>
+
+      <div className="tableBox">
+        <Table
+          scroll={{ y: 620 }}
+          dataSource={tableInfo.list}
+          columns={columns}
+          rowKey="id"
+          pagination={{
+            showQuickJumper: true,
+            position: ["bottomCenter"],
+            showSizeChanger: true,
+            current: tableSelect.pageNum,
+            pageSize: tableSelect.pageSize,
+            total: tableInfo.total,
+            onChange: paginationChange(),
+          }}
+        />
+      </div>
+      {/* 点击新增或者编辑 */}
+      {editPageShow ? (
+        <RoleAdd
+          id={editId.current}
+          closePage={() => setEditPageShow(false)}
+          upTableList={() => dispatch(getRoleListAPI(tableSelect))}
+          addTableList={resetSelectFu}
+        />
+      ) : null}
     </div>
-  )
+  );
 }
 
 const MemoRole = React.memo(Role);

+ 2 - 1
houtai/src/pages/Layout/index.tsx

@@ -26,6 +26,7 @@ import { MessageFu } from "@/utils/message";
 import logoImg from "@/assets/img/logo.png";
 import { barrageGetUnauditedAPI } from "@/store/action/B4Barrage";
 import { RootState } from "@/store";
+import { getPermissionsAPI } from "@/store/action/C2Role";
 
 function Layout() {
   const dispatch = useDispatch();
@@ -181,7 +182,7 @@ function Layout() {
   // 进页面获取所有下拉信息和权限信息
   useEffect(() => {
     dispatch(getDictListAPI());
-    // dispatch(getPermissionsAPI());
+    dispatch(getPermissionsAPI());
   }, [dispatch]);
 
   // 点击跳转

+ 64 - 0
houtai/src/store/action/C1User.ts

@@ -0,0 +1,64 @@
+import { RoleTableType, SaveUserType, UserTableAPIType } from "@/types";
+import http from "@/utils/http";
+import { AppDispatch } from "..";
+/**
+ * 获取用户管理表格列表
+ */
+export const getUserListAPI = (data: UserTableAPIType) => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post("sys/user/list", data);
+    const obj = {
+      list: res.data.records,
+      total: res.data.total,
+    };
+
+    dispatch({ type: "user/getList", payload: obj });
+  };
+};
+
+/**
+ * 获取用户管理-角色列表
+ */
+export const getUserRoleAPI = () => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.get("sys/user/getRole");
+    const data: RoleTableType[] = res.data;
+    const newData = data.map((v) => ({ label: v.roleName, value: v.id }));
+    dispatch({ type: "user/getRoleList", payload: newData });
+  };
+};
+
+/**
+ * 用户-是否显示
+ */
+export const userDisplayAPI = (id: number, display: number) => {
+  return http.get(`sys/user/editStatus/${id}/${display}`);
+};
+
+/**
+ * 删除用户
+ */
+export const userRemoveAPI = (id: number) => {
+  return http.get(`sys/user/removes/${id}`);
+};
+
+/**
+ * 重置密码
+ */
+export const userPassResetAPI = (id: number) => {
+  return http.get(`sys/user/resetPass/${id}`);
+};
+
+/**
+ * 新增/修改用户信息
+ */
+export const userSaveAPI = (data: SaveUserType) => {
+  return http.post("sys/user/save", data);
+};
+
+/**
+ * 通过id获取角色详情
+ */
+export const getUserInfoByIdAPI = (id: number) => {
+  return http.get(`sys/user/detail/${id}`);
+};

+ 56 - 0
houtai/src/store/action/C2Role.ts

@@ -0,0 +1,56 @@
+import { AddRoleType } from "@/types";
+import http from "@/utils/http";
+import { AppDispatch } from "..";
+/**
+ * 获取角色表格列表数据
+ */
+export const getRoleListAPI = (data: any) => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post("sys/role/listCountPage", data);
+
+    const obj = {
+      list: res.data.records,
+      total: res.data.total,
+    };
+
+    dispatch({ type: "Role/getList", payload: obj });
+  };
+};
+
+/**
+ * 删除角色
+ */
+export const roleRemoveAPI = (id: number) => {
+  return http.get(`sys/role/remove/${id}`);
+};
+
+/**
+ * 用户-是否显示
+ */
+export const roleDisplayAPI = (id: number, display: number) => {
+  return http.get(`sys/role/editStatus/${id}/${display}`);
+};
+
+/**
+ * 获取用户的权限信息
+ */
+export const getPermissionsAPI = () => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.get("sys/resource/getTreePermissions");
+    dispatch({ type: "login/setAuthPageArr", payload: res.data });
+  };
+};
+
+/**
+ * 新增或修改角色
+ */
+export const roleSaveAPI = (data: AddRoleType) => {
+  return http.post("sys/role/save", data);
+};
+
+/**
+ * 通过id获取角色详情
+ */
+export const getRoleInfoByIdAPI = (id: number) => {
+  return http.get(`sys/role/detail/${id}`);
+};

+ 44 - 0
houtai/src/store/reducer/C1User.ts

@@ -0,0 +1,44 @@
+import { UserTableListType } from "@/types";
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: {
+    list: [] as UserTableListType[],
+    total: 0,
+  },
+  // 角色列表数据
+  roleList: [] as {
+    label: string;
+    value: number;
+  }[],
+};
+
+// 定义 action 类型
+type UserActionType =
+  | {
+      type: "user/getList";
+      payload: { list: UserTableListType[]; total: number };
+    }
+  | {
+      type: "user/getRoleList";
+      payload: {
+        label: string;
+        value: number;
+      }[];
+    };
+
+// 频道 reducer
+export default function userReducer(state = initState, action: UserActionType) {
+  switch (action.type) {
+    // 获取列表数据
+    case "user/getList":
+      return { ...state, tableInfo: action.payload };
+    // 获取角色列表数据
+    case "user/getRoleList":
+      return { ...state, roleList: action.payload };
+
+    default:
+      return state;
+  }
+}

+ 27 - 0
houtai/src/store/reducer/C2Role.ts

@@ -0,0 +1,27 @@
+import { RoleTableType } from "@/types";
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: {
+    list: [] as RoleTableType[],
+    total: 0,
+  },
+};
+
+// 定义 action 类型
+type RoleActionType = {
+  type: "Role/getList";
+  payload: { list: RoleTableType[]; total: number };
+};
+
+// 频道 reducer
+export default function RoleReducer(state = initState, action: RoleActionType) {
+  switch (action.type) {
+    // 获取列表数据
+    case "Role/getList":
+      return { ...state, tableInfo: action.payload };
+    default:
+      return state;
+  }
+}

+ 5 - 1
houtai/src/store/reducer/index.ts

@@ -5,6 +5,8 @@ import wallReducer from './B3Wall'
 import barrageReducer from './B4Barrage'
 import topicReducer from './B5Topic'
 import smartReducer from './B6Smart'
+import userReducer from './C1User'
+import RoleReducer from './C2Role'
 import logReducer from './C3log'
 
 // 导入 登录 模块的 reducer
@@ -18,7 +20,9 @@ const rootReducer = combineReducers({
   wallReducer:wallReducer,
   barrageReducer:barrageReducer,
   smartReducer:smartReducer,
-  topicReducer:topicReducer
+  topicReducer:topicReducer,
+  userReducer:userReducer,
+  RoleReducer:RoleReducer
 })
 
 // 默认导出

+ 7 - 1
houtai/src/store/reducer/login.ts

@@ -1,4 +1,4 @@
-import { DictListTypeObj } from "@/types";
+import { DictListTypeObj, PermissionsAPIType } from "@/types";
 import { MessageType } from "@/utils/message";
 
 // 初始化状态
@@ -19,6 +19,8 @@ const initState = {
     level: [],
     source: [],
   } as DictListTypeObj,
+  // 有关权限的信息
+  authPageArr: [] as PermissionsAPIType[],
   // antd轻提示(兼容360浏览器)
   message: {
     txt: "",
@@ -33,6 +35,7 @@ type LoginActionType =
   | { type: "login/asyncLoding"; payload: boolean }
   | { type: "login/lookVideo"; payload: string }
   | { type: "login/getDictList"; payload: DictListTypeObj }
+  | { type: "login/setAuthPageArr"; payload: PermissionsAPIType[] }
   | { type: "login/message"; payload: MessageType };
 
 // 频道 reducer
@@ -56,6 +59,9 @@ export default function loginReducer(
     // antd轻提示(兼容360浏览器)
     case "login/message":
       return { ...state, message: action.payload };
+    // 有关权限的信息
+    case "login/setAuthPageArr":
+      return { ...state, authPageArr: action.payload };
     default:
       return state;
   }

+ 30 - 0
houtai/src/types/api/role.d.ts

@@ -0,0 +1,30 @@
+export type RoleTableType = {
+  count: number;
+  createTime: string;
+  creatorId: null;
+  creatorName: string;
+  id: number;
+  isEnabled: number;
+  roleDesc: string;
+  roleKey: string;
+  roleName: string;
+  sort: string;
+  updateTime: string;
+};
+
+
+export type PermissionsAPIType = {
+  authority: boolean;
+  children?: PermissionsAPIType[];
+  id: number;
+  name: string;
+  parentId?: null;
+  resourceType?: string;
+}
+
+export type AddRoleType ={
+  id:number|null
+  roleName:string
+  roleDesc:string
+  resources:number[]
+}

+ 35 - 0
houtai/src/types/api/user.d.ts

@@ -0,0 +1,35 @@
+export type UserTableAPIType={
+  startTime:string
+  endTime:string
+  nickName:string
+  pageNum:number
+  pageSize:number
+  realName:string
+  searchKey:string
+}
+
+export type UserTableListType={
+  createTime: string;
+  creatorId: null;
+  creatorName: string;
+  id: number;
+  isAdmin: number;
+  isEnabled: number;
+  nickName: string;
+  phone: string;
+  realName: string;
+  roleId: null;
+  roleName: string;
+  sex: string;
+  thumb: string;
+  updateTime: string;
+  userName: string;
+}
+
+export type SaveUserType ={
+  id:number|null
+  userName:string
+  nickName:string
+  roleId:number
+  realName:string
+}

+ 3 - 1
houtai/src/types/index.d.ts

@@ -5,4 +5,6 @@ export * from './api/hot'
 export * from './api/goods'
 export * from './api/barrage'
 export * from './api/smart'
-export * from './api/topic'
+export * from './api/topic'
+export * from './api/user'
+export * from './api/role'