<template>
  <div
    :class="[
      'aside-menu',
      currentMenu === 'homePage' ||
      customSystemRouter.some((i) => i.path === currentMenu)
        ? 'menu-hide'
        : '',
      longMenu ? 'menu-long' : 'menu-short',
    ]"
  >
    <!--  侧边栏面板  -->
    <div class="sidebar-panel" @mouseleave="sidebarPanelLeave">
      <div class="sidebar-panel-header" @click="panelHeaderClick">
        <el-tooltip
          placement="right"
          trigger="hover"
          :disabled="longMenu"
          popper-class="menu-popover"
        >
          <span slot="content">展开面板</span>
          <i :class="['el-icon-s-unfold', 'show-icon']" />
        </el-tooltip>
        <div class="sidebar-panel-header-right">
          <div class="header-title" title="服务列表">服务列表</div>
          <i
            :class="[
              'el-icon-caret-right',
              'arrow-icon',
              isShowPopupList ? 'arrow-icon-open' : '',
            ]"
          />
        </div>
      </div>
      <p></p>
      <transition-group name="drag" class="sidebar-collection-service" tag="ul">
        <li
          :class="[
            'service-item',
            item.dragIconPress ? 'service-item-drag' : '',
            item.isDragEnter ? 'service-item-dragEd' : '',
            routerPath === item.routerPath ? 'service-item-active' : '',
          ]"
          v-for="(item, index) in swiftMenusData"
          :key="item.id"
          @click="menuClick(item)"
          :draggable="item.dragIconPress"
          @dragstart="dragstart($event, index)"
          @dragenter="dragenter($event, index, item)"
          @dragend="dragend($event, index, item)"
          @dragover="dragover($event, index, item)"
          @dragleave="dragleave($event, item, index)"
          @drop="item.isDragEnter = false"
        >
          <el-tooltip
            placement="right"
            trigger="hover"
            :disabled="longMenu"
            popper-class="menu-popover"
          >
            <span slot="content">{{ item.name }}</span>
            <div class="service-item-left">
              <svgIcon
                icon-style="icon header-icon"
                :icon-class="item.menuIcon ? item.menuIcon : ''"
              />
            </div>
          </el-tooltip>
          <div class="service-item-right" :title="item.name">
            <div class="service-item-title">{{ item.name }}</div>
            <div class="function-box">
              <i
                class="collect-icon"
                @click.stop="changeCollect(item, index)"
                title="取消收藏"
              />
              <i
                class="drag-icon"
                title="拖拽排序"
                @mousedown="(_) => (item.dragIconPress = true)"
              />
            </div>
          </div>
        </li>
      </transition-group>
    </div>
    <!--  弹出层菜单列表  -->
    <div
      :class="['service-popup', isShowPopupList ? 'service-popup-show' : '']"
    >
      <service-popup-list
        :swiftMenusData="swiftMenusData"
        :routerPath="routerPath"
        :isShowPopupList="isShowPopupList"
        :currentMenu="currentMenu"
        @close-popup="closeAll"
        @change-collect="(item) => changeCollect(item)"
      />
    </div>
    <!--  遮罩层  -->
    <div
      :class="[
        'aside-menu-modal',
        isShowPopupList ? 'aside-menu-modal-show' : '',
      ]"
      @click="closeAll"
    ></div>
  </div>
</template>
<script>
import {
  getSwiftMenus,
  removeSwiftMenus,
  saveMenus,
  updateSequence,
} from '@/api/publicLayout'
import customSystemRouter from '@/router/custom-system-router'
import ServicePopupList from '@/components/layout/SideMenu/components/ServicePopupList.vue'
import pubSub from 'pubsub-js'
import {mapState} from 'vuex'
import {findDataByField} from '@/utils/treeUtils'

