init
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
import type { useAppStore } from '~/stores/app.ts'
|
||||
|
||||
export const LayoutMenuKey = Symbol('LayoutMenu')
|
||||
export function useLayoutMenuProvide(layoutMenu: ReturnType<typeof useLayoutMenu>, appStore: ReturnType<typeof useAppStore>) {
|
||||
provide(LayoutMenuKey, { layoutMenu, appStore })
|
||||
}
|
||||
|
||||
export function useLayoutMenuInject() {
|
||||
return inject(LayoutMenuKey, {} as any)
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<script setup lang="ts">
|
||||
import type { VNodeChild } from 'vue'
|
||||
import { isFunction } from '@v-c/utils'
|
||||
import { useLayoutState } from '~/layouts/basic-layout/context'
|
||||
import { useLayoutMenuInject } from './context.ts'
|
||||
|
||||
defineProps<{
|
||||
title?: string
|
||||
}>()
|
||||
const slots = defineSlots<{
|
||||
default: (props: any) => any
|
||||
title?: (props: any) => any
|
||||
content?: (props: any) => any
|
||||
extraContent?: (props: any) => any
|
||||
extra?: (props: any) => any
|
||||
footer?: (props: any) => any
|
||||
}>()
|
||||
|
||||
const { layoutMenu: layoutMenuStore, appStore } = useLayoutMenuInject()
|
||||
const { layoutSetting } = (storeToRefs as any)(appStore)
|
||||
const { menuDataMap } = (storeToRefs as any)(layoutMenuStore)
|
||||
const route = useRoute()
|
||||
function getCurrentItem() {
|
||||
const key: string = route.meta?.originPath ?? route.path
|
||||
if (key && menuDataMap.value.has(key))
|
||||
return menuDataMap.value.get(key)
|
||||
return {} as any
|
||||
}
|
||||
const currentItem = shallowRef(getCurrentItem())
|
||||
onBeforeMount(() => {
|
||||
currentItem.value = getCurrentItem()
|
||||
})
|
||||
|
||||
let timer: ReturnType<typeof setTimeout> | undefined
|
||||
watch(() => route.path, () => {
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
timer = undefined
|
||||
}
|
||||
timer = setTimeout(() => {
|
||||
currentItem.value = getCurrentItem()
|
||||
}, 300)
|
||||
})
|
||||
|
||||
// const { contentWidth } = useLayoutState()
|
||||
|
||||
const layoutState = useLayoutState()
|
||||
// ✅ 修复:使用 computed 属性安全访问,提供默认值
|
||||
const contentWidth = computed(() => {
|
||||
return layoutState?.contentWidth || 'Fluid' // 提供安全默认值
|
||||
})
|
||||
|
||||
const contentCls = computed(() => {
|
||||
const cls: string[] = [
|
||||
'flex flex-col flex-1',
|
||||
]
|
||||
// ✅ 修复:使用 contentWidth.value
|
||||
if (contentWidth.value === 'Fluid')
|
||||
cls.push('w-full')
|
||||
else if (contentWidth.value === 'Fixed')
|
||||
cls.push(...['max-w-1200px w-1200px', 'mx-auto'])
|
||||
|
||||
return cls
|
||||
})
|
||||
|
||||
// const contentCls = computed(() => {
|
||||
// const cls: string[] = [
|
||||
// 'flex flex-col flex-1',
|
||||
// ]
|
||||
// if (contentWidth.value === 'Fluid')
|
||||
// cls.push('w-full')
|
||||
|
||||
// else if (contentWidth.value === 'Fixed')
|
||||
// cls.push(...['max-w-1200px w-1200px', 'mx-auto'])
|
||||
|
||||
// return cls
|
||||
// })
|
||||
function renderTitle(title: VNodeChild | (() => VNodeChild)) {
|
||||
if (isFunction(title))
|
||||
return title()
|
||||
|
||||
return title
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="ant-pro-page-container">
|
||||
<div class="bg-[var(--bg-color)]" :class="layoutSetting.multiTab ? 'pb-16px' : 'py-16px'" px-24px mb-24px mx--24px mt--24px>
|
||||
<a-breadcrumb v-if="!currentItem.hideInBreadcrumb">
|
||||
<template v-if="currentItem.matched?.length">
|
||||
<a-breadcrumb-item v-for="item in currentItem.matched" :key="item.path">
|
||||
{{ renderTitle(item.title) }}
|
||||
</a-breadcrumb-item>
|
||||
</template>
|
||||
<a-breadcrumb-item>
|
||||
{{ renderTitle(currentItem.title) }}
|
||||
</a-breadcrumb-item>
|
||||
</a-breadcrumb>
|
||||
<div flex mt-8px justify-between>
|
||||
<div flex items-center my-4px of-hidden>
|
||||
<slot name="title">
|
||||
<span text-20px line-height-32px mr-12px mb-0 truncate font-600>{{ renderTitle(title ?? currentItem.title) }}</span>
|
||||
</slot>
|
||||
</div>
|
||||
<div>
|
||||
<slot name="extra" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="slots.content || slots.extraContent" pt-12px>
|
||||
<div flex w-full>
|
||||
<div flex-auto>
|
||||
<slot name="content" />
|
||||
</div>
|
||||
<div flex-shrink-0>
|
||||
<slot name="extraContent" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
<div :class="contentCls">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user