348 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
			
		
		
	
	
			348 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
<template>
 | 
						|
  <main
 | 
						|
    class="site-content"
 | 
						|
    :class="{ 'site-content--tabs': $route.meta.isTab }"
 | 
						|
  >
 | 
						|
    <!-- 主入口标签页 s -->
 | 
						|
    <el-tabs
 | 
						|
      v-if="$route.meta.isTab"
 | 
						|
      v-model="mainTabsActiveName"
 | 
						|
      :closable="true"
 | 
						|
      type="card"
 | 
						|
      @tab-click="selectedTabHandle"
 | 
						|
      @tab-remove="removeTabHandle"
 | 
						|
    >
 | 
						|
      <el-dropdown class="site-tabs__tools" :show-timeout="0">
 | 
						|
        <i class="el-icon-arrow-down el-icon--right"></i>
 | 
						|
        <el-dropdown-menu slot="dropdown">
 | 
						|
          <el-dropdown-item @click.native="tabsCloseCurrentHandle"
 | 
						|
            >关闭当前标签页</el-dropdown-item
 | 
						|
          >
 | 
						|
          <el-dropdown-item @click.native="tabsCloseOtherHandle"
 | 
						|
            >关闭其它标签页</el-dropdown-item
 | 
						|
          >
 | 
						|
          <el-dropdown-item @click.native="tabsCloseAllHandle"
 | 
						|
            >关闭全部标签页</el-dropdown-item
 | 
						|
          >
 | 
						|
          <el-dropdown-item @click.native="refresh()"
 | 
						|
            >刷新当前标签页</el-dropdown-item
 | 
						|
          >
 | 
						|
        </el-dropdown-menu>
 | 
						|
      </el-dropdown>
 | 
						|
      <el-tab-pane
 | 
						|
        v-for="item in mainTabs"
 | 
						|
        :key="item.name"
 | 
						|
        :label="item.title"
 | 
						|
        :name="item.name"
 | 
						|
      >
 | 
						|
        <div
 | 
						|
          slot="label"
 | 
						|
          class="inline-flex justify-center"
 | 
						|
          @contextmenu.prevent="(event) => onContextmenu(event, item)"
 | 
						|
          style="width: 100px"
 | 
						|
        >
 | 
						|
          <el-tooltip
 | 
						|
            v-if="item.title.length > 6"
 | 
						|
            effect="dark"
 | 
						|
            :content="item.title"
 | 
						|
            placement="top"
 | 
						|
          >
 | 
						|
            <span class="w-100 flex justify-center">{{
 | 
						|
              item.title.length > 6
 | 
						|
                ? `${item.title.slice(0, 6)}...`
 | 
						|
                : item.title
 | 
						|
            }}</span>
 | 
						|
          </el-tooltip>
 | 
						|
          <span v-else class="w-100 flex justify-center">{{
 | 
						|
            item.title.length > 6 ? `${item.title.slice(0, 6)}...` : item.title
 | 
						|
          }}</span>
 | 
						|
        </div>
 | 
						|
        <el-card :body-style="siteContentViewHeight" class="content-card">
 | 
						|
          <transition name="fade-transform" mode="out-in">
 | 
						|
            <iframe
 | 
						|
              v-if="item.type === 'iframe'"
 | 
						|
              :src="item.iframeUrl"
 | 
						|
              width="100%"
 | 
						|
              height="100%"
 | 
						|
              frameborder="0"
 | 
						|
              scrolling="yes"
 | 
						|
            >
 | 
						|
            </iframe>
 | 
						|
            <micro-app
 | 
						|
              v-else-if="item.type === 'microApp'"
 | 
						|
              :name="item.name"
 | 
						|
              :url="item.iframeUrl"
 | 
						|
            >
 | 
						|
            </micro-app>
 | 
						|
            <keep-alive v-else>
 | 
						|
              <router-view v-if="item.name === mainTabsActiveName" />
 | 
						|
            </keep-alive>
 | 
						|
          </transition>
 | 
						|
        </el-card>
 | 
						|
      </el-tab-pane>
 | 
						|
    </el-tabs>
 | 
						|
    <!-- 主入口标签页 e -->
 | 
						|
    <el-card v-else :body-style="siteContentViewHeight" class="content-card">
 | 
						|
      <keep-alive>
 | 
						|
        <router-view />
 | 
						|
      </keep-alive>
 | 
						|
    </el-card>
 | 
						|
  </main>
 | 
						|
</template>
 | 
						|
 | 
						|
<script>
 | 
						|
// ... script部分保持不变 ...
 | 
						|
import { isURL } from "@/utils/validate";
 | 
						|
