You need to sign in or sign up before continuing.
tabbar.js 6.2 KB
import { buildWebviewPreviewUrl } from '@/utils/webview'

const TABBAR_KEY_ALIAS_MAP = {
  message: 'news',
  application: 'list',
  mine: 'user',
}

const KNOWN_TABBAR_ITEM_MAP = {
  home: {
    key: 'home',
    title: '首页',
    class: 'fa-home',
    visible: true,
    page_url: '/pages/index/index',
    webview_url: '',
    webview_title: '首页',
  },
  news: {
    key: 'news',
    title: '资讯',
    class: 'fa-newspaper-o',
    visible: true,
    page_url: '',
    webview_url: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=news_list',
    webview_title: '资讯',
  },
  list: {
    key: 'list',
    title: '应用',
    class: 'fa-th-large',
    visible: true,
    page_url: '',
    webview_url: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=futian_list',
    webview_title: '应用',
  },
  user: {
    key: 'user',
    title: '我的',
    class: 'fa-user',
    visible: true,
    page_url: '',
    webview_url: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=futian_list',
    webview_title: '我的',
  },
}

export const TABBAR_ORDER = ['home', 'news', 'list', 'user']
const DEFAULT_ICON_CLASS = 'fa-circle-o'
const DEFAULT_TABBAR_ACTIVE_COLOR = '#a67939'

const normalizeVisibleValue = (rawValue, fallbackValue = true) => {
  if (typeof rawValue === 'boolean') {
    return rawValue
  }

  if (rawValue === 1 || rawValue === '1') {
    return true
  }

  if (rawValue === 0 || rawValue === '0') {
    return false
  }

  return fallbackValue
}

export const normalizeTabbarKey = (key) => {
  const normalizedKey = String(key || '').trim()
  return TABBAR_KEY_ALIAS_MAP[normalizedKey] || normalizedKey
}

const createFallbackTabbarItem = (key, title = '') => {
  const normalizedKey = normalizeTabbarKey(key)

  return {
    key: normalizedKey,
    title: title || '栏目',
    class: DEFAULT_ICON_CLASS,
    visible: true,
    page_url: normalizedKey === 'home' ? '/pages/index/index' : '',
    webview_url: '',
    webview_title: title || '栏目',
  }
}

export const getDefaultTabbarItem = (key) => {
  const normalizedKey = normalizeTabbarKey(key)
  const fallbackItem = KNOWN_TABBAR_ITEM_MAP[normalizedKey] || createFallbackTabbarItem(normalizedKey)

  return {
    ...fallbackItem,
  }
}

export const getDefaultTabbarItems = () => (
  TABBAR_ORDER
    .map((key) => getDefaultTabbarItem(key))
    .filter(Boolean)
)

export const getHomeOnlyTabbarItems = () => [getDefaultTabbarItem('home')]

export const getDefaultTabbarActiveColor = () => DEFAULT_TABBAR_ACTIVE_COLOR

export const normalizeTabbarColor = (rawPayload = null) => {
  const rawColor = rawPayload?.color

  if (typeof rawColor !== 'string') {
    return DEFAULT_TABBAR_ACTIVE_COLOR
  }

  const normalizedColor = rawColor.trim()
  return normalizedColor || DEFAULT_TABBAR_ACTIVE_COLOR
}

const buildTabbarPageUrl = (key, webviewUrl, webviewTitle, rawPageUrl = '') => {
  if (key === 'home') {
    return rawPageUrl || '/pages/index/index'
  }

  if (!webviewUrl) {
    return ''
  }

  return buildWebviewPreviewUrl(webviewUrl, webviewTitle)
}

export const normalizeTabbarItem = (rawItem = {}) => {
  const normalizedKey = normalizeTabbarKey(rawItem.key || rawItem.name)
  const fallbackItem = getDefaultTabbarItem(normalizedKey || rawItem.title)
  const title = String(rawItem.title || fallbackItem.title || '栏目')
  const webviewUrl = String(
    rawItem.webview_url
      || rawItem.link_url
      || rawItem.link
      || rawItem.url
      || fallbackItem.webview_url
      || '',
  )
  const webviewTitle = String(
    rawItem.webview_title
      || rawItem.link_title
      || rawItem.title
      || fallbackItem.webview_title
      || title,
  )

  return {
    ...fallbackItem,
    ...rawItem,
    key: fallbackItem.key,
    title,
    class: String(rawItem.class || rawItem.icon_class || rawItem.icon || fallbackItem.class || DEFAULT_ICON_CLASS),
    webview_url: webviewUrl,
    webview_title: webviewTitle,
    page_url: buildTabbarPageUrl(
      fallbackItem.key,
      webviewUrl,
      webviewTitle,
      String(rawItem.page_url || fallbackItem.page_url || ''),
    ),
    visible: normalizeVisibleValue(
      rawItem.visible ?? rawItem.is_show ?? rawItem.show,
      fallbackItem.visible,
    ),
  }
}

const sortTabbarObjectEntries = (entries = []) => {
  const orderMap = TABBAR_ORDER.reduce((map, key, index) => {
    map[key] = index
    return map
  }, {})

  return entries
    .map((entry, index) => ({ entry, index }))
    .sort((left, right) => {
      const leftKey = normalizeTabbarKey(left.entry[0])
      const rightKey = normalizeTabbarKey(right.entry[0])
      const leftOrder = orderMap[leftKey]
      const rightOrder = orderMap[rightKey]
      const leftKnown = Number.isInteger(leftOrder)
      const rightKnown = Number.isInteger(rightOrder)

      if (leftKnown && rightKnown) {
        return leftOrder - rightOrder
      }

      if (leftKnown) {
        return -1
      }

      if (rightKnown) {
        return 1
      }

      return left.index - right.index
    })
    .map(({ entry }) => entry)
}

const normalizeTabbarObjectItems = (rawMap = {}) => {
  const objectEntries = Object.entries(rawMap).filter(([, value]) => (
    value && typeof value === 'object' && !Array.isArray(value)
  ))

  if (!objectEntries.length) {
    return []
  }

  return sortTabbarObjectEntries(objectEntries)
    .map(([key, value]) => normalizeTabbarItem({
      ...value,
      key,
    }))
    .filter(Boolean)
}

export const normalizeTabbarItems = (rawItems = []) => {
  if (!Array.isArray(rawItems) || !rawItems.length) {
    return getHomeOnlyTabbarItems()
  }

  const normalizedItems = rawItems
    .map((item) => normalizeTabbarItem(item))
    .filter(Boolean)

  return normalizedItems.length ? normalizedItems : getHomeOnlyTabbarItems()
}

export const normalizeTabbarPayload = (rawPayload = null) => {
  if (Array.isArray(rawPayload)) {
    return normalizeTabbarItems(rawPayload)
  }

  const arrayPayload = rawPayload?.tab_items || rawPayload?.tabs || rawPayload?.menus
  if (Array.isArray(arrayPayload)) {
    return normalizeTabbarItems(arrayPayload)
  }

  const objectPayload = rawPayload?.tab_items || rawPayload?.tabs || rawPayload?.menus || rawPayload
  const normalizedItems = normalizeTabbarObjectItems(objectPayload)

  return normalizedItems.length ? normalizedItems : getHomeOnlyTabbarItems()
}