Commit e24f991f authored by 陈前坚's avatar 陈前坚

perf: 批量操作

parent bb5f817d
......@@ -153,7 +153,7 @@ const AppMenu = () => {
</>
),
key: menu.menuID,
icon: menu.leaf ? <FileOutlined /> : <FolderOpenOutlined />,
// icon: menu.leaf ? <FileOutlined /> : <FolderOpenOutlined />,
// 判断它是否存在子集,若果存在就进行再次进行遍历操作,知道不存在子集便对其他的元素进行操作
children: haveChildren ? menu.children.map(i => mapTree(i)) : [],
};
......
......@@ -14,10 +14,15 @@ import {
Tabs,
Button,
Spin,
Dropdown,
Menu,
} from 'antd';
import {
UserAddOutlined,
UsergroupAddOutlined,
EditOutlined,
EditTwoTone,
DeleteOutlined,
DeleteTwoTone,
ShareAltOutlined,
UnlockOutlined,
......@@ -25,12 +30,14 @@ import {
StopOutlined,
DoubleLeftOutlined,
DoubleRightOutlined,
DownOutlined,
} from '@ant-design/icons';
import PageContainer from '@/components/BasePageContainer';
import voca from 'voca';
import zhCN from 'antd/es/locale/zh_CN';
import {
addToOrg,
addToOrgs,
editOrgInfo,
getOneOUUserListNew,
getUserByKey,
......@@ -44,7 +51,9 @@ import {
deleteOrg as postDeleteOrg,
updateUserPassword,
setUserRelation,
multiDeleteUsers,
} from '@/services/userCenter/userManage/api';
import classnames from 'classnames';
import ListCardItem from '../orgnazation/listCardItem';
import styles from './UserManage.less';
......@@ -52,12 +61,13 @@ const UserManage = () => {
const [treeLoading, setTreeLoading] = useState(false);
const [tableLoading, setTableLoading] = useState(false);
const [loading, setLoading] = useState(true);
const [multiOperate, setMultiOperate] = useState(true); // 是否禁用用户批量操作
const [multiOperateButtonType, setMultiOperateButtonType] = useState(''); // 更改批量操作按钮样式
const [treeData, setTreeData] = useState([]); // 用户机构树
const [expandedKeys, setExpandedKeys] = useState(['']);
// const [expandedKeys, setExpandedKeys] = useState(['']);
const [treeDataCopy, setTreeDataCopy] = useState([]); // 机构树数据备份,用于更改机构
const [treeState, setTreeState] = useState(true); // 树第一次加载
// const [treeDispaly, setTreeDispaly] = useState(''); // 1
const [treeVisible, setTreeVisible] = useState(true); // 树是否可见
const [tableData, setTableData] = useState([]); // 用户表
const [orgFilters, setOrgFilters] = useState([]); // 用户列筛选
......@@ -77,12 +87,17 @@ const UserManage = () => {
const [freezeUserVisible, setFreezeUserVisible] = useState(false); // 冻结用户
const [deleteUserVisible, setDeleteUserVisible] = useState(false); // 删除用户
const [orgTitle, setOrgTitle] = useState('机构'); // 弹框标题
const [orgTitle, setOrgTitle] = useState('当前机构'); // 弹框标题
const [tableLength, setTableLength] = useState(0); // 表格标题
const [orgID, setOrgID] = useState(); // 机构ID
const [newOrgID, setNewOrgID] = useState(); // 更改机构新选择的ID
const [currentUser, setCurrentUser] = useState({}); // 当前用户
const [userIDs, setUserIDs] = useState(''); // 批量删除的用户
const [orgIDs, setOrgIDs] = useState(''); // 批量操作的机构
const [multiDelete, setMultiDelete] = useState(false); // 是否批量删除用户
const [multiChangeOrgs, setMultiChangeOrgs] = useState(false); // 是否批量更改机构
const [rolelist, setRolelist] = useState([]); // 角色列表
const [stationlist, setStationlist] = useState([]); // 站点列表
const [roleValueList, setRoleValueList] = useState({}); // 勾选的角色列表
......@@ -165,20 +180,44 @@ const UserManage = () => {
dataIndex: 'ddid',
key: 'ddid',
width: 100,
render: record => {
if (record) {
return (
<Tooltip title={record}>
<span style={{ color: '#50aefc', cursor: 'pointer' }}>
已绑定
</span>
</Tooltip>
);
}
return <span>未绑定</span>;
},
},
{
title: '微信账户',
dataIndex: 'wxid',
key: 'wxid',
width: 100,
render: record => {
if (record) {
return (
<Tooltip title={record}>
<span style={{ color: '#50aefc', cursor: 'pointer' }}>
已绑定
</span>
</Tooltip>
);
}
return <span>未绑定</span>;
},
},
{
title: '操作',
key: 'action',
fixed: 'right',
width: 250,
width: 210,
align: 'center',
render: (text, record) => (
render: record => (
<Space size="middle">
<Tooltip title="关联角色">
<ShareAltOutlined
......@@ -238,11 +277,18 @@ const UserManage = () => {
const [selectionType] = useState('checkbox');
const rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
console.log(
`selectedRowKeys: ${selectedRowKeys}`,
'selectedRows: ',
selectedRows,
);
console.log(selectedRowKeys.toString());
console.log(selectedRows.map(item => item.OUID).toString());
setUserIDs(selectedRowKeys.toString());
setOrgIDs(selectedRows.map(item => item.OUID).toString());
// 选中行数大于1时设置批量操作可行
if (selectedRows.length > 1) {
setMultiOperate(false);
setMultiOperateButtonType('primary');
} else {
setMultiOperate(true);
setMultiOperateButtonType('default');
}
},
getCheckboxProps: record => ({
name: record.name,
......@@ -322,9 +368,8 @@ const UserManage = () => {
setTableLength(temp.length);
const table = temp.map((item, index) => {
item.key = index;
item.phoneCopy = item.phone;
item.phone = item.phone || '-';
item.ddid = item.ddid ? '已绑定' : '未绑定';
item.wxid = item.wxid ? '已绑定' : '未绑定';
return item;
});
setTableData(table);
......@@ -365,15 +410,22 @@ const UserManage = () => {
const addUser = () => {
setUserVisible(true);
};
// 在根目录下添加机构
const addOrg = (title, id) => {
// 添加顶级机构
const addOrg = () => {
setAddOrgVisible(true);
setOrgTitle(title);
setOrgID(id);
setOrgID('-1');
addOrgForm.setFieldsValue({
OUName: '',
desrciption: '',
});
};
// 添加下级机构
const addSubOrg = () => {
setAddOrgVisible(true);
addOrgForm.setFieldsValue({
OUName: '',
desrciption: '',
});
};
// 编辑机构
const editOrg = () => {
......@@ -396,6 +448,22 @@ const UserManage = () => {
}
}, [currentUser]);
/** ***用户批量操作****** */
// 用户关联
const relateRoles = () => {
setRoleVisible(true);
};
// 更改机构
const changeOrgs = () => {
setChangeOrgVisible(true);
setMultiChangeOrgs(true);
};
// 删除用户
const deleteUsers = () => {
setDeleteUserVisible(true);
setMultiDelete(true);
};
/** ***右侧表格相关操作****** */
// 用户关联
const relateRole = record => {
......@@ -413,6 +481,8 @@ const UserManage = () => {
setPasswordVisible(true);
passwordForm.setFieldsValue({
oldpassword: record.password,
newPassword: '',
passwordConfirm: '',
});
setCurrentUser(record);
};
......@@ -423,7 +493,7 @@ const UserManage = () => {
editUserForm.setFieldsValue({
loginName: voca.stripTags(record.loginName),
userName: voca.stripTags(record.userName),
phone: record.phone || '',
phone: record.phoneCopy || '',
email: record.email || '',
});
setCurrentUser(record);
......@@ -504,11 +574,13 @@ const UserManage = () => {
message: '提交成功',
});
// 重新获取机构树与用户表
updateTrees().then(() => {
// 只能是字符串,数字没有选择效果
updateTrees();
onSelect([`${res.OUID}`]);
setExpandedKeys([`${res.OUID}`]);
});
// updateTrees().then(() => {
// // 只能是字符串,数字没有选择效果
// onSelect([`${res.OUID}`]);
// // setExpandedKeys([`${res.OUID}`]);
// });
} else {
notification.error({
message: '提交失败',
......@@ -538,7 +610,7 @@ const UserManage = () => {
// 重新获取机构树与用户表
updateTrees();
onSelect([orgID]);
setExpandedKeys([`${orgID}`]);
// setExpandedKeys([`${orgID}`]);
} else {
notification.error({
message: '提交失败',
......@@ -611,7 +683,7 @@ const UserManage = () => {
setRoleVisible(false);
// 跳转到新组织机构下的用户表
onSelect([`${currentUser.OUID}`]);
setExpandedKeys([`${currentUser.OUID}`]);
// setExpandedKeys([`${currentUser.OUID}`]);
notification.success({
message: '提交成功',
});
......@@ -634,7 +706,28 @@ const UserManage = () => {
setChangeOrgVisible(false);
// 跳转到新组织机构下的用户表
onSelect([newOrgID]);
setExpandedKeys([`${newOrgID}`]);
// setExpandedKeys([`${newOrgID}`]);
notification.success({
message: '提交成功',
});
} else {
notification.error({
message: '提交失败',
description: res.message,
});
}
})
.catch(err => {
message.error(err);
});
// 提交-批量更改机构
const submitChangeOrgs = () =>
addToOrgs(userIDs, orgIDs, newOrgID)
.then(res => {
if (res.code === 0) {
setChangeOrgVisible(false);
// 跳转到新组织机构下的用户表
onSelect([newOrgID]);
notification.success({
message: '提交成功',
});
......@@ -649,12 +742,16 @@ const UserManage = () => {
message.error(err);
});
// 提交-修改密码
const submitChangePassword = () =>
const submitChangePassword = () => {
const password = passwordForm.getFieldValue('password');
const newPassword = passwordForm.getFieldValue('newPassword');
const passwordConfirm = passwordForm.getFieldValue('passwordConfirm');
if (newPassword && passwordConfirm && newPassword === passwordConfirm) {
updateUserPassword(
currentUser.userID,
passwordForm.getFieldValue('password'),
passwordForm.getFieldValue('newPassword'),
passwordForm.getFieldValue('passwordConfirm'),
password,
newPassword,
passwordConfirm,
)
.then(res => {
if (res.success) {
......@@ -672,6 +769,18 @@ const UserManage = () => {
.catch(err => {
message.error(err);
});
} else if (newPassword === '' || passwordConfirm === '') {
notification.error({
message: '提交失败',
description: '带*号为必填项,不能为空',
});
} else {
notification.error({
message: '提交失败',
description: '确认密码不一致!',
});
}
};
// 提交-编辑用户
const submitEditUser = () =>
postEditUser(
......@@ -686,7 +795,7 @@ const UserManage = () => {
setEditUserVisible(false);
// 重新获取用户表
onSelect([`${currentUser.OUID}`]);
setExpandedKeys([`${currentUser.OUID}`]);
// setExpandedKeys([`${currentUser.OUID}`]);
notification.success({
message: '提交成功',
});
......@@ -715,7 +824,7 @@ const UserManage = () => {
setFreezeUserVisible(false);
// 重新获取用户表
onSelect([`${currentUser.OUID}`]);
setExpandedKeys([`${currentUser.OUID}`]);
// setExpandedKeys([`${currentUser.OUID}`]);
notification.success({
message: '提交成功',
});
......@@ -731,6 +840,7 @@ const UserManage = () => {
message.error(err);
});
};
// 提交-删除用户
const submitDeleteUser = () => {
postDeleteUser(currentUser.userID)
.then(res => {
......@@ -741,7 +851,32 @@ const UserManage = () => {
});
// 重新获取用户表
onSelect([`${currentUser.OUID}`]);
setExpandedKeys([`${currentUser.OUID}`]);
// setExpandedKeys([`${currentUser.OUID}`]);
} else {
notification.error({
message: '提交失败',
description: res.message,
});
}
})
.catch(err => {
setTableLoading(false);
message.error(err);
});
};
// 提交-批量删除用户
const submitDeleteUsers = () => {
const temp = orgIDs.split(',');
const [org] = temp;
multiDeleteUsers(userIDs, org)
.then(res => {
if (res.code === 0) {
setDeleteUserVisible(false);
notification.success({
message: '提交成功',
});
// 重新获取用户表
onSelect([currentSelectOrg]);
} else {
notification.error({
message: '提交失败',
......@@ -755,17 +890,56 @@ const UserManage = () => {
});
};
/** ***操作按钮**** */
// 机构操作
const orgButtonMenu = (
<Menu>
<Menu.Item key="1" onClick={addUser} icon={<UserAddOutlined />}>
添加用户
</Menu.Item>
<hr />
<Menu.Item key="2" onClick={addSubOrg} icon={<UsergroupAddOutlined />}>
添加机构
</Menu.Item>
<Menu.Item key="3" onClick={editOrg} icon={<EditOutlined />}>
编辑机构
</Menu.Item>
<Menu.Item key="4" onClick={deleteOrg} icon={<DeleteOutlined />}>
删除机构
</Menu.Item>
</Menu>
);
// 用户批量操作
const userButtonMenu = (
<Menu>
<Menu.Item key="1" onClick={relateRoles} icon={<ShareAltOutlined />}>
批量关联角色
</Menu.Item>
<Menu.Item key="2" onClick={changeOrgs} icon={<ApartmentOutlined />}>
批量更改机构
</Menu.Item>
<Menu.Item key="3" onClick={deleteUsers} icon={<DeleteOutlined />}>
批量删除用户
</Menu.Item>
</Menu>
);
return (
<PageContainer className={styles.userManageContainer}>
<div className={styles.contentContainer}>
{/* 左侧机构树 */}
<Spin spinning={treeLoading} tip="loading...">
<div className={treeVisible ? styles.orgContainer : styles.hide}>
{/* <div className={styles.orgContainer} style={{ display: treeDispaly }}> */}
<div
className={classnames({
[styles.orgContainer]: true,
[styles.orgContainerHide]: !treeVisible,
})}
>
<div>
<span style={{ margin: '10px' }}>机构列表</span>
<Tooltip title="添加机构">
<Tooltip title="添加顶级机构">
<UsergroupAddOutlined
onClick={() => addOrg('根目录', '-1')}
onClick={() => addOrg()}
style={{
float: 'right',
color: '#1890FF',
......@@ -786,58 +960,47 @@ const UserManage = () => {
/>
)}
</div>
</Spin>
<div style={{ color: '#1890FF', marginTop: '35vh', fontSize: '18px' }}>
<div className={styles.switcher}>
{treeVisible && (
<Tooltip title="隐藏机构列表">
<DoubleLeftOutlined
onClick={() => {
setTreeVisible(false);
// setTreeDispaly('none');
}}
/>
<DoubleLeftOutlined onClick={() => setTreeVisible(false)} />
</Tooltip>
)}
{!treeVisible && (
<Tooltip title="显示机构列表">
<DoubleRightOutlined
onClick={() => {
setTreeVisible(true);
// setTreeDispaly('block');
}}
/>
<DoubleRightOutlined onClick={() => setTreeVisible(true)} />
</Tooltip>
)}
</div>
</div>
</Spin>
{/* 右侧用户表 */}
<div className={styles.userContainer}>
<div style={{ height: '50px' }}>
<p style={{ margin: '16px 0 10px 16px', display: 'inline-block' }}>
用户数量(
<span className={styles.redText}>{tableLength}</span>
{orgTitle}(共{tableLength}人)
</p>
<span style={{ float: 'right', margin: '10px' }}>
<Search
style={{ width: 266 }}
placeholder="搜索登录名称/用户名称/手机号"
style={{ width: 300 }}
placeholder="请输入登录名称/用户名称/手机号"
onSearch={submitSearchUser}
onChange={e => handleSearch(e)}
enterButton
value={searchWord}
/>
<Button type="primary" onClick={addUser}>
添加用户
</Button>
<Button type="primary" onClick={addSubOrg}>
添加机构
</Button>
<Button type="primary" onClick={editOrg}>
编辑机构
<Dropdown overlay={orgButtonMenu}>
<Button type="primary">
机构操作 <DownOutlined />
</Button>
<Button type="primary" onClick={deleteOrg}>
删除机构
</Dropdown>
<Dropdown overlay={userButtonMenu} disabled={multiOperate}>
<Button type={multiOperateButtonType}>
用户批量操作 <DownOutlined />
</Button>
</Dropdown>
</span>
</div>
<Table
......@@ -854,8 +1017,10 @@ const UserManage = () => {
loading={tableLoading}
scroll={{ x: 'max-content' }}
pagination={{
showTotal: () => `共${tableLength}条`,
showTotal: (total, range) =>
`第${range[0]}-${range[1]} 条/共 ${total} 条`,
pageSizeOptions: [10, 20, 50, 100],
defaultPageSize: 20,
showQuickJumper: true,
showSizeChanger: true,
}}
......@@ -877,9 +1042,9 @@ const UserManage = () => {
<Form.Item
name="loginName"
label="登录名称"
rules={[{ required: true, message: '不能为空' }]}
rules={[{ required: true, message: '不能为空且不支持中文' }]}
>
<Input placeholder="请输入登录名称" />
<Input placeholder="登录名称不支持中文" />
</Form.Item>
<Form.Item
name="password"
......@@ -895,17 +1060,35 @@ const UserManage = () => {
>
<Input placeholder="请输入用户姓名" />
</Form.Item>
<Form.Item name="phone" label="手机号码">
<Form.Item
name="phone"
label="手机号码"
rules={[
{
pattern: new RegExp(/^1(3|4|5|6|7|8|9)\d{9}$/),
message: '请输入有效的手机号码!',
},
]}
>
<Input placeholder="请输入手机号码" />
</Form.Item>
<Form.Item name="email" label="电子邮箱">
<Input placeholder="请输入电子邮箱" />
<Form.Item
name="email"
label="电子邮箱"
rules={[
{
type: 'email',
message: '请输入有效的电子邮箱!',
},
]}
>
<Input placeholder="请输入电子邮箱" autoComplete="off" />
</Form.Item>
</Form>
</Modal>
{/* 添加下级机构 */}
<Modal
title={`在${orgTitle}下添加机构`}
title={orgID === '-1' ? '添加顶级机构' : `在${orgTitle}下添加机构`}
visible={addOrgVisible}
onOk={submitAddOrg}
onCancel={() => setAddOrgVisible(false)}
......@@ -1000,8 +1183,11 @@ const UserManage = () => {
<Modal
title="更改机构"
visible={changeOrgVisible}
onOk={submitChangeOrg}
onCancel={() => setChangeOrgVisible(false)}
onOk={multiChangeOrgs ? submitChangeOrgs : submitChangeOrg}
onCancel={() => {
setChangeOrgVisible(false);
setMultiChangeOrgs(false);
}}
okText="确认"
cancelText="取消"
width="330px"
......@@ -1076,11 +1262,29 @@ const UserManage = () => {
>
<Input placeholder="请输入用户姓名" />
</Form.Item>
<Form.Item name="phone" label="手机号码">
<Form.Item
name="phone"
label="手机号码"
rules={[
{
pattern: new RegExp(/^1(3|4|5|6|7|8|9)\d{9}$/),
message: '请输入有效的手机号码!',
},
]}
>
<Input placeholder="请输入手机号码" />
</Form.Item>
<Form.Item name="email" label="电子邮箱">
<Input placeholder="请输入电子邮箱" />
<Form.Item
name="email"
label="电子邮箱"
rules={[
{
type: 'email',
message: '请输入有效的电子邮箱!',
},
]}
>
<Input placeholder="请输入电子邮箱" autoComplete="off" />
</Form.Item>
</Form>
</Modal>
......@@ -1104,8 +1308,11 @@ const UserManage = () => {
<Modal
title="确认删除用户"
visible={deleteUserVisible}
onOk={submitDeleteUser}
onCancel={() => setDeleteUserVisible(false)}
onOk={multiDelete ? submitDeleteUsers : submitDeleteUser}
onCancel={() => {
setDeleteUserVisible(false);
setMultiDelete(false);
}}
okText="确认"
cancelText="取消"
>
......
......@@ -30,7 +30,15 @@
display: block;
}
}
.ant-pagination-prev,.ant-pagination-next{
line-height: 8px !important;
}
.ant-input-search-button{
line-height: 1;
}
.ant-dropdown-menu-item > .anticon:first-child {
vertical-align: 0.15em !important;
}
}
.redText{
color: red;
......@@ -78,9 +86,13 @@
height: calc(100vh - 74px);
float: left;
padding: 10px;
width: 200px;
padding-right: 22px;
width: 240px;
background: white;
overflow: auto;
margin-right:10px;
transform: translateX(0px);
transition: transform 0.5s;
.ant-tree{
padding-top: 6px;
.ant-tree-switcher{
......@@ -91,14 +103,23 @@
}
}
}
.switcher{
color: #1890FF;
font-size: 18px;
position: absolute;
left: 220px;
top: 46%;
}
}
.hide{
display: none;
.orgContainerHide{
transform: translateX(-230px);
}
.userContainer{
height: calc(100vh - 168px) !important;
height: calc(100vh - 74px) !important;
flex: 1;
min-width: 840px;
min-width: 760px;
background: white;
.ant-table-pagination{
padding-right: 12px;
......@@ -106,14 +127,13 @@
margin: 1px 0;
padding:8px;
padding-right: 20px;
.ant-pagination-prev,.ant-pagination-next{
line-height: 8px !important;
}
}
.ant-btn{
margin: 0px 10px;
.ant-btn-primary{
margin-left: 20px;
background: #50aefc;
}
}
.ant-input-search-button{
margin-left: 0px !important;
}
......@@ -133,6 +153,10 @@
border-right: white;
overflow: auto !important;
}
.ant-pagination{
z-index: 999;
border-top: 1px solid #f0eded;
}
}
}
}
......
......@@ -100,6 +100,15 @@ export const addToOrg = (userID, orgID, newOrgID) =>
oldOUID: orgID,
newOUID: newOrgID,
});
// 批量更改机构
export const addToOrgs = (userIDs, orgIDs, newOrgID) =>
get(`${PUBLISH_SERVICE}/UserCenter/ModifyUserRole`, {
_version: 9999,
_dc: Date.now(),
userIds: userIDs,
oldGroupIds: orgIDs,
newGroupId: newOrgID,
});
export const updateUserPassword = (
userID,
......@@ -141,6 +150,14 @@ export const deleteUser = userID =>
_dc: Date.now(),
userID,
});
// 批量删除用户
export const multiDeleteUsers = (userIDs, orgIDs) =>
get(`${PUBLISH_SERVICE}/UserCenter/DeleteUsers`, {
_version: 9999,
_dc: Date.now(),
userIds: userIDs,
groupId: orgIDs,
});
export const setUserRelation = (userID, roleList = [], stationList) =>
post(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment