feat(B批收尾): B1门禁可信/B7-1菜单环防护/B2空值守卫/B7-2分页/B7-3字段清洗/B3空态/B4索引key/B5-3 comment三集合选A新建schema(漂移清零)/B6清理+admin配置+changelog
This commit is contained in:
@@ -1,67 +1,116 @@
|
||||
function buildMenu(menu, menuList, menuIds) {
|
||||
let nextLayer = []
|
||||
for (let i = menu.length - 1; i > -1; i--) {
|
||||
const currentMenu = menu[i]
|
||||
const subMenu = menuList.filter(item => {
|
||||
if (item.parent_id === currentMenu.menu_id) {
|
||||
menuIds.push(item.menu_id)
|
||||
return true
|
||||
}
|
||||
})
|
||||
nextLayer = nextLayer.concat(subMenu)
|
||||
currentMenu.children = subMenu
|
||||
}
|
||||
if (nextLayer.length) {
|
||||
buildMenu(nextLayer, menuList, menuIds)
|
||||
}
|
||||
}
|
||||
|
||||
function getParentIds(menuItem, menuList) {
|
||||
const parentArr = []
|
||||
let currentItem = menuItem
|
||||
while (currentItem && currentItem.parent_id) {
|
||||
parentArr.push(currentItem.parent_id)
|
||||
currentItem = menuList.find(item => item.menu_id === currentItem.parent_id)
|
||||
}
|
||||
return parentArr
|
||||
}
|
||||
|
||||
function buildMenus(menuList, trim = true) {
|
||||
// 保证父子级顺序
|
||||
menuList = menuList.sort(function(a, b) {
|
||||
const parentIdsA = getParentIds(a, menuList)
|
||||
const parentIdsB = getParentIds(b, menuList)
|
||||
if (parentIdsA.includes(b.menu_id)) {
|
||||
return 1
|
||||
}
|
||||
return parentIdsA.length - parentIdsB.length || a.sort - b.sort
|
||||
})
|
||||
// 删除无subMenu且非子节点的菜单项
|
||||
if (trim) {
|
||||
for (let i = menuList.length - 1; i > -1; i--) {
|
||||
const currentMenu = menuList[i]
|
||||
const subMenu = menuList.filter(subMenuItem => subMenuItem.parent_id === currentMenu.menu_id)
|
||||
if (!currentMenu.isLeafNode && !subMenu.length) {
|
||||
menuList.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
const menuIds = []
|
||||
const menu = menuList.filter(item => {
|
||||
if (!item.parent_id) {
|
||||
menuIds.push(item.menu_id)
|
||||
return true
|
||||
}
|
||||
})
|
||||
buildMenu(menu, menuList, menuIds)
|
||||
// 包含所有无效菜单
|
||||
if (!trim && menuIds.length !== menuList.length) {
|
||||
menu.push(...menuList.filter(item => !menuIds.includes(item.menu_id)))
|
||||
}
|
||||
return menu
|
||||
}
|
||||
|
||||
export {
|
||||
buildMenu,
|
||||
buildMenus
|
||||
}
|
||||
function buildMenu(menu, menuList, menuIds, visited) {
|
||||
visited = visited || new Set()
|
||||
let nextLayer = []
|
||||
for (let i = menu.length - 1; i > -1; i--) {
|
||||
const currentMenu = menu[i]
|
||||
if (visited.has(currentMenu.menu_id)) continue
|
||||
visited.add(currentMenu.menu_id)
|
||||
const subMenu = menuList.filter(item => {
|
||||
if (item.parent_id === currentMenu.menu_id) {
|
||||
if (visited.has(item.menu_id)) return false
|
||||
menuIds.push(item.menu_id)
|
||||
return true
|
||||
}
|
||||
})
|
||||
nextLayer = nextLayer.concat(subMenu)
|
||||
currentMenu.children = subMenu
|
||||
}
|
||||
if (nextLayer.length) {
|
||||
buildMenu(nextLayer, menuList, menuIds, visited)
|
||||
}
|
||||
}
|
||||
|
||||
function getParentIds(menuItem, menuList) {
|
||||
const parentArr = []
|
||||
const visited = new Set()
|
||||
let currentItem = menuItem
|
||||
while (currentItem && currentItem.parent_id) {
|
||||
if (visited.has(currentItem.parent_id)) {
|
||||
// B7-1: 数据成环(A→B、B→A)时立即返回已收集链,不再死循环
|
||||
parentArr.push(currentItem.parent_id)
|
||||
break
|
||||
}
|
||||
visited.add(currentItem.parent_id)
|
||||
parentArr.push(currentItem.parent_id)
|
||||
currentItem = menuList.find(item => item.menu_id === currentItem.parent_id)
|
||||
}
|
||||
return parentArr
|
||||
}
|
||||
|
||||
// B7-1: 判断把 menuId 的 parent 改为 newParentId 是否会成环
|
||||
function wouldCreateCycle(menuList, menuId, newParentId) {
|
||||
if (!newParentId) return false
|
||||
if (newParentId === menuId) return true
|
||||
const visited = new Set()
|
||||
let current = newParentId
|
||||
while (current) {
|
||||
if (current === menuId) return true
|
||||
if (visited.has(current)) return true
|
||||
visited.add(current)
|
||||
const item = menuList.find(m => m.menu_id === current)
|
||||
current = item && item.parent_id
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function buildMenus(menuList, trim = true) {
|
||||
// B7-1: sort 比较器不再每次重算 getParentIds —— 记忆化一次算完(链式 O(n))
|
||||
const byId = new Map()
|
||||
for (const item of menuList) byId.set(item.menu_id, item)
|
||||
const parentMap = new Map()
|
||||
function ancestors(id) {
|
||||
if (parentMap.has(id)) return parentMap.get(id)
|
||||
const chain = []
|
||||
const visited = new Set()
|
||||
let cur = byId.get(id)
|
||||
while (cur && cur.parent_id) {
|
||||
if (visited.has(cur.parent_id)) { chain.push(cur.parent_id); break }
|
||||
visited.add(cur.parent_id)
|
||||
chain.push(cur.parent_id)
|
||||
if (parentMap.has(cur.parent_id)) { chain.push(...parentMap.get(cur.parent_id)); break }
|
||||
cur = byId.get(cur.parent_id)
|
||||
}
|
||||
parentMap.set(id, chain)
|
||||
return chain
|
||||
}
|
||||
for (const item of menuList) ancestors(item.menu_id)
|
||||
// 保证父子级顺序
|
||||
menuList = menuList.sort(function(a, b) {
|
||||
const parentIdsA = parentMap.get(a.menu_id) || []
|
||||
const parentIdsB = parentMap.get(b.menu_id) || []
|
||||
if (parentIdsA.includes(b.menu_id)) {
|
||||
return 1
|
||||
}
|
||||
return parentIdsA.length - parentIdsB.length || a.sort - b.sort
|
||||
})
|
||||
// 删除无subMenu且非子节点的菜单项
|
||||
if (trim) {
|
||||
for (let i = menuList.length - 1; i > -1; i--) {
|
||||
const currentMenu = menuList[i]
|
||||
const subMenu = menuList.filter(subMenuItem => subMenuItem.parent_id === currentMenu.menu_id)
|
||||
if (!currentMenu.isLeafNode && !subMenu.length) {
|
||||
menuList.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
const menuIds = []
|
||||
const menu = menuList.filter(item => {
|
||||
if (!item.parent_id) {
|
||||
menuIds.push(item.menu_id)
|
||||
return true
|
||||
}
|
||||
})
|
||||
buildMenu(menu, menuList, menuIds, new Set())
|
||||
// 包含所有无效菜单
|
||||
if (!trim && menuIds.length !== menuList.length) {
|
||||
menu.push(...menuList.filter(item => !menuIds.includes(item.menu_id)))
|
||||
}
|
||||
return menu
|
||||
}
|
||||
|
||||
export {
|
||||
buildMenu,
|
||||
buildMenus,
|
||||
getParentIds,
|
||||
wouldCreateCycle
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user