可正常启用
This commit is contained in:
parent
74cb4a3255
commit
3a6c6ad9ab
@ -88,10 +88,10 @@ const DepartmentPage: React.FC = () => {
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 60,
|
||||
title: '部门名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 250,
|
||||
fixed: 'left' as FixedType,
|
||||
sorter: true
|
||||
},
|
||||
@ -99,26 +99,9 @@ const DepartmentPage: React.FC = () => {
|
||||
title: '部门编码',
|
||||
dataIndex: 'code',
|
||||
key: 'code',
|
||||
width: 100,
|
||||
width: 120,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '部门名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 150,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '上级部门',
|
||||
dataIndex: 'parentId',
|
||||
key: 'parentId',
|
||||
width: 150,
|
||||
render: (parentId: number) => {
|
||||
const parent = departments.find(dept => dept.id === parentId);
|
||||
return parent?.name || '-';
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '部门描述',
|
||||
dataIndex: 'description',
|
||||
@ -189,12 +172,14 @@ const DepartmentPage: React.FC = () => {
|
||||
<Table
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
dataSource={departments}
|
||||
dataSource={departmentTree}
|
||||
rowKey="id"
|
||||
scroll={{x: 1500}}
|
||||
pagination={pagination}
|
||||
scroll={{x: 1200}}
|
||||
pagination={false}
|
||||
size="middle"
|
||||
bordered
|
||||
defaultExpandAllRows
|
||||
indentSize={24}
|
||||
/>
|
||||
|
||||
<Modal
|
||||
|
||||
@ -5,7 +5,7 @@ import type { TablePaginationConfig } from 'antd/es/table';
|
||||
import type { FilterValue, SorterResult } from 'antd/es/table/interface';
|
||||
import { getMenuTree } from './service';
|
||||
import type { MenuResponse } from './types';
|
||||
import { MenuTypeEnum, MenuTypeNames } from './types';
|
||||
import { MenuTypeEnum } from './types';
|
||||
import IconSelect from '@/components/IconSelect';
|
||||
import { useTableData } from '@/hooks/useTableData';
|
||||
import * as AntdIcons from '@ant-design/icons';
|
||||
@ -13,7 +13,6 @@ import * as AntdIcons from '@ant-design/icons';
|
||||
const MenuPage: React.FC = () => {
|
||||
const {
|
||||
list: menus,
|
||||
pagination,
|
||||
loading,
|
||||
loadData: fetchMenus,
|
||||
handleCreate,
|
||||
@ -24,16 +23,21 @@ const MenuPage: React.FC = () => {
|
||||
baseUrl: '/api/v1/menu'
|
||||
},
|
||||
defaultParams: {
|
||||
sortField: 'createTime',
|
||||
sortOrder: 'descend'
|
||||
sortField: 'sort',
|
||||
sortOrder: 'asc'
|
||||
}
|
||||
});
|
||||
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [iconSelectVisible, setIconSelectVisible] = useState(false);
|
||||
const [editingMenu, setEditingMenu] = useState<MenuResponse | null>(null);
|
||||
const [menuTree, setMenuTree] = useState<MenuResponse[]>([]);
|
||||
const [iconSelectVisible, setIconSelectVisible] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
getMenuTree().then(menus => setMenuTree(menus));
|
||||
}, []);
|
||||
|
||||
const handleAdd = () => {
|
||||
setEditingMenu(null);
|
||||
form.resetFields();
|
||||
@ -135,84 +139,102 @@ const MenuPage: React.FC = () => {
|
||||
return Icon ? <Icon /> : null;
|
||||
};
|
||||
|
||||
const treeData = buildMenuTree(menus).map(menu => ({
|
||||
key: menu.id,
|
||||
title: (
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%' }}>
|
||||
<Space>
|
||||
{menu.type === MenuTypeEnum.DIRECTORY ? <FolderOutlined /> :
|
||||
menu.type === MenuTypeEnum.MENU ? <MenuOutlined /> :
|
||||
<ToolOutlined />}
|
||||
<span>{menu.name}</span>
|
||||
{menu.icon && getIcon(menu.icon)}
|
||||
</Space>
|
||||
<Space size={8}>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
icon={<EditOutlined />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleEdit(menu);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleDelete(menu.id);
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
),
|
||||
children: menu.children?.map(child => ({
|
||||
key: child.id,
|
||||
title: (
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%' }}>
|
||||
<Space>
|
||||
{child.type === MenuTypeEnum.DIRECTORY ? <FolderOutlined /> :
|
||||
child.type === MenuTypeEnum.MENU ? <MenuOutlined /> :
|
||||
<ToolOutlined />}
|
||||
<span>{child.name}</span>
|
||||
{child.icon && getIcon(child.icon)}
|
||||
</Space>
|
||||
<Space size={8}>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
icon={<EditOutlined />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleEdit(child);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleDelete(child.id);
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
const columns = [
|
||||
{
|
||||
title: '菜单名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 250,
|
||||
fixed: 'left' as FixedType,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '图标',
|
||||
dataIndex: 'icon',
|
||||
key: 'icon',
|
||||
width: 80,
|
||||
render: (icon: string) => getIcon(icon)
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
width: 100,
|
||||
render: (type: MenuTypeEnum) => {
|
||||
const typeMap = {
|
||||
[MenuTypeEnum.DIRECTORY]: '目录',
|
||||
[MenuTypeEnum.MENU]: '菜单',
|
||||
[MenuTypeEnum.BUTTON]: '按钮'
|
||||
};
|
||||
return typeMap[type];
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '路由地址',
|
||||
dataIndex: 'path',
|
||||
key: 'path',
|
||||
width: 200,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '组件路径',
|
||||
dataIndex: 'component',
|
||||
key: 'component',
|
||||
width: 200,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '权限标识',
|
||||
dataIndex: 'permission',
|
||||
key: 'permission',
|
||||
width: 150,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'sort',
|
||||
key: 'sort',
|
||||
width: 80,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'enabled',
|
||||
key: 'enabled',
|
||||
width: 80,
|
||||
render: (enabled: boolean) => (
|
||||
<Switch checked={enabled} disabled size="small"/>
|
||||
)
|
||||
}))
|
||||
}));
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 160,
|
||||
fixed: 'right' as FixedType,
|
||||
render: (_: any, record: MenuResponse) => (
|
||||
<Space size={0}>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
icon={<EditOutlined/>}
|
||||
onClick={() => handleEdit(record)}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
danger
|
||||
icon={<DeleteOutlined/>}
|
||||
onClick={() => handleDelete(record.id)}
|
||||
disabled={record.children?.length > 0}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{padding: '24px'}}>
|
||||
@ -222,10 +244,17 @@ const MenuPage: React.FC = () => {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Tree
|
||||
showLine={{ showLeafIcon: false }}
|
||||
defaultExpandAll
|
||||
treeData={treeData}
|
||||
<Table
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
dataSource={menuTree}
|
||||
rowKey="id"
|
||||
scroll={{x: 1500}}
|
||||
pagination={false}
|
||||
size="middle"
|
||||
bordered
|
||||
defaultExpandAllRows
|
||||
indentSize={24}
|
||||
/>
|
||||
|
||||
<Modal
|
||||
@ -320,7 +349,7 @@ const MenuPage: React.FC = () => {
|
||||
name="sort"
|
||||
label="显示排序"
|
||||
tooltip="值越大排序越靠后,默认为当前最大值+10"
|
||||
rules={[{ required: true, message: '请输入显示排序' }]}
|
||||
rules={[{ required: true, message: '请输显示排序' }]}
|
||||
>
|
||||
<InputNumber
|
||||
style={{ width: '100%' }}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user