最近在做仓储的功能,需要实现对仓库树的拖拽功能,测试了很长时间才完成,后端使用了SpringMVC + Spring Data Jpa图片和代码展示如下:
拖拽前
拖拽中
拖拽后

Jsp程序

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="/common/taglibs.jsp"%>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="renderer" content="webkit">
    <title>物品分类</title>
    <style>
        .ztree * {font-size:14px !important;}
    </style>
</head>
<body style="background: #f1f1f1;border:1px solid #f1f1f1;">
    <div class="row" id="page_content">
        <div class="col-sm-12">
            <div class="ibox float-e-margins">
                <div class="ibox-title">
                    <h3>物品分类</h3>
                </div>
                <div class="ibox-content">
                    <div class="col-sm-12 no-padding" id="tree">
                        <div class="zTreeDemoBackground left">
                            <ul id="treeDemo" class="ztree" url="${ctx}/baseinfo/wpfl/renderTree"></ul>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <input type="hidden" id="wpflOrCkgl" value="wpfl">
    <script type="text/javascript">
    var wpfl = true;
    var ckgl = false;
    var modal = {
        saveURL : "${ctx}/baseinfo/wpfl",
        deleteURL: "${ctx}/baseinfo/wpfl/delete",
        sameLevel: "${ctx}/baseinfo/wpfl/sameLevel",
        differentLevel:"${ctx}/baseinfo/wpfl/differentLevel",
        diffLevel:"${ctx}/baseinfo/wpfl/diffLevel",
        checkURL:"${ctx}/baseinfo/wpfl/check"
    }
    </script>
</body>
</html>    

JS代码

var setting = {
    view: {
        addHoverDom: addHoverDom,
        removeHoverDom: removeHoverDom,
        selectedMulti: false,
        showLine: false,
        showIcon: showIconForTree
    },
    edit: {
        drag: {
            autoExpandTrigger: true,
            prev: dropPrev,
            inner: dropInner,
            next: dropNext
        },
        enable: true,
        editNameSelectAll: true,
        showRemoveBtn : showRemoveBtn,
        showRenameBtn : showRenameBtn
    },
    data: {
        simpleData: {
            enable: true
        }
    },
    callback: {
        beforeDrag: beforeDrag,
        beforeEditName: beforeEditName,
        beforeRemove: beforeRemove,
        beforeRename: beforeRename,
        onRemove: onRemove,
        onRename: onRename,
        beforeDrop: beforeDrop,
        beforeDragOpen: beforeDragOpen,
        onDrag: onDrag,
        onDrop: onDrop,
        onExpand: onExpand,
        onAsyncSuccess: zTreeOnAsyncSuccess,
    },
    async: {
        enable: true,
        type: "get",
        //表示异步加载采用 post 方法请求
        url: $("#treeDemo").attr("url"),
        autoParam: ["id", "type"] //传递节点的id 和 type值给后台(当异步加载数据时)
    }
};

/**数异步加载成功*/
function zTreeOnAsyncSuccess(event, treeId, node, msg) {
    var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
    var nodes = treeObj.getNodes();
    // 异步展开一级子节点
    if (nodes.length > 0) {
        treeObj.expandNode(nodes[0], true, false, false);
    }
}

var log, className = "dark";
function beforeDrag(treeId, treeNodes) {
    return false;
}
function beforeEditName(treeId, treeNode) {
    className = (className === "dark" ? "":"dark");
    showLog("[ "+getTime()+" beforeEditName ]&nbsp;&nbsp;&nbsp;&nbsp; " + treeNode.name);
    var zTree = $.fn.zTree.getZTreeObj("treeDemo");
    zTree.selectNode(treeNode);
    return;
}
function beforeRemove(treeId, treeNode) {
    className = (className === "dark" ? "":"dark");
    showLog("[ "+getTime()+" beforeRemove ]&nbsp;&nbsp;&nbsp;&nbsp; " + treeNode.name);
    var zTree = $.fn.zTree.getZTreeObj("treeDemo");
    zTree.selectNode(treeNode);
    var flag = false;
    if(confirm("确认删除 节点 -- " + treeNode.name + " 吗?")){

        // 删除节点
        flag=delNode(modal,treeNode.id);
    }
    return flag;
}
function onRemove(e, treeId, treeNode) {
    showLog("[ "+getTime()+" onRemove ]&nbsp;&nbsp;&nbsp;&nbsp; " + treeNode.name);
}
function beforeRename(treeId, treeNode, newName, isCancel) {
    className = (className === "dark" ? "":"dark");
    showLog((isCancel ? "<span style='color:red'>":"") + "[ "+getTime()+" beforeRename ]&nbsp;&nbsp;&nbsp;&nbsp; " + treeNode.name + (isCancel ? "</span>":""));
    if (newName.length == 0) {
        alert("节点名称不能为空.");
        var zTree = $.fn.zTree.getZTreeObj("treeDemo");
        setTimeout(function(){zTree.editName(treeNode)}, 10);
        return false;
    }
    else if(newName.length > 20){
        confirm("名称长度在20字以内");
        return false;
    }

    // 修改的名字没变
    if(treeNode.name == newName){
        return true;
    }

    // 判断是否重名
    var flag1 = check(newName);
    if(flag1 == false){
        alert("名称不能重复");
        return false;
    }
    return true;
}
function onRename(e, treeId, treeNode, isCancel) {
    showLog((isCancel ? "<span style='color:red'>":"") + "[ "+getTime()+" onRename ]&nbsp;&nbsp;&nbsp;&nbsp; " + treeNode.name + (isCancel ? "</span>":""));
    if(treeNode.type == 'add'){ // 新增节点
        nodeAdd(treeNode); 
        treeNode.type='edit';
    }else{ // 编辑节点
        nodeEdit(treeNode);
    }
}
function showIconForTree(treeId, treeNode) {
    return !treeNode.isParent;
}
function showLog(str) {
    if (!log) log = $("#log");
    log.append("<li class='"+className+"'>"+str+"</li>");
    if(log.children("li").length > 8) {
        log.get(0).removeChild(log.children("li")[0]);
    }
}
function getTime() {
    var now= new Date(),
        h=now.getHours(),
        m=now.getMinutes(),
        s=now.getSeconds(),
        ms=now.getMilliseconds();
    return (h+":"+m+":"+s+ " " +ms);
}

