bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?

树形列表菜单的数据组织形式一般有两种:一种是一次性向服务器请求所有节点的数据,一种是先请求根目录的节点,当用户点击该节点时,再去请求该节点的子叶节点的数据。这里我们的需求是第一种。

树形菜单是我们经常会用到的一种菜单展现方式,这里我推荐bootstrap-treeview,它是一款效果非常酷的基于bootstrap的jQuery多级列表树插件。该jQuery插件基于Twitter Bootstrap,以简单和优雅的方式来显示一些继承树结构,如视图树、列表树等。

前端页面的编写,比较简单,故简略描述,我们着重将后端如何按照要求组织返回所需的Json。

使用方法

首先要在页面中引入依赖的css样式和 bootstrap-treeview.js文件。

<!-- Required Stylesheets -->

<link href="./css/bootstrap.css" rel="external nofollow" rel="stylesheet">

<!-- Required Javascript -->

<script src="./js/jquery.js"></script>

<script src="./js/bootstrap-treeview.js"></script>

可以使用任何HTML DOM元素来作为该列表树的容器:

<div id="tree"></div>

调用

<script type="text/javascript">

$(function() {$.ajax({

type: "Get",

url: "doctype/FarmDoctypeLoadTreeNodes.do",

data: {id: ""},

dataType: "json",

success: function (result) {

$("#tree").treeview({

data: result.nodes, // 数据源

levels:1, //设置继承树默认展开的级别

showTags: true, //是否在每个节点右边显示tags标签。tag值必须在每个列表树的data结构中给出

onNodeSelected: function (event, data) {

/* console.log(data); */

/* alert(data.nodeId); */

window.location = basePath + "webtype/view"

+ data.id + "/Pub1.html";

}

});

},

error: function () {

alert("加载失败!")

}

});

});

</script>

数据源要求的数据格式:

var tree = [

{

text: "Parent 1",

tags: ['2'],

nodes: [

{

text: "Child 1",

tags: ['3'],

nodes: [

{

text: "Grandchild 1",

tags: ['1']

},

{

text: "Grandchild 2",

tags: ['1']

}

]

},

{

text: "Child 2",

tags: ['1']

}

]

},

{

text: "Parent 2",

tags: ['1']

},

{

text: "Parent 3",

tags: ['1']

},

{

text: "Parent 4",

tags: ['1']

},

{

text: "Parent 5",

tags: ['1']

}

];

看到这个数据结构,我们首先想到的是数据结构中的二叉树。欧拉,我们不妨可以把它理解成,这样的数据结构:

创建一个实例,组织所需要的数据结构的json.

