Răsfoiți Sursa

grid tree

update
jqh 5 ani în urmă
părinte
comite
4c972d20ba

+ 340 - 0
resources/assets/dcat/extra/grid-extend.js

@@ -0,0 +1,340 @@
+(function (w, $) {
+    let Dcat = w.Dcat;
+    
+    function Tree(opts) {
+        this.options = $.extend({
+            button: null,
+            table: null,
+            url: '',
+            perPage: '',
+            showNextPage: '',
+            pageQueryName: '',
+            parentIdQueryName: '',
+            tierQueryName: '',
+            showIcon: 'fa-angle-right',
+            hideIcon: 'fa-angle-down',
+            loadMoreIcon: '<i class="feather icon-more-horizontal"></i>',
+        }, opts);
+
+        this.key = this.tier = this.row = this.data = this._req = null;
+
+        this._init();
+    }
+
+    Tree.prototype = {
+        _init: function () {
+            this._bindClick();
+        },
+
+        _bindClick: function () {
+            var _this = this,
+                opts = _this.options;
+
+            $(opts.button).off('click').click(function () {
+                if (_this._req) {
+                    return;
+                }
+
+                var $this = $(this),
+                    _i = $("i", this),
+                    shown = _i.hasClass(opts.showIcon);
+
+                _this.key = $this.data('key');
+                _this.tier = $this.data('tier');
+                _this.row = $this.closest('tr');
+
+                if ($this.data('inserted') == '0') {
+                    _this._request(1);
+                    $this.data('inserted', 1);
+                }
+
+                _i.toggleClass(opts.showIcon + ' ' + opts.hideIcon);
+
+                var children = [];
+
+                getChildren(_this.row.nextAll(), _this.row).forEach(function (v) {
+                    if (getTier(v) !== (_this.tier + 1)) {
+                        return;
+                    }
+
+                    children.push(v);
+
+                    shown ? $(v).show() : $(v).hide();
+                });
+
+                children.forEach(function (v) {
+                    if (shown) {
+                        return
+                    }
+
+                    var icon = $(v).find('a[data-tier=' + getTier(v) + '] i');
+
+                    if (icon.hasClass(opts.hideIcon)) {
+                        icon.parent().click();
+                    }
+                })
+            })
+        },
+
+        _request: function (page, after) {
+            var _this = this,
+                row = _this.row,
+                key = _this.key,
+                tier = _this.tier,
+                tableSelector = _this.options.table;
+
+            if (_this._req) {
+                return;
+            }
+            _this._req = 1;
+            Dcat.loading();
+
+            var data = {
+                _token: Dcat.token,
+            };
+
+            data[_this.options.parentIdQueryName] = key;
+            data[_this.options.tierQueryName] = tier + 1;
+            data[_this.options.pageQueryName.replace(':key', key)] = page;
+
+            $.ajax({
+                url: _this.options.url,
+                type: 'GET',
+                data: data,
+                headers: {'X-PJAX': true},
+                success: function (resp) {
+                    after && after();
+                    Dcat.loading(false);
+                    _this._req = 0;
+
+                    // 获取最后一行
+                    var children = getChildren(row.nextAll(), row);
+                    row = children.length ? $(children.pop()) : row;
+
+                    var _body = $('<div>'+resp+'</div>'),
+                        _tbody = _body.find(tableSelector + ' tbody'),
+                        lastPage = _body.find('last-page').text(),
+                        nextPage = _body.find('next-page').text();
+
+                    // 标记子节点行
+                    _tbody.find('tr').each(function (_, v) {
+                        $(v).attr('data-tier', tier + 1)
+                    });
+
+                    if (
+                        _this.options.showNextPage
+                        && _tbody.find('tr').length == _this.options.perPage
+                        && lastPage >= page
+                    ) {
+                        // 加载更多
+                        let loadMore = $(
+                            `<tr data-tier="${tier + 1}" data-page="${nextPage}">
+                                <td colspan="${row.find('td').length}" align="center" style="cursor: pointer"> 
+                                    <a href="#" style="font-size: 1.5rem">${_this.options.loadMoreIcon}</a> 
+                                </td>
+                            </tr>`
+                        );
+
+                        row.after(loadMore);
+
+                        // 加载更多
+                        loadMore.click(function () {
+                            var _t = $(this);
+                            _this._request(_t.data('page'), function () {
+                                _t.remove();
+                            });
+                        });
+                    }
+
+                    // 附加子节点
+                    row.after(_tbody.html());
+
+                    // 附加子节点js脚本以及触发子节点js脚本执行
+                    _body.find('script').each(function (_, v) {
+                        row.after(v);
+                    });
+                    // 主动触发ready事件,执行子节点附带的js脚本
+                    Dcat.triggerReady();
+                },
+                error:function(a, b, c){
+                    after && after();
+                    Dcat.loading(false);
+                    _this._req = 0;
+                    if (a.status != 404) {
+                        Dcat.handleAjaxError(a, b, c);
+                    }
+                }
+            });
+        }
+    };
+
+    function Orderable(opts) {
+        this.options = $.extend({
+            button: null,
+            url: '',
+        }, opts);
+
+        this.direction = this.key = this.tier = this.row = this._req = null;
+
+        this._init();
+    }
+
+    Orderable.prototype = {
+        _init: function () {
+            this._bindClick()
+        },
+
+        _bindClick: function () {
+            var _this = this;
+
+            $(_this.options.button).off('click').click(function () {
+                if (_this._req) {
+                    return;
+                }
+
+                _this._req = 1;
+                Dcat.loading();
+
+                var $this = $(this);
+
+                _this.key = $this.data('id');
+                _this.direction = $this.data('direction');
+                _this.row = $this.closest('tr');
+                _this.tier = getTier(_this.row);
+
+                _this._request();
+            })
+        },
+
+        _request: function () {
+            var _this = this,
+                key = _this.key,
+                row = _this.row,
+                tier = _this.tier,
+                direction = _this.direction,
+                prevAll = row.prevAll(),
+                nextAll = row.nextAll(),
+                prev = row.prevAll('tr').first(),
+                next = row.nextAll('tr').first();
+
+            $.ajax({
+                type: 'POST',
+                url: _this.options.url.replace(':key', key),
+                data: {_method:'PUT', _token:Dcat.token, _orderable:direction},
+                success: function(data){
+                    Dcat.loading(false);
+                    _this._req = 0;
+                    if (! data.status) {
+                        return data.message && Dcat.warning(data.message);
+                    }
+
+                    Dcat.success(data.message);
+
+                    if (direction) {
+                        var prevRow = sibling(prevAll, tier);
+                        if (swapable(prevRow, tier) && prev.length && getTier(prev) >= tier) {
+                            prevRow.before(row);
+
+                            // 把所有子节点上移
+                            getChildren(nextAll, row).forEach(function (v) {
+                                prevRow.before(v)
+                            });
+                        }
+                    } else {
+                        var nextRow = sibling(nextAll, tier),
+                            nextRowChildren = nextRow ? getChildren(nextRow.nextAll(), nextRow) : [];
+
+                        if (swapable(nextRow, tier) && next.length && getTier(next) >= tier) {
+                            nextAll = row.nextAll();
+
+                            if (nextRowChildren.length) {
+                                nextRow = $(nextRowChildren.pop())
+                            }
+
+                            // 把所有子节点下移
+                            var all = [];
+                            getChildren(nextAll, row).forEach(function (v) {
+                                all.unshift(v)
+                            });
+
+                            all.forEach(function(v) {
+                                nextRow.after(v)
+                            });
+
+                            nextRow.after(row);
+                        }
+                    }
+                },
+                error: function (a, b, c) {
+                    _this._req = 0;
+                    Dcat.loading(false);
+                    Dcat.handleAjaxError(a, b, c)
+                }
+            });
+        },
+    };
+
+    function isTr(v) {
+        return $(v).prop('tagName').toLocaleLowerCase() === 'tr'
+    }
+
+    function getTier(v) {
+        return parseInt($(v).data('tier') || 0);
+    }
+
+    function isChildren(parent, child) {
+        return getTier(child) > getTier(parent);
+    }
+
+    function getChildren(all, parent) {
+        var arr = [], isBreak = false, firstTr;
+        all.each(function (_, v) {
+            // 过滤非tr标签
+            if (! isTr(v) || isBreak) return;
+
+            firstTr || (firstTr = $(v));
+
+            // 非连续的子节点
+            if (firstTr && ! isChildren(parent, firstTr)) {
+                return;
+            }
+
+            if (isChildren(parent, v)) {
+                arr.push(v)
+            } else {
+                isBreak = true;
+            }
+        });
+
+        return arr;
+    }
+
+    function swapable(_o, tier) {
+        if (
+            _o
+            && _o.length
+            && tier === getTier(_o)
+        ) {
+            return true
+        }
+    }
+
+    function sibling(all, tier) {
+        var next;
+
+        all.each(function (_, v) {
+            if (getTier(v) === tier && ! next && isTr(v)) {
+                next = $(v);
+            }
+        });
+
+        return next;
+    }
+
+    Dcat.grid.Tree = function (opts) {
+        return new Tree(opts);
+    };
+    Dcat.grid.Orderable = function (opts) {
+        return new Orderable(opts);
+    };
+})(window, jQuery);

