package com.yunhai.userbase.controller.api; import com.yunhai.userbase.common.annotation.OperationLog; import com.yunhai.userbase.config.Config; import com.yunhai.userbase.model.groupauthz.GroupAppAssignRequest; import com.yunhai.userbase.model.groupauthz.GroupAppVo; import com.yunhai.userbase.model.groupauthz.GroupAuthzAppVo; import com.yunhai.userbase.model.groupauthz.GroupAuthzCategoryVo; import com.yunhai.userbase.model.groupauthz.GroupModuleAuthzItem; import com.yunhai.userbase.model.groupauthz.GroupModulePermRequest; import com.yunhai.userbase.model.groupauthz.SchoolAppAuthzRequest; import com.yunhai.userbase.model.groupauthz.UserGroupNodeVo; import com.yunhai.userbase.model.groupauthz.UserPermissionCategoryVo; import com.yunhai.userbase.model.groupauthz.UserPermissionUserVo; import com.yunhai.userbase.model.groupauthz.UserRoleVo; import com.yunhai.userbase.service.IGroupAuthzService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import javax.validation.Valid; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * @author chenx * @date 2026/7/23 * @description 组应用权限管理(应用开通 + 组授权 + 权限判定)。
* 左侧组树复用 /sysgroup/GetTree;本控制器提供右侧数据加载与保存接口。
*/ @RestController @RequestMapping(value = Config.API_PATH + "/groupauthz/") public class GroupAuthzController { @Autowired private IGroupAuthzService groupAuthzService; /** * 功能1回显:点击左侧组后,返回系统全量应用列表,已开通的 checked=true。 */ @GetMapping("/GroupAppList") public List groupAppList(@RequestParam Integer groupId) { return groupAuthzService.listGroupApps(groupId); } /** * 功能1保存:全量覆盖式更新该组的应用开通记录。 */ @OperationLog("保存组应用开通") @PostMapping("AssignApps") public void assignApps(@RequestBody @Validated GroupAppAssignRequest request) { groupAuthzService.assignAppsToGroup(request); } /** * 功能2数据加载:返回该组已开通的应用及其模块权限树(含勾选与子组继承回显)。 */ @GetMapping("/GroupModuleTree") public List groupModuleTree(@RequestParam Integer groupId) { return groupAuthzService.findGroupAppsWithModules(groupId); } /** * 功能2数据加载(按应用分类分组):供组授权页面按分类面板展示,
* 返回全部分类及该组已开通的应用模块权限树。 */ @GetMapping("/GroupModuleTreeByCategory") public List groupModuleTreeByCategory(@RequestParam Integer groupId) { return groupAuthzService.findGroupAppsWithModulesByCategory(groupId); } /** * 功能2保存:全量覆盖式更新该组的模块权限(含子组继承开关)。 */ @OperationLog("保存组模块权限") @PostMapping("SaveModulePerms") public void saveModulePerms(@RequestBody @Validated GroupModulePermRequest request) { groupAuthzService.saveModulePermissions(request); } /** * 权限判定:判断用户对某模块是否有权限(供登录/拦截器/联调验证使用)。 */ @GetMapping("/HasModulePerm") public boolean hasModulePerm(@RequestParam Integer userId, @RequestParam Integer moduleId) { return groupAuthzService.hasModulePermission(userId, moduleId); } /** * 权限一览:根据组ID获取该组下的直接用户列表(不含子组,不分页)。 */ @GetMapping("/GroupUsers") public List groupUsers(@RequestParam Integer groupId) { return groupAuthzService.findGroupUsers(groupId); } /** * 权限一览:全局搜索用户(按账号/姓名/身份证模糊、手机号精确匹配),不分页。
* 返回用户及其主归属部门/组织路径,供左侧用户搜索形态展示。 */ @GetMapping("/SearchUsers") public List searchUsers(@RequestParam String keyword) { return groupAuthzService.searchUsers(keyword); } /** * 权限一览:根据用户ID聚合该用户的全部已授权应用模块树。
* 只返回有授权模块的应用,并按应用类型分组;无授权的应用类型和应用不显示。
* 角色授权并集:结果 = 组授权模块 ∪ 启用角色授权模块(角色模块不要求组先开通应用)。 */ @GetMapping("/UserPermissionTree") public List userPermissionTree(@RequestParam Integer userId, @RequestParam(required = false) Integer groupId) { return groupAuthzService.findUserPermissionTree(groupId, userId); } /** * 权限一览:查询用户所属的业务角色列表(中间下方「所属角色」区域展示用)。
* 返回该用户绑定的全部角色(含禁用角色,disabled 字段标记),普通角色回填所属应用名称。 */ @GetMapping("/UserRoles") public List userRoles(@RequestParam Integer userId) { return groupAuthzService.findUserRoles(userId); } /** * 权限一览:查询用户所属部门树(左侧上方「所属部门」区域展示用)。
* 树仅由「用户直接归属的组 + 其全部祖先组」构成(如:云平台-学校中学-语文组)。 */ @GetMapping("/UserGroupTree") public List userGroupTree(@RequestParam Integer userId) { return groupAuthzService.findUserGroupTree(userId); } // ===================== 新增:树节点式增量授权(左侧树 + 右侧 appAuthzList 勾选交互) ===================== /** * 功能3回显:点击左侧树节点后,返回该组「已开通的应用ID列表」,供右侧 AppSettings.appAuthzList 回显勾选状态。
* 交互:左树节点 → 右 appAuthzList(全量应用)→ 本接口拿到已选 id → 前端把对应多选框置为勾选。
* 实现:应用开通不继承,直接查 sys_group_app_rel(group_id=nodeId) 返回 app_id 列表(详见 service.findAuthorizedAppIds)。
* 与 GroupAppList(返回全量应用+checked)互为补充:本接口更轻量,只给 id 集合。 */ @GetMapping("/GetSchoolAppId") public List getSchoolAppId(@RequestParam Integer nodeId) { return groupAuthzService.findAuthorizedAppIds(nodeId); } /** * 功能3保存(应用维):点击应用多选框触发,对该组做应用开通/取消。
* 入参(请求体,JSON):{@link SchoolAppAuthzRequest} —— schid=组ID(nodeId);appid=单个应用ID(一次只传一个,逐次点击);mode=操作模式。
* mode 语义(SysModeEnum):0=追加(开通应用) / 2=删除(取消开通);1=覆盖 不适用,会被拒绝。
* 实现:应用开通不继承,仅操作本组;删除时同步清理该组在该应用下模块的权限残留(详见 service.setSchoolApps)。
* 注意:appid 为单个 Integer,后端不再做多值/逗号解析;每次点击提交一次请求。 */ @OperationLog("设置组应用开通") @PostMapping("SetSchoolApp") public void setSchoolApp(@RequestBody @Valid SchoolAppAuthzRequest request) { groupAuthzService.setSchoolApps(request); } /** * 功能4保存(模块维):前端「组授权」面板逐条勾选/取消时提交,对 (组,应用,模块) 做增量授权/取消。
* 入参:请求体为数组,元素见 {@link GroupModuleAuthzItem}:{groupId, appId, moduleId, mode, isAll}。
* mode:0=追加 / 2=删除(1=覆盖不适用)。
* isAll:是否对子组继承,映射 sys_group_module_perm.inherit_flag(1=子孙组自动继承 / 0=仅本组)。
* moduleId=0:表示「该应用下全部模块」,后端展开为应用下每个真实模块各写/删一条。
* 实现:逐条处理、顺序即执行顺序;追加前要求该组已开通该应用;越权写别的应用模块会被拒绝(详见 service.setGroupModulePerms)。
* 与现有 SaveModulePerms(全量覆盖)共存:本接口是单条增量,二者操作同一张表、互不冲突。 */ @OperationLog("设置组模块权限") @PostMapping("SetGroupModule") public void setGroupModule(@RequestBody @Valid List items) { groupAuthzService.setGroupModulePerms(items); } }