123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- <template>
- <main-framework
- :class="`main-theme main-theme--${theme}`"
- :hide-footer="hideFooter"
- :hide-aside-switch="hideAsideSwitch"
- :layout="usingLayout"
- :with-tabs="withTabs"
- :hide-aside="dynamicMenu.length === 0"
- >
- <template #name="{isCollapse}">
- <slot name="collapse" v-if="isCollapse">
- <span style="margin-left: 8px;">{{name?.[0]}}</span>
- </slot>
- <slot name="expand" v-else>
- <span style="margin-left: 8px;">{{name}}</span>
- </slot>
- <slot name="name" :is-collapse="isCollapse"></slot>
- </template>
- <template #nav="{isCollapse}">
- <slot name="nav">
- <cip-main-nav :nav-menu="dynamicMenu"
- :theme="theme"
- :icon-depth="iconDepth"
- :mode="navMode"
- :isCollapse="isCollapse"
- :ellipsis="true"
- :badgeMap="badgeMap"
- @triggerGetBadge="consumptionBadgeFn"/>
- </slot>
- </template>
- <template #headerNav>
- <!-- 平铺模式的菜单[注:仅显示一层]-->
- <cip-main-nav :nav-menu="menu"
- v-model:activeMenu="activeMenu"
- :icon-depth="iconDepth"
- mode="horizontal"
- :ellipsis="true"
- :top-menu-only="true"
- :badgeMap="badgeMap"
- @triggerGetBadge="consumptionBadgeFn"/>
- </template>
- <template #tabs>
- <cip-tabs
- ref="tabsRef"
- :menu="menu"
- :menu-title-map="menuPathMap"
- :home-view="homeView"
- :with-tabs="usingTabs"
- v-model:cache="cache"
- />
- </template>
- <template #breadcrumb>
- <cip-main-breadcrumb />
- </template>
- <template #header>
- <header-bar>
- <template #header-plugin><slot name="header-plugin" /></template>
- <template #header-user><slot name="header-user" /></template>
- <template v-if="$slots.dropdown" #dropdown><slot name="dropdown" /></template>
- <template v-if="$slots['pre-dropdown']" #pre-dropdown><slot name="pre-dropdown" /></template>
- </header-bar>
- </template>
- <cip-router-view :viewKey="viewKey" :cacheList="cache"/>
- <template #footer>
- <slot name="footer"></slot>
- </template>
- </main-framework>
- </template>
- <script>
- import { computed, ref, watch, provide, reactive, onUnmounted } from 'vue'
- import { useCipConfig } from '../hooks/use-cip-config'
- import MainFramework from './framework/framework'
- import CipMainNav from './cip-main-nav'
- import CipMainBreadcrumb from './cip-main-breadcrumb'
- import HeaderBar from './header-bar'
- import CipTabs from './cip-main-tabs'
- import CipRouterView from './cip-router-view'
- import { useRoute } from 'vue-router'
- import { useBadge, useMenuTitle } from './main-hooks'
- import { getFullPathWithoutHash } from './helper'
- import { isSubApp } from '../cip-subapp-container/micro-app/util'
- export default {
- name: 'Main',
- components: { MainFramework, CipMainNav, HeaderBar, CipMainBreadcrumb, CipTabs, CipRouterView },
- props: {
- logo: String, // 平台LOGO
- platformName: String, // 平台名称
- iconDepth: Number, // 菜单的icon展示的最大层级
- navMenu: Array, // 导航菜单
- // privileges: Array, // 权限
- hideFooter: Boolean, // 是否隐藏footer
- hideAsideSwitch: Boolean, // 是否隐藏手风琴折叠开关
- theme: {
- type: String,
- default: 'standard' // 默认使用数据中台的主题
- // validator: (value) => {
- // return ['data-center', 'light', 'dark'].includes(value)
- // }
- }, // 主题
- layout: {
- type: String,
- default: 'left-2',
- validator: (value) => {
- return ['left', 'left-2', 'top', 'top-left', 'hide'].includes(value)
- }
- }, // 布局
- withTabs: Boolean, // 是否使用tabs)
- homeView: Object, // 首页配置(开启tabs时建议开启)
- badgeInterval: Number, // 获取badge的时间间隔 单位min(分钟)
- noViewKey: { type: Boolean, default: undefined }
- },
- setup (props) {
- const cipConfig = useCipConfig()
- const route = useRoute()
- const activeMenu = ref([])
- const cache = ref([])
- const { menuNameMap, menuPathMap } = useMenuTitle()
- // 菜单
- const menu = computed(() => {
- return props.navMenu
- })
- const layoutHide = ref(false)
- const setFrameHide = (val) => {
- layoutHide.value = val
- }
- onUnmounted(() => {
- console.log('Main Unmounted')
- })
- const usingLayout = computed(() => {
- return layoutHide.value ? 'hide' : props.layout
- })
- const usingTabs = computed(() => {
- if (!props.withTabs) return false
- return !isSubApp(route.name)
- })
- const dynamicMenu = computed(() => {
- if (usingLayout.value !== 'top-left') return menu.value
- if (!activeMenu.value || activeMenu.value.length === 0) return []
- // 明确标记没有children时返回当前menu
- if ((activeMenu.value.children || []).length === 0) return [activeMenu.value]
- // 传入当前激活路由top menu的children
- return activeMenu.value.children
- })
- const oneMinute = 60 * 1000
- const { badgeMap, collectBadgeFn, consumptionBadgeFn } = useBadge(props.badgeInterval * oneMinute)
- watch(menu, (val) => {
- collectBadgeFn(val, { key: 'name', fnKey: 'getBadge' })
- }, { immediate: true })
- // 平台名称
- const name = computed(() => {
- return props.platformName ?? process.env.VUE_APP_PLATFORM_NAME
- })
- // 菜单模式
- const navMode = computed(() => {
- return props.layout === 'top' ? 'horizontal' : 'vertical'
- })
- // 兼容KeepAlivePages组件的运行
- const viewKey = computed(() => {
- if (props.noViewKey) return 'viewKey'
- if (isSubApp(route.name)) return 'SubApp'
- const routeMatch = route.matched
- const length = routeMatch.length
- const cacheName = length > 1 ? routeMatch[routeMatch.length - 2].name : undefined
- if (cacheName?.indexOf('_cache') > -1) {
- return cacheName
- }
- return cipConfig.withQuery === false ? route.path : getFullPathWithoutHash(route.fullPath)
- })
- const tabsRef = ref()
- const closeTab = () => {
- const fullPath = getFullPathWithoutHash(route.fullPath)
- // eslint-disable-next-line no-unused-expressions
- tabsRef.value?.removeTab(fullPath)
- }
- const handlerPathChange = (fullPath) => {
- fullPath = getFullPathWithoutHash(fullPath)
- // eslint-disable-next-line no-unused-expressions
- tabsRef.value?.handlerPathChange(fullPath)
- }
- provide('closeTab', closeTab)
- provide('pathChange', handlerPathChange)
- provide('cip-menu', reactive({
- menuNameMap,
- navMenu: menu
- }))
- provide('setFrameHide', setFrameHide)
- const setChangeSign = () => {
- // const fullPath = getFullPathWithoutHash(route.fullPath)
- }
- provide('setChangeSign', setChangeSign)
- return {
- cache,
- menu,
- name,
- menuNameMap,
- menuPathMap,
- navMode,
- dynamicMenu,
- activeMenu,
- viewKey,
- badgeMap,
- consumptionBadgeFn,
- tabsRef,
- usingLayout,
- usingTabs,
- closeTab
- }
- }
- }
- </script>
- <style lang="less">
- @import './theme';
- </style>
|