前言
多级选择器在许多项目的业务需求都需要用到,例如常见的省市区的选择、员工所属公司的具体机构等等,为此设计一个高效、好用的多级选择器非常有必要。本次多级选择器后端将使用递归的方式一次性将数据返回给前端,极大提升了系统的响应速度;后端使用了递归的方式处理数据,也意味着数据库的设计需要存在父子关系的结构;前端将引入element-ui的选择器组件,再加上一些逻辑判断,即可实现多次选择器。
数据库表设计
通常一个项目数据库表的设计,需要系统根据具体的业务逻辑来制定。由于多级选择器需要的数据在后端使用递归的方式实现,为此数据库表需要设计出父子关系的数据供后端使用,具体的数据库表设计如下代码所示。
DROP TABLE IF EXISTS `institution`;
CREATE TABLE `institution` (
`i_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '机构id',
`i_pid` int(11) NULL DEFAULT NULL COMMENT '父机构id',
`i_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '机构名称',
`gmt_create` datetime NULL DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime NULL DEFAULT NULL COMMENT '修改时间',
`is_deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`i_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
需要注意的一点,第一层级的数据,没有父数据,程序默认父数据为0时,便是第一层级的数据,创建的数据如下图所示。
后端实现
后端需要先拿到数据库表存储的所有机构数据,再调用建树方法,具体代码如下所示。
@Override
public List<Institution> queryAllInstitution() {
//查询所有机构
QueryWrapper<Institution> wrapper=new QueryWrapper<>();
wrapper.orderByDesc("i_id");
List<Institution> institutionList = baseMapper.selectList(wrapper);
//递归调用
List<Institution> result=build(institutionList);
return result;
}
上述build方法即是建树过程,需要先在所有数据中找到第一层数据,前面已经规定好了,父数据为0的就是第一层的数据,具体代码如下所示。
//使用递归方法把第一层树建立起来
public static List<Institution> build(List<Institution> treeNodes){
List<Institution> trees=new ArrayList<>();
for (Institution treeNode:treeNodes) {
if ("0".equals(treeNode.getiPid()+"")){
treeNode.setLevel(1);
trees.add(findChildren(treeNode,treeNodes))