核心提示:最近在做仓储的功能,需要实现对仓库树的拖拽功能,测试了很长时间才完成,后端使用了SpringMVC + Spring Data Jpa图片和代码展示如下: Jsp程序%@ page languag...
最近在做仓储的功能,需要实现对仓库树的拖拽功能,测试了很长时间才完成,后端使用了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;"> <p class="row" id="page_content"> <p class="col-sm-12"> <p class="ibox float-e-margins"> <p class="ibox-title"> <h3>物品分类</h3> </p> <p class="ibox-content"> <p class="col-sm-12 no-padding" id="tree"> <p class="zTreeDemoBackground left"> <ul id="treeDemo" class="ztree" url="${ctx}/baseinfo/wpfl/renderTree"></ul> </p> </p> </p> </p> </p> </p> <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 ] " + treeNode.name); var zTree = $.fn.zTree.getZTreeObj("treeDemo"); zTree.selectNode(treeNode); return; } function beforeRemove(treeId, treeNode) { className = (className === "dark" ? "":"dark"); showLog("[ "+getTime()+" beforeRemove ] " + 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 ] " + treeNode.name); } function beforeRename(treeId, treeNode, newName, isCancel) { className = (className === "dark" ? "":"dark"); showLog((isCancel ? "<span style='color:red'>":"") + "[ "+getTime()+" beforeRename ] " + 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 ] " + 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 ] 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 ] 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+'¤tNodeId='+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 ] drag: " + treeNodes.length + " nodes." ); } function onDrop(event, treeId, treeNodes, targetNode, moveType, isCopy) { className = (className === "dark" ? "":"dark"); showLog("[ "+getTime()+" onDrop ] 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 ] " + 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); }