新增系统管理页面1
parent
07f0d15e4d
commit
eefeab35e8
@ -0,0 +1,15 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Outlet } from '@umijs/max';
|
||||||
|
import './SystemContentList.less';
|
||||||
|
|
||||||
|
const SystemContentList = () => {
|
||||||
|
return (
|
||||||
|
<div className="systemContentContainer">
|
||||||
|
<div className="systemContentMain">
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SystemContentList;
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
.systemContentContainer {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.systemContentMain {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
@ -0,0 +1,408 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
DeleteOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
SearchOutlined,
|
||||||
|
RedoOutlined,
|
||||||
|
DownOutlined,
|
||||||
|
ExclamationCircleFilled,
|
||||||
|
UpOutlined,
|
||||||
|
InfoCircleFilled,
|
||||||
|
QuestionCircleFilled,
|
||||||
|
DownloadOutlined
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import {connect, history} from '@umijs/max';
|
||||||
|
import {Button, Card, Divider, Dropdown, message, Modal, Popconfirm, Space, Switch, Tag, Row, Col, Tree} from 'antd';
|
||||||
|
import StandardTable from '@/components/StandardTable';
|
||||||
|
|
||||||
|
import { MyIcon } from "@/components/Icon"
|
||||||
|
import style from "@/global.less";
|
||||||
|
import styles from './SystemMenuList.less';
|
||||||
|
import datadictionary from "@/utils/dataDictionary";
|
||||||
|
import {formatDate} from "@/utils/formatUtils";
|
||||||
|
import { formatDictText, checkButtonAuthority } from "@/utils/globalCommon";
|
||||||
|
|
||||||
|
const { confirm } = Modal;
|
||||||
|
|
||||||
|
// 菜单类型
|
||||||
|
const menu_type = datadictionary.menu_type || [];
|
||||||
|
const menu_status = datadictionary.menu_status || [];
|
||||||
|
const menu_level = datadictionary.menu_level || [];
|
||||||
|
|
||||||
|
const mockData = {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: '效率管理',
|
||||||
|
code: 'hrefficiency',
|
||||||
|
type: '1',
|
||||||
|
level: '1',
|
||||||
|
status: '1',
|
||||||
|
path: '/topnavbar00/hrefficiency',
|
||||||
|
component: '',
|
||||||
|
icon: 'setting',
|
||||||
|
createTime: '2023-01-01 10:00:00',
|
||||||
|
createUser: 'admin',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: '工时仪表盘',
|
||||||
|
code: 'timesheet',
|
||||||
|
type: '2',
|
||||||
|
level: '2',
|
||||||
|
status: '1',
|
||||||
|
path: '/topnavbar00/hrefficiency/timesheet',
|
||||||
|
component: './hrefficiency_timesheet/TimeSheetList',
|
||||||
|
icon: 'dashboard',
|
||||||
|
createTime: '2023-01-01 10:05:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
name: '员工仪表盘',
|
||||||
|
code: 'staffsheet',
|
||||||
|
type: '2',
|
||||||
|
level: '2',
|
||||||
|
status: '1',
|
||||||
|
path: '/topnavbar00/hrefficiency/staffsheet',
|
||||||
|
component: './hrefficiency_staffsheet/StaffSheetList',
|
||||||
|
icon: 'user',
|
||||||
|
createTime: '2023-01-01 10:10:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
name: '系统管理',
|
||||||
|
code: 'system',
|
||||||
|
type: '1',
|
||||||
|
level: '1',
|
||||||
|
status: '1',
|
||||||
|
path: '/topnavbar00/hrefficiency/system',
|
||||||
|
component: './nav_system_content/SystemContentList',
|
||||||
|
icon: 'control',
|
||||||
|
createTime: '2023-01-02 14:30:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
total: 2,
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@connect(({ systemMenu }) => ({
|
||||||
|
systemMenu
|
||||||
|
}))
|
||||||
|
export default class SystemMenuList extends React.Component {
|
||||||
|
state = {
|
||||||
|
selectedRows: [],
|
||||||
|
advancedFormVisible: false,
|
||||||
|
filterData: {},
|
||||||
|
pagination: {
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
},
|
||||||
|
tableData: mockData.list,
|
||||||
|
treeData: [],
|
||||||
|
expandedKeys: []
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.getMenuList();
|
||||||
|
this.buildTreeData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取菜单列表
|
||||||
|
getMenuList = () => {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
const { pagination, filterData } = this.state;
|
||||||
|
|
||||||
|
try {
|
||||||
|
dispatch({
|
||||||
|
type: 'systemMenu/fetchList',
|
||||||
|
payload: {
|
||||||
|
pageNum: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
...filterData
|
||||||
|
},
|
||||||
|
callback: (res) => {
|
||||||
|
this.setState({
|
||||||
|
tableData: res?.list || mockData.list,
|
||||||
|
pagination: {
|
||||||
|
...pagination,
|
||||||
|
total: res?.total || mockData.pagination.total
|
||||||
|
}
|
||||||
|
}, () => {
|
||||||
|
this.buildTreeData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取菜单列表失败:', error);
|
||||||
|
this.setState({
|
||||||
|
tableData: mockData.list,
|
||||||
|
pagination: mockData.pagination
|
||||||
|
}, () => {
|
||||||
|
this.buildTreeData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 构建树数据
|
||||||
|
buildTreeData = () => {
|
||||||
|
const { tableData } = this.state;
|
||||||
|
const treeData = this.transformToTree(tableData);
|
||||||
|
this.setState({ treeData });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 转换为树结构
|
||||||
|
transformToTree = (data) => {
|
||||||
|
return data.map(item => {
|
||||||
|
const node = {
|
||||||
|
title: item.name,
|
||||||
|
key: item.id,
|
||||||
|
dataRef: item
|
||||||
|
};
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
node.children = this.transformToTree(item.children);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格选择变化
|
||||||
|
handleSelectChange = (selectedRowKeys, selectedRows) => {
|
||||||
|
this.setState({ selectedRows });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页变化
|
||||||
|
handleTableChange = (pagination) => {
|
||||||
|
this.setState({
|
||||||
|
pagination: {
|
||||||
|
...this.state.pagination,
|
||||||
|
current: pagination.current
|
||||||
|
}
|
||||||
|
}, () => {
|
||||||
|
this.getMenuList();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增菜单
|
||||||
|
handleAdd = () => {
|
||||||
|
// 新增逻辑
|
||||||
|
message.success('新增菜单功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑菜单
|
||||||
|
handleEdit = (record) => {
|
||||||
|
// 编辑逻辑
|
||||||
|
message.success('编辑菜单功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除菜单
|
||||||
|
handleDelete = (record) => {
|
||||||
|
confirm({
|
||||||
|
title: '确定要删除这个菜单吗?',
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 删除逻辑
|
||||||
|
message.success('删除菜单成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 批量删除
|
||||||
|
handleBatchDelete = () => {
|
||||||
|
const { selectedRows } = this.state;
|
||||||
|
if (selectedRows.length === 0) {
|
||||||
|
message.warning('请选择要删除的菜单');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confirm({
|
||||||
|
title: `确定要删除选中的${selectedRows.length}个菜单吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 批量删除逻辑
|
||||||
|
message.success('批量删除菜单成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启用/禁用菜单
|
||||||
|
handleStatusChange = (record) => {
|
||||||
|
const newStatus = record.status === '1' ? '0' : '1';
|
||||||
|
confirm({
|
||||||
|
title: `确定要${newStatus === '1' ? '启用' : '禁用'}这个菜单吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 状态变更逻辑
|
||||||
|
message.success(`${newStatus === '1' ? '启用' : '禁用'}菜单成功`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 展开/折叠树节点
|
||||||
|
handleExpand = (expandedKeys) => {
|
||||||
|
this.setState({ expandedKeys });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击树节点
|
||||||
|
handleTreeSelect = (selectedKeys, info) => {
|
||||||
|
// 树节点选择逻辑
|
||||||
|
console.log('Selected', selectedKeys, info);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { selectedRows, tableData, pagination, treeData, expandedKeys } = this.state;
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '菜单名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '菜单编码',
|
||||||
|
dataIndex: 'code',
|
||||||
|
key: 'code',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '菜单类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
key: 'type',
|
||||||
|
render: text => formatDictText(menu_type, text)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '菜单级别',
|
||||||
|
dataIndex: 'level',
|
||||||
|
key: 'level',
|
||||||
|
render: text => formatDictText(menu_level, text)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '路径',
|
||||||
|
dataIndex: 'path',
|
||||||
|
key: 'path',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
render: text => (
|
||||||
|
<Tag color={text === '1' ? 'green' : 'red'}>
|
||||||
|
{text === '1' ? '启用' : '禁用'}
|
||||||
|
</Tag>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
key: 'createUser',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 160,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space size="middle">
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={() => this.handleEdit(record)}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
onClick={() => this.handleDelete(record)}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
<Switch
|
||||||
|
checked={record.status === '1'}
|
||||||
|
onChange={() => this.handleStatusChange(record)}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={style.contentWrapper}>
|
||||||
|
<Card className={style.contentCard}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<div className={styles.headerLeft}>
|
||||||
|
<h2 className={styles.title}>菜单配置</h2>
|
||||||
|
</div>
|
||||||
|
<div className={styles.headerRight}>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={this.handleAdd}
|
||||||
|
>
|
||||||
|
新增菜单
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
danger
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
onClick={this.handleBatchDelete}
|
||||||
|
disabled={selectedRows.length === 0}
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<div className={styles.menuContent}>
|
||||||
|
<div className={styles.menuTreeSection}>
|
||||||
|
<h3 className={styles.sectionTitle}>菜单树</h3>
|
||||||
|
<div className={styles.menuTree}>
|
||||||
|
<Tree
|
||||||
|
treeData={treeData}
|
||||||
|
expandedKeys={expandedKeys}
|
||||||
|
onExpand={this.handleExpand}
|
||||||
|
onSelect={this.handleTreeSelect}
|
||||||
|
className={styles.tree}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<StandardTable
|
||||||
|
rowKey="id"
|
||||||
|
selectedRows={selectedRows}
|
||||||
|
data={{
|
||||||
|
list: tableData,
|
||||||
|
pagination
|
||||||
|
}}
|
||||||
|
columns={columns}
|
||||||
|
onSelectRow={this.handleSelectChange}
|
||||||
|
onChange={this.handleTableChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,112 @@
|
|||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerLeft {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerRight {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterSection {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterRow {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterItem {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionButtons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batchAction {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContainer {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formHeader {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formTitle {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContent {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formFooter {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formButton {
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuContent {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuTreeSection {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionTitle {
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuTree {
|
||||||
|
border: 1px solid #e8e8e8;
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree .ant-tree-node-selected {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree .ant-tree-node-selected:hover {
|
||||||
|
background-color: #bae7ff;
|
||||||
|
}
|
||||||
@ -0,0 +1,314 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
DeleteOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
SearchOutlined,
|
||||||
|
RedoOutlined,
|
||||||
|
DownOutlined,
|
||||||
|
ExclamationCircleFilled,
|
||||||
|
UpOutlined,
|
||||||
|
InfoCircleFilled,
|
||||||
|
QuestionCircleFilled,
|
||||||
|
DownloadOutlined
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import {connect, history} from '@umijs/max';
|
||||||
|
import {Button, Card, Divider, Dropdown, message, Modal, Popconfirm, Space, Switch, Tag, Row, Col} from 'antd';
|
||||||
|
import StandardTable from '@/components/StandardTable';
|
||||||
|
|
||||||
|
import { MyIcon } from "@/components/Icon"
|
||||||
|
import style from "@/global.less";
|
||||||
|
import styles from './SystemOrganizationList.less';
|
||||||
|
import datadictionary from "@/utils/dataDictionary";
|
||||||
|
import {formatDate} from "@/utils/formatUtils";
|
||||||
|
import { formatDictText, checkButtonAuthority } from "@/utils/globalCommon";
|
||||||
|
|
||||||
|
const { confirm } = Modal;
|
||||||
|
|
||||||
|
// 组织类型
|
||||||
|
const organization_type = datadictionary.organization_type || [];
|
||||||
|
const organization_status = datadictionary.organization_status || [];
|
||||||
|
|
||||||
|
const mockData = {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: '总部',
|
||||||
|
code: 'HQ',
|
||||||
|
type: '1',
|
||||||
|
parentId: '0',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-01 10:00:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: '研发部',
|
||||||
|
code: 'R&D',
|
||||||
|
type: '2',
|
||||||
|
parentId: '1',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-02 14:30:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
name: '市场部',
|
||||||
|
code: 'MKT',
|
||||||
|
type: '2',
|
||||||
|
parentId: '1',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-03 09:15:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
total: 3,
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@connect(({ systemOrganization }) => ({
|
||||||
|
systemOrganization
|
||||||
|
}))
|
||||||
|
export default class SystemOrganizationList extends React.Component {
|
||||||
|
state = {
|
||||||
|
selectedRows: [],
|
||||||
|
advancedFormVisible: false,
|
||||||
|
filterData: {},
|
||||||
|
pagination: {
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
},
|
||||||
|
tableData: mockData.list
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.getOrganizationList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取组织列表
|
||||||
|
getOrganizationList = () => {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
const { pagination, filterData } = this.state;
|
||||||
|
|
||||||
|
try {
|
||||||
|
dispatch({
|
||||||
|
type: 'systemOrganization/fetchList',
|
||||||
|
payload: {
|
||||||
|
pageNum: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
...filterData
|
||||||
|
},
|
||||||
|
callback: (res) => {
|
||||||
|
this.setState({
|
||||||
|
tableData: res?.list || mockData.list,
|
||||||
|
pagination: {
|
||||||
|
...pagination,
|
||||||
|
total: res?.total || mockData.pagination.total
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取组织列表失败:', error);
|
||||||
|
this.setState({
|
||||||
|
tableData: mockData.list,
|
||||||
|
pagination: mockData.pagination
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格选择变化
|
||||||
|
handleSelectChange = (selectedRowKeys, selectedRows) => {
|
||||||
|
this.setState({ selectedRows });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页变化
|
||||||
|
handleTableChange = (pagination) => {
|
||||||
|
this.setState({
|
||||||
|
pagination: {
|
||||||
|
...this.state.pagination,
|
||||||
|
current: pagination.current
|
||||||
|
}
|
||||||
|
}, () => {
|
||||||
|
this.getOrganizationList();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增组织
|
||||||
|
handleAdd = () => {
|
||||||
|
// 新增逻辑
|
||||||
|
message.success('新增组织功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑组织
|
||||||
|
handleEdit = (record) => {
|
||||||
|
// 编辑逻辑
|
||||||
|
message.success('编辑组织功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除组织
|
||||||
|
handleDelete = (record) => {
|
||||||
|
confirm({
|
||||||
|
title: '确定要删除这个组织吗?',
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 删除逻辑
|
||||||
|
message.success('删除组织成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 批量删除
|
||||||
|
handleBatchDelete = () => {
|
||||||
|
const { selectedRows } = this.state;
|
||||||
|
if (selectedRows.length === 0) {
|
||||||
|
message.warning('请选择要删除的组织');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confirm({
|
||||||
|
title: `确定要删除选中的${selectedRows.length}个组织吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 批量删除逻辑
|
||||||
|
message.success('批量删除组织成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启用/禁用组织
|
||||||
|
handleStatusChange = (record) => {
|
||||||
|
const newStatus = record.status === '1' ? '0' : '1';
|
||||||
|
confirm({
|
||||||
|
title: `确定要${newStatus === '1' ? '启用' : '禁用'}这个组织吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 状态变更逻辑
|
||||||
|
message.success(`${newStatus === '1' ? '启用' : '禁用'}组织成功`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { selectedRows, tableData, pagination } = this.state;
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '组织名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '组织编码',
|
||||||
|
dataIndex: 'code',
|
||||||
|
key: 'code',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '组织类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
key: 'type',
|
||||||
|
render: text => formatDictText(organization_type, text)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
render: text => (
|
||||||
|
<Tag color={text === '1' ? 'green' : 'red'}>
|
||||||
|
{text === '1' ? '启用' : '禁用'}
|
||||||
|
</Tag>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
key: 'createUser',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 160,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space size="middle">
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={() => this.handleEdit(record)}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
onClick={() => this.handleDelete(record)}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
<Switch
|
||||||
|
checked={record.status === '1'}
|
||||||
|
onChange={() => this.handleStatusChange(record)}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={style.contentWrapper}>
|
||||||
|
<Card className={style.contentCard}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<div className={styles.headerLeft}>
|
||||||
|
<h2 className={styles.title}>组织管理</h2>
|
||||||
|
</div>
|
||||||
|
<div className={styles.headerRight}>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={this.handleAdd}
|
||||||
|
>
|
||||||
|
新增组织
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
danger
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
onClick={this.handleBatchDelete}
|
||||||
|
disabled={selectedRows.length === 0}
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<StandardTable
|
||||||
|
rowKey="id"
|
||||||
|
selectedRows={selectedRows}
|
||||||
|
data={{
|
||||||
|
list: tableData,
|
||||||
|
pagination
|
||||||
|
}}
|
||||||
|
columns={columns}
|
||||||
|
onSelectRow={this.handleSelectChange}
|
||||||
|
onChange={this.handleTableChange}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerLeft {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerRight {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterSection {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterRow {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterItem {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionButtons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batchAction {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContainer {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formHeader {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formTitle {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContent {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formFooter {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formButton {
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
@ -0,0 +1,333 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
DeleteOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
SearchOutlined,
|
||||||
|
RedoOutlined,
|
||||||
|
DownOutlined,
|
||||||
|
ExclamationCircleFilled,
|
||||||
|
UpOutlined,
|
||||||
|
InfoCircleFilled,
|
||||||
|
QuestionCircleFilled,
|
||||||
|
DownloadOutlined
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import {connect, history} from '@umijs/max';
|
||||||
|
import {Button, Card, Divider, Dropdown, message, Modal, Popconfirm, Space, Switch, Tag, Row, Col} from 'antd';
|
||||||
|
import StandardTable from '@/components/StandardTable';
|
||||||
|
|
||||||
|
import { MyIcon } from "@/components/Icon"
|
||||||
|
import style from "@/global.less";
|
||||||
|
import styles from './SystemRoleList.less';
|
||||||
|
import datadictionary from "@/utils/dataDictionary";
|
||||||
|
import {formatDate} from "@/utils/formatUtils";
|
||||||
|
import { formatDictText, checkButtonAuthority } from "@/utils/globalCommon";
|
||||||
|
|
||||||
|
const { confirm } = Modal;
|
||||||
|
|
||||||
|
// 角色类型
|
||||||
|
const role_type = datadictionary.role_type || [];
|
||||||
|
const role_status = datadictionary.role_status || [];
|
||||||
|
|
||||||
|
const mockData = {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: '超级管理员',
|
||||||
|
code: 'SUPER_ADMIN',
|
||||||
|
type: '1',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-01 10:00:00',
|
||||||
|
createUser: 'admin',
|
||||||
|
remark: '系统最高权限角色'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: '部门管理员',
|
||||||
|
code: 'DEPT_ADMIN',
|
||||||
|
type: '2',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-02 14:30:00',
|
||||||
|
createUser: 'admin',
|
||||||
|
remark: '部门级管理权限'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
name: '普通用户',
|
||||||
|
code: 'NORMAL_USER',
|
||||||
|
type: '3',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-03 09:15:00',
|
||||||
|
createUser: 'admin',
|
||||||
|
remark: '基础功能访问权限'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
total: 3,
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@connect(({ systemRole }) => ({
|
||||||
|
systemRole
|
||||||
|
}))
|
||||||
|
export default class SystemRoleList extends React.Component {
|
||||||
|
state = {
|
||||||
|
selectedRows: [],
|
||||||
|
advancedFormVisible: false,
|
||||||
|
filterData: {},
|
||||||
|
pagination: {
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
},
|
||||||
|
tableData: mockData.list
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.getRoleList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取角色列表
|
||||||
|
getRoleList = () => {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
const { pagination, filterData } = this.state;
|
||||||
|
|
||||||
|
try {
|
||||||
|
dispatch({
|
||||||
|
type: 'systemRole/fetchList',
|
||||||
|
payload: {
|
||||||
|
pageNum: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
...filterData
|
||||||
|
},
|
||||||
|
callback: (res) => {
|
||||||
|
this.setState({
|
||||||
|
tableData: res?.list || mockData.list,
|
||||||
|
pagination: {
|
||||||
|
...pagination,
|
||||||
|
total: res?.total || mockData.pagination.total
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取角色列表失败:', error);
|
||||||
|
this.setState({
|
||||||
|
tableData: mockData.list,
|
||||||
|
pagination: mockData.pagination
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格选择变化
|
||||||
|
handleSelectChange = (selectedRowKeys, selectedRows) => {
|
||||||
|
this.setState({ selectedRows });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页变化
|
||||||
|
handleTableChange = (pagination) => {
|
||||||
|
this.setState({
|
||||||
|
pagination: {
|
||||||
|
...this.state.pagination,
|
||||||
|
current: pagination.current
|
||||||
|
}
|
||||||
|
}, () => {
|
||||||
|
this.getRoleList();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增角色
|
||||||
|
handleAdd = () => {
|
||||||
|
// 新增逻辑
|
||||||
|
message.success('新增角色功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑角色
|
||||||
|
handleEdit = (record) => {
|
||||||
|
// 编辑逻辑
|
||||||
|
message.success('编辑角色功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 角色授权
|
||||||
|
handleAuth = (record) => {
|
||||||
|
// 授权逻辑
|
||||||
|
message.success('角色授权功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除角色
|
||||||
|
handleDelete = (record) => {
|
||||||
|
confirm({
|
||||||
|
title: '确定要删除这个角色吗?',
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 删除逻辑
|
||||||
|
message.success('删除角色成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 批量删除
|
||||||
|
handleBatchDelete = () => {
|
||||||
|
const { selectedRows } = this.state;
|
||||||
|
if (selectedRows.length === 0) {
|
||||||
|
message.warning('请选择要删除的角色');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confirm({
|
||||||
|
title: `确定要删除选中的${selectedRows.length}个角色吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 批量删除逻辑
|
||||||
|
message.success('批量删除角色成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启用/禁用角色
|
||||||
|
handleStatusChange = (record) => {
|
||||||
|
const newStatus = record.status === '1' ? '0' : '1';
|
||||||
|
confirm({
|
||||||
|
title: `确定要${newStatus === '1' ? '启用' : '禁用'}这个角色吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 状态变更逻辑
|
||||||
|
message.success(`${newStatus === '1' ? '启用' : '禁用'}角色成功`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { selectedRows, tableData, pagination } = this.state;
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '角色名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '角色编码',
|
||||||
|
dataIndex: 'code',
|
||||||
|
key: 'code',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '角色类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
key: 'type',
|
||||||
|
render: text => formatDictText(role_type, text)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
render: text => (
|
||||||
|
<Tag color={text === '1' ? 'green' : 'red'}>
|
||||||
|
{text === '1' ? '启用' : '禁用'}
|
||||||
|
</Tag>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
key: 'createUser',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'remark',
|
||||||
|
key: 'remark',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 200,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space size="middle">
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={() => this.handleEdit(record)}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
onClick={() => this.handleAuth(record)}
|
||||||
|
>
|
||||||
|
授权
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
onClick={() => this.handleDelete(record)}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
<Switch
|
||||||
|
checked={record.status === '1'}
|
||||||
|
onChange={() => this.handleStatusChange(record)}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={style.contentWrapper}>
|
||||||
|
<Card className={style.contentCard}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<div className={styles.headerLeft}>
|
||||||
|
<h2 className={styles.title}>角色配置</h2>
|
||||||
|
</div>
|
||||||
|
<div className={styles.headerRight}>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={this.handleAdd}
|
||||||
|
>
|
||||||
|
新增角色
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
danger
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
onClick={this.handleBatchDelete}
|
||||||
|
disabled={selectedRows.length === 0}
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<StandardTable
|
||||||
|
rowKey="id"
|
||||||
|
selectedRows={selectedRows}
|
||||||
|
data={{
|
||||||
|
list: tableData,
|
||||||
|
pagination
|
||||||
|
}}
|
||||||
|
columns={columns}
|
||||||
|
onSelectRow={this.handleSelectChange}
|
||||||
|
onChange={this.handleTableChange}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerLeft {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerRight {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterSection {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterRow {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterItem {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionButtons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batchAction {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContainer {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formHeader {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formTitle {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContent {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formFooter {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formButton {
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
@ -0,0 +1,402 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
DeleteOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
SearchOutlined,
|
||||||
|
RedoOutlined,
|
||||||
|
DownOutlined,
|
||||||
|
ExclamationCircleFilled,
|
||||||
|
UpOutlined,
|
||||||
|
InfoCircleFilled,
|
||||||
|
QuestionCircleFilled,
|
||||||
|
DownloadOutlined
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import {connect, history} from '@umijs/max';
|
||||||
|
import {Button, Card, Divider, Dropdown, message, Modal, Popconfirm, Space, Switch, Tag, Row, Col, Tree} from 'antd';
|
||||||
|
import StandardTable from '@/components/StandardTable';
|
||||||
|
|
||||||
|
import { MyIcon } from "@/components/Icon"
|
||||||
|
import style from "@/global.less";
|
||||||
|
import styles from './SystemMenuList.less';
|
||||||
|
import datadictionary from "@/utils/dataDictionary";
|
||||||
|
import {formatDate} from "@/utils/formatUtils";
|
||||||
|
import { formatDictText, checkButtonAuthority } from "@/utils/globalCommon";
|
||||||
|
|
||||||
|
const { confirm } = Modal;
|
||||||
|
|
||||||
|
// 菜单类型
|
||||||
|
const menu_type = datadictionary.menu_type || [];
|
||||||
|
const menu_status = datadictionary.menu_status || [];
|
||||||
|
const menu_level = datadictionary.menu_level || [];
|
||||||
|
|
||||||
|
const mockData = {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: '效率管理',
|
||||||
|
code: 'hrefficiency',
|
||||||
|
type: '1',
|
||||||
|
level: '1',
|
||||||
|
status: '1',
|
||||||
|
path: '/topnavbar00/hrefficiency',
|
||||||
|
component: '',
|
||||||
|
icon: 'setting',
|
||||||
|
createTime: '2023-01-01 10:00:00',
|
||||||
|
createUser: 'admin',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: '工时仪表盘',
|
||||||
|
code: 'timesheet',
|
||||||
|
type: '2',
|
||||||
|
level: '2',
|
||||||
|
status: '1',
|
||||||
|
path: '/topnavbar00/hrefficiency/timesheet',
|
||||||
|
component: './hrefficiency_timesheet/TimeSheetList',
|
||||||
|
icon: 'dashboard',
|
||||||
|
createTime: '2023-01-01 10:05:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
name: '员工仪表盘',
|
||||||
|
code: 'staffsheet',
|
||||||
|
type: '2',
|
||||||
|
level: '2',
|
||||||
|
status: '1',
|
||||||
|
path: '/topnavbar00/hrefficiency/staffsheet',
|
||||||
|
component: './hrefficiency_staffsheet/StaffSheetList',
|
||||||
|
icon: 'user',
|
||||||
|
createTime: '2023-01-01 10:10:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
name: '系统管理',
|
||||||
|
code: 'system',
|
||||||
|
type: '1',
|
||||||
|
level: '1',
|
||||||
|
status: '1',
|
||||||
|
path: '/topnavbar00/hrefficiency/system',
|
||||||
|
component: './nav_system_content/SystemContentList',
|
||||||
|
icon: 'control',
|
||||||
|
createTime: '2023-01-02 14:30:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
total: 2,
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@connect(({ systemMenu, loading }) => ({
|
||||||
|
systemMenu,
|
||||||
|
loading: loading.models.systemMenu
|
||||||
|
}))
|
||||||
|
export default class SystemMenuList extends React.Component {
|
||||||
|
state = {
|
||||||
|
selectedRows: [],
|
||||||
|
loading: false,
|
||||||
|
advancedFormVisible: false,
|
||||||
|
filterData: {},
|
||||||
|
pagination: {
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
},
|
||||||
|
tableData: mockData.list,
|
||||||
|
treeData: [],
|
||||||
|
expandedKeys: []
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.getMenuList();
|
||||||
|
this.buildTreeData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取菜单列表
|
||||||
|
getMenuList = () => {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
const { pagination, filterData } = this.state;
|
||||||
|
this.setState({ loading: true });
|
||||||
|
dispatch({
|
||||||
|
type: 'systemMenu/fetchList',
|
||||||
|
payload: {
|
||||||
|
pageNum: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
...filterData
|
||||||
|
},
|
||||||
|
callback: (res) => {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
tableData: res?.list || [],
|
||||||
|
pagination: {
|
||||||
|
...pagination,
|
||||||
|
total: res?.total || 0
|
||||||
|
}
|
||||||
|
}, () => {
|
||||||
|
this.buildTreeData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 构建树数据
|
||||||
|
buildTreeData = () => {
|
||||||
|
const { tableData } = this.state;
|
||||||
|
const treeData = this.transformToTree(tableData);
|
||||||
|
this.setState({ treeData });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 转换为树结构
|
||||||
|
transformToTree = (data) => {
|
||||||
|
return data.map(item => {
|
||||||
|
const node = {
|
||||||
|
title: item.name,
|
||||||
|
key: item.id,
|
||||||
|
dataRef: item
|
||||||
|
};
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
node.children = this.transformToTree(item.children);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格选择变化
|
||||||
|
handleSelectChange = (selectedRowKeys, selectedRows) => {
|
||||||
|
this.setState({ selectedRows });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页变化
|
||||||
|
handleTableChange = (pagination) => {
|
||||||
|
this.setState({
|
||||||
|
pagination: {
|
||||||
|
...this.state.pagination,
|
||||||
|
current: pagination.current
|
||||||
|
}
|
||||||
|
}, () => {
|
||||||
|
this.getMenuList();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增菜单
|
||||||
|
handleAdd = () => {
|
||||||
|
// 新增逻辑
|
||||||
|
message.success('新增菜单功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑菜单
|
||||||
|
handleEdit = (record) => {
|
||||||
|
// 编辑逻辑
|
||||||
|
message.success('编辑菜单功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除菜单
|
||||||
|
handleDelete = (record) => {
|
||||||
|
confirm({
|
||||||
|
title: '确定要删除这个菜单吗?',
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 删除逻辑
|
||||||
|
message.success('删除菜单成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 批量删除
|
||||||
|
handleBatchDelete = () => {
|
||||||
|
const { selectedRows } = this.state;
|
||||||
|
if (selectedRows.length === 0) {
|
||||||
|
message.warning('请选择要删除的菜单');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confirm({
|
||||||
|
title: `确定要删除选中的${selectedRows.length}个菜单吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 批量删除逻辑
|
||||||
|
message.success('批量删除菜单成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启用/禁用菜单
|
||||||
|
handleStatusChange = (record) => {
|
||||||
|
const newStatus = record.status === '1' ? '0' : '1';
|
||||||
|
confirm({
|
||||||
|
title: `确定要${newStatus === '1' ? '启用' : '禁用'}这个菜单吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 状态变更逻辑
|
||||||
|
message.success(`${newStatus === '1' ? '启用' : '禁用'}菜单成功`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 展开/折叠树节点
|
||||||
|
handleExpand = (expandedKeys) => {
|
||||||
|
this.setState({ expandedKeys });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击树节点
|
||||||
|
handleTreeSelect = (selectedKeys, info) => {
|
||||||
|
// 树节点选择逻辑
|
||||||
|
console.log('Selected', selectedKeys, info);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { selectedRows, loading, tableData, pagination, treeData, expandedKeys } = this.state;
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '菜单名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '菜单编码',
|
||||||
|
dataIndex: 'code',
|
||||||
|
key: 'code',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '菜单类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
key: 'type',
|
||||||
|
render: text => formatDictText(menu_type, text)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '菜单级别',
|
||||||
|
dataIndex: 'level',
|
||||||
|
key: 'level',
|
||||||
|
render: text => formatDictText(menu_level, text)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '路径',
|
||||||
|
dataIndex: 'path',
|
||||||
|
key: 'path',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
render: text => (
|
||||||
|
<Tag color={text === '1' ? 'green' : 'red'}>
|
||||||
|
{text === '1' ? '启用' : '禁用'}
|
||||||
|
</Tag>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
key: 'createUser',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 160,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space size="middle">
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={() => this.handleEdit(record)}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
onClick={() => this.handleDelete(record)}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
<Switch
|
||||||
|
checked={record.status === '1'}
|
||||||
|
onChange={() => this.handleStatusChange(record)}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={style.contentWrapper}>
|
||||||
|
<Card className={style.contentCard}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<div className={styles.headerLeft}>
|
||||||
|
<h2 className={styles.title}>菜单配置</h2>
|
||||||
|
</div>
|
||||||
|
<div className={styles.headerRight}>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={this.handleAdd}
|
||||||
|
>
|
||||||
|
新增菜单
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
danger
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
onClick={this.handleBatchDelete}
|
||||||
|
disabled={selectedRows.length === 0}
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<div className={styles.menuContent}>
|
||||||
|
<div className={styles.menuTreeSection}>
|
||||||
|
<h3 className={styles.sectionTitle}>菜单树</h3>
|
||||||
|
<div className={styles.menuTree}>
|
||||||
|
<Tree
|
||||||
|
treeData={treeData}
|
||||||
|
expandedKeys={expandedKeys}
|
||||||
|
onExpand={this.handleExpand}
|
||||||
|
onSelect={this.handleTreeSelect}
|
||||||
|
className={styles.tree}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<StandardTable
|
||||||
|
rowKey="id"
|
||||||
|
selectedRows={selectedRows}
|
||||||
|
loading={loading}
|
||||||
|
data={{
|
||||||
|
list: tableData,
|
||||||
|
pagination
|
||||||
|
}}
|
||||||
|
columns={columns}
|
||||||
|
onSelectRow={this.handleSelectChange}
|
||||||
|
onChange={this.handleTableChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerLeft {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerRight {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterSection {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterRow {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterItem {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionButtons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batchAction {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContainer {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formHeader {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formTitle {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContent {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formFooter {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formButton {
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuContent {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuTreeSection {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionTitle {
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuTree {
|
||||||
|
background-color: #fafafa;
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #e8e8e8;
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree .ant-tree-node-selected {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree .ant-tree-node-selected:hover {
|
||||||
|
background-color: #bae7ff;
|
||||||
|
}
|
||||||
@ -0,0 +1,310 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
DeleteOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
SearchOutlined,
|
||||||
|
RedoOutlined,
|
||||||
|
DownOutlined,
|
||||||
|
ExclamationCircleFilled,
|
||||||
|
UpOutlined,
|
||||||
|
InfoCircleFilled,
|
||||||
|
QuestionCircleFilled,
|
||||||
|
DownloadOutlined
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import {connect, history} from '@umijs/max';
|
||||||
|
import {Button, Card, Divider, Dropdown, message, Modal, Popconfirm, Space, Switch, Tag, Row, Col} from 'antd';
|
||||||
|
import StandardTable from '@/components/StandardTable';
|
||||||
|
|
||||||
|
import { MyIcon } from "@/components/Icon"
|
||||||
|
import style from "@/global.less";
|
||||||
|
import styles from './SystemOrganizationList.less';
|
||||||
|
import datadictionary from "@/utils/dataDictionary";
|
||||||
|
import {formatDate} from "@/utils/formatUtils";
|
||||||
|
import { formatDictText, checkButtonAuthority } from "@/utils/globalCommon";
|
||||||
|
|
||||||
|
const { confirm } = Modal;
|
||||||
|
|
||||||
|
// 组织类型
|
||||||
|
const organization_type = datadictionary.organization_type || [];
|
||||||
|
const organization_status = datadictionary.organization_status || [];
|
||||||
|
|
||||||
|
const mockData = {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: '总部',
|
||||||
|
code: 'HQ',
|
||||||
|
type: '1',
|
||||||
|
parentId: '0',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-01 10:00:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: '研发部',
|
||||||
|
code: 'R&D',
|
||||||
|
type: '2',
|
||||||
|
parentId: '1',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-02 14:30:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
name: '市场部',
|
||||||
|
code: 'MKT',
|
||||||
|
type: '2',
|
||||||
|
parentId: '1',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-03 09:15:00',
|
||||||
|
createUser: 'admin'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
total: 3,
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@connect(({ systemOrganization, loading }) => ({
|
||||||
|
systemOrganization,
|
||||||
|
loading: loading.models.systemOrganization
|
||||||
|
}))
|
||||||
|
export default class SystemOrganizationList extends React.Component {
|
||||||
|
state = {
|
||||||
|
selectedRows: [],
|
||||||
|
loading: false,
|
||||||
|
advancedFormVisible: false,
|
||||||
|
filterData: {},
|
||||||
|
pagination: {
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
},
|
||||||
|
tableData: mockData.list
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.getOrganizationList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取组织列表
|
||||||
|
getOrganizationList = () => {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
const { pagination, filterData } = this.state;
|
||||||
|
this.setState({ loading: true });
|
||||||
|
dispatch({
|
||||||
|
type: 'systemOrganization/fetchList',
|
||||||
|
payload: {
|
||||||
|
pageNum: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
...filterData
|
||||||
|
},
|
||||||
|
callback: (res) => {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
tableData: res?.list || [],
|
||||||
|
pagination: {
|
||||||
|
...pagination,
|
||||||
|
total: res?.total || 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格选择变化
|
||||||
|
handleSelectChange = (selectedRowKeys, selectedRows) => {
|
||||||
|
this.setState({ selectedRows });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页变化
|
||||||
|
handleTableChange = (pagination) => {
|
||||||
|
this.setState({
|
||||||
|
pagination: {
|
||||||
|
...this.state.pagination,
|
||||||
|
current: pagination.current
|
||||||
|
}
|
||||||
|
}, () => {
|
||||||
|
this.getOrganizationList();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增组织
|
||||||
|
handleAdd = () => {
|
||||||
|
// 新增逻辑
|
||||||
|
message.success('新增组织功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑组织
|
||||||
|
handleEdit = (record) => {
|
||||||
|
// 编辑逻辑
|
||||||
|
message.success('编辑组织功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除组织
|
||||||
|
handleDelete = (record) => {
|
||||||
|
confirm({
|
||||||
|
title: '确定要删除这个组织吗?',
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 删除逻辑
|
||||||
|
message.success('删除组织成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 批量删除
|
||||||
|
handleBatchDelete = () => {
|
||||||
|
const { selectedRows } = this.state;
|
||||||
|
if (selectedRows.length === 0) {
|
||||||
|
message.warning('请选择要删除的组织');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confirm({
|
||||||
|
title: `确定要删除选中的${selectedRows.length}个组织吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 批量删除逻辑
|
||||||
|
message.success('批量删除组织成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启用/禁用组织
|
||||||
|
handleStatusChange = (record) => {
|
||||||
|
const newStatus = record.status === '1' ? '0' : '1';
|
||||||
|
confirm({
|
||||||
|
title: `确定要${newStatus === '1' ? '启用' : '禁用'}这个组织吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 状态变更逻辑
|
||||||
|
message.success(`${newStatus === '1' ? '启用' : '禁用'}组织成功`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { selectedRows, loading, tableData, pagination } = this.state;
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '组织名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '组织编码',
|
||||||
|
dataIndex: 'code',
|
||||||
|
key: 'code',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '组织类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
key: 'type',
|
||||||
|
render: text => formatDictText(organization_type, text)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
render: text => (
|
||||||
|
<Tag color={text === '1' ? 'green' : 'red'}>
|
||||||
|
{text === '1' ? '启用' : '禁用'}
|
||||||
|
</Tag>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
key: 'createUser',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 160,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space size="middle">
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={() => this.handleEdit(record)}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
onClick={() => this.handleDelete(record)}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
<Switch
|
||||||
|
checked={record.status === '1'}
|
||||||
|
onChange={() => this.handleStatusChange(record)}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={style.contentWrapper}>
|
||||||
|
<Card className={style.contentCard}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<div className={styles.headerLeft}>
|
||||||
|
<h2 className={styles.title}>组织管理</h2>
|
||||||
|
</div>
|
||||||
|
<div className={styles.headerRight}>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={this.handleAdd}
|
||||||
|
>
|
||||||
|
新增组织
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
danger
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
onClick={this.handleBatchDelete}
|
||||||
|
disabled={selectedRows.length === 0}
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<StandardTable
|
||||||
|
rowKey="id"
|
||||||
|
selectedRows={selectedRows}
|
||||||
|
loading={loading}
|
||||||
|
data={{
|
||||||
|
list: tableData,
|
||||||
|
pagination
|
||||||
|
}}
|
||||||
|
columns={columns}
|
||||||
|
onSelectRow={this.handleSelectChange}
|
||||||
|
onChange={this.handleTableChange}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerLeft {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerRight {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterSection {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterRow {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterItem {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionButtons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batchAction {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContainer {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formHeader {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formTitle {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContent {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formFooter {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formButton {
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
@ -0,0 +1,329 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
DeleteOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
SearchOutlined,
|
||||||
|
RedoOutlined,
|
||||||
|
DownOutlined,
|
||||||
|
ExclamationCircleFilled,
|
||||||
|
UpOutlined,
|
||||||
|
InfoCircleFilled,
|
||||||
|
QuestionCircleFilled,
|
||||||
|
DownloadOutlined
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import {connect, history} from '@umijs/max';
|
||||||
|
import {Button, Card, Divider, Dropdown, message, Modal, Popconfirm, Space, Switch, Tag, Row, Col} from 'antd';
|
||||||
|
import StandardTable from '@/components/StandardTable';
|
||||||
|
|
||||||
|
import { MyIcon } from "@/components/Icon"
|
||||||
|
import style from "@/global.less";
|
||||||
|
import styles from './SystemRoleList.less';
|
||||||
|
import datadictionary from "@/utils/dataDictionary";
|
||||||
|
import {formatDate} from "@/utils/formatUtils";
|
||||||
|
import { formatDictText, checkButtonAuthority } from "@/utils/globalCommon";
|
||||||
|
|
||||||
|
const { confirm } = Modal;
|
||||||
|
|
||||||
|
// 角色类型
|
||||||
|
const role_type = datadictionary.role_type || [];
|
||||||
|
const role_status = datadictionary.role_status || [];
|
||||||
|
|
||||||
|
const mockData = {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: '超级管理员',
|
||||||
|
code: 'SUPER_ADMIN',
|
||||||
|
type: '1',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-01 10:00:00',
|
||||||
|
createUser: 'admin',
|
||||||
|
remark: '系统最高权限角色'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: '部门管理员',
|
||||||
|
code: 'DEPT_ADMIN',
|
||||||
|
type: '2',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-02 14:30:00',
|
||||||
|
createUser: 'admin',
|
||||||
|
remark: '部门级管理权限'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
name: '普通用户',
|
||||||
|
code: 'NORMAL_USER',
|
||||||
|
type: '3',
|
||||||
|
status: '1',
|
||||||
|
createTime: '2023-01-03 09:15:00',
|
||||||
|
createUser: 'admin',
|
||||||
|
remark: '基础功能访问权限'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
total: 3,
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@connect(({ systemRole, loading }) => ({
|
||||||
|
systemRole,
|
||||||
|
loading: loading.models.systemRole
|
||||||
|
}))
|
||||||
|
export default class SystemRoleList extends React.Component {
|
||||||
|
state = {
|
||||||
|
selectedRows: [],
|
||||||
|
loading: false,
|
||||||
|
advancedFormVisible: false,
|
||||||
|
filterData: {},
|
||||||
|
pagination: {
|
||||||
|
pageSize: 10,
|
||||||
|
current: 1
|
||||||
|
},
|
||||||
|
tableData: mockData.list
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.getRoleList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取角色列表
|
||||||
|
getRoleList = () => {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
const { pagination, filterData } = this.state;
|
||||||
|
this.setState({ loading: true });
|
||||||
|
dispatch({
|
||||||
|
type: 'systemRole/fetchList',
|
||||||
|
payload: {
|
||||||
|
pageNum: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
...filterData
|
||||||
|
},
|
||||||
|
callback: (res) => {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
tableData: res?.list || [],
|
||||||
|
pagination: {
|
||||||
|
...pagination,
|
||||||
|
total: res?.total || 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格选择变化
|
||||||
|
handleSelectChange = (selectedRowKeys, selectedRows) => {
|
||||||
|
this.setState({ selectedRows });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页变化
|
||||||
|
handleTableChange = (pagination) => {
|
||||||
|
this.setState({
|
||||||
|
pagination: {
|
||||||
|
...this.state.pagination,
|
||||||
|
current: pagination.current
|
||||||
|
}
|
||||||
|
}, () => {
|
||||||
|
this.getRoleList();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增角色
|
||||||
|
handleAdd = () => {
|
||||||
|
// 新增逻辑
|
||||||
|
message.success('新增角色功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑角色
|
||||||
|
handleEdit = (record) => {
|
||||||
|
// 编辑逻辑
|
||||||
|
message.success('编辑角色功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 角色授权
|
||||||
|
handleAuth = (record) => {
|
||||||
|
// 授权逻辑
|
||||||
|
message.success('角色授权功能');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除角色
|
||||||
|
handleDelete = (record) => {
|
||||||
|
confirm({
|
||||||
|
title: '确定要删除这个角色吗?',
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 删除逻辑
|
||||||
|
message.success('删除角色成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 批量删除
|
||||||
|
handleBatchDelete = () => {
|
||||||
|
const { selectedRows } = this.state;
|
||||||
|
if (selectedRows.length === 0) {
|
||||||
|
message.warning('请选择要删除的角色');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confirm({
|
||||||
|
title: `确定要删除选中的${selectedRows.length}个角色吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 批量删除逻辑
|
||||||
|
message.success('批量删除角色成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启用/禁用角色
|
||||||
|
handleStatusChange = (record) => {
|
||||||
|
const newStatus = record.status === '1' ? '0' : '1';
|
||||||
|
confirm({
|
||||||
|
title: `确定要${newStatus === '1' ? '启用' : '禁用'}这个角色吗?`,
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
onOk: () => {
|
||||||
|
// 状态变更逻辑
|
||||||
|
message.success(`${newStatus === '1' ? '启用' : '禁用'}角色成功`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { selectedRows, loading, tableData, pagination } = this.state;
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '角色名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '角色编码',
|
||||||
|
dataIndex: 'code',
|
||||||
|
key: 'code',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '角色类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
key: 'type',
|
||||||
|
render: text => formatDictText(role_type, text)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
render: text => (
|
||||||
|
<Tag color={text === '1' ? 'green' : 'red'}>
|
||||||
|
{text === '1' ? '启用' : '禁用'}
|
||||||
|
</Tag>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建人',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
key: 'createUser',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'remark',
|
||||||
|
key: 'remark',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 200,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space size="middle">
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={() => this.handleEdit(record)}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
onClick={() => this.handleAuth(record)}
|
||||||
|
>
|
||||||
|
授权
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
onClick={() => this.handleDelete(record)}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
<Switch
|
||||||
|
checked={record.status === '1'}
|
||||||
|
onChange={() => this.handleStatusChange(record)}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={style.contentWrapper}>
|
||||||
|
<Card className={style.contentCard}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<div className={styles.headerLeft}>
|
||||||
|
<h2 className={styles.title}>角色配置</h2>
|
||||||
|
</div>
|
||||||
|
<div className={styles.headerRight}>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={this.handleAdd}
|
||||||
|
>
|
||||||
|
新增角色
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
danger
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
onClick={this.handleBatchDelete}
|
||||||
|
disabled={selectedRows.length === 0}
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<StandardTable
|
||||||
|
rowKey="id"
|
||||||
|
selectedRows={selectedRows}
|
||||||
|
loading={loading}
|
||||||
|
data={{
|
||||||
|
list: tableData,
|
||||||
|
pagination
|
||||||
|
}}
|
||||||
|
columns={columns}
|
||||||
|
onSelectRow={this.handleSelectChange}
|
||||||
|
onChange={this.handleTableChange}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerLeft {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerRight {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterSection {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterRow {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterItem {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionButtons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batchAction {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContainer {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formHeader {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formTitle {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.formContent {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formFooter {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formButton {
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue