ContentLayout.vue 8.69 KB
<template>
  <el-container id="tabs-content-layout" class="content-layout">
    <el-header
      v-if="tabPaneList.length > 0 && !isShowTabs"
      class="content-layout__header"
    >
      <el-tabs v-model="activeName" @tab-click="handleTabClick">
        <el-tab-pane
          v-for="(pane, index) in tabPaneList"
          :key="index"
          :label="pane.label"
          :name="pane.name"
        ></el-tab-pane>
      </el-tabs>
      <ul
        v-if="contextMenuVisible"
        :style="{ left: left + 'px', top: '178px' }"
        class="context-menu"
      >
        <li
          class="context-menu-item copy-btn"
          :data-clipboard-text="winUrl"
          @click="copyCurrentUrl()"
        >
          <el-button type="text">复制当前链接</el-button>
        </li>
      </ul>
    </el-header>
    <el-container
      class="content-layout__container"
      :class="{ 'has-left-border': !showAside }"
    >
      <!-- TODO:领导已办流程分类未实现暂时不显示 -->
      <div
        v-if="isShowAside && activeName !== 'leaderDone'"
        :class="{ 'aside-wrap': showAside }"
      >
        <el-aside
          v-show="showAside"
          class="content-layout__aside"
          :class="{ 'is-show-aside': showAside }"
        >
          <process-classify
            :tab-active-name="activeName"
            @node-click="nodeClick"
          ></process-classify>
        </el-aside>
        <div
          class="navbar-collapse"
          :class="{ 'navbar-collapse-right': !showAside }"
          @click="showAside = !showAside"
        >
          <div class="navbar-collapse-bg">
            <div class="navbar-collapse-box">
              <i
                class="navbar-collapse-arrow"
                :class="{
                  'el-icon-arrow-left': showAside,
                  'el-icon-arrow-right': !showAside,
                }"
              ></i>
            </div>
          </div>
        </div>
      </div>
      <el-main class="content-layout__main">
        <slot></slot>
        <page-403 v-if="!checkPermission()" />
      </el-main>
    </el-container>
  </el-container>
</template>

<script>
  import screenfull from 'screenfull'
  import Clipboard from 'clipboard'
  import { mapGetters } from 'vuex'
  import ProcessClassify from '@/views/matter/components/ProcessClassify'
  import Page403 from '@/views/page403'
  export default {
    name: 'ContentLayout',
    components: {
      ProcessClassify,
      Page403,
    },
    props: {
      tabPaneList: {
        type: Array,
        default: () => {
          return []
        },
      },
      defaultExpandOrCollapse: {
        type: Boolean,
        default: false,
      },
      currentActiveName: {
        type: String,
        default: '',
      },
      isShowAside: {
        type: Boolean,
        default: true,
      },
    },
    data() {
      return {
        activeName: '',
        showAside: false,
        winUrl: '',
        contextMenuVisible: false,
        left: 0,
        top: 0,
      }
    },
    computed: {
      tabActiveName() {
        return (
          this.$route.query.tabActiveName ||
          this.tabPaneList[0]?.name ||
          this.currentActiveName
        )
      },
      currentShowAside() {
        const isExpand = localStorage.getItem(`${this.tabActiveName}AsideShow`)
        return isExpand === true || isExpand === 'true'
      },
      isShowTabs() {
        return (
          this.$store.getters['routes/fullScreenState'] &&
          this.$route.query.tabActiveName
        )
      },
    },
    watch: {
      contextMenuVisible() {
        if (this.contextMenuVisible) {
          document.body.addEventListener('click', this.closeContextMenu)
        } else {
          document.body.removeEventListener('click', this.closeContextMenu)
        }
      },
      activeName() {
        this.handlerWinUrl()
      },
    },
    activated() {
      this.activeName = this.tabActiveName
    },
    created() {
      this.activeName = this.tabActiveName
      this.showAside = this.currentShowAside
    },
    mounted() {
      this.bindRightClickMenu()
    },
    methods: {
      checkPermission() {
        if (this.tabPaneList.length <= 0) {
          return true
        }
        const tabs = this.tabPaneList.filter((p) => p.name == this.activeName)
        return tabs.length > 0
      },
      handleTabClick(tab) {
        this.$emit('tab-click', tab, this.activeName)
      },
      nodeClick(node) {
        this.$emit('node-click', node)
      },
      closeContextMenu() {
        this.contextMenuVisible = false
      },
      bindRightClickMenu() {
        const tabsDom = document.getElementById('tabs-content-layout')
        let tabsHeaderDom = tabsDom.getElementsByClassName(
          'el-tabs__header is-top'
        )
        if (tabsHeaderDom && tabsHeaderDom[0]) {
          tabsHeaderDom[0].oncontextmenu = this.handleClickContextMenu
        }
      },
      handleClickContextMenu(e) {
        e.preventDefault()

        let curName = e.target.id.split('-')[1]

        if (e.srcElement.id && this.activeName == curName) {
          this.contextMenuVisible = true
          this.left = e.clientX - 24
          this.top = e.clientY - 10

          this.contextMenuVisible = true
        }
      },
      copyCurrentUrl() {
        this.contextMenuVisible = false
        this.handlerWinUrl()
        let clipboard = new Clipboard('.copy-btn')
        clipboard.on('success', (e) => {
          clipboard.destroy()
        })
        clipboard.on('error', () => {
          clipboard.destroy()
        })
      },
      handlerWinUrl() {
        let url = window.location.href
        if (url.includes('?')) {
          url = `${url}&__isFull__=true&tabActiveName=${this.activeName}`
        } else {
          url = `${url}?__isFull__=true&tabActiveName=${this.activeName}`
        }
        this.winUrl = url
      },
    },
  }
</script>

<style lang="scss" scoped>
  @mixin background-color {
    background-color: $base-color-white;
  }
  .content-layout {
    height: 100%;
    position: relative;
    .content-layout__header {
      height: $base-tabs-bar-height !important;
      padding: 0 $base-content-margin;
      @include background-color;
      ::v-deep {
        .el-tabs__header {
          height: $base-tabs-bar-height;
          line-height: $base-tabs-bar-height;
        }
        .el-tabs__nav-wrap {
          &::after {
            height: 0;
          }
          .el-tabs__active-bar {
            bottom: 2px;
          }
        }
      }
    }
    .content-layout__container {
      // height: calc(100% - 48px);
      height: calc(100% - 1px);
      position: relative;
      border-top: 1px solid $base-content-border-color;
      .aside-wrap {
        border-right: 1px solid $base-content-border-color;
        @include background-color;
      }
      .content-layout__aside {
        width: 0 !important;
        height: 100%;
      }
      .is-show-aside {
        width: $base-process-classify-width !important;
      }
      .navbar-collapse {
        position: absolute;
        top: 50%;
        transform: translate(0, -50%);
        left: $base-process-classify-width;
        cursor: pointer;
        .navbar-collapse-bg {
          background: $base-content-border-color;
          border-right: 1px solid $base-content-border-color;
          clip-path: polygon(0 0, 16px 10px, 56px 16px, 0 56px);
          line-height: 56px;
          .navbar-collapse-box {
            background: #f9f9f9;
            clip-path: polygon(0px 1px, 15px 11px, 55px 15px, -1px 55px);
          }
          .navbar-collapse-arrow {
            color: $base-dark-title-color;
          }
        }
      }
      .navbar-collapse-right {
        left: -1px;
      }
      .content-layout__main {
        overflow: hidden;
        height: 100%;
        @include background-color;
        padding: 20px 24px 0 24px;
        ::v-deep {
          .pagination-panel {
            padding: 24px 0 0 0;
          }
        }
      }
    }
    .has-left-border {
      border-left: 1px solid #e6e6e6;
    }
    .context-menu {
      width: 122px;
      background: $base-color-white;
      position: fixed;
      z-index: 99;
      padding: 4px 0;
      border-radius: 2px;
      box-shadow: 0px 1px 6px rgba(91, 91, 91, 0.15);
      text-align: center;
      .context-menu-item {
        ::v-deep {
          .el-button--text {
            color: $base-color-second-color;
            font-size: 14px;
            padding: 6px 10px;
            &:hover {
              color: var(--themeColor);
              background: #f9f9f9;
            }
          }
          .is-disabled {
            color: #ccc;
            &:hover {
              color: #ccc;
              background: $base-color-white;
            }
          }
        }
      }
    }
  }
</style>