• 树组件——jstree使用


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

    一、使用前提:

    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);
                    }
                }
            }
        }
  • 相关阅读:
    CentOS7安装Oracle 11gR2 安装
    CentOS7 FTP服务搭建(虚拟用户访问FTP服务)
    .NET中RabbitMQ的使用
    ElasticSearch(站内搜索)
    SignalR 2.1 简单入门项目
    Oracl基础知识(一)
    CentOS6—HAProxy安装与配置
    Redis C#缓存的使用
    CentOS6— Redis安装(转和延续)
    Linux(CentOS)常用操作指令(二)
  • 原文地址:https://www.cnblogs.com/guxiong/p/10837570.html
Copyright © 2020-2023  润新知