java实现树形结构的设计

一、页面效果

在这里插入图片描述

二、数据库表设计

CREATE TABLE `qc_question` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `p_id` bigint(11) NOT NULL,
  `rank` int(4) NOT NULL COMMENT '层级',
  `name` varchar(255) NOT NULL COMMENT '名称',
  `code` varchar(255) DEFAULT NULL COMMENT '编号',
  `group_id` bigint(20) DEFAULT NULL COMMENT '问题分组id',
  `group_name` varchar(255) DEFAULT NULL COMMENT '问题分组',
  `status` int(4) NOT NULL DEFAULT '1' COMMENT '状态',
  `order_num` int(4) DEFAULT NULL COMMENT '排序号',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='质量问题库';

三、代码实现

controller

package com.juliet.quality.controller;


import com.juliet.common.core.web.domain.AjaxResult;
import com.juliet.quality.domain.dto.QuestionAddOrUpdateDTO;
import com.juliet.quality.domain.dto.QuestionListDTO;
import com.juliet.quality.domain.dto.QuestionOrderDTO;
import com.juliet.quality.domain.dto.QuestionUpdateStatusDTO;
import com.juliet.quality.domain.vo.QuestionListVO;
import com.juliet.quality.service.IQcQuestionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

/**
 * <p>
 * 质量问题库 前端控制器
 * </p>
 *
 * @author zsj
 * @since 2024-07-04 09:59:18
 */
@Api(tags = "质量问题库")
@Validated
@RestController
@RequestMapping("/question")
@RequiredArgsConstructor
public class QcQuestionController {

    private final IQcQuestionService questionService;

    @ApiOperation("列表")
    @PostMapping("list")
    public AjaxResult<List<QuestionListVO>> getList(@RequestBody QuestionListDTO dto) {
        return AjaxResult.success(questionService.getList(dto));
    }


    @ApiOperation("新增或编辑")
    @PostMapping("addOrUpdate")
    public AjaxResult<Boolean> addOrUpdate(@RequestBody @Valid QuestionAddOrUpdateDTO dto) {
        return AjaxResult.success(questionService.addOrUpdate(dto));
    }

    @ApiOperation("排序")
    @PostMapping("order")
    public AjaxResult<Boolean> order(@RequestBody @Valid QuestionOrderDTO dto) {
        return AjaxResult.success(questionService.order(dto));
    }

    @ApiOperation("修改状态")
    @PostMapping("updateStatus")
    public AjaxResult<Boolean> updateStatus(@RequestBody @Valid QuestionUpdateStatusDTO dto) {
        return AjaxResult.success(questionService.updateStatus(dto));
    }


}


service

package com.juliet.quality.service;

import com.juliet.quality.domain.dto.QuestionAddOrUpdateDTO;
import com.juliet.quality.domain.dto.QuestionListDTO;
import com.juliet.quality.domain.dto.QuestionOrderDTO;
import com.juliet.quality.domain.dto.QuestionUpdateStatusDTO;
import com.juliet.quality.domain.entity.QcQuestionEntity;
import com.baomidou.mybatisplus.extension.service.IService;
import com.juliet.quality.domain.vo.QuestionListVO;

import java.util.List;

/**
 * <p>
 * 质量问题库 服务类
 * </p>
 *
 * @author zsj
 * @since 2024-07-04 09:59:18
 */
public interface IQcQuestionService extends IService<QcQuestionEntity> {

    List<QuestionListVO> getList(QuestionListDTO dto);

    Boolean addOrUpdate(QuestionAddOrUpdateDTO dto);

    Boolean updateStatus(QuestionUpdateStatusDTO dto);

    Boolean order(QuestionOrderDTO dto);

}

package com.juliet.quality.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.juliet.quality.domain.dto.QuestionAddOrUpdateDTO;
import com.juliet.quality.domain.dto.QuestionListDTO;
import com.juliet.quality.domain.dto.QuestionOrderDTO;
import com.juliet.quality.domain.dto.QuestionUpdateStatusDTO;
import com.juliet.quality.domain.entity.QcQuestionEntity;
import com.juliet.quality.dao.QcQuestionDao;
import com.juliet.quality.domain.vo.QuestionListVO;
import com.juliet.quality.domain.vo.QuestionSourceVO;
import com.juliet.quality.service.IQcQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 质量问题库 服务实现类
 * </p>
 *
 * @author zsj
 * @since 2024-07-04 09:59:18
 */
@Service
@RequiredArgsConstructor
public class QcQuestionServiceImpl extends ServiceImpl<QcQuestionDao, QcQuestionEntity> implements IQcQuestionService {

    private final QcQuestionDao qcQuestionDao;


