2024-08-18 15:46:20 +08:00
|
|
|
import { useState, useEffect } from 'react';
|
2024-08-18 22:27:32 +08:00
|
|
|
import { Table, Button, Form, Input, Popconfirm, message, Card, Modal, Transfer, Spin } from 'antd';
|
2024-08-18 16:48:09 +08:00
|
|
|
import { getRouteListAPI } from '@/api/Route';
|
2024-08-18 20:31:33 +08:00
|
|
|
import { getRoleListAPI, addRoleDataAPI, editRoleDataAPI, delRoleDataAPI, getRouteListAPI as getRoleRouteListAPI, bindingRouteAPI } from '@/api/Role';
|
2024-08-18 15:46:20 +08:00
|
|
|
import { Role } from '@/types/app/role';
|
|
|
|
|
import Title from '@/components/Title';
|
|
|
|
|
import { ColumnsType } from 'antd/es/table';
|
2024-08-18 16:48:09 +08:00
|
|
|
import "./index.scss"
|
2024-08-18 15:46:20 +08:00
|
|
|
|
|
|
|
|
const RolePage = () => {
|
|
|
|
|
const [loading, setLoading] = useState<boolean>(false);
|
2024-08-18 20:31:33 +08:00
|
|
|
const [bindingLoading, setBindingLoading] = useState<boolean>(false);
|
2024-11-22 14:40:15 +08:00
|
|
|
const [addLoading, setAddLoading] = useState(false)
|
|
|
|
|
|
2024-08-18 20:31:33 +08:00
|
|
|
const [id, setId] = useState(0)
|
2024-08-18 15:46:20 +08:00
|
|
|
const [role, setRole] = useState<Role>({} as Role);
|
2024-08-18 16:48:09 +08:00
|
|
|
const [roleList, setRoleList] = useState<Role[]>([]);
|
|
|
|
|
const [routeList, setRouteList] = useState<{ key: number, title: string }[]>([]);
|
2024-08-18 17:07:56 +08:00
|
|
|
// 当前角色的路由列表
|
|
|
|
|
const [targetKeys, setTargetKeys] = useState<number[]>([]);
|
2024-08-18 16:48:09 +08:00
|
|
|
|
|
|
|
|
// 角色权限框
|
|
|
|
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
2024-08-18 15:46:20 +08:00
|
|
|
|
|
|
|
|
const columns: ColumnsType<Role> = [
|
|
|
|
|
{ title: 'ID', dataIndex: 'id', key: 'id', align: 'center' },
|
2024-08-18 20:31:33 +08:00
|
|
|
{ title: '角色名称', dataIndex: 'name', key: 'name' },
|
|
|
|
|
{ title: '角色标识', dataIndex: 'mark', key: 'mark' },
|
2024-08-18 15:46:20 +08:00
|
|
|
{ title: '角色描述', dataIndex: 'description', key: 'description' },
|
|
|
|
|
{
|
|
|
|
|
title: '操作', key: 'action',
|
|
|
|
|
render: (text: string, record: Role) => (
|
|
|
|
|
<>
|
2024-08-18 20:31:33 +08:00
|
|
|
<Button type="primary" onClick={() => bindingRoute(record)}>权限</Button>
|
2024-08-18 16:48:09 +08:00
|
|
|
<Button onClick={() => editRoleData(record)} className="mx-2">修改</Button>
|
2024-08-18 15:46:20 +08:00
|
|
|
<Popconfirm title="警告" description="你确定要删除吗" okText="确定" cancelText="取消" onConfirm={() => delRoleData(record.id!)}>
|
2024-08-18 16:48:09 +08:00
|
|
|
<Button type="primary" danger>删除</Button>
|
2024-08-18 15:46:20 +08:00
|
|
|
</Popconfirm>
|
|
|
|
|
</>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
|
2024-08-18 17:07:56 +08:00
|
|
|
// 获取指定角色的路由列表
|
|
|
|
|
const getRoleRouteList = async (id: number) => {
|
|
|
|
|
const { data } = await getRoleRouteListAPI(id);
|
|
|
|
|
|
|
|
|
|
setTargetKeys(data.map(item => item.id) as number[])
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取路由列表
|
2024-08-18 16:48:09 +08:00
|
|
|
const getRouteList = async () => {
|
|
|
|
|
const { data } = await getRouteListAPI();
|
2024-12-15 21:25:21 +08:00
|
|
|
setRouteList(data.map(item => ({ key: item.id, title: item.description })) as { key: number, title: string }[]);
|
2024-08-18 16:48:09 +08:00
|
|
|
};
|
|
|
|
|
|
2024-08-18 17:07:56 +08:00
|
|
|
// 获取角色列表
|
2024-08-18 15:46:20 +08:00
|
|
|
const getRoleList = async () => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
const { data } = await getRoleListAPI();
|
2024-08-18 16:48:09 +08:00
|
|
|
setRoleList(data as Role[]);
|
2024-08-18 15:46:20 +08:00
|
|
|
setLoading(false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2024-08-18 17:07:56 +08:00
|
|
|
getRoleList()
|
2024-08-18 16:48:09 +08:00
|
|
|
getRouteList()
|
2024-08-18 15:46:20 +08:00
|
|
|
}, []);
|
|
|
|
|
|
2024-08-18 20:31:33 +08:00
|
|
|
|
2024-08-18 15:46:20 +08:00
|
|
|
const [form] = Form.useForm();
|
2024-08-18 20:31:33 +08:00
|
|
|
|
|
|
|
|
const bindingRoute = (record: Role) => {
|
|
|
|
|
setIsModalOpen(true)
|
|
|
|
|
getRoleRouteList(record.id)
|
|
|
|
|
setId(record.id)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-18 15:46:20 +08:00
|
|
|
const editRoleData = (record: Role) => {
|
|
|
|
|
setRole(record);
|
|
|
|
|
form.setFieldsValue(record);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const delRoleData = async (id: number) => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
await delRoleDataAPI(id);
|
|
|
|
|
message.success('🎉 删除角色成功');
|
|
|
|
|
getRoleList();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onSubmit = async () => {
|
|
|
|
|
setLoading(true);
|
2024-11-22 14:40:15 +08:00
|
|
|
setAddLoading(true)
|
|
|
|
|
|
2024-08-18 15:46:20 +08:00
|
|
|
form.validateFields().then(async (values: Role) => {
|
|
|
|
|
if (role.id) {
|
|
|
|
|
await editRoleDataAPI({ ...role, ...values });
|
|
|
|
|
message.success('🎉 编辑角色成功');
|
|
|
|
|
} else {
|
|
|
|
|
await addRoleDataAPI(values);
|
|
|
|
|
message.success('🎉 新增角色成功');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getRoleList();
|
|
|
|
|
form.resetFields();
|
|
|
|
|
form.setFieldsValue({ name: '', description: '' })
|
|
|
|
|
setRole({} as Role);
|
|
|
|
|
});
|
2024-11-22 14:40:15 +08:00
|
|
|
|
|
|
|
|
setAddLoading(false)
|
2024-08-18 15:46:20 +08:00
|
|
|
};
|
|
|
|
|
|
2024-08-18 17:07:56 +08:00
|
|
|
const onChange: any = (list: number[]) => {
|
|
|
|
|
setTargetKeys(list);
|
2024-08-18 16:48:09 +08:00
|
|
|
};
|
|
|
|
|
|
2024-08-18 20:31:33 +08:00
|
|
|
// 绑定路由
|
|
|
|
|
const onBindingRouteSubmit = async () => {
|
|
|
|
|
setBindingLoading(true);
|
|
|
|
|
await bindingRouteAPI(id, targetKeys)
|
|
|
|
|
setBindingLoading(false)
|
|
|
|
|
|
|
|
|
|
message.success('🎉 绑定成功');
|
|
|
|
|
setIsModalOpen(false)
|
2024-08-18 22:55:30 +08:00
|
|
|
|
|
|
|
|
// 刷新页面
|
|
|
|
|
window.location.reload()
|
2024-08-18 20:31:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 让n改变 触发Transfer重新渲染
|
|
|
|
|
const [n, setN] = useState(0)
|
|
|
|
|
|
2024-08-18 15:46:20 +08:00
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<Title value="角色管理" />
|
|
|
|
|
|
2025-01-10 21:24:20 +08:00
|
|
|
<div className='flex md:justify-between flex-col md:flex-row mx-auto mt-2 min-h-[calc(100vh-180px)]'>
|
|
|
|
|
<Card className="w-full md:w-[40%] h-94">
|
2024-08-18 15:46:20 +08:00
|
|
|
<Form
|
|
|
|
|
form={form}
|
|
|
|
|
layout="vertical"
|
|
|
|
|
initialValues={role}
|
|
|
|
|
onFinish={onSubmit}
|
|
|
|
|
size='large'
|
|
|
|
|
|
|
|
|
|
>
|
2024-08-18 20:31:33 +08:00
|
|
|
<Form.Item label="角色名称" name="name" rules={[{ required: true, message: '角色名称不能为空' }]}>
|
|
|
|
|
<Input placeholder="请输入角色名称" />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Form.Item label="角色标识" name="mark" rules={[{ required: true, message: '角色标识不能为空' }]}>
|
2024-08-18 16:48:09 +08:00
|
|
|
<Input placeholder="请输入角色标识" />
|
2024-08-18 15:46:20 +08:00
|
|
|
</Form.Item>
|
|
|
|
|
|
2024-08-18 20:31:33 +08:00
|
|
|
<Form.Item label="角色描述" name="description" rules={[{ required: true, message: '角色描述不能为空' }]}>
|
2024-08-18 15:46:20 +08:00
|
|
|
<Input placeholder="请输入角色描述" />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Form.Item>
|
2024-11-22 14:40:15 +08:00
|
|
|
<Button type="primary" htmlType="submit" loading={addLoading} className="w-full">{role.id ? '编辑角色' : '新增角色'}</Button>
|
2024-08-18 15:46:20 +08:00
|
|
|
</Form.Item>
|
|
|
|
|
</Form>
|
|
|
|
|
</Card>
|
|
|
|
|
|
2024-11-10 18:57:50 +08:00
|
|
|
<Card className="w-full md:w-[59%] mt-2 md:mt-0 [&>.ant-card-body]:!p-0">
|
2024-08-18 15:46:20 +08:00
|
|
|
<Table
|
|
|
|
|
rowKey="id"
|
2024-08-18 16:48:09 +08:00
|
|
|
dataSource={roleList}
|
2024-08-18 15:46:20 +08:00
|
|
|
columns={columns}
|
|
|
|
|
scroll={{ x: 'max-content' }}
|
|
|
|
|
pagination={{
|
|
|
|
|
position: ['bottomCenter'],
|
|
|
|
|
pageSize: 8
|
|
|
|
|
}}
|
|
|
|
|
loading={loading}
|
|
|
|
|
/>
|
|
|
|
|
</Card>
|
|
|
|
|
</div>
|
2024-08-18 16:48:09 +08:00
|
|
|
|
2024-08-18 20:31:33 +08:00
|
|
|
<Modal title="角色权限" open={isModalOpen} onCancel={() => [setIsModalOpen(false), setN(n + 1)]} footer={null} className='RolePageModal'>
|
2024-08-18 16:48:09 +08:00
|
|
|
<div className='flex justify-center py-6'>
|
2024-08-18 20:31:33 +08:00
|
|
|
<Spin spinning={bindingLoading}>
|
|
|
|
|
<Transfer
|
|
|
|
|
key={n}
|
|
|
|
|
dataSource={routeList}
|
|
|
|
|
targetKeys={targetKeys}
|
|
|
|
|
titles={['权限列表', '当前权限']}
|
|
|
|
|
render={(item) => item.title}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
showSelectAll={false}
|
|
|
|
|
/>
|
|
|
|
|
</Spin>
|
2024-08-18 16:48:09 +08:00
|
|
|
</div>
|
|
|
|
|
|
2024-11-22 14:40:15 +08:00
|
|
|
<Button type='primary' className='w-full mt-2' loading={bindingLoading} onClick={onBindingRouteSubmit}>保存</Button>
|
2024-08-18 16:48:09 +08:00
|
|
|
</Modal>
|
2024-08-18 15:46:20 +08:00
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default RolePage;
|