樹組件——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);
                }
            }
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM