新增系统管理页面1

main
yupeng 1 month ago
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…
Cancel
Save