fix: 导航交互对齐 Ant Design Pro 体验(issue #131)

- 父级菜单整行点击 = 就地展开/收起 inline 子菜单(不再跳转),
  只有子项才导航,与 Pro 的 Menu inline 模式一致
- 子菜单展开加 max-height 过渡动画
- 菜单加 AntD Menu.ItemGroup 风格分组标题,hover 态补半透明白底
- 页内旧 topbar 去背景去边线,融入内容区当页标题行,消除双顶栏感
This commit is contained in:
2026-08-05 16:20:52 +08:00
parent 0b3dc0b9ae
commit c0af291502
2 changed files with 29 additions and 14 deletions
+7 -4
View File
@@ -162,16 +162,16 @@
var head = el("a", "pro-menu-item pro-submenu-title" + var head = el("a", "pro-menu-item pro-submenu-title" +
(isActiveModule ? " active" : "")); (isActiveModule ? " active" : ""));
head.href = prefix + m.url; head.href = "#";
head.title = m.title; head.title = m.title;
head.appendChild(el("span", "pro-menu-icon", m.icon)); head.appendChild(el("span", "pro-menu-icon", m.icon));
head.appendChild(el("span", "pro-menu-text", m.title)); head.appendChild(el("span", "pro-menu-text", m.title));
var arrow = el("span", "pro-submenu-arrow", "▸"); var arrow = el("span", "pro-submenu-arrow", "▸");
head.appendChild(arrow); head.appendChild(arrow);
// 箭头区域点击只展开/收起,不跳转;点标题文字跳转 // AntD Pro inline 菜单交互:整行点击 = 就地展开/收起(不跳转),
arrow.addEventListener("click", function (e) { // 只有子项才导航(跨页跳转或同页 hash 切换)
head.addEventListener("click", function (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation();
wrap.classList.toggle("open"); wrap.classList.toggle("open");
}); });
wrap.appendChild(head); wrap.appendChild(head);
@@ -203,6 +203,9 @@
function renderMenu(user) { function renderMenu(user) {
menu.innerHTML = ""; menu.innerHTML = "";
// AntD Menu.ItemGroup 风格分组标题
var group = el("div", "pro-menu-group-title", "功能模块");
menu.appendChild(group);
// 无门户页(2026-08):菜单即模块清单,按角色过滤 // 无门户页(2026-08):菜单即模块清单,按角色过滤
var mods = user ? IAOP_SESSION.modulesFor(user.role) : []; var mods = user ? IAOP_SESSION.modulesFor(user.role) : [];
mods.forEach(function (m) { mods.forEach(function (m) {
+22 -10
View File
@@ -137,11 +137,19 @@ body {
overflow: hidden; overflow: hidden;
transition: background 0.2s, color 0.2s; transition: background 0.2s, color 0.2s;
} }
.pro-menu-item:hover { color: #fff; } .pro-menu-item:hover { color: #fff; background: rgba(255, 255, 255, 0.08); }
.pro-menu-item.active { .pro-menu-item.active {
background: var(--ant-primary); background: var(--ant-primary);
color: #fff; color: #fff;
} }
/* AntD Menu.ItemGroup 分组标题 */
.pro-menu-group-title {
padding: 10px 16px 4px;
font-size: 12px;
color: rgba(255, 255, 255, 0.45);
white-space: nowrap;
overflow: hidden;
}
.pro-menu-icon { font-size: 16px; flex-shrink: 0; width: 20px; text-align: center; } .pro-menu-icon { font-size: 16px; flex-shrink: 0; width: 20px; text-align: center; }
.pro-menu-text { overflow: hidden; text-overflow: ellipsis; flex: 1; } .pro-menu-text { overflow: hidden; text-overflow: ellipsis; flex: 1; }
@@ -155,13 +163,15 @@ body {
} }
.pro-submenu.open .pro-submenu-arrow { transform: rotate(90deg); } .pro-submenu.open .pro-submenu-arrow { transform: rotate(90deg); }
.pro-submenu-items { .pro-submenu-items {
display: none; max-height: 0;
overflow: hidden;
transition: max-height 0.25s ease; /* AntD inline 菜单展开动画 */
background: #000c17; /* AntD 深色菜单子层底色 */ background: #000c17; /* AntD 深色菜单子层底色 */
border-radius: var(--ant-radius); border-radius: var(--ant-radius);
margin: 0 8px 4px; margin: 0 8px 4px;
padding: 4px 0; padding: 0;
} }
.pro-submenu.open .pro-submenu-items { display: block; } .pro-submenu.open .pro-submenu-items { max-height: 320px; padding: 4px 0; }
.pro-subitem { .pro-subitem {
display: block; display: block;
height: 34px; height: 34px;
@@ -177,7 +187,7 @@ body {
text-overflow: ellipsis; text-overflow: ellipsis;
transition: background 0.2s, color 0.2s; transition: background 0.2s, color 0.2s;
} }
.pro-subitem:hover { color: #fff; } .pro-subitem:hover { color: #fff; background: rgba(255, 255, 255, 0.08); }
.pro-subitem.active { .pro-subitem.active {
background: var(--ant-primary); background: var(--ant-primary);
color: #fff; color: #fff;
@@ -284,11 +294,13 @@ body.pro-sider-collapsed .pro-sider-logo { justify-content: center; padding: 0;
.pro-tag-default{ color: var(--ant-text-secondary); background: #fafafa; .pro-tag-default{ color: var(--ant-text-secondary); background: #fafafa;
border-color: var(--ant-border); } border-color: var(--ant-border); }
/* ---- 各模块页页内顶栏 → AntD PageHeader 风格 --------------------------- */ /* ---- 各模块页页内顶栏 → 融入内容区的页标题行 ----------------------------- */
/* 覆盖 cockpit/studio/admin/users 的 #topbar(结构不变,外观统一) */ /* 全局 Sider+细栏已就位,页内 #topbar 不再画成第二条导航条:
#topbar { 去背景去边线,视觉上只是内容区的页面标题行(AntD Pro PageContainer 语义) */
background: var(--ant-bg-container) !important; body.has-pro-sider #topbar {
border-bottom: 1px solid var(--ant-split) !important; background: transparent !important;
border-bottom: none !important;
box-shadow: none !important;
} }
#topbar h1, #topbar h1 .sub { color: var(--ant-text) !important; } #topbar h1, #topbar h1 .sub { color: var(--ant-text) !important; }
#topbar h1 .sub { color: var(--ant-text-tertiary) !important; } #topbar h1 .sub { color: var(--ant-text-tertiary) !important; }