From bf3f3344c1dd9e452caf9bce5b8df3de5e21058b Mon Sep 17 00:00:00 2001 From: chenxing Date: Wed, 21 Oct 2026 15:12:29 +0800 Subject: [PATCH] =?UTF-8?q?feat(dept):=20sys=5Fgroup=20=E5=A2=9E=E5=88=97?= =?UTF-8?q?=20include=5Fchildren=EF=BC=8C=E6=94=AF=E6=8C=81=E3=80=8C?= =?UTF-8?q?=E5=8C=85=E5=90=AB=E5=AD=90=E7=BB=84=E3=80=8D=E8=90=BD=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 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 手工执行 --- .../controller/api/SysGroupController.java | 16 ++++++++++++++++ .../com/yunhai/userbase/entity/SysGroup.java | 7 +++++++ .../SysGroupIncludeChildrenRequest.java | 19 +++++++++++++++++++ .../userbase/model/sysgroup/SysGroupVo.java | 2 ++ .../repository/SysGroupRepository.java | 8 ++++++++ .../userbase/service/ISysGroupService.java | 9 +++++++++ .../service/impl/SysGroupService.java | 18 ++++++++++++++++++ 7 files changed, 79 insertions(+) create mode 100644 src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupIncludeChildrenRequest.java diff --git a/src/main/java/com/yunhai/userbase/controller/api/SysGroupController.java b/src/main/java/com/yunhai/userbase/controller/api/SysGroupController.java index bcbee13..fe1cdb9 100644 --- a/src/main/java/com/yunhai/userbase/controller/api/SysGroupController.java +++ b/src/main/java/com/yunhai/userbase/controller/api/SysGroupController.java @@ -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 部门线):该学校在部门管理页是否连同下级部门一起列出。
+ * 单列 UPDATE sys_group.include_children,不碰其他列与表。
+ * 权限只用 {@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 list(SysGroupQuery query) { diff --git a/src/main/java/com/yunhai/userbase/entity/SysGroup.java b/src/main/java/com/yunhai/userbase/entity/SysGroup.java index b1d3ba7..7612c24 100644 --- a/src/main/java/com/yunhai/userbase/entity/SysGroup.java +++ b/src/main/java/com/yunhai/userbase/entity/SysGroup.java @@ -41,6 +41,13 @@ public class SysGroup extends BaseEntity { @Column(name = "status") private Integer status = 0; + /** + * 包含子组(2026-10-21 部门线):1=部门列表含下级部门 / 0=仅一级部门,仅学校节点使用。
+ * 与 status 同为节点自身属性,翻转只允许走 {@code updateIncludeChildren} 单列 UPDATE。 + */ + @Column(name = "include_children") + private Integer includeChildren = 1; + // 一对多反向关联中间表 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) diff --git a/src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupIncludeChildrenRequest.java b/src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupIncludeChildrenRequest.java new file mode 100644 index 0000000..7bd7f70 --- /dev/null +++ b/src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupIncludeChildrenRequest.java @@ -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 设置「包含子组」请求:该校在部门管理页是否连同下级部门一起列出。
+ * 仅学校节点使用;true=含子组(1)/ false=仅本级(0)。 + */ +@Data +public class SysGroupIncludeChildrenRequest { + + /** 是否包含子组。 */ + @NotNull(message = "includeChildren 不能为空") + private Boolean includeChildren; +} diff --git a/src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupVo.java b/src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupVo.java index 071c55f..2bf51f8 100644 --- a/src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupVo.java +++ b/src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupVo.java @@ -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 children = new ArrayList<>(); } diff --git a/src/main/java/com/yunhai/userbase/repository/SysGroupRepository.java b/src/main/java/com/yunhai/userbase/repository/SysGroupRepository.java index 295bb34..9797635 100644 --- a/src/main/java/com/yunhai/userbase/repository/SysGroupRepository.java +++ b/src/main/java/com/yunhai/userbase/repository/SysGroupRepository.java @@ -25,6 +25,14 @@ public interface SysGroupRepository extends JpaRepository, 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(); diff --git a/src/main/java/com/yunhai/userbase/service/ISysGroupService.java b/src/main/java/com/yunhai/userbase/service/ISysGroupService.java index b16b241..f6f01b8 100644 --- a/src/main/java/com/yunhai/userbase/service/ISysGroupService.java +++ b/src/main/java/com/yunhai/userbase/service/ISysGroupService.java @@ -37,6 +37,15 @@ public interface ISysGroupService { */ void changeStatus(Integer id, boolean disabled); + /** + * 设置「包含子组」(2026-10-21 部门线):单列 UPDATE sys_group.include_children,不碰其他任何表与列。
+ * 仅学校节点使用,语义是「部门管理页的部门列表是否连同下级部门一起展示」。 + * + * @param id 学校组ID + * @param include true=含子组(1)/ false=仅本级(0) + */ + void changeIncludeChildren(Integer id, boolean include); + /** * 开放接口专用:在学校(组)范围内删除组。
* 与 {@link #delete(Integer)} 删除逻辑一致,但额外强制边界:
diff --git a/src/main/java/com/yunhai/userbase/service/impl/SysGroupService.java b/src/main/java/com/yunhai/userbase/service/impl/SysGroupService.java index 3404f05..51a1519 100644 --- a/src/main/java/com/yunhai/userbase/service/impl/SysGroupService.java +++ b/src/main/java/com/yunhai/userbase/service/impl/SysGroupService.java @@ -249,6 +249,24 @@ public class SysGroupService implements ISysGroupService { eventPublisher.publishEvent(new GroupChangedEvent(this, "changeStatus")); } + /** + * 「包含子组」翻转(2026-10-21 部门线):严格单列 UPDATE,范式与 {@link #changeStatus} 完全一致。
+ * 必须发 {@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) {