import { pages, groups, subPackages } from '@/pages.json'
type Group = {
id : string,
name : string,
children : (Group | null)[] | null
}
type PageGroup = {
id : string,
name : string,
index : number
}
type Page = {
path : string,
style : UTSJSONObject,
group ?: string | null,
}
export type MenuItem = {
id : string,
name : string,
index : number,
path : string,
style : UTSJSONObject,
group ?: string | null,
items : MenuItem[]
}
subPackages.forEach(subPackage => {
(subPackage.pages as UTSJSONObject[]).forEach(page => {
(pages as Page[]).push({
path: `${subPackage.root}/${page.path}`,
style: page.style as UTSJSONObject,
group: page.group as string | null
})
})
})
export function generateMenu(tabBarType : string) : MenuItem[] {
let res : MenuItem[] = []
const tabBarPages = JSON.parse<Page[]>(JSON.stringify(pages))!.filter((page : Page) : boolean => page.path.startsWith(tabBarType) && hasPageGroup(page.group))
const groupTree = JSON.parse<(Group | null)[]>(JSON.stringify(groups))
let currentMenu : MenuItem | null = null
tabBarPages.forEach(page => {
let menuItemArr : MenuItem[] = res
const groupIndexList = page.group!.split(',').map((index : string) : number => parseInt(index))
let currentGroups : (Group | null)[] | null = groupTree
const pageGroups : PageGroup[] = []
groupIndexList.forEach((groupIndex, index) => {
// 跳过第一层 component API CSS
if (index > 0) {
pageGroups.push({ id: currentGroups![groupIndex]!.id, name: currentGroups![groupIndex]!.name, index: groupIndex } as PageGroup)
}
currentGroups = currentGroups![groupIndex]!.children
})
const lastGroup = pageGroups[pageGroups.length - 1]
let hasPageGroup = false
if (
(
page.path.endsWith(camelToDash(lastGroup.name)) ||
page.path.endsWith(camelToDash(lastGroup.name.replace('uni.', '')))
) &&
pageGroups.length > 1
) {
hasPageGroup = true
pageGroups.pop()
}
const groupLength = pageGroups.length
pageGroups.forEach((group, groupIndex) => {
const { index, id, name } = group
const validIndex = index
fillMenuArrayWithEmptyMenuItem(menuItemArr, validIndex)
if (menuItemArr[validIndex].name == 'empty') {
menuItemArr[validIndex] = {
id: id.split('.').slice(-1)[0],
name,
index: validIndex,
path: '',
style: {},
group: '',
items: [] as MenuItem[],
} as MenuItem
}
currentMenu = menuItemArr[validIndex]
if (groupIndex < groupLength - 1) {
menuItemArr = menuItemArr[validIndex].items
}
})
const pageMenuItem : MenuItem = {
id: page.path,
name: page.style["navigationBarTitleText"] as string,
index: lastGroup.index,
path: page.path,
style: page.style,
group: page.group,
items: [] as MenuItem[],
}
if (hasPageGroup && currentMenu != null) {
const pageIndex = lastGroup.index
fillMenuArrayWithEmptyMenuItem(currentMenu!.items, pageIndex)
if (currentMenu!.items[pageIndex].name == 'empty') {
currentMenu!.items[pageIndex] = pageMenuItem
} else {
currentMenu!.items.push(pageMenuItem)
}
} else {
currentMenu!.items.push(pageMenuItem)
}
})
return removeEmptyItem(res)
}
function hasPageGroup(value ?: string | null) : boolean {
// #ifdef APP-ANDROID
return value !== null
// #endif
// #ifndef APP-ANDROID
return !!value
// #endif
}
function camelToDash(camelStr: string): string {
// 将首字母转换为小写, 兼容类似 Base64 场景
camelStr = camelStr.charAt(0).toLowerCase() + camelStr.slice(1);
return camelStr.replace(/([A-Z])/g, '-$1').toLowerCase()
}
function fillMenuArrayWithEmptyMenuItem(arr : MenuItem[], index : number) : void {
const len = arr.length
for (let i = 0; i <= index - (len - 1); i++) {
arr.push({
id: '',
name: 'empty',
index: i,
path: '',
style: {},
group: '',
items: [] as MenuItem[],
} as MenuItem)
}
}
function removeEmptyItem(arr : MenuItem[]) : MenuItem[] {
const res = arr.filter((item : MenuItem) : boolean => item.name !== 'empty')
res.forEach(menuItem => {
addSetTabBarPage(menuItem)
// #ifdef APP-ANDROID
menuItem.items = removeEmptyItem(menuItem.items)
// #endif
// #ifndef APP-ANDROID
menuItem!.items = removeEmptyItem(menuItem!.items)
// #endif
})
return res
}
function addSetTabBarPage(menuItem : MenuItem) {
const { id, name } = menuItem
if (id == 'page' && name == '页面和路由') {
menuItem.items.push({
id: 'set-tab-bar',
name: '设置 TabBar',
index: 0,
path: 'set-tab-bar',
style: {
navigationBarTitleText: '设置 TabBar'
},
group: null,
items: []
} as MenuItem)
}
}