+ 2 - 2
resources/assets/dcat/sass/components/_button.scss

@@ -2,7 +2,7 @@
   padding: .75rem 1.35rem!important;
   font-size: .95rem;
   height: 36px;
-  line-height: .7;
+  line-height: 1.2;
   border-radius: 0.2rem;
   box-shadow: $shadow-100;
 }
@@ -24,7 +24,7 @@
 .btn-sm, .btn-group-sm > .btn {
   padding: 0.6rem 1rem!important;;
   font-size: 0.6rem;
-  line-height: 12px;
+  line-height: 1.2;
   height: 30px;
 }
 

+ 3 - 3
resources/assets/dcat/sass/components/_table.scss

@@ -43,14 +43,14 @@ table.data-list-view.dataTable tbody tr:hover, table.data-thumb-view.dataTable t
 }
 
 .table td {
-  padding: .5rem;
-  height: 64px;
+  padding: .55rem;
+  height: 62px;
   line-height: 1.42857;
 }
 
 table.data-list-view.dataTable tbody td, table.data-thumb-view.dataTable tbody td {
   height: 46px;
-  padding: .5rem;
+  padding: .55rem;
   line-height: 1.42857;
 }
 

+ 1 - 0
resources/assets/dcat/sass/dcat-app.scss

@@ -99,6 +99,7 @@ code {
   box-shadow: 0 1px 1px rgba(0,0,0,0.125);
   padding: 3px 5px;
   background: #f7f7f9;
+  color: darken($primary, 8%);
 }
 pre {
   padding: 7px;

+ 36 - 36
resources/dist/css/plugins/loaders/animations/ball-grid-beat.css

@@ -27,66 +27,66 @@
 }
 
 .ball-grid-beat > div:nth-child(1) {
-  -webkit-animation-delay: -0.08s;
-          animation-delay: -0.08s;
-  -webkit-animation-duration: 0.87s;
-          animation-duration: 0.87s;
+  -webkit-animation-delay: 0.06s;
+          animation-delay: 0.06s;
+  -webkit-animation-duration: 0.89s;
+          animation-duration: 0.89s;
 }
 
 .ball-grid-beat > div:nth-child(2) {
-  -webkit-animation-delay: 0.55s;
-          animation-delay: 0.55s;
-  -webkit-animation-duration: 1.28s;
-          animation-duration: 1.28s;
+  -webkit-animation-delay: 0.62s;
+          animation-delay: 0.62s;
+  -webkit-animation-duration: 0.69s;
+          animation-duration: 0.69s;
 }
 
 .ball-grid-beat > div:nth-child(3) {
-  -webkit-animation-delay: 0.73s;
-          animation-delay: 0.73s;
-  -webkit-animation-duration: 0.82s;
-          animation-duration: 0.82s;
+  -webkit-animation-delay: 0.71s;
+          animation-delay: 0.71s;
+  -webkit-animation-duration: 0.68s;
+          animation-duration: 0.68s;
 }
 
 .ball-grid-beat > div:nth-child(4) {
-  -webkit-animation-delay: 0.41s;
-          animation-delay: 0.41s;
-  -webkit-animation-duration: 1.36s;
-          animation-duration: 1.36s;
+  -webkit-animation-delay: 0.55s;
+          animation-delay: 0.55s;
+  -webkit-animation-duration: 0.76s;
+          animation-duration: 0.76s;
 }
 
 .ball-grid-beat > div:nth-child(5) {
-  -webkit-animation-delay: -0.06s;
-          animation-delay: -0.06s;
-  -webkit-animation-duration: 0.87s;
-          animation-duration: 0.87s;
+  -webkit-animation-delay: 0.6s;
+          animation-delay: 0.6s;
+  -webkit-animation-duration: 1.35s;
+          animation-duration: 1.35s;
 }
 
 .ball-grid-beat > div:nth-child(6) {
-  -webkit-animation-delay: 0.58s;
-          animation-delay: 0.58s;
-  -webkit-animation-duration: 1.48s;
-          animation-duration: 1.48s;
+  -webkit-animation-delay: -0.17s;
+          animation-delay: -0.17s;
+  -webkit-animation-duration: 1.05s;
+          animation-duration: 1.05s;
 }
 
 .ball-grid-beat > div:nth-child(7) {
-  -webkit-animation-delay: 0.53s;
-          animation-delay: 0.53s;
-  -webkit-animation-duration: 1.18s;
-          animation-duration: 1.18s;
+  -webkit-animation-delay: 0.33s;
+          animation-delay: 0.33s;
+  -webkit-animation-duration: 1.57s;
+          animation-duration: 1.57s;
 }
 
 .ball-grid-beat > div:nth-child(8) {
-  -webkit-animation-delay: 0.77s;
-          animation-delay: 0.77s;
-  -webkit-animation-duration: 0.82s;
-          animation-duration: 0.82s;
+  -webkit-animation-delay: 0.16s;
+          animation-delay: 0.16s;
+  -webkit-animation-duration: 1.41s;
+          animation-duration: 1.41s;
 }
 
 .ball-grid-beat > div:nth-child(9) {
-  -webkit-animation-delay: 0.61s;
-          animation-delay: 0.61s;
-  -webkit-animation-duration: 1.48s;
-          animation-duration: 1.48s;
+  -webkit-animation-delay: 0.68s;
+          animation-delay: 0.68s;
+  -webkit-animation-duration: 1.29s;
+          animation-duration: 1.29s;
 }
 
 .ball-grid-beat > div {

+ 36 - 36
resources/dist/css/plugins/loaders/animations/ball-grid-pulse.css

@@ -39,66 +39,66 @@
 }
 
 .ball-grid-pulse > div:nth-child(1) {
-  -webkit-animation-delay: 0.79s;
-          animation-delay: 0.79s;
-  -webkit-animation-duration: 1.56s;
-          animation-duration: 1.56s;
+  -webkit-animation-delay: -0.08s;
+          animation-delay: -0.08s;
+  -webkit-animation-duration: 1.38s;
+          animation-duration: 1.38s;
 }
 
 .ball-grid-pulse > div:nth-child(2) {
-  -webkit-animation-delay: 0.22s;
-          animation-delay: 0.22s;
-  -webkit-animation-duration: 1.6s;
-          animation-duration: 1.6s;
+  -webkit-animation-delay: 0.02s;
+          animation-delay: 0.02s;
+  -webkit-animation-duration: 1.11s;
+          animation-duration: 1.11s;
 }
 
 .ball-grid-pulse > div:nth-child(3) {
-  -webkit-animation-delay: 0.27s;
-          animation-delay: 0.27s;
-  -webkit-animation-duration: 0.73s;
-          animation-duration: 0.73s;
+  -webkit-animation-delay: -0.06s;
+          animation-delay: -0.06s;
+  -webkit-animation-duration: 1.51s;
+          animation-duration: 1.51s;
 }
 
 .ball-grid-pulse > div:nth-child(4) {
-  -webkit-animation-delay: 0.33s;
-          animation-delay: 0.33s;
-  -webkit-animation-duration: 0.7s;
-          animation-duration: 0.7s;
+  -webkit-animation-delay: 0.35s;
+          animation-delay: 0.35s;
+  -webkit-animation-duration: 0.99s;
+          animation-duration: 0.99s;
 }
 
 .ball-grid-pulse > div:nth-child(5) {
-  -webkit-animation-delay: 0.37s;
-          animation-delay: 0.37s;
-  -webkit-animation-duration: 0.79s;
-          animation-duration: 0.79s;
+  -webkit-animation-delay: -0.09s;
+          animation-delay: -0.09s;
+  -webkit-animation-duration: 0.97s;
+          animation-duration: 0.97s;
 }
 
 .ball-grid-pulse > div:nth-child(6) {
-  -webkit-animation-delay: -0.15s;
-          animation-delay: -0.15s;
-  -webkit-animation-duration: 0.73s;
-          animation-duration: 0.73s;
+  -webkit-animation-delay: 0.12s;
+          animation-delay: 0.12s;
+  -webkit-animation-duration: 0.87s;
+          animation-duration: 0.87s;
 }
 
 .ball-grid-pulse > div:nth-child(7) {
-  -webkit-animation-delay: 0.55s;
-          animation-delay: 0.55s;
-  -webkit-animation-duration: 1.19s;
-          animation-duration: 1.19s;
+  -webkit-animation-delay: 0.52s;
+          animation-delay: 0.52s;
+  -webkit-animation-duration: 1.01s;
+          animation-duration: 1.01s;
 }
 
 .ball-grid-pulse > div:nth-child(8) {
-  -webkit-animation-delay: 0.18s;
-          animation-delay: 0.18s;
-  -webkit-animation-duration: 0.96s;
-          animation-duration: 0.96s;
+  -webkit-animation-delay: -0.1s;
+          animation-delay: -0.1s;
+  -webkit-animation-duration: 1.36s;
+          animation-duration: 1.36s;
 }
 
 .ball-grid-pulse > div:nth-child(9) {
-  -webkit-animation-delay: 0.24s;
-          animation-delay: 0.24s;
-  -webkit-animation-duration: 1.47s;
-          animation-duration: 1.47s;
+  -webkit-animation-delay: 0.36s;
+          animation-delay: 0.36s;
+  -webkit-animation-duration: 1.03s;
+          animation-duration: 1.03s;
 }
 
 .ball-grid-pulse > div {

+ 16 - 16
resources/dist/css/plugins/loaders/animations/line-scale-random.css

@@ -31,31 +31,31 @@
 }
 
 .line-scale-party > div:nth-child(1) {
-  -webkit-animation-delay: 0.22s;
-          animation-delay: 0.22s;
-  -webkit-animation-duration: 1.28s;
-          animation-duration: 1.28s;
+  -webkit-animation-delay: -0.13s;
+          animation-delay: -0.13s;
+  -webkit-animation-duration: 0.92s;
+          animation-duration: 0.92s;
 }
 
 .line-scale-party > div:nth-child(2) {
-  -webkit-animation-delay: 0.52s;
-          animation-delay: 0.52s;
-  -webkit-animation-duration: 1.05s;
-          animation-duration: 1.05s;
+  -webkit-animation-delay: 0.69s;
+          animation-delay: 0.69s;
+  -webkit-animation-duration: 0.88s;
+          animation-duration: 0.88s;
 }
 
 .line-scale-party > div:nth-child(3) {
-  -webkit-animation-delay: -0.15s;
-          animation-delay: -0.15s;
-  -webkit-animation-duration: 0.59s;
-          animation-duration: 0.59s;
+  -webkit-animation-delay: 0.37s;
+          animation-delay: 0.37s;
+  -webkit-animation-duration: 0.54s;
+          animation-duration: 0.54s;
 }
 
 .line-scale-party > div:nth-child(4) {
-  -webkit-animation-delay: 0.28s;
-          animation-delay: 0.28s;
-  -webkit-animation-duration: 0.49s;
-          animation-duration: 0.49s;
+  -webkit-animation-delay: -0.08s;
+          animation-delay: -0.08s;
+  -webkit-animation-duration: 0.42s;
+          animation-duration: 0.42s;
 }
 
 .line-scale-party > div {

+ 86 - 86
resources/dist/css/plugins/loaders/loaders.css

@@ -1454,64 +1454,64 @@
 }
 
 .ball-grid-beat > div:nth-child(1) {
-  -webkit-animation-delay: 0.02s;
-          animation-delay: 0.02s;
-  -webkit-animation-duration: 0.98s;
-          animation-duration: 0.98s;
+  -webkit-animation-delay: 0.55s;
+          animation-delay: 0.55s;
+  -webkit-animation-duration: 0.79s;
+          animation-duration: 0.79s;
 }
 
 .ball-grid-beat > div:nth-child(2) {
-  -webkit-animation-delay: -0.09s;
-          animation-delay: -0.09s;
-  -webkit-animation-duration: 1.37s;
-          animation-duration: 1.37s;
+  -webkit-animation-delay: -0.05s;
+          animation-delay: -0.05s;
+  -webkit-animation-duration: 0.83s;
+          animation-duration: 0.83s;
 }
 
 .ball-grid-beat > div:nth-child(3) {
-  -webkit-animation-delay: 0.29s;
-          animation-delay: 0.29s;
-  -webkit-animation-duration: 0.82s;
-          animation-duration: 0.82s;
+  -webkit-animation-delay: 0.16s;
+          animation-delay: 0.16s;
+  -webkit-animation-duration: 1.44s;
+          animation-duration: 1.44s;
 }
 
 .ball-grid-beat > div:nth-child(4) {
-  -webkit-animation-delay: 0.39s;
-          animation-delay: 0.39s;
-  -webkit-animation-duration: 1.33s;
-          animation-duration: 1.33s;
+  -webkit-animation-delay: 0.34s;
+          animation-delay: 0.34s;
+  -webkit-animation-duration: 1.19s;
+          animation-duration: 1.19s;
 }
 
 .ball-grid-beat > div:nth-child(5) {
-  -webkit-animation-delay: -0.06s;
-          animation-delay: -0.06s;
-  -webkit-animation-duration: 0.62s;
-          animation-duration: 0.62s;
+  -webkit-animation-delay: 0.34s;
+          animation-delay: 0.34s;
+  -webkit-animation-duration: 1.02s;
+          animation-duration: 1.02s;
 }
 
 .ball-grid-beat > div:nth-child(6) {
-  -webkit-animation-delay: 0.61s;
-          animation-delay: 0.61s;
-  -webkit-animation-duration: 0.78s;
-          animation-duration: 0.78s;
+  -webkit-animation-delay: 0.23s;
+          animation-delay: 0.23s;
+  -webkit-animation-duration: 1.27s;
+          animation-duration: 1.27s;
 }
 
 .ball-grid-beat > div:nth-child(7) {
-  -webkit-animation-delay: 0.08s;
-          animation-delay: 0.08s;
-  -webkit-animation-duration: 0.98s;
-          animation-duration: 0.98s;
+  -webkit-animation-delay: 0.27s;
+          animation-delay: 0.27s;
+  -webkit-animation-duration: 1.57s;
+          animation-duration: 1.57s;
 }
 
 .ball-grid-beat > div:nth-child(8) {
-  -webkit-animation-delay: 0.07s;
-          animation-delay: 0.07s;
-  -webkit-animation-duration: 0.7s;
-          animation-duration: 0.7s;
+  -webkit-animation-delay: 0s;
+          animation-delay: 0s;
+  -webkit-animation-duration: 1.11s;
+          animation-duration: 1.11s;
 }
 
 .ball-grid-beat > div:nth-child(9) {
-  -webkit-animation-delay: -0.14s;
-          animation-delay: -0.14s;
+  -webkit-animation-delay: 0.73s;
+          animation-delay: 0.73s;
   -webkit-animation-duration: 0.96s;
           animation-duration: 0.96s;
 }
