本文记录的只是我自己当时的代码,每行的注释很清楚了,你自己可以做相应变通

一、使用前提:

1、下载jstree依赖包

2、相关页面引入样式["jstree/themes/default/style.css"]、js["jstree/jstree.js"]

3、页面声明一个空div  <div id="sortTree"></div>

二、对应的代码

1、树的初始化及相关的操作

$(function () {
/**
* 该树分为三层为 --项目
* --项目文档分类
* --分类下具体文档
* 即项目在1级、文档分类在2级、文档在3级
*/
//项目的上下文,在上面提到的页面中
var contextPath = $('#contextPath').val();
//树的当前操作节点级别(实际上就是树的1级或2级或其他)
var beforeLevel = null;
//树的目标操作节点级别
var targetLevel = null;
//节点拖动的目标地址位置下标
var targetPosition = null;
//页面中树div的dom
var tree = $('#sortTree');
//树的初始化
tree.on('move_node.jstree', function (event, data) { //以下是节点的移动事件要触发的操作
var targetId = data.parent;
var sourceId = data.node.id;
targetPosition = data.position;
//分类移动
if(beforeLevel == 2) {
$.ajax({
type: "POST",
url: contextPath + "/docclassify/move",
data: {"docClassifyId": sourceId, "helpDocSystemId": targetId, "targetPosition": targetPosition},
dataType: "json",
success: function (res) {
layer.msg(res.message);
}
})
} else if(beforeLevel == 3) { //文档移动
$.ajax({
type: "POST",
url: contextPath + "/helpDoc/move",
data: {"helpDocId": sourceId, "docClassifyId": targetId, "targetPosition": targetPosition},
dataType: "json",
success: function (res) {
layer.msg(res.message);
}
})
}
}).jstree({
"core":{ //树的事件方法回调
"check_callback": function (op, node, parent) {
beforeLevel = $('#'+node.id).attr("aria-level");
targetLevel = $('#'+parent.id).attr("aria-level");
if(beforeLevel == 3 && targetLevel == 1) { //文档不能直接移到项目下
layer.msg("文档需要移动到分类");
return false;
} else if(beforeLevel == 3 && targetLevel == 3) { // 文档不能移到文档
return false;
} else if(beforeLevel == 2 && targetLevel == 2) { // 分类不能移到分类
return false;
} else if(beforeLevel == 2 && targetLevel == 3) { // 分类不能移到文档
return false;
} else if(beforeLevel == 1 ) { //我这边遇到的问题就是第1级节点,也就是所有项目节点不能拖动,所以我在下面把项目的排序变为右键点击出现上移下移菜单来处理
return false;
}
},
data: function (obj, callback) { //初始化树的第1级数据,即所有有序排列的项目
var jsonStr = "[]";
var jsonArray = eval(jsonStr);
$.ajax({
type: "GET",
url: contextPath + "/helpdocsystem/initTree",
dataType: "json",
success: function (res) {
var arrays = res.result;
for (var i = 0; i < arrays.length; i++) {
var arr = {
"id": arrays[i].id,
"parent": "#",
"text": arrays[i].name,
"icon": "icon iconfont icon-report-type",
"index": arrays[i].index //数据库中的数据排序字段
}
jsonArray.push(arr);
}
callback.call(this, jsonArray);
}
});
}
},
"contexmenu": { //右键菜单
"item": function (node) {
var temp = {
"上移": {
"lable": "上移",
"action": function () {
$.ajax({
type: "POST",
url: contextPath + "/helpdocsystem/order",
data: {"docSystemId": node.id, "moveFlag": 1},
dataType: "json",
success: function (res) {
layer.msg(res.message);
//刷新树
tree.jstree(true).refresh();
}
})
}
},
"下移": {
"lable": "下移",
"action": function () {
$.ajax({
type: "POST",
url: contextPath + "/helpdocsystem/order",
data: {"docSystemId": node.id, "moveFlag": 0},
dataType: "json",
success: function (res) {
layer.msg(res.message);
//刷新树
tree.jstree(true).refresh();
}
})
}
}
};
var menu = {};
var level = $('#'+node.id).attr("aria-level");
//此处限制节点为1级时才允许出现右键菜单
(level == 1) && (menu = temp);
return menu;
}
},
"plugins": ["sort", "contextmenu", "dnd", "state"], //依次为排序、右键菜单、拖拽移动、状态组件
"sort": function (a, b) {
return a['index'] - b['index'];
}
}).bind("select_node.jstree", function (event, data) {
var instant = data.instance;
var selectedNode = instant.get_node(data.selected);
var level = $('#'+selectNode.id).attr("aria-level");
if(parseInt(level) == 2) { //点击2级节点,加载分类下的文档
loadHelpDoc(instant, selectedNode);
}
if(parseInt(level) == 1) { //点击1级节点,加载项目下的文档分类
loadDocClassify(instant, selectedNode);
}
}); /**
* 加载分类下文档
* @param instant
* @param selectNode
*/
function loadHelpDoc(instant, selectedNode) {
$.ajax({
type: "GET",
url: contextPath + "/helpdoc/initTree",
data: {"docClassifyId": selectedNode.id},
dataType: "json",
success: function (res) {
var data = res.result;
if(null != data && data.length > 0) {
selectedNode.children = [];
$.each(data, function (i, item) {
var obj = {
"id": item.id,
"parent": item.parentId,
"text": item.name,
"icon": "icon iconfont icon-over-task"
};
instant.create_node(selectedNode, obj, "last"); //创建子节点
if($("#"+selectedNode.id).hasClass("jstree-open")){ //打开关闭节点
instant.close_node(selectedNode);
} else if($("#"+selectedNode.id).hasClass("jstree-closed")) {
instant.open_node(selectedNode);
}
});
}
}
})
} /**
* 加载项目下文档分类
* @param instant
* @param selectNode
*/
function loadDocClassify(instant, selectedNode) {
$.ajax({
type: "GET",
url: contextPath + "/docclassify/initTree",
data: {"helpDocSystemId": selectedNode.id},
dataType: "json",
success: function (res) {
var data = res.result;
if(null != data && data.length > 0) {
selectedNode.children = [];
$.each(data, function (i, item) {
var obj = {
"id": item.id,
"parent": item.parentId,
"text": item.name,
"icon": "icon iconfont icon-report-type"
};
instant.create_node(selectedNode, obj, "last"); //创建子节点
if($("#"+selectedNode.id).hasClass("jstree-open")){ //打开关闭节点
instant.close_node(selectedNode);
} else if($("#"+selectedNode.id).hasClass("jstree-closed")) {
instant.open_node(selectedNode);
}
});
}
}
});
}
});

