feat: 1. 本地化思源黑体的字体包并优先使用。
2. 添加权限映射表和全局查看权限的hook,便于路由控制不同权限按钮显示/隐藏。 3. 删除评查点分组的部分旧api方法。 4. 对接评查点分组接口,文档类型接口, 提示词管理接口, 入口模块管理的接口。 5. 优化角色权限管理的接口,完善不用地区的访问权限认证。 6. 优化主页交叉评查和设置的入口样式和布局。 7. 优化评查点分组,评查规则的功能权限校验。
This commit is contained in:
@@ -0,0 +1,272 @@
|
||||
/**
|
||||
* 权限检查Hook
|
||||
*
|
||||
* 基于RBAC(基于角色的访问控制)模型,提供细粒度的权限检查功能。
|
||||
*
|
||||
* 权限键格式:module:resource:action
|
||||
* 例如:prompt_template:create:write
|
||||
*
|
||||
* 使用示例:
|
||||
* ```typescript
|
||||
* const { hasPermission, canCreate, canEdit } = usePermission();
|
||||
*
|
||||
* // 检查单个权限
|
||||
* if (hasPermission('prompt_template:create:write')) {
|
||||
* // 显示创建按钮
|
||||
* }
|
||||
*
|
||||
* // 使用便捷方法
|
||||
* if (canCreate('prompt_template')) {
|
||||
* // 显示创建按钮
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
import { useRouteLoaderData, useLocation } from "@remix-run/react";
|
||||
|
||||
interface RootLoaderData {
|
||||
permissions?: string[];
|
||||
permissionMap?: Record<string, string[]>; // ✅ 新增:权限映射表
|
||||
userRole: string;
|
||||
userInfo?: {
|
||||
role_id?: number;
|
||||
role_key?: string;
|
||||
role_name?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export function usePermission() {
|
||||
const rootData = useRouteLoaderData("root") as RootLoaderData;
|
||||
const location = useLocation();
|
||||
|
||||
// 从root loader获取权限映射表
|
||||
const permissionMap = rootData?.permissionMap || {};
|
||||
const userRole = rootData?.userRole || 'common';
|
||||
|
||||
// 🔑 根据当前路由获取权限列表
|
||||
const currentPath = location.pathname;
|
||||
// console.log('currentPath', currentPath)
|
||||
const currentPermissions = permissionMap[currentPath] || [];
|
||||
|
||||
// 向后兼容:如果存在旧的permissions数组,也要支持
|
||||
const legacyPermissions = rootData?.permissions || [];
|
||||
|
||||
/**
|
||||
* 检查是否有指定权限
|
||||
* @param permissionKey 权限键,如 "prompt_template:create:write"
|
||||
* @returns boolean
|
||||
*/
|
||||
const hasPermission = (permissionKey: string): boolean => {
|
||||
// 优先使用当前路由的权限列表
|
||||
if (currentPermissions.length > 0) {
|
||||
return currentPermissions.includes(permissionKey);
|
||||
}
|
||||
|
||||
// 向后兼容:支持旧的permissions数组
|
||||
if (legacyPermissions.length > 0) {
|
||||
return legacyPermissions.includes(permissionKey);
|
||||
}
|
||||
|
||||
// 降级方案:如果没有权限数据,使用userRole判断(兼容现有系统)
|
||||
// 包含'provin'的角色拥有所有权限
|
||||
if (userRole.toLowerCase().includes('provin')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 默认只有查看权限
|
||||
if (permissionKey.includes(':read')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查是否有指定路由的权限
|
||||
* @param path 路由路径,如 "/prompts"
|
||||
* @param permissionKey 权限键
|
||||
* @returns boolean
|
||||
*/
|
||||
const hasRoutePermission = (path: string, permissionKey: string): boolean => {
|
||||
const routePermissions = permissionMap[path] || [];
|
||||
return routePermissions.includes(permissionKey);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前路由的所有权限
|
||||
* @returns 权限列表
|
||||
*/
|
||||
const getCurrentPermissions = (): string[] => {
|
||||
return currentPermissions;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取指定路由的所有权限
|
||||
* @param path 路由路径
|
||||
* @returns 权限列表
|
||||
*/
|
||||
const getRoutePermissions = (path: string): string[] => {
|
||||
return permissionMap[path] || [];
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查是否有指定模块的任意权限
|
||||
* @param module 模块名,如 "prompt_template"
|
||||
* @returns boolean
|
||||
*/
|
||||
const hasModulePermission = (module: string): boolean => {
|
||||
if (currentPermissions.length > 0) {
|
||||
return currentPermissions.some(p => p.startsWith(`${module}:`));
|
||||
}
|
||||
|
||||
if (legacyPermissions.length > 0) {
|
||||
return legacyPermissions.some(p => p.startsWith(`${module}:`));
|
||||
}
|
||||
|
||||
// 降级方案
|
||||
return userRole.toLowerCase().includes('provin');
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查是否有指定资源和动作的权限
|
||||
* @param module 模块名,如 "prompt_template"
|
||||
* @param resource 资源名,如 "create", "list", "detail"
|
||||
* @param action 动作,如 "read", "write", "delete"
|
||||
* @returns boolean
|
||||
*/
|
||||
const hasResourcePermission = (module: string, resource: string, action: string): boolean => {
|
||||
const permissionKey = `${module}:${resource}:${action}`;
|
||||
return hasPermission(permissionKey);
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量检查权限(需要全部满足)
|
||||
* @param permissionKeys 权限键数组
|
||||
* @returns boolean
|
||||
*/
|
||||
const hasAllPermissions = (permissionKeys: string[]): boolean => {
|
||||
return permissionKeys.every(key => hasPermission(key));
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量检查权限(满足任意一个即可)
|
||||
* @param permissionKeys 权限键数组
|
||||
* @returns boolean
|
||||
*/
|
||||
const hasAnyPermission = (permissionKeys: string[]): boolean => {
|
||||
return permissionKeys.some(key => hasPermission(key));
|
||||
};
|
||||
|
||||
// 便捷方法:检查常见操作权限
|
||||
const canCreate = (module: string): boolean => {
|
||||
return hasResourcePermission(module, 'create', 'write');
|
||||
};
|
||||
|
||||
const canRead = (module: string, resource: string = 'list'): boolean => {
|
||||
return hasResourcePermission(module, resource, 'read');
|
||||
};
|
||||
|
||||
const canUpdate = (module: string): boolean => {
|
||||
return hasResourcePermission(module, 'update', 'write');
|
||||
};
|
||||
|
||||
const canDelete = (module: string): boolean => {
|
||||
return hasResourcePermission(module, 'delete', 'delete');
|
||||
};
|
||||
|
||||
const canList = (module: string): boolean => {
|
||||
return hasResourcePermission(module, 'list', 'read');
|
||||
};
|
||||
|
||||
const canView = (module: string): boolean => {
|
||||
return hasResourcePermission(module, 'detail', 'read');
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查是否有批量操作权限
|
||||
* @param module 模块名,如 "evaluation_group"
|
||||
* @returns boolean - 检查是否有 module:batch:write 权限
|
||||
*/
|
||||
const canBatch = (module: string): boolean => {
|
||||
return hasResourcePermission(module, 'batch', 'write');
|
||||
};
|
||||
|
||||
return {
|
||||
// 原始权限数据
|
||||
permissions: currentPermissions, // ✅ 返回当前路由的权限
|
||||
permissionMap, // ✅ 返回完整的权限映射表
|
||||
userRole,
|
||||
|
||||
// 基础检查方法
|
||||
hasPermission,
|
||||
hasModulePermission,
|
||||
hasResourcePermission,
|
||||
hasAllPermissions,
|
||||
hasAnyPermission,
|
||||
|
||||
// ✅ 新增:路由权限查询方法
|
||||
hasRoutePermission,
|
||||
getCurrentPermissions,
|
||||
getRoutePermissions,
|
||||
|
||||
// 便捷方法
|
||||
canCreate,
|
||||
canRead,
|
||||
canUpdate,
|
||||
canDelete,
|
||||
canList,
|
||||
canView,
|
||||
canBatch // ✅ 新增:批量操作权限检查
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限组件包装器
|
||||
*
|
||||
* 根据权限控制子组件的显示/隐藏
|
||||
*
|
||||
* 使用示例:
|
||||
* ```typescript
|
||||
* <PermissionGuard permission="prompt_template:create:write">
|
||||
* <Button>新增模板</Button>
|
||||
* </PermissionGuard>
|
||||
* ```
|
||||
*/
|
||||
interface PermissionGuardProps {
|
||||
permission?: string;
|
||||
permissions?: string[];
|
||||
requireAll?: boolean; // true=需要全部权限,false=任意一个即可
|
||||
fallback?: React.ReactNode; // 无权限时显示的内容
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function PermissionGuard({
|
||||
permission,
|
||||
permissions: permissionList,
|
||||
requireAll = false,
|
||||
fallback = null,
|
||||
children
|
||||
}: PermissionGuardProps) {
|
||||
const { hasPermission, hasAllPermissions, hasAnyPermission } = usePermission();
|
||||
|
||||
let hasAccess = false;
|
||||
|
||||
if (permission) {
|
||||
// 单个权限检查
|
||||
hasAccess = hasPermission(permission);
|
||||
} else if (permissionList && permissionList.length > 0) {
|
||||
// 多个权限检查
|
||||
hasAccess = requireAll
|
||||
? hasAllPermissions(permissionList)
|
||||
: hasAnyPermission(permissionList);
|
||||
} else {
|
||||
// 没有指定权限,默认允许访问
|
||||
hasAccess = true;
|
||||
}
|
||||
|
||||
if (!hasAccess) {
|
||||
return <>{fallback}</>;
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
Reference in New Issue
Block a user