文档列表documents添加用户id的限制,添加通过统一认证之后数据库中用户数据的添加和角色的添加,添加Sidebar菜单通过数据库请求获取
This commit is contained in:
@@ -0,0 +1,613 @@
|
||||
import { toastService } from '~/components/ui';
|
||||
import { postgrestGet } from '../postgrest-client';
|
||||
|
||||
// 路由数据接口
|
||||
export interface RouteInfo {
|
||||
id: number;
|
||||
path: string;
|
||||
name: string;
|
||||
meta: {
|
||||
title: string;
|
||||
icon: string;
|
||||
order: number;
|
||||
requiredRole?: string;
|
||||
};
|
||||
parent_id: number;
|
||||
is_menu: number;
|
||||
}
|
||||
|
||||
// 用户路由权限接口
|
||||
export interface UserRoutePermission {
|
||||
route_id: number;
|
||||
role_id: number;
|
||||
permission: string;
|
||||
route: RouteInfo;
|
||||
}
|
||||
|
||||
// MenuItem结构接口
|
||||
export interface MenuItem {
|
||||
id: string;
|
||||
title: string;
|
||||
path: string;
|
||||
icon: string;
|
||||
order: number;
|
||||
hideBreadcrumb?: boolean;
|
||||
requiredRole?: string;
|
||||
children?: MenuItem[];
|
||||
}
|
||||
|
||||
// 静态菜单数据作为后备 (保留用于开发和紧急情况,当前不使用)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const FALLBACK_MENU_DATA: Record<string, MenuItem[]> = {
|
||||
'admin': [
|
||||
{
|
||||
id: 'home',
|
||||
title: '系统概览',
|
||||
path: '/home',
|
||||
icon: 'ri-home-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'chat-with-llm',
|
||||
title: 'AI对话',
|
||||
path: '/chat-with-llm',
|
||||
icon: 'ri-chat-smile-2-line',
|
||||
order: 2
|
||||
},
|
||||
{
|
||||
id: 'file-management',
|
||||
title: '文件管理',
|
||||
path: '/files',
|
||||
icon: 'ri-folder-line',
|
||||
order: 3,
|
||||
children: [
|
||||
{
|
||||
id: 'file-upload',
|
||||
title: '文件上传',
|
||||
path: '/files/upload',
|
||||
icon: 'ri-upload-cloud-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'documents',
|
||||
title: '文档列表',
|
||||
path: '/documents',
|
||||
icon: 'ri-file-list-3-line',
|
||||
order: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'rule-management',
|
||||
title: '评查规则库',
|
||||
path: '/rules',
|
||||
icon: 'ri-book-3-line',
|
||||
order: 4,
|
||||
children: [
|
||||
{
|
||||
id: 'rule-groups',
|
||||
title: '评查点分组',
|
||||
path: '/rule-groups',
|
||||
icon: 'ri-folder-open-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'rules-list',
|
||||
title: '评查点列表',
|
||||
path: '/rules',
|
||||
icon: 'ri-list-check-3',
|
||||
order: 2
|
||||
},
|
||||
{
|
||||
id: 'rules-file',
|
||||
title: '评查文件列表',
|
||||
path: '/rules-files',
|
||||
icon: 'ri-list-check-2',
|
||||
order: 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'contract-template',
|
||||
title: '合同模板',
|
||||
path: '/contract-template',
|
||||
icon: 'ri-file-search-line',
|
||||
order: 5,
|
||||
children: [
|
||||
{
|
||||
id: 'contract-search-ai',
|
||||
title: '智能搜索',
|
||||
path: '/contract-template/search',
|
||||
icon: 'ri-search-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'contract-list',
|
||||
title: '合同列表',
|
||||
path: '/contract-template/list',
|
||||
icon: 'ri-folder-line',
|
||||
order: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'system-settings',
|
||||
title: '系统设置',
|
||||
path: '/settings',
|
||||
icon: 'ri-settings-4-line',
|
||||
order: 6,
|
||||
requiredRole: 'developer',
|
||||
children: [
|
||||
{
|
||||
id: 'config-lists',
|
||||
title: '配置列表',
|
||||
path: '/config-lists',
|
||||
icon: 'ri-list-check-3',
|
||||
order: 1,
|
||||
requiredRole: 'developer'
|
||||
},
|
||||
{
|
||||
id: 'document-types',
|
||||
title: '文档类型',
|
||||
path: '/document-types',
|
||||
icon: 'ri-file-list-line',
|
||||
order: 2,
|
||||
requiredRole: 'developer'
|
||||
},
|
||||
{
|
||||
id: 'prompt-management',
|
||||
title: '提示词管理',
|
||||
path: '/prompts',
|
||||
icon: 'ri-chat-1-line',
|
||||
order: 3,
|
||||
requiredRole: 'developer'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'cross-checking',
|
||||
title: '交叉评查',
|
||||
path: '/cross-checking',
|
||||
icon: 'ri-color-filter-line',
|
||||
order: 7
|
||||
}
|
||||
],
|
||||
'common': [
|
||||
{
|
||||
id: 'home',
|
||||
title: '系统概览',
|
||||
path: '/home',
|
||||
icon: 'ri-home-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'file-management',
|
||||
title: '文件管理',
|
||||
path: '/files',
|
||||
icon: 'ri-folder-line',
|
||||
order: 3,
|
||||
children: [
|
||||
{
|
||||
id: 'file-upload',
|
||||
title: '文件上传',
|
||||
path: '/files/upload',
|
||||
icon: 'ri-upload-cloud-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'documents',
|
||||
title: '文档列表',
|
||||
path: '/documents',
|
||||
icon: 'ri-file-list-3-line',
|
||||
order: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'rule-management',
|
||||
title: '评查规则库',
|
||||
path: '/rules',
|
||||
icon: 'ri-book-3-line',
|
||||
order: 4,
|
||||
children: [
|
||||
{
|
||||
id: 'rule-groups',
|
||||
title: '评查点分组',
|
||||
path: '/rule-groups',
|
||||
icon: 'ri-folder-open-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'rules-list',
|
||||
title: '评查点列表',
|
||||
path: '/rules',
|
||||
icon: 'ri-list-check-3',
|
||||
order: 2
|
||||
},
|
||||
{
|
||||
id: 'rules-file',
|
||||
title: '评查文件列表',
|
||||
path: '/rules-files',
|
||||
icon: 'ri-list-check-2',
|
||||
order: 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'contract-template',
|
||||
title: '合同模板',
|
||||
path: '/contract-template',
|
||||
icon: 'ri-file-search-line',
|
||||
order: 5,
|
||||
children: [
|
||||
{
|
||||
id: 'contract-search-ai',
|
||||
title: '智能搜索',
|
||||
path: '/contract-template/search',
|
||||
icon: 'ri-search-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'contract-list',
|
||||
title: '合同列表',
|
||||
path: '/contract-template/list',
|
||||
icon: 'ri-folder-line',
|
||||
order: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'cross-checking',
|
||||
title: '交叉评查',
|
||||
path: '/cross-checking',
|
||||
icon: 'ri-color-filter-line',
|
||||
order: 7
|
||||
}
|
||||
],
|
||||
'deptLeader': [
|
||||
{
|
||||
id: 'home',
|
||||
title: '系统概览',
|
||||
path: '/home',
|
||||
icon: 'ri-home-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'chat-with-llm',
|
||||
title: 'AI对话',
|
||||
path: '/chat-with-llm',
|
||||
icon: 'ri-chat-smile-2-line',
|
||||
order: 2
|
||||
},
|
||||
{
|
||||
id: 'file-management',
|
||||
title: '文件管理',
|
||||
path: '/files',
|
||||
icon: 'ri-folder-line',
|
||||
order: 3,
|
||||
children: [
|
||||
{
|
||||
id: 'file-upload',
|
||||
title: '文件上传',
|
||||
path: '/files/upload',
|
||||
icon: 'ri-upload-cloud-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'documents',
|
||||
title: '文档列表',
|
||||
path: '/documents',
|
||||
icon: 'ri-file-list-3-line',
|
||||
order: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'rule-management',
|
||||
title: '评查规则库',
|
||||
path: '/rules',
|
||||
icon: 'ri-book-3-line',
|
||||
order: 4,
|
||||
children: [
|
||||
{
|
||||
id: 'rule-groups',
|
||||
title: '评查点分组',
|
||||
path: '/rule-groups',
|
||||
icon: 'ri-folder-open-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'rules-list',
|
||||
title: '评查点列表',
|
||||
path: '/rules',
|
||||
icon: 'ri-list-check-3',
|
||||
order: 2
|
||||
},
|
||||
{
|
||||
id: 'rules-file',
|
||||
title: '评查文件列表',
|
||||
path: '/rules-files',
|
||||
icon: 'ri-list-check-2',
|
||||
order: 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'contract-template',
|
||||
title: '合同模板',
|
||||
path: '/contract-template',
|
||||
icon: 'ri-file-search-line',
|
||||
order: 5,
|
||||
children: [
|
||||
{
|
||||
id: 'contract-search-ai',
|
||||
title: '智能搜索',
|
||||
path: '/contract-template/search',
|
||||
icon: 'ri-search-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'contract-list',
|
||||
title: '合同列表',
|
||||
path: '/contract-template/list',
|
||||
icon: 'ri-folder-line',
|
||||
order: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'cross-checking',
|
||||
title: '交叉评查',
|
||||
path: '/cross-checking',
|
||||
icon: 'ri-color-filter-line',
|
||||
order: 7
|
||||
}
|
||||
],
|
||||
'groupLeader': [
|
||||
{
|
||||
id: 'home',
|
||||
title: '系统概览',
|
||||
path: '/home',
|
||||
icon: 'ri-home-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'file-management',
|
||||
title: '文件管理',
|
||||
path: '/files',
|
||||
icon: 'ri-folder-line',
|
||||
order: 3,
|
||||
children: [
|
||||
{
|
||||
id: 'file-upload',
|
||||
title: '文件上传',
|
||||
path: '/files/upload',
|
||||
icon: 'ri-upload-cloud-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'documents',
|
||||
title: '文档列表',
|
||||
path: '/documents',
|
||||
icon: 'ri-file-list-3-line',
|
||||
order: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'rule-management',
|
||||
title: '评查规则库',
|
||||
path: '/rules',
|
||||
icon: 'ri-book-3-line',
|
||||
order: 4,
|
||||
children: [
|
||||
{
|
||||
id: 'rule-groups',
|
||||
title: '评查点分组',
|
||||
path: '/rule-groups',
|
||||
icon: 'ri-folder-open-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'rules-list',
|
||||
title: '评查点列表',
|
||||
path: '/rules',
|
||||
icon: 'ri-list-check-3',
|
||||
order: 2
|
||||
},
|
||||
{
|
||||
id: 'rules-file',
|
||||
title: '评查文件列表',
|
||||
path: '/rules-files',
|
||||
icon: 'ri-list-check-2',
|
||||
order: 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'contract-template',
|
||||
title: '合同模板',
|
||||
path: '/contract-template',
|
||||
icon: 'ri-file-search-line',
|
||||
order: 5,
|
||||
children: [
|
||||
{
|
||||
id: 'contract-search-ai',
|
||||
title: '智能搜索',
|
||||
path: '/contract-template/search',
|
||||
icon: 'ri-search-line',
|
||||
order: 1
|
||||
},
|
||||
{
|
||||
id: 'contract-list',
|
||||
title: '合同列表',
|
||||
path: '/contract-template/list',
|
||||
icon: 'ri-folder-line',
|
||||
order: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'cross-checking',
|
||||
title: '交叉评查',
|
||||
path: '/cross-checking',
|
||||
icon: 'ri-color-filter-line',
|
||||
order: 7
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据角色获取用户可访问的路由
|
||||
* @param roleKey 角色标识 (如: 'admin', 'common', 'deptLeader', 'groupLeader')
|
||||
* @returns 用户可访问的路由列表
|
||||
*/
|
||||
export async function getUserRoutesByRole(roleKey: string): Promise<{ success: boolean; data?: MenuItem[]; error?: string; shouldRedirectToHome?: boolean }> {
|
||||
try {
|
||||
console.log(`获取角色 ${roleKey} 的路由权限`);
|
||||
|
||||
// 首先获取角色ID
|
||||
const roleResult = await postgrestGet<Array<{id: number}>>("roles", {
|
||||
filter: {
|
||||
"role_key": `eq.${roleKey}`
|
||||
}
|
||||
});
|
||||
|
||||
if (roleResult.error || !roleResult.data || roleResult.data.length === 0) {
|
||||
console.error("角色不存在:", roleKey);
|
||||
toastService.error("角色不存在,请联系管理员配置权限后重新登录");
|
||||
return { success: false, error: "角色不存在", shouldRedirectToHome: true };
|
||||
}
|
||||
|
||||
const roleId = roleResult.data[0].id;
|
||||
|
||||
// 查询角色的路由权限
|
||||
const roleRoutesResult = await postgrestGet<Array<{route_id: number}>>("role_route", {
|
||||
filter: {
|
||||
"role_id": `eq.${roleId}`
|
||||
}
|
||||
});
|
||||
|
||||
if (roleRoutesResult.error) {
|
||||
console.error("查询角色路由关联失败:", roleRoutesResult.error);
|
||||
toastService.error("查询角色路由关联失败,请稍后再试");
|
||||
return { success: false, error: "查询角色路由关联失败", shouldRedirectToHome: true };
|
||||
}
|
||||
|
||||
const roleRoutes = roleRoutesResult.data || [];
|
||||
const routeIds = roleRoutes.map(item => item.route_id);
|
||||
|
||||
if (routeIds.length === 0) {
|
||||
console.log(`角色 ${roleKey} 没有分配任何路由权限`);
|
||||
toastService.error("您的角色没有分配任何路由权限,请联系管理员配置权限");
|
||||
return { success: false, error: "角色没有分配任何路由权限", shouldRedirectToHome: true };
|
||||
}
|
||||
|
||||
// 查询具体的路由信息
|
||||
const routesResult = await postgrestGet<RouteInfo[]>("sys_routes", {
|
||||
filter: {
|
||||
"id": `in.(${routeIds.join(',')})`,
|
||||
"is_menu": "eq.1"
|
||||
},
|
||||
order: "parent_id,meta->>order"
|
||||
});
|
||||
|
||||
if (routesResult.error) {
|
||||
console.error("查询路由信息失败:", routesResult.error);
|
||||
toastService.error("查询路由信息失败,请稍后再试");
|
||||
return { success: false, error: "查询路由信息失败", shouldRedirectToHome: true };
|
||||
}
|
||||
|
||||
const routes = routesResult.data || [];
|
||||
|
||||
// 构建菜单树
|
||||
const menuItems = buildMenuTreeFromRoutes(routes);
|
||||
|
||||
console.log(`角色 ${roleKey} 可访问 ${menuItems.length} 个路由`);
|
||||
return { success: true, data: menuItems };
|
||||
|
||||
} catch (error) {
|
||||
console.error("获取用户路由时发生错误:", error);
|
||||
toastService.error("获取用户路由时发生错误,请稍后再试");
|
||||
return {
|
||||
success: false,
|
||||
error: `获取用户路由失败: ${error instanceof Error ? error.message : String(error)}`,
|
||||
shouldRedirectToHome: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从路由信息构建菜单树结构
|
||||
* @param routes 路由信息数组
|
||||
* @returns 菜单树结构
|
||||
*/
|
||||
function buildMenuTreeFromRoutes(routes: RouteInfo[]): MenuItem[] {
|
||||
// 转换为MenuItem格式
|
||||
const menuMap = new Map<number, MenuItem>();
|
||||
|
||||
routes.forEach(route => {
|
||||
const menuItem: MenuItem = {
|
||||
id: route.name,
|
||||
title: route.meta.title,
|
||||
path: route.path,
|
||||
icon: route.meta.icon,
|
||||
order: route.meta.order || 0,
|
||||
requiredRole: route.meta.requiredRole
|
||||
};
|
||||
|
||||
menuMap.set(route.id, menuItem);
|
||||
});
|
||||
|
||||
// 构建父子关系
|
||||
const rootItems: MenuItem[] = [];
|
||||
const itemsWithParent: Array<{ item: MenuItem; parentId: number }> = [];
|
||||
|
||||
routes.forEach(route => {
|
||||
const menuItem = menuMap.get(route.id);
|
||||
if (!menuItem) return;
|
||||
|
||||
if (route.parent_id === 0) {
|
||||
rootItems.push(menuItem);
|
||||
} else {
|
||||
itemsWithParent.push({ item: menuItem, parentId: route.parent_id });
|
||||
}
|
||||
});
|
||||
|
||||
// 添加子菜单
|
||||
itemsWithParent.forEach(({ item, parentId }) => {
|
||||
const parent = menuMap.get(parentId);
|
||||
if (parent) {
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
parent.children.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
// 排序
|
||||
rootItems.sort((a, b) => a.order - b.order);
|
||||
rootItems.forEach(item => {
|
||||
if (item.children) {
|
||||
item.children.sort((a, b) => a.order - b.order);
|
||||
}
|
||||
});
|
||||
|
||||
return rootItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户角色映射到权限系统的角色标识
|
||||
* @param userRole 前端用户角色 ('common' | 'developer')
|
||||
* @returns 数据库中的角色标识
|
||||
*/
|
||||
export function mapUserRoleToRoleKey(userRole: string): string {
|
||||
const roleMapping: Record<string, string> = {
|
||||
'common': 'common',
|
||||
'developer': 'admin',
|
||||
'deptLeader': 'deptLeader',
|
||||
'groupLeader': 'groupLeader'
|
||||
};
|
||||
|
||||
return roleMapping[userRole] || 'common';
|
||||
}
|
||||
Reference in New Issue
Block a user