var newCount = 1;

/** 是否显示编辑按钮 */
function showRenameBtn(treeId, treeNode){
    // 根节点不显示编辑按钮
    if(treeNode.level == 0){
        return false;
    }else{
        return true;
    }
}
/** 是否显示删除按钮 */
function showRemoveBtn(treeId, treeNode){
    // 根节点不显示删除按钮
    if(treeNode.level == 0){
        return false;
    }else{
        return true;
    }
}

/** 新增节点 */
function addHoverDom(treeId, treeNode) {
    if(wpfl == true && treeNode.level == 3){ // 物品分类最多支持三级
        return;
    }else if(ckgl == true && treeNode.level == 2){ // 仓库管理最多支持二级
        return;
    }
    var sObj = $("#" + treeNode.tId + "_span");
    if (treeNode.editNameFlag || $("#addBtn_"+treeNode.tId).length>0) return;
    var addStr = "<span class='button add' id='addBtn_" + treeNode.tId
        + "' title='新增' onfocus='this.blur();'></span>";
    sObj.after(addStr);
    var btn = $("#addBtn_"+treeNode.tId);
    if (btn) btn.bind("click", function(){
        var zTree = $.fn.zTree.getZTreeObj("treeDemo");
        var newName = "new node" + (newCount++);
        zTree.addNodes(treeNode, {id:(100 + newCount), pId:treeNode.id, name:newName,type : 'add'});
        var newNode=treeNode.children[treeNode.children.length-1];
        zTree.editName(newNode);

        return false;
    });
}
function removeHoverDom(treeId, treeNode) {
    $("#addBtn_"+treeNode.tId).unbind().remove();
}
function selectAll() {
    var zTree = $.fn.zTree.getZTreeObj("treeDemo");
    zTree.setting.edit.editNameSelectAll =  $("#selectAll").attr("checked");
}
function dropPrev(treeId, nodes, targetNode) {
    var pNode = targetNode.getParentNode();
    if (pNode && pNode.dropInner === false) {
        return false;
    } else {
        for (var i=0,l=curDragNodes.length; i<l; i++) {
            var curPNode = curDragNodes[i].getParentNode();
            if (curPNode && curPNode !== targetNode.getParentNode() && curPNode.childOuter === false) {
                return false;
            }
        }
    }
    return true;
}
function dropInner(treeId, nodes, targetNode) {
    if (targetNode && targetNode.dropInner === false) {
        return false;
    } else {
        for (var i=0,l=curDragNodes.length; i<l; i++) {
            if (!targetNode && curDragNodes[i].dropRoot === false) {
                return false;
            } else if (curDragNodes[i].parentTId && curDragNodes[i].getParentNode() !== targetNode && curDragNodes[i].getParentNode().childOuter === false) {
                return false;
            }
        }
    }
    return true;
}
function dropNext(treeId, nodes, targetNode) {
    var pNode = targetNode.getParentNode();
    if (pNode && pNode.dropInner === false) {
        return false;
    } else {
        for (var i=0,l=curDragNodes.length; i<l; i++) {
            var curPNode = curDragNodes[i].getParentNode();
            if (curPNode && curPNode !== targetNode.getParentNode() && curPNode.childOuter === false) {
                return false;
            }
        }
    }
    return true;
}

var log, className = "dark", curDragNodes, autoExpandNode;
var dragId ; //拖拽节点的父节点的id
/** 拖拽前执行 */
function beforeDrag(treeId, treeNodes) {
    className = (className === "dark" ? "":"dark");
    showLog("[ "+getTime()+" beforeDrag ]&nbsp;&nbsp;&nbsp;&nbsp; drag: " + treeNodes.length + " nodes." );
    for (var i=0,l=treeNodes.length; i<l; i++) {
        dragId = treeNodes[i].pId;
        if (treeNodes[i].drag === false) {
            curDragNodes = null;
            return false;
        } else if (treeNodes[i].parentTId && treeNodes[i].getParentNode().childDrag === false) {
            curDragNodes = null;
            return false;
        }
    }
    curDragNodes = treeNodes;
    return true;
}
function beforeDragOpen(treeId, treeNode) {
    autoExpandNode = treeNode;
    return true;
}

