feat(admin): 选人教师树(仿 Notice GetSchoolAll)——组树剔除学生组, YschClassOpenApi.getSchTeaList 按 GroupIds 挂组+空组剪枝 (GET /admin/user/teacherTree); 管理端新增 /def/diagram.png 示意图页进度图 <img> 直嵌
build / build-push (push) Successful in 46s
build / build-push (push) Successful in 46s
This commit is contained in:
@@ -18,6 +18,8 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -45,6 +47,7 @@ public class FlowAdminController {
|
||||
private final FlowCallbackAdminService callbackAdminService;
|
||||
private final FlwInstanceRepository instanceRepository;
|
||||
private final FlowDiagramService diagramService;
|
||||
private final com.yunhai.flowcenter.service.DiagramImageService imageService;
|
||||
|
||||
// ==================== 流程定义 ====================
|
||||
|
||||
@@ -93,6 +96,21 @@ public class FlowAdminController {
|
||||
return diagramService.build(def, null, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程定义示意图 PNG 流(2026-09-17,示意图页"进度图"视图):<img> 直嵌走同域 CAS 会话,
|
||||
* 可见性与 /def/diagram 同口径(requireAdmin)。
|
||||
*/
|
||||
@GetMapping("/def/diagram.png")
|
||||
public ResponseEntity<byte[]> defDiagramPng(BoaUser user, @RequestParam("id") Long id,
|
||||
@RequestParam(value = "mode", required = false) String mode) {
|
||||
Long schId = adminGuard.requireAdmin(user, null);
|
||||
FlwDef def = defAdminService.get(schId, id);
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.IMAGE_PNG)
|
||||
.cacheControl(org.springframework.http.CacheControl.noStore())
|
||||
.body(imageService.renderPng(diagramService.build(def, null, mode)));
|
||||
}
|
||||
|
||||
// ==================== 办理人映射 ====================
|
||||
|
||||
@GetMapping("/map/list")
|
||||
@@ -146,6 +164,15 @@ public class FlowAdminController {
|
||||
return mapAdminService.userTree(adminGuard.requireAdmin(user, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 选人组件树·教师版(2026-09-17,仿 Notice /api/base/GetSchoolAll):组树骨架(剔除学生组)+
|
||||
* userclass 教师按 GroupIds 挂组,管理端「选择用户」统一走它。
|
||||
*/
|
||||
@GetMapping("/user/teacherTree")
|
||||
public List<FlowMapAdminService.SelectUserNodeVo> teacherTree(BoaUser user) {
|
||||
return mapAdminService.teacherTree(adminGuard.requireAdmin(user, null));
|
||||
}
|
||||
|
||||
// ==================== 回调注册/推送日志/死信 ====================
|
||||
|
||||
@GetMapping("/callback/regList")
|
||||
|
||||
@@ -18,7 +18,9 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 办理人映射管理(概览 §4.7/§六):DEPT_KEY → 办理人显式映射,成员检索经
|
||||
@@ -42,6 +44,9 @@ public class FlowMapAdminService {
|
||||
@Value("${flow-center.map.dept-group-type:7}")
|
||||
private int deptGroupType = 7;
|
||||
|
||||
/** 学生组(UserBase GroupTypeEnum.STUDENT_GROUP),选人组树中整棵剔除(口径同 Notice) */
|
||||
private static final int GROUP_TYPE_STUDENT = 8;
|
||||
|
||||
public List<FlwAssigneeMap> listByDept(Long schId, String deptKey) {
|
||||
if (deptKey == null || deptKey.trim().isEmpty()) {
|
||||
return mapRepository.findEnabledBySchId(schId);
|
||||
@@ -152,6 +157,118 @@ public class FlowMapAdminService {
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 选人组件树·教师版(2026-09-17 仿 Notice GetSchoolAll 口径):组树只做骨架(剔除学生组),
|
||||
* 成员来自 userclass(YschClassOpenApi.getSchTeaList)的教师列表,按教师所属 GroupIds 挂组。
|
||||
* 组内 getGroupUsers 不再混入——旧实现会把管理员等非教师账号挂进树(选人数据不对的根因)。
|
||||
* 空组(无教师)剪枝;教师归属组全被剔除时挂学校根节点。
|
||||
*/
|
||||
public List<SelectUserNodeVo> teacherTree(Long schId) {
|
||||
BoaGroup subtree;
|
||||
try {
|
||||
subtree = groupClient.getGroupById(schId.intValue(), true);
|
||||
} catch (Exception e) {
|
||||
throw new BizException(ErrorCode.PARAM_ERROR, "UserBase 组树不可达:" + e.getMessage());
|
||||
}
|
||||
if (subtree == null || subtree.getId() == null) {
|
||||
throw new BizException(ErrorCode.PARAM_ERROR, "学校组不存在(schId=" + schId + ")");
|
||||
}
|
||||
// 扁平化组(剔除学生组整棵),组节点先建壳 isParent=true
|
||||
Map<Integer, SelectUserNodeVo> groups = new LinkedHashMap<>();
|
||||
List<BoaGroup> flat = new ArrayList<>();
|
||||
flattenGroups(subtree, flat);
|
||||
for (BoaGroup g : flat) {
|
||||
SelectUserNodeVo vo = new SelectUserNodeVo();
|
||||
vo.setId(g.getId());
|
||||
vo.setName(g.getName() == null ? "" : g.getName());
|
||||
vo.setIsParent(true);
|
||||
groups.put(g.getId(), vo);
|
||||
}
|
||||
// 教师挂组;同一 (教师, 组) 去重,归属组全不在树内时兜底挂根
|
||||
try {
|
||||
List<com.yunhai.platform.openapi.clazz.model.SchTea> teachers =
|
||||
com.yunhai.platform.openapi.clazz.YschClassOpenApi.getSchTeaList(schId.intValue());
|
||||
if (teachers != null) {
|
||||
for (com.yunhai.platform.openapi.clazz.model.SchTea tea : teachers) {
|
||||
if (tea == null || tea.getUserTeaSerId() == null) {
|
||||
continue;
|
||||
}
|
||||
SelectUserNodeVo leaf = new SelectUserNodeVo();
|
||||
leaf.setId(tea.getUserTeaSerId());
|
||||
leaf.setName(tea.getTeaName() == null ? "" : tea.getTeaName());
|
||||
List<Integer> gids = tea.getGroupIds();
|
||||
if ((gids == null || gids.isEmpty()) && tea.getGroupId() != null) {
|
||||
gids = Collections.singletonList(tea.getGroupId());
|
||||
}
|
||||
boolean attached = false;
|
||||
if (gids != null) {
|
||||
for (Integer gid : gids) {
|
||||
SelectUserNodeVo g = groups.get(gid);
|
||||
if (g != null) {
|
||||
g.getChildren().add(leaf);
|
||||
attached = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!attached) {
|
||||
SelectUserNodeVo root = groups.get(schId.intValue());
|
||||
if (root != null) {
|
||||
root.getChildren().add(leaf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("[flow-center] 教师列表拉取失败(schId={}):{}", schId, e.getMessage());
|
||||
}
|
||||
// 建父子结构并剪空组(无教师后代的组不进树,根始终保留)
|
||||
for (BoaGroup g : flat) {
|
||||
for (BoaGroup child : g.getChildren() == null ? Collections.<BoaGroup>emptyList() : g.getChildren()) {
|
||||
SelectUserNodeVo childVo = child == null ? null : groups.get(child.getId());
|
||||
if (childVo != null && groups.containsKey(g.getId())) {
|
||||
groups.get(g.getId()).getChildren().add(childVo);
|
||||
}
|
||||
}
|
||||
}
|
||||
SelectUserNodeVo root = groups.get(schId.intValue());
|
||||
if (root == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
pruneEmpty(root);
|
||||
return Collections.singletonList(root);
|
||||
}
|
||||
|
||||
/** 组子树扁平化;学生组(type=8)整棵剔除(含其后代) */
|
||||
private void flattenGroups(BoaGroup group, List<BoaGroup> out) {
|
||||
if (group == null || group.getId() == null) {
|
||||
return;
|
||||
}
|
||||
if (group.getType() != null && group.getType() == GROUP_TYPE_STUDENT) {
|
||||
return;
|
||||
}
|
||||
out.add(group);
|
||||
for (BoaGroup child : group.getChildren() == null ? Collections.<BoaGroup>emptyList() : group.getChildren()) {
|
||||
flattenGroups(child, out);
|
||||
}
|
||||
}
|
||||
|
||||
/** 剪掉无教师叶子后代(isParent 组但 children 全空)的组节点;返回该子树是否仍有内容 */
|
||||
private boolean pruneEmpty(SelectUserNodeVo node) {
|
||||
List<SelectUserNodeVo> kept = new ArrayList<>();
|
||||
for (SelectUserNodeVo child : node.getChildren() == null ? new ArrayList<SelectUserNodeVo>() : node.getChildren()) {
|
||||
if (child.getIsParent() != null && child.getIsParent()) {
|
||||
if (pruneEmpty(child)) {
|
||||
kept.add(child);
|
||||
}
|
||||
} else {
|
||||
kept.add(child);
|
||||
}
|
||||
}
|
||||
node.getChildren().clear();
|
||||
node.getChildren().addAll(kept);
|
||||
return Boolean.TRUE.equals(node.getIsParent()) && !node.getChildren().isEmpty();
|
||||
}
|
||||
|
||||
// ==================== 一键拉取教师组 ====================
|
||||
|
||||
/** 科室预览/导入项(deptKey=UserBase 组 id) */
|
||||
|
||||
Reference in New Issue
Block a user