@@ -1575,66 +1575,66 @@
 }
 
 .ball-grid-pulse > div:nth-child(1) {
-  -webkit-animation-delay: -0.09s;
-          animation-delay: -0.09s;
-  -webkit-animation-duration: 1.29s;
-          animation-duration: 1.29s;
+  -webkit-animation-delay: 0.07s;
+          animation-delay: 0.07s;
+  -webkit-animation-duration: 0.9s;
+          animation-duration: 0.9s;
 }
 
 .ball-grid-pulse > div:nth-child(2) {
-  -webkit-animation-delay: 0.16s;
-          animation-delay: 0.16s;
-  -webkit-animation-duration: 1.52s;
-          animation-duration: 1.52s;
+  -webkit-animation-delay: 0s;
+          animation-delay: 0s;
+  -webkit-animation-duration: 1.46s;
+          animation-duration: 1.46s;
 }
 
 .ball-grid-pulse > div:nth-child(3) {
-  -webkit-animation-delay: -0.03s;
-          animation-delay: -0.03s;
-  -webkit-animation-duration: 0.95s;
-          animation-duration: 0.95s;
+  -webkit-animation-delay: 0.23s;
+          animation-delay: 0.23s;
+  -webkit-animation-duration: 1.53s;
+          animation-duration: 1.53s;
 }
 
 .ball-grid-pulse > div:nth-child(4) {
-  -webkit-animation-delay: 0.69s;
-          animation-delay: 0.69s;
-  -webkit-animation-duration: 1.2s;
-          animation-duration: 1.2s;
+  -webkit-animation-delay: 0.09s;
+          animation-delay: 0.09s;
+  -webkit-animation-duration: 1.43s;
+          animation-duration: 1.43s;
 }
 
 .ball-grid-pulse > div:nth-child(5) {
-  -webkit-animation-delay: 0.32s;
-          animation-delay: 0.32s;
-  -webkit-animation-duration: 0.97s;
-          animation-duration: 0.97s;
+  -webkit-animation-delay: 0.56s;
+          animation-delay: 0.56s;
+  -webkit-animation-duration: 1.39s;
+          animation-duration: 1.39s;
 }
 
 .ball-grid-pulse > div:nth-child(6) {
-  -webkit-animation-delay: -0.1s;
-          animation-delay: -0.1s;
-  -webkit-animation-duration: 1.52s;
-          animation-duration: 1.52s;
+  -webkit-animation-delay: 0.77s;
+          animation-delay: 0.77s;
+  -webkit-animation-duration: 1.35s;
+          animation-duration: 1.35s;
 }
 
 .ball-grid-pulse > div:nth-child(7) {
-  -webkit-animation-delay: -0.03s;
-          animation-delay: -0.03s;
-  -webkit-animation-duration: 1.08s;
-          animation-duration: 1.08s;
+  -webkit-animation-delay: 0.47s;
+          animation-delay: 0.47s;
+  -webkit-animation-duration: 1.17s;
+          animation-duration: 1.17s;
 }
 
 .ball-grid-pulse > div:nth-child(8) {
-  -webkit-animation-delay: 0.68s;
-          animation-delay: 0.68s;
-  -webkit-animation-duration: 1.16s;
-          animation-duration: 1.16s;
+  -webkit-animation-delay: 0.26s;
+          animation-delay: 0.26s;
+  -webkit-animation-duration: 1.25s;
+          animation-duration: 1.25s;
 }
 
 .ball-grid-pulse > div:nth-child(9) {
-  -webkit-animation-delay: 0.27s;
-          animation-delay: 0.27s;
-  -webkit-animation-duration: 1.45s;
-          animation-duration: 1.45s;
+  -webkit-animation-delay: 0.76s;
+          animation-delay: 0.76s;
+  -webkit-animation-duration: 1.52s;
+          animation-duration: 1.52s;
 }
 
 .ball-grid-pulse > div {
@@ -2181,31 +2181,31 @@
 }
 
 .line-scale-party > div:nth-child(1) {
-  -webkit-animation-delay: 0.76s;
-          animation-delay: 0.76s;
-  -webkit-animation-duration: 0.53s;
-          animation-duration: 0.53s;
+  -webkit-animation-delay: 0.15s;
+          animation-delay: 0.15s;
+  -webkit-animation-duration: 0.79s;
+          animation-duration: 0.79s;
 }
 
 .line-scale-party > div:nth-child(2) {
-  -webkit-animation-delay: 0.67s;
-          animation-delay: 0.67s;
-  -webkit-animation-duration: 0.43s;
-          animation-duration: 0.43s;
+  -webkit-animation-delay: -0.16s;
+          animation-delay: -0.16s;
+  -webkit-animation-duration: 0.91s;
+          animation-duration: 0.91s;
 }
 
 .line-scale-party > div:nth-child(3) {
-  -webkit-animation-delay: 0.34s;
-          animation-delay: 0.34s;
-  -webkit-animation-duration: 0.72s;
-          animation-duration: 0.72s;
+  -webkit-animation-delay: 0.71s;
+          animation-delay: 0.71s;
+  -webkit-animation-duration: 0.32s;
+          animation-duration: 0.32s;
 }
 
 .line-scale-party > div:nth-child(4) {
-  -webkit-animation-delay: 0.1s;
-          animation-delay: 0.1s;
-  -webkit-animation-duration: 0.82s;
-          animation-duration: 0.82s;
+  -webkit-animation-delay: 0.27s;
+          animation-delay: 0.27s;
+  -webkit-animation-duration: 0.33s;
+          animation-duration: 0.33s;
 }
 
 .line-scale-party > div {

+ 6 - 5
resources/dist/dcat/css/dcat-app.css

@@ -1753,7 +1753,7 @@ html body .content .content-wrapper {
   padding: 0.75rem 1.35rem !important;
   font-size: 0.95rem;
   height: 36px;
-  line-height: 0.7;
+  line-height: 1.2;
   border-radius: 0.2rem;
   box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.05), 0 1px 5px 1px rgba(0, 0, 0, 0.05);
 }