/** 拖拽释放之后执行 */
function beforeDrop(treeId, treeNodes, targetNode, moveType, isCopy) {
    className = (className === "dark" ? "":"dark");
    showLog("[ "+getTime()+" beforeDrop ]&nbsp;&nbsp;&nbsp;&nbsp; moveType:" + moveType);
    showLog("target: " + (targetNode ? targetNode.name : "root") + "  -- is "+ (isCopy==null? "cancel" : isCopy ? "copy" : "move"));

  if(dragId == targetNode.pId && moveType != 'inner'){// 同级位置调整
      var data = 'pId='+dragId+'&currentNodeId='+treeNodes[0].id+'&newNodeId='+targetNode.id+'&moveType='+moveType;
      nodeExchange(data,modal.sameLevel);
  }else if(moveType == 'inner'){ // 一个节点变成另一个节点的子节点
      // 不能移到仓库管理第二节点,物品分类第三节点
      if((ckgl == true && targetNode.level == 2) || (wpfl == true && targetNode.level == 3)){
          return false;
      }else{
          var data = 'currentNodeId='+treeNodes[0].id+'&newParentNodeId='+targetNode.id;
      }
      nodeExchange(data,modal.differentLevel);
  }else if(dragId != targetNode.pId && moveType != 'inner'){ // 不同级之间的调整
      var flag1 = canMove(treeNodes[0].id);
      if(flag1 == false){
          alert("您选择的节点已经被引用,不能被拖动");
          return false;
      }

    // 物品管理最高3级,仓库管理最高2级  isParent
      if(ckgl == true && treeNodes[0].pId == 0 && targetNode.level == 2){
          alert("最多支持二级分类");
          return false;
      }else if((wpfl == true && targetNode.level == 3 && treeNodes[0].isParent == true) || (wpfl == true && targetNode.level == 2 && treeNodes[0].pId == 0)){
          alert("最多支持三级分类");
          return false;
      }
      var data = 'currentNodeId='+treeNodes[0].id+'&newNodeId='+targetNode.id+'&moveType='+moveType;
      nodeExchange(data,modal.diffLevel);
  }
    return true;
}
function onDrag(event, treeId, treeNodes) {
    className = (className === "dark" ? "":"dark");
    showLog("[ "+getTime()+" onDrag ]&nbsp;&nbsp;&nbsp;&nbsp; drag: " + treeNodes.length + " nodes." );
}
function onDrop(event, treeId, treeNodes, targetNode, moveType, isCopy) {
    className = (className === "dark" ? "":"dark");
    showLog("[ "+getTime()+" onDrop ]&nbsp;&nbsp;&nbsp;&nbsp; moveType:" + moveType);
    showLog("target: " + (targetNode ? targetNode.name : "root") + "  -- is "+ (isCopy==null? "cancel" : isCopy ? "copy" : "move"))
}
function onExpand(event, treeId, treeNode) {
    if (treeNode === autoExpandNode) {
        className = (className === "dark" ? "":"dark");
        showLog("[ "+getTime()+" onExpand ]&nbsp;&nbsp;&nbsp;&nbsp;" + treeNode.name);
    }
}

function showLog(str) {
    if (!log) log = $("#log");
    log.append("<li class='"+className+"'>"+str+"</li>");
    if(log.children("li").length > 8) {
        log.get(0).removeChild(log.children("li")[0]);
    }
}
function getTime() {
    var now= new Date(),
        h=now.getHours(),
        m=now.getMinutes(),
        s=now.getSeconds(),
        ms=now.getMilliseconds();
    return (h+":"+m+":"+s+ " " +ms);
}

function setTrigger() {
    var zTree = $.fn.zTree.getZTreeObj("treeDemo");
    zTree.setting.edit.drag.autoExpandTrigger = $("#callbackTrigger").attr("checked");
}

/** 鼠标移入移出显示操作图标 */
function over(aa){
    $(aa).children(".hides").css("display","block");
}
function out(aa){
    $(aa).children(".hides").css("display","none");
}

function change_bgcolor(aa){
    $(aa).addClass("active")
        .parent().siblings().children().removeClass("active");
    $("#table-body").animate({
        scrollTop:'0px',
        scrollLeft:'0px'
    },0);
}

/** 点击物品分类 */
function kind_click(a,b,c){
    $(a).addClass("active").parent().siblings().children().removeClass("active");
    var oUl = $(a).parent().parent();
    var oDiv = oUl.parent();
    if(oUl.index() == 0){
        $(".show_kind").children("span").html('');
        $(".show_kind").children("span").eq(0).html($(a).html());
    }
    else if(oUl.index() == 1){
        if(oDiv.children("ul").eq(0).find(".active").length){
            $(".show_kind").children("span").eq(oUl.index()).html("-> "+$(a).html());
            $(".show_kind").children("span").eq(2).html('');
        }
        else{
            confirm("请选中上一级菜单,再点击");
        }
    }else{
         if(oUl.index() == 2 && oDiv.children("ul").eq(0).find(".active").length && oDiv.children("ul").eq(1).find(".active").length){
             $(".show_kind").children("span").eq(oUl.index()).html("-> "+$(a).html());
         }
         else{
             confirm("请选中上一级菜单,再点击");
         }
    }
    myKindClick(a,b,c);
}

/** 删除table记录 */
function delete_tr(p){
    var y=p.parentNode.parentNode;
    y.parentNode.removeChild(y);//只能上找一层parentNode
    againPx();
}

/** 重新排序 */
function againPx(){
    var index = 1;
    $("td[name='px']").each(function(){
        $(this).find('span').html(index);
        index++;
    });
}

