- 新增 sys_group.include_children(1=部门列表含下级部门 / 0=仅本级,默认 1),仅学校节点使用
- 实体 / Vo / Repository / Service / Controller 全链路打通:单列 UPDATE + 发布 GroupChangedEvent 驱逐 groupSnapshot 缓存
- 新端点 POST /api/sysgroup/SetIncludeChildren/{id},权限只用 requireGroupInScope
(不能用 requireGroupModifiable:后者禁止 SCHOOL 级操作学校组本身,而本属性正是学校管理员要改的本校属性)
- deploy/sql/20261021_add_sys_group_include_children.sql 提供幂等 DDL,需在 160 手工执行
This commit is contained in:
@@ -4,6 +4,7 @@ import com.yunhai.userbase.common.annotation.OperationLog;
|
||||
import com.yunhai.userbase.common.validation.ValidationGroups;
|
||||
import com.yunhai.userbase.config.Config;
|
||||
import com.yunhai.userbase.model.sysgroup.SysGroupBatchRequest;
|
||||
import com.yunhai.userbase.model.sysgroup.SysGroupIncludeChildrenRequest;
|
||||
import com.yunhai.userbase.model.sysgroup.SysGroupMoveRequest;
|
||||
import com.yunhai.userbase.model.sysgroup.SysGroupQuery;
|
||||
import com.yunhai.userbase.model.sysgroup.SysGroupRequest;
|
||||
@@ -90,6 +91,21 @@ public class SysGroupController {
|
||||
sysGroupService.changeStatus(id, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置「包含子组」(2026-10-21 部门线):该学校在部门管理页是否连同下级部门一起列出。<br>
|
||||
* 单列 UPDATE sys_group.include_children,不碰其他列与表。<br>
|
||||
* 权限<b>只用</b> {@code requireGroupInScope}:不能加 {@code requireGroupModifiable}——
|
||||
* 后者禁止 SCHOOL 级操作学校组本身,而本属性恰恰是学校管理员必须能改的本校属性。
|
||||
*/
|
||||
@OperationLog("设置包含子组")
|
||||
@Operation(operationId = "sysGroupSetIncludeChildren")
|
||||
@PostMapping("SetIncludeChildren/{id}")
|
||||
public void setIncludeChildren(@PathVariable Integer id,
|
||||
@RequestBody @Validated SysGroupIncludeChildrenRequest request) {
|
||||
accessScopeService.requireGroupInScope(id);
|
||||
sysGroupService.changeIncludeChildren(id, Boolean.TRUE.equals(request.getIncludeChildren()));
|
||||
}
|
||||
|
||||
@Operation(operationId = "sysGroupList")
|
||||
@GetMapping("/List")
|
||||
public List<SysGroupVo> list(SysGroupQuery query) {
|
||||
|
||||
@@ -41,6 +41,13 @@ public class SysGroup extends BaseEntity {
|
||||
@Column(name = "status")
|
||||
private Integer status = 0;
|
||||
|
||||
/**
|
||||
* 包含子组(2026-10-21 部门线):1=部门列表含下级部门 / 0=仅一级部门,仅学校节点使用。<br>
|
||||
* 与 status 同为节点自身属性,翻转只允许走 {@code updateIncludeChildren} 单列 UPDATE。
|
||||
*/
|
||||
@Column(name = "include_children")
|
||||
private Integer includeChildren = 1;
|
||||
|
||||
|
||||
// 一对多反向关联中间表
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.yunhai.userbase.model.sysgroup;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author chenx
|
||||
* @date 2026/10/21
|
||||
* @description 设置「包含子组」请求:该校在部门管理页是否连同下级部门一起列出。<br>
|
||||
* 仅学校节点使用;true=含子组(1)/ false=仅本级(0)。
|
||||
*/
|
||||
@Data
|
||||
public class SysGroupIncludeChildrenRequest {
|
||||
|
||||
/** 是否包含子组。 */
|
||||
@NotNull(message = "includeChildren 不能为空")
|
||||
private Boolean includeChildren;
|
||||
}
|
||||
@@ -18,6 +18,8 @@ public class SysGroupVo {
|
||||
private Integer sort;
|
||||
/** 启停状态(2026-10-20 部门线 P0):0=启用 / 1=停用;BeanUtils 同名拷贝,null 视为 0 由前端兜底 */
|
||||
private Integer status;
|
||||
/** 包含子组(2026-10-21):1=部门列表含下级部门 / 0=仅本级;BeanUtils 同名拷贝,null 视为 1 由前端兜底 */
|
||||
private Integer includeChildren;
|
||||
/** 子组(递归);默认空列表,避免 JSON 序列化出现 null。 */
|
||||
private List<SysGroupVo> children = new ArrayList<>();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,14 @@ public interface SysGroupRepository extends JpaRepository<SysGroup, Integer>, Jp
|
||||
@Query("UPDATE SysGroup g SET g.status = :status WHERE g.id = :id")
|
||||
int updateStatus(@Param("id") Integer id, @Param("status") Integer status);
|
||||
|
||||
/**
|
||||
* 「包含子组」单列 UPDATE(2026-10-21 部门线):与 {@link #updateStatus} 同语义,
|
||||
* 严格只动 sys_group.include_children 一列,不触发实体监听器与审计列。
|
||||
*/
|
||||
@Modifying
|
||||
@Query("UPDATE SysGroup g SET g.includeChildren = :includeChildren WHERE g.id = :id")
|
||||
int updateIncludeChildren(@Param("id") Integer id, @Param("includeChildren") Integer includeChildren);
|
||||
|
||||
@Query("SELECT MAX(g.sort) FROM SysGroup g")
|
||||
Integer findMaxSort();
|
||||
|
||||
|
||||
@@ -37,6 +37,15 @@ public interface ISysGroupService {
|
||||
*/
|
||||
void changeStatus(Integer id, boolean disabled);
|
||||
|
||||
/**
|
||||
* 设置「包含子组」(2026-10-21 部门线):单列 UPDATE sys_group.include_children,不碰其他任何表与列。<br>
|
||||
* 仅学校节点使用,语义是「部门管理页的部门列表是否连同下级部门一起展示」。
|
||||
*
|
||||
* @param id 学校组ID
|
||||
* @param include true=含子组(1)/ false=仅本级(0)
|
||||
*/
|
||||
void changeIncludeChildren(Integer id, boolean include);
|
||||
|
||||
/**
|
||||
* 开放接口专用:在学校(组)范围内删除组。<br>
|
||||
* 与 {@link #delete(Integer)} 删除逻辑一致,但额外强制边界:<br>
|
||||
|
||||
@@ -249,6 +249,24 @@ public class SysGroupService implements ISysGroupService {
|
||||
eventPublisher.publishEvent(new GroupChangedEvent(this, "changeStatus"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 「包含子组」翻转(2026-10-21 部门线):严格单列 UPDATE,范式与 {@link #changeStatus} 完全一致。<br>
|
||||
* 必须发 {@link GroupChangedEvent}:GetTree / oapi 组树都吃 groupSnapshot 缓存,
|
||||
* 不发则页面读到的 includeChildren 最多滞后 30min。
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void changeIncludeChildren(Integer id, boolean include) {
|
||||
if (id == null || sysGroupRepository.findById(id).orElse(null) == null) {
|
||||
throw new DException("系统组不存在");
|
||||
}
|
||||
int updated = sysGroupRepository.updateIncludeChildren(id, include ? 1 : 0);
|
||||
if (updated == 0) {
|
||||
throw new DException("系统组不存在");
|
||||
}
|
||||
eventPublisher.publishEvent(new GroupChangedEvent(this, "changeIncludeChildren"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void delete(Integer id, Integer schoolId) {
|
||||
|
||||
Reference in New Issue
Block a user