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