李志伟 3 anni fa
parent
commit
91cd4855e0

+ 104
- 0
src/components/RoleCheckbox/index.jsx Vedi File

1
+import React, { useState, useEffect, useRef } from 'react';
2
+import { Checkbox, Divider } from 'antd';
3
+
4
+const BoxGroup = (props) => {
5
+  const { value, onchange, title, currenList } = props;
6
+  const [indeterminate, setIndeterminate] = useState(false);
7
+  const [checkAll, setCheckAll] = useState(false);
8
+  const [oldRoleList, setOldRoleList] = useState([]);
9
+
10
+  const onChange = (list) => {
11
+    var current;
12
+    if (oldRoleList.length === 0) {
13
+      onchange([...value, list[0]]);
14
+    } else if (list.length === 0) {
15
+      onchange(value.filter((item) => item !== oldRoleList[0]));
16
+    } else if (oldRoleList.length > list.length) {
17
+      //老的数据大于新的数据说明在减少
18
+      oldRoleList.map((item) => {
19
+        if (list.indexOf(item) === -1) {
20
+          current = item;
21
+        }
22
+      });
23
+      onchange(value.filter((item) => item !== current));
24
+    } else {
25
+      list.map((item) => {
26
+        if (oldRoleList.indexOf(item) === -1) {
27
+          current = item;
28
+        }
29
+      });
30
+      onchange([...value, current]);
31
+    }
32
+    setIndeterminate(!!list.length && list.length < currenList.length);
33
+    setCheckAll(list.length === currenList.length);
34
+    setOldRoleList(list);
35
+  };
36
+  const onCheckAllChange = (e) => {
37
+    var list = currenList.map((item) => {
38
+      return item.permissionId;
39
+    });
40
+    // 将对象数组转换为字符串数组
41
+    var list2 = [...value];
42
+    if (e.target.checked) {
43
+      // 全选了吧需要的加入
44
+      list.forEach((item) => {
45
+        if (list2.indexOf(item) === -1) {
46
+          list2.push(item);
47
+        }
48
+      });
49
+      onchange(list2);
50
+    } else {
51
+      list.forEach((item) => {
52
+        if (list2.indexOf(item) !== -1) {
53
+          list2.splice(list2.indexOf(item), 1);
54
+        }
55
+      });
56
+      onchange(list2);
57
+    }
58
+    setIndeterminate(false);
59
+    setCheckAll(e.target.checked);
60
+  };
61
+  useEffect(() => {
62
+    if (currenList.length > 0) {
63
+      let num = 0;
64
+      var list = currenList.map((item) => {
65
+        return item.permissionId;
66
+      });
67
+      value.forEach((item) => {
68
+        if (list.indexOf(item) !== -1) {
69
+          num++;
70
+        }
71
+      });
72
+      if (num === 0) {
73
+        setIndeterminate(false);
74
+        setCheckAll(false);
75
+      } else if (num < currenList.length) {
76
+        setIndeterminate(!!num && num < currenList.length);
77
+      } else {
78
+        setIndeterminate(false);
79
+        setCheckAll(true);
80
+      }
81
+    }
82
+  }, [currenList]);
83
+  return (
84
+    <>
85
+      <Divider orientation="center">{title}权限</Divider>
86
+      {currenList.length > 0 && (
87
+        <Checkbox indeterminate={indeterminate} onChange={onCheckAllChange} checked={checkAll}>
88
+          全选
89
+        </Checkbox>
90
+      )}
91
+      <Checkbox.Group style={{ width: '100%' }} value={value} onChange={onChange}>
92
+        {currenList.map((item) => {
93
+          return (
94
+            <div key={item.permissionId}>
95
+              <Checkbox value={item.permissionId}>{item.name}</Checkbox>
96
+              <br />
97
+            </div>
98
+          );
99
+        })}
100
+      </Checkbox.Group>
101
+    </>
102
+  );
103
+};
104
+export default BoxGroup;

+ 0
- 1
src/pages/ContentManagementSystem/Advertisement/edit.jsx Vedi File

24
 
24
 