/** 新增节点 */
function nodeAdd(treeNode){
    $.ajax({
        type: 'post',
        url: modal.saveURL,
        data: {
            'id':null,
            'sjfl':treeNode.pId,
            'mc':treeNode.name
        },
        dataType: 'json',
//        async : false,
        traditional: true,
        success: function(result) {
            if (result.success) {
                var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
                var obj=result.data.obj;
                treeNode.id = obj['id'];
                treeNode.pId = obj['sjfl'];
                treeObj.updateNode(treeNode);

                showRemindMsg();

                try {
                    mySave(modal);
                } catch(e) {}
            } else {
                alert(result.errorMsg);
            }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            btn.disabled = false;
            alert("请求异常");
        }
    });
}

/** 编辑节点 */
function nodeEdit(treeNode){
    $.ajax({
        type: 'post',
        url: modal.saveURL,
        data: {
            'id':treeNode.id,
            'sjfl':treeNode.pId,
            'mc':treeNode.name
        },
        dataType: 'json',
        traditional: true,
        success: function(result) {
//            btn.disabled = false;

            if (result.success) {

                showRemindMsg();

                try {
                    mySave(modal);
                } catch(e) {}
            } else {
                alert(result.errorMsg);
            }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            btn.disabled = false;
            alert("请求异常");
        }
    });
}

/**执行删除*/
function delNode(modal, id) {
    var flag=true;
    $.ajax({
        type: 'post',
        url: modal.deleteURL,
        data: {
            ids: id
        },
        async:false,
        dataType: 'json',
        traditional: true,
        success: function(result) {
            if (result.success) {
                showRemindMsg();
            } else {
                flag = false;
                if (result.errorMsg.indexOf("ConstraintViolationException") > 0) {
                    alert("您选择的记录已经被引用,不能被删除");
                }

            }
        }
    });
    return flag;
}
/** 节点位置调换 */
function nodeExchange(data,ways){
      $.ajax({
             type:"get",
             data:data,
             url: ways,
             dataType:'json',
             success: function(result) {
                if (result.success) {
                    showRemindMsg();

                    try {
                        mySave(modal);
                    } catch(e) {}
                } else {
                    alert(result.errorMsg);
                }
             },
             error: function(XMLHttpRequest, textStatus, errorThrown) {
                 alert("请求异常");
             }


          });
}

/**
 * 验证节点名字唯一性
 * 
 * @param name
 * @returns {Boolean}
 */
function check(name){
    var flag = true;
    $.ajax({
        type: 'post',
        url: modal.checkURL,
        data: {
            name:name
        },
        dataType: 'json',
        traditional: true,
        async:false,
        success: function(result) {
            if (result.success) {
                var check = result.data.check;
                if(check == false){
                    flag = false;
                }else{
                    flag = true;
                }
                try {
                    mySave(modal);
                } catch(e) {}
            } else {
                alert(result.errorMsg);
            }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            btn.disabled = false;
            alert("请求异常");
        }
    });
    return flag;
}

/**
 * 仓库管理二级节点被引用的不能被拖动
 * @param kfkwId
 * @returns {Boolean}
 */
function canMove(kfkwId){
    var flag = true;
    $.ajax({
        type: 'get',
        url: modal.canMoveURL,
        data: {
            id:kfkwId
        },
        dataType: 'json',
        traditional: true,
        async:false,
        success: function(result) {
            if (result.success) {
                var can = result.data.canMove;
                if(can == false){
                    flag = false;
                }else{
                    flag = true;
                }
                try {
                    mySave(modal);
                } catch(e) {}
            } else {
                alert(result.errorMsg);
            }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            btn.disabled = false;
            alert("请求异常");
        }
    });
    return flag;
}

Controller代码

package com.dtyun.ccgl.web.controller.baseinfo;

/**
 * 仓库管理Controller
 * 
 * @author WangYuanJun
 */
@Controller
@RequestMapping(value = "/baseinfo/ckgl")
@FunctionModule(value = "仓库管理", entry = "/baseinfo/ckgl", parent = "基础数据")
public class KfkwController extends BaseController {

    /** 仓库管理Service */
    @Autowired
    private KfkwService kfkwService;

    /** 库存历史Service */
    @Autowired
    private KcglHisService kcglHisService;

    /** 系统配置Service */
    @Autowired
    private CcSysConfigService sysConfigService;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @RequestMapping(method = RequestMethod.GET)
    public String index(Model model) {
        CcSysConfigEntity sysConfigEntity= sysConfigService.findGjdmcBySchool(AuthUtils.getCurrentSchoolId());
        Boolean boolean1 = false;

        // 设置了仓库根节点名称
        if(sysConfigEntity != null){
            boolean1 = true;
        }
        model.addAttribute("ssxx", AuthUtils.getCurrentSchoolId());
        model.addAttribute("booleanSetGjdmc", boolean1);
        return "/baseinfo/ckgl/ckgl";
    }

    /**
     * 添加物品分类
     * 
     * @param dto
     * @param result
     * @return
     */
    @ResponseBody
    @RequestMapping(method = RequestMethod.POST)
    public Retval save(@Valid KfkwDto dto, BindingResult result) {
        Retval retval = Retval.newInstance();

        // 表单校验
        if (result.hasErrors()) {
            retval.fail(getErrorMessage(result));
            return retval;
        }

        // 保存
        try {
            // 当上级分类为0时,为一级目录
            if (dto.getSjfl() == null || dto.getSjfl() == 0) {
                dto.setSjfl(null);
            }
            KfkwEntity kfkwEntity = kfkwService.save(dto);
            retval.put("obj", kfkwEntity);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            retval.fail(e.getMessage());
        }
        return retval;
    }