    @Override
    public List<QuestionListVO> getList(QuestionListDTO dto) {
        QuestionListDTO.QueryDTO queryLevel1 = dto.getQueryLevel1();
        QuestionListDTO.QueryDTO queryLevel2 = dto.getQueryLevel2();
        QuestionListDTO.QueryDTO queryLevel3 = dto.getQueryLevel3();
        List<QcQuestionEntity> questionEntityList = qcQuestionDao.selectList(
                Wrappers.<QcQuestionEntity>lambdaQuery()
                        .or(Objects.nonNull(queryLevel1), condition -> addCondition(queryLevel1, condition, 1))
                        .or(Objects.nonNull(dto.getQueryLevel2()), condition -> addCondition(queryLevel2, condition, 2))
                        .or(Objects.nonNull(dto.getQueryLevel3()), condition -> addCondition(queryLevel3, condition, 3))
                        .orderByAsc(QcQuestionEntity::getRank, QcQuestionEntity::getOrderNum)
        );
        return buildTree(questionEntityList);
    }


    private void addCondition(QuestionListDTO.QueryDTO queryLevel, LambdaQueryWrapper<QcQuestionEntity> condition, int level) {
        condition.eq(QcQuestionEntity::getRank, level)
                .in(CollectionUtils.isNotEmpty(queryLevel.getStatusList()), QcQuestionEntity::getStatus, queryLevel.getStatusList())
                .and(StringUtils.isNotBlank(queryLevel.getKeyword()),
                        keyword ->
                                keyword.like(QcQuestionEntity::getName, queryLevel.getKeyword())
                                        .or()
                                        .like(QcQuestionEntity::getCode, queryLevel.getKeyword()))
        ;
    }

    private List<QuestionListVO> buildTree(List<QcQuestionEntity> questionEntityList) {
        List<QuestionListVO> questionListVOList = new ArrayList<>();
        for (QcQuestionEntity question : questionEntityList) {
            Long pId = question.getPId();
            if (Objects.equals(pId, 0L)) {
                QuestionListVO questionListVO = new QuestionListVO();
                BeanUtils.copyProperties(question, questionListVO);
                questionListVOList.add(findChild(questionListVO, questionEntityList));
            }
        }
        calcCount(questionListVOList);
        return questionListVOList;
    }

    private void calcCount(List<QuestionListVO> questionListVOList) {
        for (QuestionListVO questionListVO : questionListVOList) {
            List<QuestionListVO> childList = questionListVO.getChildList();
            if (CollectionUtils.isEmpty(childList)) {
                questionListVO.setCount(0);
            } else {
                questionListVO.setCount(childList.size());
                calcCount(childList);
            }
        }
    }

    private QuestionListVO findChild(QuestionListVO questionListVO, List<QcQuestionEntity> questionEntityList) {
        List<QuestionListVO> childList = new ArrayList<>();
        for (QcQuestionEntity question : questionEntityList) {
            if (Objects.equals(questionListVO.getId(), question.getPId())) {
                QuestionListVO child = new QuestionListVO();
                BeanUtils.copyProperties(question, child);
                childList.add(findChild(child, questionEntityList));
            }
        }
        questionListVO.setChildList(childList);
        return questionListVO;
    }

    @Override
    public Boolean addOrUpdate(QuestionAddOrUpdateDTO dto) {
        Long id = dto.getId();
        QcQuestionEntity question = new QcQuestionEntity();
        BeanUtils.copyProperties(dto, question);
        if (Objects.isNull(id)) {
            return save(question);
        } else {
            return updateById(question);
        }
    }

    @Override
    @Transactional
    public Boolean updateStatus(QuestionUpdateStatusDTO dto) {
        update(Wrappers.<QcQuestionEntity>lambdaUpdate()
                .eq(QcQuestionEntity::getId, dto.getId())
                .set(QcQuestionEntity::getStatus, dto.getStatus())
        );
        updateChild(dto);
        return true;
    }

    private void updateChild(QuestionUpdateStatusDTO dto) {
        List<QcQuestionEntity> list = list(Wrappers.<QcQuestionEntity>lambdaQuery()
                .eq(QcQuestionEntity::getPId, dto.getId()));
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        for (QcQuestionEntity question : list) {
            question.setStatus(dto.getStatus());
            QuestionUpdateStatusDTO statusDTO = new QuestionUpdateStatusDTO();
            statusDTO.setId(question.getId());
            statusDTO.setStatus(dto.getStatus());
            updateChild(statusDTO);
        }
        updateBatchById(list);
    }


    @Override
    public Boolean order(QuestionOrderDTO dto) {
        Integer rank = dto.getRank();
        List<QuestionOrderDTO.Order> orderList = dto.getOrderList();
        for (QuestionOrderDTO.Order order : orderList) {
            update(Wrappers.<QcQuestionEntity>lambdaUpdate()
                    .eq(QcQuestionEntity::getRank, rank)
                    .eq(QcQuestionEntity::getId, order.getId())
                    .set(QcQuestionEntity::getOrderNum, order.getOrderNum())
            );
        }
        return true;
    }
}


dao

package com.juliet.quality.dao;

import com.juliet.quality.domain.entity.QcQuestionEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