25
   const Submit = (values) => {
25
   const Submit = (values) => {
26
     message.success(`成功成功成功`);
26
     message.success(`成功成功成功`);
27
-    console.log('🚀 ~ file: index.jsx ~ line 21 ~ values', values);
28
   };
27
   };
29
 
28
 
30
   return (
29
   return (

+ 1
- 3
src/pages/ContentManagementSystem/InformationClassification/InformationClassificationEdit/index.jsx Vedi File

19
     wrapperCol: { span: 14 },
19
     wrapperCol: { span: 14 },
20
   };
20
   };
21
 
21
 
22
-  const Submit = (values) => {
23
-    console.log('🚀 ~ file: index.jsx ~ line 21 ~ values', values);
24
-  };
22
+  const Submit = (values) => {};
25
 
23
 
26
   return (
24
   return (
27
     <Card>
25
     <Card>

+ 1
- 3
src/pages/ContentManagementSystem/InformationList/InformationListEdit/index.jsx Vedi File

21
     wrapperCol: { span: 14 },
21
     wrapperCol: { span: 14 },
22
   };
22
   };
23
 
23
 
24
-  const Submit = (values) => {
25
-    console.log('🚀 ~ file: index.jsx ~ line 21 ~ values', values);
26
-  };
24
+  const Submit = (values) => {};
27
 
25
 
28
   return (
26
   return (
29
     <Card>
27
     <Card>

+ 11
- 1
src/pages/SystemManagement/Administrator/index.jsx Vedi File

12
 } from '@/services/user';
12
 } from '@/services/user';
13
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
13
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
14
 import PageTable from '@/components/PageTable';
14
 import PageTable from '@/components/PageTable';
15
+import moment from 'moment';
15
 import Search from '@/components/CooperativeSearch';
16
 import Search from '@/components/CooperativeSearch';
16
 
17
 
17
 const FormItem = Form.Item;
18
 const FormItem = Form.Item;
18
 const { Option } = Select;
19
 const { Option } = Select;
19
-
20
+const formatterTime = (val) => {
21
+  return val && val !== '-' ? moment(val).format('YYYY-MM-DD') : '-';
22
+};
20
 export default (props) => {
23
 export default (props) => {
21
   //编辑弹窗
24
   //编辑弹窗
22
   const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 14 } };
25
   const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 14 } };
163
       dataIndex: 'email',
166
       dataIndex: 'email',
164
       key: 'email',
167
       key: 'email',
165
     },
168
     },
