menu.js 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import { reactive, computed } from 'vue'
  2. import { fetchCurrentMenu } from '@/api/menu'
  3. const state = reactive({
  4. loaded: false,
  5. loading: false,
  6. error: null,
  7. topMenus: [],
  8. activeId: null,
  9. })
  10. function bySort(a, b) {
  11. return (a?.sort ?? 0) - (b?.sort ?? 0)
  12. }
  13. function sortTree(list) {
  14. if (!Array.isArray(list)) return []
  15. return list
  16. .slice()
  17. .sort(bySort)
  18. .map((m) => ({ ...m, children: Array.isArray(m.children) ? sortTree(m.children) : [] }))
  19. }
  20. export function useMenu() {
  21. async function load(force = false) {
  22. if (state.loading) return
  23. if (state.loaded && !force) return
  24. state.loading = true
  25. state.error = null
  26. try {
  27. const data = await fetchCurrentMenu()
  28. const list = Array.isArray(data) ? data : []
  29. state.topMenus = sortTree(list)
  30. state.loaded = true
  31. if (!state.topMenus.some((m) => m.id === state.activeId)) {
  32. state.activeId = state.topMenus[0]?.id ?? null
  33. }
  34. } catch (err) {
  35. state.error = err
  36. } finally {
  37. state.loading = false
  38. }
  39. }
  40. function setActive(id) {
  41. if (state.activeId === id) return
  42. state.activeId = id
  43. }
  44. const activeTopMenu = computed(
  45. () => state.topMenus.find((m) => m.id === state.activeId) ?? null,
  46. )
  47. const subMenus = computed(() => {
  48. const cur = activeTopMenu.value
  49. return cur && Array.isArray(cur.children) ? cur.children : []
  50. })
  51. return { state, load, setActive, activeTopMenu, subMenus }
  52. }