还是贴一下一个接口排序的例子,当时写的确实有点烦,以免以后会忘;initTree相关接口就是关联查询出的有序集合,拼接成需要格式数据即可。

在这把排序可以理解成往一个有序的list中的某个位置插入元素,假如插入元素a,i作为目标位置,那么a元素的实际orderNo为list(i-1).getOrderNo() + 1,那么i位置以下的节点orderNo依次为i+1

需要注意的地方:1、目标位置为0时做了处理,a元素实际位置从1开始;2、目标元素的所有下级元素orderNo增加时需要排除目标元素

1、/docclassify/move

@PostMapping("/docclassify/move")
public String move(DocClassifyVo docClassifyVo, int targetPosition, Model model) {
try {
if (StringUtils.isNotEmpty(docClassifyVo.getHelpDocSystemId)) {
this.docClassifyManager.move(docClassifyVo, targetPosition);
model.addAttribute("message", "移动成功");
}
} catch (Exception e) {
e.printStackTrace();
model.addAttribute("message", "移动失败");
}
return "json";
}
public void move(DocClassifyVo docClassifyVo, int targetPosition) {
DocClassify docClassify = this.docClassifyService.findById(docClassifyVo.getDocClassifyId());
HelpDocSystem helpDocSystem = new HelpDocSystem();
helpDocSystem.setHelpDocSystemId(docClassifyVo.getHelpDocSystemId());
docClassify.setHelpDocSystem(helpDocSystem);
docClassify.setOrderNo(this.docClassifyService.getMaxOrderByHelpDocSystemId(docClassifyVo.getHelpDocSystemId) + 1);
this.docClassifyService.update(docClassify); //按orderNo升序查询该项目下的所有分类
DocClassifyQo docClassifyQo = new DocClassifyQo();
docClassifyQo.setHelpDocSystemId(docClassifyVo.getHelpDocSystemId());
List<DocClassify> docClassifies = this.docClassifyService.queryPageList(docClassifyQo);
if(CollectionUtils.isNotEmpty(docClassifies)) {
for (int i = 0; i < docClassifies.size(); i++) {
if(docClassifies.get(i).getDocClassifyId().equals(docClassifyVo.getDocClassifyId())) {
List<DocClassify> batchUpdateList = new ArrayList<>();
//目标节点上级
DocClassify upDocClassify = null;
//目标节点
DocClassify targetDocClassify = docClassifies.get(i);
int realTargetPosition = 0;
int tempTargetPosition = 0;
if(targetPosition != 0) {
upDocClassify = docClassifies.get(targetPosition - 1);
tempTargetPosition = upDocClassify.getOrderNo() + 1;
realTargetPosition = upDocClassify.getOrderNo() + 1;
targetDocClassify.setOrderNo(realTargetPosition);
} else {
upDocClassify = docClassifies.get(targetPosition);
//移动到第一个时从1开始计算
tempTargetPosition = 1;
realTargetPosition = 1;
targetDocClassify.setOrderNo(realTargetPosition);
}
this.docClassifyService.update(targetDocClassify);
//目标节点所有下级
List<DocClassify> afterDocClassifies = this.docClassifyService.queryPageList(docClassifyQo);
for (int j = targetPosition; j < afterDocClassifies.size(); j++) {
if(!afterDocClassifies.get(i).getDocClassifyId().equals(docClassifyVo.getDocClassifyId())) {
DocClassify downDocClassify = afterDocClassifies.get(j);
downDocClassify.setOrderNo(++tempTargetPosition);
batchUpdateList.add(downDocClassify);
}
}
batchUpdateList.add(targetDocClassify);
this.docClassifyService.batchUpdate(batchUpdateList);
break;
}
}
}
//重新设置orderNo,避免排序次数多了后orderNo不连续
List<DocClassify> beforeDocClassifies = this.docClassifyService.queryPageList(docClassifyQo);
List<DocClassify> batchUpdateList = new ArrayList<>();
if(CollectionUtils.isNotEmpty(beforeDocClassifies)) {
for (int i = targetPosition; i < beforeDocClassifies.size(); i++) {
DocClassify sortDocClassify = beforeDocClassifies.get(i);
downDocClassify.setOrderNo(i+1);
batchUpdateList.add(sortDocClassify);
}
this.docClassifyService.batchUpdate(batchUpdateList);
} }