169
+    {
170
+      title: '注册时间',
171
+      dataIndex: 'createDate',
172
+      key: 'createDate',
173
+      render: formatterTime,
174
+      search: false,
175
+    },
166
     {
176
     {
167
       title: '状态',
177
       title: '状态',
168
       dataIndex: 'status',
178
       dataIndex: 'status',

+ 443
- 3
src/pages/SystemManagement/UserRights/index.jsx Vedi File

1
+import React, { useState, useEffect, useRef } from 'react';
2
+import { history, Link } from 'umi';
3
+import {
4
+  Button,
5
+  Popconfirm,
6
+  Modal,
7
+  Form,
8
+  Input,
9
+  message,
10
+  Tree,
11
+  Checkbox,
12
+  Row,
13
+  Col,
14
+  Divider,
15
+} from 'antd';
16
+import { PlusOutlined } from '@ant-design/icons';
17
+import { getRoleList, addRole, deleteRole, updateRole, getMenuList } from '@/services/role';
18
+import { getPermissionList, addPermission, getRoleRermissionDetail } from '@/services/permission';
19
+import { PageHeaderWrapper } from '@ant-design/pro-layout';
20
+import moment from 'moment';
21
+import PageTable from '@/components/PageTable';
22
+import RoleCheckbox from '@/components/RoleCheckbox';
23
+
24
+const formatterTime = (val) => {
25
+  return val && val !== '-' ? moment(val).format('YYYY-MM-DD') : '-';
26
+};
27
+const FormItem = Form.Item;
1
 
28
 
2
 export default (props) => {
29
 export default (props) => {
30
+  //列表
31
+  const actionRef = useRef();
32
+  // 角色表单
33
+  const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 14 } };
34
+  const [form] = Form.useForm();
35
+  const [editModal, setEditModal] = useState(false);
36
+  const [loading, setLoading] = useState(false);
37
+  const [roleId, setRoleId] = useState();
38
+  const [roleMId, setRoleMId] = useState();
39
+
40
+  // 授权弹窗
41
+  const [showModal, setShowModal] = useState(false);
42
+  const [treeList, setTreeList] = useState([]);
43
+  const [permissionAllList, setPermissionAllList] = useState([]);
44
+  const [primordialData, setPrimordialData] = useState([]);
45
+
46
+  const [currenList, setCurrentList] = useState([]);
47
+  const [title, setTitle] = useState('');
48
+  //选中的权限列表
49
+  const [rolePermissionList, setRolePermissionList] = useState([]);
50
+  const [pLoading, setPLoading] = useState(false);
51
+  let parentList = [];
52
+  let pid = '';
53
+
54
+  //列表编辑
55
+  const handelEdit = (val) => {
56
+    setRoleId(val.roleId);
57
+    form.setFieldsValue(val);
58
+    setEditModal(true);
59
+  };
60
+  //列表删除
61
+  const handleDelete = (id) => {
62
+    deleteRole(id)
63
+      .then(() => {
64
+        message.success('删除成功');
65
+        actionRef.current.reload();
66
+      })
67
+      .catch((err) => {
68
+        message.error(err);
69
+      });
70
+  };
71
+  //列表角色授权
72
+  const handelEmpower = (val) => {
73
+    setRoleMId(val.roleId);
74
+    setShowModal(true);
75
+    getRoleRermissionDetail({ roleId: val.roleId })
76
+      .then((res) => {
77
+        setRolePermissionList(
78
+          res.map((item) => {
79
+            return item.permissionId;
80
+          }),
81
+        );
82
+      })
83
+      .catch((err) => {
84
+        message.error(err);
85
+      });
86
+  };
87
+
88
+  // 表单提交
89
+  const Submit = (values) => {
90
+    setLoading(true);
91
+    if (roleId) {
92
+      updateRole(roleId, values).then(() => {
93
+        setLoading(false);
94
+        message.success(`修改成功`);
95
+        onCancel();
96
+        actionRef.current.reload();
97
+      });
98
+    } else {
99
+      addRole(values)
100
+        .then(() => {
101
+          setLoading(false);
102
+          message.success(`保存成功`);
103
+          onCancel();
104
+          actionRef.current.reload();
105
+        })
106
+        .catch((err) => {
107
+          setLoading(false);
108
+          message.error(err.message || err);
109
+        });
110
+    }
111
+  };
112
+  //角色弹窗关闭
113
+  const onCancel = () => {
114
+    setRoleId();
115
+    form.resetFields();
116
+    setEditModal(false);
117
+  };
118
+  //授权弹窗关闭
119
+  const onEmpowerCancel = () => {
120
+    setRoleMId();
121
+    setShowModal(false);
122
+    setRolePermissionList([]);
123
+    setCurrentList([]);
124
+    parentList = [];
125
+    pid = '';
126
+  };
127
+  //递归取出树结构中的所以项便于加入最终选中的菜单项
128
+  const treeToArray = (tree) => {
129
+    if (tree.children) {
130
+      return [{ title: tree.title, key: tree.key }, ...tree.children];
131
+    } else return { title: tree.title, key: tree.key };
132
+  };
133
+  // 选择左侧的菜单多选框
134
+  const onCheck = (checkedKeys, info) => {
135
+    //当前选中数组
136
+    let list2;
137
+    let list3 = [...rolePermissionList];
138
+    //权限数据
139
+    var list4 = list3.filter((item) => item.split(':').length == 2);
140
+    if (info.checked) {
141
+      if (info.node.children) {
142
+        list2 = treeToArray(info.node).map((item) => {
143
+          return item.key;
144
+        });
145
+        list2.forEach((item) => {
146
+          if (list3.indexOf(item) === -1) {
147
+            list3.push(item);
148
+          }
149
+        });
150
+      } else {
151
+        list2 = info.node.key;
152
+        if (list3.indexOf(list2) === -1) {
153
+          list3.push(list2);
154
+        }
155
+      }
156
+    } else {
157
+      setTitle();
158
+      setCurrentList([]);
159
+      //取消菜单
160
+      if (info.node.children) {
161
+        list2 = treeToArray(info.node).map((item) => {
162
+          return item.key;
163
+        });
164
+        list2.forEach((item) => {
165
+          if (list3.indexOf(item) !== -1) {
166
+            list3.splice(list3.indexOf(item), 1);
167
+            list4.map((v) => {
168
+              if (v.split(':')[0] == item) {
169
+                list3.splice(list3.indexOf(v), 1);
170
+              }
171
+            });
172
+          }
173
+        });
174
+      } else {
175
+        list2 = info.node.key;
176
+        if (list3.indexOf(list2) !== -1) {
177
+          list3.splice(list3.indexOf(list2), 1);
178
+          list4.map((v) => {
179
+            if (v.split(':')[0] == list2) {
180
+              list3.splice(list3.indexOf(list2), 1);
181
+            }
182
+          });
183
+        }
184
+      }
185
+    }
186
+    if (list3.length < checkedKeys.length + list4.length) {
187
+      // 说明父节点是因为子节点全部选中才选中实际上菜单数组中没有父节点的数据
188
+      checkedKeys.forEach((item) => {
189
+        if (list3.indexOf(item) === -1) {
190
+          list3.push(item);
191
+        }
192
+      });
193
+    } else if (list3.length > checkedKeys.length + list4.length) {
194
+      // 说明父节点是因为子节点全部取消才取消实际上菜单数组中多了父节点的数据
195
+      list3.forEach((item) => {
196
+        if (checkedKeys.indexOf(item) === -1 && list4.indexOf(item) === -1) {
197
+          list3.splice(list3.indexOf(item), 1);
198
+        }
199
+      });
200
+    }
201
+    setRolePermissionList(list3);
202
+  };
203
+  // 选择左侧菜单文字
204
+  const onSelect = (checkedKeys, info) => {
205
+    if (info.selected) {
206
+      var list = permissionAllList.filter((item) => item.resourceId === info.node.key);
207
+      setTitle(info.node.title);
208
+      setCurrentList(list);
209
+    } else {
210
+      setTitle();
211
+      setCurrentList([]);
212
+    }
213
+  };
214
+  const setParnentList = (val) => {
215
+    pid = primordialData.filter((item) => item.menuId === val)[0].menuPId;
216
+    if (pid !== '-1') {
217
+      parentList.push(pid);
218
+      setParnentList(pid);
219
+    }
220
+  };
221
+  const handelOk = () => {
222
+    var list = [...rolePermissionList];
223
+    if (list.length == 0) {
224
+      message.info('授权内容不能为空');
225
+      return;
226
+    }
227
+    setPLoading(true);
228
+    //菜单数据
229
+    var list4 = rolePermissionList.filter((item) => item.split(':').length !== 2);
230
+    list4.forEach((item) => {
231
+      setParnentList(item);
232
+    });
233
+
234
+    parentList = [...new Set(parentList)];
235
+    parentList.forEach((item) => {
236
+      if (list.indexOf(item) === -1) {
237
+        list.push(item);
238
+      }
239
+    });
240
+    list = list.map((item) => {
241
+      return { permissionId: item };
242
+    });
243
+    addPermission(roleMId, list)
244
+      .then(() => {
245
+        message.success('授权成功');
246
+        setPLoading(false);
247
+        onEmpowerCancel();
248
+      })
249
+      .catch((err) => {
250
+        message.error(err);
251
+        setPLoading(false);
252
+      });
253
+  };
254
+
255
+  // 将一维对象数组装换为树形数组
256
+  const translateDataToTree = (data) => {
257
+    //没有父节点的数据
258
+    let parents = data.filter((value) => value.menuPId == '-1');
259
+
260
+    //有父节点的数据
261
+    let children = data.filter((value) => value.menuPId !== '-1');
262
+
263
+    //定义转换方法的具体实现
264
+    let translator = (parents, children) => {
265
+      //遍历父节点数据
266
+      parents.forEach((parent) => {
267
+        //遍历子节点数据
268
+        children.forEach((current, index) => {
269
+          //此时找到父节点对应的一个子节点
270
+          if (current.menuPId === parent.menuId) {
271
+            //对子节点数据进行深复制,这里只支持部分类型的数据深复制,对深复制不了解的童靴可以先去了解下深复制
272
+            let temp = JSON.parse(JSON.stringify(children));
273
+            //让当前子节点从temp中移除,temp作为新的子节点数据,这里是为了让递归时,子节点的遍历次数更少,如果父子关系的层级越多,越有利
274
+            temp.splice(index, 1);
275
+            //让当前子节点作为唯一的父节点,去递归查找其对应的子节点
276
+            translator([current], temp);
277
+            //把找到子节点放入父节点的children属性中
278
+            typeof parent.children !== 'undefined'
279
+              ? parent.children.push(current)
280
+              : (parent.children = [current]);
281
+          }
282
+        });
283
+      });
284
+    };
285
+
286
+    //调用转换方法
287
+    translator(parents, children);
288
+
289
+    //返回最终的结果
290
+    return parents;
291
+  };
292
+  useEffect(() => {
293
+    getMenuList()
294
+      .then((res) => {
295
+        setPrimordialData(res);
296
+        const list = translateDataToTree(res);
297
+        const list2 = list.map((item) => {
298
+          if (item.children?.length > 0) {
299
+            return {
300
+              title: item.name,
301
+              key: item.menuId,
302
+              children: item.children.map((v) => {
303
+                return { title: v.name, key: v.menuId };
304
+              }),
305
+            };
306
+          } else {
307
+            return { title: item.name, key: item.menuId };
308
+          }
309
+        });
310
+        setTreeList(list2);
311
+      })
312
+      .catch((err) => {
313
+        message.error(err);
314
+      });
315
+    getPermissionList()
316
+      .then((res) => {
317
+        setPermissionAllList(res);
318
+      })
319
+      .catch((err) => {
320
+        message.error(err);
321
+      });
322
+  }, []);
323
+  useEffect(() => {
324
+    if (roleId) {
325
+    } else {
326
+      form.resetFields();
327
+    }
328
+  }, [roleId]);
329
+
330
+  const actions = () => [
331
+    <Button key="add" type="primary" icon={<PlusOutlined />} onClick={() => setEditModal(true)}>
332
+      新增
333
+    </Button>,
334
+  ];
335
+  const columns = [
336
+    {
337
+      title: '角色名',
338
+      dataIndex: 'name',
339
+      key: 'name',
340
+    },
341
+    {
342
+      title: '创建时间',
343
+      dataIndex: 'createDate',
344
+      key: 'createDate',
345
+      render: formatterTime,
346
+    },
347
+    {
348
+      title: '操作',
349
+      valueType: 'option',
350
+      render: (_, record) => [
351
+        <a key={1} onClick={() => handelEdit(record)}>
352
+          编辑
353
+        </a>,
354
+        <Popconfirm
355
+          key={2}
356
+          title="您是否确认删除 ?"
357
+          onConfirm={() => handleDelete(record.roleId)}
358
+          okText="确定"
359
+          cancelText="取消"
360
+        >
361
+          <a href="#">删除</a>
362
+        </Popconfirm>,
363
+        <a key={3} onClick={() => handelEmpower(record)}>
364
+          角色授权
365
+        </a>,
366
+      ],
367
+    },
368
+  ];
3
 
369
 
4
   return (
370
   return (
5
-    <div>角色权限</div>
6
-  )
7
-}
371
+    <PageHeaderWrapper>
372
+      <PageTable
373
+        request={getRoleList}
374
+        // expfunc={exportPersonList}
375
+        columns={columns}
376
+        actionRef={actionRef}
377
+        rowKey="roleId"
378
+        options={false}
379
+        toolBarRender={actions}
380
+        search={false}
381
+      />
382
+      <Modal
383
+        forceRender
384
+        title={roleId ? '角色编辑' : '角色新增'}
385
+        visible={editModal}
386
+        onCancel={onCancel}
387
+        keyboard={false}
388
+        maskClosable={false}
389
+        destroyOnClose={true}
390
+        footer={null}
391
+      >
392
+        <Form {...formItemLayout} onFinish={Submit} form={form}>
393
+          <FormItem label="角色名" name="name" rules={[{ required: true, message: '请输入' }]}>
394
+            <Input placeholder="请输入" />
395
+          </FormItem>
396
+          <FormItem label=" " colon={false}>
397
+            <Button type="default" onClick={onCancel}>
398
+              取消
399
+            </Button>
400
+            <Button
401
+              type="primary"
402
+              loading={loading}
403
+              htmlType="Submit"
404
+              style={{ marginLeft: '4em' }}
405
+            >
406
+              确认
407
+            </Button>
408
+          </FormItem>
409
+        </Form>
410
+      </Modal>
411
+      <Modal
412
+        title="角色授权"
413
+        visible={showModal}
414
+        onCancel={onEmpowerCancel}
415
+        keyboard={false}
416
+        maskClosable={false}
417
+        destroyOnClose={true}
418
+        onOk={handelOk}
419
+        confirmLoading={pLoading}
420
+      >
421
+        <Row gutter={24}>
422
+          <Col span={12}>
423
+            <Divider orientation="center">菜单</Divider>
424
+            <Tree
425
+              height={500}
426
+              checkable
427
+              defaultExpandAll
428
+              onSelect={onSelect}
429
+              onCheck={onCheck}
430
+              checkStrictly
431
+              checkedKeys={rolePermissionList}
432
+              treeData={treeList}
433
+            />
434
+          </Col>
435
+          <Col span={12}>
436
+            <RoleCheckbox
437
+              value={rolePermissionList}
438
+              title={title}
439
+              currenList={currenList}
440
+              onchange={setRolePermissionList}
441
+            />
442
+          </Col>
443
+        </Row>
444
+      </Modal>
445
+    </PageHeaderWrapper>
446
+  );
447
+};