/**
 * <p>
 * 质量问题库 Mapper 接口
 * </p>
 *
 * @author zsj
 * @since 2024-07-04 09:59:18
 */
@Mapper
public interface QcQuestionDao extends BaseMapper<QcQuestionEntity> {

}


mapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.juliet.quality.dao.QcQuestionDao">

</mapper>


domain.entity

package com.juliet.quality.domain.entity;

import com.baomidou.mybatisplus.annotation.*;

import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

/**
 * <p>
 * 质量问题库
 * </p>
 *
 * @author zsj
 * @since 2024-07-04 09:59:18
 */
@Getter
@Setter
@Accessors(chain = true)
@TableName("qc_question")
@ApiModel(value = "QcQuestionEntity对象", description = "质量问题库")
public class QcQuestionEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @TableField(value = "p_id")
    private Long pId;

    @ApiModelProperty("层级")
    @TableField("rank")
    private Integer rank;

    @ApiModelProperty("名称")
    @TableField("name")
    private String name;

    @ApiModelProperty("编号")
    @TableField(value = "code", updateStrategy = FieldStrategy.IGNORED)
    private String code;

    @ApiModelProperty("问题分组id")
    @TableField(value = "group_id", updateStrategy = FieldStrategy.IGNORED)
    private Long groupId;

    @ApiModelProperty("问题分组")
    @TableField(value = "group_name", updateStrategy = FieldStrategy.IGNORED)
    private String groupName;

    @ApiModelProperty("状态")
    @TableField("status")
    private Integer status;

    @ApiModelProperty("排序号")
    @TableField("order_num")
    private Integer orderNum;

}

domain.dto

package com.juliet.quality.domain.dto;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

/**
 * @author ZSJ
 * @date 2024/7/4 10:05
 */
@Data
@ApiModel(value = "QuestionListDTO对象", description = "")
public class QuestionListDTO {

    @ApiModelProperty("问题大类")
    private QueryDTO queryLevel1;
    @ApiModelProperty("问题中类")
    private QueryDTO queryLevel2;
    @ApiModelProperty("问题小类")
    private QueryDTO queryLevel3;


    @Data
    @ApiModel(value = "QueryDTO对象", description = "")
    public static class QueryDTO {
        @ApiModelProperty("关键字")
        private String keyword;
        @ApiModelProperty("状态")
        private List<Integer> statusList;
    }

}


package com.juliet.quality.domain.dto;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author ZSJ
 * @date 2024/7/4 10:07
 */
@Data
@ApiModel(value = "QuestionAddOrUpdateDTO对象", description = "")
public class QuestionAddOrUpdateDTO {

    private Long id;
    @ApiModelProperty("大类传0")
    private Long pId;
    @ApiModelProperty("层级1/2/3")
    private Integer rank;

    @ApiModelProperty("名称")
    private String name;

    @ApiModelProperty("编号")
    private String code;

    @ApiModelProperty("问题分组id")
    private Long groupId;

    @ApiModelProperty("问题分组")
    private String groupName;

}

package com.juliet.quality.domain.dto;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.NotNull;
import java.util.List;

/**
 * @author ZSJ
 * @date 2024/7/11 10:26
 */
@Data
@ApiModel(value = "QuestionOrderDTO对象", description = "")
public class QuestionOrderDTO {

    @ApiModelProperty("层级1/2/3")
    @NotNull(message = "层级不能为空")
    private Integer rank;

    @NotNull(message = "排序数据不能为空")
    @ApiModelProperty("排序集合")
    private List<Order> orderList;


    @Data
    @ApiModel(value = "Order", description = "")
    public static class Order {
        private Long id;

        @ApiModelProperty("排序号")
        private Integer orderNum;
    }
}

package com.juliet.quality.domain.dto;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.NotNull;

/**
 * @author ZSJ
 * @date 2024/7/4 10:11
 */
@Data
@ApiModel(value = "QuestionUpdateStatusDTO对象", description = "")
public class QuestionUpdateStatusDTO {

    @NotNull(message = "id不能为空")
    private Long id;

    @NotNull(message = "状态不能为空")
    @ApiModelProperty("状态")
    private Integer status;
}

domain.vo

package com.juliet.quality.domain.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

/**
 * @author ZSJ
 * @date 2024/7/4 10:05
 */
@Data
@ApiModel(value = "QuestionListVO对象", description = "")
public class QuestionListVO {

    private Long id;
    private Long pId;
    @ApiModelProperty("层级")
    private Integer rank;
    @ApiModelProperty("名称")
    private String name;
    @ApiModelProperty("编号")
    private String code;
    @ApiModelProperty("问题分组id")
    private Long groupId;
    @ApiModelProperty("问题分组")
    private String groupName;
    @ApiModelProperty("状态")
    private Integer status;
    @ApiModelProperty("子集数量")
    private Integer count;
    @ApiModelProperty("排序号")
    private Integer orderNum;
    @ApiModelProperty("状态")
    private List<QuestionListVO> childList;

}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值