generateMenu.uts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import { pages, groups, subPackages } from '@/pages.json'
  2. type Group = {
  3. id : string,
  4. name : string,
  5. children : (Group | null)[] | null
  6. }
  7. type PageGroup = {
  8. id : string,
  9. name : string,
  10. index : number
  11. }
  12. type Page = {
  13. path : string,
  14. style : UTSJSONObject,
  15. group ?: string | null,
  16. }
  17. export type MenuItem = {
  18. id : string,
  19. name : string,
  20. index : number,
  21. path : string,
  22. style : UTSJSONObject,
  23. group ?: string | null,
  24. items : MenuItem[]
  25. }
  26. subPackages.forEach(subPackage => {
  27. (subPackage.pages as UTSJSONObject[]).forEach(page => {
  28. (pages as Page[]).push({
  29. path: `${subPackage.root}/${page.path}`,
  30. style: page.style as UTSJSONObject,
  31. group: page.group as string | null
  32. })
  33. })
  34. })
  35. export function generateMenu(tabBarType : string) : MenuItem[] {
  36. let res : MenuItem[] = []
  37. const tabBarPages = JSON.parse<Page[]>(JSON.stringify(pages))!.filter((page : Page) : boolean => page.path.startsWith(tabBarType) && hasPageGroup(page.group))
  38. const groupTree = JSON.parse<(Group | null)[]>(JSON.stringify(groups))
  39. let currentMenu : MenuItem | null = null
  40. tabBarPages.forEach(page => {
  41. let menuItemArr : MenuItem[] = res
  42. const groupIndexList = page.group!.split(',').map((index : string) : number => parseInt(index))
  43. let currentGroups : (Group | null)[] | null = groupTree
  44. const pageGroups : PageGroup[] = []
  45. groupIndexList.forEach((groupIndex, index) => {
  46. // 跳过第一层 component API CSS
  47. if (index > 0) {
  48. pageGroups.push({ id: currentGroups![groupIndex]!.id, name: currentGroups![groupIndex]!.name, index: groupIndex } as PageGroup)
  49. }
  50. currentGroups = currentGroups![groupIndex]!.children
  51. })
  52. const lastGroup = pageGroups[pageGroups.length - 1]
  53. let hasPageGroup = false
  54. if (
  55. (
  56. page.path.endsWith(camelToDash(lastGroup.name)) ||
  57. page.path.endsWith(camelToDash(lastGroup.name.replace('uni.', '')))
  58. ) &&
  59. pageGroups.length > 1
  60. ) {
  61. hasPageGroup = true
  62. pageGroups.pop()
  63. }
  64. const groupLength = pageGroups.length
  65. pageGroups.forEach((group, groupIndex) => {
  66. const { index, id, name } = group
  67. const validIndex = index
  68. fillMenuArrayWithEmptyMenuItem(menuItemArr, validIndex)
  69. if (menuItemArr[validIndex].name == 'empty') {
  70. menuItemArr[validIndex] = {
  71. id: id.split('.').slice(-1)[0],
  72. name,
  73. index: validIndex,
  74. path: '',
  75. style: {},
  76. group: '',
  77. items: [] as MenuItem[],
  78. } as MenuItem
  79. }
  80. currentMenu = menuItemArr[validIndex]
  81. if (groupIndex < groupLength - 1) {
  82. menuItemArr = menuItemArr[validIndex].items
  83. }
  84. })
  85. const pageMenuItem : MenuItem = {
  86. id: page.path,
  87. name: page.style["navigationBarTitleText"] as string,
  88. index: lastGroup.index,
  89. path: page.path,
  90. style: page.style,
  91. group: page.group,
  92. items: [] as MenuItem[],
  93. }
  94. if (hasPageGroup && currentMenu != null) {
  95. const pageIndex = lastGroup.index
  96. fillMenuArrayWithEmptyMenuItem(currentMenu!.items, pageIndex)
  97. if (currentMenu!.items[pageIndex].name == 'empty') {
  98. currentMenu!.items[pageIndex] = pageMenuItem
  99. } else {
  100. currentMenu!.items.push(pageMenuItem)
  101. }
  102. } else {
  103. currentMenu!.items.push(pageMenuItem)
  104. }
  105. })
  106. return removeEmptyItem(res)
  107. }
  108. function hasPageGroup(value ?: string | null) : boolean {
  109. // #ifdef APP-ANDROID
  110. return value !== null
  111. // #endif
  112. // #ifndef APP-ANDROID
  113. return !!value
  114. // #endif
  115. }
  116. function camelToDash(camelStr: string): string {
  117. // 将首字母转换为小写, 兼容类似 Base64 场景
  118. camelStr = camelStr.charAt(0).toLowerCase() + camelStr.slice(1);
  119. return camelStr.replace(/([A-Z])/g, '-$1').toLowerCase()
  120. }
  121. function fillMenuArrayWithEmptyMenuItem(arr : MenuItem[], index : number) : void {
  122. const len = arr.length
  123. for (let i = 0; i <= index - (len - 1); i++) {
  124. arr.push({
  125. id: '',
  126. name: 'empty',
  127. index: i,
  128. path: '',
  129. style: {},
  130. group: '',
  131. items: [] as MenuItem[],
  132. } as MenuItem)
  133. }
  134. }
  135. function removeEmptyItem(arr : MenuItem[]) : MenuItem[] {
  136. const res = arr.filter((item : MenuItem) : boolean => item.name !== 'empty')
  137. res.forEach(menuItem => {
  138. addSetTabBarPage(menuItem)
  139. // #ifdef APP-ANDROID
  140. menuItem.items = removeEmptyItem(menuItem.items)
  141. // #endif
  142. // #ifndef APP-ANDROID
  143. menuItem!.items = removeEmptyItem(menuItem!.items)
  144. // #endif
  145. })
  146. return res
  147. }
  148. function addSetTabBarPage(menuItem : MenuItem) {
  149. const { id, name } = menuItem
  150. if (id == 'page' && name == '页面和路由') {
  151. menuItem.items.push({
  152. id: 'set-tab-bar',
  153. name: '设置 TabBar',
  154. index: 0,
  155. path: 'set-tab-bar',
  156. style: {
  157. navigationBarTitleText: '设置 TabBar'
  158. },
  159. group: null,
  160. items: []
  161. } as MenuItem)
  162. }
  163. }