LIJIAN 1 bulan lalu
induk
melakukan
fd46bab698

+ 58 - 0
ema-admin/src/main/resources/web/css/main.css

@@ -682,6 +682,64 @@ body {
     to { opacity: 1; transform: translateX(0); }
 }
 
+/* ==================== 标签页右键菜单 ==================== */
+.tab-ctx-menu {
+    position: fixed;
+    z-index: 99999;
+    min-width: 140px;
+    background: #fff;
+    border-radius: var(--border-radius-sm);
+    box-shadow: var(--shadow-lg);
+    border: 1px solid var(--border-color);
+    padding: 4px 0;
+    display: none;
+    animation: fadeIn 0.15s ease-out;
+}
+
+.tab-ctx-menu li {
+    padding: 8px 16px;
+    font-size: 13px;
+    color: #595959;
+    cursor: pointer;
+    transition: all var(--transition-fast);
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    white-space: nowrap;
+}
+
+.tab-ctx-menu li:hover {
+    background: var(--primary-light-bg);
+    color: var(--primary-color);
+}
+
+.tab-ctx-menu li.disabled {
+    color: #d9d9d9;
+    cursor: not-allowed;
+}
+
+.tab-ctx-menu li.disabled:hover {
+    background: transparent;
+    color: #d9d9d9;
+}
+
+.tab-ctx-menu li .layui-icon {
+    font-size: 14px;
+    margin-right: 0;
+}
+
+.tab-ctx-menu .ctx-divider {
+    height: 1px;
+    background: var(--border-color);
+    margin: 4px 0;
+    padding: 0;
+    cursor: default;
+}
+
+.tab-ctx-menu .ctx-divider:hover {
+    background: var(--border-color);
+}
+
 /* ==================== 工具类 ==================== */
 .text-center { text-align: center; }
 .text-right { text-align: right; }

+ 175 - 0
ema-admin/src/main/resources/web/js/main.js

