middle-admin-ant/src/layouts/PageLayout.vue

151 lines
5.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="page-layout">
<page-header ref="pageHeader" :style="`margin-top: ${multiPage ? 0 : -24}px`" :breadcrumb="breadcrumb" :title="pageTitle" :logo="logo" :avatar="avatar">
<slot name="action" slot="action"></slot>
<slot slot="content" name="headerContent"></slot>
<div slot="content" v-if="(!this.$slots.headerContent && desc) || (this.$slots.headerContent == ' ' || desc == ' ')">
<!-- 如果desc存在内容则显示如果不存在则不显示 -->
<p v-if="desc" v-html="desc"></p>
<div v-if="this.linkList" class="link">
<template v-for="(link, index) in linkList">
<a :key="index" :href="link.href"><a-icon :type="link.icon" />{{link.title}}</a>
</template>
</div>
</div>
<slot v-if="this.$slots.extra" slot="extra" name="extra"></slot>
</page-header>
<div ref="page" :class="['page-content', layout, pageWidth]" >
<slot></slot>
</div>
</div>
</template>
<script>
import PageHeader from '@/components/page/header/PageHeader' // 加载头部组件
import {mapState, mapMutations} from 'vuex' // 加载vuex
import {getI18nKey} from '@/utils/routerUtil' // 加载路由工具
export default {
name: 'PageLayout', // 组件名称
components: {PageHeader}, // 注册组件
props: ['desc', 'logo', 'title', 'avatar', 'linkList', 'extraImage'], // 组件属性
data () { // 组件数据
return {
page: {}, // 页面数据
pageHeaderHeight: 0, // 页面头部高度
}
},
watch: { // 监听
$route() {
this.page = this.$route.meta.page // 监听路由变化
}
},
updated() { // 更新
if (!this._inactive) { // 如果页面不是隐藏状态
this.updatePageHeight() // 更新页面高度
}
},
activated() { // 激活
this.updatePageHeight() // 更新页面高度
},
deactivated() { // 隐藏
this.updatePageHeight(0) // 更新页面高度
},
mounted() { // 挂载
this.updatePageHeight() // 更新页面高度
},
created() { // 创建
this.page = this.$route.meta.page // 获取页面数据
},
beforeDestroy() { // 销毁前
this.updatePageHeight(0) // 更新页面高度
},
computed: {
...mapState('setting', ['layout', 'multiPage', 'pageMinHeight', 'pageWidth', 'customTitles']),
// 获取vuex数据 获取布局、多页签、页面最小高度、页面宽度、自定义标题
pageTitle() { // 页面标题
let pageTitle = this.page && this.page.title // 获取页面标题
return this.customTitle || (pageTitle && this.$t(pageTitle)) || this.title || this.routeName // 返回自定义标题、页面标题、组件标题、路由名称
},
routeName() { // 路由名称
const route = this.$route // 获取路由
return this.$t(getI18nKey(route.matched[route.matched.length - 1].path)) // 返回路由名称
},
breadcrumb() { // 面包屑
let page = this.page // 获取页面数据
let breadcrumb = page && page.breadcrumb // 获取面包屑
if (breadcrumb) { // 如果有面包屑
let i18nBreadcrumb = [] // 国际化面包屑
breadcrumb.forEach(item => { // 遍历面包屑
i18nBreadcrumb.push(this.$t(item)) // 添加国际化面包屑
})
return i18nBreadcrumb // 返回国际化面包屑
} else {
return this.getRouteBreadcrumb() // 返回路由面包屑
}
},
marginCorrect() { // 间距修正
return this.multiPage ? 24 : 0 // 返回多页签间距修正
}
},
methods: {
...mapMutations('setting', ['correctPageMinHeight']), // 获取vuex方法 更新页面最小高度
getRouteBreadcrumb() { // 获取路由面包屑
let routes = this.$route.matched // 获取路由
const path = this.$route.path // 获取路由路径
let breadcrumb = []
routes.filter(item => path.includes(item.path)) // 过滤路由
.forEach(route => { // 遍历路由
const path = route.path.length === 0 ? '/home' : route.path // 获取路由路径
breadcrumb.push(this.$t(getI18nKey(path))) // 添加国际化面包屑
})
let pageTitle = this.page && this.page.title // 获取页面标题
if (this.customTitle || pageTitle) { // 如果有自定义标题或页面标题
breadcrumb[breadcrumb.length - 1] = this.customTitle || pageTitle // 替换面包屑
}
return breadcrumb // 返回面包屑
},
/**
* 用于计算页面内容最小高度
* @param newHeight
*/
updatePageHeight(newHeight = this.$refs.pageHeader.$el.offsetHeight + this.marginCorrect) { // 更新页面高度
this.correctPageMinHeight(this.pageHeaderHeight - newHeight) // 更新页面最小高度
this.pageHeaderHeight = newHeight // 更新页面头部高度
}
}
}
</script>
<style lang="less">
.page-header{
margin: 0 -24px 0;
}
.link{
/*margin-top: 16px;*/
line-height: 24px;
a{
font-size: 14px;
margin-right: 32px;
i{
font-size: 22px;
margin-right: 8px;
}
}
}
.page-content{
position: relative;
padding: 24px 0 0;
&.side{
}
&.head.fixed{
margin: 0 auto;
max-width: 1400px;
}
}
</style>