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);
}
}