Commit 1c5e79b5 authored by Q.Roy's avatar Q.Roy

feat(角色模块):

parent bc10ef2c
.normal {
background: #79F2AA;
}
import styles from './index.css';
export default function() {
return (
<div className={styles.normal}>
<h1>I am a umi block!</h1>
</div>
);
}
{
"name": "authority",
"name": "role",
"version": "0.0.1",
"description": "权限管理模块",
"description": "角色管理模块",
"main": "src/index.js",
"authors": {
"name": "",
"email": ""
},
"repository": "https://code.cnjiang.com/qi.ruan/admin-page-blocks/authority",
"repository": "https://code.cnjiang.com/qi.ruan/admin-page-blocks/role",
"scripts": {
"dev": "umi dev"
},
"dependencies": {
"react": ">=16.0.0"
"dva": "^2.4.0",
"moment": "^2.22.2",
"redux": "^4.0.1",
"umi-request": "^1.0.0"
},
"devDependencies": {
"umi": "^2.9.0",
"umi-plugin-block-dev": "^2.0.0"
},
"peerDependencies": {
"@ant-design/pro-layout": "^4.5.5"
},
"license": "MIT"
}
import { parse } from 'url';
// mock tableListDataSource
let tableListDataSource = [];
for (let i = 0; i < 8; i += 1) {
tableListDataSource.push({
key: i,
disabled: i % 6 === 0,
href: 'https://ant.design',
avatar: [
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
][i % 2],
name: `TradeCode ${i}`,
title: `一个任务名称 ${i}`,
owner: '曲丽丽',
desc: '这是一段描述',
callNo: Math.floor(Math.random() * 1000),
status: Math.floor(Math.random() * 10) % 4,
updatedAt: new Date(`2017-07-${Math.floor(i / 2) + 1}`),
createdAt: new Date(`2017-07-${Math.floor(i / 2) + 1}`),
progress: Math.ceil(Math.random() * 100),
});
}
function getRule(req, res, u) {
let url = u;
if (!url || Object.prototype.toString.call(url) !== '[object String]') {
// eslint-disable-next-line prefer-destructuring
url = req.url;
}
const params = parse(url, true).query;
let dataSource = tableListDataSource;
if (params.sorter) {
const s = params.sorter.split('_');
dataSource = dataSource.sort((prev, next) => {
if (s[1] === 'descend') {
return next[s[0]] - prev[s[0]];
}
return prev[s[0]] - next[s[0]];
});
}
if (params.status) {
const status = params.status.split(',');
let filterDataSource = [];
status.forEach(s => {
filterDataSource = filterDataSource.concat(
dataSource.filter(item => {
if (parseInt(`${item.status}`, 10) === parseInt(s.split('')[0], 10)) {
return true;
}
return false;
}),
);
});
dataSource = filterDataSource;
}
if (params.name) {
dataSource = dataSource.filter(data => data.name.indexOf(params.name) > -1);
}
let pageSize = 10;
if (params.pageSize) {
pageSize = parseInt(`${params.pageSize}`, 0);
}
const result = {
list: dataSource,
pagination: {
total: dataSource.length,
pageSize,
current: parseInt(`${params.currentPage}`, 10) || 1,
},
};
return res.json(result);
}
function postRule(req, res, u, b) {
let url = u;
if (!url || Object.prototype.toString.call(url) !== '[object String]') {
// eslint-disable-next-line prefer-destructuring
url = req.url;
}
const body = (b && b.body) || req.body;
const { method, name, desc, key } = body;
switch (method) {
/* eslint no-case-declarations:0 */
case 'delete':
tableListDataSource = tableListDataSource.filter(item => key.indexOf(item.key) === -1);
break;
case 'post':
const i = Math.ceil(Math.random() * 10000);
tableListDataSource.unshift({
key: i,
href: 'https://ant.design',
avatar: [
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
][i % 2],
name: `TradeCode ${i}`,
title: `一个任务名称 ${i}`,
owner: '曲丽丽',
desc,
callNo: Math.floor(Math.random() * 1000),
status: Math.floor(Math.random() * 10) % 2,
updatedAt: new Date(),
createdAt: new Date(),
progress: Math.ceil(Math.random() * 100),
});
break;
case 'update':
tableListDataSource = tableListDataSource.map(item => {
if (item.key === key) {
return { ...item, desc, name };
}
return item;
});
break;
default:
break;
}
const result = {
list: tableListDataSource,
pagination: {
total: tableListDataSource.length,
},
};
return res.json(result);
}
export default {
'GET /api/rule': getRule,
'POST /api/rule': postRule,
};
import { Form, TreeSelect, Modal, Input } from 'antd';
import React from 'react';
import { connect } from 'dva';
const { SHOW_ALL } = TreeSelect;
const RoleConfigForm = props => {
const {
modalVisible,
form,
handleUpdateRole,
handleModalVisible,
record: { id: roleId, actionType },
} = props;
const editable = actionType === 'edit';
const selectedAuths = [];
const okHandle = () => {
form.validateFields((err, fieldsValue) => {
if (err) return;
form.resetFields();
handleUpdateRole({
roleId,
...fieldsValue,
});
});
};
const onChange = value => {
form.setFieldsValue({ authIds: value });
};
const mappingRoleInfoToTreeData = (roleInfo, selected) => {
const mappedNodes = roleInfo.map(node => {
if (node.enabled === 'T') {
// set initial selected item
selectedAuths.push(node.id);
}
return {
key: node.id,
value: node.id,
title: node.name,
children: mappingRoleInfoToTreeData(node.childs || [], selected),
};
});
return mappedNodes;
};
const treeData = mappingRoleInfoToTreeData(props.roleInfo || [], selectedAuths);
const treeSelectProps = {
onChange,
treeCheckable: true,
showCheckedStrategy: SHOW_ALL,
searchPlaceholder: '请选择用户权限',
treeDefaultExpandAll: true,
allowClear: editable,
style: {
width: '100%',
},
};
const renderTreeNodes = data =>
data.map(item => {
if (item.children) {
return (
<TreeSelect.TreeNode
title={item.title}
key={item.key}
value={item.value}
disableCheckbox={!editable}
>
{renderTreeNodes(item.children)}
</TreeSelect.TreeNode>
);
}
return <TreeSelect.TreeNode key={item.key} {...item} disableCheckbox={!editable} />;
});
return (
<Modal
destroyOnClose
title="新建规则"
visible={modalVisible}
onOk={okHandle}
onCancel={() => handleModalVisible()}
width={800}
>
<Form.Item
labelCol={{
span: 5,
}}
wrapperCol={{
span: 15,
}}
label="角色名称"
>
{form.getFieldDecorator('roleName', {
initialValue: props.record.roleName,
rules: [
{
required: true,
message: '请输入角色名称',
},
],
})(<Input placeholder="请输入" disabled />)}
</Form.Item>
<Form.Item
labelCol={{
span: 5,
}}
wrapperCol={{
span: 15,
}}
label="用户权限"
>
{form.getFieldDecorator('authIds', {
initialValue: selectedAuths,
})(<TreeSelect {...treeSelectProps}>{renderTreeNodes(treeData)}</TreeSelect>)}
</Form.Item>
</Modal>
);
};
export default connect(({ role, loading }) => ({
roleInfo: role.roleInfo,
loading: loading.models.role,
}))(Form.create()(RoleConfigForm));
import { Form, Input, Modal } from 'antd';
import React from 'react';
const FormItem = Form.Item;
const CreateForm = props => {
const { modalVisible, form, handleAddRole, handleModalVisible } = props;
const okHandle = () => {
form.validateFields((err, fieldsValue) => {
if (err) return;
form.resetFields();
handleAddRole(fieldsValue);
});
};
return (
<Modal
destroyOnClose
title="新增角色"
visible={modalVisible}
onOk={okHandle}
onCancel={() => handleModalVisible()}
>
<FormItem
labelCol={{
span: 5,
}}
wrapperCol={{
span: 15,
}}
label="角色名称"
>
{form.getFieldDecorator('roleName', {
rules: [
{
required: true,
message: '请输入角色名称',
},
],
})(<Input placeholder="请输入" />)}
</FormItem>
<FormItem
labelCol={{
span: 5,
}}
wrapperCol={{
span: 15,
}}
label="角色说明"
>
{form.getFieldDecorator('info')(<Input.TextArea placeholder="请输入" />)}
</FormItem>
</Modal>
);
};
export default Form.create()(CreateForm);
import { Alert, Table } from 'antd';
import React, { Component, Fragment } from 'react';
import styles from './index.less';
function initTotalList(columns) {
if (!columns) {
return [];
}
const totalList = [];
columns.forEach(column => {
if (column.needTotal) {
totalList.push({ ...column, total: 0 });
}
});
return totalList;
}
class StandardTable extends Component {
static getDerivedStateFromProps(nextProps) {
// clean state
if (nextProps.selectedRows.length === 0) {
const needTotalList = initTotalList(nextProps.columns);
return {
selectedRowKeys: [],
needTotalList,
};
}
return null;
}
constructor(props) {
super(props);
const { columns } = props;
const needTotalList = initTotalList(columns);
this.state = {
selectedRowKeys: [],
needTotalList,
};
}
handleRowSelectChange = (selectedRowKeys, selectedRows) => {
const currySelectedRowKeys = selectedRowKeys;
let { needTotalList } = this.state;
needTotalList = needTotalList.map(item => ({
...item,
total: selectedRows.reduce((sum, val) => sum + parseFloat(val[item.dataIndex || 0]), 0),
}));
const { onSelectRow } = this.props;
if (onSelectRow) {
onSelectRow(selectedRows);
}
this.setState({
selectedRowKeys: currySelectedRowKeys,
needTotalList,
});
};
handleTableChange = (pagination, filters, sorter, ...rest) => {
const { onChange } = this.props;
if (onChange) {
onChange(pagination, filters, sorter, ...rest);
}
};
cleanSelectedKeys = () => {
if (this.handleRowSelectChange) {
this.handleRowSelectChange([], []);
}
};
render() {
const { selectedRowKeys, needTotalList } = this.state;
const { data, rowKey, ...rest } = this.props;
const { list = [], pagination = false } = data || {};
const paginationProps = pagination
? {
showSizeChanger: true,
showQuickJumper: true,
...pagination,
}
: false;
const rowSelection = {
selectedRowKeys,
onChange: this.handleRowSelectChange,
getCheckboxProps: record => ({
disabled: record.disabled,
}),
};
return (
<div className={styles.standardTable}>
<div className={styles.tableAlert}>
<Alert
message={
<Fragment>
已选择{' '}
<a
style={{
fontWeight: 600,
}}
>
{selectedRowKeys.length}
</a>{' '}
&nbsp;&nbsp;
{needTotalList.map((item, index) => (
<span
style={{
marginLeft: 8,
}}
key={item.dataIndex}
>
{item.title}
总计&nbsp;
<span
style={{
fontWeight: 600,
}}
>
{item.render ? item.render(item.total, item, index) : item.total}
</span>
</span>
))}
<a
onClick={this.cleanSelectedKeys}
style={{
marginLeft: 24,
}}
>
清空
</a>
</Fragment>
}
type="info"
showIcon
/>
</div>
<Table
rowKey={rowKey || 'key'}
rowSelection={rowSelection}
dataSource={list}
pagination={paginationProps}
onChange={this.handleTableChange}
{...rest}
/>
</div>
);
}
}
export default StandardTable;
@import '~antd/es/style/themes/default.less';
.standardTable {
:global {
.ant-table-pagination {
margin-top: 24px;
}
}
.tableAlert {
margin-bottom: 16px;
}
}
import { Button, DatePicker, Form, Input, Modal, Radio, Select, Steps } from 'antd';
import React, { Component } from 'react';
const FormItem = Form.Item;
const { Step } = Steps;
const { TextArea } = Input;
const { Option } = Select;
const RadioGroup = Radio.Group;
class UpdateForm extends Component {
static defaultProps = {
handleUpdate: () => {},
handleUpdateModalVisible: () => {},
values: {},
};
formLayout = {
labelCol: {
span: 7,
},
wrapperCol: {
span: 13,
},
};
constructor(props) {
super(props);
this.state = {
formVals: {
name: props.values.name,
desc: props.values.desc,
key: props.values.key,
target: '0',
template: '0',
type: '1',
time: '',
frequency: 'month',
},
currentStep: 0,
};
}
handleNext = currentStep => {
const { form, handleUpdate } = this.props;
const { formVals: oldValue } = this.state;
form.validateFields((err, fieldsValue) => {
if (err) return;
const formVals = { ...oldValue, ...fieldsValue };
this.setState(
{
formVals,
},
() => {
if (currentStep < 2) {
this.forward();
} else {
handleUpdate(formVals);
}
},
);
});
};
backward = () => {
const { currentStep } = this.state;
this.setState({
currentStep: currentStep - 1,
});
};
forward = () => {
const { currentStep } = this.state;
this.setState({
currentStep: currentStep + 1,
});
};
renderContent = (currentStep, formVals) => {
const { form } = this.props;
if (currentStep === 1) {
return [
<FormItem key="target" {...this.formLayout} label="监控对象">
{form.getFieldDecorator('target', {
initialValue: formVals.target,
})(
<Select
style={{
width: '100%',
}}
>
<Option value="0">表一</Option>
<Option value="1">表二</Option>
</Select>,
)}
</FormItem>,
<FormItem key="template" {...this.formLayout} label="规则模板">
{form.getFieldDecorator('template', {
initialValue: formVals.template,
})(
<Select
style={{
width: '100%',
}}
>
<Option value="0">规则模板一</Option>
<Option value="1">规则模板二</Option>
</Select>,
)}
</FormItem>,
<FormItem key="type" {...this.formLayout} label="规则类型">
{form.getFieldDecorator('type', {
initialValue: formVals.type,
})(
<RadioGroup>
<Radio value="0"></Radio>
<Radio value="1"></Radio>
</RadioGroup>,
)}
</FormItem>,
];
}
if (currentStep === 2) {
return [
<FormItem key="time" {...this.formLayout} label="开始时间">
{form.getFieldDecorator('time', {
rules: [
{
required: true,
message: '请选择开始时间!',
},
],
})(
<DatePicker
style={{
width: '100%',
}}
showTime
format="YYYY-MM-DD HH:mm:ss"
placeholder="选择开始时间"
/>,
)}
</FormItem>,
<FormItem key="frequency" {...this.formLayout} label="调度周期">
{form.getFieldDecorator('frequency', {
initialValue: formVals.frequency,
})(
<Select
style={{
width: '100%',
}}
>
<Option value="month"></Option>
<Option value="week"></Option>
</Select>,
)}
</FormItem>,
];
}
return [
<FormItem key="name" {...this.formLayout} label="规则名称">
{form.getFieldDecorator('name', {
rules: [
{
required: true,
message: '请输入规则名称!',
},
],
initialValue: formVals.name,
})(<Input placeholder="请输入" />)}
</FormItem>,
<FormItem key="desc" {...this.formLayout} label="规则描述">
{form.getFieldDecorator('desc', {
rules: [
{
required: true,
message: '请输入至少五个字符的规则描述!',
min: 5,
},
],
initialValue: formVals.desc,
})(<TextArea rows={4} placeholder="请输入至少五个字符" />)}
</FormItem>,
];
};
renderFooter = currentStep => {
const { handleUpdateModalVisible, values } = this.props;
if (currentStep === 1) {
return [
<Button
key="back"
style={{
float: 'left',
}}
onClick={this.backward}
>
上一步
</Button>,
<Button key="cancel" onClick={() => handleUpdateModalVisible(false, values)}>
取消
</Button>,
<Button key="forward" type="primary" onClick={() => this.handleNext(currentStep)}>
下一步
</Button>,
];
}
if (currentStep === 2) {
return [
<Button
key="back"
style={{
float: 'left',
}}
onClick={this.backward}
>
上一步
</Button>,
<Button key="cancel" onClick={() => handleUpdateModalVisible(false, values)}>
取消
</Button>,
<Button key="submit" type="primary" onClick={() => this.handleNext(currentStep)}>
完成
</Button>,
];
}
return [
<Button key="cancel" onClick={() => handleUpdateModalVisible(false, values)}>
取消
</Button>,
<Button key="forward" type="primary" onClick={() => this.handleNext(currentStep)}>
下一步
</Button>,
];
};
render() {
const { updateModalVisible, handleUpdateModalVisible, values } = this.props;
const { currentStep, formVals } = this.state;
return (
<Modal
width={640}
bodyStyle={{
padding: '32px 40px 48px',
}}
destroyOnClose
title="规则配置"
visible={updateModalVisible}
footer={this.renderFooter(currentStep)}
onCancel={() => handleUpdateModalVisible(false, values)}
afterClose={() => handleUpdateModalVisible()}
>
<Steps
style={{
marginBottom: 28,
}}
size="small"
current={currentStep}
>
<Step title="基本信息" />
<Step title="配置规则属性" />
<Step title="设定调度周期" />
</Steps>
{this.renderContent(currentStep, formVals)}
</Modal>
);
}
}
export default Form.create()(UpdateForm);
export interface TableListItem {
key: number;
disabled?: boolean;
href: string;
avatar: string;
name: string;
title: string;
owner: string;
desc: string;
callNo: number;
status: number;
updatedAt: Date;
createdAt: Date;
progress: number;
}
export interface TableListPagination {
total: number;
pageSize: number;
current: number;
}
export interface TableListData {
list: TableListItem[];
pagination: Partial<TableListPagination>;
}
export interface TableListParams {
sorter: string;
status: string;
name: string;
pageSize: number;
currentPage: number;
}
import {
Button,
Card,
Col,
Divider,
Dropdown,
Form,
Icon,
Input,
Menu,
Row,
message,
Popconfirm,
} from 'antd';
import React, { Component, Fragment } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { connect } from 'dva';
import StandardTable from './components/StandardTable';
import RoleCreateForm from './components/RoleCreateForm';
import RoleConfigForm from './components/RoleConfigForm';
import styles from './style.less';
const getValue = obj =>
Object.keys(obj)
.map(key => obj[key])
.join(',');
/* eslint react/no-multi-comp:0 */
@connect(({ role, loading }) => ({
role,
loading: loading.models.role,
}))
class RoleManagement extends Component {
/**
* state
* 维护组件唯一数据源
* 允许存在以下数据源
* Modal: 页面弹出框配置数据
* ListOptions: 列表筛选器配置数据
* List: 列表主要数据源
* Selected: 选中相关的
*/
state = {
roleCreateModalVisible: false,
roleConfigModalVisible: false,
selectedRows: [],
listOptions: {},
currentRecord: {},
pagination: {
pageNum: 1,
pageSize: 10,
},
};
columns = [
{
title: '角色名称',
dataIndex: 'roleName',
},
{
title: '操作',
render: (text, record) => (
<Fragment>
<a onClick={() => this.handleOpenRoleConfigModal('view', record)}>查看</a>
<Divider type="vertical" />
<a onClick={() => this.handleOpenRoleConfigModal('edit', record)}>编辑</a>
<Divider type="vertical" />
<Popconfirm
title="您确定要移除该角色吗?"
onConfirm={() => this.handleDeleteRoleRecord(true, record)}
okText="确认"
cancelText="取消"
>
<a>删除</a>
</Popconfirm>
</Fragment>
),
},
];
componentDidMount() {
const { pagination } = this.state;
this.getRoles({
...pagination,
});
}
/**
* private methods
*/
getRoles = payload => {
const { dispatch } = this.props;
dispatch({
type: 'role/getRoles',
payload: {
...payload,
},
});
};
refreshList = () => {
const { pagination, listOptions } = this.state;
this.getRoles({
...pagination,
...listOptions,
});
};
/**
* handlers
*/
handleStandardTableChange = (pagination, filtersArg, sorter) => {
const { dispatch } = this.props;
const { listOptions } = this.state;
const filters = Object.keys(filtersArg).reduce((obj, key) => {
const newObj = { ...obj };
newObj[key] = getValue(filtersArg[key]);
return newObj;
}, {});
this.setState({
pagination: {
pageNum: pagination.current,
pageSize: pagination.pageSize,
},
});
const params = {
...pagination,
...listOptions,
...filters,
};
if (sorter.field) {
params.sorter = `${sorter.field}_${sorter.order}`;
}
dispatch({
type: 'role/getRoles',
payload: params,
});
};
handleFormReset = () => {
const { form } = this.props;
const { pagination } = this.state;
form.resetFields();
this.setState({
listOptions: {},
});
this.getRoles({
...pagination,
});
};
handleBatchOperationMenuClick = e => {
const { dispatch } = this.props;
const { selectedRows } = this.state;
if (!selectedRows) return;
switch (e.key) {
case 'remove':
dispatch({
type: 'listAndtableAndlist/remove',
payload: {
key: selectedRows.map(row => row.key),
},
callback: () => {
this.setState({
selectedRows: [],
});
},
});
break;
default:
break;
}
};
handleSelectRows = rows => {
this.setState({
selectedRows: rows,
});
};
handleSearch = e => {
e.preventDefault();
const { dispatch, form } = this.props;
const { pagination } = this.state;
form.validateFields((err, fieldsValue) => {
if (err) return;
const values = {
...fieldsValue,
};
this.setState({
listOptions: values,
pagination: {
pageNum: 1,
pageSize: 10,
},
});
dispatch({
type: 'role/getRoles',
payload: {
...values,
...pagination,
},
});
});
};
handleRoleCreateModalVisible = flag => {
this.setState({
roleCreateModalVisible: !!flag,
});
};
handleRoleConfigModalVisible = flag => {
this.setState({
roleConfigModalVisible: !!flag,
});
};
handleAddRole = fields => {
const { dispatch } = this.props;
dispatch({
type: 'role/addRole',
payload: {
...fields,
},
callback: () => {
message.success('操作成功');
this.refreshList();
this.handleRoleCreateModalVisible();
},
});
};
handleOpenRoleConfigModal = (type, record) => {
const { dispatch } = this.props;
dispatch({
type: 'role/getRoleInfo',
payload: { ...record },
});
this.setState({
currentRecord: {
...record,
actionType: type,
},
});
this.handleRoleConfigModalVisible(true);
};
handleUpdateRole = values => {
const { dispatch } = this.props;
dispatch({
type: 'role/updateRoleInfo',
payload: { ...values },
callback: () => {
message.success('操作成功');
},
});
};
handleDeleteRoleRecord = (flag, record) => {
if (!flag) {
return;
}
const { dispatch } = this.props;
dispatch({
type: 'role/deleteRole',
payload: {
id: record.id,
},
callback: () => {
message.success('操作成功');
this.refreshList();
},
});
};
/**
* renders
*/
renderFilter() {
// you can use expandForm or another key to expand and fold an complex form
const { form } = this.props;
const { getFieldDecorator } = form;
return (
<Form onSubmit={this.handleSearch} layout="inline">
<Row
gutter={{
md: 8,
lg: 24,
xl: 48,
}}
>
<Col md={8} sm={24}>
<Form.Item label="角色名称">
{getFieldDecorator('roleName')(<Input placeholder="请输入" />)}
</Form.Item>
</Col>
<Col md={8} sm={24}>
<span className={styles.submitButtons}>
<Button type="primary" htmlType="submit">
查询
</Button>
<Button
style={{
marginLeft: 8,
}}
onClick={this.handleFormReset}
>
重置
</Button>
</span>
</Col>
</Row>
</Form>
);
}
render() {
const {
role: { users },
loading,
} = this.props;
const {
selectedRows,
roleCreateModalVisible,
roleConfigModalVisible,
currentRecord,
} = this.state;
const batchOperationMenu = (
<Menu onClick={this.handleBatchOperationMenuClick} selectedKeys={[]}>
<Menu.Item key="remove">删除</Menu.Item>
</Menu>
);
const roleCreateModalMethods = {
handleAddRole: this.handleAddRole,
handleModalVisible: this.handleRoleCreateModalVisible,
};
const roleConfigModalMethods = {
handleModalVisible: this.handleRoleConfigModalVisible,
handleUpdateRole: this.handleUpdateRole,
};
return (
<PageHeaderWrapper>
<Card bordered={false}>
<div className={styles.tableList}>
<div className={styles.tableListForm}>{this.renderFilter()}</div>
<div className={styles.tableListOperator}>
<Button
icon="plus"
type="primary"
onClick={() => this.handleRoleCreateModalVisible(true)}
>
新建
</Button>
{selectedRows.length > 0 && (
<span>
<Dropdown overlay={batchOperationMenu}>
<Button>
批量操作 <Icon type="down" />
</Button>
</Dropdown>
</span>
)}
</div>
<StandardTable
selectedRows={selectedRows}
loading={loading}
data={users}
columns={this.columns}
onSelectRow={this.handleSelectRows}
onChange={this.handleStandardTableChange}
/>
</div>
</Card>
<RoleCreateForm {...roleCreateModalMethods} modalVisible={roleCreateModalVisible} />
<RoleConfigForm
{...roleConfigModalMethods}
record={currentRecord}
modalVisible={roleConfigModalVisible}
/>
</PageHeaderWrapper>
);
}
}
export default Form.create()(RoleManagement);
import { getRoles, removeRole, insertRole, getRoleInfo, updateRoleInfo } from './service';
const Model = {
namespace: 'role',
state: {
users: {
list: [],
pagination: {},
},
roleInfo: [],
},
effects: {
*getRoles({ payload }, { call, put }) {
const response = yield call(getRoles, payload);
yield put({
type: 'saveUser',
payload: response.data,
});
},
*deleteRole({ payload, callback }, { call }) {
const response = yield call(removeRole, payload);
if (response.code === 200 && callback) {
callback(response);
}
},
*addRole({ payload, callback }, { call }) {
const response = yield call(insertRole, payload);
if (response.code === 200 && callback) {
callback(response);
}
},
*getRoleInfo({ payload }, { call, put }) {
const response = yield call(getRoleInfo, payload);
yield put({
type: 'saveRole',
payload: response.data,
});
},
*updateRoleInfo({ payload, callback }, { call }) {
const response = yield call(updateRoleInfo, payload);
if (response.code === 200 && callback) {
callback(response);
}
},
},
reducers: {
saveUser(state, action) {
return { ...state, users: action.payload };
},
saveRole(state, action) {
return { ...state, roleInfo: action.payload };
},
},
};
export default Model;
import request from '@/utils/request';
export async function getRoles(params) {
return request(
{
method: 'post',
url: '/rest/admin/SysSystemRole/list',
// front end params to server end dto
params: {
...params,
},
},
// server end vo to front end object
res => {
const formattedRes = {
...res,
data: {
list: res.data.list.map(item => Object.assign(item, { key: item.id })),
pagination: {
current: res.data.pageNum,
pageSize: res.data.pageSize,
total: res.data.total,
},
},
};
return formattedRes;
},
);
}
export async function removeUser(params) {
return request({
method: 'post',
url: '/rest/admin/MemberInfo/remove',
params,
});
}
export async function insertRole(params) {
return request({
method: 'post',
url: '/rest/admin/SysSystemRole/insert',
params,
});
}
export async function removeRole(params) {
return request({
method: 'post',
url: '/rest/admin/SysSystemRole/remove',
params,
});
}
export async function updateRole(params) {
return request({
method: 'post',
url: '/rest/admin/SysSystemRole/update',
params,
});
}
export async function viewRole(params) {
return request({
method: 'post',
url: '/rest/admin/SysSystemRole/insert',
params,
});
}
export async function getRoleInfo(params) {
return request({
method: 'post',
url: '/rest/admin/SysSystemRole/getInfo',
params: {
roleId: params.id,
},
});
}
export async function updateRoleInfo(params) {
const { roleId, authIds } = params;
return request({
method: 'post',
url: '/rest/admin/SysSystemRole/updateInfo',
params: {
roleId,
authIds,
},
});
}
@import '~antd/es/style/themes/default.less';
@import './utils/utils.less';
.tableList {
.tableListOperator {
margin-bottom: 16px;
button {
margin-right: 8px;
}
}
}
.tableListForm {
:global {
.ant-form-item {
display: flex;
margin-right: 0;
margin-bottom: 24px;
> .ant-form-item-label {
width: auto;
padding-right: 8px;
line-height: 32px;
}
.ant-form-item-control {
line-height: 32px;
}
}
.ant-form-item-control-wrapper {
flex: 1;
}
}
.submitButtons {
display: block;
margin-bottom: 24px;
white-space: nowrap;
}
}
@media screen and (max-width: @screen-lg) {
.tableListForm :global(.ant-form-item) {
margin-right: 24px;
}
}
@media screen and (max-width: @screen-md) {
.tableListForm :global(.ant-form-item) {
margin-right: 8px;
}
}
.textOverflow() {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
word-break: break-all;
}
.textOverflowMulti(@line: 3, @bg: #fff) {
position: relative;
max-height: @line * 1.5em;
margin-right: -1em;
padding-right: 1em;
overflow: hidden;
line-height: 1.5em;
text-align: justify;
&::before {
position: absolute;
right: 14px;
bottom: 0;
padding: 0 1px;
background: @bg;
content: '...';
}
&::after {
position: absolute;
right: 14px;
width: 1em;
height: 1em;
margin-top: 0.2em;
background: white;
content: '';
}
}
// mixins for clearfix
// ------------------------
.clearfix() {
zoom: 1;
&::before,
&::after {
display: table;
content: ' ';
}
&::after {
clear: both;
height: 0;
font-size: 0;
visibility: hidden;
}
}
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