diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/controller/DqInspectProblemController.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/controller/DqInspectProblemController.java index 11b26c7..3c1b7a0 100644 --- a/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/controller/DqInspectProblemController.java +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/controller/DqInspectProblemController.java @@ -193,6 +193,18 @@ public class DqInspectProblemController extends JeecgController>> parentOptions(@RequestParam(name = "nodeType") String nodeType) { + return Result.OK(dqInspectProblemService.queryParentOptions(nodeType)); + } + /** * 添加 * diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/service/IDqInspectProblemService.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/service/IDqInspectProblemService.java index d53b852..6645066 100644 --- a/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/service/IDqInspectProblemService.java +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/service/IDqInspectProblemService.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.service.IService; import org.jeecg.common.exception.JeecgBootException; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import java.util.List; +import java.util.Map; /** * @Description: dq_inspect_problem @@ -24,6 +25,12 @@ public interface IDqInspectProblemService extends IService { /**树节点无子节点状态值*/ public static final String NOCHILD = "0"; + String NODE_TYPE_CATEGORY = "category"; + + String NODE_TYPE_SURFACE = "surface"; + + String NODE_TYPE_SPECIFIC = "specific"; + /** * 新增节点 * @@ -71,4 +78,12 @@ public interface IDqInspectProblemService extends IService { */ List queryListByPid(String pid); + /** + * 根据当前节点类型,返回合法的父级候选树。 + * + * @param nodeType 当前节点类型 + * @return 父级候选树 + */ + List> queryParentOptions(String nodeType); + } diff --git a/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/service/impl/DqInspectProblemServiceImpl.java b/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/service/impl/DqInspectProblemServiceImpl.java index e4a7236..a04f6c3 100644 --- a/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/service/impl/DqInspectProblemServiceImpl.java +++ b/jeecg-module-supervision/src/main/java/org/jeecg/modules/demo/dqinspectproblem/service/impl/DqInspectProblemServiceImpl.java @@ -12,7 +12,9 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -27,6 +29,7 @@ public class DqInspectProblemServiceImpl extends ServiceImpl> queryParentOptions(String nodeType) { + if (NODE_TYPE_SURFACE.equals(nodeType)) { + return queryParentNodesByType(NODE_TYPE_CATEGORY); + } + if (NODE_TYPE_SPECIFIC.equals(nodeType)) { + return querySurfaceParentTree(); + } + return new ArrayList<>(); + } + + /** + * 问题清单固定为三层:问题分类 -> 面上问题 -> 具体问题。 + * 服务层兜底校验层级,避免绕过前端直接提交非法关系。 + */ + private void validateAndNormalizeNode(DqInspectProblem dqInspectProblem, boolean update) { + if (dqInspectProblem == null) { + throw new JeecgBootException("表单数据不能为空"); + } + String nodeType = trimToEmpty(dqInspectProblem.getNodeType()); + if (!NODE_TYPE_CATEGORY.equals(nodeType) && !NODE_TYPE_SURFACE.equals(nodeType) && !NODE_TYPE_SPECIFIC.equals(nodeType)) { + throw new JeecgBootException("请选择正确的问题种类"); + } + dqInspectProblem.setNodeType(nodeType); + + if (NODE_TYPE_CATEGORY.equals(nodeType)) { + dqInspectProblem.setPid(ROOT_PID_VALUE); + clearSpecificFields(dqInspectProblem); + return; + } + + String pid = trimToEmpty(dqInspectProblem.getPid()); + if (oConvertUtils.isEmpty(pid) || ROOT_PID_VALUE.equals(pid)) { + throw new JeecgBootException("请选择上一级问题"); + } + if (update && pid.equals(dqInspectProblem.getId())) { + throw new JeecgBootException("上一级问题不能选择自身"); + } + if (update && isDescendantOf(pid, dqInspectProblem.getId())) { + throw new JeecgBootException("上一级问题不能选择当前节点的下级节点"); + } + + DqInspectProblem parent = baseMapper.selectById(pid); + if (parent == null) { + throw new JeecgBootException("上一级问题不存在"); + } + String expectedParentType = NODE_TYPE_SURFACE.equals(nodeType) ? NODE_TYPE_CATEGORY : NODE_TYPE_SURFACE; + if (!expectedParentType.equals(parent.getNodeType())) { + throw new JeecgBootException("上一级问题类型不正确"); + } + dqInspectProblem.setPid(pid); + + if (!NODE_TYPE_SPECIFIC.equals(nodeType)) { + clearSpecificFields(dqInspectProblem); + } + } + + private void clearSpecificFields(DqInspectProblem dqInspectProblem) { + dqInspectProblem.setInspectAdvice(null); + dqInspectProblem.setQuestionResLeader(null); + dqInspectProblem.setQuestionResDept(null); + } + + private String trimToEmpty(String value) { + return value == null ? "" : value.trim(); + } + + private boolean isDescendantOf(String possibleChildId, String parentId) { + if (oConvertUtils.isEmpty(possibleChildId) || oConvertUtils.isEmpty(parentId)) { + return false; + } + DqInspectProblem node = baseMapper.selectById(possibleChildId); + while (node != null && !ROOT_PID_VALUE.equals(node.getPid())) { + if (parentId.equals(node.getPid())) { + return true; + } + node = baseMapper.selectById(node.getPid()); + } + return false; + } + + private List> queryParentNodesByType(String nodeType) { + List nodes = baseMapper.selectList( + new QueryWrapper() + .eq("node_type", nodeType) + .orderByAsc("sort_no", "create_time") + ); + List> result = new ArrayList<>(); + for (DqInspectProblem node : nodes) { + result.add(toTreeOption(node, false)); + } + return result; + } + + private List> querySurfaceParentTree() { + List categories = baseMapper.selectList( + new QueryWrapper() + .eq("node_type", NODE_TYPE_CATEGORY) + .orderByAsc("sort_no", "create_time") + ); + List> result = new ArrayList<>(); + for (DqInspectProblem category : categories) { + Map categoryOption = toTreeOption(category, true); + List surfaces = baseMapper.selectList( + new QueryWrapper() + .eq("pid", category.getId()) + .eq("node_type", NODE_TYPE_SURFACE) + .orderByAsc("sort_no", "create_time") + ); + List> children = new ArrayList<>(); + for (DqInspectProblem surface : surfaces) { + children.add(toTreeOption(surface, false)); + } + categoryOption.put("children", children); + result.add(categoryOption); + } + return result; + } + + private Map toTreeOption(DqInspectProblem node, boolean disabled) { + Map option = new HashMap<>(); + option.put("key", node.getId()); + option.put("value", node.getId()); + option.put("title", node.getProblemName()); + option.put("label", node.getProblemName()); + option.put("nodeType", node.getNodeType()); + option.put("disabled", disabled); + return option; + } + @Override public List queryListByPid(String pid) { if (oConvertUtils.isEmpty(pid)) {