useTabbar.js 2.42 KB
import { computed, reactive, readonly } from 'vue';
import { getTabbarConfigAPI } from './tabbar.api';
import {
  getDefaultTabbarItem,
  getHomeOnlyTabbarItems,
  normalizeTabbarKey,
  normalizeTabbarPayload,
  resolveTabbarTargetUrl,
} from './tabbar.utils';

const state = reactive({
  tabItems: getHomeOnlyTabbarItems(),
  loaded: false,
  loading: false,
  loadMode: 'api',
});

let tabbarRequestPromise = null;

const applyFallbackItems = () => {
  state.tabItems = getHomeOnlyTabbarItems();
};

const resolveLoadMode = (options = {}) => (options.useMock ? 'mock' : 'api');

export const fetchTabbarConfig = async (force = false, options = {}) => {
  const loadMode = resolveLoadMode(options);

  if (!force && state.loaded && state.loadMode === loadMode) {
    return state.tabItems;
  }

  if (state.loading && tabbarRequestPromise) {
    return tabbarRequestPromise;
  }

  state.loading = true;

  tabbarRequestPromise = (async () => {
    try {
      if (loadMode === 'mock') {
        state.tabItems = normalizeTabbarPayload(options.mockData);
        state.loadMode = loadMode;
        return state.tabItems;
      }

      const response = await getTabbarConfigAPI();

      if (response?.code === 1) {
        state.tabItems = normalizeTabbarPayload(response?.data);
      } else {
        applyFallbackItems();
      }

      state.loadMode = loadMode;
    } catch (error) {
      console.error('获取底部导航配置失败:', error);
      applyFallbackItems();
      state.loadMode = loadMode;
    } finally {
      state.loaded = true;
      state.loading = false;
      tabbarRequestPromise = null;
    }

    return state.tabItems;
  })();

  return tabbarRequestPromise;
};

export const ensureTabbarLoaded = (options = {}) => {
  const loadMode = resolveLoadMode(options);

  if (state.loaded && state.loadMode === loadMode) {
    return Promise.resolve(state.tabItems);
  }

  return fetchTabbarConfig(false, options);
};

export const useJlsTabbar = () => {
  const visibleTabItems = computed(() => state.tabItems.filter((item) => item.visible !== false));

  const getTabItem = (key) => {
    const normalizedKey = normalizeTabbarKey(key);
    return state.tabItems.find((item) => item.key === normalizedKey) || getDefaultTabbarItem(normalizedKey);
  };

  return {
    state: readonly(state),
    visibleTabItems,
    getTabItem,
    ensureLoaded: ensureTabbarLoaded,
    fetchTabbarConfig,
    resolveTargetUrl: resolveTabbarTargetUrl,
  };
};