fix: harden module outline normalization

This commit is contained in:
王鹏
2026-07-07 14:05:06 +08:00
parent 0e3d2f09a2
commit 27aaa13fcc
2 changed files with 46 additions and 12 deletions

View File

@@ -11,8 +11,10 @@ function textFromFields(value, fallback = '') {
return cleanText(value.title ?? value.name ?? value.code, fallback)
}
function menuTitle(menu, index) {
return cleanText(menu?.name ?? menu?.title ?? menu?.code, `功能${index + 1}`)
function menuToItem(menu) {
if (!menu || typeof menu !== 'object') return null
const title = cleanText(menu.name ?? menu.title ?? menu.code)
return title ? { title } : null
}
function warning(code, line) {
@@ -30,12 +32,15 @@ export function normalizeModuleOutline(outline = {}) {
const groups = Array.isArray(outline.groups) ? outline.groups : []
return {
title: textFromFields(outline),
groups: groups.map((group) => ({
title: textFromFields(group),
items: (Array.isArray(group?.items) ? group.items : []).map((item) => ({
groups: groups.map((group) => {
const items = (Array.isArray(group?.items) ? group.items : []).map((item) => ({
title: textFromFields(item)
})).filter((item) => item.title)
})).filter((group) => group.title || group.items.length)
return {
title: textFromFields(group, items.length ? FALLBACK_GROUP_TITLE : ''),
items
}
}).filter((group) => group.title || group.items.length)
}
}
@@ -94,15 +99,11 @@ export function blueprintToModuleOutline(blueprint = {}, options = {}) {
const groups = [
{
title: '管理员端',
items: (Array.isArray(blueprint.adminMenus) ? blueprint.adminMenus : []).map((menu, index) => ({
title: menuTitle(menu, index)
})).filter((item) => item.title)
items: (Array.isArray(blueprint.adminMenus) ? blueprint.adminMenus : []).map(menuToItem).filter(Boolean)
},
{
title: '普通用户端',
items: (Array.isArray(blueprint.frontendMenus) ? blueprint.frontendMenus : []).map((menu, index) => ({
title: menuTitle(menu, index)
})).filter((item) => item.title)
items: (Array.isArray(blueprint.frontendMenus) ? blueprint.frontendMenus : []).map(menuToItem).filter(Boolean)
}
].filter((group) => group.items.length)

View File

@@ -95,6 +95,39 @@ test('blueprintToModuleOutline maps project menus into standard groups', () => {
assert.deepEqual(outline.groups[1].items.map((item) => item.title), ['社团浏览', 'profile'])
})
test('blueprintToModuleOutline skips invalid menus while preserving code-only menus', () => {
const outline = blueprintToModuleOutline({
adminMenus: [
null,
'菜单',
{},
{ name: ' ', title: '', code: '\t' },
{ code: 'users' }
],
frontendMenus: [
undefined,
{ title: ' ' },
{ code: 'browse' }
]
})
assert.deepEqual(outline.groups.map((group) => group.title), ['管理员端', '普通用户端'])
assert.deepEqual(outline.groups[0].items.map((item) => item.title), ['users'])
assert.deepEqual(outline.groups[1].items.map((item) => item.title), ['browse'])
})
test('normalizeModuleOutline gives untitled groups with items the fallback group title', () => {
const outline = normalizeModuleOutline({
title: '客户管理系统',
groups: [
{ title: ' ', items: [{ title: '客户列表' }] }
]
})
assert.equal(outline.groups[0].title, '未分组模块')
assert.equal(moduleOutlineToText(outline), '客户管理系统\n 未分组模块\n 客户列表')
})
test('moduleOutlineToText serializes normalized outlines with two-space levels', () => {
const outline = normalizeModuleOutline({
title: '学生社团管理系统',