    /**
     * 删除物品分类
     * 
     * @param ids
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    public Retval delete(@RequestParam Long[] ids) {
        Retval retval = Retval.newInstance();
        try {
            kfkwService.deleteByIds(ids);
        } catch (DataIntegrityViolationException e) {
            retval.fail(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            retval.fail(e.getMessage());
        }
        return retval;
    }

    /**
     * 判断被引用的二级节点能否被移动
     * 
     * @param id
     * @return
     */
    @ResponseBody
    @RequestMapping(value="/canMove",method=RequestMethod.GET)
    public Retval canMove(@RequestParam Long id){
        Retval retval = Retval.newInstance();
        Boolean boolean1 = kcglHisService.findKfkwById(id);
        retval.put("canMove", boolean1);
        return retval;
    }

    /**
     *同级之间拖拽
     *
     * @param pId 拖拽节点父节点id
     * @param currentNodeId 拖拽节点id
     * @param newNodeId 目标节点id
     * @param moveType 拖拽类型
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/sameLevel", method = RequestMethod.GET)
    public Retval sameLevel(@RequestParam Long pId, @RequestParam Long currentNodeId, @RequestParam Long newNodeId,
            @RequestParam String moveType) {
        Retval retval = Retval.newInstance();
        try {

            kfkwService.sameLevel(pId, currentNodeId, newNodeId, moveType);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            retval.fail(e.getMessage());
        }
        return retval;
    }

    /**
     * 拖拽节点成为目标节点的子节点
     * 
     * @param currentNodeId 拖拽节点id
     * @param newParentNodeId 目标父节点id
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/differentLevel", method = RequestMethod.GET)
    public Retval differentLevel(@RequestParam Long currentNodeId, @RequestParam Long newParentNodeId) {
        Retval retval = Retval.newInstance();
        try {
            kfkwService.differentLevel(currentNodeId, newParentNodeId);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            retval.fail(e.getMessage());
        }
        return retval;
    }

    /**
     * 不同级节点为位置调换
     * 
     * @param currentNodeId 被拖拽节点id
     * @param newNodeId 新的节点id
     * @param moveType
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/diffLevel", method = RequestMethod.GET)
    public Retval diffLevel(@RequestParam Long currentNodeId, @RequestParam Long newNodeId,@RequestParam String moveType) {
        Retval retval = Retval.newInstance();
        try {
             kfkwService.diffLevel(currentNodeId, newNodeId, moveType);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            retval.fail(e.getMessage());
        }
        return retval;
    }

    /**
     * 加载树
     * 
     * @param id
     * @param type
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "/renderTree", method = RequestMethod.GET)
    public List<Map<String, Object>> renderTree(Long id, String type) throws Exception {

        List<Map<String, Object>> returnList = new ArrayList<Map<String, Object>>();
        CcSysConfigEntity sysConfigEntity= sysConfigService.findGjdmcBySchool(AuthUtils.getCurrentSchoolId());
        // 加载根节点
        if (StringUtils.isEmpty(id)) {
            Map<String, Object> root = new HashMap<String, Object>();

            root.put("id", 0);
            root.put("name", sysConfigEntity.getCckcgjdmc());
            root.put("isParent", true);

            // 加载一级节点
            List<Map<String, Object>> returnList1 = new ArrayList<Map<String, Object>>();
            List<KfkwEntity> list1 = kfkwService.findLeveL1Node();
            for (KfkwEntity kfkw : list1) {
                Map<String, Object> node = new HashMap<String, Object>();
                node.put("id", kfkw.getId());
                node.put("name", kfkw.getMc());
                Boolean isParent = kfkwService.hasSubNodeById(kfkw.getId());
                node.put("isParent", isParent);
                returnList1.add(node);
            }

            root.put("children", returnList1);
            returnList.add(root);

            return returnList;
        }

        // 加载子节点
        List<KfkwEntity> list = null;
        if (id != null && id > 0L) {
            list = kfkwService.findSubNodeById(id);
            for (KfkwEntity kfkw : list) {
                Map<String, Object> node = new HashMap<String, Object>();
                node.put("id", kfkw.getId());
                node.put("name", kfkw.getMc());
                Boolean isParent = kfkwService.hasSubNodeById(kfkw.getId());
                node.put("isParent", isParent);
                returnList.add(node);
            }
        }

        return returnList;
    }

    /**
     * 查重
     * 
     * @param name
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/check", method = RequestMethod.POST)
    public Retval check(@RequestParam String name) {
        Retval retval = Retval.newInstance();
        Boolean boolean1 = kfkwService.check(name);
        retval.put("check", boolean1);
        return retval;
    }

}

service代码

/**
 * 仓库管理Service
 * 
 * @author WangYuanJun
 */
@Service
public class KfkwService extends BaseService{

    /** 物品分类Dao */
    @Autowired
    private KfkwDao kfkwDao;


    /**
     * 找该级的子目录
     * 
     * @param sjfl
     * @return
     */
    public List<KfkwEntity> findByMaxPx(Long sjfl) {
        Sort sort = new Sort(Direction.DESC,"px");
        return kfkwDao.findAll(spc3(sjfl),sort);
    }

