|
@@ -0,0 +1,225 @@
|
|
|
+<template>
|
|
|
+ <div id="app">
|
|
|
+ <router-view v-if="$route.path == '/frame/login'"></router-view>
|
|
|
+ <div v-else class="main">
|
|
|
+ <div class="left" :style="{ 'width': is_collapse.leftWidth }">
|
|
|
+ <logo :isCollapse="isCollapse" class="logo" :style="{ 'height': computedHeigth.headerHeigth }"></logo>
|
|
|
+ <menus ref="menus" :menuList="menuList" :isCollapse="isCollapse" class="menu" :style="{ 'height': computedHeigth.menuHeigth }" @menuSelect="menuSelect"></menus>
|
|
|
+ </div>
|
|
|
+ <div class="right" :style="{ 'width': is_collapse.rightWidth }">
|
|
|
+ <headers class="header" :style="{ 'height': computedHeigth.headerHeigth }" @isCollapseChage="isCollapse = $event"></headers>
|
|
|
+ <!-- 非标签页时使用 -->
|
|
|
+ <breadcrumb v-if="!config.tabs" :menuList="menuList" :home="frameTabs"></breadcrumb>
|
|
|
+ <!-- 标签页 -->
|
|
|
+ <el-tabs v-if="config.tabs" class="tabBox" :style="{ 'height': computedHeigth.contentHeigth }" v-model="editableTabsValue" :type="config.tabs_card" @tab-remove="removeTab" @tab-click="clickTab">
|
|
|
+ <el-tab-pane
|
|
|
+ v-for="item in frameTabs"
|
|
|
+ :key="item.code"
|
|
|
+ :label="item.title"
|
|
|
+ :name="item.code"
|
|
|
+ >
|
|
|
+ <router-view></router-view>
|
|
|
+ </el-tab-pane>
|
|
|
+ <el-tab-pane
|
|
|
+ closable
|
|
|
+ v-for="item in editableTabs"
|
|
|
+ :key="item.code"
|
|
|
+ :label="item.title"
|
|
|
+ :name="item.code"
|
|
|
+ >
|
|
|
+ <template v-if="editableTabsValue == item.code">
|
|
|
+ <div :id="item.module" class="content"></div>
|
|
|
+ </template>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ <!-- 非标签页时使用 -->
|
|
|
+ <router-view v-if="is_frame && !config.tabs"></router-view>
|
|
|
+ <div v-show="!is_frame" v-if="!config.tabs" id="content" class="content"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+/* 此处进行菜单数据模拟,正式调试后删除 */
|
|
|
+// import menuList from '@mock/menu.js';
|
|
|
+/* 调试结束符号 */
|
|
|
+import style from '@style/index.module.scss';
|
|
|
+import headers from '@components/header';
|
|
|
+import menus from '@components/menu';
|
|
|
+import logo from '@components/header/logo';
|
|
|
+import breadcrumb from '@components/header/breadcrumb';
|
|
|
+import { mapState, mapActions } from 'vuex';
|
|
|
+// .env配置
|
|
|
+const config = {
|
|
|
+ tabs: eval(process.env.VUE_APP_TABS ?? false),
|
|
|
+ headerHeigth: process.env.VUE_APP_HEADER,
|
|
|
+ tabs_card: process.env.VUE_APP_TABS_CARD
|
|
|
+};
|
|
|
+export default {
|
|
|
+ components: {
|
|
|
+ headers,
|
|
|
+ menus,
|
|
|
+ logo,
|
|
|
+ breadcrumb
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ ...mapState(['menuList']),
|
|
|
+ // 切换路由或dom对象计算属性 如果当前选项包含frame 使用路由 否则 使用dom
|
|
|
+ is_frame() {
|
|
|
+ return this.editableTabsValue.includes('frame');
|
|
|
+ },
|
|
|
+ // 切换菜单宽度计算属性
|
|
|
+ is_collapse() {
|
|
|
+ return { leftWidth: this.isCollapse ? style.minLeftWidth : style.maxLeftWidth, rightWidth: this.isCollapse ? style.maxRightWidth : style.minRightWidth };
|
|
|
+ },
|
|
|
+ // 切换header高度 与 menu高度
|
|
|
+ computedHeigth() {
|
|
|
+ if (config.headerHeigth == 'max') {
|
|
|
+ return { headerHeigth: style.maxHeaderHeigth, menuHeigth: style.minMenuHeigth, contentHeigth: style.minContentHeigth };
|
|
|
+ }
|
|
|
+ return { headerHeigth: style.minHeaderHeigth, menuHeigth: style.maxMenuHeigth, contentHeigth: style.maxContentHeigth };
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ // .env配置
|
|
|
+ config,
|
|
|
+ // 折叠收起菜单
|
|
|
+ isCollapse: false,
|
|
|
+ // tabs当前选项
|
|
|
+ editableTabsValue: '',
|
|
|
+ // 默认不可关闭页面数组
|
|
|
+ frameTabs: [
|
|
|
+ { module: 'frame', path: '/frame/home', title: '首页', code: 'frameHome', parentCode: null }
|
|
|
+ ],
|
|
|
+ // 可关闭页面数组
|
|
|
+ editableTabs: []
|
|
|
+ };
|
|
|
+ },
|
|
|
+ async mounted() {
|
|
|
+ if (sessionStorage.userInfo) {
|
|
|
+ const { id } = JSON.parse(sessionStorage.userInfo);
|
|
|
+ await this.queryUserMenu({ userId: id });
|
|
|
+ }
|
|
|
+ if (this.$route.path !== '/frame/login') this.menuInit();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ ...mapActions(['queryUserMenu']),
|
|
|
+ // 初始化菜单点击
|
|
|
+ menuInit() {
|
|
|
+ // 获取当前选中tab 没有默认设置Home页
|
|
|
+ this.editableTabsValue = sessionStorage.getItem('tabs') ?? 'frameHome';
|
|
|
+ // 调用菜单点击函数
|
|
|
+ this.$refs.menus.menuSelect(this.editableTabsValue);
|
|
|
+ },
|
|
|
+ // 菜单选择函数
|
|
|
+ menuSelect(e) {
|
|
|
+ // 赋值当前选项
|
|
|
+ this.editableTabsValue = e.code;
|
|
|
+ // 不是子应用向选项组添加当前选项
|
|
|
+ if (!this.is_frame && !this.editableTabs.includes(e)) {
|
|
|
+ this.editableTabs.push(e);
|
|
|
+ }
|
|
|
+ this.clickTab(e);
|
|
|
+ },
|
|
|
+ // tab点击函数
|
|
|
+ clickTab (e) {
|
|
|
+ // 解决点击tab标签是导航不跟随切换问题
|
|
|
+ if (this.$refs.menus.defaultActiveItem !== this.editableTabsValue) {
|
|
|
+ this.$refs.menus.menuSelect(this.editableTabsValue);
|
|
|
+ }
|
|
|
+ // 解决tab标签实例不存在code属性
|
|
|
+ if (!e.code) e.code = e.name;
|
|
|
+ // 存储 sessionStorage
|
|
|
+ sessionStorage.setItem('tabs', e.code);
|
|
|
+ let item;
|
|
|
+ // 判断是不是子应用
|
|
|
+ if (!this.is_frame) {
|
|
|
+ item = this.editableTabs.find(i => i.code == e.code);
|
|
|
+ } else {
|
|
|
+ item = this.frameTabs.find(i => i.code == e.code);
|
|
|
+ }
|
|
|
+ // 如果是当前路由,直接返回
|
|
|
+ if (item.path == this.$route.path) return;
|
|
|
+ // 路由跳转
|
|
|
+ this.$router.push(item.path);
|
|
|
+ },
|
|
|
+ // 移除tab标签函数
|
|
|
+ removeTab (index) {
|
|
|
+ // 删除当前选项
|
|
|
+ this.editableTabs = this.editableTabs.filter(e => e.code !== index);
|
|
|
+ // 删除后选择打开的最后一项 或 首页
|
|
|
+ this.editableTabsValue = this.editableTabs[this.editableTabs.length - 1]?.code ?? 'frameHome';
|
|
|
+ this.$refs.menus.menuSelect(this.editableTabsValue);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ $route(to) {
|
|
|
+ if (this.$route.path == '/') this.$router.go(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+@import '@style/index.scss';
|
|
|
+body {
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+#app {
|
|
|
+ width: 100vw;
|
|
|
+ height: 100vh;
|
|
|
+ .main {
|
|
|
+ display: flex;
|
|
|
+ overflow: hidden;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ .left {
|
|
|
+ height: 100vh;
|
|
|
+ .logo {
|
|
|
+ width: 100%;
|
|
|
+ background: $menuBackgroundColor;
|
|
|
+ }
|
|
|
+ .menu {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .right {
|
|
|
+ height: 100%;
|
|
|
+ .header {
|
|
|
+ height: 10vh;
|
|
|
+ }
|
|
|
+ .tabBox {
|
|
|
+ width: 100%;
|
|
|
+ .el-tabs__header {
|
|
|
+ margin: 0;
|
|
|
+ }
|
|
|
+ .el-tabs__content {
|
|
|
+ width: 100%;
|
|
|
+ height: 97%;
|
|
|
+ .el-tab-pane {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .content {
|
|
|
+ height: 100%;
|
|
|
+ width: 100%;
|
|
|
+ > div {
|
|
|
+ height: 98%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #content {
|
|
|
+ height: 100%;
|
|
|
+ width: 100%;
|
|
|
+ > div {
|
|
|
+ height: 98%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|