@ -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 |
|||
}; |
@ -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 |
|||
} |
@ -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,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); |
|||
}; |
@ -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); |
|||
|
@ -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'); |
@ -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'); |
@ -0,0 +1,31 @@ |
|||
/* |
|||
* Eslint config file |
|||
* Documentation: https://eslint.org/docs/user-guide/configuring/
|
|||
* Install the Eslint extension before using this feature. |
|||
*/ |
|||
module.exports = { |
|||
env: { |
|||
es6: true, |
|||
browser: true, |
|||
node: true, |
|||
}, |
|||
ecmaFeatures: { |
|||
modules: true, |
|||
}, |
|||
parserOptions: { |
|||
ecmaVersion: 2018, |
|||
sourceType: 'module', |
|||
}, |
|||
globals: { |
|||
wx: true, |
|||
App: true, |
|||
Page: true, |
|||
getCurrentPages: true, |
|||
getApp: true, |
|||
Component: true, |
|||
requirePlugin: true, |
|||
requireMiniProgram: true, |
|||
}, |
|||
// extends: 'eslint:recommended',
|
|||
rules: {}, |
|||
} |
@ -0,0 +1,38 @@ |
|||
// app.js
|
|||
App({ |
|||
onLaunch() { }, |
|||
globalData: { |
|||
userInfo: null, |
|||
baseUrl: 'http://10.8.16.221:4900', //api 本地环境
|
|||
// imgUrl: 'http://10.8.16.221:5000/_file-server/', //本地环境
|
|||
}, |
|||
onShow(e) { |
|||
// 检查是否有更新
|
|||
const updateManager = wx.getUpdateManager(); |
|||
updateManager.onCheckForUpdate(function (res) { |
|||
// 请求完新版本信息的回调
|
|||
console.log(res.hasUpdate); |
|||
}); |
|||
updateManager.onUpdateReady(function () { |
|||
wx.showModal({ |
|||
title: "更新提示", |
|||
content: "新版本已经准备好,是否重启应用?", |
|||
success(res) { |
|||
if (res.confirm) { |
|||
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
|
|||
updateManager.applyUpdate(); |
|||
} |
|||
} |
|||
}); |
|||
}); |
|||
|
|||
updateManager.onUpdateFailed(function () { |
|||
// 新版本下载失败
|
|||
wx.showToast({ |
|||
title: "新版本下载失败", |
|||
icon: "none", |
|||
duration: 1000 |
|||
}); |
|||
}); |
|||
} |
|||
}) |
@ -0,0 +1,45 @@ |
|||
{ |
|||
"pages": [ |
|||
"pages/index/index", |
|||
"pages/login/login", |
|||
"pages/myInfo/myInfo", |
|||
"pages/overview/overview" |
|||
], |
|||
"subPackages": [{ |
|||
"root": "package", |
|||
"pages": [ |
|||
"polling/polling", |
|||
"basic/basic" |
|||
] |
|||
}], |
|||
"window": { |
|||
"backgroundTextStyle": "dark", |
|||
"navigationBarBackgroundColor": "#1979ff", |
|||
"navigationBarTextStyle": "white" |
|||
}, |
|||
"tabBar": { |
|||
"color": "#000000", |
|||
"selectedColor": "#2F54FF", |
|||
"borderStyle": "black", |
|||
"backgroundColor": "#ffffff", |
|||
"list": [{ |
|||
"pagePath": "pages/index/index", |
|||
"iconPath": "images/tabBar/icon_polling.png", |
|||
"selectedIconPath": "images/tabBar/icon_polling_active.png", |
|||
"text": "巡检总览" |
|||
}, { |
|||
"pagePath": "pages/overview/overview", |
|||
"iconPath": "images/tabBar/icon_menu.png", |
|||
"selectedIconPath": "images/tabBar/icon_menu_active.png", |
|||
"text": "工作台" |
|||
}, |
|||
{ |
|||
"pagePath": "pages/myInfo/myInfo", |
|||
"iconPath": "images/tabBar/icon_person.png", |
|||
"selectedIconPath": "images/tabBar/icon_person_active.png", |
|||
"text": "我的" |
|||
} |
|||
] |
|||
}, |
|||
"sitemapLocation": "sitemap.json" |
|||
} |
@ -0,0 +1,10 @@ |
|||
/**app.wxss**/ |
|||
.container { |
|||
height: 100%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
padding: 200rpx 0; |
|||
box-sizing: border-box; |
|||
} |
@ -0,0 +1,73 @@ |
|||
const app = getApp(); |
|||
const { baseUrl } = app.globalData; |
|||
|
|||
// 全局配置 请求拦截, 长时间
|
|||
const buildRequest = (type, url, data) => { |
|||
return new Promise((resolve, reject) => { |
|||
if (url.indexOf('token') == -1) { |
|||
let token = wx.getStorageSync('token'); |
|||
if (token) { |
|||
url += url.indexOf('?') == -1 ? '?' : '&'; |
|||
url += `token=${token}`; |
|||
} |
|||
} |
|||
if (url.indexOf('http') != 0) { |
|||
url = baseUrl + url; |
|||
} |
|||
|
|||
wx.request({ |
|||
url, |
|||
data, |
|||
method: type, |
|||
success: res => { |
|||
if (res.statusCode == 200 || res.statusCode == 204) { |
|||
resolve(res.data); |
|||
return; |
|||
} |
|||
if (res.statusCode == 400) { |
|||
console.error("400报错" + url, res); |
|||
wx.showToast({ |
|||
title: res.data.message, |
|||
icon: "none", |
|||
duration: 1500 |
|||
}); |
|||
// reject(res);
|
|||
} |
|||
if (res.statusCode == 401) { |
|||
wx.clearStorageSync(); |
|||
wx.reLaunch({ |
|||
url: '/pages/login/login' |
|||
}); |
|||
} |
|||
}, |
|||
fail: err => { |
|||
wx.showToast({ |
|||
title: '网络异常', |
|||
icon: 'none', |
|||
duration: 1500 |
|||
}) |
|||
console.error('网络异常' + url, err); |
|||
reject(err); |
|||
} |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
// 请求拦截
|
|||
let Request = {}; |
|||
Request.get = (url, query) => { |
|||
return buildRequest('GET', url, query); |
|||
} |
|||
Request.post = (url, data) => { |
|||
return buildRequest('POST', url, data); |
|||
} |
|||
Request.put = (url, data) => { |
|||
return buildRequest('PUT', url, data); |
|||
} |
|||
Request.del = (url, data) => { |
|||
return buildRequest('DELETE', url, data); |
|||
} |
|||
|
|||
module.exports = { |
|||
Request |
|||
} |
After Width: | Height: | Size: 868 B |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 915 B |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.8 KiB |
@ -0,0 +1,70 @@ |
|||
// package/basic/basic.js
|
|||
Page({ |
|||
|
|||
/** |
|||
* 页面的初始数据 |
|||
*/ |
|||
data: { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面加载 |
|||
*/ |
|||
onLoad(options) { |
|||
let that = this; |
|||
let userInfo = wx.getStorageSync('userInfo'); |
|||
that.setData({ |
|||
userInfo |
|||
}) |
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面初次渲染完成 |
|||
*/ |
|||
onReady() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面显示 |
|||
*/ |
|||
onShow() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面隐藏 |
|||
*/ |
|||
onHide() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面卸载 |
|||
*/ |
|||
onUnload() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面相关事件处理函数--监听用户下拉动作 |
|||
*/ |
|||
onPullDownRefresh() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面上拉触底事件的处理函数 |
|||
*/ |
|||
onReachBottom() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 用户点击右上角分享 |
|||
*/ |
|||
onShareAppMessage() { |
|||
|
|||
} |
|||
}) |
@ -0,0 +1,6 @@ |
|||
{ |
|||
"navigationBarBackgroundColor": "#1979ff", |
|||
"navigationBarTextStyle": "white", |
|||
"navigationBarTitleText": "基本信息", |
|||
"enablePullDownRefresh": false |
|||
} |
@ -0,0 +1,41 @@ |
|||
<!--package/basic/basic.wxml--> |
|||
<view class="page"> |
|||
<view class='header-item-container'> |
|||
<image class='logo' src='../../images/avatar.svg' /> |
|||
<view> |
|||
<text class='userName'>{{userInfo.name || '--'}}</text> |
|||
</view> |
|||
</view> |
|||
<view class='list'> |
|||
<view class='content'> |
|||
<view class='title'>姓名:</view> |
|||
<view class='value'> |
|||
{{userInfo.name || '--'}} |
|||
</view> |
|||
</view> |
|||
<view class='content'> |
|||
<view class='title'>电话:</view> |
|||
<view class='value'> |
|||
{{userInfo.phone || '--'}} |
|||
</view> |
|||
</view> |
|||
<view class='content'> |
|||
<view class='title'>部门:</view> |
|||
<view class='value'> |
|||
管理部门 |
|||
</view> |
|||
</view> |
|||
<view class='content'> |
|||
<view class='title'>职务:</view> |
|||
<view class='value'> |
|||
{{userInfo.post || '--'}} |
|||
</view> |
|||
</view> |
|||
<view class='content'> |
|||
<view class='title'>邮箱:</view> |
|||
<view class='value'> |
|||
{{userInfo.email || '--'}} |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
@ -0,0 +1,60 @@ |
|||
/* package/basic/basic.wxss */ |
|||
|
|||
page { |
|||
background-color: rgb(242, 242, 245); |
|||
} |
|||
|
|||
.page { |
|||
padding: 30rpx; |
|||
} |
|||
|
|||
.header-item-container { |
|||
width: 100%; |
|||
height: 180rpx; |
|||
background: rgb(255, 255, 255); |
|||
border-radius: 10rpx; |
|||
flex-direction: row; |
|||
display: flex; |
|||
justify-content: start; |
|||
align-items: center; |
|||
box-shadow: 0rpx 0rpx 16rpx #ccc; |
|||
} |
|||
|
|||
.logo { |
|||
width: 120rpx; |
|||
height: 120rpx; |
|||
padding: 30rpx; |
|||
} |
|||
|
|||
.userName { |
|||
font-size: 36rpx; |
|||
font-weight: 600; |
|||
} |
|||
|
|||
.list { |
|||
color: #6C6C6C; |
|||
background: #fff; |
|||
padding: 40rpx; |
|||
box-sizing: border-box; |
|||
width: 100%; |
|||
margin: 40rpx auto; |
|||
border-radius: 10rpx; |
|||
box-shadow: 0rpx 0rpx 16rpx #ccc; |
|||
} |
|||
|
|||
.content { |
|||
width: 100%; |
|||
overflow: hidden; |
|||
margin: 20rpx auto; |
|||
} |
|||
|
|||
.title { |
|||
float: left; |
|||
} |
|||
|
|||
.value { |
|||
float: left; |
|||
margin-left: 80rpx; |
|||
width: 400rpx; |
|||
word-break: break-word; |
|||
} |
@ -0,0 +1,71 @@ |
|||
// package/polling/polling.js
|
|||
Page({ |
|||
|
|||
/** |
|||
* 页面的初始数据 |
|||
*/ |
|||
data: { |
|||
|
|||
}, |
|||
|
|||
// 顶部tab切换
|
|||
clickTab(e) { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面加载 |
|||
*/ |
|||
onLoad(options) { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面初次渲染完成 |
|||
*/ |
|||
onReady() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面显示 |
|||
*/ |
|||
onShow() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面隐藏 |
|||
*/ |
|||
onHide() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面卸载 |
|||
*/ |
|||
onUnload() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面相关事件处理函数--监听用户下拉动作 |
|||
*/ |
|||
onPullDownRefresh() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面上拉触底事件的处理函数 |
|||
*/ |
|||
onReachBottom() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 用户点击右上角分享 |
|||
*/ |
|||
onShareAppMessage() { |
|||
|
|||
} |
|||
}) |
@ -0,0 +1,6 @@ |
|||
{ |
|||
"navigationBarBackgroundColor": "#1979ff", |
|||
"navigationBarTextStyle": "white", |
|||
"navigationBarTitleText": "巡检", |
|||
"enablePullDownRefresh": false |
|||
} |
@ -0,0 +1,11 @@ |
|||
<!--package/polling/polling.wxml--> |
|||
<view class="page"> |
|||
<!-- 顶部tab切换 --> |
|||
<view class='swiper-tab'> |
|||
<view class="swiper-tab-item active" data-current="0" bindtap="clickTab">巡检记录</view> |
|||
<!-- <view class="swiper-tab-item active" data-current="1" bindtap="clickTab">问题上报</view> --> |
|||
</view> |
|||
<view class='swiper-tab' style="top:100rpx;"> |
|||
<view class="swiper-tab-item" data-current="0" bindtap="clickTab">待巡检</view> |
|||
</view> |
|||
</view> |
@ -0,0 +1,33 @@ |
|||
/* package/polling/polling.wxss */ |
|||
|
|||
.page { |
|||
min-height: 100vh; |
|||
background: #F7F7FA; |
|||
position: relative; |
|||
} |
|||
|
|||
/* 顶部tab */ |
|||
.swiper-tab { |
|||
display: flex; |
|||
height: 98rpx; |
|||
line-height: 98rpx; |
|||
width: 100%; |
|||
position: fixed; |
|||
top: 0; |
|||
z-index: 100; |
|||
background: #fff; |
|||
border-bottom: 2rpx solid #e8e8e8; |
|||
} |
|||
|
|||
.swiper-tab-item { |
|||
flex: 1; |
|||
font-size: 28rpx; |
|||
text-align: center; |
|||
color: #333333; |
|||
position: relative; |
|||
} |
|||
|
|||
.active { |
|||
color: #1979ff; |
|||
position: relative; |
|||
} |
@ -0,0 +1,76 @@ |
|||
// pages/index/index.js
|
|||
Page({ |
|||
|
|||
/** |
|||
* 页面的初始数据 |
|||
*/ |
|||
data: { |
|||
dataList: [1, 2, 3, 4] |
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面加载 |
|||
*/ |
|||
onLoad(options) { |
|||
const userInfo = wx.getStorageSync('userInfo'); |
|||
if (!userInfo || !userInfo.id) { |
|||
wx.reLaunch({ |
|||
url: '/pages/login/login' |
|||
}); |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面初次渲染完成 |
|||
*/ |
|||
onReady() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面显示 |
|||
*/ |
|||
onShow() { |
|||
const userInfo = wx.getStorageSync('userInfo'); |
|||
if (!userInfo || !userInfo.id) { |
|||
wx.reLaunch({ |
|||
url: '/pages/login/login' |
|||
}); |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面隐藏 |
|||
*/ |
|||
onHide() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面卸载 |
|||
*/ |
|||
onUnload() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面相关事件处理函数--监听用户下拉动作 |
|||
*/ |
|||
onPullDownRefresh() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面上拉触底事件的处理函数 |
|||
*/ |
|||
onReachBottom() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 用户点击右上角分享 |
|||
*/ |
|||
onShareAppMessage() { |
|||
|
|||
} |
|||
}) |
@ -0,0 +1,6 @@ |
|||
{ |
|||
"navigationBarBackgroundColor": "#1979ff", |
|||
"navigationBarTextStyle": "white", |
|||
"navigationBarTitleText": "巡检总览", |
|||
"enablePullDownRefresh": false |
|||
} |
@ -0,0 +1,26 @@ |
|||
<!--pages/index/index.wxml--> |
|||
<view> |
|||
<view class="searchFixed"> |
|||
<view class="searchBoxs"> |
|||
<input class="searchInps" bindinput="formInp" bindconfirm="bindconfirm" value='{{name}}' type="text" placeholder="请输入结构物名称" /> |
|||
<button class="btnSearch" bindtap="goSearch">搜索</button> |
|||
</view> |
|||
</view> |
|||
|
|||
<view style="margin-top: 117rpx;"> |
|||
<block wx:for="{{dataList}}"> |
|||
<view style="padding-bottom: 60rpx;"> |
|||
<image style="width: 100%;height: 372rpx;display: block;" src="https://dingyue.ws.126.net/2021/0428/099be11ej00qs9xld006bc000xc00m7m.jpg"></image> |
|||
<view class="box"> |
|||
<view style="font-weight:bold;font-size:32rpx;">结构物A</view> |
|||
<view style="font-size:28rpx;color: rgb(166,166,166);"> |
|||
<view style=" margin-top:6rpx;">今日问题:<text>12</text></view> |
|||
<view style="float:left;width:360rpx;">未处理问题:<text>12</text></view> |
|||
<view style="float:left;width:350rpx;">已处理问题:<text>12</text></view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</block> |
|||
</view> |
|||
|
|||
</view> |
@ -0,0 +1,55 @@ |
|||
/* pages/index/index.wxss */ |
|||
page { |
|||
background: rgb(242, 242, 245); |
|||
} |
|||
|
|||
.searchBoxs { |
|||
position: relative; |
|||
margin: 20rpx 0rpx; |
|||
height: 76rpx; |
|||
} |
|||
|
|||
.searchInps { |
|||
background-color: #fff; |
|||
width: 542rpx; |
|||
height: 76rpx; |
|||
border-radius: 8rpx; |
|||
padding-left: 32rpx; |
|||
padding-right: 144rpx; |
|||
border: 1px solid rgba(225, 225, 225, 0.44); |
|||
position: absolute; |
|||
top: -2rpx; |
|||
left: 16rpx; |
|||
font-size: 28rpx; |
|||
} |
|||
|
|||
.btnSearch { |
|||
width: 128rpx; |
|||
height: 68rpx; |
|||
line-height: 68rpx; |
|||
border-radius: 8rpx; |
|||
color: #fff; |
|||
font-size: 28rpx; |
|||
background: linear-gradient(180deg, #1979ff 0%, #1979ff 100%); |
|||
position: absolute; |
|||
top: 6rpx; |
|||
right: 28rpx; |
|||
z-index: 10; |
|||
} |
|||
|
|||
.searchFixed { |
|||
position: fixed; |
|||
top: 0; |
|||
width: 100%; |
|||
background-color: #fff; |
|||
box-shadow: 0rpx -4rpx 20rpx #c2c2c2; |
|||
z-index: 10; |
|||
} |
|||
|
|||
.box { |
|||
padding: 20rpx; |
|||
box-shadow: 0rpx 0rpx 10rpx #ccc; |
|||
overflow: hidden; |
|||
line-height: 50rpx; |
|||
background: #fff; |
|||
} |
@ -0,0 +1,117 @@ |
|||
// pages/login/login.js
|
|||
import { loginUrl } from "../../utils/getApiUrl"; |
|||
import { Request } from "../../common"; |
|||
|
|||
Page({ |
|||
|
|||
/** |
|||
* 页面的初始数据 |
|||
*/ |
|||
data: { |
|||
userNameCan: false, |
|||
passwordCan: false, |
|||
}, |
|||
|
|||
setColor: function () { |
|||
this.setData({ |
|||
backgroundInput: this.data.userNameCan == true && this.data.passwordCan == true ? 'rgb(51, 133, 255)' : 'rgb(255,255,255)', |
|||
colorInput: this.data.userNameCan == true && this.data.passwordCan == true ? 'rgb(255, 255, 255)' : 'rgb(201,201,201)', |
|||
}) |
|||
}, |
|||
bindUserName: function (e) { |
|||
this.setData({ |
|||
userNameCan: e.detail.value.length > 0 ? true : false, |
|||
}) |
|||
this.setColor(); |
|||
}, |
|||
bindPassword: function (e) { |
|||
this.setData({ |
|||
passwordCan: e.detail.value.length > 0 ? true : false, |
|||
}) |
|||
this.setColor(); |
|||
}, |
|||
|
|||
// 登录
|
|||
getLogin: function (e) { |
|||
if (e.detail.value.username.length == 0 || e.detail.value.password == 0) { |
|||
wx.showToast({ |
|||
title: '请输入用户名密码', |
|||
icon: 'none', |
|||
}) |
|||
return |
|||
} |
|||
wx.showLoading() |
|||
Request.post(loginUrl(), { |
|||
"username": e.detail.value.username, |
|||
"password": e.detail.value.password |
|||
}).then((res) => { |
|||
if (!res.authorized) { |
|||
wx.showToast({ title: "登录失败", icon: "none" }); |
|||
return; |
|||
} |
|||
wx.setStorageSync('token', res.token); |
|||
wx.setStorageSync("userInfo", res); |
|||
getApp().globalData.userInfo = res |
|||
wx.switchTab({ |
|||
url: '/pages/index/index', |
|||
}) |
|||
wx.hideLoading() |
|||
}) |
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面加载 |
|||
*/ |
|||
onLoad(options) { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面初次渲染完成 |
|||
*/ |
|||
onReady() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面显示 |
|||
*/ |
|||
onShow() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面隐藏 |
|||
*/ |
|||
onHide() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面卸载 |
|||
*/ |
|||
onUnload() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面相关事件处理函数--监听用户下拉动作 |
|||
*/ |
|||
onPullDownRefresh() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面上拉触底事件的处理函数 |
|||
*/ |
|||
onReachBottom() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 用户点击右上角分享 |
|||
*/ |
|||
onShareAppMessage() { |
|||
|
|||
} |
|||
}) |
@ -0,0 +1,6 @@ |
|||
{ |
|||
"navigationBarBackgroundColor": "#fff", |
|||
"navigationBarTextStyle": "white", |
|||
"navigationBarTitleText": "登录", |
|||
"enablePullDownRefresh": false |
|||
} |
@ -0,0 +1,25 @@ |
|||
<!--pages/login/login.wxml--> |
|||
<view class='logo-container'> |
|||
<image class='logo' src='/images/logo.png' mode='aspectFit' /> |
|||
</view> |
|||
|
|||
<view class="body-container" wx:if='{{!isAutoLogin}}'> |
|||
<form report-submit='true' bindsubmit='getLogin'> |
|||
<view class='userName-container marginBottom'> |
|||
<image class='userName-logo' src='/images/userName.png' /> |
|||
<input class='input' name='username' placeholder='请输入用户名' value='' type='text' maxlength="50" confirm-type="next" bindinput='bindUserName' /> |
|||
</view> |
|||
|
|||
<view class='userName-container'> |
|||
<image class='password-logo' src='/images/password.png' /> |
|||
<input class='input' name='password' placeholder='输入密码' value='' type='text' password='true' maxlength="50" confirm-type="done" bindinput='bindPassword' /> |
|||
</view> |
|||
|
|||
<button class='login-btn' disabled="{{!userNameCan || !passwordCan}}" style='background:{{backgroundInput}}; color:{{colorInput}};' form-type="submit">登录</button> |
|||
</form> |
|||
</view> |
|||
|
|||
<view class='co-info'> |
|||
<view>仅提供内部人员使用</view> |
|||
<view>©飞尚科技</view> |
|||
</view> |
@ -0,0 +1,156 @@ |
|||
/* pages/login/login.wxss */ |
|||
page { |
|||
background: rgb(255, 255, 255); |
|||
} |
|||
|
|||
.logo-container { |
|||
margin-top: 85rpx; |
|||
margin-bottom: 125rpx; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
text-align: center; |
|||
} |
|||
|
|||
.logo { |
|||
width: 180rpx; |
|||
height: 180rpx; |
|||
} |
|||
|
|||
.body-container { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.marginBottom { |
|||
margin-bottom: 30rpx; |
|||
} |
|||
|
|||
.userName-container { |
|||
width: 580rpx; |
|||
height: 95rpx; |
|||
background: rgb(245, 245, 247); |
|||
border-radius: 10rpx; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.userName-logo { |
|||
width: 30rpx; |
|||
height: 34rpx; |
|||
padding-right: 15rpx; |
|||
border-right: 1px dashed #8A8A8A; |
|||
} |
|||
|
|||
.password-logo { |
|||
width: 30rpx; |
|||
height: 34rpx; |
|||
padding-right: 15rpx; |
|||
border-right: 1px dashed #8A8A8A; |
|||
} |
|||
|
|||
.input { |
|||
width: 492rpx; |
|||
height: 95rpx; |
|||
padding-left: 15rpx; |
|||
font-size: 32rpx; |
|||
} |
|||
|
|||
.login-btn { |
|||
width: 580rpx !important; |
|||
height: 98rpx; |
|||
margin-top: 90rpx; |
|||
color: rgb(201, 201, 201); |
|||
background: rgb(255, 255, 255); |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
border-radius: 10rpx; |
|||
} |
|||
|
|||
.backColor { |
|||
color: rgb(138, 138, 138); |
|||
} |
|||
|
|||
|
|||
|
|||
/* 按钮 */ |
|||
.cancle-sure { |
|||
width: 100%; |
|||
/* height: 100rpx; */ |
|||
background: white; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
border-bottom: 1px solid #E5E5E5; |
|||
} |
|||
|
|||
.sure { |
|||
color: rgb(36, 123, 255); |
|||
padding: 30rpx; |
|||
font-size: 36rpx; |
|||
} |
|||
|
|||
.picker-view-column-container { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.sitePicker { |
|||
width: 100%; |
|||
height: 240rpx; |
|||
font-size: 34rpx; |
|||
padding-left: 30rpx; |
|||
padding-right: 30rpx; |
|||
} |
|||
|
|||
.picker-item { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
font-size: 34rpx; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.sensorTypePicker { |
|||
width: 100%; |
|||
height: 240rpx; |
|||
font-size: 34rpx; |
|||
padding-left: 30rpx; |
|||
padding-right: 30rpx; |
|||
} |
|||
|
|||
.indecate { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
color: rgb(241, 241, 242); |
|||
} |
|||
|
|||
|
|||
.noSensor-container { |
|||
height: 800rpx; |
|||
flex-direction: column; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
/* background: rgb(0,0,0); */ |
|||
} |
|||
|
|||
|
|||
.selectIndex { |
|||
height: 80rpx; |
|||
} |
|||
|
|||
.co-info { |
|||
position: fixed; |
|||
bottom: 10px; |
|||
left: 0; |
|||
width: 100vw; |
|||
color: #ccc; |
|||
text-align: center; |
|||
font-size: 14px |
|||
} |
@ -0,0 +1,102 @@ |
|||
// pages/myInfo/myInfo.js
|
|||
import { logoutUrl } from "../../utils/getApiUrl"; |
|||
import { Request } from "../../common"; |
|||
|
|||
Page({ |
|||
|
|||
/** |
|||
* 页面的初始数据 |
|||
*/ |
|||
data: { |
|||
|
|||
}, |
|||
|
|||
bindClick() { |
|||
wx.navigateTo({ |
|||
url: '/package/basic/basic', |
|||
}) |
|||
}, |
|||
|
|||
// 登出
|
|||
logout() { |
|||
wx.showModal({ |
|||
title: '切换用户', |
|||
content: '将退出当前用户,重新登录', |
|||
confirmText: '切换用户', |
|||
confirmColor: '#1979ff', |
|||
success: res => { |
|||
if (res.confirm) { |
|||
wx.showLoading() |
|||
Request.put(logoutUrl(), {}).then((res) => { |
|||
wx.clearStorage(); |
|||
getApp().globalData.userInfo = null; |
|||
wx.reLaunch({ |
|||
url: '../login/login', |
|||
}) |
|||
wx.hideLoading() |
|||
}) |
|||
} |
|||
} |
|||
}) |
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面加载 |
|||
*/ |
|||
onLoad(options) { |
|||
let that = this; |
|||
let userInfo = wx.getStorageSync('userInfo'); |
|||
that.setData({ |
|||
userInfo |
|||
}) |
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面初次渲染完成 |
|||
*/ |
|||
onReady() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面显示 |
|||
*/ |
|||
onShow() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面隐藏 |
|||
*/ |
|||
onHide() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面卸载 |
|||
*/ |
|||
onUnload() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面相关事件处理函数--监听用户下拉动作 |
|||
*/ |
|||
onPullDownRefresh() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面上拉触底事件的处理函数 |
|||
*/ |
|||
onReachBottom() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 用户点击右上角分享 |
|||
*/ |
|||
onShareAppMessage() { |
|||
|
|||
} |
|||
}) |
@ -0,0 +1,6 @@ |
|||
{ |
|||
"navigationBarBackgroundColor": "#1979ff", |
|||
"navigationBarTextStyle": "white", |
|||
"navigationBarTitleText": "我的", |
|||
"enablePullDownRefresh": false |
|||
} |
@ -0,0 +1,25 @@ |
|||
<!--pages/myInfo/myInfo.wxml--> |
|||
<view class='box'> |
|||
<view class='header-item-container'> |
|||
<image class='logo' src='../../images/avatar.svg' /> |
|||
<view> |
|||
<text class='userName'>{{userInfo.name}}</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class='body-container'> |
|||
<view class='body-item' bindtap="bindClick"> |
|||
<view class='body-info'>基本信息</view> |
|||
<image class="right" src="/images/right.svg"></image> |
|||
</view> |
|||
|
|||
<!-- <view class='body-item'> |
|||
<view class='body-info'>通知消息</view> |
|||
<image class="right" src="/images/right.svg"></image> |
|||
</view> --> |
|||
</view> |
|||
|
|||
<view class='foot-container'> |
|||
<view class='foot-item' bindtap='logout'>退出登录</view> |
|||
</view> |
|||
</view> |
@ -0,0 +1,100 @@ |
|||
/* pages/myInfo/myInfo.wxss */ |
|||
|
|||
page { |
|||
background-color: rgb(242, 242, 245); |
|||
} |
|||
|
|||
/* 容器 */ |
|||
.box { |
|||
padding: 30rpx; |
|||
font-family: 'PingFang SC-Medium'; |
|||
} |
|||
|
|||
.header-item-container { |
|||
width: 100%; |
|||
height: 180rpx; |
|||
background: rgb(255, 255, 255); |
|||
border-radius: 10rpx; |
|||
flex-direction: row; |
|||
display: flex; |
|||
justify-content: start; |
|||
align-items: center; |
|||
} |
|||
|
|||
.logo { |
|||
width: 120rpx; |
|||
height: 120rpx; |
|||
padding: 30rpx; |
|||
} |
|||
|
|||
.userName { |
|||
font-size: 36rpx; |
|||
font-weight: 600; |
|||
} |
|||
|
|||
.company { |
|||
font-size: 28rpx; |
|||
font-family: "PingFang SC"; |
|||
color: rgb(138, 138, 138); |
|||
margin-top: 14rpx; |
|||
} |
|||
|
|||
.body-container { |
|||
width: 100%; |
|||
background: rgb(255, 255, 255); |
|||
border-radius: 10rpx; |
|||
flex-direction: column; |
|||
display: flex; |
|||
margin-top: 30rpx; |
|||
margin-bottom: 30rpx; |
|||
} |
|||
|
|||
.body-item { |
|||
height: 110rpx; |
|||
flex-direction: row; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
padding: 0 30rpx; |
|||
border-bottom: 1px solid #EFEFF4; |
|||
} |
|||
|
|||
.body-info { |
|||
font-size: 32rpx; |
|||
font-family: "PingFang SC"; |
|||
font-weight: 600; |
|||
} |
|||
|
|||
.body-number { |
|||
font-size: 30rpx; |
|||
font-family: "PingFang SC"; |
|||
color: rgb(138, 138, 138); |
|||
} |
|||
|
|||
.foot-container { |
|||
width: 100%; |
|||
background: rgb(255, 255, 255); |
|||
border-radius: 10rpx; |
|||
flex-direction: column; |
|||
display: flex; |
|||
border: 1px #FFFFFF; |
|||
} |
|||
|
|||
.foot-item { |
|||
color: rgb(0, 0, 0); |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
padding: 30rpx; |
|||
font-size: 32rpx; |
|||
font-family: "PingFang SC"; |
|||
font-weight: 600; |
|||
} |
|||
|
|||
.right { |
|||
width: 32rpx; |
|||
height: 32rpx; |
|||
display: block; |
|||
float: right; |
|||
margin: 38rpx 40rpx; |
|||
} |
@ -0,0 +1,73 @@ |
|||
// pages/overview/overview.js
|
|||
Page({ |
|||
|
|||
/** |
|||
* 页面的初始数据 |
|||
*/ |
|||
data: { |
|||
|
|||
}, |
|||
|
|||
// 巡检
|
|||
bindPolling() { |
|||
wx.navigateTo({ |
|||
url: '/package/polling/polling', |
|||
}) |
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面加载 |
|||
*/ |
|||
onLoad(options) { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面初次渲染完成 |
|||
*/ |
|||
onReady() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面显示 |
|||
*/ |
|||
onShow() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面隐藏 |
|||
*/ |
|||
onHide() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面卸载 |
|||
*/ |
|||
onUnload() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面相关事件处理函数--监听用户下拉动作 |
|||
*/ |
|||
onPullDownRefresh() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面上拉触底事件的处理函数 |
|||
*/ |
|||
onReachBottom() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 用户点击右上角分享 |
|||
*/ |
|||
onShareAppMessage() { |
|||
|
|||
} |
|||
}) |
@ -0,0 +1,6 @@ |
|||
{ |
|||
"navigationBarBackgroundColor": "#1979ff", |
|||
"navigationBarTextStyle": "white", |
|||
"navigationBarTitleText": "工作台", |
|||
"enablePullDownRefresh": false |
|||
} |
@ -0,0 +1,18 @@ |
|||
<!--pages/overview/overview.wxml--> |
|||
<view style="margin-top: 42rpx;"> |
|||
<view class="box" bindtap="bindPolling"> |
|||
<image class="logo" src="/images/xunjian.svg"></image> |
|||
<view class="txt">巡检</view> |
|||
<image class="right" src="/images/right.svg"></image> |
|||
</view> |
|||
<!-- <view class="box"> |
|||
<image class="logo" src="/images/tabBar/icon_menu.png"></image> |
|||
<view class="txt">问题处理</view> |
|||
<image class="right" src="/images/right.svg"></image> |
|||
</view> |
|||
<view class="box"> |
|||
<image class="logo" src="/images/tabBar/icon_menu.png"></image> |
|||
<view class="txt">巡检报告</view> |
|||
<image class="right" src="/images/right.svg"></image> |
|||
</view> --> |
|||
</view> |
@ -0,0 +1,35 @@ |
|||
/* pages/overview/overview.wxss */ |
|||
|
|||
page { |
|||
background-color: rgb(242, 242, 245); |
|||
} |
|||
|
|||
.box { |
|||
width: 672rpx; |
|||
height: 178rpx; |
|||
margin: 42rpx auto 21rpx; |
|||
background: #fff; |
|||
box-shadow: 0rpx 0rpx 10rpx #ccc; |
|||
border-radius: 8rpx; |
|||
} |
|||
|
|||
.logo { |
|||
width: 90rpx; |
|||
height: 90rpx; |
|||
float: left; |
|||
margin: 48rpx 50rpx 0 50rpx; |
|||
} |
|||
|
|||
.txt { |
|||
float: left; |
|||
line-height: 112rpx; |
|||
margin: 34rpx; |
|||
} |
|||
|
|||
.right { |
|||
width: 32rpx; |
|||
height: 32rpx; |
|||
display: block; |
|||
float: right; |
|||
margin: 74rpx 40rpx; |
|||
} |
@ -0,0 +1,51 @@ |
|||
{ |
|||
"description": "项目配置文件", |
|||
"packOptions": { |
|||
"ignore": [], |
|||
"include": [] |
|||
}, |
|||
"setting": { |
|||
"bundle": false, |
|||
"userConfirmedBundleSwitch": false, |
|||
"urlCheck": true, |
|||
"scopeDataCheck": false, |
|||
"coverView": true, |
|||
"es6": true, |
|||
"postcss": true, |
|||
"compileHotReLoad": false, |
|||
"lazyloadPlaceholderEnable": false, |
|||
"preloadBackgroundData": false, |
|||
"minified": true, |
|||
"autoAudits": false, |
|||
"newFeature": false, |
|||
"uglifyFileName": false, |
|||
"uploadWithSourceMap": true, |
|||
"useIsolateContext": true, |
|||
"nodeModules": false, |
|||
"enhance": true, |
|||
"useMultiFrameRuntime": true, |
|||
"useApiHook": true, |
|||
"useApiHostProcess": true, |
|||
"showShadowRootInWxmlPanel": true, |
|||
"packNpmManually": false, |
|||
"enableEngineNative": false, |
|||
"packNpmRelationList": [], |
|||
"minifyWXSS": true, |
|||
"showES6CompileOption": false, |
|||
"minifyWXML": true, |
|||
"babelSetting": { |
|||
"ignore": [], |
|||
"disablePlugins": [], |
|||
"outputPath": "" |
|||
} |
|||
}, |
|||
"compileType": "miniprogram", |
|||
"libVersion": "2.19.4", |
|||
"appid": "wxe9595234589a0147", |
|||
"projectname": "miniprogram-92", |
|||
"condition": {}, |
|||
"editorSetting": { |
|||
"tabIndent": "insertSpaces", |
|||
"tabSize": 2 |
|||
} |
|||
} |
@ -0,0 +1,36 @@ |
|||
{ |
|||
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", |
|||
"projectname": "%E5%B7%A1%E6%A3%80%E5%B0%8F%E7%A8%8B%E5%BA%8F", |
|||
"setting": { |
|||
"compileHotReLoad": false, |
|||
"urlCheck": false |
|||
}, |
|||
"condition": { |
|||
"miniprogram": { |
|||
"list": [ |
|||
{ |
|||
"name": "", |
|||
"pathName": "pages/login/login", |
|||
"query": "", |
|||
"launchMode": "default", |
|||
"scene": null |
|||
}, |
|||
{ |
|||
"name": "", |
|||
"pathName": "package/polling/polling", |
|||
"query": "", |
|||
"launchMode": "default", |
|||
"scene": null |
|||
}, |
|||
{ |
|||
"name": "", |
|||
"pathName": "package/basic/basic", |
|||
"query": "", |
|||
"launchMode": "default", |
|||
"scene": null |
|||
} |
|||
] |
|||
} |
|||
}, |
|||
"libVersion": "2.29.0" |
|||
} |
@ -0,0 +1,7 @@ |
|||
{ |
|||
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", |
|||
"rules": [{ |
|||
"action": "allow", |
|||
"page": "*" |
|||
}] |
|||
} |
@ -0,0 +1,9 @@ |
|||
// 登录
|
|||
exports.loginUrl = () => { |
|||
return `/login` |
|||
} |
|||
|
|||
// 登出
|
|||
exports.logoutUrl = () => { |
|||
return `/logout` |
|||
} |
@ -0,0 +1,19 @@ |
|||
const formatTime = date => { |
|||
const year = date.getFullYear() |
|||
const month = date.getMonth() + 1 |
|||
const day = date.getDate() |
|||
const hour = date.getHours() |
|||
const minute = date.getMinutes() |
|||
const second = date.getSeconds() |
|||
|
|||
return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}` |
|||
} |
|||
|
|||
const formatNumber = n => { |
|||
n = n.toString() |
|||
return n[1] ? n : `0${n}` |
|||
} |
|||
|
|||
module.exports = { |
|||
formatTime |
|||
} |
@ -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,11 @@ |
|||
'use strict'; |
|||
|
|||
import * as authority from './authority' |
|||
import { getDepMessage, getDepUser, createUser } from './user' |
|||
|
|||
export default { |
|||
...authority, |
|||
getDepMessage, |
|||
getDepUser, |
|||
createUser, |
|||
} |
@ -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 |
|||
} |
@ -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); |
@ -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,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 |
@ -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); |
@ -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); |
@ -0,0 +1,6 @@ |
|||
'use strict'; |
|||
|
|||
import Authority from './authority'; |
|||
import UserManage from './user'; |
|||
|
|||
export { Authority, UserManage }; |
@ -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); |
@ -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,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> |
|||
); |
|||
} |
@ -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: '权限配置', |
|||
}] |
|||
} |
|||
}]; |