    public Specification<KfkwEntity> spc3(Long sjfl) {
        Specification<KfkwEntity> sp = new Specification<KfkwEntity>() {
            @Override
            public Predicate toPredicate(Root<KfkwEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = Lists.newArrayList();
                if(sjfl == null){
                    Predicate pSjfl = cb.isNull(root.get("sjfl").as(Long.class));
                    predicates.add(pSjfl);
                }else{
                    Predicate pSjfl = cb.equal(root.get("sjfl").as(Long.class), sjfl);
                    predicates.add(pSjfl);
                }
                Predicate pXx = cb.equal(root.get("ssxx").as(Long.class), getSchoolId());// 所属学校
                predicates.add(pXx);
                query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
                return query.getRestriction();
            }
        };
        return sp;
    }

    /**
     * 同级之间拖拽
     * 
     * @param pId 父节点
     * @param currentNodeId 拖拽的id
     * @param newNodeId 拖拽新的id
     */
    @Transactional
    public void sameLevel(Long pId, Long currentNodeId, Long newNodeId, String moveType) {
        // 将他们中间的影响的记录跟新

        if ("next".equals(moveType)) {
            KfkwEntity currentKfkw = kfkwDao.findOne(currentNodeId);
            KfkwEntity newKfkw = kfkwDao.findOne(newNodeId);
            // 向下拖拽
            if(currentKfkw.getPx()<newKfkw.getPx()){
                // 跟新受影响的记录
                List<KfkwEntity> kfkwList = findInfluenceData(pId, currentKfkw.getPx(), newKfkw.getPx());
                for (int i = 0; i < kfkwList.size(); i++) {
                    KfkwEntity kfkw = kfkwList.get(i);
                    if (!(kfkw.getId().equals(currentKfkw.getId())) && !(kfkw.getId().equals(newKfkw.getId()))) {
                        KfkwEntity kfkwEntity2 = kfkwDao.findOne(kfkw.getId());
                        kfkwEntity2.setPx(kfkwEntity2.getPx() - 1);
                        kfkwDao.save(kfkwEntity2);
                    }

                }
                // 拖拽节点排序变为目标节点的排序
                currentKfkw.setPx(newKfkw.getPx());
                kfkwDao.save(currentKfkw);
                // 目标排序节点排序为其排序-1
                newKfkw.setPx(newKfkw.getPx() - 1);
                kfkwDao.save(newKfkw);
            }else{

                // 向上拖拽,movetpe=next
                // 目标节点wpflList.get(0),去除目标节点,将目标节点的下一个节点变为目标节点
                List<KfkwEntity> kfkwList = findInfluenceData(pId, currentKfkw.getPx(), newKfkw.getPx());
                kfkwList.remove(0);
                KfkwEntity kfkwNew=kfkwDao.findOne(kfkwList.get(0).getId());
                int kfkwNewPx = kfkwNew.getPx();
                for (int i = 0; i < kfkwList.size(); i++) {
                    KfkwEntity kfkw = kfkwList.get(i);
                    if (!(kfkw.getId().equals(currentKfkw.getId())) ) {
                        KfkwEntity kfkwEntity2 = kfkwDao.findOne(kfkw.getId());
                        kfkwEntity2.setPx(kfkwEntity2.getPx() + 1);
                        kfkwDao.save(kfkwEntity2);
                    }
                }
                // 拖拽的排序变为目标节点排序
                currentKfkw.setPx(kfkwNewPx);
                kfkwDao.save(currentKfkw);
            }

        } else if ("prev".equals(moveType)) {
            KfkwEntity currentKfkw = kfkwDao.findOne(currentNodeId);
            KfkwEntity newKfkw = kfkwDao.findOne(newNodeId);
            // 向上拖拽
            if(currentKfkw.getPx()>newKfkw.getPx()){
                // 跟新受影响的记录
                List<KfkwEntity> kfkwList = findInfluenceData(pId, currentKfkw.getPx(), newKfkw.getPx());
                for (int i = 0; i < kfkwList.size(); i++) {
                    KfkwEntity kfkw = kfkwList.get(i);
                    if (!(kfkw.getId().equals(currentKfkw.getId())) && !(kfkw.getId().equals(newKfkw.getId()))) {
                        KfkwEntity kfkwEntity2 = kfkwDao.findOne(kfkw.getId());
                        kfkwEntity2.setPx(kfkwEntity2.getPx() + 1);
                        kfkwDao.save(kfkwEntity2);
                    }

                }
                // 拖拽的排序变为目标节点排序
                currentKfkw.setPx(newKfkw.getPx());
                kfkwDao.save(currentKfkw);
                // 目标排序的排序为其排序至+1
                newKfkw.setPx(newKfkw.getPx() + 1);
                kfkwDao.save(newKfkw);
            }else{
                    // 向下拖拽,movetype=prev
                    // 跟新受影响的记录
                     // 目标节点wpflList.get(最大值),去除目标节点,将目标节点的上一个节点变为目标节点
                    List<KfkwEntity> kfkwList = findInfluenceData(pId, currentKfkw.getPx(), newKfkw.getPx());
                    kfkwList.remove(kfkwList.size()-1);
                    KfkwEntity kfkwNew=kfkwDao.findOne(kfkwList.get(kfkwList.size()-1).getId()); //新的目标节点
                    int kfkwNewPx = kfkwNew.getPx();
                    for (int i = 0; i < kfkwList.size(); i++) {
                        KfkwEntity kfkw = kfkwList.get(i);
                        if (!(kfkw.getId().equals(currentKfkw.getId())) ) {
                            KfkwEntity kfkwEntity2 = kfkwDao.findOne(kfkw.getId());
                            kfkwEntity2.setPx(kfkwEntity2.getPx() - 1);
                            kfkwDao.save(kfkwEntity2);
                        }

                    }
                    // 拖拽节点排序变为目标节点的排序
                    currentKfkw.setPx(kfkwNewPx);
                    kfkwDao.save(currentKfkw);
            }

        }

    }

