重构:🔥 重构查询树列表相关 API,并抽取到后端 CRUD 公共组件中
1.基于 Hutool TreeUtil 重构查询树列表相关 API 2.抽取查询树列表 API 到后端 CRUD 公共组件中,大大简化部门管理和菜单管理部分代码
This commit is contained in:
parent
6723903c62
commit
d4fd76dcc1
@ -51,6 +51,10 @@ public @interface CrudRequestMapping {
|
||||
* 分页
|
||||
*/
|
||||
PAGE,
|
||||
/**
|
||||
* 树列表
|
||||
*/
|
||||
TREE,
|
||||
/**
|
||||
* 列表
|
||||
*/
|
||||
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.cnadmin.common.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 树结构字段
|
||||
*
|
||||
* @see cn.hutool.core.lang.tree.TreeNodeConfig
|
||||
* @author Charles7c
|
||||
* @since 2023/2/26 23:50
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface TreeField {
|
||||
|
||||
/**
|
||||
* ID 字段名
|
||||
*
|
||||
* @return ID 字段名
|
||||
*/
|
||||
String value() default "key";
|
||||
|
||||
/**
|
||||
* 父 ID 字段名
|
||||
*
|
||||
* @return 父 ID 字段名
|
||||
*/
|
||||
String parentIdKey() default "parentId";
|
||||
|
||||
/**
|
||||
* 名称字段名
|
||||
*
|
||||
* @return 名称字段名
|
||||
*/
|
||||
String nameKey() default "title";
|
||||
|
||||
/**
|
||||
* 排序字段名
|
||||
*
|
||||
* @return 排序字段名
|
||||
*/
|
||||
String weightKey() default "sort";
|
||||
|
||||
/**
|
||||
* 子列表字段名
|
||||
*
|
||||
* @return 子列表字段名
|
||||
*/
|
||||
String childrenKey() default "children";
|
||||
|
||||
/**
|
||||
* 递归深度(< 0 不限制)
|
||||
*
|
||||
* @return 递归深度
|
||||
*/
|
||||
int deep() default -1;
|
||||
}
|
@ -30,6 +30,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
|
||||
import top.charles7c.cnadmin.common.model.query.PageQuery;
|
||||
import top.charles7c.cnadmin.common.model.query.SortQuery;
|
||||
import top.charles7c.cnadmin.common.model.vo.PageDataVO;
|
||||
@ -74,6 +76,23 @@ public abstract class BaseController<S extends BaseService<V, D, Q, C>, V, D, Q,
|
||||
return R.ok(pageDataVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询树列表
|
||||
*
|
||||
* @param query
|
||||
* 查询条件
|
||||
* @param sortQuery
|
||||
* 排序查询条件
|
||||
* @return 树列表信息
|
||||
*/
|
||||
@Operation(summary = "查询树列表")
|
||||
@ResponseBody
|
||||
@GetMapping("/tree")
|
||||
protected R<List<Tree<Long>>> tree(@Validated Q query, @Validated SortQuery sortQuery) {
|
||||
List<Tree<Long>> list = baseService.tree(query, sortQuery, false);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
|
@ -20,6 +20,8 @@ import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
|
||||
import top.charles7c.cnadmin.common.model.query.PageQuery;
|
||||
import top.charles7c.cnadmin.common.model.query.SortQuery;
|
||||
import top.charles7c.cnadmin.common.model.vo.PageDataVO;
|
||||
@ -51,6 +53,19 @@ public interface BaseService<V, D, Q, C extends BaseRequest> {
|
||||
*/
|
||||
PageDataVO<V> page(Q query, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询树列表
|
||||
*
|
||||
* @param query
|
||||
* 查询条件
|
||||
* @param sortQuery
|
||||
* 排序查询条件
|
||||
* @param isSimple
|
||||
* 是否为简单树结构(不包含基本树结构之外的扩展字段)
|
||||
* @return 树列表信息
|
||||
*/
|
||||
List<Tree<Long>> tree(Q query, SortQuery sortQuery, boolean isSimple);
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
|
@ -16,8 +16,11 @@
|
||||
|
||||
package top.charles7c.cnadmin.common.base;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@ -41,15 +44,21 @@ import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Opt;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.core.lang.tree.TreeNodeConfig;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
|
||||
import top.charles7c.cnadmin.common.annotation.TreeField;
|
||||
import top.charles7c.cnadmin.common.model.query.PageQuery;
|
||||
import top.charles7c.cnadmin.common.model.query.SortQuery;
|
||||
import top.charles7c.cnadmin.common.model.vo.PageDataVO;
|
||||
import top.charles7c.cnadmin.common.service.CommonUserService;
|
||||
import top.charles7c.cnadmin.common.util.ExcelUtils;
|
||||
import top.charles7c.cnadmin.common.util.ExceptionUtils;
|
||||
import top.charles7c.cnadmin.common.util.ReflectUtils;
|
||||
import top.charles7c.cnadmin.common.util.TreeUtils;
|
||||
import top.charles7c.cnadmin.common.util.helper.QueryHelper;
|
||||
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
|
||||
|
||||
@ -90,6 +99,40 @@ public abstract class BaseServiceImpl<M extends BaseMapper<T>, T, V, D, Q, C ext
|
||||
return pageDataVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tree<Long>> tree(Q query, SortQuery sortQuery, boolean isSimple) {
|
||||
List<V> list = this.list(query, sortQuery);
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 如果构建简单树结构,则不包含基本树结构之外的扩展字段
|
||||
TreeNodeConfig treeNodeConfig = TreeUtils.DEFAULT_CONFIG;
|
||||
TreeField treeField = voClass.getDeclaredAnnotation(TreeField.class);
|
||||
if (!isSimple) {
|
||||
// 根据 @TreeField 配置生成树结构配置
|
||||
treeNodeConfig = TreeUtils.genTreeNodeConfig(treeField);
|
||||
}
|
||||
|
||||
// 构建树
|
||||
return TreeUtils.build(list, treeNodeConfig, (node, tree) -> {
|
||||
// 转换器
|
||||
tree.setId(ReflectUtil.invoke(node, StrUtil.genGetter(treeField.value())));
|
||||
tree.setParentId(ReflectUtil.invoke(node, StrUtil.genGetter(treeField.parentIdKey())));
|
||||
tree.setName(ReflectUtil.invoke(node, StrUtil.genGetter(treeField.nameKey())));
|
||||
tree.setWeight(ReflectUtil.invoke(node, StrUtil.genGetter(treeField.weightKey())));
|
||||
if (!isSimple) {
|
||||
Field[] fieldArr = ReflectUtils.getNonStaticFields(voClass);
|
||||
List<Field> fieldList = Arrays.stream(fieldArr)
|
||||
.filter(f -> !StrUtil.containsAnyIgnoreCase(f.getName(), treeField.value(), treeField.parentIdKey(),
|
||||
treeField.nameKey(), treeField.weightKey(), treeField.childrenKey()))
|
||||
.collect(Collectors.toList());
|
||||
fieldList
|
||||
.forEach(f -> tree.putExtra(f.getName(), ReflectUtil.invoke(node, StrUtil.genGetter(f.getName()))));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<V> list(Q query, SortQuery sortQuery) {
|
||||
List<V> list = this.list(query, sortQuery, voClass);
|
||||
|
@ -29,6 +29,9 @@ import cn.hutool.core.lang.tree.TreeUtil;
|
||||
import cn.hutool.core.lang.tree.parser.NodeParser;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
|
||||
import top.charles7c.cnadmin.common.annotation.TreeField;
|
||||
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
|
||||
|
||||
/**
|
||||
* 树工具类
|
||||
*
|
||||
@ -39,7 +42,7 @@ import cn.hutool.core.util.ReflectUtil;
|
||||
public class TreeUtils {
|
||||
|
||||
/** 默认属性配置对象(根据前端树结构灵活调整名称) */
|
||||
private static final TreeNodeConfig DEFAULT_CONFIG =
|
||||
public static final TreeNodeConfig DEFAULT_CONFIG =
|
||||
TreeNodeConfig.DEFAULT_CONFIG.setNameKey("title").setIdKey("key").setWeightKey("sort");
|
||||
|
||||
/**
|
||||
@ -53,13 +56,46 @@ public class TreeUtils {
|
||||
* 源数据集合
|
||||
* @param nodeParser
|
||||
* 转换器
|
||||
* @return List
|
||||
* @return List 树列表
|
||||
*/
|
||||
public static <T, E> List<Tree<E>> build(List<T> list, NodeParser<T, E> nodeParser) {
|
||||
return build(list, DEFAULT_CONFIG, nodeParser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 树构建
|
||||
*
|
||||
* @param <T>
|
||||
* 转换的实体 为数据源里的对象类型
|
||||
* @param <E>
|
||||
* ID类型
|
||||
* @param list
|
||||
* 源数据集合
|
||||
* @param treeNodeConfig
|
||||
* 配置
|
||||
* @param nodeParser
|
||||
* 转换器
|
||||
* @return List 树列表
|
||||
*/
|
||||
public static <T, E> List<Tree<E>> build(List<T> list, TreeNodeConfig treeNodeConfig, NodeParser<T, E> nodeParser) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
E parentId = (E)ReflectUtil.getFieldValue(list.get(0), DEFAULT_CONFIG.getParentIdKey());
|
||||
return TreeUtil.build(list, parentId, DEFAULT_CONFIG, nodeParser);
|
||||
E parentId = (E)ReflectUtil.getFieldValue(list.get(0), treeNodeConfig.getParentIdKey());
|
||||
return TreeUtil.build(list, parentId, treeNodeConfig, nodeParser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 @TreeField 配置生成树结构配置
|
||||
*
|
||||
* @param treeField
|
||||
* 树结构字段注解
|
||||
* @return 树结构配置
|
||||
*/
|
||||
public static TreeNodeConfig genTreeNodeConfig(TreeField treeField) {
|
||||
CheckUtils.throwIfNull(treeField, "请添加并配置 @TreeField 树结构信息");
|
||||
return new TreeNodeConfig().setIdKey(treeField.value()).setParentIdKey(treeField.parentIdKey())
|
||||
.setNameKey(treeField.nameKey()).setWeightKey(treeField.weightKey()).setChildrenKey(treeField.childrenKey())
|
||||
.setDeep(treeField.deep() < 0 ? null : treeField.deep());
|
||||
}
|
||||
}
|
||||
|
@ -16,13 +16,12 @@
|
||||
|
||||
package top.charles7c.cnadmin.system.model.vo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.charles7c.cnadmin.common.annotation.TreeField;
|
||||
import top.charles7c.cnadmin.common.base.BaseVO;
|
||||
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
|
||||
|
||||
@ -34,6 +33,7 @@ import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TreeField(value = "deptId", nameKey = "deptName", weightKey = "deptSort")
|
||||
@Schema(description = "部门信息")
|
||||
public class DeptVO extends BaseVO {
|
||||
|
||||
@ -74,10 +74,4 @@ public class DeptVO extends BaseVO {
|
||||
*/
|
||||
@Schema(description = "状态(1启用 2禁用)")
|
||||
private DisEnableStatusEnum status;
|
||||
|
||||
/**
|
||||
* 子部门列表
|
||||
*/
|
||||
@Schema(description = "子部门列表")
|
||||
private List<DeptVO> children;
|
||||
}
|
||||
|
@ -16,13 +16,12 @@
|
||||
|
||||
package top.charles7c.cnadmin.system.model.vo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.charles7c.cnadmin.common.annotation.TreeField;
|
||||
import top.charles7c.cnadmin.common.base.BaseVO;
|
||||
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
|
||||
import top.charles7c.cnadmin.common.enums.MenuTypeEnum;
|
||||
@ -35,6 +34,7 @@ import top.charles7c.cnadmin.common.enums.MenuTypeEnum;
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TreeField(value = "menuId", nameKey = "menuName", weightKey = "menuSort")
|
||||
@Schema(description = "菜单信息")
|
||||
public class MenuVO extends BaseVO {
|
||||
|
||||
@ -123,10 +123,4 @@ public class MenuVO extends BaseVO {
|
||||
*/
|
||||
@Schema(description = "状态(1启用 2禁用)")
|
||||
private DisEnableStatusEnum status;
|
||||
|
||||
/**
|
||||
* 子菜单列表
|
||||
*/
|
||||
@Schema(description = "子菜单列表")
|
||||
private List<MenuVO> children;
|
||||
}
|
||||
|
@ -16,10 +16,6 @@
|
||||
|
||||
package top.charles7c.cnadmin.system.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
|
||||
import top.charles7c.cnadmin.common.base.BaseService;
|
||||
import top.charles7c.cnadmin.system.model.query.DeptQuery;
|
||||
import top.charles7c.cnadmin.system.model.request.DeptRequest;
|
||||
@ -32,23 +28,4 @@ import top.charles7c.cnadmin.system.model.vo.DeptVO;
|
||||
* @author Charles7c
|
||||
* @since 2023/1/22 17:54
|
||||
*/
|
||||
public interface DeptService extends BaseService<DeptVO, DeptDetailVO, DeptQuery, DeptRequest> {
|
||||
|
||||
/**
|
||||
* 构建树
|
||||
*
|
||||
* @param list
|
||||
* 原始列表数据
|
||||
* @return 树列表
|
||||
*/
|
||||
List<DeptVO> buildListTree(List<DeptVO> list);
|
||||
|
||||
/**
|
||||
* 构建树
|
||||
*
|
||||
* @param list
|
||||
* 原始列表数据
|
||||
* @return 树列表
|
||||
*/
|
||||
List<Tree<Long>> buildTree(List<DeptVO> list);
|
||||
}
|
||||
public interface DeptService extends BaseService<DeptVO, DeptDetailVO, DeptQuery, DeptRequest> {}
|
||||
|
@ -16,10 +16,6 @@
|
||||
|
||||
package top.charles7c.cnadmin.system.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
|
||||
import top.charles7c.cnadmin.common.base.BaseService;
|
||||
import top.charles7c.cnadmin.system.model.query.MenuQuery;
|
||||
import top.charles7c.cnadmin.system.model.request.MenuRequest;
|
||||
@ -31,23 +27,4 @@ import top.charles7c.cnadmin.system.model.vo.MenuVO;
|
||||
* @author Charles7c
|
||||
* @since 2023/2/15 20:30
|
||||
*/
|
||||
public interface MenuService extends BaseService<MenuVO, MenuVO, MenuQuery, MenuRequest> {
|
||||
|
||||
/**
|
||||
* 构建树
|
||||
*
|
||||
* @param list
|
||||
* 原始列表数据
|
||||
* @return 树列表
|
||||
*/
|
||||
List<MenuVO> buildListTree(List<MenuVO> list);
|
||||
|
||||
/**
|
||||
* 构建树
|
||||
*
|
||||
* @param list
|
||||
* 原始列表数据
|
||||
* @return 树列表
|
||||
*/
|
||||
List<Tree<Long>> buildTree(List<MenuVO> list);
|
||||
}
|
||||
public interface MenuService extends BaseService<MenuVO, MenuVO, MenuQuery, MenuRequest> {}
|
||||
|
@ -16,11 +16,7 @@
|
||||
|
||||
package top.charles7c.cnadmin.system.service.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@ -29,13 +25,9 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
|
||||
import top.charles7c.cnadmin.common.base.BaseServiceImpl;
|
||||
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
|
||||
import top.charles7c.cnadmin.common.util.ExceptionUtils;
|
||||
import top.charles7c.cnadmin.common.util.TreeUtils;
|
||||
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
|
||||
import top.charles7c.cnadmin.system.mapper.DeptMapper;
|
||||
import top.charles7c.cnadmin.system.model.entity.DeptDO;
|
||||
@ -90,68 +82,6 @@ public class DeptServiceImpl extends BaseServiceImpl<DeptMapper, DeptDO, DeptVO,
|
||||
super.lambdaUpdate().in(DeptDO::getParentId, ids).remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeptVO> buildListTree(List<DeptVO> list) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 去除重复子部门列表
|
||||
List<DeptVO> deDuplicationList = deDuplication(list);
|
||||
return deDuplicationList.stream().map(d -> d.setChildren(this.getChildren(d, list)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据去重(去除重复子部门列表)
|
||||
*
|
||||
* @param list
|
||||
* 部门列表
|
||||
* @return 去重后部门列表
|
||||
*/
|
||||
private List<DeptVO> deDuplication(List<DeptVO> list) {
|
||||
List<DeptVO> deDuplicationList = new ArrayList<>();
|
||||
for (DeptVO outer : list) {
|
||||
boolean flag = true;
|
||||
for (DeptVO inner : list) {
|
||||
// 忽略重复子列表
|
||||
if (Objects.equals(inner.getDeptId(), outer.getParentId())) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
deDuplicationList.add(outer);
|
||||
}
|
||||
}
|
||||
return deDuplicationList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定部门的子部门列表
|
||||
*
|
||||
* @param deptVO
|
||||
* 指定部门
|
||||
* @param list
|
||||
* 部门列表
|
||||
* @return 子部门列表
|
||||
*/
|
||||
private List<DeptVO> getChildren(DeptVO deptVO, List<DeptVO> list) {
|
||||
return list.stream().filter(d -> Objects.equals(d.getParentId(), deptVO.getDeptId()))
|
||||
.map(d -> d.setChildren(this.getChildren(d, list))).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tree<Long>> buildTree(List<DeptVO> list) {
|
||||
return TreeUtils.build(list, (d, tree) -> {
|
||||
tree.setId(d.getDeptId());
|
||||
tree.setName(d.getDeptName());
|
||||
tree.setParentId(d.getParentId());
|
||||
tree.setWeight(d.getDeptSort());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查名称是否存在
|
||||
*
|
||||
|
@ -16,23 +16,15 @@
|
||||
|
||||
package top.charles7c.cnadmin.system.service.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
|
||||
import top.charles7c.cnadmin.common.base.BaseServiceImpl;
|
||||
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
|
||||
import top.charles7c.cnadmin.common.util.TreeUtils;
|
||||
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
|
||||
import top.charles7c.cnadmin.system.mapper.MenuMapper;
|
||||
import top.charles7c.cnadmin.system.model.entity.MenuDO;
|
||||
@ -71,6 +63,7 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuVO,
|
||||
boolean isExists = this.checkNameExists(menuName, request.getParentId(), request.getMenuId());
|
||||
CheckUtils.throwIf(() -> isExists, String.format("修改失败,'%s'已存在", menuName));
|
||||
|
||||
// 更新信息
|
||||
super.update(request);
|
||||
}
|
||||
|
||||
@ -81,68 +74,6 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuVO,
|
||||
super.lambdaUpdate().in(MenuDO::getParentId, ids).remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MenuVO> buildListTree(List<MenuVO> list) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 去除重复子菜单列表
|
||||
List<MenuVO> deDuplicationList = deDuplication(list);
|
||||
return deDuplicationList.stream().map(m -> m.setChildren(this.getChildren(m, list)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据去重(去除重复子菜单列表)
|
||||
*
|
||||
* @param list
|
||||
* 菜单列表
|
||||
* @return 去重后菜单列表
|
||||
*/
|
||||
private List<MenuVO> deDuplication(List<MenuVO> list) {
|
||||
List<MenuVO> deDuplicationList = new ArrayList<>();
|
||||
for (MenuVO outer : list) {
|
||||
boolean flag = true;
|
||||
for (MenuVO inner : list) {
|
||||
// 忽略重复子列表
|
||||
if (Objects.equals(inner.getMenuId(), outer.getParentId())) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
deDuplicationList.add(outer);
|
||||
}
|
||||
}
|
||||
return deDuplicationList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定菜单的子菜单列表
|
||||
*
|
||||
* @param menuVO
|
||||
* 指定菜单
|
||||
* @param list
|
||||
* 菜单列表
|
||||
* @return 子菜单列表
|
||||
*/
|
||||
private List<MenuVO> getChildren(MenuVO menuVO, List<MenuVO> list) {
|
||||
return list.stream().filter(m -> Objects.equals(m.getParentId(), menuVO.getMenuId()))
|
||||
.map(m -> m.setChildren(this.getChildren(m, list))).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tree<Long>> buildTree(List<MenuVO> list) {
|
||||
return TreeUtils.build(list, (m, tree) -> {
|
||||
tree.setId(m.getMenuId());
|
||||
tree.setName(m.getMenuName());
|
||||
tree.setParentId(m.getParentId());
|
||||
tree.setWeight(m.getMenuSort());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查名称是否存在
|
||||
*
|
||||
|
@ -24,7 +24,7 @@ export interface DeptParam {
|
||||
}
|
||||
|
||||
export function listDept(params: DeptParam) {
|
||||
return axios.get<DeptRecord[]>(`${BASE_URL}/list`, {
|
||||
return axios.get<DeptRecord[]>(`${BASE_URL}/tree`, {
|
||||
params,
|
||||
paramsSerializer: (obj) => {
|
||||
return qs.stringify(obj);
|
||||
|
@ -32,7 +32,7 @@ export interface MenuParam {
|
||||
}
|
||||
|
||||
export function listMenu(params: MenuParam) {
|
||||
return axios.get<MenuRecord[]>(`${BASE_URL}/list`, {
|
||||
return axios.get<MenuRecord[]>(`${BASE_URL}/tree`, {
|
||||
params,
|
||||
paramsSerializer: (obj) => {
|
||||
return qs.stringify(obj);
|
||||
|
@ -40,8 +40,6 @@ import top.charles7c.cnadmin.system.model.query.DeptQuery;
|
||||
import top.charles7c.cnadmin.system.model.query.MenuQuery;
|
||||
import top.charles7c.cnadmin.system.model.query.PostQuery;
|
||||
import top.charles7c.cnadmin.system.model.query.RoleQuery;
|
||||
import top.charles7c.cnadmin.system.model.vo.DeptVO;
|
||||
import top.charles7c.cnadmin.system.model.vo.MenuVO;
|
||||
import top.charles7c.cnadmin.system.model.vo.PostVO;
|
||||
import top.charles7c.cnadmin.system.model.vo.RoleVO;
|
||||
import top.charles7c.cnadmin.system.service.DeptService;
|
||||
@ -72,16 +70,14 @@ public class CommonController {
|
||||
@Operation(summary = "查询部门树", description = "查询树结构的部门列表")
|
||||
@GetMapping("/tree/dept")
|
||||
public R<List<Tree<Long>>> listDeptTree(@Validated DeptQuery query, @Validated SortQuery sortQuery) {
|
||||
List<DeptVO> list = deptService.list(query, sortQuery);
|
||||
List<Tree<Long>> treeList = deptService.buildTree(list);
|
||||
List<Tree<Long>> treeList = deptService.tree(query, sortQuery, true);
|
||||
return R.ok(treeList);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询菜单树", description = "查询树结构的菜单列表")
|
||||
@GetMapping("/tree/menu")
|
||||
public R<List<Tree<Long>>> listMenuTree(@Validated MenuQuery query, @Validated SortQuery sortQuery) {
|
||||
List<MenuVO> list = menuService.list(query, sortQuery);
|
||||
List<Tree<Long>> treeList = menuService.buildTree(list);
|
||||
List<Tree<Long>> treeList = menuService.tree(query, sortQuery, true);
|
||||
return R.ok(treeList);
|
||||
}
|
||||
|
||||
|
@ -18,18 +18,12 @@ package top.charles7c.cnadmin.webapi.controller.system;
|
||||
|
||||
import static top.charles7c.cnadmin.common.annotation.CrudRequestMapping.Api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import top.charles7c.cnadmin.common.annotation.CrudRequestMapping;
|
||||
import top.charles7c.cnadmin.common.base.BaseController;
|
||||
import top.charles7c.cnadmin.common.model.query.SortQuery;
|
||||
import top.charles7c.cnadmin.common.model.vo.R;
|
||||
import top.charles7c.cnadmin.system.model.query.DeptQuery;
|
||||
import top.charles7c.cnadmin.system.model.request.DeptRequest;
|
||||
import top.charles7c.cnadmin.system.model.vo.DeptDetailVO;
|
||||
@ -44,13 +38,5 @@ import top.charles7c.cnadmin.system.service.DeptService;
|
||||
*/
|
||||
@Tag(name = "部门管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/system/dept", api = {Api.LIST, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class DeptController extends BaseController<DeptService, DeptVO, DeptDetailVO, DeptQuery, DeptRequest> {
|
||||
|
||||
@Override
|
||||
@Operation(summary = "查询列表树")
|
||||
public R<List<DeptVO>> list(@Validated DeptQuery query, @Validated SortQuery sortQuery) {
|
||||
List<DeptVO> list = baseService.list(query, sortQuery);
|
||||
return R.ok(baseService.buildListTree(list));
|
||||
}
|
||||
}
|
||||
@CrudRequestMapping(value = "/system/dept", api = {Api.TREE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class DeptController extends BaseController<DeptService, DeptVO, DeptDetailVO, DeptQuery, DeptRequest> {}
|
||||
|
@ -18,18 +18,12 @@ package top.charles7c.cnadmin.webapi.controller.system;
|
||||
|
||||
import static top.charles7c.cnadmin.common.annotation.CrudRequestMapping.Api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import top.charles7c.cnadmin.common.annotation.CrudRequestMapping;
|
||||
import top.charles7c.cnadmin.common.base.BaseController;
|
||||
import top.charles7c.cnadmin.common.model.query.SortQuery;
|
||||
import top.charles7c.cnadmin.common.model.vo.R;
|
||||
import top.charles7c.cnadmin.system.model.query.MenuQuery;
|
||||
import top.charles7c.cnadmin.system.model.request.MenuRequest;
|
||||
import top.charles7c.cnadmin.system.model.vo.MenuVO;
|
||||
@ -43,13 +37,5 @@ import top.charles7c.cnadmin.system.service.MenuService;
|
||||
*/
|
||||
@Tag(name = "菜单管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/system/menu", api = {Api.LIST, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class MenuController extends BaseController<MenuService, MenuVO, MenuVO, MenuQuery, MenuRequest> {
|
||||
|
||||
@Override
|
||||
@Operation(summary = "查询列表树")
|
||||
public R<List<MenuVO>> list(@Validated MenuQuery query, @Validated SortQuery sortQuery) {
|
||||
List<MenuVO> list = baseService.list(query, sortQuery);
|
||||
return R.ok(baseService.buildListTree(list));
|
||||
}
|
||||
}
|
||||
@CrudRequestMapping(value = "/system/menu", api = {Api.TREE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class MenuController extends BaseController<MenuService, MenuVO, MenuVO, MenuQuery, MenuRequest> {}
|
||||
|
Loading…
Reference in New Issue
Block a user