export default {
  name: 'SideMenu',
  components: {ServicePopupList},
  props: {
    // 一级菜单别名
    currentMenu: {
      default: '',
      type: String,
    },
  },
  data() {
    return {
      showMenu: false,
      longMenu: false,
      isShowPopupList: false,
      swiftMenusData: [],
      dragIndex: '',
      enterIndex: '',
      customSystemRouter, // 自定义后台路由
      pubDirectory: null, // 目录点击pubSub实例
    }
  },
  computed: {
    routerPath() {
      return this.$route.path
    },
    ...mapState({
      // 重构菜单信息
      businessMenu(state) {
        return (
          state.menu.frontMenus.find((i) => i.alias === 'MasterDataSystem')
            ?.children || []
        )
      },
    }),
  },
  watch: {
    // 监听路由，如果为首页等非菜单页面，取消菜单选中项
    $route: {
      handler(to, from) {
        this.closeAll()

        // 获取一级菜单的别名
        const newCurrentMenu = to.path.split('/')[2] || ''
        const oldCurrentMenu = from?.path.split('/')[2] || ''

        if (newCurrentMenu) {
          // 当为初次刷新时或一级菜单切换时请求快捷菜单
          if (!oldCurrentMenu || newCurrentMenu !== oldCurrentMenu) {
            this.swiftMenusData = []
            // 递归菜单数据查询path
            const path = findDataByField(
              this.businessMenu,
              newCurrentMenu,
              'alias'
            )?.path
            path && this.getSwiftMenusData(path)
          }
        }
      },
      immediate: true,
    },
  },
  mounted() {
    //监听键盘按键事件
    this.$nextTick(() => document.addEventListener('keyup', this.escClose))

    //监听是否点击目录（二级菜单）
    this.pubDirectory = pubSub.subscribe('directory-click', (_) => {
      this.longMenu = true
      this.isShowPopupList = true
    })
  },
  methods: {
    /**
     * 获取快捷菜单数据
     * @param {String} [parentMenuPath] 一级菜单path
     * @return viod
     * */
    async getSwiftMenusData(parentMenuPath) {
      this.swiftMenusData = (await getSwiftMenus(parentMenuPath)).map((i) => ({
        ...i,
        routerPath: i.routerPath.replace('MasterDataSystem', '/platLayout'),
        dragIconPress: false,
        isDragEnter: false,
      }))
    },

    // 面板头部点击
    panelHeaderClick() {
      if (this.longMenu) {
        this.isShowPopupList = !this.isShowPopupList
      } else {
        this.longMenu = true
        this.isShowPopupList = true
      }
    },

    // 面板鼠标移出
    sidebarPanelLeave() {
      if (this.isShowPopupList) return
      this.longMenu = false
    },

    // 关闭面板和菜单弹层
    closeAll() {
      this.isShowPopupList = false
      this.longMenu = false
    },

    // 菜单点击
    menuClick(item) {
      this.closeAll()
      this.$router.push(item.routerPath)
    },

    /**
     * 收藏菜单改变
     * @param {Object} item 传入当前点击的对象
     * @param {Number} changeIndex 删除索引-1为新增，大于等于0为删除，不传则会判断改变类型
     * */
    async changeCollect(item, changeIndex = undefined) {
      if (typeof changeIndex === 'undefined') {
        changeIndex = this.swiftMenusData.findIndex(
          (i) => i.alias === item.alias
        )
      }
      if (changeIndex === -1) {
        this.swiftMenusData.push({
          ...item,
          dragIconPress: false,
          isDragEnter: false,
        })
        try {
          const {
            data: {state, value},
          } = await saveMenus(item.alias)
          if (!state) {
            this.swiftMenusData.splice(
              this.swiftMenusData.findIndex((i) => i.alias === value),
              1
            )
          }
        } catch ({data: {value}}) {
          this.swiftMenusData.splice(
            this.swiftMenusData.findIndex((i) => i.alias === value),
            1
          )
        }
      } else {
        const {
          data: {state},
        } = await removeSwiftMenus(item.alias)
        if (state) this.swiftMenusData.splice(changeIndex, 1)
      }
    },

    //  esc关闭
    escClose(e) {
      if (e.keyCode === 27) this.closeAll()
    },

    // 拖动开始
    dragstart(e, index) {
      this.enterIndex = index
      let img = new Image()
      img.src =
        "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' %3E%3Cpath /%3E%3C/svg%3E"
      e.dataTransfer.setDragImage(img, 0, 0)
    },

    // 记录移动到哪个盒子
    dragenter(e, index) {
      this.dragIndex = index
      e.preventDefault()
    },

    // 拖拽最终操作
    async dragend(e, index, item) {
      item.dragIconPress = false
      if (this.dragIndex !== index) {
        const {swiftMenusData: arr} = this
        const dragStartItem = arr[index]
        const dragenterItem = arr[this.dragIndex]
        /**
         *  @param {Object} changItem 交换位置的菜单对象
         * */
        const menuTransposition = (changItem) => {
          arr.splice(this.dragIndex, 1, ...arr.splice(index, 1, changItem))
        }
        menuTransposition(dragenterItem)
        try {
          const {
            data: {state},
          } = await updateSequence({
            [dragStartItem.swiftId]: this.dragIndex + 1,
            [dragenterItem.swiftId]: index + 1,
          })
          if (!state) menuTransposition(dragStartItem)
        } catch {
          menuTransposition(dragStartItem)
        }
      }
    },

    // 拖动事件（主要是为了拖动时鼠标光标不变为禁止）
    dragover(e, index, item) {
      if (this.enterIndex !== index) item.isDragEnter = true
      e.preventDefault()
    },

    dragleave(e, item, index) {
      if (this.enterIndex !== index) item.isDragEnter = false
    },
  },
  beforeDestroy() {
    window.removeEventListener('keyup', this.escClose)
    pubSub.unsubscribe(this.pubDirectory)
  },
}
</script>

