Archer_cdm 2 years ago
parent
commit
594858d752
  1. 87
      api/app/lib/controllers/organization/authority.js
  2. 373
      api/app/lib/controllers/organization/user.js
  3. 4
      api/app/lib/models/department.js
  4. 28
      api/app/lib/routes/organization/authority.js
  5. 41
      api/app/lib/routes/organization/user.js
  6. 2
      script/1.0.0/data/1.admin_user.sql
  7. 11
      script/1.0.0/data/2.updata_resource_data.sql
  8. 11
      script/1.0.0/data/3.updata_user_resource_data.sql
  9. 2
      script/1.0.0/schema/1.init_inspection.sql
  10. 3
      web/client/src/app.js
  11. 51
      web/client/src/sections/organization/actions/authority.js
  12. 11
      web/client/src/sections/organization/actions/index.js
  13. 113
      web/client/src/sections/organization/actions/user.js
  14. 88
      web/client/src/sections/organization/components/deptModal.js
  15. 74
      web/client/src/sections/organization/components/resetPwd.js
  16. 121
      web/client/src/sections/organization/components/resource.js
  17. 171
      web/client/src/sections/organization/components/userModal.js
  18. 149
      web/client/src/sections/organization/containers/authority.js
  19. 6
      web/client/src/sections/organization/containers/index.js
  20. 331
      web/client/src/sections/organization/containers/user.js
  21. 15
      web/client/src/sections/organization/index.js
  22. 22
      web/client/src/sections/organization/nav-item.js
  23. 5
      web/client/src/sections/organization/reducers/index.js
  24. 26
      web/client/src/sections/organization/routes.js
  25. 17
      web/client/src/utils/webapi.js

87
api/app/lib/controllers/organization/authority.js

@ -0,0 +1,87 @@
async function getResource(ctx, next) {
try {
const models = ctx.fs.dc.models;
const res = await models.Resource.findAll({
where: { parentResource: null },
include: [{
model: models.Resource,
}]
})
ctx.body = res;
ctx.status = 200;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "查询所有权限数据失败"
}
}
}
async function getUserResource(ctx, next) {
try {
const models = ctx.fs.dc.models;
const { userId } = ctx.query;
const res = await models.UserResource.findAll({
where: { userId: userId },
include: [{
model: models.Resource,
}]
})
ctx.body = res;
ctx.status = 200;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "查询用户权限数据失败"
}
}
}
async function updateUserRes(ctx, next) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const models = ctx.fs.dc.models;
const { userId, resCode } = ctx.request.body;
const res = await models.UserResource.findAll({
attributes: ["resourceId"],
raw: true,
where: { userId: userId }
})
const addRes = resCode.filter(r => !res.some(rr => rr.resourceId == r)).map(r => { return { userId: userId, resourceId: r } });
const delRes = res.filter(r => !resCode.includes(r.resourceId)).map(r => r.resourceId);
addRes.length && await models.UserResource.bulkCreate(addRes, { transaction: transaction });
delRes.length && await models.UserResource.destroy({
where: {
resourceId: { $in: delRes },
userId: userId
},
transaction: transaction
})
ctx.status = 204;
await transaction.commit();
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "更新用户权限数据失败"
}
}
}
module.exports = {
getResource,
getUserResource,
updateUserRes
};

373
api/app/lib/controllers/organization/user.js

