menus.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import { computed, ref, Ref, toRaw } from "vue";
  2. import { uiType } from "@/hook/useGraphic";
  3. type MenuRaw = {
  4. key: any;
  5. children?: MenuRaw[];
  6. };
  7. type GenerateResult<R, E = {}> = Array<
  8. R & { children: GenerateResult<R, E> } & E
  9. >;
  10. export const generateByMenus = <T extends MenuRaw, R>(
  11. generateFn: (men: T) => R,
  12. mainMenus: T[]
  13. ): GenerateResult<R> => {
  14. return mainMenus.map((mainMenu) => ({
  15. ...generateFn(mainMenu),
  16. children: mainMenu.children
  17. ? generateByMenus(generateFn, mainMenu.children)
  18. : [],
  19. }));
  20. };
  21. export const findMenuByAttr = <
  22. T extends MenuRaw,
  23. K extends keyof T,
  24. V extends T[K]
  25. >(
  26. value: V,
  27. attr: K,
  28. mainMenus: T[]
  29. ) => {
  30. for (const mainMenu of mainMenus) {
  31. if (toRaw(mainMenu[attr]) === toRaw(value)) {
  32. return mainMenu;
  33. } else if (mainMenu.children) {
  34. const childMainMenu = findMenuByAttr(
  35. value,
  36. attr as any,
  37. mainMenu.children
  38. );
  39. if (childMainMenu) {
  40. return childMainMenu;
  41. }
  42. }
  43. }
  44. };
  45. export type GenerateMinMenusResult<TK, R> = {
  46. menus: GenerateResult<R, { onClick: () => void }>;
  47. child: Ref<TK>;
  48. activeMenuKey: Ref<any>;
  49. };
  50. export const generateMixMenus = <T extends MenuRaw, K extends keyof T, R>(
  51. childKey: K,
  52. generateFn: (men: T) => R,
  53. mainMenus: T[],
  54. itemAction: (men: T) => void,
  55. getActiveItem: () => any
  56. ): GenerateMinMenusResult<T[K], R> => {
  57. const child = ref();
  58. const menus = generateByMenus(
  59. (menu) => ({
  60. ...generateFn(menu),
  61. onClick: () => {
  62. if (menu[childKey]) {
  63. if (toRaw(menu[childKey]) !== toRaw(child.value)) {
  64. child.value = menu[childKey];
  65. return;
  66. }
  67. } else {
  68. itemAction(menu);
  69. }
  70. child.value = null;
  71. },
  72. }),
  73. mainMenus
  74. );
  75. const activeMenuKey = computed(() =>
  76. child.value
  77. ? findMenuByAttr(child.value, childKey, mainMenus)?.key
  78. : getActiveItem()
  79. );
  80. return {
  81. child,
  82. menus,
  83. activeMenuKey,
  84. };
  85. };