+ 21
- 0
src/services/permission.js Vedi File

1
+import request from '@/utils/request';
2
+
3
+/**
4
+ * 角色授权
5
+ * @param {*} data
6
+ * @returns
7
+ */
8
+export const addPermission = (id, data) =>
9
+  request(`/role/${id}/permission`, { method: 'post', data });
10
+/**
11
+ * 查询角色权限详情
12
+ * @param {*} params
13
+ * @returns
14
+ */
15
+export const getRoleRermissionDetail = (params) => request(`/role-permission`, { params });
16
+/**
17
+ * 查询权限列表
18
+ * @param {*} params
19
+ * @returns
20
+ */
21
+export const getPermissionList = (params) => request('/permission', { params });

+ 50
- 0
src/services/role.js Vedi File

1
+import request from '@/utils/request';
2
+
3
+/**
4
+ * 保存角色
5
+ * @param {*} data
6
+ * @returns
7
+ */
8
+export const addRole = (data) => request('/role', { method: 'post', data });
9
+
10
+/**
11
+ * 修改角色
12
+ * @param {*} data
13
+ * @returns
14
+ */
15
+export const updateRole = (id, data) => request(`/role/${id}`, { method: 'put', data });
16
+
17
+/**
18
+ * 查询角色列表
19
+ * @param {*} params
20
+ * @returns
21
+ */
22
+export const getRoleList = (params) => request('/role', { params });
23
+
24
+/**
25
+ * 删除角色
26
+ * @param {*} data
27
+ * @returns
28
+ */
29
+export const deleteRole = (id) => request(`/role/${id}`, { method: 'delete' });
30
+
31
+/**
32
+ * 查询角色详情
33
+ * @param {*} params
34
+ * @returns
35
+ */
36
+export const getRoleDetail = (id) => request(`/role/${id}`);
37
+
38
+/**
39
+ * 查询菜单列表
40
+ * @param {*} params
41
+ * @returns
42
+ */
43
+export const getMenuList = (params) => request('/menu', { params });
44
+
45
+/**
46
+ * 查询权限列表
47
+ * @param {*} params
48
+ * @returns
49
+ */
50
+export const getPermissionList = (params) => request('/permission', { params });