2、/helpdocsystem/order

关于项目排序由于我们采用的是右键上移下移的操作,所以排序的算法也就没那么复杂,上移时moveFlag为1,下移时moveFlag为0。上移时取移动节点的前一个节点(i-1)的orderNo,下移时orderNo则为(i+1)
,互相交换orderNo更新即可
public void order(String docSystemId, int moveFlag) {
//按orderNo升序查询该所有项目
HelpDocSystemQo helpDocSystemQo = new HelpDocSystemQo();
PageList<HelpDocSystemQo> helpDocSystems = this.helpDocSystemService.queryPageList(helpDocSystemQo);
if(CollectionUtils.isNotEmpty(helpDocSystems)) {
List<HelpDocSystem> batchUpdateList = new ArrayList<>();
for (int i = 0; i < helpDocSystems.size(); i++) {
if(helpDocSystems.get(i).getHelpDocSystemId().equals(docSystemId)) {
if(i == 0 && moveFlag == 1) {
throw new RuntimeException("到顶了,不能再移动了");
}
if(i == helpDocSystems.size() - 1 && moveFlag == 0) {
throw new RuntimeException("到底了,不能再移动了");
}
HelpDocSystem sourceHelpDocSystem = helpDocSystems.get(i);
HelpDocSystem targetHelpDocSystem = null;
if(moveFlag == 1) {
targetHelpDocSystem = helpDocSystems.get(i - 1);
} else {
targetHelpDocSystem = helpDocSystems.get(i + 1);
}
int sourceOrderNo = sourceHelpDocSystem.getOrderNo();
int targetOrderNo = targetHelpDocSystem.getOrderNo();
sourceHelpDocSystem.setOrderNo(targetOrderNo);
targetHelpDocSystem.setOrderNo(sourceOrderNo);
batchUpdateList.add(sourceHelpDocSystem);
batchUpdateList.add(targetHelpDocSystem);
this.helpDocSystemService.batchUpdate(batchUpdateList);
}
}
}
}