@@ -1778,7 +1778,7 @@ html body .content .content-wrapper {
 .btn-group-sm > .btn {
   padding: 0.6rem 1rem !important;
   font-size: 0.6rem;
-  line-height: 12px;
+  line-height: 1.2;
   height: 30px;
 }
 
@@ -2010,15 +2010,15 @@ table.data-thumb-view.dataTable tbody tr:hover {
 }
 
 .table td {
-  padding: 0.5rem;
-  height: 64px;
+  padding: 0.55rem;
+  height: 62px;
   line-height: 1.42857;
 }
 
 table.data-list-view.dataTable tbody td,
 table.data-thumb-view.dataTable tbody td {
   height: 46px;
-  padding: 0.5rem;
+  padding: 0.55rem;
   line-height: 1.42857;
 }
 
@@ -2453,6 +2453,7 @@ code {
   box-shadow: 0 1px 1px rgba(0, 0, 0, 0.125);
   padding: 3px 5px;
   background: #f7f7f9;
+  color: #4152b9;
 }
 
 pre {

+ 427 - 0
resources/dist/dcat/extra/grid-extend.js

@@ -0,0 +1,427 @@
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "/";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = 1);
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./resources/assets/dcat/extra/grid-extend.js":
+/*!****************************************************!*\
+  !*** ./resources/assets/dcat/extra/grid-extend.js ***!
+  \****************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+(function (w, $) {
+  var Dcat = w.Dcat;
+
+  function Tree(opts) {
+    this.options = $.extend({
+      button: null,
+      table: null,
+      url: '',
+      perPage: '',
+      showNextPage: '',
+      pageQueryName: '',
+      parentIdQueryName: '',
+      tierQueryName: '',
+      showIcon: 'fa-angle-right',
+      hideIcon: 'fa-angle-down',
+      loadMoreIcon: '<i class="feather icon-more-horizontal"></i>'
+    }, opts);
+    this.key = this.tier = this.row = this.data = this._req = null;
+
+    this._init();
+  }
+
+  Tree.prototype = {
+    _init: function _init() {
+      this._bindClick();
+    },
+    _bindClick: function _bindClick() {
+      var _this = this,
+          opts = _this.options;
+
+      $(opts.button).off('click').click(function () {
+        if (_this._req) {
+          return;
+        }
+
+        var $this = $(this),
+            _i = $("i", this),
+            shown = _i.hasClass(opts.showIcon);
+
+        _this.key = $this.data('key');
+        _this.tier = $this.data('tier');
+        _this.row = $this.closest('tr');
+
+        if ($this.data('inserted') == '0') {
+          _this._request(1);
+
+          $this.data('inserted', 1);
+        }
+
+        _i.toggleClass(opts.showIcon + ' ' + opts.hideIcon);
+
+        var children = [];
+        getChildren(_this.row.nextAll(), _this.row).forEach(function (v) {
+          if (getTier(v) !== _this.tier + 1) {
+            return;
+          }
+
+          children.push(v);
+          shown ? $(v).show() : $(v).hide();
+        });
+        children.forEach(function (v) {
+          if (shown) {
+            return;
+          }
+
+          var icon = $(v).find('a[data-tier=' + getTier(v) + '] i');
+
+          if (icon.hasClass(opts.hideIcon)) {
+            icon.parent().click();
+          }
+        });
+      });
+    },
+    _request: function _request(page, after) {
+      var _this = this,
+          row = _this.row,
+          key = _this.key,
+          tier = _this.tier,
+          tableSelector = _this.options.table;
+
+      if (_this._req) {
+        return;
+      }
+
+      _this._req = 1;
+      Dcat.loading();
+      var data = {
+        _token: Dcat.token
+      };
+      data[_this.options.parentIdQueryName] = key;
+      data[_this.options.tierQueryName] = tier + 1;
+      data[_this.options.pageQueryName.replace(':key', key)] = page;
+      $.ajax({
+        url: _this.options.url,
+        type: 'GET',
+        data: data,
+        headers: {
+          'X-PJAX': true
+        },
+        success: function success(resp) {
+          after && after();
+          Dcat.loading(false);
+          _this._req = 0; // 获取最后一行
+
+          var children = getChildren(row.nextAll(), row);
+          row = children.length ? $(children.pop()) : row;
+
+          var _body = $('<div>' + resp + '</div>'),
+              _tbody = _body.find(tableSelector + ' tbody'),
+              lastPage = _body.find('last-page').text(),
+              nextPage = _body.find('next-page').text(); // 标记子节点行
+
+
+          _tbody.find('tr').each(function (_, v) {
+            $(v).attr('data-tier', tier + 1);
+          });
+
+          if (_this.options.showNextPage && _tbody.find('tr').length == _this.options.perPage && lastPage >= page) {
+            // 加载更多
+            var loadMore = $("<tr data-tier=\"".concat(tier + 1, "\" data-page=\"").concat(nextPage, "\">\n                                <td colspan=\"").concat(row.find('td').length, "\" align=\"center\" style=\"cursor: pointer\"> \n                                    <a href=\"#\" style=\"font-size: 1.5rem\">").concat(_this.options.loadMoreIcon, "</a> \n                                </td>\n                            </tr>"));
+            row.after(loadMore); // 加载更多
+
+            loadMore.click(function () {
+              var _t = $(this);
+
+              _this._request(_t.data('page'), function () {
+                _t.remove();
+              });
+            });
+          } // 附加子节点
+
+
+          row.after(_tbody.html()); // 附加子节点js脚本以及触发子节点js脚本执行
+
+          _body.find('script').each(function (_, v) {
+            row.after(v);
+          }); // 主动触发ready事件,执行子节点附带的js脚本
+
+
+          Dcat.triggerReady();
+        },
+        error: function error(a, b, c) {
+          after && after();
+          Dcat.loading(false);
+          _this._req = 0;
+
+          if (a.status != 404) {
+            Dcat.handleAjaxError(a, b, c);
+          }
+        }
+      });
+    }
+  };
+
+  function Orderable(opts) {
+    this.options = $.extend({
+      button: null,
+      url: ''
+    }, opts);
+    this.direction = this.key = this.tier = this.row = this._req = null;
+
+    this._init();
+  }
+
+  Orderable.prototype = {
+    _init: function _init() {
+      this._bindClick();
+    },
+    _bindClick: function _bindClick() {
+      var _this = this;
+
+      $(_this.options.button).off('click').click(function () {
+        if (_this._req) {
+          return;
+        }
+
+        _this._req = 1;
+        Dcat.loading();
+        var $this = $(this);
+        _this.key = $this.data('id');
+        _this.direction = $this.data('direction');
+        _this.row = $this.closest('tr');
+        _this.tier = getTier(_this.row);
+
+        _this._request();
+      });
+    },
+    _request: function _request() {
+      var _this = this,
+          key = _this.key,
+          row = _this.row,
+          tier = _this.tier,
+          direction = _this.direction,
+          prevAll = row.prevAll(),
+          nextAll = row.nextAll(),
+          prev = row.prevAll('tr').first(),
+          next = row.nextAll('tr').first();
+
+      $.ajax({
+        type: 'POST',
+        url: _this.options.url.replace(':key', key),
+        data: {
+          _method: 'PUT',
+          _token: Dcat.token,
+          _orderable: direction
+        },
+        success: function success(data) {
+          Dcat.loading(false);
+          _this._req = 0;
+
+          if (!data.status) {
+            return data.message && Dcat.warning(data.message);
+          }
+
+          Dcat.success(data.message);
+
+          if (direction) {
+            var prevRow = sibling(prevAll, tier);
+
+            if (swapable(prevRow, tier) && prev.length && getTier(prev) >= tier) {
+              prevRow.before(row); // 把所有子节点上移
+
+              getChildren(nextAll, row).forEach(function (v) {
+                prevRow.before(v);
+              });
+            }
+          } else {
+            var nextRow = sibling(nextAll, tier),
+                nextRowChildren = nextRow ? getChildren(nextRow.nextAll(), nextRow) : [];
+
+            if (swapable(nextRow, tier) && next.length && getTier(next) >= tier) {
+              nextAll = row.nextAll();
+
+              if (nextRowChildren.length) {
+                nextRow = $(nextRowChildren.pop());
+              } // 把所有子节点下移
+
+
+              var all = [];
+              getChildren(nextAll, row).forEach(function (v) {
+                all.unshift(v);
+              });
+              all.forEach(function (v) {
+                nextRow.after(v);
+              });
+              nextRow.after(row);
+            }
+          }
+        },
+        error: function error(a, b, c) {
+          _this._req = 0;
+          Dcat.loading(false);
+          Dcat.handleAjaxError(a, b, c);
+        }
+      });
+    }
+  };
+
+  function isTr(v) {
+    return $(v).prop('tagName').toLocaleLowerCase() === 'tr';
+  }
+
+  function getTier(v) {
+    return parseInt($(v).data('tier') || 0);
+  }
+
+  function isChildren(parent, child) {
+    return getTier(child) > getTier(parent);
+  }
+
+  function getChildren(all, parent) {
+    var arr = [],
+        isBreak = false,
+        firstTr;
+    all.each(function (_, v) {
+      // 过滤非tr标签
+      if (!isTr(v) || isBreak) return;
+      firstTr || (firstTr = $(v)); // 非连续的子节点
+
+      if (firstTr && !isChildren(parent, firstTr)) {
+        return;
+      }
+
+      if (isChildren(parent, v)) {
+        arr.push(v);
+      } else {
+        isBreak = true;
+      }
+    });
+    return arr;
+  }
+
+  function swapable(_o, tier) {
+    if (_o && _o.length && tier === getTier(_o)) {
+      return true;
+    }
+  }
+
+  function sibling(all, tier) {
+    var next;
+    all.each(function (_, v) {
+      if (getTier(v) === tier && !next && isTr(v)) {
+        next = $(v);
+      }
+    });
+    return next;
+  }
+
+  Dcat.grid.Tree = function (opts) {
+    return new Tree(opts);
+  };
+
+  Dcat.grid.Orderable = function (opts) {
+    return new Orderable(opts);
+  };
+})(window, jQuery);
+
+/***/ }),
+
+/***/ 1:
+/*!**********************************************************!*\
+  !*** multi ./resources/assets/dcat/extra/grid-extend.js ***!
+  \**********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = __webpack_require__(/*! F:\p\dcat-admin-github\dcat-admin\resources\assets\dcat\extra\grid-extend.js */"./resources/assets/dcat/extra/grid-extend.js");
+
+
+/***/ })
+
+/******/ });