    public List<KfkwEntity> findInfluenceData(Long sjfl, Integer currentNodePx, Integer newNodePx) {
        Specification<KfkwEntity> spec = new Specification<KfkwEntity>() {

            @Override
            public Predicate toPredicate(Root<KfkwEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = Lists.newArrayList();

                if(sjfl != 0){
                    Predicate p1 = cb.equal(root.get("sjfl").as(Long.class), sjfl);
                    predicates.add(p1);
                }else{
                    Predicate p1 = cb.isNull(root.get("sjfl").as(Long.class));
                    predicates.add(p1);
                }
                Predicate p2 = cb.equal(root.get("ssxx").as(Long.class), getSchoolId());
                predicates.add(p2);
                if(currentNodePx<newNodePx){
                    Predicate p3 = cb.between(root.get("px"), currentNodePx, newNodePx);
                    predicates.add(p3);
                }else if(currentNodePx>newNodePx){
                    Predicate p3 = cb.between(root.get("px"), newNodePx, currentNodePx);
                    predicates.add(p3);;
                }
                query.orderBy(cb.asc(root.get("px").as(Long.class)));
                query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
                return query.getRestriction();
            }
        };

        List<KfkwEntity> wpflList = kfkwDao.findAll(spec);

        return wpflList;
    }

    //成为目标节点的子节点
    /**
     * 
     * @param currentNodeId 拖拽节点id
     * @param newParentNodeId 目标父节点id
     * @throws Exception 
     */
    @Transactional
    public void differentLevel(Long currentNodeId,Long newParentNodeId) throws Exception{

        KfkwEntity kfkwEntity=kfkwDao.findOne(currentNodeId);  // 拖拽节点
        List<KfkwEntity> kfkwEntities = null;
        if(kfkwEntity.getSjfl() != null){
            kfkwEntities= findInfluenceData1(kfkwEntity.getSjfl().getId(), kfkwEntity.getPx());
        }else{
            kfkwEntities= findInfluenceData1(null, kfkwEntity.getPx());
        }
        if(CollectionUtils.isNotEmpty(kfkwEntities)){ // 当前节点为同级最后节点时wpflEntities=[]
            for (int i = 0; i < kfkwEntities.size(); i++) {
                KfkwEntity kfkwEntity2= kfkwEntities.get(i);
                kfkwEntity2.setPx(kfkwEntity2.getPx()-1);
                kfkwDao.save(kfkwEntity2);
            }
        }
        //当前节点成为目标节点(父节点)的最后一个节点
        KfkwDto kfkwDto = new KfkwDto();
        List<KfkwEntity> kfkwEntities2= kfkwDao.findByMaxPx(newParentNodeId, getSchoolId()); //  得到目标节点子节点的集合
        if(CollectionUtils.isEmpty(kfkwEntities2)){
            kfkwDto.setPx(1);
        }else{
            kfkwDto.setPx(kfkwEntities2.get(0).getPx()+1);
        }
        kfkwEntity.setSjfl(kfkwDao.findOne(newParentNodeId));
        super.save(kfkwEntity, kfkwDto);
    }


    public List<KfkwEntity> findInfluenceData1(Long sjfl, Integer currentNodePx) {
        Specification<KfkwEntity> spec = new Specification<KfkwEntity>() {

            @Override
            public Predicate toPredicate(Root<KfkwEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = Lists.newArrayList();

                if(sjfl != null){
                    Predicate p1 = cb.equal(root.get("sjfl").as(Long.class), sjfl);
                    predicates.add(p1);
                }else{
                    Predicate p1 = cb.isNull(root.get("sjfl").as(Long.class));
                    predicates.add(p1);
                }
                Predicate p2 = cb.equal(root.get("ssxx").as(Long.class), getSchoolId());
                predicates.add(p2);
                Predicate p3 = cb.greaterThan(root.get("px"), currentNodePx);
                predicates.add(p3);
                query.orderBy(cb.asc(root.get("px").as(Long.class)));
                query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
                return query.getRestriction();
            }
        };

        List<KfkwEntity> wpflList = kfkwDao.findAll(spec);

        return wpflList;
    }


