From 161978b1beb91adea0b8649dde30cb7ff1ec64d3 Mon Sep 17 00:00:00 2001 From: dengqichen Date: Tue, 11 Nov 2025 10:09:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=93=E5=8D=B0=E4=BA=86JENKINS=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/RepositoryBranchApiController.java | 34 ++--- .../api/RepositoryProjectApiController.java | 34 ++--- .../api/ServerCategoryApiController.java | 4 +- .../system/api/DepartmentApiController.java | 17 ++- .../backend/system/api/MenuApiController.java | 25 ++++ .../backend/system/api/RoleApiController.java | 19 +-- .../system/api/RoleTagApiController.java | 39 ++---- .../system/api/TenantApiController.java | 34 ++--- .../backend/system/service/IRoleService.java | 16 ++- .../system/service/impl/RoleServiceImpl.java | 124 +++++++++++------- .../db/changelog/changes/v1.0.0-data.sql | 4 +- 11 files changed, 173 insertions(+), 177 deletions(-) diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryBranchApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryBranchApiController.java index ef7b917c..4379bdcf 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryBranchApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryBranchApiController.java @@ -13,6 +13,7 @@ import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -31,44 +32,25 @@ public class RepositoryBranchApiController extends BaseController create(RepositoryBranchDTO dto) { + public Response create(@Validated @RequestBody RepositoryBranchDTO dto) { return super.create(dto); } @Override - public Response update(Long aLong, RepositoryBranchDTO dto) { - return super.update(aLong, dto); + public Response update(@PathVariable Long id, @Validated @RequestBody RepositoryBranchDTO dto) { + return super.update(id, dto); } @Override - public Response delete(Long aLong) { - return super.delete(aLong); + public Response delete(@PathVariable Long id) { + return super.delete(id); } @Override - public Response findById(Long aLong) { - return super.findById(aLong); + public Response findById(@PathVariable Long id) { + return super.findById(id); } - @Override - public Response> findAll() { - return super.findAll(); - } - - @Override - public Response> page(RepositoryBranchQuery query) { - return super.page(query); - } - - @Override - public Response> findAll(RepositoryBranchQuery query) { - return super.findAll(query); - } - - @Override - public CompletableFuture> batchProcess(List dtos) { - return super.batchProcess(dtos); - } @Operation(summary = "同步Git分支", description = "异步同步,支持三种模式:1)只传externalSystemId-全量同步 2)传externalSystemId+repoGroupId-同步仓库组 3)传externalSystemId+repoGroupId+repoProjectId-同步单个项目") @PostMapping("/sync") diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryProjectApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryProjectApiController.java index a2afa9fb..f6627813 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryProjectApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryProjectApiController.java @@ -13,6 +13,7 @@ import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -31,44 +32,25 @@ public class RepositoryProjectApiController extends BaseController create(RepositoryProjectDTO dto) { + public Response create(@Validated @RequestBody RepositoryProjectDTO dto) { return super.create(dto); } @Override - public Response update(Long aLong, RepositoryProjectDTO dto) { - return super.update(aLong, dto); + public Response update(@PathVariable Long id, @Validated @RequestBody RepositoryProjectDTO dto) { + return super.update(id, dto); } @Override - public Response delete(Long aLong) { - return super.delete(aLong); + public Response delete(@PathVariable Long id) { + return super.delete(id); } @Override - public Response findById(Long aLong) { - return super.findById(aLong); + public Response findById(@PathVariable Long id) { + return super.findById(id); } - @Override - public Response> findAll() { - return super.findAll(); - } - - @Override - public Response> page(RepositoryProjectQuery query) { - return super.page(query); - } - - @Override - public Response> findAll(RepositoryProjectQuery query) { - return super.findAll(query); - } - - @Override - public CompletableFuture> batchProcess(List dtos) { - return super.batchProcess(dtos); - } @Operation(summary = "同步Git项目", description = "异步同步,支持两种模式:1)只传externalSystemId-全量同步 2)传externalSystemId+repoGroupId-同步单个仓库组") @PostMapping("/sync") diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/ServerCategoryApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/ServerCategoryApiController.java index 9752c6e0..6ef49bd2 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/ServerCategoryApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/ServerCategoryApiController.java @@ -11,6 +11,8 @@ import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -31,7 +33,7 @@ public class ServerCategoryApiController private IServerCategoryService serverCategoryService; @Override - public Response create(ServerCategoryDTO dto) { + public Response create(@Validated @RequestBody ServerCategoryDTO dto) { return super.create(dto); } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/system/api/DepartmentApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/system/api/DepartmentApiController.java index 9096541f..7585f022 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/system/api/DepartmentApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/system/api/DepartmentApiController.java @@ -12,7 +12,10 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import org.springframework.data.domain.Page; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -26,23 +29,23 @@ public class DepartmentApiController extends BaseController create(DepartmentDTO dto) { + public Response create(@Validated @RequestBody DepartmentDTO dto) { return super.create(dto); } @Override - public Response update(Long aLong, DepartmentDTO dto) { - return super.update(aLong, dto); + public Response update(@PathVariable Long id, @Validated @RequestBody DepartmentDTO dto) { + return super.update(id, dto); } @Override - public Response delete(Long aLong) { - return super.delete(aLong); + public Response delete(@PathVariable Long id) { + return super.delete(id); } @Override - public Response findById(Long aLong) { - return super.findById(aLong); + public Response findById(@PathVariable Long id) { + return super.findById(id); } @Override diff --git a/backend/src/main/java/com/qqchen/deploy/backend/system/api/MenuApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/system/api/MenuApiController.java index a5ee52f1..c79c3041 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/system/api/MenuApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/system/api/MenuApiController.java @@ -13,7 +13,11 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -28,6 +32,27 @@ public class MenuApiController extends BaseController create(@Validated @RequestBody MenuDTO dto) { + return super.create(dto); + } + + @Override + public Response update(@PathVariable Long id, @Validated @RequestBody MenuDTO dto) { + return super.update(id, dto); + } + + @Override + public Response delete(@PathVariable Long id) { + return super.delete(id); + } + + @Override + public Response findById(@PathVariable Long id) { + return super.findById(id); + } + + /** * 获取当前用户的菜单 */ diff --git a/backend/src/main/java/com/qqchen/deploy/backend/system/api/RoleApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/system/api/RoleApiController.java index a5bf9712..c177df40 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/system/api/RoleApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/system/api/RoleApiController.java @@ -6,6 +6,7 @@ import com.qqchen.deploy.backend.framework.controller.BaseController; import com.qqchen.deploy.backend.system.model.PermissionDTO; import com.qqchen.deploy.backend.system.model.RoleDTO; import com.qqchen.deploy.backend.system.model.query.RoleQuery; +import com.qqchen.deploy.backend.system.model.response.RoleMenusAndPermissionsResponse; import com.qqchen.deploy.backend.system.service.IRoleService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -72,21 +73,21 @@ public class RoleApiController extends BaseController> getRolePermissions( + @Operation(summary = "获取角色菜单和权限", description = "返回菜单ID列表和功能权限点ID列表") + @GetMapping("/{id}/menus-and-permissions") + public Response getRoleMenusAndPermissions( @Parameter(description = "角色ID", required = true) @PathVariable Long id ) { - return Response.success(roleService.listRolePermissions(id)); + return Response.success(roleService.getRoleMenusAndPermissions(id)); } - @Operation(summary = "分配权限") - @PostMapping("/{id}/permissions") - public Response assignPermissions( + @Operation(summary = "分配菜单和权限", description = "同时分配菜单和功能权限点,后端自动补全父菜单") + @PostMapping("/{id}/menus-and-permissions") + public Response assignMenusAndPermissions( @Parameter(description = "角色ID", required = true) @PathVariable Long id, - @Parameter(description = "权限ID列表", required = true) @RequestBody List permissionIds + @Parameter(description = "分配权限请求", required = true) @RequestBody com.qqchen.deploy.backend.system.model.request.AssignPermissionsRequest request ) { - roleService.assignPermissions(id, permissionIds); + roleService.assignMenusAndPermissions(id, request.getMenuIds(), request.getPermissionIds()); return Response.success(); } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/system/api/RoleTagApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/system/api/RoleTagApiController.java index 96d738fa..fcd384b9 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/system/api/RoleTagApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/system/api/RoleTagApiController.java @@ -10,6 +10,9 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import org.springframework.data.domain.Page; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -21,48 +24,26 @@ import java.util.concurrent.CompletableFuture; @RequestMapping("/api/v1/role-tag") public class RoleTagApiController extends BaseController { - @Resource - private IRoleTagService roleTagService; - @Override - public Response create(RoleTagDTO dto) { + public Response create(@Validated @RequestBody RoleTagDTO dto) { return super.create(dto); } @Override - public Response update(Long aLong, RoleTagDTO dto) { - return super.update(aLong, dto); + public Response update(@PathVariable Long id, @Validated @RequestBody RoleTagDTO dto) { + return super.update(id, dto); } @Override - public Response delete(Long aLong) { - return super.delete(aLong); + public Response delete(@PathVariable Long id) { + return super.delete(id); } @Override - public Response findById(Long aLong) { - return super.findById(aLong); + public Response findById(@PathVariable Long id) { + return super.findById(id); } - @Override - public Response> findAll() { - return super.findAll(); - } - - @Override - public Response> page(RoleTagQuery query) { - return super.page(query); - } - - @Override - public Response> findAll(RoleTagQuery query) { - return super.findAll(query); - } - - @Override - public CompletableFuture> batchProcess(List dtos) { - return super.batchProcess(dtos); - } @Override protected void exportData(HttpServletResponse response, List data) { diff --git a/backend/src/main/java/com/qqchen/deploy/backend/system/api/TenantApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/system/api/TenantApiController.java index 4b0ed1ce..80e40655 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/system/api/TenantApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/system/api/TenantApiController.java @@ -13,6 +13,7 @@ import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -37,44 +38,25 @@ public class TenantApiController extends BaseController create(TenantDTO dto) { + public Response create(@Validated @RequestBody TenantDTO dto) { return super.create(dto); } @Override - public Response update(Long aLong, TenantDTO dto) { - return super.update(aLong, dto); + public Response update(@PathVariable Long id, @Validated @RequestBody TenantDTO dto) { + return super.update(id, dto); } @Override - public Response delete(Long aLong) { - return super.delete(aLong); + public Response delete(@PathVariable Long id) { + return super.delete(id); } @Override - public Response findById(Long aLong) { - return super.findById(aLong); + public Response findById(@PathVariable Long id) { + return super.findById(id); } - @Override - public Response> findAll() { - return super.findAll(); - } - - @Override - public Response> page(TenantQuery query) { - return super.page(query); - } - - @Override - public Response> findAll(TenantQuery query) { - return super.findAll(query); - } - - @Override - public CompletableFuture> batchProcess(List dtos) { - return super.batchProcess(dtos); - } @Operation(summary = "获取状态") @GetMapping("/{id}/enabled") diff --git a/backend/src/main/java/com/qqchen/deploy/backend/system/service/IRoleService.java b/backend/src/main/java/com/qqchen/deploy/backend/system/service/IRoleService.java index 4706852a..d39c21ef 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/system/service/IRoleService.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/system/service/IRoleService.java @@ -5,6 +5,7 @@ import com.qqchen.deploy.backend.system.entity.Role; import com.qqchen.deploy.backend.system.model.RoleDTO; import com.qqchen.deploy.backend.system.model.PermissionDTO; import com.qqchen.deploy.backend.system.model.query.RoleQuery; +import com.qqchen.deploy.backend.system.model.response.RoleMenusAndPermissionsResponse; import java.util.List; @@ -31,12 +32,19 @@ public interface IRoleService extends IBaseService tagIds); /** - * 获取角色的权限列表 + * 获取角色的菜单和功能权限(两个维度) + * + * @param roleId 角色ID + * @return 包含菜单ID和权限点ID的响应对象 */ - List listRolePermissions(Long roleId); + RoleMenusAndPermissionsResponse getRoleMenusAndPermissions(Long roleId); /** - * 分配权限给角色 + * 分配菜单和功能权限给角色(两个维度) + * + * @param roleId 角色ID + * @param menuIds 菜单ID列表(后端会自动补全父菜单) + * @param permissionIds 功能权限点ID列表 */ - void assignPermissions(Long roleId, List permissionIds); + void assignMenusAndPermissions(Long roleId, List menuIds, List permissionIds); } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/system/service/impl/RoleServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/system/service/impl/RoleServiceImpl.java index 90edd2e2..007cb929 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/system/service/impl/RoleServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/system/service/impl/RoleServiceImpl.java @@ -14,6 +14,7 @@ import com.qqchen.deploy.backend.system.model.MenuDTO; import com.qqchen.deploy.backend.system.model.PermissionDTO; import com.qqchen.deploy.backend.system.model.RoleDTO; import com.qqchen.deploy.backend.system.model.query.RoleQuery; +import com.qqchen.deploy.backend.system.model.response.RoleMenusAndPermissionsResponse; import com.qqchen.deploy.backend.system.repository.IMenuRepository; import com.qqchen.deploy.backend.system.repository.IPermissionRepository; import com.qqchen.deploy.backend.system.repository.IRoleRepository; @@ -71,11 +72,11 @@ public class RoleServiceImpl extends BaseServiceImpl new BusinessException(ResponseCode.ROLE_NOT_FOUND)); - + if (Boolean.TRUE.equals(role.getIsAdmin())) { throw new BusinessException(ResponseCode.ROLE_ADMIN_CANNOT_DELETE); } - + // 调用父类的删除方法 super.delete(id); } @@ -122,67 +123,96 @@ public class RoleServiceImpl extends BaseServiceImpl listRolePermissions(Long roleId) { + public RoleMenusAndPermissionsResponse getRoleMenusAndPermissions(Long roleId) { Role role = roleRepository.findById(roleId) .orElseThrow(() -> new BusinessException(ResponseCode.ROLE_NOT_FOUND)); - List permissionDTOs = role.getPermissions().stream() - .map(permissionConverter::toDto) + // 获取菜单ID列表 + List menuIds = role.getMenus().stream() + .map(Menu::getId) + .sorted() .collect(Collectors.toList()); - // 批量填充菜单信息 - enrichWithMenuInfo(permissionDTOs); - - return permissionDTOs; - } - - /** - * 为权限DTO列表批量填充菜单信息 - */ - private void enrichWithMenuInfo(List permissionDTOs) { - if (permissionDTOs == null || permissionDTOs.isEmpty()) { - return; - } - - // 收集所有菜单ID - List menuIds = permissionDTOs.stream() - .map(PermissionDTO::getMenuId) - .filter(id -> id != null) - .distinct() + // 获取功能权限点ID列表 + List permissionIds = role.getPermissions().stream() + .map(Permission::getId) + .sorted() .collect(Collectors.toList()); - if (menuIds.isEmpty()) { - return; - } - - // 批量查询菜单并转换为DTO - Map menuMap = menuRepository.findAllById(menuIds).stream() - .map(menuConverter::toDto) - .collect(Collectors.toMap(MenuDTO::getId, menu -> menu)); - - // 填充菜单信息 - permissionDTOs.forEach(dto -> { - if (dto.getMenuId() != null) { - dto.setMenu(menuMap.get(dto.getMenuId())); - } - }); + return new com.qqchen.deploy.backend.system.model.response.RoleMenusAndPermissionsResponse(menuIds, permissionIds); } @Override @Transactional - public void assignPermissions(Long roleId, List permissionIds) { + public void assignMenusAndPermissions(Long roleId, List menuIds, List permissionIds) { Role role = roleRepository.findById(roleId) .orElseThrow(() -> new BusinessException(ResponseCode.ROLE_NOT_FOUND)); - Set permissions = permissionRepository.findByIdIn(permissionIds) - .stream() - .collect(Collectors.toSet()); - - if (permissions.size() != permissionIds.size()) { - throw new BusinessException(ResponseCode.PERMISSION_NOT_FOUND); + // 1. 处理菜单维度:自动补全父菜单 + if (menuIds != null && !menuIds.isEmpty()) { + // 一次性查询所有菜单,避免N+1查询 + List allMenus = menuRepository.findByDeletedFalseOrderBySort(); + Map menuMap = allMenus.stream() + .collect(Collectors.toMap(Menu::getId, menu -> menu)); + + // 验证请求的菜单是否存在 + for (Long menuId : menuIds) { + if (!menuMap.containsKey(menuId)) { + throw new BusinessException(ResponseCode.DATA_NOT_FOUND); + } + } + + // 在内存中递归补全父菜单ID + Set completeMenuIds = new HashSet<>(menuIds); + for (Long menuId : menuIds) { + addParentMenuIdsFromMap(completeMenuIds, menuId, menuMap); + } + + // 根据补全后的ID获取菜单对象 + Set menus = completeMenuIds.stream() + .map(menuMap::get) + .filter(menu -> menu != null) + .collect(Collectors.toSet()); + + role.setMenus(menus); + + log.info("角色[{}]分配菜单完成,原始菜单数:{},补全后菜单数:{}", + roleId, menuIds.size(), completeMenuIds.size()); + } else { + role.setMenus(new HashSet<>()); + } + + // 2. 处理功能权限点维度 + if (permissionIds != null && !permissionIds.isEmpty()) { + Set permissions = permissionRepository.findByIdIn(permissionIds) + .stream() + .collect(Collectors.toSet()); + + if (permissions.size() != permissionIds.size()) { + throw new BusinessException(ResponseCode.PERMISSION_NOT_FOUND); + } + + role.setPermissions(permissions); + log.info("角色[{}]分配功能权限完成,权限点数:{}", roleId, permissionIds.size()); + } else { + role.setPermissions(new HashSet<>()); } - role.setPermissions(permissions); roleRepository.save(role); } + + /** + * 在内存中递归添加所有父菜单ID(优化版,避免数据库查询) + * @param menuIds 菜单ID集合 + * @param menuId 当前菜单ID + * @param menuMap 所有菜单的Map + */ + private void addParentMenuIdsFromMap(Set menuIds, Long menuId, Map menuMap) { + Menu menu = menuMap.get(menuId); + if (menu != null && menu.getParentId() != null) { + menuIds.add(menu.getParentId()); + // 递归查找父菜单的父菜单 + addParentMenuIdsFromMap(menuIds, menu.getParentId(), menuMap); + } + } } \ No newline at end of file diff --git a/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql b/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql index 52c0598b..2ff451be 100644 --- a/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql +++ b/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql @@ -144,8 +144,8 @@ INSERT INTO sys_role_menu (role_id, menu_id) VALUES -- 运维拥有工作台、运维管理和资源管理权限 (2, 99), (2, 200), (2, 201), (2, 202), (2, 203), (2, 204), (2, 205), (2, 300), (2, 301), (2, 302), (2, 303), (2, 304), --- 开发拥有工作台、工作流子菜单和应用管理(不包含父菜单) -(3, 99), (3, 101), (3, 102), (3, 104), (3, 202); +-- 开发拥有工作台、工作流管理及子菜单、运维管理及应用管理(后端自动补全父菜单,但显式声明更清晰) +(3, 99), (3, 100), (3, 101), (3, 102), (3, 104), (3, 200), (3, 202); -- ==================== 初始化权限数据 ==================== DELETE FROM sys_permission WHERE id < 10000;