export default {
 | 
						|
  inject: ["refresh"],
 | 
						|
  data() {
 | 
						|
    return {};
 | 
						|
  },
 | 
						|
  computed: {
 | 
						|
    documentClientHeight: {
 | 
						|
      get() {
 | 
						|
        return this.$store.state.common.documentClientHeight;
 | 
						|
      },
 | 
						|
    },
 | 
						|
    menuActiveName: {
 | 
						|
      get() {
 | 
						|
        return this.$store.state.common.menuActiveName;
 | 
						|
      },
 | 
						|
      set(val) {
 | 
						|
        this.$store.commit("common/updateMenuActiveName", val);
 | 
						|
      },
 | 
						|
    },
 | 
						|
    mainTabs: {
 | 
						|
      get() {
 | 
						|
        return this.$store.state.common.mainTabs;
 | 
						|
      },
 | 
						|
      set(val) {
 | 
						|
        this.$store.commit("common/updateMainTabs", val);
 | 
						|
      },
 | 
						|
    },
 | 
						|
    mainTabsActiveName: {
 | 
						|
      get() {
 | 
						|
        return this.$store.state.common.mainTabsActiveName;
 | 
						|
      },
 | 
						|
      set(val) {
 | 
						|
        this.$store.commit("common/updateMainTabsActiveName", val);
 | 
						|
      },
 | 
						|
    },
 | 
						|
    siteContentViewHeight() {
 | 
						|
      var height = this.documentClientHeight - 50 - 2;
 | 
						|
      if (this.$route.meta.isTab) {
 | 
						|
        height -= 40;
 | 
						|
        return isURL(this.$route.meta.iframeUrl)
 | 
						|
          ? { height: height + "px" }
 | 
						|
          : { minHeight: height + "px" };
 | 
						|
      }
 | 
						|
      return { minHeight: height + "px" };
 | 
						|
    },
 | 
						|
  },
 | 
						|
  methods: {
 | 
						|
    onContextmenu(event, item) {
 | 
						|
      this.$contextmenu({
 | 
						|
        items: [
 | 
						|
          {
 | 
						|
            label: "关闭当前标签页",
 | 
						|
            icon:"el-icon-close",
 | 
						|
            onClick: () => {
 | 
						|
              this.removeTabHandle(item.name);
 | 
						|
            },
 | 
						|
          },
 | 
						|
          {
 | 
						|
            label: "关闭其他标签页",
 | 
						|
            icon:"el-icon-folder-delete",
 | 
						|
            onClick: () => {
 | 
						|
              this.tabsCloseOtherHandle()
 | 
						|
            },
 | 
						|
          },
 | 
						|
          {
 | 
						|
            label: "关闭右侧标签页",
 | 
						|
            icon:"el-icon-d-arrow-right",
 | 
						|
            onClick: () => {
 | 
						|
              this.mainTabs.splice(
 | 
						|
                this.mainTabs.findIndex((el) => {
 | 
						|
                  return el.name === item.name;
 | 
						|
                }) + 1,
 | 
						|
                this.mainTabs.length - 1
 | 
						|
              );
 | 
						|
              this.mainTabsActiveName = item.name;
 | 
						|
            },
 | 
						|
          },
 | 
						|
          {
 | 
						|
            label: "全部关闭标签页",
 | 
						|
            icon:"el-icon-document-delete",
 | 
						|
            onClick: () => {
 | 
						|
              this.tabsCloseAllHandle();
 | 
						|
            },
 | 
						|
          },
 | 
						|
        ],
 | 
						|
        event,
 | 
						|
        //x: event.clientX,
 | 
						|
        //y: event.clientY,
 | 
						|
        customClass: "custom-class",
 | 
						|
        zIndex: 99999999999999,
 | 
						|
        minWidth: 160,
 | 
						|
      });
 | 
						|
      return false;
 | 
						|
    },
 | 
						|
    // tabs, 选中tab
 | 
						|
    selectedTabHandle(tab) {
 | 
						|
      tab = this.mainTabs.filter((item) => item.name === tab.name);
 | 
						|
      if (tab.length >= 1) {
 | 
						|
        this.$router.push({
 | 
						|
          name: tab[0].name,
 | 
						|
          query: tab[0].query,
 | 
						|
          params: tab[0].params,
 | 
						|
        });
 | 
						|
      }
 | 
						|
    },
 | 
						|
    // tabs, 删除tab
 | 
						|
    removeTabHandle(tabName) {
 | 
						|
      this.mainTabs = this.mainTabs.filter((item) => item.name !== tabName);
 | 
						|
      if (this.mainTabs.length >= 1) {
 | 
						|
        // 当前选中tab被删除
 | 
						|
        if (tabName === this.mainTabsActiveName) {
 | 
						|
          var tab = this.mainTabs[this.mainTabs.length - 1];
 | 
						|
          this.$router.push(
 | 
						|
            { name: tab.name, query: tab.query, params: tab.params },
 | 
						|
            () => {
 | 
						|
              this.mainTabsActiveName = this.$route.name;
 | 
						|
            }
 | 
						|
          );
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        this.menuActiveName = "";
 | 
						|
        this.$router.push({ name: "home" });
 | 
						|
      }
 | 
						|
    },
 | 
						|
    // tabs, 关闭当前
 | 
						|
    tabsCloseCurrentHandle() {
 | 
						|
      this.removeTabHandle(this.mainTabsActiveName);
 | 
						|
    },
 | 
						|
    // tabs, 关闭其它
 | 
						|
    tabsCloseOtherHandle() {
 | 
						|
      this.mainTabs = this.mainTabs.filter(
 | 
						|
        (item) => item.name === this.mainTabsActiveName
 | 
						|
      );
 | 
						|
    },
 | 
						|
    // tabs, 关闭全部
 | 
						|
    tabsCloseAllHandle() {
 | 
						|
      this.mainTabs = [];
 | 
						|
      this.menuActiveName = "";
 | 
						|
      this.$router.push({ name: "home" });
 | 
						|
    },
 | 
						|
    // tabs, 刷新当前
 | 
						|
    tabsRefreshCurrentHandle() {
 | 
						|
      var tab = this.$route;
 | 
						|
      this.removeTabHandle(tab.name);
 | 
						|
      this.$nextTick(() => {
 | 
						|
        this.$router.push({
 | 
						|
          name: tab.name,
 | 
						|
          query: tab.query,
 | 
						|
          params: tab.params,
 | 
						|
        });
 | 
						|
      });
 | 
						|
    },
 | 
						|
  },
 | 
						|
};
 | 
						|
</script>
 | 
						|
 | 
						|
<style lang="scss">
 | 
						|
.site-content--tabs {
 | 
						|
  padding: 48px 0 0;
 | 
						|
}
 | 
						|
 | 
						|
// 优化 el-tabs 样式
 | 
						|
.el-tabs--card {
 | 
						|
  ::v-deep .el-tabs__header {
 | 
						|
    border-bottom: 1px solid #e0e2e5;
 | 
						|
    margin: 0;
 | 
						|
    padding: 0 8px; // 增加左右内边距
 | 
						|
    background-color: #ffffff;
 | 
						|
  }
 | 
						|
 | 
						|
  ::v-deep .el-tabs__nav {
 | 
						|
    border: none !important;
 | 
						|
  }
 | 
						|
 | 
						|
  ::v-deep .el-tabs__item {
 | 
						|
    height: 40px;
 | 
						|
    line-height: 40px;
 | 
						|
    color: #5f6368;
 | 
						|
    background-color: transparent;
 | 
						|
    border: none !important;
 | 
						|
    border-radius: 4px 4px 0 0;
 | 
						|
    transition: all 0.2s ease-in-out;
 | 
						|
    margin: 0 4px; // 增加标签间距
 | 
						|
    padding: 0 16px;
 | 
						|
 | 
						|
    .el-icon-close {
 | 
						|
      visibility: hidden; // 默认隐藏关闭按钮
 | 
						|
      width: 14px;
 | 
						|
      height: 14px;
 | 
						|
      font-size: 14px;
 | 
						|
      border-radius: 50%;
 | 
						|
      transition: all 0.2s;
 | 
						|
      &:hover {
 | 
						|
        background-color: #c0c4cc;
 | 
						|
        color: #fff;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    &:hover {
 | 
						|
      background-color: #f5f7fa;
 | 
						|
      color: #409eff;
 | 
						|
      .el-icon-close {
 | 
						|
        visibility: visible; // 悬停时显示
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  ::v-deep .el-tabs__item.is-active {
 | 
						|
    background-color: #f5f7fa !important; // 激活时增加背景色
 | 
						|
    color: #409eff !important;
 | 
						|
    position: relative;
 | 
						|
 | 
						|
    .el-icon-close {
 | 
						|
      visibility: visible; // 激活时也显示
 | 
						|
    }
 | 
						|
 | 
						|
    // 顶部指示器
 | 
						|
    &::before {
 | 
						|
      content: '';
 | 
						|
      position: absolute;
 | 
						|
      top: 0;
 | 
						|
      left: 50%;
 | 
						|
      transform: translateX(-50%);
 | 
						|
      width: 24px;
 | 
						|
      height: 2px;
 | 
						|
      background-color: #409eff;
 | 
						|
      border-radius: 0 0 2px 2px;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// 优化 el-card 样式
 | 
						|
.content-card {
 | 
						|
  border: none !important;
 | 
						|
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06) !important;
 | 
						|
  border-radius: 8px;
 | 
						|
}
 | 
						|
 | 
						|
// 优化过渡动画
 | 
						|
.fade-transform-leave-active,
 | 
						|
.fade-transform-enter-active {
 | 
						|
  transition: all .5s;
 | 
						|
}
 | 
						|
.fade-transform-enter {
 | 
						|
  opacity: 0;
 | 
						|
  transform: translateX(-30px);
 | 
						|
}
 | 
						|
.fade-transform-leave-to {
 | 
						|
  opacity: 0;
 | 
						|
  transform: translateX(30px);
 | 
						|
}
 | 
						|
</style>
 |