Web端常用界面 樹形選單
- 1. 說明
- 2. 表設計
- 3. 普通遞回
- 4. 流式遞回語法糖
1. 說明
樹形選單在web后臺管理系統, 權限管理中基本上很容易見到,如:csdn的個人后臺管理系統,

只不過這個目錄只有兩層,三層的如下:

甚至可以套n層,
為什么要遞回?
因為資料庫表的設計,選單會用一張表設計,選單表的兩個關鍵列,主鍵id和其父級id,使用父級id參考主鍵id 來作為父級選單,即主鍵自關聯,

2. 表設計
create table acl_permission
(
id char(19) default '' not null comment '編號' primary key,
pid char(19) default '' not null comment '所屬上級',
name varchar(20) default '' not null comment '名稱',
type tinyint(3) default 0 not null comment '型別(1:選單,2:按鈕)',
permission_value varchar(50) null comment '權限值',
path varchar(100) null comment '訪問路徑',
component varchar(100) null comment '組件路徑',
icon varchar(50) null comment '圖示',
status tinyint null comment '狀態(0:禁止,1:正常)',
is_deleted tinyint(1) unsigned default 0 not null comment '邏輯洗掉 1(true)已洗掉, 0(false)未洗掉',
gmt_create datetime null comment '創建時間',
gmt_modified datetime null comment '更新時間'
)
comment '權限';
物體類
package top.bitqian.rye.acl.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import lombok.Data;
/**
* 權限
*
* @author echo lovely
* @date 2021-01-21 19:31:47
*/
@Data
@TableName("acl_permission")
public class PermissionEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 編號
*/
@TableId
private String id;
/**
* 所屬上級
*/
private String pid;
/**
* 名稱
*/
private String name;
/**
* 型別(1:選單,2:按鈕)
*/
private Integer type;
/**
* 權限值
*/
private String permissionValue;
/**
* 訪問路徑
*/
private String path;
/**
* 組件路徑
*/
private String component;
/**
* 圖示
*/
private String icon;
/**
* 狀態(0:禁止,1:正常)
*/
private Integer status;
/**
* 邏輯洗掉 1(true)已洗掉, 0(false)未洗掉
*/
@TableField(fill = FieldFill.INSERT)
private Integer isDeleted;
/**
* 創建時間
*/
@TableField(fill = FieldFill.INSERT)
private Date gmtCreate;
/**
* 更新時間
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date gmtModified;
/**
* 等級 根節點為0
*/
@TableField(exist = false)
private String level;
/**
* 子級結點
*/
@TableField(exist = false)
private List<PermissionEntity> children;
}
3. 普通遞回
@Test
void contextLoad1() {
// 表中所有資料
List<PermissionEntity> list = permissionService.list();
List<PermissionEntity> nodeList = new ArrayList<>();
for (PermissionEntity item : list) {
if ("1".equals(item.getPid())) {
// 一級父節點
nodeList.add(item);
// 為每個父結點設定 children
item.setChildren(collectTreeData(item, list));
}
}
nodeList.forEach(System.out::println);
}
/**
*
* @param permission 每個父級結點
* @param list 所有資料
* @return 封裝好的資料 子節點
*/
private List<PermissionEntity> collectTreeData(PermissionEntity permission, List<PermissionEntity> list) {
List<PermissionEntity> tmpList = new ArrayList<>();
// 遍歷所有元素
for (PermissionEntity item : list) {
// 找到子節點
if (item.getPid().equals(permission.getId())) {
// 將兒子收集
tmpList.add(item);
// 繼續遞回
collectTreeData(item, list);
}
}
// 設定父級結點的兒子
permission.setChildren(tmpList);
return tmpList;
}
4. 流式遞回語法糖
public List<PermissionEntity> getMenuTree() {
// 所有樹形選單
List<PermissionEntity> list = this.list();
// pid = 1 的根節點
List<PermissionEntity> nodeList = list.stream().
filter(r -> "1".equals(r.getPid())).
collect(Collectors.toList());
// 為 pid=1 設定子節點,遞回,
return nodeList.stream().peek(r -> {
r.setLevel("0");
// 為每個根結點 設定 children
List<PermissionEntity> dataList = collectTreeData(r, list);
r.setChildren(dataList);
}).collect(Collectors.toList());
}
private List<PermissionEntity> collectTreeData(PermissionEntity permission, List<PermissionEntity> list) {
return list.stream().
filter(r -> r.getPid().equals(permission.getId())).peek(r -> {
// set value..
r.setChildren(collectTreeData(r, list));
}).collect(Collectors.toList());
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/258063.html
標籤:其他