    /**
     * 不同级节点为位置调换,movetype != inner
     * 
     * @param currentNodeId
     * @param newNodeId
     * @param moveType
     * @throws Exception
     */
    @Transactional
    public void diffLevel(Long currentNodeId, Long newNodeId, String moveType) throws Exception {
        if("next".equals(moveType)){
            KfkwEntity currentKfkw = kfkwDao.findOne(currentNodeId);// 拖拽节点
            KfkwEntity newKfkw = kfkwDao.findOne(newNodeId);//目标节点 
            KfkwEntity newKfkwSjfl =null;
            // 移到第一节点
            if(newKfkw.getSjfl() != null){
                newKfkwSjfl = kfkwDao.findOne(newKfkw.getSjfl().getId()); //目标节点的父类
            }

            List<KfkwEntity> ccKfkwEntities = null;
            if(newKfkw.getSjfl() != null){
                // 目标节点后面的数据排序+1,如果是最后一位不要+1
                ccKfkwEntities = this.findInfluenceData2(newKfkw.getSjfl().getId(), newKfkw.getPx());
            }else{
                ccKfkwEntities = this.findInfluenceData2(null, newKfkw.getPx());
            }

            if(CollectionUtils.isNotEmpty(ccKfkwEntities)){
                for (int i = 0; i < ccKfkwEntities.size(); i++) {
                    KfkwEntity ccKfkwEntity=ccKfkwEntities.get(i);
                    ccKfkwEntity.setPx(ccKfkwEntity.getPx()+1);
                    kfkwDao.save(ccKfkwEntity);
                }
            }

            List<KfkwEntity> cckfkwEntities2 = null;
            if(currentKfkw.getSjfl() != null){
                // 当前节点之后的排序值减一,判断是不是最后一个节点,如果是最后一个节点,就不需要-1了
                cckfkwEntities2 = this.findInfluenceData2(currentKfkw.getSjfl().getId(), currentKfkw.getPx());
            }else{
                cckfkwEntities2 = this.findInfluenceData2(null, currentKfkw.getPx());
            }
            if(CollectionUtils.isNotEmpty(cckfkwEntities2)){
                for (int i = 0; i < cckfkwEntities2.size(); i++) {
                    KfkwEntity ccKfkwEntity=cckfkwEntities2.get(i);
                    ccKfkwEntity.setPx(ccKfkwEntity.getPx()-1);
                    kfkwDao.save(ccKfkwEntity);
                }
            }

            currentKfkw.setPx(newKfkw.getPx()+1); 
            currentKfkw.setSjfl(newKfkwSjfl);
            kfkwDao.save(currentKfkw);
        }else{
            KfkwEntity currentKfkw = kfkwDao.findOne(currentNodeId);// 拖拽节点
            KfkwEntity newKfkw = kfkwDao.findOne(newNodeId);//目标节点 
            KfkwEntity newKfkwSjfl =null;
            // 移到第一节点
            if(newKfkw.getSjfl() != null){
                newKfkwSjfl = kfkwDao.findOne(newKfkw.getSjfl().getId()); //目标节点的父类
            }

            List<KfkwEntity> ccKfkwEntities2 = null;
            if(currentKfkw.getSjfl() !=null){
                // 当前节点之后的排序值减一,判断是不是最后一个节点,如果是最后一个节点,就不需要-1了
                ccKfkwEntities2 = this.findInfluenceData2(currentKfkw.getSjfl().getId(), currentKfkw.getPx());
            }else{
                ccKfkwEntities2 = this.findInfluenceData2(null, currentKfkw.getPx());
            }

            if(CollectionUtils.isNotEmpty(ccKfkwEntities2)){
                for (int i = 0; i < ccKfkwEntities2.size(); i++) {
                    KfkwEntity ccKfkwEntity=ccKfkwEntities2.get(i);
                    ccKfkwEntity.setPx(ccKfkwEntity.getPx()-1);
                    kfkwDao.save(ccKfkwEntity);
                }
            }

            List<KfkwEntity> ccKfkwEntities = null;
            if(newKfkw.getSjfl() !=null){
                // 目标节点之后的排序值加一
                ccKfkwEntities = this.findInfluenceData2(newKfkw.getSjfl().getId(), newKfkw.getPx());
            }else{
                ccKfkwEntities = this.findInfluenceData2(null, newKfkw.getPx());
            }

            if(CollectionUtils.isNotEmpty(ccKfkwEntities)){
                for (int i = 0; i < ccKfkwEntities.size(); i++) {
                    KfkwEntity ccKfkwEntity=ccKfkwEntities.get(i);
                    ccKfkwEntity.setPx(ccKfkwEntity.getPx()+1);
                    kfkwDao.save(ccKfkwEntity);
                }
            }

            currentKfkw.setPx(newKfkw.getPx()); 
            currentKfkw.setSjfl(newKfkwSjfl);
            kfkwDao.save(currentKfkw);

//            目标节点的排序值加一
            newKfkw.setPx(newKfkw.getPx()+1);
            kfkwDao.save(newKfkw);

        }
    }

    public List<KfkwEntity> findInfluenceData2(Long sjfl, Integer currentNodePx) {
        Specification<KfkwEntity> spec = new Specification<KfkwEntity>() {

            @Override
            public Predicate toPredicate(Root<KfkwEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = Lists.newArrayList();

                if(sjfl != null){
                    Predicate p1 = cb.equal(root.get("sjfl").as(Long.class), sjfl);
                    predicates.add(p1);
                }else{
                    Predicate p1 = cb.isNull(root.get("sjfl").as(Long.class));
                    predicates.add(p1);
                }
                Predicate p2 = cb.equal(root.get("ssxx").as(Long.class), getSchoolId());
                predicates.add(p2);
                Predicate p3 = cb.greaterThan(root.get("px"), currentNodePx);
                predicates.add(p3);
                query.orderBy(cb.asc(root.get("px").as(Long.class)));
                query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
                return query.getRestriction();
            }
        };

        List<KfkwEntity> wpflList = kfkwDao.findAll(spec);

        return wpflList;
    }

}

dao代码

/**
 * 仓库管理Dao
 * 
 * @author WangYuanJun
 */
public interface KfkwDao extends JpaRepository<KfkwEntity, Long>, JpaSpecificationExecutor<KfkwEntity> {

    @Query("select o from KfkwEntity o where o.sjfl.id=?1 and o.ssxx.id=?2 order by o.px desc")
    public List<KfkwEntity> findByMaxPx(Long sjfl,Long ssxx);

}