diff --git a/panel/web/src/pages/Admin.tsx b/panel/web/src/pages/Admin.tsx index bd18371..f59e9fb 100644 --- a/panel/web/src/pages/Admin.tsx +++ b/panel/web/src/pages/Admin.tsx @@ -887,7 +887,17 @@ function InstanceAdminCard({ const installed = wx.installed && wx.phase !== 'downloading'; const offline = inst.runtime !== 'running'; const working = !!acting || busy; // 生命周期操作中 或 微信下载/更新中 → 锁住卡片 - const [menuOpen, setMenuOpen] = useState(false); // 「管理」折叠菜单是否展开 + const [menuOpen, setMenuOpen] = useState(false); // 「管理」菜单是否展开(悬浮层,不占文档流) + const menuRef = useRef(null); + // 悬浮下拉:点击菜单外部时关闭 + useEffect(() => { + if (!menuOpen) return; + const onDocDown = (e: MouseEvent) => { + if (menuRef.current && !menuRef.current.contains(e.target as Node)) setMenuOpen(false); + }; + document.addEventListener('mousedown', onDocDown); + return () => document.removeEventListener('mousedown', onDocDown); + }, [menuOpen]); let badge: { text: string; cls: string }; if (acting) badge = { text: '处理中', cls: 'tag-busy' }; @@ -905,7 +915,7 @@ function InstanceAdminCard({ else sub = '微信尚未安装'; return ( -
+
{inst.name} {badge.text} @@ -939,13 +949,14 @@ function InstanceAdminCard({ )}
- +
+ - {menuOpen && ( -
+ {menuOpen && ( +
setMenuOpen(false)}>
运维
@@ -997,7 +1008,8 @@ function InstanceAdminCard({
- )} + )} +
)}
diff --git a/panel/web/src/styles.css b/panel/web/src/styles.css index 35aad48..7a05465 100644 --- a/panel/web/src/styles.css +++ b/panel/web/src/styles.css @@ -307,7 +307,6 @@ button { /* 实例卡片操作:「管理」分类折叠菜单(默认收起,点开按运维/设置/危险分组展开文字操作) */ .inst-menu-toggle { - margin-top: 10px; width: 100%; height: 38px; display: flex; @@ -335,11 +334,24 @@ button { .inst-menu-toggle.open .inst-menu-caret { transform: rotate(180deg); } +/* 「管理」菜单:绝对定位悬浮层,浮在下方内容之上,不把卡片撑高、不顶走后面的内容 */ +.inst-menu-wrap { + position: relative; + margin-top: 10px; +} .inst-menu { - margin-top: 8px; + position: absolute; + top: calc(100% + 6px); + left: 0; + right: 0; + z-index: 2; display: flex; flex-direction: column; gap: 6px; + padding: 10px; + background: var(--surface); + border-radius: var(--r-small); + box-shadow: 0 6px 22px rgba(var(--shadow) / 0.26), 0 2px 6px rgba(var(--shadow) / 0.18); animation: inst-menu-in 0.16s ease; } @keyframes inst-menu-in { @@ -928,6 +940,11 @@ button { .inst-card > * { position: relative; } +/* 菜单展开时:放开裁剪让悬浮层露出,并抬升层级盖住下方/同列卡片(仍低于弹窗 z-index 20) */ +.inst-card.open-menu { + overflow: visible; + z-index: 5; +} .inst-head { display: flex; align-items: center;