liujiangyong
10 months ago
48 changed files with 1862 additions and 72 deletions
@ -0,0 +1,49 @@ |
|||
'use strict'; |
|||
|
|||
async function getLog(ctx, next) { |
|||
try { |
|||
const models = ctx.fs.dc.models; |
|||
const { limit, page, startTime, endTime, keyword } = ctx.query |
|||
|
|||
let findOption = { |
|||
where: {}, |
|||
order: [['time', 'DESC']], |
|||
include: [{ |
|||
model: models.User, |
|||
attributes: ["name", "username"], |
|||
}], |
|||
distinct: true |
|||
} |
|||
if (limit) { |
|||
findOption.limit = Number(limit) |
|||
} |
|||
if (page && limit) { |
|||
findOption.offset = page * limit |
|||
} |
|||
if (startTime && endTime) { |
|||
findOption.where.time = { $between: [startTime, endTime] }; |
|||
} |
|||
if (keyword) { |
|||
findOption.where['$or'] = { |
|||
clientType: { $like: `%${keyword}%` }, |
|||
content: { $like: `%${keyword}%` }, |
|||
parameter: { $like: `%${keyword}%` }, |
|||
} |
|||
} |
|||
|
|||
const res = await models.OperationLog.findAndCountAll(findOption) |
|||
|
|||
ctx.status = 200; |
|||
ctx.body = res |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = { |
|||
"message": "获取操作日志失败" |
|||
} |
|||
} |
|||
} |
|||
|
|||
module.exports = { |
|||
getLog, |
|||
} |
@ -0,0 +1,102 @@ |
|||
async function getResource(ctx, next) { |
|||
try { |
|||
const models = ctx.fs.dc.models; |
|||
|
|||
const res = await models.Resource.findAll({ |
|||
where: { parentCode: 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: ["resourceCode"], |
|||
raw: true, |
|||
where: { userId: userId } |
|||
}) |
|||
|
|||
const addRes = resCode.filter(r => !res.some(rr => rr.resourceCode == r)).map(r => { return { userId: userId, resourceCode: r } }); |
|||
const delRes = res.filter(r => !resCode.includes(r.resourceCode)).map(r => r.resourceCode); |
|||
addRes.length && await models.UserResource.bulkCreate(addRes, { transaction: transaction }); |
|||
delRes.length && await models.UserResource.destroy({ |
|||
where: { |
|||
resourceCode: { $in: delRes }, |
|||
userId: userId |
|||
}, |
|||
transaction: transaction |
|||
}) |
|||
|
|||
const operationUserId = ctx.fs.api.userId; |
|||
const user = await models.User.findOne({ |
|||
attributes: ["name"], |
|||
where: { id: userId }, |
|||
raw: true, |
|||
transaction: transaction, |
|||
}) |
|||
await models.OperationLog.create({ |
|||
time: new Date().getTime(), |
|||
clientType: ctx.header['user-agent'], |
|||
content: `修改 (${user.name}) 用户权限`, |
|||
parameter: null, |
|||
userId: operationUserId, |
|||
}, { 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 |
|||
}; |
@ -0,0 +1,204 @@ |
|||
'use strict'; |
|||
const Hex = require('crypto-js/enc-hex'); |
|||
const MD5 = require('crypto-js/md5'); |
|||
|
|||
async function getUser(ctx, next) { |
|||
try { |
|||
const models = ctx.fs.dc.models; |
|||
const userRes = await models.User.findAll({ |
|||
where: { |
|||
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.username, |
|||
delete: false |
|||
} |
|||
}) |
|||
|
|||
if (repeatUserNameCount) { |
|||
errMsg = '已有当前用户名' |
|||
throw errMsg |
|||
} |
|||
|
|||
await models.User.create({ |
|||
name: data.name, |
|||
username: data.username, |
|||
password: Hex.stringify(MD5(data.password)), |
|||
delete: false, |
|||
}) |
|||
const userId = ctx.fs.api.userId; |
|||
await models.OperationLog.create({ |
|||
time: new Date().getTime(), |
|||
clientType: ctx.header['user-agent'], |
|||
content: `新建用户:${data.name}`, |
|||
parameter: null, |
|||
userId, |
|||
}) |
|||
|
|||
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.findOne({ |
|||
where: { |
|||
username: data.username, |
|||
delete: false |
|||
}, |
|||
raw: true, |
|||
}) |
|||
|
|||
if (repeatUserNameCount && repeatUserNameCount.id != id) { |
|||
errMsg = '已有当前用户名' |
|||
throw errMsg |
|||
} |
|||
|
|||
await models.User.update({ |
|||
name: data.name, |
|||
username: data.username, |
|||
delete: false, |
|||
}, { |
|||
where: { id } |
|||
}); |
|||
|
|||
const userId = ctx.fs.api.userId; |
|||
await models.OperationLog.create({ |
|||
time: new Date().getTime(), |
|||
clientType: ctx.header['user-agent'], |
|||
content: `修改 (${data.name}) 用户信息`, |
|||
parameter: null, |
|||
userId, |
|||
}) |
|||
|
|||
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(','); |
|||
const delUser = await models.User.update({ |
|||
delete: true, |
|||
}, { |
|||
where: { |
|||
id: { $in: userIds }, |
|||
}, |
|||
returning: true, |
|||
}); |
|||
|
|||
const userId = ctx.fs.api.userId; |
|||
const userName = delUser[1].map(item => item.name).join() |
|||
await models.OperationLog.create({ |
|||
time: new Date().getTime(), |
|||
clientType: ctx.header['user-agent'], |
|||
content: `删除用户:${userName}`, |
|||
parameter: null, |
|||
userId, |
|||
}) |
|||
|
|||
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 { password } = ctx.request.body; |
|||
if (!password) { |
|||
ctx.status = 400; |
|||
ctx.body = { "message": "请输入修改密码" }; |
|||
return; |
|||
} |
|||
const userRes = await models.User.findOne({ |
|||
where: { id }, |
|||
attributes: ['id'] |
|||
}); |
|||
if (userRes) { |
|||
const updateUser = await models.User.update( |
|||
{ password: Hex.stringify(MD5(password)) }, |
|||
{ |
|||
where: { id }, |
|||
returning: true, |
|||
}, |
|||
); |
|||
const userId = ctx.fs.api.userId; |
|||
await models.OperationLog.create({ |
|||
time: new Date().getTime(), |
|||
clientType: ctx.header['user-agent'], |
|||
content: `修改 (${updateUser[1][0].name}) 用户密码`, |
|||
parameter: null, |
|||
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 = { |
|||
getUser, |
|||
creatUser, |
|||
updateUser, |
|||
deleteUser, |
|||
resetPwd, |
|||
} |
@ -0,0 +1,74 @@ |
|||
/* eslint-disable*/ |
|||
'use strict'; |
|||
|
|||
module.exports = dc => { |
|||
const DataTypes = dc.ORM; |
|||
const sequelize = dc.orm; |
|||
const OperationLog = sequelize.define("operationLog", { |
|||
id: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: true, |
|||
field: "id", |
|||
autoIncrement: true, |
|||
}, |
|||
time: { |
|||
type: DataTypes.DATE, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: "操作时间", |
|||
primaryKey: false, |
|||
field: "time", |
|||
autoIncrement: false |
|||
}, |
|||
clientType: { |
|||
type: DataTypes.STRING, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: "客户端类型", |
|||
primaryKey: false, |
|||
field: "client_type", |
|||
autoIncrement: false |
|||
}, |
|||
content: { |
|||
type: DataTypes.STRING, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: "操作内容", |
|||
primaryKey: false, |
|||
field: "content", |
|||
autoIncrement: false |
|||
}, |
|||
parameter: { |
|||
type: DataTypes.STRING, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: "操作参数", |
|||
primaryKey: false, |
|||
field: "parameter", |
|||
autoIncrement: false |
|||
}, |
|||
userId: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: "操作用户ID", |
|||
primaryKey: false, |
|||
field: "user_id", |
|||
autoIncrement: false, |
|||
references: { |
|||
key: "id", |
|||
model: "t_user" |
|||
} |
|||
}, |
|||
}, { |
|||
tableName: "t_operation_log", |
|||
comment: "", |
|||
indexes: [] |
|||
}); |
|||
|
|||
dc.models.OperationLog = OperationLog; |
|||
return OperationLog; |
|||
}; |
@ -0,0 +1,43 @@ |
|||
/* eslint-disable*/ |
|||
'use strict'; |
|||
|
|||
module.exports = dc => { |
|||
const DataTypes = dc.ORM; |
|||
const sequelize = dc.orm; |
|||
const Resource = sequelize.define("resource", { |
|||
code: { |
|||
type: DataTypes.STRING, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: true, |
|||
field: "code", |
|||
autoIncrement: false, |
|||
}, |
|||
name: { |
|||
type: DataTypes.STRING, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "name", |
|||
autoIncrement: false |
|||
}, |
|||
parentCode: { |
|||
type: DataTypes.STRING, |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "parent_code", |
|||
autoIncrement: false, |
|||
}, |
|||
}, { |
|||
tableName: "t_resource", |
|||
comment: "", |
|||
indexes: [] |
|||
}); |
|||
|
|||
dc.models.Resource = Resource; |
|||
return Resource; |
|||
}; |
@ -0,0 +1,51 @@ |
|||
/* eslint-disable*/ |
|||
'use strict'; |
|||
|
|||
module.exports = dc => { |
|||
const DataTypes = dc.ORM; |
|||
const sequelize = dc.orm; |
|||
const UserResource = sequelize.define("userResource", { |
|||
id: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: true, |
|||
field: "id", |
|||
autoIncrement: true, |
|||
}, |
|||
userId: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "user_id", |
|||
autoIncrement: false, |
|||
references: { |
|||
key: "id", |
|||
model: "t_user" |
|||
} |
|||
}, |
|||
resourceCode: { |
|||
type: DataTypes.STRING, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "resource_code", |
|||
autoIncrement: false, |
|||
references: { |
|||
key: "code", |
|||
model: "t_resource" |
|||
} |
|||
} |
|||
}, { |
|||
tableName: "t_user_resource", |
|||
comment: "", |
|||
indexes: [] |
|||
}); |
|||
|
|||
dc.models.UserResource = UserResource; |
|||
return UserResource; |
|||
}; |
@ -0,0 +1,19 @@ |
|||
'use strict'; |
|||
|
|||
const operationLog = require('../../controllers/operationLogs/index'); |
|||
|
|||
module.exports = function (app, router, opts) { |
|||
|
|||
app.fs.api.logAttr['GET/operationLog'] = { content: '获取操作日志', visible: false }; |
|||
router.get('/operationLog', operationLog.getLog); |
|||
|
|||
// app.fs.api.logAttr['POST/operationLog'] = { content: '创建操作日志', visible: false };
|
|||
// router.post('/operationLog', operationLog.creatLog);
|
|||
|
|||
// app.fs.api.logAttr['PUT/operationLog/:id'] = { content: '修改操作日志', visible: false };
|
|||
// router.put('/operationLog/:id', operationLog.updateLog);
|
|||
|
|||
// app.fs.api.logAttr['DEL/operationLog/:ids'] = { content: '删除操作日志', visible: false };
|
|||
// router.del('/operationLog/:ids', operationLog.deleteLog);
|
|||
|
|||
}; |
@ -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); |
|||
}; |
@ -0,0 +1,22 @@ |
|||
'use strict'; |
|||
|
|||
const user = require('../../controllers/organization/user'); |
|||
|
|||
module.exports = function (app, router, opts) { |
|||
|
|||
app.fs.api.logAttr['GET/organization/user'] = { content: '获取用户信息', visible: false }; |
|||
router.get('/organization/user', user.getUser); |
|||
|
|||
app.fs.api.logAttr['POST/organization/user'] = { content: '创建用户信息', visible: false }; |
|||
router.post('/organization/user', user.creatUser); |
|||
|
|||
app.fs.api.logAttr['PUT/organization/user/:id'] = { content: '修改用户信息', visible: false }; |
|||
router.put('/organization/user/:id', user.updateUser); |
|||
|
|||
app.fs.api.logAttr['DEL/organization/user/:ids'] = { content: '删除用户信息', visible: false }; |
|||
router.del('/organization/user/:ids', user.deleteUser); |
|||
|
|||
app.fs.api.logAttr['PUT/organization/user/resetPwd/:id'] = { content: '重置用户密码', visible: false }; |
|||
router.put('/organization/user/resetPwd/:id', user.resetPwd); |
|||
|
|||
}; |
@ -0,0 +1,16 @@ |
|||
INSERT INTO |
|||
"public"."t_user" ( |
|||
"id", |
|||
"name", |
|||
"username", |
|||
"password", |
|||
"delete" |
|||
) |
|||
VALUES |
|||
( |
|||
default, |
|||
'超级管理员', |
|||
'SuperAdmin', |
|||
'e10adc3949ba59abbe56e057f20f883e', |
|||
'f' |
|||
); |
@ -0,0 +1,47 @@ |
|||
INSERT INTO "public"."t_resource" VALUES ('ORG_MANAGE', '组织管理', NULL); |
|||
INSERT INTO "public"."t_resource" VALUES ('ORG_MEMBER', '用户管理', 'ORG_MANAGE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('ORG_AUTH', '权限配置', 'ORG_MANAGE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('OPERATION_LOG', '操作日志', NULL); |
|||
INSERT INTO "public"."t_resource" VALUES ('OPERATION_LOG_VIEW', '操作日志查看', 'OPERATION_LOG'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_CONTROL', '泵站控制', NULL); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_WATER_CONTROL', '泵站水泵控制', 'PUMP_CONTROL'); |
|||
INSERT INTO "public"."t_resource" VALUES ('MONITORING_SCOPE', '泵站监测', NULL); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3569', '八月湖二站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3590', '张坊电排站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3592', '东山电排站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3593', '利用站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3594', '杨家湾站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3595', '汇仁大道补水站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3596', '河下电排站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3597', '石岐补水站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3598', '石岐电排站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3599', '三山电排站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3600', '万寿湖电排站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3601', '河外电排站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3642', '沥山电排站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3652', '象湖泵站', 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3653', '雄溪泵站', 'MONITORING_SCOPE'); |
|||
|
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'ORG_MANAGE'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'ORG_MEMBER'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'ORG_AUTH'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'OPERATION_LOG'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'OPERATION_LOG_VIEW'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_CONTROL'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_WATER_CONTROL'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'MONITORING_SCOPE'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3569'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3590'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3592'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3593'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3594'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3595'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3596'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3597'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3598'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3599'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3600'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3601'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3642'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3652'); |
|||
INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3653'); |
@ -0,0 +1,30 @@ |
|||
DROP TABLE IF EXISTS "public"."t_user"; |
|||
CREATE TABLE "public"."t_user" ( |
|||
"id" serial, |
|||
"name" varchar(64) NOT NULL, |
|||
"username" varchar(64) NOT NULL, |
|||
"password" varchar(255) NOT NULL, |
|||
"delete" bool NOT NULL DEFAULT false, |
|||
PRIMARY KEY ("id") |
|||
); |
|||
COMMENT ON COLUMN "public"."t_user"."username" IS '用户名 账号'; |
|||
|
|||
|
|||
DROP TABLE IF EXISTS "public"."t_resource"; |
|||
CREATE TABLE "public"."t_resource" ( |
|||
"code" varchar(128) NOT NULL, |
|||
"name" varchar(128) NOT NULL, |
|||
"parent_code" varchar(128), |
|||
PRIMARY KEY ("code") |
|||
); |
|||
|
|||
|
|||
DROP TABLE IF EXISTS "public"."t_user_resource"; |
|||
CREATE TABLE "public"."t_user_resource" ( |
|||
"id" serial, |
|||
"user_id" int4 NOT NULL, |
|||
"resource_code" varchar(128) NOT NULL, |
|||
PRIMARY KEY ("id"), |
|||
CONSTRAINT "user_resource_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."t_user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, |
|||
CONSTRAINT "user_resource_resource_code_fk" FOREIGN KEY ("resource_code") REFERENCES "public"."t_resource" ("code") ON DELETE NO ACTION ON UPDATE NO ACTION |
|||
); |
@ -0,0 +1,22 @@ |
|||
DROP TABLE IF EXISTS "public"."t_operation_log"; |
|||
|
|||
CREATE TABLE "public"."t_operation_log" ( |
|||
"id" serial, |
|||
"time" timestamptz NOT NULL, |
|||
"client_type" varchar(512) NOT NULL, |
|||
"content" varchar(255) NOT NULL, |
|||
"parameter" varchar(512), |
|||
"user_id" int4 NOT NULL, |
|||
PRIMARY KEY ("id"), |
|||
CONSTRAINT "operation_log_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."t_user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION |
|||
); |
|||
|
|||
COMMENT ON COLUMN "public"."t_operation_log"."time" IS '操作时间'; |
|||
|
|||
COMMENT ON COLUMN "public"."t_operation_log"."client_type" IS '客户端类型'; |
|||
|
|||
COMMENT ON COLUMN "public"."t_operation_log"."content" IS '操作内容'; |
|||
|
|||
COMMENT ON COLUMN "public"."t_operation_log"."parameter" IS '操作参数'; |
|||
|
|||
COMMENT ON COLUMN "public"."t_operation_log"."user_id" IS '操作用户ID'; |
@ -0,0 +1,7 @@ |
|||
'use strict'; |
|||
|
|||
import * as operationLogs from './operationLogs' |
|||
|
|||
export default { |
|||
...operationLogs, |
|||
} |
@ -0,0 +1,20 @@ |
|||
'use strict'; |
|||
|
|||
import { basicAction } from '@peace/utils' |
|||
import { ApiTable } from '$utils' |
|||
|
|||
export function getOperationLog(query) { |
|||
return dispatch => basicAction({ |
|||
type: 'get', |
|||
dispatch: dispatch, |
|||
actionType: 'GET_OPERATION_LOG', |
|||
url: ApiTable.getOperationLog, |
|||
query, |
|||
msg: { error: '获取操作日志失败' }, |
|||
// reducer: { name: 'operationLog' }
|
|||
}); |
|||
} |
|||
|
|||
export default { |
|||
getOperationLog, |
|||
} |
@ -0,0 +1,5 @@ |
|||
'use strict'; |
|||
|
|||
import OperationLogs from './operationLogs'; |
|||
|
|||
export { OperationLogs }; |
@ -0,0 +1,93 @@ |
|||
import React, { useEffect, useState } from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { Button } from 'antd'; |
|||
import ProTable from '@ant-design/pro-table'; |
|||
import { getOperationLog, } from '../actions/operationLogs'; |
|||
import moment from 'moment'; |
|||
|
|||
const UserManage = (props) => { |
|||
const { dispatch, clientHeight, user } = props |
|||
|
|||
const [dataSource, setDataSource] = useState([]); |
|||
const [date, setDate] = useState([moment().subtract(1, 'days'), moment()]); |
|||
|
|||
const columns = [ |
|||
{ |
|||
title: '关键字', |
|||
dataIndex: 'keyword', |
|||
hideInTable: true, |
|||
}, { |
|||
title: '时间', |
|||
dataIndex: 'time', |
|||
key: 'time', |
|||
valueType: 'dateRange', |
|||
fieldProps: { |
|||
value: date, |
|||
onChange: e => { setDate(e) } |
|||
}, |
|||
ellipsis: true, |
|||
width: 150, |
|||
render: (_, record) => { |
|||
console.log(record, 'record') |
|||
return <div>{moment(record.time).format('YYYY-MM-DD HH:mm:ss')}</div> |
|||
} |
|||
}, { |
|||
title: '客户端类型 ', |
|||
dataIndex: 'clientType', |
|||
key: 'clientType', |
|||
search: false, |
|||
ellipsis: true, |
|||
}, { |
|||
title: '内容', |
|||
dataIndex: 'content', |
|||
key: 'content', |
|||
search: false, |
|||
ellipsis: true, |
|||
}, { |
|||
title: '操作用户', |
|||
dataIndex: 'user', |
|||
key: 'user', |
|||
search: false, |
|||
ellipsis: true, |
|||
width: 150, |
|||
render: (_, record) => { |
|||
return <div>{record.user?.name}</div> |
|||
} |
|||
}, |
|||
]; |
|||
|
|||
return ( |
|||
<ProTable |
|||
columns={columns} |
|||
dataSource={dataSource || []} |
|||
pagination={{ pageSize: 20, size: 'default' }} |
|||
options={false} |
|||
rowKey="id" |
|||
request={async (params = {}) => { |
|||
const res = await dispatch(getOperationLog({ |
|||
limit: params?.pageSize, |
|||
page: params?.current - 1, |
|||
keyword: params?.keyword, |
|||
startTime: date ? date[0].format('YYYY-MM-DD') + ' 00:00:00' : '', |
|||
endTime: date ? date[1].format('YYYY-MM-DD') + ' 23:59:59' : '', |
|||
})); |
|||
setDataSource(res?.payload.data?.rows); |
|||
return { |
|||
...res, |
|||
total: res.payload.data.count ? res.payload.data.count : 0, |
|||
}; |
|||
}} |
|||
onReset={() => { setDate([moment().subtract(1, 'days'), moment()]) }} |
|||
/> |
|||
) |
|||
} |
|||
|
|||
function mapStateToProps(state) { |
|||
const { global, auth } = state; |
|||
return { |
|||
clientHeight: global.clientHeight, |
|||
user: auth.user, |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(UserManage); |
@ -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: 'operationLog', |
|||
name: '', |
|||
reducers: reducers, |
|||
routes: routes, |
|||
actions: actions, |
|||
getNavItem: getNavItem |
|||
}; |
@ -0,0 +1,20 @@ |
|||
import React from 'react'; |
|||
import { Link } from 'react-router-dom'; |
|||
import { Menu } from 'antd'; |
|||
import { UnorderedListOutlined } from '@ant-design/icons'; |
|||
import { Func } from '$utils'; |
|||
|
|||
const SubMenu = Menu.SubMenu; |
|||
|
|||
export function getNavItem(user, dispatch) { |
|||
if (!Func.isAuthorized("OPERATION_LOG")) { |
|||
return null |
|||
} |
|||
|
|||
return (<> |
|||
{Func.isAuthorized("OPERATION_LOG") && |
|||
<Menu.Item key="operationLog" icon={<UnorderedListOutlined />}> |
|||
<Link to="/operationLog">操作日志</Link> |
|||
</Menu.Item>} |
|||
</>); |
|||
} |
@ -0,0 +1,5 @@ |
|||
'use strict'; |
|||
|
|||
export default { |
|||
|
|||
}; |
@ -0,0 +1,14 @@ |
|||
'use strict'; |
|||
import { OperationLogs } from './containers'; |
|||
|
|||
export default [{ |
|||
type: 'inner', |
|||
route: { |
|||
path: '/operationLog', |
|||
key: 'operationLog', |
|||
breadcrumb: '操作日志', |
|||
// menuSelectKeys: ['operationLog'],
|
|||
menuOpenKeys: ['operationLog'], |
|||
component: OperationLogs, |
|||
} |
|||
}]; |
@ -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 |
|||
} |
@ -0,0 +1,9 @@ |
|||
'use strict'; |
|||
|
|||
import * as authority from './authority' |
|||
import * as user from './user' |
|||
|
|||
export default { |
|||
...authority, |
|||
...user, |
|||
} |
@ -0,0 +1,66 @@ |
|||
'use strict'; |
|||
|
|||
import { basicAction } from '@peace/utils' |
|||
import { ApiTable } from '$utils' |
|||
|
|||
export function getUser() { |
|||
return dispatch => basicAction({ |
|||
type: 'get', |
|||
dispatch: dispatch, |
|||
actionType: 'GET_USER', |
|||
url: ApiTable.getUser, |
|||
msg: { error: '获取用户信息失败' }, |
|||
reducer: { name: 'users' } |
|||
}); |
|||
} |
|||
|
|||
export function createUser(data) { |
|||
return dispatch => basicAction({ |
|||
type: 'post', |
|||
data, |
|||
dispatch: dispatch, |
|||
actionType: 'CREATE_USER', |
|||
url: ApiTable.createUser, |
|||
msg: { option: '新建用户' }, |
|||
}); |
|||
} |
|||
|
|||
export function updateUser(id, data) { |
|||
return dispatch => basicAction({ |
|||
type: 'put', |
|||
data, |
|||
dispatch: dispatch, |
|||
actionType: 'UPDATE_USER', |
|||
url: ApiTable.updateUser.replace('{id}', id), |
|||
msg: { option: '修改用户' }, |
|||
}); |
|||
} |
|||
|
|||
export function delUser(ids) { |
|||
return dispatch => basicAction({ |
|||
type: 'del', |
|||
dispatch: dispatch, |
|||
actionType: 'DEL_USER', |
|||
url: ApiTable.delUser.replace('{ids}', ids), |
|||
msg: { option: '删除用户' }, |
|||
}); |
|||
} |
|||
|
|||
export function resetPwd(id, data) { |
|||
return dispatch => basicAction({ |
|||
type: 'put', |
|||
data, |
|||
dispatch: dispatch, |
|||
actionType: 'RESET_PWD', |
|||
url: ApiTable.resetPwd.replace('{id}', id), |
|||
msg: { option: '重置用户密码' }, |
|||
}); |
|||
} |
|||
|
|||
export default { |
|||
getUser, |
|||
createUser, |
|||
updateUser, |
|||
delUser, |
|||
resetPwd |
|||
} |
@ -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); |
@ -0,0 +1,120 @@ |
|||
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({}); //二级权限码
|
|||
|
|||
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.resourceCode == 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={roleData} |
|||
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 |
@ -0,0 +1,93 @@ |
|||
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, onVisibleChange, onConfirm, editData } = props |
|||
|
|||
const onFinish = (values) => { |
|||
if (onConfirm) { |
|||
onConfirm(values); |
|||
} |
|||
} |
|||
|
|||
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', 'username']} |
|||
width="md" |
|||
label="用户名" |
|||
required |
|||
fieldProps={{ |
|||
maxLength: 11, |
|||
}} |
|||
getValueFromEvent={(event) => { |
|||
return event.target.value.replace(/\D/g, '') |
|||
}} |
|||
placeholder="请输入用户名" |
|||
rules={[ |
|||
{ required: true, }, { message: "请输入用户名" } |
|||
]} |
|||
/> |
|||
</ProForm.Group> |
|||
|
|||
<ProForm.Group> |
|||
{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> |
|||
</ModalForm> |
|||
</Spin> |
|||
) |
|||
} |
|||
|
|||
function mapStateToProps(state) { |
|||
const { } = state; |
|||
|
|||
return { |
|||
|
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(UserModal); |
@ -0,0 +1,109 @@ |
|||
import React, { useEffect, useState } from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { Spin, Row, Col, Card, Button, Tree, Empty } from 'antd'; |
|||
import { getUser } from '../actions/user'; |
|||
import { getResource, getUserResource, postUserRes } from '../actions/authority'; |
|||
import Resource from '../components/resource'; |
|||
|
|||
const Authority = (props) => { |
|||
const { dispatch, loading, users, resource, userResource, clientHeight } = props |
|||
const [userSelectedKeys, setUserSelectedKeys] = useState([]) |
|||
const [userSelected, setUserSelected] = useState() |
|||
const [resCode, setResCode] = useState({}) |
|||
const [useName, setUseName] = useState()// 选中名字
|
|||
const [userType, setUserType] = useState() |
|||
|
|||
useEffect(() => { |
|||
if (!users.length) dispatch(getUser()) |
|||
dispatch(getResource()) |
|||
}, []) |
|||
|
|||
useEffect(() => { |
|||
if (users.length) { |
|||
setUserSelectedKeys([users[0].id]) |
|||
setUserSelected(users[0].username) |
|||
dispatch(getUserResource(users[0].id)) |
|||
setUseName(users[0].name) |
|||
} |
|||
}, [users]) |
|||
|
|||
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 }}> |
|||
{ |
|||
users.length ? |
|||
<Tree |
|||
height={clientHeight - 100} |
|||
defaultSelectedKeys={[users[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={users} |
|||
fieldNames={{ |
|||
title: 'name', |
|||
key: 'id' |
|||
}} |
|||
/> : <Empty /> |
|||
} |
|||
</Card> |
|||
</Col> |
|||
<Col span={16} style={{ height: '100%', }}> |
|||
{users.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, users, global } = state; |
|||
|
|||
return { |
|||
clientHeight: global.clientHeight, |
|||
loading: users.isRequesting || resource.isRequesting, |
|||
userResource: userResource.data || [], |
|||
resource: resource.data || [], |
|||
users: users.data || [] |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(Authority); |
@ -0,0 +1,6 @@ |
|||
'use strict'; |
|||
|
|||
import Authority from './authority'; |
|||
import UserManage from './user'; |
|||
|
|||
export { Authority, UserManage }; |
@ -0,0 +1,186 @@ |
|||
import React, { useEffect, useState } from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { EllipsisOutlined } from '@ant-design/icons'; |
|||
import { Spin, Space, Button, Popconfirm, Row, Col, Tree, Table, Card, Switch } from 'antd'; |
|||
import ProTable from '@ant-design/pro-table'; |
|||
import { getUser, createUser, updateUser, delUser, resetPwd } from '../actions/user'; |
|||
import UserModal from '../components/userModal'; |
|||
import ResetPwd from '../components/resetPwd'; |
|||
|
|||
const TreeNode = Tree.TreeNode; |
|||
|
|||
const UserManage = (props) => { |
|||
const { dispatch, loading, users, clientHeight, user } = props |
|||
const [modalVisible, setModalVisible] = useState(false); |
|||
const [modalType, setModalType] = useState(); |
|||
const [modalRecord, setModalRecord] = useState(); |
|||
const [pwdModalVisible, setPwdModalVisible] = useState(false); |
|||
const [rowSelected, setRowSelected] = useState([]) |
|||
|
|||
useEffect(() => { |
|||
dispatch(getUser()) |
|||
}, []) |
|||
|
|||
const columns = |
|||
[ |
|||
{ |
|||
title: '姓名', |
|||
dataIndex: 'name', |
|||
}, { |
|||
title: '用户名', |
|||
dataIndex: 'username', |
|||
}, { |
|||
title: '操作', |
|||
dataIndex: 'action', |
|||
render: (dom, record) => { |
|||
|
|||
return record.username == 'SuperAdmin' |
|||
? user.username == 'SuperAdmin' |
|||
? <Button |
|||
type="link" |
|||
onClick={() => { |
|||
setModalRecord(record); |
|||
setPwdModalVisible(true); |
|||
}} |
|||
>重置密码</Button> |
|||
: '' |
|||
: [ |
|||
<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(getUser()); |
|||
} |
|||
}); |
|||
} else { |
|||
dispatch(createUser(values.contract)).then(res => { |
|||
if (res.success) { |
|||
setModalVisible(false); |
|||
dispatch(getUser()); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
} |
|||
|
|||
//打开弹窗
|
|||
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(getUser()); |
|||
if (type == 'batch') { |
|||
setRowSelected([]); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
//重置密码
|
|||
const onPwdConfirm = (values) => { |
|||
dispatch(resetPwd(modalRecord.id, { password: values.password })).then(res => { |
|||
if (res.success) { |
|||
setPwdModalVisible(false); |
|||
dispatch(getUser()); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
return ( |
|||
<Spin spinning={loading} /* style={{ height: "calc(100vh - 70px)" }} */> |
|||
<ProTable |
|||
columns={columns} |
|||
dataSource={users} |
|||
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(getUser()); }}>刷新</Button> |
|||
<Popconfirm title="确认删除?" onConfirm={() => { delUsers(rowSelected, 'batch') }}> |
|||
<Button>批量删除</Button> |
|||
</Popconfirm> |
|||
</span> |
|||
]} |
|||
/> |
|||
|
|||
{ |
|||
modalVisible ? |
|||
<UserModal |
|||
visible={modalVisible} |
|||
onVisibleChange={setModalVisible} |
|||
modalType={modalType} |
|||
onConfirm={onConfirm} |
|||
editData={modalRecord} |
|||
/> : '' |
|||
} |
|||
{pwdModalVisible ? <ResetPwd visible={pwdModalVisible} |
|||
onVisibleChange={setPwdModalVisible} |
|||
onConfirm={onPwdConfirm} /> : '' |
|||
} |
|||
</Spin> |
|||
) |
|||
} |
|||
|
|||
function mapStateToProps(state) { |
|||
const { users, global, auth } = state; |
|||
|
|||
return { |
|||
clientHeight: global.clientHeight, |
|||
users: users.data || [], |
|||
loading: users.isRequesting, |
|||
user: auth.user, |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(UserManage); |
@ -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 |
|||
}; |
@ -0,0 +1,28 @@ |
|||
import React from 'react'; |
|||
import { Link } from 'react-router-dom'; |
|||
import { Menu } from 'antd'; |
|||
import { SettingOutlined } from '@ant-design/icons'; |
|||
import { Func } from '$utils'; |
|||
|
|||
const SubMenu = Menu.SubMenu; |
|||
|
|||
export function getNavItem(user, dispatch) { |
|||
if (!Func.isAuthorized("ORG_MANAGE")) { |
|||
return null |
|||
} |
|||
|
|||
return ( |
|||
<SubMenu key="organization" icon={<SettingOutlined />} title={'组织管理'}> |
|||
{Func.isAuthorized("ORG_MEMBER") && |
|||
<Menu.Item key="userManage"> |
|||
<Link to="/organization/user">用户管理</Link> |
|||
</Menu.Item> |
|||
} |
|||
{Func.isAuthorized("ORG_AUTH") && |
|||
<Menu.Item key="authority"> |
|||
<Link to="/organization/authority">权限配置</Link> |
|||
</Menu.Item> |
|||
} |
|||
</SubMenu> |
|||
); |
|||
} |
@ -0,0 +1,5 @@ |
|||
'use strict'; |
|||
|
|||
export default { |
|||
|
|||
}; |
@ -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: '权限配置', |
|||
}] |
|||
} |
|||
}]; |
@ -1,13 +1,13 @@ |
|||
'use strict'; |
|||
|
|||
export default class Func { |
|||
static isAuthorized(authcode) { |
|||
if (JSON.parse(sessionStorage.getItem('user'))) { |
|||
const { resources } = JSON.parse(sessionStorage.getItem('user')); |
|||
return resources.includes(authcode); |
|||
}else{ |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
export default class Func { |
|||
static isAuthorized(authcode) { |
|||
if (JSON.parse(sessionStorage.getItem('user'))) { |
|||
const { userResources } = JSON.parse(sessionStorage.getItem('user')); |
|||
const resources = userResources.map(item => item.resourceCode); |
|||
return resources.includes(authcode); |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
Loading…
Reference in new issue