index.vue 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <template>
  2. <main-framework :class="`main-theme main-theme--${theme}`" :hide-footer="hideFooter" :layout="layout" :with-tabs="withTabs">
  3. <template #name="{isCollapse}">
  4. <slot name="collapse" v-if="isCollapse">
  5. <span style="margin-left: 8px;">{{name?.[0]}}</span>
  6. </slot>
  7. <slot name="expand" v-else>
  8. <span style="margin-left: 8px;">{{name}}</span>
  9. </slot>
  10. <slot name="name" :is-collapse="isCollapse"></slot>
  11. </template>
  12. <template #nav="{isCollapse}">
  13. <!-- 经过asideNav组件时menu会注入一个_hasChildren属性用于判断是否存在子menu需要渲染-->
  14. <slot name="nav">
  15. <cip-main-nav :nav-menu="dynamicMenu"
  16. :privileges="privileges"
  17. :mode="navMode"
  18. :isCollapse="isCollapse"
  19. :badgeMap="badgeMap"
  20. @triggerGetBadge="consumptionBadgeFn"/>
  21. </slot>
  22. </template>
  23. <template #headerNav>
  24. <!-- 平铺模式的菜单[注:仅显示一层]-->
  25. <cip-main-nav :nav-menu="menu"
  26. v-model:activeMenu="activeMenu"
  27. :privileges="privileges"
  28. mode="horizontal"
  29. :top-menu-only="true"
  30. :badgeMap="badgeMap"
  31. @triggerGetBadge="consumptionBadgeFn"/>
  32. </template>
  33. <template #tabs>
  34. <cip-tabs :menu="menu" ref="tabsRef" :menu-title-map="menuPathMap" :home-view="homeView" v-model:cache="cache"/>
  35. </template>
  36. <template #breadcrumb>
  37. <cip-main-breadcrumb />
  38. </template>
  39. <template #header>
  40. <header-bar>
  41. <template #header-user><slot name="header-user" /></template>
  42. <template #dropdown><slot name="dropdown" /></template>
  43. <template #pre-dropdown><slot name="pre-dropdown" /></template>
  44. </header-bar>
  45. </template>
  46. <cip-router-view :viewKey="viewKey" :cacheList="cache"/>
  47. <template #footer>
  48. <slot name="footer"></slot>
  49. </template>
  50. </main-framework>
  51. </template>
  52. <script>
  53. import { computed, ref, watch, provide, reactive } from 'vue'
  54. import { useCipConfig } from '../hooks/use-cip-config'
  55. import MainFramework from './framework/framework'
  56. import CipMainNav from './cip-main-nav'
  57. import CipMainBreadcrumb from './cip-main-breadcrumb'
  58. import HeaderBar from './header-bar'
  59. import CipTabs from './cip-main-tabs'
  60. import CipRouterView from './cip-router-view'
  61. import { useRoute } from 'vue-router'
  62. import { useBadge, useMenuTitle } from './main-hooks'
  63. import { getFullPathWithoutHash } from './helper'
  64. export default {
  65. name: 'Main',
  66. components: { MainFramework, CipMainNav, HeaderBar, CipMainBreadcrumb, CipTabs, CipRouterView },
  67. props: {
  68. logo: String, // 平台LOGO
  69. platformName: String, // 平台名称
  70. navMenu: Array, // 导航菜单
  71. privileges: Array, // 权限
  72. hideFooter: Boolean, // 是否隐藏footer
  73. theme: {
  74. type: String,
  75. default: 'data-center' // 默认使用数据中台的主题
  76. // validator: (value) => {
  77. // return ['data-center', 'light', 'dark'].includes(value)
  78. // }
  79. }, // 主题
  80. layout: {
  81. type: String,
  82. default: 'left',
  83. validator: (value) => {
  84. return ['left', 'left-2', 'top', 'top-left', 'hide'].includes(value)
  85. }
  86. }, // 布局
  87. withTabs: Boolean, // 是否使用tabs)
  88. homeView: Object, // 首页配置(开启tabs时建议开启)
  89. badgeInterval: Number // 获取badge的时间间隔 单位min(分钟)
  90. },
  91. setup (props) {
  92. const cipConfig = useCipConfig()
  93. const route = useRoute()
  94. const activeMenu = ref([])
  95. const cache = ref([])
  96. const { menuNameMap, menuPathMap } = useMenuTitle()
  97. // 菜单
  98. const menu = computed(() => {
  99. return props.navMenu
  100. })
  101. const dynamicMenu = computed(() => {
  102. if (props.layout !== 'top-left') return menu.value
  103. if (!activeMenu.value) return []
  104. // 明确标记没有children时返回当前menu
  105. if (!activeMenu.value._hasChildren) return [activeMenu.value]
  106. // 传入当前激活路由top menu的children
  107. return activeMenu.value.children
  108. })
  109. const oneMinute = 60 * 1000
  110. const { badgeMap, collectBadgeFn, consumptionBadgeFn } = useBadge(props.badgeInterval * oneMinute)
  111. watch(menu, (val) => {
  112. collectBadgeFn(val, { key: 'name', fnKey: 'getBadge' })
  113. }, { immediate: true })
  114. // 平台名称
  115. const name = computed(() => {
  116. return props.platformName ?? process.env.VUE_APP_PLATFORM_NAME
  117. })
  118. // 菜单模式
  119. const navMode = computed(() => {
  120. return props.layout === 'top' ? 'horizontal' : 'vertical'
  121. })
  122. // 兼容KeepAlivePages组件的运行
  123. const viewKey = computed(() => {
  124. const routeMatch = route.matched
  125. const length = routeMatch.length
  126. const cacheName = length > 1 ? routeMatch[routeMatch.length - 2].name : undefined
  127. if (cacheName?.indexOf('_cache') > -1) {
  128. return cacheName
  129. }
  130. return cipConfig.withQuery === false ? route.path : getFullPathWithoutHash(route.fullPath)
  131. })
  132. const tabsRef = ref()
  133. const closeTab = () => {
  134. const fullPath = getFullPathWithoutHash(route.fullPath)
  135. // eslint-disable-next-line no-unused-expressions
  136. tabsRef.value?.removeTab(fullPath)
  137. }
  138. const handlerPathChange = (fullPath) => {
  139. fullPath = getFullPathWithoutHash(fullPath)
  140. // eslint-disable-next-line no-unused-expressions
  141. tabsRef.value?.handlerPathChange(fullPath)
  142. }
  143. provide('closeTab', closeTab)
  144. provide('pathChange', handlerPathChange)
  145. provide('cip-menu', reactive({
  146. menuNameMap,
  147. navMenu: menu
  148. }))
  149. const setChangeSign = () => {
  150. // const fullPath = getFullPathWithoutHash(route.fullPath)
  151. }
  152. provide('setChangeSign', setChangeSign)
  153. return {
  154. cache,
  155. menu,
  156. name,
  157. menuNameMap,
  158. menuPathMap,
  159. navMode,
  160. dynamicMenu,
  161. activeMenu,
  162. viewKey,
  163. badgeMap,
  164. consumptionBadgeFn,
  165. tabsRef
  166. }
  167. }
  168. }
  169. </script>
  170. <style lang="less">
  171. @import './theme';
  172. </style>