yxk-20260527-巡视整改提升台账,问题清单树形结构改造

This commit is contained in:
ye1023
2026-05-27 16:40:42 +08:00
parent 1e3cea1594
commit 758252977e
3 changed files with 164 additions and 1 deletions
@@ -193,6 +193,18 @@ public class DqInspectProblemController extends JeecgController<DqInspectProblem
}
}
/**
* 根据当前节点类型获取合法父级候选。
*
* @param nodeType 当前节点类型
* @return 父级候选树
*/
@Operation(summary="dq_inspect_problem-父级候选")
@GetMapping(value = "/parentOptions")
public Result<List<Map<String, Object>>> parentOptions(@RequestParam(name = "nodeType") String nodeType) {
return Result.OK(dqInspectProblemService.queryParentOptions(nodeType));
}
/**
* 添加
*
@@ -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<DqInspectProblem> {
/**树节点无子节点状态值*/
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<DqInspectProblem> {
*/
List<SelectTreeModel> queryListByPid(String pid);
/**
* 根据当前节点类型,返回合法的父级候选树。
*
* @param nodeType 当前节点类型
* @return 父级候选树
*/
List<Map<String, Object>> queryParentOptions(String nodeType);
}
@@ -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<DqInspectProblemMap
@Override
public void addDqInspectProblem(DqInspectProblem dqInspectProblem) {
validateAndNormalizeNode(dqInspectProblem, false);
//新增时设置hasChild为0
dqInspectProblem.setHasChild(IDqInspectProblemService.NOCHILD);
if(oConvertUtils.isEmpty(dqInspectProblem.getPid())){
@@ -48,9 +51,12 @@ public class DqInspectProblemServiceImpl extends ServiceImpl<DqInspectProblemMap
if(entity==null) {
throw new JeecgBootException("未找到对应实体");
}
validateAndNormalizeNode(dqInspectProblem, true);
// hasChild 由树结构维护,忽略前端提交值,避免编辑时误改父子状态。
dqInspectProblem.setHasChild(entity.getHasChild());
String old_pid = entity.getPid();
String new_pid = dqInspectProblem.getPid();
if(!old_pid.equals(new_pid)) {
if(!trimToEmpty(old_pid).equals(trimToEmpty(new_pid))) {
updateOldParentNode(old_pid);
if(oConvertUtils.isEmpty(new_pid)){
dqInspectProblem.setPid(IDqInspectProblemService.ROOT_PID_VALUE);
@@ -139,6 +145,136 @@ public class DqInspectProblemServiceImpl extends ServiceImpl<DqInspectProblemMap
return baseMapper.queryListByPid(pid, null);
}
@Override
public List<Map<String, Object>> 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<Map<String, Object>> queryParentNodesByType(String nodeType) {
List<DqInspectProblem> nodes = baseMapper.selectList(
new QueryWrapper<DqInspectProblem>()
.eq("node_type", nodeType)
.orderByAsc("sort_no", "create_time")
);
List<Map<String, Object>> result = new ArrayList<>();
for (DqInspectProblem node : nodes) {
result.add(toTreeOption(node, false));
}
return result;
}
private List<Map<String, Object>> querySurfaceParentTree() {
List<DqInspectProblem> categories = baseMapper.selectList(
new QueryWrapper<DqInspectProblem>()
.eq("node_type", NODE_TYPE_CATEGORY)
.orderByAsc("sort_no", "create_time")
);
List<Map<String, Object>> result = new ArrayList<>();
for (DqInspectProblem category : categories) {
Map<String, Object> categoryOption = toTreeOption(category, true);
List<DqInspectProblem> surfaces = baseMapper.selectList(
new QueryWrapper<DqInspectProblem>()
.eq("pid", category.getId())
.eq("node_type", NODE_TYPE_SURFACE)
.orderByAsc("sort_no", "create_time")
);
List<Map<String, Object>> children = new ArrayList<>();
for (DqInspectProblem surface : surfaces) {
children.add(toTreeOption(surface, false));
}
categoryOption.put("children", children);
result.add(categoryOption);
}
return result;
}
private Map<String, Object> toTreeOption(DqInspectProblem node, boolean disabled) {
Map<String, Object> 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<SelectTreeModel> queryListByPid(String pid) {
if (oConvertUtils.isEmpty(pid)) {