+ 2 - 2
resources/dist/dcat/extra/resource-selector.js

@@ -81,7 +81,7 @@
 /******/
 /******/
 /******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(__webpack_require__.s = 1);
+/******/ 	return __webpack_require__(__webpack_require__.s = 2);
 /******/ })
 /************************************************************************/
 /******/ ({
@@ -464,7 +464,7 @@ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "functi
 
 /***/ }),
 
-/***/ 1:
+/***/ 2:
 /*!****************************************************************!*\
   !*** multi ./resources/assets/dcat/extra/resource-selector.js ***!
   \****************************************************************/

+ 2 - 2
resources/dist/js/core/app-menu.js

@@ -81,7 +81,7 @@
 /******/
 /******/
 /******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(__webpack_require__.s = 2);
+/******/ 	return __webpack_require__(__webpack_require__.s = 3);
 /******/ })
 /************************************************************************/
 /******/ ({
@@ -1013,7 +1013,7 @@ window.addEventListener('resize', function () {
 
 /***/ }),
 
-/***/ 2:
+/***/ 3:
 /*!****************************************************!*\
   !*** multi ./resources/assets/js/core/app-menu.js ***!
   \****************************************************/

+ 2 - 2
resources/dist/js/core/app.js

@@ -81,7 +81,7 @@
 /******/
 /******/
 /******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(__webpack_require__.s = 3);
+/******/ 	return __webpack_require__(__webpack_require__.s = 4);
 /******/ })
 /************************************************************************/
 /******/ ({
@@ -850,7 +850,7 @@
 
 /***/ }),
 