<style lang="scss" scoped>
@import '@/assets/css/element-variables';

$font-color: $--menu-text;
$icon-color: $--menu-text;
$icon-color-hover: $--system-hover-active-text;
$menu-long-width: 250px;

.aside-menu {
  height: 100% !important;
  position: relative;
  transition: width 0.15s;
  width: 0;
  flex-shrink: 0;

  &.menu-long {
    width: $menu-long-width;

    .sidebar-panel {
      .sidebar-panel-header {
        .sidebar-panel-header-right {
          transition: opacity 0s;
        }
      }

      .sidebar-collection-service {
        .service-item {
          .service-item-right {
            transition: opacity 0s;
          }
        }
      }
    }
  }

  &.menu-short {
    width: 58px;

    .sidebar-panel {
      .sidebar-panel-header {
        .sidebar-panel-header-right {
          transition: opacity 1s;
          opacity: 0;
        }
      }

      .sidebar-collection-service {
        .service-item {
          .service-item-right {
            transition: opacity 1s;
            opacity: 0;
          }
        }
      }
    }
  }

  &.menu-hide {
    width: 0 !important;
    right: 2px;
  }

  .sidebar-panel {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
    z-index: 10;
    background-color: $--system-module-color1;
    background-image: url('~@/assets/img/publicLayout/menu-bg.png');
    background-repeat: no-repeat;
    background-position: 0 35vh;
    background-size: $menu-long-width calc(100% - 30vh);

    .sidebar-panel-header {
      width: $menu-long-width;
      display: flex;
      align-items: center;
      box-sizing: border-box;
      position: relative;
      white-space: nowrap;
      cursor: pointer;
      user-select: none;
      left: 0;
      top: 0;

      .show-icon {
        width: 58px;
        height: 58px;
        text-align: center;
        line-height: 58px;
        font-size: 28px;
        color: $icon-color;
      }

      .sidebar-panel-header-right {
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex: 1;
        padding-right: 20px;
        opacity: 1;

        .header-title {
          height: 20px;
          line-height: 20px;
          color: $font-color;
          font-size: 14px;
          font-family: Microsoft YaHei, serif;
        }

        .arrow-icon {
          color: $icon-color;
          font-size: 18px;
          transition: 0.15s;
          transform-origin: center;
          transform: rotateZ(180deg);

          &.arrow-icon-open {
            transition: 0.3s;
            transform-origin: center;
            transform: rotateZ(0deg);
          }
        }
      }
    }

    p {
      margin: 0 10px;
      bottom: 0;
      height: 1px;
      background: $--system-border-color2;
    }

    .sidebar-collection-service {
      width: $menu-long-width;
      position: relative;
      left: 0;
      top: 0;
      flex: 1;
      overflow-x: hidden;
      overflow-y: auto;

      .drag-move {
        transition: transform 1s;
      }

      &::-webkit-scrollbar {
        display: none;
      }

      .service-item {
        width: 100%;
        display: flex;
        align-items: center;
        transition: all 0.3s;
        cursor: pointer;
        user-select: none;
        border-bottom: 1px solid transparent;

        @mixin hover-dragEd {
          background: $--system-box-color3;

          .service-item-left {
            svg {
              color: $icon-color-hover;
            }
          }

          .service-item-right {
            .service-item-title {
              color: $icon-color-hover;
            }
          }
        }

        &:hover {
          @include hover-dragEd;

          .service-item-right {
            .function-box {
              opacity: 1;
            }
          }
        }

        &.service-item-active {
          @include hover-dragEd;
        }

        &.service-item-drag {
          opacity: 0.7;
        }

        &.service-item-dragEd {
          @include hover-dragEd;
          border-color: $icon-color-hover;
        }

        .service-item-left {
          display: flex;
          align-items: center;
          justify-content: center;
          width: 58px;
          height: 52px;
          flex-shrink: 0;

          svg {
            font-size: 28px;
            color: $icon-color;
            transition: all 0.3s;
          }
        }

        .service-item-right {
          display: flex;
          justify-content: space-between;
          align-items: center;
          flex: 1;
          padding-right: 10px;

          .service-item-title {
            width: 140px;
            height: 20px;
            line-height: 20px;
            color: $font-color;
            font-size: 14px;
            font-family: Microsoft YaHei, serif;
            transition: all 0.3s;
            text-overflow: ellipsis;
            overflow: hidden;
            word-break: break-all;
            white-space: nowrap;
          }

          .function-box {
            opacity: 0;
            transition: all 0.1s;
            display: flex;
            align-items: center;
            column-gap: 2px;

            .collect-icon {
              display: inline-block;
              width: 20px;
              height: 20px;
              background-image: url('~@/assets/img/publicLayout/collect2.png');
              background-repeat: no-repeat;
              background-position: 50% 50%;
              background-size: 75% 75%;
              transition: all 0.2s;

              &:hover {
                background: url('~@/assets/img/publicLayout/collect1.png')
                  no-repeat 50% 50%;
                background-size: 75% 75%;
              }
            }

            .drag-icon {
              display: inline-block;
              width: 20px;
              height: 20px;
              background: url('~@/assets/img/publicLayout/drag-icon.png')
                no-repeat 50% 50%;
              background-size: 85% 85%;
              transition: all 0.2s;
              cursor: move;
            }
          }
        }
      }
    }
  }

  .service-popup {
    position: absolute;
    width: 1000px;
    top: 0;
    height: 100%;
    background: #fff;
    box-shadow: 4px 0 10px 0 rgba(53, 152, 220, 0.1);
    z-index: 6;
    left: -1000px;
    transition: all 0.15s;

    &.service-popup-show {
      left: $menu-long-width;
      transition: all 0.3s;
    }

    &::before {
      content: '';
      background-color: mix($--color-black, $--system-border-color2, 10%);
      width: 1px;
      height: 100%;
      position: absolute;
      left: 0;
      top: 0;
    }

    &::after {
      content: '';
      background-color: mix($--color-black, $--system-border-color2, 5%);
      width: 1px;
      height: 100%;
      position: absolute;
      right: 0;
      top: 0;
    }
  }

  .aside-menu-modal {
    width: 100vw;
    height: 100%;
    margin-left: $menu-long-width;
    position: absolute;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 5;
    opacity: 0;
    transition: opacity 0.2s;
    pointer-events: none;

    &.aside-menu-modal-show {
      opacity: 1;
      pointer-events: auto;
    }
  }
}
</style>
