|
|
|
@ -1,6 +1,8 @@
|
|
|
|
|
<template>
|
|
|
|
|
<!-- 使用 `a-layout` 组件构建页面布局,并根据 `device` 变量的值动态添加类名,与下面的样式设置配合来实现不同设备下的布局样式适配,例如可能根据是移动端、桌面端等设备呈现不同的外观和布局形式。 -->
|
|
|
|
|
<a-layout :class="['layout', device]">
|
|
|
|
|
<!-- SideMenu -->
|
|
|
|
|
<!-- 当设备处于移动端(通过 `isMobile()` 方法判断)时,显示侧边栏抽屉组件(`a-drawer`),用于在移动端展示侧边栏菜单,提供更好的交互体验和节省屏幕空间。 -->
|
|
|
|
|
<a-drawer
|
|
|
|
|
v-if="isMobile()"
|
|
|
|
|
placement="left"
|
|
|
|
@ -9,6 +11,7 @@
|
|
|
|
|
:visible="collapsed"
|
|
|
|
|
@close="drawerClose"
|
|
|
|
|
>
|
|
|
|
|
<!-- 在抽屉内部使用 `side-menu` 组件来展示侧边栏菜单,设置菜单模式为 `inline`(内联模式,可能表示菜单项水平排列等样式特点),传入 `menus` 数据用于生成具体的菜单项,同时传递主题、折叠状态等相关属性,用于控制菜单的外观和交互行为。 -->
|
|
|
|
|
<side-menu
|
|
|
|
|
mode="inline"
|
|
|
|
|
:menus="menus"
|
|
|
|
@ -19,6 +22,7 @@
|
|
|
|
|
></side-menu>
|
|
|
|
|
</a-drawer>
|
|
|
|
|
|
|
|
|
|
<!-- 当设备不是移动端且满足 `isSideMenu()` 条件时(推测是桌面端等支持侧边栏显示的情况),显示侧边栏菜单(`side-menu`)组件,同样传入相关属性来配置菜单的展示形式、主题、折叠状态等,这里的折叠状态由 `collapsed` 变量控制。 -->
|
|
|
|
|
<side-menu
|
|
|
|
|
v-else-if="isSideMenu()"
|
|
|
|
|
mode="inline"
|
|
|
|
@ -28,8 +32,10 @@
|
|
|
|
|
:collapsible="true"
|
|
|
|
|
></side-menu>
|
|
|
|
|
|
|
|
|
|
<!-- 使用另一个 `a-layout` 组件来进一步构建页面主体部分的布局,通过动态绑定类名和内联样式来控制布局样式,例如根据不同的 `layoutMode` 和 `contentWidth` 来呈现不同的页面布局风格,同时设置最小高度为视口高度(`100vh`),确保页面内容区域能占满整个屏幕高度。 -->
|
|
|
|
|
<a-layout :class="[layoutMode, `content-width-${contentWidth}`]" :style="{ paddingLeft: contentPaddingLeft, minHeight: '100vh' }">
|
|
|
|
|
<!-- layout header -->
|
|
|
|
|
<!-- 使用 `global-header` 组件来展示页面头部,传入如布局模式、菜单数据、主题、折叠状态、设备类型等属性,通过这些属性来控制头部的显示内容和交互行为,例如根据不同的布局模式显示不同的菜单样式,根据折叠状态显示或隐藏某些元素等,同时监听 `toggle` 事件用于处理头部相关的交互操作(如展开/收起侧边栏等)。 -->
|
|
|
|
|
<global-header
|
|
|
|
|
:mode="layoutMode"
|
|
|
|
|
:menus="menus"
|
|
|
|
@ -40,19 +46,24 @@
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<!-- layout content -->
|
|
|
|
|
<a-layout-content :style="{ height: '100%', margin: '24px 24px 0', paddingTop: fixedHeader ? '64px' : '0' }">
|
|
|
|
|
<!-- 使用 `a-layout-content` 组件来承载页面的主体内容部分,设置内容区域的高度为 `100%`(占满父容器高度),设置外边距以及根据 `fixedHeader` 变量的值来决定顶部的内边距(若头部固定则设置顶部内边距为 `64px`,否则为 `0`),确保内容区域在页面中的布局位置和样式符合设计要求。 -->
|
|
|
|
|
<a-layout-content :style="{ height: '100%', margin: '24px 24px 0', paddingTop: fixedHeader? '64px' : '0' }">
|
|
|
|
|
<!-- 当启用多标签页功能(`multiTab` 为 `true`)时,显示 `multi-tab` 组件,可能用于实现同时展示多个页面标签并可切换查看不同页面内容的功能,方便用户在多个相关页面之间快速切换浏览。 -->
|
|
|
|
|
<multi-tab v-if="multiTab"></multi-tab>
|
|
|
|
|
<!-- 使用 Vue 的过渡效果(`transition`)组件包裹 `route-view` 组件,当路由切换时,通过名为 `page-transition` 的过渡效果来实现页面切换的动画效果,比如淡入淡出、缩放等动画表现,提升页面切换的视觉体验。 -->
|
|
|
|
|
<transition name="page-transition">
|
|
|
|
|
<route-view />
|
|
|
|
|
</transition>
|
|
|
|
|
</a-layout-content>
|
|
|
|
|
|
|
|
|
|
<!-- layout footer -->
|
|
|
|
|
<!-- 使用 `a-layout-footer` 组件来展示页面底部,内部包含 `global-footer` 组件,用于展示如版权信息、联系方式等页面底部相关的通用内容。 -->
|
|
|
|
|
<a-layout-footer>
|
|
|
|
|
<global-footer />
|
|
|
|
|
</a-layout-footer>
|
|
|
|
|
|
|
|
|
|
<!-- Setting Drawer (show in development mode) -->
|
|
|
|
|
<!-- 当处于非生产环境(`!production`)时,显示 `setting-drawer` 组件,从命名推测可能是用于在开发阶段展示一些设置选项的抽屉式组件,方便开发人员进行调试、配置等操作,在正式上线的生产环境中则不显示该组件。 -->
|
|
|
|
|
<setting-drawer v-if="!production"></setting-drawer>
|
|
|
|
|
</a-layout>
|
|
|
|
|
</a-layout>
|
|
|
|
@ -60,20 +71,26 @@
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import { triggerWindowResizeEvent } from '../utils/util'
|
|
|
|
|
import { mapState, mapActions } from 'vuex'
|
|
|
|
|
import { mixin, mixinDevice } from '../utils/mixin'
|
|
|
|
|
import config from '../config/defaultSettings'
|
|
|
|
|
// 从 '../utils/util' 文件中导入 `triggerWindowResizeEvent` 函数,从命名推测该函数可能用于触发窗口大小改变的事件,也许在页面布局调整等场景下需要手动触发此事件来让相关组件重新计算布局、更新样式等。
|
|
|
|
|
import { triggerWindowResizeEvent } from '../utils/util';
|
|
|
|
|
// 从 'vuex' 中导入 `mapState` 和 `mapActions` 两个辅助函数,`mapState` 用于将 Vuex 中的状态映射到组件的计算属性中,方便在组件内获取和使用全局状态数据;`mapActions` 则用于将 Vuex 中的 actions(用于提交 mutations 来改变状态的函数)映射到组件的方法中,便于在组件内触发相应的状态变更操作。
|
|
|
|
|
import { mapState, mapActions } from 'vuex';
|
|
|
|
|
// 从 '../utils/mixin' 文件中导入 `mixin` 和 `mixinDevice`,Vue 的混入(mixin)机制允许将一些公共的逻辑(如方法、生命周期钩子、计算属性等)提取出来,在多个组件中复用,这里导入的两个混入对象大概率包含了与通用功能、设备相关判断等逻辑,供当前组件使用。
|
|
|
|
|
import { mixin, mixinDevice } from '../utils/mixin';
|
|
|
|
|
// 导入项目的默认配置对象 `config`,里面包含了如页面布局、生产环境判断等各种项目相关的默认设置参数,在组件中会依据这些默认配置来进行一些属性初始化、条件判断等操作。
|
|
|
|
|
import config from '../config/defaultSettings';
|
|
|
|
|
|
|
|
|
|
import RouteView from './RouteView'
|
|
|
|
|
import MultiTab from '../components/MultiTab'
|
|
|
|
|
import SideMenu from '../components/Menu/SideMenu'
|
|
|
|
|
import GlobalHeader from '../components/GlobalHeader'
|
|
|
|
|
import GlobalFooter from '../components/GlobalFooter'
|
|
|
|
|
import SettingDrawer from '../components/SettingDrawer'
|
|
|
|
|
// 导入多个自定义组件,这些组件将在当前模板中使用,用于构建页面的不同部分,如路由视图、多标签页、侧边栏菜单、页面头部、页面底部以及设置抽屉等组件,每个组件都有其特定的功能和对应的 UI 展示及交互逻辑。
|
|
|
|
|
import RouteView from './RouteView';
|
|
|
|
|
import MultiTab from '../components/MultiTab';
|
|
|
|
|
import SideMenu from '../components/Menu/SideMenu';
|
|
|
|
|
import GlobalHeader from '../components/GlobalHeader';
|
|
|
|
|
import GlobalFooter from '../components/GlobalFooter';
|
|
|
|
|
import SettingDrawer from '../components/SettingDrawer';
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
name: 'BasicLayout',
|
|
|
|
|
// 将导入的 `mixin` 和 `mixinDevice` 混入到当前组件中,使得组件可以继承混入对象中定义的各种属性、方法、生命周期钩子等,实现代码复用,提升开发效率以及保证不同组件间相关逻辑的一致性。
|
|
|
|
|
mixins: [mixin, mixinDevice],
|
|
|
|
|
components: {
|
|
|
|
|
RouteView,
|
|
|
|
@ -85,75 +102,92 @@ export default {
|
|
|
|
|
},
|
|
|
|
|
data () {
|
|
|
|
|
return {
|
|
|
|
|
// 从配置对象 `config` 中获取 `production` 属性值,用于判断当前是否处于生产环境,后续可以根据这个值来决定是否显示某些仅在开发环境中使用的组件或者执行特定的调试相关逻辑。
|
|
|
|
|
production: config.production,
|
|
|
|
|
// 初始化 `collapsed` 状态为 `false`,这个变量大概率用于控制侧边栏(如抽屉式侧边栏或者普通侧边栏)是否处于折叠状态,`false` 表示初始状态下侧边栏是展开的。
|
|
|
|
|
collapsed: false,
|
|
|
|
|
// 初始化 `menus` 数组为空,这个数组应该是用于存储侧边栏菜单的数据,后续会通过获取路由等相关信息来填充具体的菜单内容,用于在侧边栏中展示具体的菜单项。
|
|
|
|
|
menus: []
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
...mapState({
|
|
|
|
|
// 动态主路由
|
|
|
|
|
// 使用 `mapState` 函数将 Vuex 中的 `state.permission.addRouters` 状态映射到当前组件的计算属性 `mainMenu` 中,这样在组件内就能方便地获取到动态生成的主路由信息,用于构建侧边栏菜单等相关功能,可能根据不同用户权限动态加载不同的路由和菜单选项。
|
|
|
|
|
mainMenu: state => state.permission.addRouters
|
|
|
|
|
}),
|
|
|
|
|
contentPaddingLeft () {
|
|
|
|
|
// 根据侧边栏是否固定(`fixSidebar`)以及是否处于移动端(`isMobile()`)来计算内容区域的左边距(`contentPaddingLeft`),用于控制页面主体内容在水平方向上的布局位置,避免与侧边栏产生布局冲突等情况。
|
|
|
|
|
if (!this.fixSidebar || this.isMobile()) {
|
|
|
|
|
return '0'
|
|
|
|
|
return '0';
|
|
|
|
|
}
|
|
|
|
|
// 如果侧边栏是展开的(`sidebarOpened` 为 `true`),设置左边距为 `256px`,这个值可能是侧边栏展开时所占据的宽度,确保内容区域能合理避让侧边栏。
|
|
|
|
|
if (this.sidebarOpened) {
|
|
|
|
|
return '256px'
|
|
|
|
|
return '256px';
|
|
|
|
|
}
|
|
|
|
|
return '80px'
|
|
|
|
|
return '80px';
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
sidebarOpened (val) {
|
|
|
|
|
this.collapsed = !val
|
|
|
|
|
// 监听 `sidebarOpened` 属性的变化,当它的值改变时(可能是用户操作展开或折叠侧边栏等情况),同步更新 `collapsed` 状态,取反操作可能意味着 `sidebarOpened` 为 `true` 时 `collapsed` 为 `false`,反之亦然,以此保持侧边栏状态在不同变量间的一致性。
|
|
|
|
|
this.collapsed =!val;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
created () {
|
|
|
|
|
this.menus = this.mainMenu.find(item => item.path === '/').children
|
|
|
|
|
this.collapsed = !this.sidebarOpened
|
|
|
|
|
// 在组件创建生命周期钩子中,从 `mainMenu`(通过 Vuex 映射过来的动态主路由信息)中查找路径为 `'/'` 的路由对象,并获取其 `children` 属性值赋给 `menus` 数组,用于初始化侧边栏菜单的数据,也就是将根路由下的子路由作为侧边栏的菜单项数据来源。
|
|
|
|
|
this.menus = this.mainMenu.find(item => item.path === '/').children;
|
|
|
|
|
// 根据侧边栏是否初始打开(`sidebarOpened`)状态来设置 `collapsed` 状态,同样是保持两者状态的一致性,确保侧边栏的初始显示状态符合预期。
|
|
|
|
|
this.collapsed =!this.sidebarOpened;
|
|
|
|
|
},
|
|
|
|
|
mounted () {
|
|
|
|
|
const userAgent = navigator.userAgent
|
|
|
|
|
const userAgent = navigator.userAgent;
|
|
|
|
|
// 判断当前浏览器的用户代理字符串(`userAgent`)中是否包含 `Edge` 字符串,若包含则说明当前是在 Edge 浏览器环境下,执行以下特殊的逻辑处理,可能是为了解决 Edge 浏览器下与侧边栏折叠展开相关的样式或交互问题。
|
|
|
|
|
if (userAgent.indexOf('Edge') > -1) {
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.collapsed = !this.collapsed
|
|
|
|
|
// 先将 `collapsed` 状态取反,触发相关的样式更新或其他依赖此状态的逻辑执行,可能用于初次渲染时的一些调整。
|
|
|
|
|
this.collapsed =!this.collapsed;
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
this.collapsed = !this.collapsed
|
|
|
|
|
}, 16)
|
|
|
|
|
})
|
|
|
|
|
// 经过短暂的延迟(16 毫秒)后,再次将 `collapsed` 状态取反,可能是为了让某些过渡动画、样式调整等能正确完成,解决 Edge 浏览器下特定的显示或交互问题,具体作用取决于相关代码中对 `collapsed` 状态变化的响应逻辑。
|
|
|
|
|
this.collapsed =!this.collapsed;
|
|
|
|
|
}, 16);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
...mapActions(['setSidebar']),
|
|
|
|
|
toggle () {
|
|
|
|
|
this.collapsed = !this.collapsed
|
|
|
|
|
this.setSidebar(!this.collapsed)
|
|
|
|
|
triggerWindowResizeEvent()
|
|
|
|
|
// 定义 `toggle` 方法,用于切换侧边栏的折叠/展开状态,先对 `collapsed` 状态取反,然后调用 `setSidebar` 方法(通过 `mapActions` 从 Vuex 映射过来的用于改变侧边栏状态的 action)并传入取反后的 `collapsed` 值,来更新 Vuex 中的侧边栏状态,最后触发窗口大小改变事件(`triggerWindowResizeEvent`),以便页面其他相关部分能根据侧边栏状态变化重新调整布局等。
|
|
|
|
|
this.collapsed =!this.collapsed;
|
|
|
|
|
this.setSidebar(!this.collapsed);
|
|
|
|
|
triggerWindowResizeEvent();
|
|
|
|
|
},
|
|
|
|
|
paddingCalc () {
|
|
|
|
|
let left = ''
|
|
|
|
|
let left = '';
|
|
|
|
|
// 根据侧边栏是否展开(`sidebarOpened`)以及是否处于移动端(`isMobile()`)或者侧边栏是否固定(`fixSidebar`)等条件来计算内容区域左边距的值,用于动态调整内容区域在水平方向上的位置,确保布局的合理性,不同条件下返回不同的宽度值(如 `256px`、`80px` 或 `0`)来适应侧边栏的不同状态。
|
|
|
|
|
if (this.sidebarOpened) {
|
|
|
|
|
left = this.isDesktop() ? '256px' : '80px'
|
|
|
|
|
left = this.isDesktop()? '256px' : '80px';
|
|
|
|
|
} else {
|
|
|
|
|
left = (this.isMobile() && '0') || ((this.fixSidebar && '80px') || '0')
|
|
|
|
|
left = (this.isMobile() && '0') || ((this.fixSidebar && '80px') || '0');
|
|
|
|
|
}
|
|
|
|
|
return left
|
|
|
|
|
return left;
|
|
|
|
|
},
|
|
|
|
|
menuSelect () {
|
|
|
|
|
// 定义 `menuSelect` 方法,当菜单项被选中时触发,判断如果当前设备不是桌面端(`!isDesktop()`),则将侧边栏设置为展开状态(`collapsed` 设为 `false`),可能是在移动端等设备上为了方便用户查看菜单内容,选中菜单项后自动展开侧边栏。
|
|
|
|
|
if (!this.isDesktop()) {
|
|
|
|
|
this.collapsed = false
|
|
|
|
|
this.collapsed = false;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
drawerClose () {
|
|
|
|
|
this.collapsed = false
|
|
|
|
|
// 定义 `drawerClose` 方法,当侧边栏抽屉关闭时触发,将侧边栏设置为展开状态(`collapsed` 设为 `false`),确保侧边栏在抽屉关闭后呈现展开的默认状态,方便用户再次操作和查看菜单内容。
|
|
|
|
|
this.collapsed = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="less">
|
|
|
|
|
// 导入 '../components/global.less' 文件中的样式,这个文件可能包含了一些全局通用的样式规则,用于定义页面中通用元素的基本样式,如字体、颜色、基础布局等,确保整个页面的风格具有一致性。
|
|
|
|
|
@import url('../components/global.less');
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -165,17 +199,20 @@ export default {
|
|
|
|
|
* these styles.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// 当元素应用了名为 `page-transition` 的过渡效果且处于进入(enter)阶段时(也就是页面切换进入时),设置元素的透明度为 `0`,实现淡入的过渡起始效果,用户会看到元素从透明逐渐变为不透明的动画过程。
|
|
|
|
|
.page-transition-enter {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当元素应用了名为 `page-transition` 的过渡效果且处于离开(leave)且激活(active)阶段时(也就是页面切换离开时),设置元素的透明度为 `0`,实现淡出的过渡结束效果,与 `page-transition-enter` 配合,呈现完整的淡入淡出过渡动画效果。
|
|
|
|
|
.page-transition-leave-active {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.page-transition-enter .page-transition-container,
|
|
|
|
|
.page-transition-leave-active .page-transition-container {
|
|
|
|
|
// 当元素应用了名为 `page-transition` 的过渡效果且处于进入(enter)阶段或者处于离开(leave)且激活(active)阶段时,对元素内部的 `.page-transition-container` 类名对应的子元素(从命名推测可能是用于包裹页面内容等的容器元素)进行样式设置,通过 `transform` 属性将其在水平和垂直方向上按比例缩放 `1.1` 倍,实现页面切换时的缩放动画效果,与透明度变化的动画效果结合,丰富了页面切换的视觉体验,开发者可以通过编辑这些样式规则来调整页面过渡动画的具体表现形式,以满足不同的设计需求。
|
|
|
|
|
.page-transition-enter.page-transition-container,
|
|
|
|
|
.page-transition-leave-active.page-transition-container {
|
|
|
|
|
-webkit-transform: scale(1.1);
|
|
|
|
|
transform: scale(1.1);
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
</style>
|