App.vue 9.39 KB
<template>
  <div id="app" style="--leftBarTop:4px;">
    <el-container class="is-vertical fullheight">
      <template v-if="$route.meta.isRoute && !$route.meta.single">
        <Navigator :menuShow.sync="menuShow" />
        <el-container
          style="overflow-x: hidden;overflow-y: hidden;position: relative;"
        >
          <Menu
            @menuChange="handleMenuChange"
            :menuShow="menuShow"
            @cliceCommon="isShowMask = true"
            @is-collapse="getIsCollapse"
          />
          <div
            :class="{
              showMask: isShowMask,
              hideMask: !isShowMask,
              'is-collapse': isCollapse
            }"
            @click="handleMask"
          >
            <div class="commonList">
              <div class="commonList-header">
                <span>常用菜单</span>
                <i class="el-icon-close" @click="isShowMask = false"></i>
              </div>
              <div
                class="commonList-item"
                v-for="item in commonList"
                :key="item.menuId"
                @click="goToMenu(item)"
              >
                <span>{{ item.name }}</span>
                <i
                  class="icon-collect"
                  style="color:#FFCA28;font-size:18px"
                  @click="removeBmk(item)"
                ></i>
              </div>
              <div class="noCollection" v-if="!commonList.length">
                <img src="./assets/img/NoCollection.png" alt="" />
                <div class="text">暂无常用菜单~</div>
              </div>
            </div>
          </div>
          <el-main
            class="app-main"
            :class="{'no-margin': $route.meta.noMargin}"
          >
            <!-- <el-card
              class="app-box__card"
              :class="{'box-card-noheader': !showHeader}"
              shadow="never"
            > -->
            <!-- <div
                v-if="showHeader && !$route.meta.isHome"
                slot="header"
                class="clearfix"
              > -->
            <!-- <el-breadcrumb separator="/">
                  <el-breadcrumb-item :to="{path: '/'}"
                    >首页</el-breadcrumb-item
                  >
                  <el-breadcrumb-item>{{
                    currentMenuLabel
                  }}</el-breadcrumb-item>
                </el-breadcrumb> -->
            <!-- </div> -->
            <keep-alive v-if="$route.meta.keepAlive">
              <router-view
                class="fullheight"
                @menuChange="handleMenuChange"
              ></router-view>
            </keep-alive>
            <router-view
              class="fullheight"
              v-else
              @menuChange="handleMenuChange"
            ></router-view>
            <!-- </el-card> -->
          </el-main>
        </el-container>
      </template>
      <router-view v-if="$route.meta.isRoute && $route.meta.single" />
    </el-container>

    <AppCenterImportDialog ></AppCenterImportDialog>
  </div>
