diff --git a/src/hooks/resource/useResource.js b/src/hooks/resource/useResource.js index af7f50a..f131734 100644 --- a/src/hooks/resource/useResource.js +++ b/src/hooks/resource/useResource.js @@ -77,6 +77,8 @@ export const useResources = (initialPagination, initialSorter, type) => { const deleteResource = async (id) => { try { const data= await resourceService.deleteResource(id, type); + console.log(data,data.length,'data'); + if(data?.length>0){ const newCurrent = resources.length === 1 && currentPagination.current > 1 diff --git a/src/pages/resource/role/index.jsx b/src/pages/resource/role/index.jsx index 90fbab8..db2608b 100644 --- a/src/pages/resource/role/index.jsx +++ b/src/pages/resource/role/index.jsx @@ -1,7 +1,585 @@ -import React from 'react' +import React, { useState, useEffect } from 'react'; +import { Card, App, Table, Button, Modal, Form, Select, message, Input, Divider } from 'antd'; +import { PlusOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'; +import { supabase } from '@/config/supabase'; + +const RoleHeader = ({ onAdd, onSearch }) => ( +
+ + +
+); + +export default function PermissionManagement() { + const [loading, setLoading] = useState(false); + const [permissions, setPermissions] = useState([]); + const [roles, setRoles] = useState([]); + const [resources, setResources] = useState([]); + const [modalVisible, setModalVisible] = useState(false); + const [modalType, setModalType] = useState('add'); + const [form] = Form.useForm(); + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, + }); + + const [sorter, setSorter] = useState({ + field: 'created_at', + order: 'descend', + }); + + const [roleModalVisible, setRoleModalVisible] = useState(false); + const [resourceModalVisible, setResourceModalVisible] = useState(false); + const [roleForm] = Form.useForm(); + const [resourceForm] = Form.useForm(); + + // 获取所有权限数据(包括关联数据) + const fetchPermissions = async (params = {}) => { + try { + setLoading(true); + let query = supabase + .from('permissions') + .select(` + *, + roles:role_id(*), + resources:resource_id(*) + `, { count: 'exact' }); + + // 添加搜索条件 + if (params.search) { + query = query.or(` + roles.name.ilike.%${params.search}%, + resources.resource_name.ilike.%${params.search}%, + resources.description.ilike.%${params.search}% + `); + } + + // 添加排序 + if (params.field && params.order) { + const ascending = params.order === 'ascend'; + query = query.order(params.field, { ascending }); + } else { + // 默认排序 + query = query.order('created_at', { ascending: false }); + } + + // 添加分页 + const from = (params.current - 1) * params.pageSize || 0; + const to = from + (params.pageSize || 10) - 1; + query = query.range(from, to); + + const { data, count, error } = await query; + + if (error) throw error; + + setPermissions(data || []); + setPagination(prev => ({ + ...prev, + total: count || 0, + current: params.current || prev.current, + pageSize: params.pageSize || prev.pageSize, + })); + } catch (error) { + message.error('获取权限数据失败'); + console.error(error); + } finally { + setLoading(false); + } + }; + + // 获取所有角色 + const fetchRoles = async () => { + try { + const { data, error } = await supabase + .from('roles') + .select('*') + .order('name'); + + if (error) throw error; + setRoles(data || []); + } catch (error) { + message.error('获取角色数据失败'); + console.error(error); + } + }; + + // 获取所有资源 + const fetchResources = async () => { + try { + const { data, error } = await supabase + .from('permission_resources') + .select('*') + .order('resource_name'); + + if (error) throw error; + setResources(data || []); + } catch (error) { + message.error('获取资源数据失败'); + console.error(error); + } + }; + + // 添加权限 + const handleAdd = async (values) => { + try { + const { error } = await supabase + .from('permissions') + .insert([{ + role_id: values.role_id, + resource_id: values.resource_id, + action: values.action + }]); + + if (error) throw error; + message.success('添加成功'); + fetchPermissions(pagination); + } catch (error) { + message.error('添加失败'); + throw error; + } + }; + + // 更新权限 + const handleUpdate = async (values) => { + try { + const { error } = await supabase + .from('permissions') + .update({ + role_id: values.role_id, + resource_id: values.resource_id, + action: values.action + }) + .eq('id', values.id); + + if (error) throw error; + message.success('更新成功'); + fetchPermissions(pagination); + } catch (error) { + message.error('更新失败'); + throw error; + } + }; + + // 删除权限 + const handleDelete = async (id) => { + try { + const { error } = await supabase + .from('permissions') + .delete() + .eq('id', id); + + if (error) throw error; + message.success('删除成功'); + fetchPermissions(pagination); + } catch (error) { + message.error('删除失败'); + throw error; + } + }; + + // 添加新角色 + const handleAddRole = async (values) => { + try { + const { data, error } = await supabase + .from('roles') + .insert([{ + name: values.name, + description: values.description + }]) + .select() + .single(); + + if (error) throw error; + + message.success('添加角色成功'); + setRoles([...roles, data]); + setRoleModalVisible(false); + roleForm.resetFields(); + return data; + } catch (error) { + message.error('添加角色失败'); + throw error; + } + }; + + // 添加新资源 + const handleAddResource = async (values) => { + try { + const { data, error } = await supabase + .from('permission_resources') + .insert([{ + resource_name: values.resource_name, + resource_type: values.resource_type, + attributes_type: values.attributes_type, + description: values.description + }]) + .select() + .single(); + + if (error) throw error; + + message.success('添加资源成功'); + setResources([...resources, data]); + setResourceModalVisible(false); + resourceForm.resetFields(); + return data; + } catch (error) { + message.error('添加资源失败'); + throw error; + } + }; + + // 初始化加载 + useEffect(() => { + fetchPermissions(); + fetchRoles(); + fetchResources(); + }, []); + + const handleTableChange = (newPagination, filters, newSorter) => { + const params = { + current: newPagination?.current, + pageSize: newPagination?.pageSize, + field: newSorter?.field, + order: newSorter?.order, + }; + + setPagination(prev => ({ + ...prev, + current: params.current, + pageSize: params.pageSize, + })); + + setSorter({ + field: params.field || sorter.field, + order: params.order || sorter.order, + }); + + fetchPermissions(params); + }; + + const columns = [ + { + title: '角色', + dataIndex: ['roles', 'name'], + key: 'role_name', + sorter: true, + render: (name) => ( + + {name} + + ) + }, + { + title: '资源', + dataIndex: ['resources', 'resource_name'], + key: 'resource_name', + sorter: true, + }, + { + title: '资源类型', + dataIndex: ['resources', 'resource_type'], + key: 'resource_type', + render: (type) => ( + + {type === 'table' ? '数据表' : '字段值'} + + ) + }, + { + title: '属性类型', + dataIndex: ['resources', 'attributes_type'], + key: 'attributes_type', + render: (attributes_type) => ( + + {!attributes_type ? '无' : attributes_type} + + + + ) + }, + { + title: '操作类型', + dataIndex: 'action', + key: 'action', + render: (action) => { + const actionMap = { + create: { text: '创建', color: 'bg-green-100 text-green-800' }, + read: { text: '读取', color: 'bg-blue-100 text-blue-800' }, + update: { text: '更新', color: 'bg-yellow-100 text-yellow-800' }, + delete: { text: '删除', color: 'bg-red-100 text-red-800' } + }; + + const { text, color } = actionMap[action] || { text: action, color: 'bg-gray-100 text-gray-800' }; + + return ( + + {text} + + ); + } + }, + { + title: '描述', + dataIndex: ['resources', 'description'], + key: 'description', + ellipsis: true, + }, + { + title: '操作', + key: 'operation', + render: (_, record) => ( +
+
+ ), + }, + ]; + + // Modal 表单内容 + const renderFormItems = () => ( + <> + + + + + + + + + + + + + ); -export default function index() { return ( -
index
- ) -} + + + { + setModalType('add'); + setModalVisible(true); + }} + onSearch={(value) => { + fetchPermissions({ + ...pagination, + current: 1, + search: value + }); + }} + /> + + + + { + setModalVisible(false); + form.resetFields(); + }} + onOk={() => form.submit()} + confirmLoading={loading} + > +
{ + try { + setLoading(true); + if (modalType === 'add') { + await handleAdd(values); + } else { + await handleUpdate(values); + } + setModalVisible(false); + form.resetFields(); + } catch (error) { + console.error(error); + } finally { + setLoading(false); + } + }} + > + {renderFormItems()} + +
+ + {/* 添加角色 Modal */} + { + setRoleModalVisible(false); + roleForm.resetFields(); + }} + onOk={() => roleForm.submit()} + > +
+ + + + + + + +
+ + {/* 添加资源 Modal */} + { + setResourceModalVisible(false); + resourceForm.resetFields(); + }} + onOk={() => resourceForm.submit()} + > +
+ + + + + + + + + + + + + +
+ + + ); +} \ No newline at end of file diff --git a/src/services/supabase/resource.js b/src/services/supabase/resource.js index fc2ead6..997412a 100644 --- a/src/services/supabase/resource.js +++ b/src/services/supabase/resource.js @@ -78,7 +78,7 @@ export const resourceService = { async deleteResource(id,type) { try { - const { error } = await supabase + const { data,error } = await supabase .from('resources') .delete() .eq('id', id) @@ -86,7 +86,7 @@ export const resourceService = { .select() if (error) throw error; - return true; + return data; } catch (error) { throw error; }