@ -0,0 +1,373 @@
'use strict';
const Hex = require('crypto-js/enc-hex');
const MD5 = require('crypto-js/md5');
// async function getDepMessage (ctx, next) {
// try {
// const { fs: { api: { userInfo } } } = ctx
// const models = ctx.fs.dc.models;
// let deptWhere = {}
// if (userInfo.username !== 'SuperAdmin') {
// deptWhere.id = userInfo.departmentId
// }
// let depType1 = await models.Department.findAll({
// order: [['id', 'asc']],
// // include: [{
// // model: models.User,
// // required: false,
// // where: { delete: false },
// // attributes: { exclude: ['password'] },
// // }],
// where: deptWhere,
// })
// let depRslt = []
// const getDep = async (d) => {
// let subordinate = []
// let depRes = await models.Department.findAll({
// order: [['id', 'asc']],
// // include: [{
// // model: models.User,
// // required: false,
// // where: { delete: false },
// // attributes: { exclude: ['password'] },
// // }],
// where: {
// dependence: d.id
// },
// })
// if (depRes.length)
// for (let d of depRes) {
// let dep = d.dataValues
// dep.subordinate = await getDep(d.dataValues)
// subordinate.push(dep)
// }
// return subordinate
// }
// for (let d of depType1) {
// let dep_1 = d.dataValues
// dep_1.subordinate = await getDep(d.dataValues)
// depRslt.push(dep_1)
// }
// ctx.status = 200;
// ctx.body = depRslt
// } catch (error) {
// ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
// ctx.status = 400;
// ctx.body = {
// "message": "获取部门信息失败"
// }
// }
// }
async function getDepMessage(ctx, next) {
let error = { name: 'FindError', message: '获取部门列表失败' };
let rslt = [];
try {
const models = ctx.fs.dc.models;
let list = await models.Department.findAll({});
let deptMap = []
list.filter(l => !l.dependence).map(ld => {//一级
deptMap.push({
id: ld.id,
name: ld.name,
dependence: ld.dependence,
subordinate: []
})
})
list.filter(l => l.dependence).map(ld => {//二级
let parent = deptMap.find(dm => dm.id == ld.dependence);
if (parent) {
parent.subordinate.push({
id: ld.id,
name: ld.name,
dependence: ld.dependence,
subordinate: []
})
}
})
rslt = deptMap;
error = null;
} catch (err) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${err}`);
}
if (error) {
ctx.status = 400;
ctx.body = error;
} else {
ctx.status = 200;
ctx.body = rslt;
}
}
async function createDept(ctx, next) {
const models = ctx.fs.dc.models;
try {
let rslt = ctx.request.body;
await models.Department.create(Object.assign({}, rslt, { read: 1 }))
ctx.status = 204;
ctx.body = { message: '新建部门成功' }
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = { message: '新建部门失败' }
}
}
async function updateDept(ctx, next) {
try {
const models = ctx.fs.dc.models;
const { id } = ctx.params;
const body = ctx.request.body;
await models.Department.update(
body,
{ where: { id: id } }
)
ctx.status = 204;
ctx.body = { message: '修改部门成功' }
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = { message: '修改部门失败' }
}
}
async function delDept(ctx, next) {
let errMsg = "删除部门失败";
try {
const models = ctx.fs.dc.models;
const { id } = ctx.params;
let list = await models.Department.findAll({});
let deptIds = list.map(l => l.id);
const allUsers = await models.User.findAll({
where: {
departmentId: { $in: deptIds },
delete: false
}
})
const childrenDept = await models.Department.findAll({ where: { dependence: id } })
const childrenUser = allUsers.filter(au => au.departmentId == id);
if (childrenUser.length || childrenDept.length) {
errMsg = '请先删除部门下的用户或子部门';
throw errMsg;
}
await models.Department.destroy({ where: { id: id } });
await models.Department.destroy({ where: { dependence: id } });
ctx.status = 204;
ctx.body = { message: '删除部门成功' }
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = { message: error }
}
}
async function getUser(ctx, next) {
try {
const models = ctx.fs.dc.models;
const { depId } = ctx.params
const userRes = await models.User.findAll({
where: {
departmentId: parseInt(depId),
delete: false
},
attributes: { exclude: ['password'] },
order: [['id', 'asc']],
})
ctx.status = 200;
ctx.body = userRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "获取用户信息失败"
}
}
}
async function creatUser(ctx, next) {
let errMsg = "新建用户失败"
try {
const models = ctx.fs.dc.models;
const data = ctx.request.body;
let repeatUserNameCount = await models.User.count({
where: {
username: data.phone,
delete: false
}
})
if (repeatUserNameCount) {
errMsg = '已有当前用户名'
throw errMsg
}
await models.User.create({
name: data.name,
username: data.phone,
password: Hex.stringify(MD5(data.password)),
departmentId: data.departmentId,
email: data.email,
enable: data.enable,
delete: false,
phone: data.phone,
post: data.post,
})
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": errMsg
}
}
}
async function updateUser(ctx, next) {
let errMsg = "修改用户失败"
try {
const models = ctx.fs.dc.models;
const data = ctx.request.body;
const { id } = ctx.params;
let repeatUserNameCount = await models.User.count({
where: {
username: data.username
}
})
if (repeatUserNameCount) {
errMsg = '已有当前用户名'
throw errMsg
}
await models.User.update({
name: data.name,
username: data.phone,
departmentId: data.departmentId,
email: data.email,
enable: data.enable,
delete: false,
phone: data.phone,
post: data.post,
}, {
where: {
id: id
}
});
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": errMsg
}
}
}
async function deleteUser(ctx, next) {
try {
const models = ctx.fs.dc.models;
const { ids } = ctx.params;
const userIds = ids.split(',');
await models.User.update({
delete: true,
}, {
where: {
id: { $in: userIds },
}
});
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "删除用户失败"
}
}
}
async function resetPwd(ctx, next) {
try {
const models = ctx.fs.dc.models;
const { id } = ctx.params;
const data = ctx.request.body;
await models.User.update({
password: Hex.stringify(MD5(data.password)),
}, {
where: {
id: id,
}
});
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "重置用户密码失败"
}
}
}
/**
* 修改用户密码
* @params {userId-用户Id} ctx
* @request.body {password-用户新密码} ctx
*/
async function updateUserPassword(ctx, next) {
try {
const models = ctx.fs.dc.models;
const { userId } = ctx.params;
const { password } = ctx.request.body;
if (!password) {
ctx.status = 400;
ctx.body = { "message": "请输入修改密码" };
return;
}
const userRes = await models.User.findOne({
where: {
id: userId
},
attributes: ['id']
});
if (userRes) {
await models.User.update({ password: Hex.stringify(MD5(password)) }, { where: { id: userId, } });
ctx.status = 204;
} else {
ctx.status = 400;
ctx.body = {
"message": "用户不存在"
}
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "修改用户密码失败"
}
}
}
module.exports = {
getDepMessage,
createDept,
updateDept,
delDept,
getUser,
creatUser,
updateUser,
deleteUser,
resetPwd,
updateUserPassword
}

4
api/app/lib/models/department.js

@ -35,9 +35,9 @@ module.exports = dc => {
},
type: {
type: DataTypes.INTEGER,
allowNull: false,
allowNull: true,
defaultValue: null,
comment: "市1,区县2,乡镇3,村4",
comment: "",
primaryKey: false,
field: "type",
autoIncrement: false

28
api/app/lib/routes/organization/authority.js

@ -0,0 +1,28 @@
'use strict';
const Authority = require('../../controllers/organization/authority');
module.exports = function (app, router, opts) {
/**
* @api {GET} resource 查询所有权限码.
* @apiVersion 1.0.0
* @apiGroup Org
*/
app.fs.api.logAttr['GET/resource'] = { content: '查询所有权限码', visible: true };
router.get('resource', Authority.getResource);
/**
* @api {GET} user/resource 查询用户权限.
* @apiVersion 1.0.0
* @apiGroup Org
*/
app.fs.api.logAttr['GET/user/resource'] = { content: '查询用户权限', visible: true };
router.get('user/resource', Authority.getUserResource);
/**
* @api {POST} user/resource 更新用户权限.
* @apiVersion 1.0.0
* @apiGroup Org
*/
app.fs.api.logAttr['POST/user/resource'] = { content: '更新用户权限', visible: true };
router.post('user/resource', Authority.updateUserRes);
};

41
api/app/lib/routes/organization/user.js

@ -0,0 +1,41 @@
'use strict';
const user = require('../../controllers/organization/user');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/organization/department'] = { content: '获取部门信息', visible: false };
router.get('/organization/department', user.getDepMessage);
app.fs.api.logAttr['POST/organization/dept/add'] = { content: '新增部门', visible: true };
router.post('/organization/dept/add', user.createDept);
app.fs.api.logAttr['PUT/organization/dept/:id/modify'] = { content: '修改部门', visible: true };
router.put('/organization/dept/:id/modify', user.updateDept);
app.fs.api.logAttr['DELETE/organization/dept/:id'] = { content: '删除部门', visible: true };
router.del('/organization/dept/:id', user.delDept);
app.fs.api.logAttr['GET/organization/department/:depId/user'] = { content: '获取部门下用户信息', visible: false };
router.get('/organization/department/:depId/user', user.getUser);
app.fs.api.logAttr['POST/organization/department/user'] = { content: '创建部门下用户信息', visible: false };
router.post('/organization/department/user', user.creatUser);
app.fs.api.logAttr['PUT/organization/department/user/:id'] = { content: '修改部门下用户信息', visible: false };
router.put('/organization/department/user/:id', user.updateUser);
app.fs.api.logAttr['DEL/organization/department/user/:ids'] = { content: '删除部门下用户信息', visible: false };
router.del('/organization/department/user/:ids', user.deleteUser);
app.fs.api.logAttr['PUT/organization/department/user/resetPwd/:id'] = { content: '重置用户密码', visible: false };
router.put('/organization/department/user/resetPwd/:id', user.resetPwd);
/**
* @api {PUT} user/password/:id 修改用户密码
* @apiVersion 1.0.0
* @apiGroup Organization
*/
app.fs.api.logAttr['PUT/user/password/:userId'] = { content: '修改用户密码', visible: false };
router.put('/user/password/:userId', user.updateUserPassword);
};

2
script/1.0.0/data/1.admin_user.sql

@ -1 +1 @@
INSERT INTO "public"."user" VALUES (1, '管理员', 'SuperAdmin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL, 't', 'f', '123456789', NULL);
INSERT INTO "public"."user" VALUES (default, '管理员', 'SuperAdmin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL, 't', 'f', '123456789', NULL);

11
script/1.0.0/data/2.updata_resource_data.sql

@ -0,0 +1,11 @@
INSERT INTO "public"."resource" VALUES ('STRUCTURE_MANAGE', '结构物管理', NULL);
INSERT INTO "public"."resource" VALUES ('STRU_INFO_CONFIG', '基础信息维护', 'STRUCTURE_MANAGE');
INSERT INTO "public"."resource" VALUES ('QR_CODE_CONFIG', '二维码管理', 'STRUCTURE_MANAGE');
INSERT INTO "public"."resource" VALUES ('PATROL_MANAGE', '巡检管理', NULL);
INSERT INTO "public"."resource" VALUES ('PATROL_PLAN_CONFIG', '巡检计划制订', 'PATROL_MANAGE');
INSERT INTO "public"."resource" VALUES ('PATROL_RECORD_VIEW', '巡检记录查看', 'PATROL_MANAGE');
INSERT INTO "public"."resource" VALUES ('REPAIR_MANAGE', '维修处理', NULL);
INSERT INTO "public"."resource" VALUES ('HANDLE_REPAIR', '维修处理', 'REPAIR_MANAGE');
INSERT INTO "public"."resource" VALUES ('ORG_MANAGE', '组织管理', NULL);
INSERT INTO "public"."resource" VALUES ('USER_CONFIG', '部门成员', 'ORG_MANAGE');
INSERT INTO "public"."resource" VALUES ('AUTH_CONFIG', '权限配置', 'ORG_MANAGE');

11
script/1.0.0/data/3.updata_user_resource_data.sql

@ -0,0 +1,11 @@
INSERT INTO "public"."user_resource" VALUES (default, 1, 'STRUCTURE_MANAGE');
INSERT INTO "public"."user_resource" VALUES (default, 1, 'STRU_INFO_CONFIG');
INSERT INTO "public"."user_resource" VALUES (default, 1, 'QR_CODE_CONFIG');
INSERT INTO "public"."user_resource" VALUES (default, 1, 'PATROL_MANAGE');
INSERT INTO "public"."user_resource" VALUES (default, 1, 'PATROL_PLAN_CONFIG');
INSERT INTO "public"."user_resource" VALUES (default, 1, 'PATROL_RECORD_VIEW');
INSERT INTO "public"."user_resource" VALUES (default, 1, 'REPAIR_MANAGE');
INSERT INTO "public"."user_resource" VALUES (default, 1, 'HANDLE_REPAIR');
INSERT INTO "public"."user_resource" VALUES (default, 1, 'ORG_MANAGE');
INSERT INTO "public"."user_resource" VALUES (default, 1, 'USER_CONFIG');
INSERT INTO "public"."user_resource" VALUES (default, 1, 'AUTH_CONFIG');

2
script/1.0.0/schema/1.init_inspection.sql

@ -69,7 +69,7 @@ CREATE TABLE "public"."department" (
"id" int4 NOT NULL DEFAULT nextval('department_id_seq'::regclass),
"name" varchar(128) COLLATE "pg_catalog"."default" NOT NULL,
"dependence" int4,
"type" int4 NOT NULL
"type" int4
);
COMMENT ON COLUMN "public"."department"."dependence" IS '上级部门/从属';
-- COMMENT ON COLUMN "public"."department"."type" IS '市1,区县2,乡镇3,村4';

3
web/client/src/app.js

@ -5,6 +5,7 @@ import Layout from './layout';
import Auth from './sections/auth';
import Safetymanage from './sections/safetymanage';
import ProjectRegime from './sections/projectRegime';
import Organization from './sections/organization';
const App = props => {
const { projectName } = props
@ -16,7 +17,7 @@ const App = props => {
return (
<Layout
title={projectName}
sections={[ Auth, ProjectRegime, Safetymanage]}
sections={[Auth, ProjectRegime, Safetymanage, Organization]}
/>
)

51
web/client/src/sections/organization/actions/authority.js

@ -0,0 +1,51 @@
'use strict';
import { basicAction } from '@peace/utils'
import { ApiTable } from '$utils'
export function getAuthority(orgId) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_MEMBERS',
url: `${ApiTable.getEnterprisesMembers.replace('{enterpriseId}', orgId)}`,
msg: { error: '获取用户列表失败' },
reducer: { name: 'members' }
});
}
export function getResource(userId) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_RESOURCE',
url: `${ApiTable.getResource}`,
msg: { error: '获取权限失败' },
reducer: { name: 'resource' }
});
}
export function getUserResource(userId) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_USER_RESOURCE',
url: `${ApiTable.getUserResource}?userId=${userId}`,
msg: { error: '获取用户权限失败' },
reducer: { name: 'userResource' }
});
}
export function postUserRes(body) {
return dispatch => basicAction({
type: 'post',
dispatch: dispatch,
actionType: 'UPDATE_USER_RESOURCE',
url: `${ApiTable.postUserRes}`,
data: body,
msg: { success: '更新用户权限' }
});
}
export default {
getAuthority,
getResource,
getUserResource,
postUserRes
}

11
web/client/src/sections/organization/actions/index.js

@ -0,0 +1,11 @@
'use strict';
import * as authority from './authority'
import { getDepMessage, getDepUser, createUser } from './user'
export default {
...authority,
getDepMessage,
getDepUser,
createUser,
}

113
web/client/src/sections/organization/actions/user.js

@ -0,0 +1,113 @@
'use strict';
import { basicAction } from '@peace/utils'
import { ApiTable } from '$utils'
export function getDepMessage() {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_DEPARTMENT_MESSAGE',
url: ApiTable.getDepMessage,
msg: { error: '获取部门信息失败' },
reducer: { name: 'depMessage' }
});
}
//新建部门
export function createDept(data) {
return dispatch => basicAction({
type: 'post',
data,
dispatch: dispatch,
actionType: 'CREATE_DEPT',
url: ApiTable.createDept,
msg: { option: '新建部门' },
});
}
//修改部门
export function updateDept(id, data) {
return dispatch => basicAction({
type: 'put',
data,
dispatch: dispatch,
actionType: 'UPDATE_DEPT',
url: ApiTable.updateDept.replace('{id}', id),
msg: { option: '修改部门' },
});
}
//删除部门
export function delDept(id) {
return dispatch => basicAction({
type: 'del',
dispatch: dispatch,
actionType: 'DEL_DEPT',
url: ApiTable.delDept.replace('{id}', id),
msg: { option: '删除部门' },
});
}
export function getDepUser(depId) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_DEPARTMENT_USER',
url: ApiTable.getDepUser.replace('{depId}', depId),
msg: { error: '获取部门下用户信息失败' },
reducer: { name: 'depUser' }
});
}
export function createUser(data) {
return dispatch => basicAction({
type: 'post',
data,
dispatch: dispatch,
actionType: 'CREATE_DEPARTMENT_USER',
url: ApiTable.createUser,
msg: { option: '新建用户' },
});
}
export function updateUser(id, data) {
return dispatch => basicAction({
type: 'put',
data,
dispatch: dispatch,
actionType: 'UPDATE_DEPARTMENT_USER',
url: ApiTable.updateUser.replace('{id}', id),
msg: { option: '修改用户' },
});
}
export function delUser(ids) {
return dispatch => basicAction({
type: 'del',
dispatch: dispatch,
actionType: 'DEL_DEPARTMENT_USER',
url: ApiTable.delUser.replace('{ids}', ids),
msg: { option: '删除用户' },
});
}
export function resetPwd(id, data) {
return dispatch => basicAction({
type: 'put',
data,
dispatch: dispatch,
actionType: 'CREATE_DEPARTMENT_USER',
url: ApiTable.resetPwd.replace('{id}', id),
msg: { option: '重置用户密码' },
});
}
export default {
getDepMessage,
getDepUser,
createUser,
updateUser,
delUser,
resetPwd
}

88
web/client/src/sections/organization/components/deptModal.js

@ -0,0 +1,88 @@
import React from 'react';
import { connect } from 'react-redux';
import { ProFormText, ModalForm, ProFormSelect } from '@ant-design/pro-form';
const DeptModal = (props) => {
const { visible, modalType, onVisibleChange, onConfirm, editData, depts } = props
let deptOptions = [], sonArr = [];
depts.map(d => {
deptOptions.push({
value: d.id,
label: d.name
});
d.subordinate.map(ds => {
sonArr.push({
value: ds.id,
label: ds.name
})
})
})
const onFinish = (values) => {
if (onConfirm) {
if (modalType === 'edit') {
values.contract.parentDeptId = values.contract.parentDeptId || null
onConfirm(values)
} else {
onConfirm(values);
}
}
}
const checkName = (rule, value, callback) => {
const list = modalType == 'edit' ? deptOptions.concat(sonArr).filter(g => g.value != editData.id) : deptOptions.concat(sonArr)
if (list.filter(s => s.label == value).length) {
callback('该名称已存在');
} else {
callback();
}
}
return (
<ModalForm
width={400}
title={modalType == 'edit' ? '编辑部门' : '新建部门'}
visible={visible}
onVisibleChange={onVisibleChange}
onFinish={onFinish}
destroyOnClose
initialValues={
modalType == 'edit' ?
{
contract: editData
} :
{
contract: {
enable: true
}
}
}
>
<ProFormText
name={['contract', 'name']}
maxLength={24}
width="md"
label="部门名称"
required
placeholder="请输入部门名称"
rules={[{ required: true, message: '请输入部门名称' }, { validator: checkName }]}
/>
<ProFormSelect
name={['contract', 'dependence']}
label="上级部门"
request={async () => {
let t = modalType === 'edit' ? deptOptions.filter(i => i.value !== editData.id) : deptOptions
return t
}}
disabled={modalType === 'edit' ? editData.subordinate?.length === 0 ? false : true : false}
/>
</ModalForm>
)
}
function mapStateToProps(state) {
return {
};
}
export default connect(mapStateToProps)(DeptModal);

74
web/client/src/sections/organization/components/resetPwd.js

@ -0,0 +1,74 @@
import React, { useRef, useState } from 'react';
import { connect } from 'react-redux';
import { Spin, Card, Modal, TreeSelect } from 'antd';
import ProForm, { ProFormText, ModalForm, ProFormSwitch, ProFormTreeSelect } from '@ant-design/pro-form';
const ResetPwd = (props) => {
const { visible, onVisibleChange, onConfirm } = props;
const formRef = useRef();
const onFinish = (values) => {
if (onConfirm) {
onConfirm(values);
}
}
return (
<Spin spinning={false}>
<ModalForm
title={'重置密码'}
visible={visible}
onVisibleChange={onVisibleChange}
onFinish={onFinish}
formRef={formRef}
destroyOnClose
>
<ProFormText.Password
name={['password']}
width="md"
label="新密码"
required
placeholder="请输入密码"
fieldProps={{
autocomplete: 'new-password'
}}
rules={[
{ required: true, message: '请填写密码' },
{ min: 6, message: '请填写至少6位密码' },
]}
/>
<ProFormText.Password
name={['checkPassword']}
width="md"
label="确认密码"
required
autocomplete='off'
placeholder="请输入密码"
rules={[
{ required: true, message: '请再次填写密码' },
{ min: 6, message: '请填写至少6位密码' },
{
validator: (rule, value, callback) => {
const pwd = formRef.current.getFieldValue('password');
if (!value) {
callback();
}
if (pwd == value) {
callback();
} else {
callback('两次输入的密码不一致');
}
}
}
]}
/>
</ModalForm>
</Spin>
)
}
function mapStateToProps(state) {
return {};
}
export default connect(mapStateToProps)(ResetPwd);

121
web/client/src/sections/organization/components/resource.js

@ -0,0 +1,121 @@
import React, { useEffect } from 'react';
import { Checkbox, Table } from 'antd';
import { useState } from 'react';
const CheckboxGroup = Checkbox.Group;
const Resource = props => {
const { roleData, userRole, userSelected, setResCode, userType } = props;
const [indeterminate, setIndeterminate] = useState({});
const [roleCheck, setRoleCheck] = useState({});//一级权限码
const [parentRoleCheck, setParentRoleCheck] = useState({}); //二级权限码
const roleDatas=roleData.slice(0)
useEffect(() => {
const check = {}
const parentCheck = {}
const initInd = {}
roleData && roleData.map && roleData.map(r => {
let currentInd = false;
let sum = 0;
if (r.resources) {
check[r.code] = []
r.resources.map(child => {
if (userRole.find(code => code.resourceId == child.code)) {
currentInd = true;
sum++;
check[r.code].push(child.code);
}
})
}
parentCheck[r.code] = r.resources.length === sum
initInd[r.code] = parentCheck[r.code] ? false : currentInd
});
setParentRoleCheck(parentCheck)
setRoleCheck(check);
setIndeterminate(initInd);
}, [userRole]);
const setResData = (role) => {
let codes = [];
// Object.keys(partRole).map(r => {
// if (partRole[r]) codes.push(r)
// })
Object.keys(role).map(r => {
if (role[r].length) {
codes.push(r);
}
codes = codes.concat(role[r])
})
setResCode(codes)
}
return (
<Table
bordered
pagination={false}
dataSource={roleDatas}
columns={[{
title: '功能',
key: 'name',
dataIndex: 'name',
render: (text, record) => {
const parentCode = record.code
return <Checkbox
indeterminate={indeterminate[parentCode]}
onChange={(e) => {
const currentParCheck = JSON.parse(JSON.stringify(parentRoleCheck));
currentParCheck[parentCode] = e.target.checked;
const currentCode = JSON.parse(JSON.stringify(roleCheck));
currentCode[parentCode] = e.target.checked ? roleData.find(r => r.code == parentCode).resources.map(r => r.code) : []
const currentInd = JSON.parse(JSON.stringify(indeterminate));
currentInd[parentCode] = false;
setParentRoleCheck(currentParCheck);
setRoleCheck(currentCode);
setIndeterminate(currentInd);
setResData(currentCode)
}}
checked={parentRoleCheck[parentCode] || false}
disabled={userSelected === "SuperAdmin" || userType === 4}
options={''}
>
{text}
</Checkbox>
}
}, {
title: '列表',
key: 'resources',
dataIndex: 'resources',
render: (text, record) => {
let data = [];
console.log()
text.map(s => { s.name !== "整治汇总编辑" ? data.push({ label: s.name, value: s.code }) : '' })
let parentCode = record.code;
return <CheckboxGroup
disabled={userSelected === "SuperAdmin" || userType === 4}
options={data}
value={roleCheck[parentCode] || []}
onChange={value => {
const checkArr = JSON.parse(JSON.stringify(roleCheck));
const parentCheck = JSON.parse(JSON.stringify(parentRoleCheck));
const ind = JSON.parse(JSON.stringify(indeterminate));
const currentCode = roleData.find(r => r.code == parentCode) || {}
checkArr[parentCode] = value;
ind[parentCode] = !!value.length && value.length < currentCode.resources.length
parentCheck[parentCode] = value.length === currentCode.resources.length
setRoleCheck(checkArr);
setIndeterminate(ind);
setParentRoleCheck(parentCheck);
setResData(checkArr)
}}
/>
}
}]}
></Table >
)
}
export default Resource

171
web/client/src/sections/organization/components/userModal.js

@ -0,0 +1,171 @@
import React from 'react';
import { connect } from 'react-redux';
import { Spin, Card, Modal, TreeSelect, message } from 'antd';
import ProForm, { ProFormText, ModalForm, ProFormSwitch, ProFormTreeSelect } from '@ant-design/pro-form';
const UserModal = (props) => {
const { visible, modalType, depData, onVisibleChange, onConfirm, editData } = props
const reg_tel = /^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$/;
const onFinish = (values) => {
if (onConfirm) {
onConfirm(values);
}
}
const mobile = (value) => {
if (reg_tel.test(value)) {
return
}
return message('请输入姓名')
}
return (
<Spin spinning={false}>
<ModalForm
title={modalType == 'edit' ? '编辑用户' : '新建用户'}
visible={visible}
onVisibleChange={onVisibleChange}
onFinish={onFinish}
destroyOnClose
initialValues={
modalType == 'edit' ?
{
contract: editData
} :
{
contract: {
enable: true
}
}
}
>
<ProForm.Group>
<ProFormText
name={['contract', 'name']}
maxLength={24}
width="md"
label="姓名"
required
placeholder="请输入姓名"
rules={[{ required: true, message: '请输入姓名' }]}
/>
<ProFormText
name={['contract', 'phone']}
width="md"
label="用户名(手机号)"
required
fieldProps={{
maxLength: 11,
}}
getValueFromEvent={(event) => {
return event.target.value.replace(/\D/g, '')
}}
placeholder="请输入用户名(手机号)"
rules={[
{ required: true, valueType: Number, max: 11 }, { pattern: /^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$/, message: "请输入正确的手机号" }
]}
/>
</ProForm.Group>
<ProForm.Group>
<ProFormTreeSelect
name={['contract', 'departmentId']}
placeholder="请选择所属部门"
width="md"
label="所属部门"
required
fieldNames={{
title: 'name',
key: 'id',
children: 'subordinate'
}}
onSelect={(selectedKeys, { selected, selectedNodes }) => {
if (selected) {
setDepSelectedKeys(selectedKeys)
setDepSelected(selectedNodes[0].name || "")
dispatch(getDepUser(selectedKeys[0]))
}
}}
fieldProps={{
fieldNames: {
label: 'title',
},
treeDefaultExpandAll: false,
}}
rules={[{ required: true, message: '请选择所属部门' }]}
request={async () => {
console.log(depData);
return depData
}}
expandedKeys={["title"]}
/>
< ProFormText
name={['contract', 'post']}
width="md"
label="职位"
// required
placeholder="请输入职位"
/>
</ProForm.Group>
<ProForm.Group>
<ProFormText
name={['contract', 'email']}
width="md"
label="邮箱"
// required
placeholder="请输入邮箱"
rules={[
// { required: true, message: '请输入邮箱' },
{ type: 'email', message: '请输入正确格式的邮箱' },
]}
/>
{modalType == 'edit' ? null : <ProFormText.Password
name={['contract', 'password']}
width="md"
label="密码"
required
placeholder="请输入密码"
fieldProps={{
autocomplete: 'new-password'
}}
rules={[
{ required: true, message: '请填写密码' },
{ min: 6, message: '请填写至少6位密码' },
]}
/>}
</ProForm.Group>
<ProForm.Group>
<ProFormSwitch
name={['contract', 'enable']}
width="md"
label="是否启用"
placeholder="请选择"
// defaultChecked
valuePropName="checked"
/>
</ProForm.Group>
</ModalForm>
</Spin>
)
}
function mapStateToProps(state) {
const { depMessage } = state;
const pakData = (dep) => {
// console.log(dep);
return dep.map((d) => {
return {
title: d.name,
value: d.id,
// key: d.id,
children: pakData(d.subordinate)
}
})
}
let depData = pakData(depMessage.data || [])
return {
loading: depMessage.isRequesting,
depData,
};
}
export default connect(mapStateToProps)(UserModal);

149
web/client/src/sections/organization/containers/authority.js

@ -0,0 +1,149 @@
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { Spin, Row, Col, Card, Button, Tree, Empty } from 'antd';
import { getDepMessage, getDepUser } from '../actions/user';
import { getResource, getUserResource, postUserRes } from '../actions/authority';
import Resource from '../components/resource';
const Authority = (props) => {
const { dispatch, loading, depMessage, depUser, resource, userResource, clientHeight } = props
const [depSelectedKeys, setDepSelectedKeys] = useState([])
const [userSelectedKeys, setUserSelectedKeys] = useState([])
const [depSelected, setDepSelected] = useState()
const [userSelected, setUserSelected] = useState()
const [resCode, setResCode] = useState({})
const [useName, setUseName] = useState()// 选中名字
const [userType,setUserType]=useState()
console.log(resource)
useEffect(() => {
dispatch(getResource())
if (!(depMessage && depMessage.length)) {
dispatch(getDepMessage())
}
}, [])
useEffect(() => {
if (depMessage.length) {
setDepSelectedKeys([depMessage[0].id])
setDepSelected([depMessage[0].name])
dispatch(getDepUser(depMessage[0].id))
}
}, [depMessage])
useEffect(() => {
if (depUser.length) {
setUserSelectedKeys([depUser[0].id])
setUserSelected(depUser[0].username)
dispatch(getUserResource(depUser[0].id))
setUseName(depUser[0].name)
}
console.log(depUser, 'depUser')
}, [depUser])
const handleSave = () => {
dispatch(postUserRes({ userId: userSelectedKeys[0], resCode: resCode })).then(res => {
if (res.success) {
dispatch(getUserResource(userSelectedKeys[0]))
}
})
}
return (
<Spin spinning={loading}>
<Row gutter={16}>
<Col span={4} style={{ height: '100%' }}>
<Card title="部门" bordered={false} bodyStyle={{ padding: 8, paddingTop: 24 }}>
{
depMessage.length ?
<Tree
height={clientHeight - 100}
defaultExpandedKeys={[depMessage[0].id]}
selectedKeys={depSelectedKeys}
onSelect={(selectedKeys, { selected, selectedNodes, node }) => {
setUserType(selectedNodes[0].type)
if (selected) {
setDepSelectedKeys(selectedKeys)
setDepSelected(selectedNodes[0].name || "")
dispatch(getDepUser(selectedKeys[0]))
}
}}
treeData={depMessage}
fieldNames={{
title: 'name',
key: 'id',
children: 'subordinate'
}}
/> : ''
}
</Card>
</Col>
<Col span={4} style={{ height: '100%', }}>
<Card title={`[${depSelected}] 用户列表`} bordered={false} bodyStyle={{ padding: 8, paddingTop: 24 }}>
{
depUser.length ?
<Tree
height={clientHeight - 100}
defaultSelectedKeys={[depUser[0].id]}
selectedKeys={userSelectedKeys}
onSelect={(selectedKeys, { selected, selectedNodes, node, event }) => {
const name = node.name
setUseName(name)
if (selected) {
setUserSelectedKeys(selectedKeys)
setUserSelected(selectedNodes[0].username || '')
dispatch(getUserResource(selectedKeys[0]))
}
}}
treeData={depUser}
fieldNames={{
title: 'name',
key: 'id'
}}
/> : <Empty />
}
</Card>
</Col>
<Col span={16} style={{ height: '100%', }}>
{depUser.length ?
<Card title={`[${useName ? useName : '管理员'}] 功能范围`} bordered={false} bodyStyle={{ padding: 8, paddingTop: 24 }}>
<Resource
userSelected={userSelected}
roleData={resource}
userRole={userResource}
setResCode={setResCode}
userType={userType}
/>
<Row type="flex" justify="center" style={{ marginBottom: 16, marginTop: 16, textAlign: 'center' }}>
<Col span="24">
<Button
disabled={userSelected === "SuperAdmin"||userType===4}
onClick={handleSave}
style={{ width: '60%' }}
type='primary'>保存修改</Button>
</Col></Row>
</Card>
: <Card title={`[]功能范围`} bordered={false} bodyStyle={{ padding: 8, paddingTop: 24 }}>
<Empty />
</Card>
}
</Col>
</Row>
</Spin >
)
}
function mapStateToProps(state) {
const { userResource, resource, depMessage, depUser, global } = state;
return {
clientHeight: global.clientHeight,
loading: depMessage.isRequesting || depUser.isRequesting || resource.isRequesting,
userResource: userResource.data || [],
resource: resource.data || [],
depMessage: depMessage.data || [],
depUser: depUser.data || []
};
}
export default connect(mapStateToProps)(Authority);

6
web/client/src/sections/organization/containers/index.js

@ -0,0 +1,6 @@
'use strict';
import Authority from './authority';
import UserManage from './user';
export { Authority, UserManage };

331
web/client/src/sections/organization/containers/user.js

@ -0,0 +1,331 @@
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { FormOutlined, DeleteOutlined } from '@ant-design/icons';
import { Spin, Tooltip, Button, Popconfirm, Row, Col, Tree, Card, Switch } from 'antd';
import ProTable from '@ant-design/pro-table';
import { getDepMessage, getDepUser, createUser, updateUser, delUser, resetPwd, createDept, updateDept, delDept } from '../actions/user';
import UserModal from '../components/userModal';
import ResetPwd from '../components/resetPwd';
import DeptModal from '../components/deptModal';
const TreeNode = Tree.TreeNode;
const user = JSON.parse(sessionStorage.getItem('user'));
const UserManage = (props) => {
const { dispatch, loading, depMessage, depUser, clientHeight } = props;
// 部门
const [deptModalVisible, setDeptModalVisible] = useState(false);
const [deptModalType, setDeptModalType] = useState();
const [deptModalRecord, setDeptModalRecord] = useState();
// 成员
const [modalVisible, setModalVisible] = useState(false);
const [modalType, setModalType] = useState();
const [modalRecord, setModalRecord] = useState();
const [pwdModalVisible, setPwdModalVisible] = useState(false);
const [depSelectedKeys, setDepSelectedKeys] = useState([])
const [rowSelected, setRowSelected] = useState([])
useEffect(() => {
dispatch(getDepMessage())
}, [])
useEffect(() => {
if (depMessage.length) {
setDepSelectedKeys([depMessage[0].id])
dispatch(getDepUser(depMessage[0].id))
}
}, [depMessage])
const columns = [
{
title: '姓名',
dataIndex: 'name',
}, {
title: '用户名(手机号)',
dataIndex: 'username',
},
{
title: '职位',
dataIndex: 'post',
}, {
title: '邮箱',
dataIndex: 'email',
}, {
title: '启用状态',
dataIndex: 'enable',
render: (_, r) => {
return <Switch checkedChildren="启用" unCheckedChildren="禁用" disabled defaultChecked={r.enable} />
}
}, {
title: '操作',
dataIndex: 'action',
render: (dom, record) => {
return record.username == 'SuperAdmin' ? '' : [
<Button type="link" onClick={() => { openModal('edit', record) }}>编辑</Button>,
<Popconfirm
title="确认删除?"
onConfirm={() => {
delUsers([record.id])
}}
>
<Button type="link">删除</Button>
</Popconfirm>,
<Button
type="link"
onClick={() => {
setModalRecord(record);
setPwdModalVisible(true);
}}
>重置密码</Button>
]
},
},
];
//弹窗确认
const onConfirm = (values) => {
if (modalType == 'edit') {
dispatch(updateUser(modalRecord.id, values.contract)).then(res => {
if (res.success) {
setModalVisible(false);
dispatch(getDepUser(depSelectedKeys[0]));
}
});
} else {
dispatch(createUser(values.contract)).then(res => {
if (res.success) {
setModalVisible(false);
dispatch(getDepUser(depSelectedKeys[0]));
}
});
}
}
//打开弹窗
const openModal = (type, record) => {
setModalVisible(true);
setModalType(type);
if (type == 'edit') {
setModalRecord(record);
} else {
setModalRecord(null);
}
}
//删除用户
const delUsers = (ids, type) => {
dispatch(delUser(ids)).then(res => {
dispatch(getDepUser(depSelectedKeys[0]));
if (type == 'batch') {
setRowSelected([]);
}
});
}
//重置密码
const onPwdConfirm = (values) => {
dispatch(resetPwd(modalRecord.id, { password: values.password })).then(res => {
if (res.success) {
setPwdModalVisible(false);
dispatch(getDepUser(depSelectedKeys[0]));
}
});
}
const openDeptModal = (type, record) => {
console.log(type, record, 'type, record')
setDeptModalVisible(true);
setDeptModalType(type);
if (type === 'edit') {
setDeptModalRecord(record);
} else {
setDeptModalRecord(null);
}
}
const onDeptConfirm = (values) => {
if (deptModalType === 'edit') {
dispatch(updateDept(deptModalRecord.id, values.contract)).then(res => {
if (res.success) {
setDeptModalVisible(false);
dispatch(getDepMessage())
}
});
} else {
dispatch(createDept(values.contract)).then(res => {
if (res.success) {
setDeptModalVisible(false);
dispatch(getDepMessage())
}
});
}
}
const delDepartment = (id) => {
dispatch(delDept(id)).then(res => {
if (res.success) {
dispatch(getDepMessage())
}
});
}
const renderTree = (item, id) => {
// let cannotDel = item.users.length || item.subordinate?.filter(is => is.users.length).length;//自己下面有成员 或者下级部门下有成员 不能删除
return <div style={{ display: 'flex', width: '6vw', justifyContent: 'space-between' }}>
<Tooltip title={item.name}>
<div style={{ width: '70%', textOverflow: 'ellipsis', whiteSpace: 'nowrap', overflow: 'hidden' }}>{item.name}</div>
</Tooltip>
<div style={{ width: '30%' }} >
{
depSelectedKeys == id && user.username === "SuperAdmin" ?
<>
<FormOutlined onClick={() => {
setDeptModalRecord(item)
setDeptModalVisible(true)
setDeptModalType('edit')
}} />
{
<Popconfirm title='是否确认删除?' onConfirm={() => { delDepartment(id) }}>
<DeleteOutlined style={{ marginLeft: 5 }} />
</Popconfirm>
}
</> : null
}
</div>
</div>
}
return (<div >
<Spin spinning={loading} /* style={{ height: "calc(100vh - 70px)" }} */>
<Row gutter={16} /* style={{ overflow: "scroll" }} */>
<Col flex="260px" style={{ height: '100%' }}>
<Card title="部门" bordered={false} bodyStyle={{ padding: 8, paddingTop: 24, }}>
{
user.username === "SuperAdmin" && <Button
type="primary"
key="primary"
style={{ margin: '16px 0px' }}
onClick={() => openDeptModal('create')}
>新建部门</Button>
}
{
depMessage.length ?
<Tree
height={clientHeight - 95}
defaultExpandedKeys={[depMessage[0].id]}
selectedKeys={depSelectedKeys}
onSelect={(selectedKeys, e) => {
if (e.selected) {
setDepSelectedKeys(selectedKeys)
dispatch(getDepUser(selectedKeys[0]))
}
}}
// treeData={depMessage}
// fieldNames={{
// title: 'name',
// key: 'id',
// children: 'subordinate'
// }}
>
{
depMessage.map((s, index) => {
return <TreeNode title={renderTree(s, s.id)} key={s.id} >
{
s.subordinate.map(k => {
return <TreeNode title={renderTree(k, k.id)} key={k.id} onMouseOver={() => { setIShowIcon(k.id) }} onMouseOut={() => { setIShowIcon(null) }}>
</TreeNode>
})
}
</TreeNode>
})
}
</Tree> : ''
}
</Card>
</Col>
<Col /* flex="auto" */ style={{ width: "calc(100% - 260px)", height: '100%', display: "black" }}>
<Card title="用户" bordered={false} height={clientHeight} bodyStyle={{ padding: 8, paddingTop: 24, overflow: "hidden", width: "100%" }}>
<ProTable
columns={columns}
dataSource={depUser}
style={{ width: "100% ", height: clientHeight - 95, overflow: "auto" }}
rowSelection={{
selectedRowKeys: rowSelected,
onChange: (selectedRowKeys) => {
setRowSelected(selectedRowKeys);
},
getCheckboxProps: (record) => {
return {
disabled: record.username === 'SuperAdmin',
}
},
}}
options={false}
search={false}
rowKey="id"
toolBarRender={() => [
<span>
<Button
type="primary"
key="primary"
style={{ marginRight: 10 }}
onClick={() => openModal('create')}
>新建用户</Button>
<Button style={{ marginRight: 10 }} onClick={() => { dispatch(getDepUser(depSelectedKeys[0])); }}>刷新</Button>
<Popconfirm title="确认删除?" onConfirm={() => { delUsers(rowSelected, 'batch') }}>
<Button>批量删除</Button>
</Popconfirm>
</span>
]}
/>
</Card>
{
deptModalVisible ?
<DeptModal
visible={deptModalVisible}
onVisibleChange={setDeptModalVisible}
modalType={deptModalType}
onConfirm={onDeptConfirm}
editData={deptModalRecord}
depts={depMessage}
/>
: ''
}
{
depMessage.length && modalVisible ?
<UserModal
visible={modalVisible}
onVisibleChange={setModalVisible}
modalType={modalType}
onConfirm={onConfirm}
editData={modalRecord}
/>
: ''
}
{pwdModalVisible ? <ResetPwd visible={pwdModalVisible}
onVisibleChange={setPwdModalVisible}
onConfirm={onPwdConfirm} /> : ''}
</Col>
</Row>
</Spin>
</div>
)
}
function mapStateToProps(state) {
const { depMessage, depUser, global } = state;
return {
clientHeight: global.clientHeight,
loading: depMessage.isRequesting,
depMessage: depMessage.data || [],
depUser: depUser.data || []
};
}
export default connect(mapStateToProps)(UserManage);

15
web/client/src/sections/organization/index.js

@ -0,0 +1,15 @@
'use strict';
import reducers from './reducers';
import routes from './routes';
import actions from './actions';
import { getNavItem } from './nav-item';
export default {
key: 'organization',
name: '',
reducers: reducers,
routes: routes,
actions: actions,
getNavItem: getNavItem
};

22
web/client/src/sections/organization/nav-item.js

@ -0,0 +1,22 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { Menu } from 'antd';
import { SettingOutlined } from '@ant-design/icons';
const SubMenu = Menu.SubMenu;
export function getNavItem(user, dispatch) {
// if (!Func.isAuthorized("ORG_MANAGE")) {
// return null
// }
return (
<SubMenu key="organization" icon={<SettingOutlined />} title={'组织管理'}>
<Menu.Item key="userManage">
<Link to="/organization/user">部门成员</Link>
</Menu.Item>
<Menu.Item key="authority">
<Link to="/organization/authority">权限配置</Link>
</Menu.Item>
</SubMenu>
);
}

5
web/client/src/sections/organization/reducers/index.js

@ -0,0 +1,5 @@
'use strict';
export default {
};

26
web/client/src/sections/organization/routes.js

@ -0,0 +1,26 @@
'use strict';
import { UserManage, Authority } from './containers';
export default [{
type: 'inner',
route: {
path: '/organization',
key: 'organization',
breadcrumb: '组织管理',
menuSelectKeys: ['userManage'],
menuOpenKeys: ['organization'],
childRoutes: [{
path: '/user',
key: 'userManage',
menuSelectKeys: ['userManage'],
component: UserManage,
breadcrumb: '部门成员',
}, {
path: '/authority',
key: 'authority',
component: Authority,
menuSelectKeys: ['authority'],
breadcrumb: '权限配置',
}]
}
}];

17
web/client/src/utils/webapi.js

@ -7,6 +7,23 @@ export const ApiTable = {
validatePhone: 'validate/phone',
getUserSiteList: 'user/site/list',
// 组织管理-用户管理
getDepMessage: 'organization/department',
createDept: '/organization/dept/add',
updateDept: '/organization/dept/{id}/modify',
delDept: '/organization/dept/{id}',
getDepUser: 'organization/department/{depId}/user',
createUser: 'organization/department/user',
updateUser: 'organization/department/user/{id}',
delUser: 'organization/department/user/{ids}',
resetPwd: '/organization/department/user/resetPwd/{id}',
// 用户权限
getResource: 'resource',
getUserResource: 'user/resource',
postUserRes: 'user/resource',
//安全风险预报
getSiteWeekRegiste: 'sites/report',
getRiskReportList: 'risk/report',

Loading…
Cancel
Save