-/***/ 3:
+/***/ 4:
 /*!***********************************************!*\
   !*** multi ./resources/assets/js/core/app.js ***!
   \***********************************************/

+ 2 - 2
src/Controllers/PermissionController.php

@@ -163,7 +163,7 @@ class PermissionController extends AdminController
                 }
 
                 if (! empty(config('admin.route.prefix'))) {
-                    $path = admin_base_path($path);
+                    $path = trim(admin_base_path($path), '/');
                 }
 
                 return "<div style='margin-bottom: 5px;'>$method<code>$path</code></div>";
@@ -184,7 +184,7 @@ class PermissionController extends AdminController
 
             $label = trans('admin.default');
             $url = url(request()->getPathInfo());
-            $tools->append("<a class='btn btn-sm btn-white ' href='{$url}'>$label</a>");
+            $tools->append("<a class='btn btn-white ' href='{$url}'>$label</a>");
         });
 
         $grid->filter(function (Grid\Filter $filter) {

+ 2 - 2
src/Grid/Displayers/Orderable.php

@@ -7,7 +7,7 @@ use Dcat\Admin\Admin;
 class Orderable extends AbstractDisplayer
 {
     protected static $js = [
-        'vendor/dcat-admin/dcat-admin/grid-extend.min.js',
+        'grid-extension',
     ];
 
     public function display()
@@ -30,7 +30,7 @@ EOT;
     protected function script()
     {
         return <<<JS
-        Dcat.grid.orderable({
+        Dcat.grid.Orderable({
             button: '.{$this->grid->getRowName()}-orderable',
             url: '{$this->resource()}/:key',
         });

+ 1 - 1
src/Grid/Displayers/Tree.php

@@ -43,7 +43,7 @@ JS;
         $tableId = $this->grid->getTableId();
 
         $tier = $this->grid->model()->getTierFromRequest();
-        $indents = str_repeat(' &nbsp; &nbsp; &nbsp; &nbsp; ', $tier);
+        $indents = str_repeat(' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ', $tier);
 
         return <<<EOT
 <a href="javascript:void(0)" class="{$tableId}-grid-load-children" data-tier="{$tier}" data-inserted="0" data-key="{$key}">

+ 4 - 0
src/Layout/Assets.php

@@ -21,6 +21,10 @@ class Assets
             'css' => 'dcat-admin/css/custom-laravel.css',
         ],
 
+        'grid-extension' => [
+            'js' => 'dcat-admin/dcat/extra/grid-extend.js',
+        ],
+
         'jquery.nestable' => [
             'js'  => 'dcat-admin/dcat/plugins/nestable/jquery.nestable.min.js',
             'css' => 'dcat-admin/dcat/plugins/nestable/nestable.css',