@@ -162,6 +162,181 @@ layui.use(['element', 'layer'], function () {
         $(document).on('click', '.refresh-page', function () {
             refreshCurrentTab();
         });
+
+        // 初始化标签页右键菜单
+        initTabContextMenu();
+    }
+
+    /**
+     * 初始化标签页右键菜单
+     */
+    function initTabContextMenu() {
+        // 创建右键菜单DOM
+        var menuHtml = '<ul class="tab-ctx-menu" id="tabCtxMenu">' +
+            '<li data-action="refresh"><i class="layui-icon layui-icon-refresh"></i>刷新当前</li>' +
+            '<li class="ctx-divider"></li>' +
+            '<li data-action="closeCurrent"><i class="layui-icon layui-icon-close"></i>关闭当前</li>' +
+            '<li data-action="closeOther"><i class="layui-icon layui-icon-unlink"></i>关闭其他</li>' +
+            '<li data-action="closeLeft"><i class="layui-icon layui-icon-prev"></i>关闭左侧</li>' +
+            '<li data-action="closeRight"><i class="layui-icon layui-icon-next"></i>关闭右侧</li>' +
+            '<li class="ctx-divider"></li>' +
+            '<li data-action="closeAll"><i class="layui-icon layui-icon-delete"></i>关闭所有</li>' +
+            '</ul>';
+        $('body').append(menuHtml);
+
+        var $menu = $('#tabCtxMenu');
+        var contextTabId = null; // 右键点击的标签 ID
+
+        // 标签页右键事件
+        $(document).on('contextmenu', '#tabTitle li', function (e) {
+            e.preventDefault();
+            contextTabId = $(this).attr('lay-id');
+
+            // 设置菜单项状态
+            var $tabs = $('#tabTitle li');
+            var currentIndex = $tabs.index($(this));
+            var totalTabs = $tabs.length;
+            var isHome = contextTabId === 'home';
+
+            // 关闭当前:首页不可关闭
+            $menu.find('[data-action="closeCurrent"]').toggleClass('disabled', isHome);
+            // 关闭其他:只有首页时禁用
+            $menu.find('[data-action="closeOther"]').toggleClass('disabled', totalTabs <= 1 || (totalTabs === 1 && isHome));
+            // 关闭左侧:左边没有可关闭的标签时禁用
+            $menu.find('[data-action="closeLeft"]').toggleClass('disabled', currentIndex <= 1);
+            // 关闭右侧:右边没有标签时禁用
+            $menu.find('[data-action="closeRight"]').toggleClass('disabled', currentIndex >= totalTabs - 1);
+            // 关闭所有:只有首页时禁用
+            $menu.find('[data-action="closeAll"]').toggleClass('disabled', totalTabs <= 1);
+
+            // 显示菜单并定位
+            var menuWidth = 160;
+            var menuHeight = 230;
+            var posX = e.clientX;
+            var posY = e.clientY;
+
+            // 防止菜单超出右侧和底部
+            if (posX + menuWidth > $(window).width()) {
+                posX = $(window).width() - menuWidth - 5;
+            }
+            if (posY + menuHeight > $(window).height()) {
+                posY = $(window).height() - menuHeight - 5;
+            }
+
+            $menu.css({ left: posX, top: posY }).show();
+        });
+
+        // 菜单项点击事件
+        $menu.on('click', 'li[data-action]', function () {
+            var action = $(this).data('action');
+            if ($(this).hasClass('disabled') || $(this).hasClass('ctx-divider')) return;
+
+            switch (action) {
+                case 'refresh':
+                    // 先切换到目标标签,再刷新
+                    element.tabChange('mainTab', contextTabId);
+                    setTimeout(refreshCurrentTab, 100);
+                    break;
+                case 'closeCurrent':
+                    if (contextTabId !== 'home') {
+                        element.tabDelete('mainTab', contextTabId);
+                    }
+                    break;
+                case 'closeOther':
+                    closeOtherTabs(contextTabId);
+                    break;
+                case 'closeLeft':
+                    closeLeftTabs(contextTabId);
+                    break;
+                case 'closeRight':
+                    closeRightTabs(contextTabId);
+                    break;
+                case 'closeAll':
+                    closeAllTabs();
+                    break;
+            }
+            $menu.hide();
+        });
+
+        // 点击其他地方关闭菜单
+        $(document).on('click', function () {
+            $menu.hide();
+        });
+
+        // 滚动时关闭菜单
+        $(document).on('scroll', function () {
+            $menu.hide();
+        });
+    }
+
+    /**
+     * 关闭其他标签页(保留首页和指定标签)
+     */
+    function closeOtherTabs(keepId) {
+        $('#tabTitle li').each(function () {
+            var id = $(this).attr('lay-id');
+            if (id !== 'home' && id !== keepId) {
+                element.tabDelete('mainTab', id);
+            }
+        });
+        element.tabChange('mainTab', keepId);
+    }
+
+    /**
+     * 关闭左侧标签页
+     */
+    function closeLeftTabs(currentId) {
+        var found = false;
+        var toClose = [];
+        $('#tabTitle li').each(function () {
+            var id = $(this).attr('lay-id');
+            if (id === currentId) {
+                found = true;
+                return false;
+            }
+            if (id !== 'home') {
+                toClose.push(id);
+            }
+        });
+        toClose.forEach(function (id) {
+            element.tabDelete('mainTab', id);
+        });
+        element.tabChange('mainTab', currentId);
+    }
+
+    /**
+     * 关闭右侧标签页
+     */
+    function closeRightTabs(currentId) {
+        var found = false;
+        var toClose = [];
+        $('#tabTitle li').each(function () {
+            var id = $(this).attr('lay-id');
+            if (id === currentId) {
+                found = true;
+                return;
+            }
+            if (found && id !== 'home') {
+                toClose.push(id);
+            }
+        });
+        toClose.forEach(function (id) {
+            element.tabDelete('mainTab', id);
+        });
+        element.tabChange('mainTab', currentId);
+    }
+
+    /**
+     * 关闭所有标签页(保留首页)
+     */
+    function closeAllTabs() {
+        $('#tabTitle li').each(function () {
+            var id = $(this).attr('lay-id');
+            if (id !== 'home') {
+                element.tabDelete('mainTab', id);
+            }
+        });
+        element.tabChange('mainTab', 'home');
     }
 
     /**