树组件——jstree使用的更多相关文章

  1. 基于HTML5树组件延迟加载技术实现

    HT for Web的HTML5树组件有延迟加载的功能,这个功能对于那些需要从服务器读取具有层级依赖关系数据时非常有用,需要获取数据的时候再向服务器发起请求,这样可减轻服务器压力,同时也减少了浏览器的 ...

  2. HT for Web的HTML5树组件延迟加载技术实现

    HT for Web的HTML5树组件有延迟加载的功能,这个功能对于那些需要从服务器读取具有层级依赖关系数据时非常有用,需要获取数据的时候再向服务器发起请求,这样可减轻服务器压力,同时也减少了浏览器的 ...

  3. GUI树组件,表格

    树组件首先要new一个JTree,再加结点,然后添加到 JScrollPane JTree tree1=new JTree(); //.......添加节点 add(new ScrollPane(tr ...

  4. Tree( 树) 组件[4]

    本节课重点了解 EasyUI 中 Tree(树)组件的使用方法, 这个组件依赖于 Draggable(拖动)和 Droppable(放置)组件.一.方法列表 //部分方法onClick : funct ...

  5. Tree( 树) 组件[3]

    本节课重点了解 EasyUI 中 Tree(树)组件的使用方法, 这个组件依赖于 Draggable(拖动)和 Droppable(放置)组件.一. 事件列表很多事件的回调函数都包含'node'参数, ...

  6. Tree( 树) 组件[2]

    本节课重点了解 EasyUI 中 Tree(树)组件的使用方法, 这个组件依赖于 Draggable(拖动)和 Droppable(放置)组件.一. 异步加载如果想从数据库里获取导航内容, 那么就必须 ...

  7. Tree( 树) 组件[1]

    本节课重点了解 EasyUI 中 Tree(树)组件的使用方法, 这个组件依赖于 Draggable(拖动)和 Droppable(放置)组件. 一. 加载方式//class 加载方式<ul c ...

  8. Omi树组件omi-tree编写指南

    Omi框架能够以少量的代码声明式地编写可拖拽移动节点的树形组件. 通常树组件能够考验UI框架的健壮性,因为需要使用到UI框架的如下特性: 组件嵌套 组件传值 组件批量传值 组件依赖自身递归嵌套(nes ...

  9. 自己封装element-ui树组件的过滤

    前言:vue开发项目时用到了element-ui的树组件,但是发现一执行过滤事件,树就全部都展开了,为了解决这个问题,只能自己先过滤数剧,再赋值给树组件的data,就避免了一上来全部展开的尴尬. 一. ...

随机推荐

  1. 阿里云主机centos7系统创建SWAP区,并启动挂载(适合无SWAP区虚拟化平台)

    以root用户登录建立交换区文件: fallocate -l 2G /swapfile /swapfile //赋予仅root用户的权限,确保安全 mkswap /swapfile swapon /s ...

  2. PTA A1016

    A1016 Phone Bills (25 分) 题目内容 A long-distance telephone company charges its customers by the followi ...

  3. :阿里巴巴 Java 开发手册 (十一)工程结构

    (一) 应用分层 1. [推荐]图中默认上层依赖于下层,箭头关系表示可直接依赖,如:开放接口层可以依赖于 Web 层,也可以直接依赖于 Service 层,依此类推:  开放接口层:可直接封装 Se ...

  4. (转)微服务_创建一个简单的Eureka注册中心

    原文地址:https://www.cnblogs.com/lplshermie/p/9105329.html 微服务和分布式已经成了一种极其普遍的技术,为了跟上时代的步伐,最近开始着手学习Spring ...

  5. 使用NODEJS实现JSONP的实例

    JSONP与JSON只有一字之差,我们在使用Jquery的Ajax调用的时候也是使用相同的方法来调用,两者的区别几乎只在于使用的dataType这个属性的不同.但是实际上JSON和JSONP是完全不同 ...

  6. honeyd使用

    honeyd可以同时模仿上千个不同的计算机 官网 honeyd-1.5c.tar.gz:http://www.honeyd.org 依赖包 libevent-1.3a.tar.gz:http://li ...

  7. sqlserver 备份集中的数据库备份与现有的 'XXX' 数据库不同。

    需求是将Ecology复制一份出来用于发布测试程序. 方案一 正确步骤 1.新建数据库Ecology2 2.选中Ecology2 点击右键:任务--还原--文件和文件组 选中源设备--点击右侧...按 ...

  8. zookeeper的安装使用

    转载从:https://blog.csdn.net/shenlan211314/article/details/6170717 一.zookeeper 介绍 ZooKeeper 是一个为分布式应用所设 ...

  9. QQ推广工具

    目前比较简单易用的QQ推广工具有:一键加群.在线聊天 一.一键加群 1.官网链接 http://qun.qq.com/join.html 2.使用 1登录自己的QQ 2创建一个想要作为推广的群 3选择 ...

  10. windows10 进入BIOS

    windows10开机进入不了BIOS 原因 上网查了电脑固件所应该有的进入键,什么F1.F2.F12.Delete以及什么要配置Fn+F1...等等方法就是开机进入不了BIOS. 解决办法 最后发现 ...