public class BootstrapUiTreeNode implements Serializable {

private static final long serialVersionUID = 1L;

static final Logger log = Logger.getLogger(BootstrapUiTreeNode.class);

private String id;

private String parentId;

private String text;

//子叶节点

private List<BootstrapUiTreeNode> nodes = new ArrayList<>();

//统计该节点分类下文档的数量

private List<String> tags = new ArrayList<>(); // tags: ['NUM']

public BootstrapUiTreeNode(String id, String parentId, String text) {

super();

this.id = id;

this.parentId = parentId;

this.text = text;

}

public BootstrapUiTreeNode(String id, String parentId, String text, List<BootstrapUiTreeNode> nodes) {

super();

this.id = id;

this.parentId = parentId;

this.text = text;

this.nodes = nodes;

}

public String getParentId() {

return parentId;

}

public void setParentId(String parentId) {

this.parentId = parentId;

}

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getText() {

return text;

}

public void setText(String text) {

this.text = text;

}

public List<BootstrapUiTreeNode> getNodes() {

return nodes;

}

public void setNodes(List<BootstrapUiTreeNode> nodes) {

this.nodes = nodes;

}

public List<String> getTags() {

return tags;

}

public void setTags(List<String> tags) {

this.tags = tags;

}

/**

* 加载第一层树节点 父节点的根目录的父id必须为"NONE",包含字段名ID,PARENTID,NAME

*

* @param parentId

* 父亲节点id

* @param SortTitle

* 排序字段index

* @param tableTitle

* 表名index

* @param id_title

* 表id的index

* @param parentId_title

* 表parentid的index

* @param name_title

* 表name的index

* @param icon_title

*/

public static List<Map<String, Object>> queryTreeNodeOne(String parentId, String SortTitle, String tableTitle, String id_title,

String parentId_title, String name_title) {

if (StringUtils.isEmpty(parentId)) {

parentId = "NONE";

}

DataResult nodeResult = null;

DBSort sort = new DBSort("a." + SortTitle, "ASC");

DataQuery query = DataQuery.getInstance("1",

id_title

+ ","

+ parentId_title

+ " as "

+ parentId_title

+ ","

+ name_title

+ " as "

+ name_title,

tableTitle + " a");

query.setPagesize(100);

query.addSort(sort);

DataQuerys.wipeVirus(parentId);

query.setSqlRule("and " + parentId_title + "='" + parentId + "'");

try {

nodeResult = query.search();

} catch (SQLException e) {

log.error(e.getMessage());

}

return nodeResult.getResultList();

}

public static List<TypeBrief> getPopTypesForReadDoc() {

DataQuery query = DataQuery.init(new DataQuery(),

"(SELECT a.NAME as NAME,a.SORT as SORT, a.ID as ID, a.READPOP as READPOP,a.WRITEPOP AS WRITEPOP, a.AUDITPOP AS AUDITPOP, a.PARENTID AS PARENTID, (SELECT COUNT(B1.ID) FROM FARM_DOC B1 LEFT JOIN FARM_RF_DOCTYPE B2 ON B1.ID = B2.DOCID LEFT JOIN FARM_DOCTYPE B3 ON B3.ID = B2.TYPEID WHERE B1.STATE='1' and B3.TREECODE LIKE CONCAT(A.TREECODE,'%') AND B1.STATE='1') AS NUM,f.oid as OID,f.FUNTYPE as FUNTYPE FROM farm_doctype AS a left join FARM_DOCTYPE_POP as f on f.TYPEID=a.ID WHERE 1 = 1 AND (TYPE = '1' OR TYPE = '3') AND PSTATE = '1' ) AS e",

"NAME,ID,PARENTID,NUM,OID,READPOP,AUDITPOP,WRITEPOP,FUNTYPE,SORT");

query.setPagesize(1000);

query.setNoCount();

query.setCache(Integer.valueOf(0), CACHE_UNIT.second);

query.addSort(new DBSort("SORT", "ASC"));

try {

DataResult result = query.search();

//利用反射获取对象集合

return result.getObjectList(TypeBrief.class);

} catch (SQLException e) {

log.error(e.toString());

return new ArrayList<TypeBrief>();

}

}

/**

* 遍历集合获得对象

*

* @param nodeList

* @return

*/

public static List<BootstrapUiTreeNode> findNode(List<TypeBrief> typeBriefs, List<Map<String, Object>> data, String id_title,

String parentId_title, String name_title) {

List<BootstrapUiTreeNode> nodeList = new ArrayList<>();

try {

for (Map<String, Object> node : data) {

if (node.get(id_title) == null) {

continue;

}

BootstrapUiTreeNode item = new BootstrapUiTreeNode(node.get(id_title).toString(),

node.get(parentId_title).toString(), node.get(name_title).toString());

//统计该节点下分类的文档数

for(TypeBrief typeBrief : typeBriefs) {

if(typeBrief.getId().equals(node.get(id_title).toString())) {

item.getTags().add(typeBrief.getNum() + "");

break;

}

}

nodeList.add(item);

}

} catch (Exception e) {

throw new RuntimeException(e);

}

return nodeList;

}

/**

* 先用递归构造除第一层几个根节点外的类多叉树结构

* @param node

* @param parentId

* @param sortTitle

* @param tableTitle

* @param id_title

* @param parentId_title

* @param name_title

* @return

*/

public static BootstrapUiTreeNode createSubtreeTreeNodes(List<TypeBrief> typeBriefs, BootstrapUiTreeNode node, String parentId, String sortTitle, String tableTitle, String id_title,

String parentId_title, String name_title) {

//获取该根节点下的所有子节点

List<Map<String, Object>> data = queryTreeNodeOne(parentId, sortTitle, tableTitle, id_title, parentId_title, name_title);

List<BootstrapUiTreeNode> roots = findNode(typeBriefs, data, id_title, parentId_title, name_title);

if(null != roots && roots.size() > 0) {

//递归继续查询

for(BootstrapUiTreeNode child : roots) {

BootstrapUiTreeNode treeNode = createSubtreeTreeNodes(typeBriefs, child, child.getId(), sortTitle, tableTitle, id_title, parentId_title, name_title);

node.getNodes().add(treeNode);

}

} else {

node.setNodes(null);

}

return node;

}

/**

* 补上第一层的几个根节点

* @param parentId

* @param sortTitle

* @param tableTitle

* @param id_title

* @param parentId_title

* @param name_title

* @return

*

* 注意:所以会存在叶子节点中的nodes没有数据的情况,这个时候会出现叶子节点是可以伸缩的,

* 因为nodes属性就是一个对象数组,它会被认为它还有子节点,其实是没有的。

*

*/

public static List<BootstrapUiTreeNode> createTreeNodes(String parentId, String sortTitle, String tableTitle, String id_title,

String parentId_title, String name_title) {

//统计所有节点分类对应的文档数目

List<TypeBrief> typeBriefs = getPopTypesForReadDoc();

List<BootstrapUiTreeNode> nodes = new ArrayList<>();

//查询第一层根节点

List<Map<String, Object>> data = queryTreeNodeOne(parentId, sortTitle, tableTitle, id_title, parentId_title, name_title);

List<BootstrapUiTreeNode> treeNodes = findNode(typeBriefs, data, id_title, parentId_title, name_title);

for(BootstrapUiTreeNode node : treeNodes) {

BootstrapUiTreeNode treeNode = createSubtreeTreeNodes(typeBriefs, node, node.getId(), sortTitle, tableTitle, id_title, parentId_title, name_title);

nodes.add(treeNode);

}

return nodes;

}

}

控制器:

@RequestMapping("/FarmDoctypeLoadTreeNodes")

@ResponseBody

public Map<String, Object> loadTreeNodes(DataQuery query, HttpServletRequest request, String id) {

query = EasyUiUtils.formatGridQuery(request, query);

try {

List<BootstrapUiTreeNode> treeNodes = BootstrapUiTreeNode.createTreeNodes(id, "SORT", "FARM_DOCTYPE", "ID", "PARENTID", "NAME");

return ViewMode.getInstance().putAttr("nodes", treeNodes).returnObjMode();

} catch (Exception e) {

log.error(e.getMessage());

return ViewMode.getInstance().setError(e.getMessage()).returnObjMode();

}

}

访问结果:

最终树形菜单效果:

以上是 bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织? 的全部内容, 来源链接: utcz.com/z/354588.html

回到顶部