|
|
@@ -1,8 +1,9 @@
|
|
|
import React, { useState, useEffect } from 'react';
|
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
|
-import { Card, Table, Button, Modal, Form, Input, Space, Tag, message, Tree, Spin } from 'antd';
|
|
|
+import { Card, Table, Button, Modal, Form, Input, Space, Tag, message } from 'antd';
|
|
|
import { EditOutlined, DeleteOutlined, PlusOutlined, KeyOutlined } from '@ant-design/icons';
|
|
|
-import { roleClient, permissionClient, rolePermissionClient } from '@/client/api';
|
|
|
+import { roleClient, rolePermissionClient } from '@/client/api';
|
|
|
+import PermissionConfigModal from '@/client/admin/components/PermissionConfigModal';
|
|
|
import type { InferResponseType, InferRequestType } from 'hono/client';
|
|
|
import dayjs from 'dayjs';
|
|
|
|
|
|
@@ -13,9 +14,6 @@ type RoleItem = RoleListResponse['data'][0];
|
|
|
type CreateRoleRequest = InferRequestType<typeof roleClient.$post>['json'];
|
|
|
type UpdateRoleRequest = InferRequestType<typeof roleClient[':id']['$put']>['json'];
|
|
|
|
|
|
-type PermissionListResponse = InferResponseType<typeof permissionClient.$get, 200>;
|
|
|
-type PermissionItem = PermissionListResponse['data'][0];
|
|
|
-
|
|
|
// React Query hooks
|
|
|
const useRoles = (params?: { page?: number; pageSize?: number; keyword?: string }) => {
|
|
|
return useQuery({
|
|
|
@@ -34,34 +32,6 @@ const useRoles = (params?: { page?: number; pageSize?: number; keyword?: string
|
|
|
});
|
|
|
};
|
|
|
|
|
|
-const usePermissions = () => {
|
|
|
- return useQuery({
|
|
|
- queryKey: ['permissions'],
|
|
|
- queryFn: async () => {
|
|
|
- const response = await permissionClient.$get({ query: {} });
|
|
|
- if (!response.ok) throw new Error('获取权限列表失败');
|
|
|
- const data = await response.json();
|
|
|
- return data.data;
|
|
|
- },
|
|
|
- });
|
|
|
-};
|
|
|
-
|
|
|
-const useRolePermissions = (roleId: number | null) => {
|
|
|
- return useQuery({
|
|
|
- queryKey: ['role-permissions', roleId],
|
|
|
- queryFn: async () => {
|
|
|
- if (!roleId) return [];
|
|
|
- const response = await rolePermissionClient.$get({
|
|
|
- query: { filters: JSON.stringify({ roleId }) }
|
|
|
- });
|
|
|
- if (!response.ok) throw new Error('获取角色权限失败');
|
|
|
- const data = await response.json();
|
|
|
- return data.data.map((item: any) => item.permissionId);
|
|
|
- },
|
|
|
- enabled: !!roleId,
|
|
|
- });
|
|
|
-};
|
|
|
-
|
|
|
const useCreateRole = () => {
|
|
|
const queryClient = useQueryClient();
|
|
|
return useMutation({
|
|
|
@@ -123,57 +93,6 @@ const useDeleteRole = () => {
|
|
|
});
|
|
|
};
|
|
|
|
|
|
-const useUpdateRolePermissions = () => {
|
|
|
- const queryClient = useQueryClient();
|
|
|
- return useMutation({
|
|
|
- mutationFn: async ({ roleId, permissionIds }: { roleId: number; permissionIds: number[] }) => {
|
|
|
- const permissions = permissionIds.map(permissionId => ({
|
|
|
- permissionId,
|
|
|
- dataScopeType: 'COMPANY' as const,
|
|
|
- customDepartments: [] as number[]
|
|
|
- }));
|
|
|
-
|
|
|
- const response = await rolePermissionClient.batch.$post({
|
|
|
- json: { roleId, permissions }
|
|
|
- });
|
|
|
- if (!response.ok) throw new Error('更新角色权限失败');
|
|
|
- return response.json();
|
|
|
- },
|
|
|
- onSuccess: () => {
|
|
|
- message.success('角色权限更新成功');
|
|
|
- },
|
|
|
- onError: (error: Error) => {
|
|
|
- message.error(error.message);
|
|
|
- },
|
|
|
- });
|
|
|
-};
|
|
|
-
|
|
|
-const Roles: React.FC = () => {
|
|
|
-const queryClient = useQueryClient();
|
|
|
-const [modalVisible, setModalVisible] = useState(false);
|
|
|
-const [permissionModalVisible, setPermissionModalVisible] = useState(false);
|
|
|
-const [editingRole, setEditingRole] = useState<RoleItem | null>(null);
|
|
|
-const [selectedRole, setSelectedRole] = useState<RoleItem | null>(null);
|
|
|
-const [form] = Form.useForm();
|
|
|
-const [selectedPermissionIds, setSelectedPermissionIds] = useState<number[]>([]);
|
|
|
-const [searchKeyword, setSearchKeyword] = useState('');
|
|
|
-const [pagination, setPagination] = useState({
|
|
|
- current: 1,
|
|
|
- pageSize: 10,
|
|
|
- total: 0
|
|
|
-});
|
|
|
-
|
|
|
-// React Query hooks
|
|
|
-const { data: rolesData, isLoading: rolesLoading } = useRoles({
|
|
|
- page: pagination.current,
|
|
|
- pageSize: pagination.pageSize,
|
|
|
- keyword: searchKeyword
|
|
|
-});
|
|
|
-const roles = rolesData?.data || [];
|
|
|
-const { data: permissions = [], isLoading: permissionsLoading } = usePermissions();
|
|
|
-const { data: rolePermissions = [], isLoading: rolePermissionsLoading } = useRolePermissions(selectedRole?.id ?? null);
|
|
|
-
|
|
|
-// 单独查询每个角色的权限数量
|
|
|
const useRolePermissionCount = (roleId: number) => {
|
|
|
return useQuery({
|
|
|
queryKey: ['role-permission-count', roleId],
|
|
|
@@ -189,23 +108,44 @@ const useRolePermissionCount = (roleId: number) => {
|
|
|
});
|
|
|
};
|
|
|
|
|
|
-// 更新分页信息
|
|
|
-React.useEffect(() => {
|
|
|
- if (rolesData?.pagination) {
|
|
|
- setPagination(prev => ({
|
|
|
- ...prev,
|
|
|
- current: rolesData.pagination.current,
|
|
|
- pageSize: rolesData.pagination.pageSize,
|
|
|
- total: rolesData.pagination.total
|
|
|
- }));
|
|
|
- }
|
|
|
-}, [rolesData?.pagination]);
|
|
|
+const Roles: React.FC = () => {
|
|
|
+ const queryClient = useQueryClient();
|
|
|
+ const [modalVisible, setModalVisible] = useState(false);
|
|
|
+ const [permissionModalVisible, setPermissionModalVisible] = useState(false);
|
|
|
+ const [editingRole, setEditingRole] = useState<RoleItem | null>(null);
|
|
|
+ const [selectedRole, setSelectedRole] = useState<RoleItem | null>(null);
|
|
|
+ const [form] = Form.useForm();
|
|
|
+ const [searchKeyword, setSearchKeyword] = useState('');
|
|
|
+ const [pagination, setPagination] = useState({
|
|
|
+ current: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ total: 0
|
|
|
+ });
|
|
|
+
|
|
|
+ // React Query hooks
|
|
|
+ const { data: rolesData, isLoading: rolesLoading } = useRoles({
|
|
|
+ page: pagination.current,
|
|
|
+ pageSize: pagination.pageSize,
|
|
|
+ keyword: searchKeyword
|
|
|
+ });
|
|
|
+ const roles = rolesData?.data || [];
|
|
|
+
|
|
|
+ // 更新分页信息
|
|
|
+ useEffect(() => {
|
|
|
+ if (rolesData?.pagination) {
|
|
|
+ setPagination(prev => ({
|
|
|
+ ...prev,
|
|
|
+ current: rolesData.pagination.current,
|
|
|
+ pageSize: rolesData.pagination.pageSize,
|
|
|
+ total: rolesData.pagination.total
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ }, [rolesData?.pagination]);
|
|
|
|
|
|
// Mutations
|
|
|
const createRoleMutation = useCreateRole();
|
|
|
const updateRoleMutation = useUpdateRole();
|
|
|
const deleteRoleMutation = useDeleteRole();
|
|
|
- const updateRolePermissionsMutation = useUpdateRolePermissions();
|
|
|
|
|
|
// 打开编辑模态框
|
|
|
const handleEdit = (record: RoleItem) => {
|
|
|
@@ -227,7 +167,6 @@ React.useEffect(() => {
|
|
|
// 打开权限配置模态框
|
|
|
const handlePermissionConfig = (role: RoleItem) => {
|
|
|
setSelectedRole(role);
|
|
|
- setSelectedPermissionIds(rolePermissions);
|
|
|
setPermissionModalVisible(true);
|
|
|
};
|
|
|
|
|
|
@@ -273,50 +212,6 @@ React.useEffect(() => {
|
|
|
setPagination(prev => ({ ...prev, current: 1 }));
|
|
|
};
|
|
|
|
|
|
- // 保存角色权限
|
|
|
- const handleSavePermissions = () => {
|
|
|
- if (!selectedRole) return;
|
|
|
-
|
|
|
- updateRolePermissionsMutation.mutate(
|
|
|
- { roleId: selectedRole.id, permissionIds: selectedPermissionIds },
|
|
|
- {
|
|
|
- onSuccess: () => {
|
|
|
- setPermissionModalVisible(false);
|
|
|
- queryClient.invalidateQueries({ queryKey: ['roles'] });
|
|
|
- }
|
|
|
- }
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
- // 权限数据按模块分组
|
|
|
- const permissionTreeData = React.useMemo(() => {
|
|
|
- const grouped: Record<string, PermissionItem[]> = {};
|
|
|
- permissions.forEach(permission => {
|
|
|
- const module = permission.module || '其他';
|
|
|
- if (!grouped[module]) {
|
|
|
- grouped[module] = [];
|
|
|
- }
|
|
|
- grouped[module].push(permission);
|
|
|
- });
|
|
|
-
|
|
|
- return Object.entries(grouped).map(([module, items]) => ({
|
|
|
- title: module,
|
|
|
- key: module,
|
|
|
- checkable: false,
|
|
|
- children: items.map(item => ({
|
|
|
- title: `${item.name} (${item.code})`,
|
|
|
- key: item.id.toString(),
|
|
|
- })),
|
|
|
- }));
|
|
|
- }, [permissions]);
|
|
|
-
|
|
|
- // 在权限模态框打开时更新选中状态
|
|
|
- useEffect(() => {
|
|
|
- if (permissionModalVisible && rolePermissions.length > 0) {
|
|
|
- setSelectedPermissionIds(rolePermissions);
|
|
|
- }
|
|
|
- }, [permissionModalVisible, rolePermissions]);
|
|
|
-
|
|
|
const columns = [
|
|
|
{
|
|
|
title: '角色名称',
|
|
|
@@ -401,7 +296,7 @@ React.useEffect(() => {
|
|
|
|
|
|
return (
|
|
|
<div className="p-6">
|
|
|
- <Spin spinning={rolesLoading || permissionsLoading}>
|
|
|
+ <Spin spinning={rolesLoading}>
|
|
|
<Card
|
|
|
title="角色管理"
|
|
|
extra={
|
|
|
@@ -493,34 +388,16 @@ React.useEffect(() => {
|
|
|
</Modal>
|
|
|
|
|
|
{/* 权限配置模态框 */}
|
|
|
- <Modal
|
|
|
- title={`配置权限 - ${selectedRole?.name}`}
|
|
|
- open={permissionModalVisible}
|
|
|
- onCancel={() => setPermissionModalVisible(false)}
|
|
|
- onOk={handleSavePermissions}
|
|
|
- okButtonProps={{ loading: updateRolePermissionsMutation.isPending }}
|
|
|
- width={800}
|
|
|
- destroyOnClose
|
|
|
- >
|
|
|
- <Spin spinning={rolePermissionsLoading}>
|
|
|
- <Tree
|
|
|
- checkable
|
|
|
- treeData={permissionTreeData}
|
|
|
- checkedKeys={selectedPermissionIds.map(String)}
|
|
|
- onCheck={(checkedKeys) => {
|
|
|
- const checked = checkedKeys as string[];
|
|
|
- setSelectedPermissionIds(checked.map(Number));
|
|
|
- }}
|
|
|
- height={400}
|
|
|
- titleRender={(node) => {
|
|
|
- if (node.children) {
|
|
|
- return <strong>{node.title}</strong>;
|
|
|
- }
|
|
|
- return <span>{node.title}</span>;
|
|
|
- }}
|
|
|
- />
|
|
|
- </Spin>
|
|
|
- </Modal>
|
|
|
+ <PermissionConfigModal
|
|
|
+ visible={permissionModalVisible}
|
|
|
+ roleId={selectedRole?.id || null}
|
|
|
+ roleName={selectedRole?.name}
|
|
|
+ onClose={() => setPermissionModalVisible(false)}
|
|
|
+ onSuccess={() => {
|
|
|
+ message.success('权限配置成功');
|
|
|
+ queryClient.invalidateQueries({ queryKey: ['roles'] });
|
|
|
+ }}
|
|
|
+ />
|
|
|
</div>
|
|
|
);
|
|
|
};
|