feat: Phase 2 Sider 菜单由 FBA 服务端授权驱动 + 菜单/角色播种脚本(Epic #159)
This commit is contained in:
@@ -241,14 +241,14 @@
|
||||
menu.appendChild(wrap);
|
||||
}
|
||||
|
||||
function renderMenu(user) {
|
||||
function renderMenu(mods) {
|
||||
menu.innerHTML = "";
|
||||
// AntD Menu.ItemGroup 风格分组标题
|
||||
var group = el("div", "pro-menu-group-title", "功能模块");
|
||||
menu.appendChild(group);
|
||||
// 菜单即模块清单,按角色过滤
|
||||
var mods = user ? IAOP_SESSION.modulesFor(user.role) : [];
|
||||
mods.forEach(function (m) {
|
||||
// 菜单即模块清单:Epic #159 Phase 2 起由 session.js menuTree()
|
||||
// 输出(FBA 服务端按角色授权过滤,本地角色过滤兜底)
|
||||
(mods || []).forEach(function (m) {
|
||||
if (m.children && m.children.length) addSubMenu(m);
|
||||
else addLeafItem(m.key, m.icon, m.title, prefix + m.url);
|
||||
});
|
||||
@@ -296,12 +296,12 @@
|
||||
};
|
||||
}
|
||||
|
||||
/* ---- 用户区(后端优先、本地降级由 session.js 内部处理) --------------- */
|
||||
/* ---- 用户区 + 菜单(FBA 服务端授权优先,本地角色过滤兜底) ------------- */
|
||||
IAOP_SESSION.currentUser().then(function (u) {
|
||||
renderMenu(u);
|
||||
userBox.innerHTML = "";
|
||||
if (!u) {
|
||||
userBox.appendChild(el("span", "pro-tag pro-tag-default", "未登录"));
|
||||
renderMenu([]);
|
||||
return;
|
||||
}
|
||||
var avatar = el("span", "pro-avatar",
|
||||
@@ -311,6 +311,8 @@
|
||||
var color = IAOP_SESSION.ROLE_TAG_COLORS[u.role] || "default";
|
||||
var label = IAOP_SESSION.ROLE_LABELS[u.role] || u.role;
|
||||
userBox.appendChild(el("span", "pro-tag pro-tag-" + color, label));
|
||||
// 菜单异步:FBA token 存在时取服务端授权菜单树(Phase 2)
|
||||
IAOP_SESSION.menuTree(u).then(renderMenu);
|
||||
});
|
||||
|
||||
bindPageTabs();
|
||||
|
||||
+53
-1
@@ -396,6 +396,57 @@ var IAOP_SESSION = (function () {
|
||||
return !!m && m.roles.indexOf(role) >= 0;
|
||||
}
|
||||
|
||||
/* ---- Epic #159 Phase 2:服务端驱动菜单 ----------------------------------
|
||||
* 有 FBA token 时:GET /fba/api/v1/sys/menus/sidebar 取当前用户在服务端
|
||||
* 被授权的菜单树(vben5 结构,按角色在服务端过滤),与本地 MODULES 注册表
|
||||
* 按 name == module.key 匹配,得到「服务端授权 ∩ 本地已知模块」的最终菜单;
|
||||
* 子菜单同理按 child.key 匹配过滤。
|
||||
* FBA 不可用 / 无匹配(菜单未播种 deploy/fba/seed_iaop_menus.py)时,
|
||||
* 降级为本地角色过滤,保证菜单不空白。
|
||||
* 返回 Promise<MODULES 子集>。 */
|
||||
function menuTree(user) {
|
||||
if (!user) return Promise.resolve([]);
|
||||
if (!readFbaToken()) return Promise.resolve(modulesFor(user.role));
|
||||
return fbaFetch("/sys/menus/sidebar")
|
||||
.then(function (r) { return r.ok ? r.json() : null; })
|
||||
.then(function (d) {
|
||||
if (!d || d.code !== 200 || !Array.isArray(d.data)) {
|
||||
return modulesFor(user.role);
|
||||
}
|
||||
var allowed = {}; // moduleKey -> true(无子菜单)| {childKey: true}
|
||||
d.data.forEach(function (node) {
|
||||
if (!node || !node.name) return;
|
||||
var mod = null;
|
||||
for (var i = 0; i < MODULES.length; i++) {
|
||||
if (MODULES[i].key === node.name) { mod = MODULES[i]; break; }
|
||||
}
|
||||
if (!mod) return; // FBA 自有菜单(系统管理等)不匹配,跳过
|
||||
if (node.children && node.children.length) {
|
||||
var kids = {};
|
||||
node.children.forEach(function (c) {
|
||||
if (c && c.name) kids[c.name] = true;
|
||||
});
|
||||
allowed[mod.key] = kids;
|
||||
} else {
|
||||
allowed[mod.key] = true;
|
||||
}
|
||||
});
|
||||
var mods = MODULES.filter(function (m) { return !!allowed[m.key]; })
|
||||
.map(function (m) {
|
||||
if (!m.children || !m.children.length || allowed[m.key] === true) return m;
|
||||
var kids = allowed[m.key];
|
||||
var copy = Object.assign({}, m, {
|
||||
children: m.children.filter(function (c) { return !!kids[c.key]; })
|
||||
});
|
||||
return copy;
|
||||
});
|
||||
// 服务端树里没有任何 iAOP 模块(未播种)→ 本地角色过滤兜底
|
||||
return mods.length ? mods : modulesFor(user.role);
|
||||
})
|
||||
.catch(function () { return modulesFor(user.role); });
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
MODULES: MODULES,
|
||||
ROLE_LABELS: ROLE_LABELS,
|
||||
@@ -409,7 +460,8 @@ var IAOP_SESSION = (function () {
|
||||
/* FBA 新增 */
|
||||
fbaStatus: fbaStatus,
|
||||
getCaptcha: getCaptcha,
|
||||
getAuthHeaders: getAuthHeaders
|
||||
getAuthHeaders: getAuthHeaders,
|
||||
menuTree: menuTree
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user