From a83a32b969fbb7f927144d212a09f4efb5db3d8a Mon Sep 17 00:00:00 2001 From: Leo <98382335+gaoziman@users.noreply.github.com> Date: Sun, 6 Jul 2025 18:31:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(api):=20=E5=AE=8C=E5=96=84=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E6=A8=A1=E5=9D=97=E7=9A=84API?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=92=8C=E7=B1=BB=E5=9E=8B=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增角色管理相关API接口和类型定义 - 新增菜单权限管理相关API接口 - 完善用户角色分配API接口 - 优化路由处理工具函数 - 统一API响应类型定义 - 为弹框组件集成提供完整的数据支持 --- src/service/api/system/menu/index.ts | 36 +++++++++++++++++++++ src/service/api/system/role/index.ts | 48 +++++++++++++++++++++++++++- src/service/api/system/role/types.ts | 41 ++++++++++++++++++++++-- src/store/router/helper.ts | 44 ++++++++++++++++++++++--- src/typings/service.d.ts | 16 ++++++++++ 5 files changed, 177 insertions(+), 8 deletions(-) diff --git a/src/service/api/system/menu/index.ts b/src/service/api/system/menu/index.ts index 27a3d4b..6f4ae9d 100644 --- a/src/service/api/system/menu/index.ts +++ b/src/service/api/system/menu/index.ts @@ -1,5 +1,23 @@ import { request } from '../../../http' +// 菜单信息类型 +export interface MenuVo { + menuId: number + menuName: string + parentId: number + menuType: string + isSpread?: string + auth?: string // 权限标识 + perms?: string // 权限标识的别名 + permission?: string // 权限标识的另一个别名 +} + +// 菜单权限数据类型 +export interface MenuPermissionData { + menuList: MenuVo[] + spreadList: number[] +} + // 菜单路由管理相关API // 获取用户动态路由信息 @@ -7,5 +25,23 @@ export function getUserRoutes() { return request.Get>('/coder/sysMenu/listRouters') } +// 查询所有正常的菜单和展开节点(角色分配菜单权限使用) +export function getMenuPermissionData() { + return request.Get>('/coder/sysMenu/listMenuNormal') +} + +// 根据角色ID查询菜单权限ID列表 +export function getMenuIdsByRoleId(roleId: number) { + return request.Get>(`/coder/sysMenu/listMenuIdsByRoleId/${roleId}`) +} + +// 保存角色和菜单权限之间的关系 +export function saveRoleMenuPermission(roleId: number, menuIds: number[]) { + const menuIdsStr = menuIds.length > 0 ? menuIds.join(',') : '-1' + return request.Post>(`/coder/sysMenu/saveRoleMenu/${roleId}/${menuIdsStr}`) +} + // 兼容性导出 - 保持原有函数名以确保向后兼容 export const fetchUserRoutes = getUserRoutes +export const fetchMenuPermissionData = getMenuPermissionData +export const fetchMenuIdsByRoleId = getMenuIdsByRoleId diff --git a/src/service/api/system/role/index.ts b/src/service/api/system/role/index.ts index 9173260..c376db7 100644 --- a/src/service/api/system/role/index.ts +++ b/src/service/api/system/role/index.ts @@ -1,5 +1,7 @@ import { request } from '../../../http' import type { + RoleForm, + RoleQueryBo, RoleSelectVo, RoleTransferVo, RoleVo, @@ -7,6 +9,9 @@ import type { // 重新导出类型供外部使用 export type { + RoleForm, + RoleQueryBo, + RoleSearchForm, RoleSelectVo, RoleTransferVo, RoleVo, @@ -14,11 +19,51 @@ export type { // 角色管理相关API +// 分页查询角色列表 +export function getRolePage(params: RoleQueryBo) { + return request.Get>>('/coder/sysRole/listPage', { params }) +} + // 获取所有角色列表 export function getRoleList() { return request.Get>('/coder/sysRole/list') } +// 根据ID查询角色详情 +export function getRoleById(id: number) { + return request.Get>(`/coder/sysRole/getById/${id}`) +} + +// 新增角色 +export function addRole(data: RoleForm) { + return request.Post>('/coder/sysRole/add', data) +} + +// 修改角色 +export function updateRole(data: RoleForm) { + return request.Post>('/coder/sysRole/update', data) +} + +// 删除角色 +export function deleteRole(id: number) { + return request.Post>(`/coder/sysRole/deleteById/${id}`) +} + +// 批量删除角色 +export function batchDeleteRoles(ids: number[]) { + return request.Post>('/coder/sysRole/batchDelete', ids) +} + +// 修改角色状态 +export function updateRoleStatus(roleId: number, roleStatus: string) { + return request.Post>(`/coder/sysRole/updateStatus/${roleId}/${roleStatus}`) +} + +// 获取最新排序号 +export function getRoleSorted() { + return request.Get>('/coder/sysRole/getSorted') +} + // 获取角色下拉框数据 export function getRoleElSelect() { return request.Get>('/coder/sysRole/listRoleElSelect') @@ -26,7 +71,7 @@ export function getRoleElSelect() { // 查询正常角色穿梭框 export function getNormalRoleForUser(userId: number) { - return request.Get>(`/coder/sysRole/listNormalRole/${userId}`) + return request.Get>(`/coder/sysRole/listNormalRole/${userId}`) } // 分配用户角色 @@ -38,3 +83,4 @@ export function assignUserRole(userId: number, roleIds: string) { export const fetchRoleList = getRoleList export const fetchRoleElSelect = getRoleElSelect export const fetchNormalRoleForUser = getNormalRoleForUser +export const fetchRolePage = getRolePage diff --git a/src/service/api/system/role/types.ts b/src/service/api/system/role/types.ts index bbac783..0d6004d 100644 --- a/src/service/api/system/role/types.ts +++ b/src/service/api/system/role/types.ts @@ -3,6 +3,42 @@ export interface RoleVo { roleId: number roleName: string roleCode: string + roleStatus: string + remark?: string + sorted?: number + createTime?: string + updateTime?: string + createBy?: string + updateBy?: string +} + +// 角色查询参数类型 +export interface RoleQueryBo { + pageNo?: number + pageSize?: number + roleName?: string + roleCode?: string + roleStatus?: string + beginTime?: string + endTime?: string +} + +// 角色搜索表单类型 +export interface RoleSearchForm { + roleName?: string + roleCode?: string + roleStatus?: string | null + timeRange?: [number, number] | null +} + +// 角色表单类型 +export interface RoleForm { + roleId?: number + roleName: string + roleCode: string + roleStatus: string + remark: string + sorted?: number } // 角色选择器选项类型 @@ -13,7 +49,6 @@ export interface RoleSelectVo { // 角色穿梭框选项类型 export interface RoleTransferVo { - label: string - value: number - parentId: string + data1: RoleSelectVo[] + data2: number[] } diff --git a/src/store/router/helper.ts b/src/store/router/helper.ts index fd84cae..12cf81a 100644 --- a/src/store/router/helper.ts +++ b/src/store/router/helper.ts @@ -207,16 +207,52 @@ export function createMenus(routeData: (AppRoute.BackendRoute | AppRoute.RowRout // filter menus that do not need to be displayed const visibleMenus = resultMenus.filter(route => !route.meta.hide && route.meta.menuType !== '3') // 过滤按钮类型 + // 处理权限过滤和父子关系 + const menusWithPermission = processMenuPermissions(visibleMenus) + // generate side menu - return arrayToTree(transformAuthRoutesToMenus(visibleMenus)) + return arrayToTree(transformAuthRoutesToMenus(menusWithPermission)) +} + +// 处理菜单权限,确保有子菜单权限时父菜单也可见 +function processMenuPermissions(routes: AppRoute.Route[]): AppRoute.Route[] { + const { hasPermission } = usePermission() + + // 创建路由映射表 + const routeMap = new Map() + routes.forEach(route => routeMap.set(route.id, route)) + + // 找出有权限的路由 + const authorizedRoutes = new Set() + + routes.forEach((route) => { + if (hasPermission(route.meta.roles)) { + authorizedRoutes.add(route.id) + + // 如果是页面类型(menuType='2')或没有menuType的路由,确保其父菜单也被包含 + if (!route.meta.menuType || route.meta.menuType === '2') { + let parentId = route.pid + while (parentId !== null && parentId !== undefined) { + const parentRoute = routeMap.get(parentId) + if (parentRoute) { + authorizedRoutes.add(parentId) + parentId = parentRoute.pid + } + else { + break + } + } + } + } + }) + + // 返回有权限的路由 + return routes.filter(route => authorizedRoutes.has(route.id)) } // render the returned routing table as a sidebar function transformAuthRoutesToMenus(userRoutes: AppRoute.Route[]) { - const { hasPermission } = usePermission() return userRoutes - // Filter out side menus without permission - .filter(i => hasPermission(i.meta.roles)) // Sort the menu according to the order size .sort((a, b) => { if (a.meta && a.meta.order && b.meta && b.meta.order) diff --git a/src/typings/service.d.ts b/src/typings/service.d.ts index ef0439e..d13ce3e 100644 --- a/src/typings/service.d.ts +++ b/src/typings/service.d.ts @@ -45,5 +45,21 @@ declare namespace Service { message: string /** 返回的数据 */ data: T + /** 错误信息别名 */ + msg?: string + } + + /** 分页结果类型 */ + interface PageResult { + /** 当前页数据 */ + records: T[] + /** 总记录数 */ + total: number + /** 当前页 */ + current: number + /** 每页大小 */ + size: number + /** 总页数 */ + pages: number } }