</template>
<script>
import Navigator from '@/views/Navigator.vue'
import Menu from '@/views/Menu.vue'
import menu from '@/api/menu.js'
import {mapState} from 'vuex'
import utils from '@/hotent-ui-util.js'
import AppCenterImportDialog from '@/views/portal/AppCenterImportDialog.vue'
export default {
  name: 'app',
  components: {Navigator, Menu, AppCenterImportDialog},
  data() {
    return {
      showHeader: true,
      currentMenuLabel: '',
      menuShow: true,
      isShowMask: false,
      commonList: [],
      isCollapse: false
    }
  },
  mounted() {
    // 因为resize事件在整个项目中只能监听一次,所以这里通过全局广播发送这个事件
    window.onresize = () => {
      this.$root.$emit('resize')
    }
    menu.getMenuByAlias(this.$route.name, m => {
      if (m) {
        this.$emit('menuChange', m)
      }
    })
    this.$root.$on('menuBookmarkChange', () => {
      this.initCollectMenuKey()
    })
  },
  methods: {
    getIsCollapse(val) {
      this.isCollapse = val
    },
    doRemoveBmk(data) {
      let menuIds = []
      let gatherFun = function(data) {
        if (!data) {
          return
        }
        if (data.value) {
          menuIds.push(data.value)
        }
        if (data.children && data.children.length > 0) {
          data.children.forEach(child => {
            gatherFun.call(null, child)
          })
        }
      }
      gatherFun.call(null, data)
      this.$store.dispatch('menu/removeMenuBookmark', menuIds).then(() => {
        this.commonList = this.commonList.filter(
          item => item.menuId != data.value
        )
        this.$message.success('删除成功')
        this.$root.$emit('menuBookmarkChange')
      })
    },
    // 取消收藏
    removeBmk(node) {
      node.data = {value: node.menuId || node.id, name: node.name}
      window.event.stopPropagation()
      this.$confirm('该菜单被收藏,是否确认删除?', '提示', {})
        .then(() => {
          this.doRemoveBmk(node.data)
        })
        .catch(() => {})
    },
    getMenuByMenuId(menuId) {
      let innerFun = menus => {
        if (!menus || menus.length == 0) {
          return
        }
        for (let i = 0; i < menus.length; i++) {
          if (menus[i].id === menuId) {
            return menus[i]
          }
          let menu = innerFun(menus[i].children)
          if (menu) {
            return menu
          }
        }
      }
      return innerFun(this.menus)
    },
    // 点击常用菜单里的菜单
    goToMenu(item) {
      let menuId = item.menuId || item.id
      //获取菜单路径
      let menu = this.getMenuByMenuId(menuId)
      if (menu && menu.href) {
        //跳转
        this.$router.push('/' + menu.alias)
        return
      }
      if (menu && menu.path) {
        if (menu.path.split('.').length == 5) {
          //二级菜单,如数据应用、图标应用
          this.$router.push('/' + menu.alias)
        } else if (menu.path.split('.').length == 6) {
          //三级菜单,如PC表单设计
          let parentMenu = this.getMenuByMenuId(menu.parentId)
          this.$router.push('/' + parentMenu.alias + '#' + menu.alias)
        }
      }
      this.isShowMask = false
    },
    // 点击遮罩层
    handleMask(e) {
      if (e.target._prevClass === 'showMask') {
        this.isShowMask = false
      }
    },
    handleMenuChange: function(menu) {
      if (this.isShowMask) {
        this.isShowMask = false
      }
      this.currentMenuLabel = menu.name
      this.showHeader = !(menu.children && menu.children.length > 0)
    },
    initCollectMenuKey() {
      let obj = JSON.parse(sessionStorage.getItem('currentMenuBookmark'))
      this.commonList = []
      for (const key in obj) {
        this.commonList.push(obj[key])
      }
      const menuList = utils.nest2tile(this.menus)
      const collectMenuKey = this.commonList.map(item => item.alias)
      this.commonList = menuList.filter(it => collectMenuKey.includes(it.alias))
    }
  },
  watch: {
    isShowMask(val) {
      if (val) {
        this.initCollectMenuKey()
      }
    }
  },
  computed: {
    ...mapState({
      menus: state => state.menu.menus,
      dialogVisible: state => state.user.dialogVisible
    })
  }
}
</script>
<style lang="scss" scoped>
#app {
  background: #f5f5f5;
}
.app-main {
  margin: 24px;
  padding: 0;
  overflow: hidden;
  background: #fff;
}
.no-margin {
  margin: 0;
}
.el-main > .el-card {
  border-radius: 0;
}

.app-box__card {
  height: calc(100% - 3px);
}

::v-deep {
  .app-box__card {
    .el-card__header {
      padding: 12px 20px;
      margin-bottom: 10px;
    }
    .el-card__body {
      height: calc(100% - 55px);
      padding: 0;
    }
  }
}

.box-card-noheader /deep/ > .el-card__body {
  height: calc(100% - 5px) !important;
}

>>> .el-tree--highlight-current
  .el-tree-node.is-current
  > .el-tree-node__content {
  background-color: rgba(155, 194, 230, 0.2) !important;
}
.hideMask {
  display: none;
  transform: 0.5s;
}
.showMask {
  display: block;
  width: 100%;
  height: 100%;
  position: absolute;
  right: 0;
  background-color: #00000054;
  z-index: 10;
  .commonList {
    position: absolute;
    left: 210px;
    top: 0;
    width: 180px;
    height: 100%;
    background-color: #fff;
    box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
    overflow-y: auto;
    .commonList-header {
      width: 100%;
      height: 56px;
      background-color: #fff;
      line-height: 56px;
      font-size: 16px;
      font-family: Source Han Sans SC;
      font-weight: bold;
      color: #222222;
      padding: 0 24px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 8px;
      box-sizing: border-box;
      i {
        font-size: 12px;
        &:hover {
          font-weight: 700;
          cursor: pointer;
        }
      }
    }
    .commonList-item {
      width: 100%;
      height: 40px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0px 20px 0px 32px;
      box-sizing: border-box;
      cursor: pointer;
      &:hover {
        background-color: #f0f8ff;
      }
    }
    .noCollection {
      margin: 120px 31px 0px;
      .text {
        // width: 92px;
        height: 20px;
        font-size: 14px;
        font-family: Source Han Sans SC;
        font-weight: 400;
        line-height: 22px;
        color: #999999;
        text-align: center;
      }
    }
  }
}
.is-collapse {
  .commonList {
    left: 64px;
  }
}
</style>