import { useState, useEffect } from "react"; import { ClientLoaderFunctionArgs, ClientActionFunctionArgs } from "@remix-run/react"; import { Card } from "~/components/ui/Card"; import { Button } from "~/components/ui/Button"; import { toastService } from "~/components/ui/Toast"; import { getRoles, getRoutes, getRoleRoutePermissions, updateRoleRoutePermissions, getRoleUsers, getAllUsers, assignUserRoles, createRole, updateRole, deleteRole, type RoleInfo, type RouteInfo, type UserInfo } from "~/api/role-permissions/role-permissions"; import rolePermissionsStyles from "~/styles/pages/role-permissions.css?url"; // 引入样式 export function links() { return [ { rel: "stylesheet", href: rolePermissionsStyles } ]; } // 页面元数据 export const meta = () => { return [ { title: "角色权限管理 - 中国烟草AI合同及卷宗审核系统" }, { name: "description", content: "管理系统角色和权限分配" } ]; }; // ClientLoader - 加载初始数据 export async function clientLoader({ request }: ClientLoaderFunctionArgs) { try { const [roles, routes, users] = await Promise.all([ getRoles(), getRoutes(), getAllUsers() ]); return { roles, routes, users }; } catch (error) { console.error("加载数据失败:", error); return { roles: [], routes: [], users: [] }; } } // ClientAction - 处理用户操作 export async function clientAction({ request }: ClientActionFunctionArgs) { const formData = await request.formData(); const action = formData.get("action") as string; try { switch (action) { case "updatePermissions": { const roleId = parseInt(formData.get("roleId") as string); const routeIds = JSON.parse(formData.get("routeIds") as string); const result = await updateRoleRoutePermissions(roleId, routeIds); return result; } case "assignUserRoles": { const userId = parseInt(formData.get("userId") as string); const roleIds = JSON.parse(formData.get("roleIds") as string); const result = await assignUserRoles(userId, roleIds); return result; } case "createRole": { const roleData = JSON.parse(formData.get("roleData") as string); const result = await createRole(roleData); return result; } case "updateRole": { const roleId = parseInt(formData.get("roleId") as string); const roleData = JSON.parse(formData.get("roleData") as string); const result = await updateRole(roleId, roleData); return result; } case "deleteRole": { const roleId = parseInt(formData.get("roleId") as string); const result = await deleteRole(roleId); return result; } default: return { success: false, message: "未知操作" }; } } catch (error) { console.error("操作失败:", error); return { success: false, message: error instanceof Error ? error.message : "操作失败" }; } } // 主组件 export default function RolePermissions() { const [roles, setRoles] = useState([]); const [routes, setRoutes] = useState([]); const [users, setUsers] = useState([]); const [selectedRole, setSelectedRole] = useState(null); const [activeTab, setActiveTab] = useState<'permissions' | 'users'>('permissions'); const [loading, setLoading] = useState(true); // 路由权限相关状态 const [selectedRouteIds, setSelectedRouteIds] = useState([]); const [roleUsers, setRoleUsers] = useState([]); // 加载初始数据 useEffect(() => { loadData(); }, []); const loadData = async () => { setLoading(true); try { const [rolesData, routesData, usersData] = await Promise.all([ getRoles(), getRoutes(), getAllUsers() ]); setRoles(rolesData); setRoutes(routesData); setUsers(usersData); // 默认选中第一个角色 if (rolesData.length > 0) { handleSelectRole(rolesData[0]); } } catch (error) { console.error("加载数据失败:", error); toastService.error("加载数据失败"); } finally { setLoading(false); } }; // 选择角色 const handleSelectRole = async (role: RoleInfo) => { setSelectedRole(role); // 加载该角色的权限 const permissions = await getRoleRoutePermissions(role.id); const routeIds = permissions.map(p => p.route_id); setSelectedRouteIds(routeIds); // 加载该角色的用户列表 const users = await getRoleUsers(role.id); setRoleUsers(users); }; // 递归获取所有路由ID(包括子路由) const getAllRouteIds = (routes: RouteInfo[]): number[] => { let ids: number[] = []; routes.forEach(route => { ids.push(route.id); if (route.children && route.children.length > 0) { ids = ids.concat(getAllRouteIds(route.children)); } }); return ids; }; // 切换路由权限 const handleToggleRoute = (routeId: number, checked: boolean) => { if (checked) { setSelectedRouteIds([...selectedRouteIds, routeId]); } else { setSelectedRouteIds(selectedRouteIds.filter(id => id !== routeId)); } }; // 切换父路由(包括所有子路由) const handleToggleParentRoute = (route: RouteInfo, checked: boolean) => { const childIds = route.children ? getAllRouteIds(route.children) : []; const allIds = [route.id, ...childIds]; if (checked) { const newIds = [...selectedRouteIds, ...allIds].filter( (id, index, self) => self.indexOf(id) === index ); setSelectedRouteIds(newIds); } else { setSelectedRouteIds( selectedRouteIds.filter(id => !allIds.includes(id)) ); } }; // 保存权限 const handleSavePermissions = async () => { if (!selectedRole) return; try { const formData = new FormData(); formData.append("action", "updatePermissions"); formData.append("roleId", selectedRole.id.toString()); formData.append("routeIds", JSON.stringify(selectedRouteIds)); const response = await fetch("/role-permissions", { method: "POST", body: formData }); const result = await response.json(); if (result.success) { toastService.success(result.message); } else { toastService.error(result.message); } } catch (error) { console.error("保存权限失败:", error); toastService.error("保存权限失败"); } }; // 渲染路由树 const renderRouteTree = (routes: RouteInfo[], level = 0) => { return routes.map(route => { const hasChildren = route.children && route.children.length > 0; const isChecked = selectedRouteIds.includes(route.id); const allChildIds = hasChildren ? getAllRouteIds(route.children!) : []; const checkedChildCount = allChildIds.filter(id => selectedRouteIds.includes(id) ).length; const isIndeterminate = hasChildren && checkedChildCount > 0 && checkedChildCount < allChildIds.length; return (
{ if (el) el.indeterminate = isIndeterminate; }} onChange={(e) => { if (hasChildren) { handleToggleParentRoute(route, e.target.checked); } else { handleToggleRoute(route.id, e.target.checked); } }} className="route-checkbox" />
{hasChildren && (
{renderRouteTree(route.children!, level + 1)}
)}
); }); }; if (loading) { return (
加载中...
); } return (
{/* 页面头部 */}

角色权限管理

{/* 左侧:角色列表 */}
{roles.map(role => (
handleSelectRole(role)} >
{role.role_name} {role.is_system_role && ( 系统角色 )}
{role.role_key}
{role.description}
{role.data_scope} 优先级: {role.priority}
{!role.is_system_role && (
)}
))}
{/* 右侧:角色详情和权限设置 */}
{selectedRole ? ( <> {/* Tab 切换 */}
{/* 路由权限Tab */} {activeTab === 'permissions' && (

为角色 "{selectedRole.role_name}" 分配路由权限

{renderRouteTree(routes)}
已选择 {selectedRouteIds.length} 个路由权限
)} {/* 用户列表Tab */} {activeTab === 'users' && (

拥有角色 "{selectedRole.role_name}" 的用户

{roleUsers.length > 0 ? ( roleUsers.map(user => (
{user.nick_name} {user.is_leader && ( 负责人 )}
@{user.username}
{user.ou_name}
{user.phone_number && ( {user.phone_number} )} {user.email && ( {user.email} )}
)) ) : (

暂无用户拥有此角色

)}
)}
) : (

请选择一个角色查看详情

)}
); }