初始化3.0.0版本

This commit is contained in:
zengqiao
2022-08-18 17:04:05 +08:00
parent 462303fca0
commit 51832385b1
2446 changed files with 93177 additions and 127211 deletions

View File

@@ -0,0 +1,635 @@
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import {
Form,
ProTable,
Button,
Input,
Modal,
Space,
Divider,
Drawer,
Transfer,
Row,
Col,
message,
Tooltip,
Spin,
AppContainer,
Utils,
Popover,
IconFont,
} from 'knowdesign';
import moment from 'moment';
import { CloseOutlined, LoadingOutlined, PlusOutlined } from '@ant-design/icons';
import { defaultPagination } from 'constants/common';
import { RoleProps, PermissionNode, AssignUser, RoleOperate, FormItemPermission } from './config';
import api from 'api';
import CheckboxGroupContainer from './CheckboxGroupContainer';
import { ConfigPermissionMap } from '../CommonConfig';
const { request } = Utils;
const { confirm } = Modal;
const { TextArea } = Input;
// 新增/编辑角色、查看角色详情抽屉
// eslint-disable-next-line react/display-name
const RoleDetailAndUpdate = forwardRef((props, ref): JSX.Element => {
const [global] = AppContainer.useGlobalValue();
const [form] = Form.useForm();
const [visible, setVisible] = useState<boolean>(false);
const [type, setType] = useState<RoleOperate>(RoleOperate.Add);
const [roleDetail, setRoleDetail] = useState<RoleProps>();
const [permissions, setPermissions] = useState<FormItemPermission[]>([]);
const [permissionFormLoading, setPermissionFormLoading] = useState<boolean>(false);
const [initSelectedPermissions, setInitSelectedPermission] = useState<{ [index: string]: [] }>({});
const [confirmLoading, setConfirmLoading] = useState(false);
const callback = useRef(() => {
return;
});
useEffect(() => {
const globalPermissions = global.permissions;
if (globalPermissions && globalPermissions.length) {
const sysPermissions = globalPermissions.map((sys: PermissionNode) => ({
id: sys.id,
name: sys.permissionName,
options: sys.childList.map((node) => ({ label: node.permissionName, value: node.id })),
}));
setPermissions(sysPermissions);
}
}, [global]);
useEffect(() => {
if (roleDetail) {
setPermissionFormLoading(true);
request(api.role(roleDetail.id)).then((res: any) => {
const initSelected = {};
const permissions = res.permissionTreeVO.childList;
permissions.forEach((sys) => {
initSelected[sys.id] = [];
sys.childList.forEach((node) => node.has && initSelected[sys.id].push(node.id));
});
setInitSelectedPermission(initSelected);
setPermissionFormLoading(false);
});
}
}, [roleDetail]);
const onSubmit = () => {
form.validateFields().then((formData) => {
formData.permissionIdList.forEach((arr, i) => {
// 如果分配的系统下的子权限,自动赋予该系统的权限
if (arr !== null && arr.length) {
arr.push(permissions[i].id);
}
});
formData.permissionIdList = formData.permissionIdList.flat();
setConfirmLoading(true);
request(api.editRole, {
method: type === RoleOperate.Add ? 'POST' : 'PUT',
data: Object.assign(formData, type === RoleOperate.Edit ? { id: roleDetail.id } : {}),
}).then(
(res) => {
callback.current();
onClose();
setInitSelectedPermission({});
message.success(`${type === RoleOperate.Add ? '新增' : '编辑'}角色成功`);
},
() => setConfirmLoading(false)
);
});
};
// 打开抽屉
const onOpen = (status: boolean, type: RoleOperate, cbk: () => { return }, record: RoleProps) => {
setInitSelectedPermission({});
form.setFieldsValue(record);
callback.current = cbk;
setRoleDetail(record);
setType(type);
setVisible(status);
};
// 关闭抽屉
const onClose = () => {
setVisible(false);
setRoleDetail(undefined);
form.resetFields();
setConfirmLoading(false);
};
useImperativeHandle(ref, () => ({
onOpen,
}));
return (
<Drawer
title={`${type === RoleOperate.Add ? '新增角色' : type === RoleOperate.Edit ? '编辑角色' : '查看角色详情'}`}
className="role-tab-detail"
width={600}
visible={visible}
maskClosable={false}
onClose={onClose}
extra={
<Space>
{type !== RoleOperate.View && (
<>
<Button size="small" onClick={onClose}>
</Button>
<Button type="primary" size="small" loading={confirmLoading} onClick={onSubmit}>
</Button>
<Divider type="vertical" />
</>
)}
</Space>
}
>
{type === RoleOperate.View ? (
// 查看角色详情
<>
<Row gutter={[12, 12]} className="desc-row">
<Col span={3} className="label-col">
:
</Col>
<Col span={21} className="value-col">
{(roleDetail && roleDetail.roleName) || '-'}
</Col>
<Col span={3} className="label-col">
:
</Col>
<Col span={21} className="value-col">
{(roleDetail && roleDetail.description) || '-'}
</Col>
</Row>
<div className="role-permissions-container">
<div className="title"></div>
<>
{permissions.length ? (
<Spin spinning={permissionFormLoading}>
{permissions.map((permission, i) => (
<CheckboxGroupContainer
key={i}
formInstance={form}
fieldName="permissionIdList"
options={permission.options}
initSelectedOptions={initSelectedPermissions[permission.id] || []}
groupIdx={i}
allCheckText={permission.name}
disabled
/>
))}
</Spin>
) : (
<></>
)}
</>
</div>
</>
) : (
// 新增/编辑角色
<Form form={form} layout="vertical">
<Form.Item
label="角色名称"
name="roleName"
rules={[
{ required: true, message: '角色名称不能为空' },
{
pattern: /^[\u4e00-\u9fa5a-zA-Z0-9_]{3,128}$/,
message: '角色名称只能由中英文大小写、数字、下划线(_)组成长度限制在3128字符',
},
]}
>
<Input placeholder="请输入角色名称" />
</Form.Item>
<Form.Item label="描述" name="description" rules={[{ required: true, message: '描述不能为空' }]}>
<TextArea placeholder="请输入描述" maxLength={200} />
</Form.Item>
<Form.Item
label="分配权限"
name="permissionIdList"
rules={[
() => ({
validator(_, value) {
if (Array.isArray(value) && value.some((item) => !!item.length)) {
return Promise.resolve();
}
return Promise.reject(new Error('请为角色至少分配一项权限'));
},
}),
]}
>
<>
{permissions.length ? (
<Spin spinning={permissionFormLoading}>
{permissions.map((permission, i) => (
<CheckboxGroupContainer
key={i}
formInstance={form}
fieldName="permissionIdList"
options={permission.options}
initSelectedOptions={initSelectedPermissions[permission.id] || []}
groupIdx={i}
allCheckText={permission.name}
/>
))}
</Spin>
) : (
<></>
)}
</>
</Form.Item>
</Form>
)}
</Drawer>
);
});
// 用户角色分配抽屉
// eslint-disable-next-line react/display-name
const AssignRoles = forwardRef((props, ref) => {
// TODO: check 状态
const [visible, setVisible] = useState<boolean>(false);
const [roleInfo, setRoleInfo] = useState<RoleProps>(undefined);
const [users, setUsers] = useState<AssignUser[]>([]);
const [selectedUsers, setSelectedUsers] = useState<string[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const [confirmLoading, setConfirmLoading] = useState<boolean>(false);
const callback = useRef(() => {
return;
});
const onClose = () => {
setVisible(false);
setRoleInfo(undefined);
setUsers([]);
setSelectedUsers([]);
setLoading(false);
setConfirmLoading(false);
};
const filterOption = (inputValue, option) => option.name.includes(inputValue);
const onChange = (newTargetKeys) => {
setSelectedUsers(newTargetKeys);
};
const onSubmit = () => {
if (!roleInfo) return;
setConfirmLoading(true);
request(api.assignRoles, {
method: 'POST',
data: {
flag: false,
id: roleInfo.id,
idList: selectedUsers,
},
}).then(
(res) => {
message.success('成功为角色分配用户');
callback.current();
onClose();
},
() => setConfirmLoading(false)
);
};
useEffect(() => {
if (roleInfo && visible) {
setLoading(true);
request(api.getAssignedUsersByRoleId(roleInfo.id)).then((res: AssignUser[]) => {
const selectedUsers = [];
res.forEach((user) => user.has && selectedUsers.push(user.id));
setUsers(res);
setSelectedUsers(selectedUsers);
setLoading(false);
});
}
}, [visible, roleInfo]);
useImperativeHandle(ref, () => ({
setVisible: (status: boolean, record: RoleProps, cbk: () => { return }) => {
callback.current = cbk;
setRoleInfo(record);
setVisible(status);
},
}));
return (
<Drawer
title="分配角色"
className="role-tab-assign-user"
width={600}
visible={visible}
maskClosable={false}
onClose={onClose}
extra={
<Space>
<Button size="small" onClick={onClose}>
</Button>
<Button type="primary" size="small" disabled={loading} loading={confirmLoading} onClick={onSubmit}>
</Button>
<Divider type="vertical" />
</Space>
}
>
<Row gutter={[12, 12]} className="desc-row">
<Col span={3} className="label-col">
:
</Col>
<Col span={21} className="value-col">
{roleInfo && roleInfo.roleName}
</Col>
<Col span={3} className="label-col">
:
</Col>
<Col span={21} className="value-col">
{roleInfo && roleInfo.description}
</Col>
</Row>
<Spin spinning={loading}>
<Transfer
titles={['未分配用户', '已分配用户']}
dataSource={users}
rowKey={(record) => record.id}
render={(item: AssignUser) => item.name}
showSearch
filterOption={filterOption}
targetKeys={selectedUsers}
onChange={onChange}
pagination
suffix={<IconFont type="icon-fangdajing" />}
/>
</Spin>
</Drawer>
);
});
export default (props: { curTabKey: string }): JSX.Element => {
const [global] = AppContainer.useGlobalValue();
const { curTabKey } = props;
const [roles, setRoles] = useState<RoleProps[]>([]);
const [pagination, setPagination] = useState<any>(defaultPagination);
const [loading, setLoading] = useState<boolean>(true);
const [deleteBtnLoading, setDeleteBtnLoading] = useState<number>(-1);
const [form] = Form.useForm();
const detailRef = useRef(null);
const assignRolesRef = useRef(null);
const columns = [
{
title: '角色ID',
dataIndex: 'roleCode',
},
{
title: '名称',
dataIndex: 'roleName',
},
{
title: '描述',
dataIndex: 'description',
lineClampOne: true,
},
{
title: '分配用户数',
dataIndex: 'authedUserCnt',
width: 100,
render(cnt: Pick<RoleProps, 'authedUserCnt'>, record: RoleProps) {
return (
<Popover
placement="right"
overlayClassName="tags-with-hide-popover"
content={
<div className="container-item-popover">
{record.authedUsers.map((username) => (
<div key={username} className="container-item">
{username}
</div>
))}
</div>
}
>
<Button size="small" type="link">
{cnt}
</Button>
</Popover>
);
},
},
{
title: '最后修改人',
dataIndex: 'lastReviser',
},
{
title: '最后更新时间',
dataIndex: 'updateTime',
width: 180,
render: (date) => moment(date).format('YYYY-MM-DD HH:mm:ss'),
},
{
title: '操作',
width: 260,
render(record) {
return (
<>
<Button
type="link"
size="small"
style={{ paddingLeft: 0 }}
onClick={() => detailRef.current.onOpen(true, RoleOperate.View, getRoleList, record)}
>
</Button>
{global.hasPermission && global.hasPermission(ConfigPermissionMap.ROLE_ASSIGN) ? (
<Button type="link" size="small" onClick={() => assignRolesRef.current.setVisible(true, record, getRoleList)}>
</Button>
) : (
<></>
)}
{global.hasPermission && global.hasPermission(ConfigPermissionMap.ROLE_EDIT) ? (
<Button type="link" size="small" onClick={() => detailRef.current.onOpen(true, RoleOperate.Edit, getRoleList, record)}>
</Button>
) : (
<></>
)}
{global.hasPermission && global.hasPermission(ConfigPermissionMap.ROLE_DEL) ? (
<Button type="link" size="small" onClick={() => onDelete(record)}>
{record.id === deleteBtnLoading ? <LoadingOutlined /> : '删除'}
</Button>
) : (
<></>
)}
</>
);
},
},
];
const getRoleList = (query = {}) => {
const formData = form.getFieldsValue();
const data = {
page: pagination.current,
size: pagination.pageSize,
...formData,
...query,
};
setLoading(true);
request(api.roleList, {
method: 'POST',
data,
}).then(
(res: any) => {
const { pageNo, pageSize, pages, total } = res.pagination;
if (pageNo > pages && pages !== 0) {
getRoleList({ page: pages });
return false;
}
setPagination({
...pagination,
current: pageNo,
pageSize,
total,
});
setRoles(res.bizData);
setLoading(false);
},
() => setLoading(false)
);
};
const onDelete = (record) => {
if (deleteBtnLoading !== -1) return;
setDeleteBtnLoading(record.id);
request(api.checkRole(record.id), {
method: 'DELETE',
}).then(
(res: any) => {
setDeleteBtnLoading(-1);
const userList = res && res.userNameList;
const couldDelete = !(userList && userList.length);
const isShowTooltip = couldDelete ? false : userList.length > 2;
confirm({
// 删除角色弹窗
title: couldDelete ? '确定删除以下角色吗?' : '请先解除角色引用关系',
content: (
<div>
<div>{record.roleName}</div>
{!couldDelete && (
<span>
{isShowTooltip ? (
<Tooltip title={userList.join('')}>
{userList.slice(0, 2).join('')}... {userList.length}
</Tooltip>
) : (
userList.join('')
)}
</span>
)}
</div>
),
okText: couldDelete ? '删除' : '确定',
okType: 'primary',
centered: true,
okButtonProps: {
size: 'small',
danger: couldDelete,
},
cancelButtonProps: {
size: 'small',
},
maskClosable: true,
onOk() {
return (
couldDelete &&
request(api.role(record.id), {
method: 'DELETE',
}).then((_) => {
message.success('删除成功');
getRoleList();
})
);
},
onCancel() {
return;
},
});
},
() => setDeleteBtnLoading(-1)
);
};
const onTableChange = (curPagination) => {
getRoleList({
page: curPagination.current,
size: curPagination.pageSize,
});
};
useEffect(() => {
if (curTabKey === 'role') {
getRoleList();
}
}, [curTabKey]);
return (
<>
<div className="operate-bar">
<Form form={form} layout="inline" onFinish={() => getRoleList({ page: 1 })}>
<Form.Item name="roleName">
<Input placeholder="请输入角色名称" />
</Form.Item>
<Form.Item>
<Button type="primary" ghost htmlType="submit">
</Button>
</Form.Item>
</Form>
{global.hasPermission && global.hasPermission(ConfigPermissionMap.ROLE_ADD) ? (
<Button
type="primary"
icon={<PlusOutlined />}
onClick={() => detailRef.current.onOpen(true, RoleOperate.Add, getRoleList, undefined)}
>
</Button>
) : (
<></>
)}
</div>
<ProTable
tableProps={{
showHeader: false,
loading,
rowKey: 'id',
dataSource: roles,
paginationProps: pagination,
columns,
lineFillColor: true,
attrs: {
onChange: onTableChange,
scroll: {
scrollToFirstRowOnChange: true,
x: true,
y: 'calc(100vh - 326px)',
},
},
}}
/>
<RoleDetailAndUpdate ref={detailRef} />
<AssignRoles ref={assignRolesRef} />
</>
);
};