<template>
  <div>
    <transition-group class="p-tabs" name="tab" tag="div" ref="ptab">
      <div
        class="tab-item"
        v-for="(item, index) in list"
        :key="item.name + item.rountPath || item.jspUrl"
        :class="{
          'tab-item-active':
            (item.rountPath == undefined
              ? item.jspUrl
              : item.rountPath) == getDefaultActive,
        }"
        @click="handleClick($event, item, index)"
        @contextmenu.prevent="clickright($event, item, index)"
      >
        <!-- <div class="tab-item-shap"></div> -->
        <el-tooltip
          placement="bottom"
          effect="dark"
          :content="item.name || item.functionName"
          :visible-arrow="false"
          :open-delay="1000"
        >
          <div class="text">
            {{ item.name || item.functionName }}
          </div>
        </el-tooltip>
        <i
          class="el-icon-error close"
          @click="handleClose($event, item, index)"
        ></i>
      </div>
    </transition-group>
    <div class="rightCbox" :style="cbox" v-if="rcbStatus">
      <el-card shadow="always">
        <span @click="closetab(1)">关闭其它所有标签</span>
        <span @click="closetab(2)">关闭左侧所有标签</span>
        <span @click="closetab(3)">关闭右侧所有标签</span>
      </el-card>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    list: {
      required: false,
      type: Array,
      default() {
        return [];
      },
    },
  },
  data() {
    return {
      isDrag: false,
      moveX: 0,
      touchX: 0,
      lastTouchX: 0,
      eachWidth: 0,
      offsetWidth: 0,
      scrollWidth: 0,
      mouseDownTime: 0,
      canClick: true,
      scrolling: false,
      cbox: {
        top: 0,
        left: 0,
      },
      rcbStatus: false,
      tabsobj: {},
    };
  },
  computed: {
    getDefaultActive() {
      return this.$store.state.defaultActive;
    },
  },
  mounted() {
    this.initData();
    this.$nextTick(() => {
      document.querySelector("body").addEventListener("click", this.closetab);
    });
  },
  watch: {
    /**
     * 监听默认选中对象值的变化，当菜单切换时自动滚动到指定tab
     * @param {Object} v
     */
    getDefaultActive(v) {
      for (let i = 0; i < this.list.length; i++) {
        if (this.list[i].rountPath == v) {
          this.scrollTo(i);
        }
      }
    },
  },
  updated() {
    this.initData();
  },
  methods: {
    initData() {
      if (this.list.length > 0) {
        this.eachWidth = this.$refs.ptab.$el.children[0].offsetWidth;
        this.offsetWidth = this.$refs.ptab.$el.offsetWidth;
        this.scrollWidth = this.$refs.ptab.$el.scrollWidth;
        let _this = this;
        this.$refs.ptab.$el.onmousedown = (e) => {
          _this.mouseDown(e);
        };
        this.$refs.ptab.$el.onmousemove = (e) => {
          _this.mouseMove(e);
        };
        this.$refs.ptab.$el.onmouseup = (e) => {
          _this.mouseUp(e);
        };
        this.$refs.ptab.$el.onmouseout = (e) => {
          _this.mouseUp(e);
        };
      }
    },
    /**
     * 删除tab元素触发关闭页面的逻辑
     * @param {Object} e 事件对象
     * @param {Object} item 当前点击的tab元素数据
     * @param {Object} index 当前tab的下标
     */
    handleClose(e, item, index) {
      this.$store.commit(
        "removePagesByName",
        (item.rountPath == undefined ? item.jspUrl : item.rountPath).replace(
          "/",
          ""
        )
      );
      e.preventDefault();
      e.stopPropagation();
      let list = [...this.list];
      if (list.length > 1) {
        if (
          (item.rountPath == undefined ? item.jspUrl : item.rountPath) !=
          this.getDefaultActive
        ) {
          list.splice(index, 1);
          this.$store.commit("setTabList", list);
        } else {
          if (list[index - 1]) {
            let rountPath = list[index - 1].hasOwnProperty("rountPath")
              ? list[index - 1].rountPath
              : list[index - 1].jspUrl;
            this.$store.commit("setDefaultActive", rountPath);
            list.splice(index, 1);
            this.$store.commit("setTabList", list);
            this.$router.push(rountPath);
          } else if (list[index + 1]) {
            let rountPath = list[index + 1].hasOwnProperty("rountPath")
              ? list[index + 1].rountPath
              : list[index + 1].jspUrl;
            this.$store.commit("setDefaultActive", rountPath);
            list.splice(index, 1);
            this.$store.commit("setTabList", list);
            this.$router.push(rountPath);
          } else {
            list.splice(index, 1);
            this.$store.commit("setTabList", list);
            this.$router.push("/");
          }
        }
      }
    },
    /**
     * 点击tab触发的事件
     * @param {Object} item 事件对象
     * @param {Object} index 点击的tab对象的下标
     */
    handleClick(e, item, index) {
      e.preventDefault();
      if (this.canClick) {
        let clickTime = new Date().getTime();
        if (clickTime - this.mouseDownTime < 500) {
          if (item.rountPath != undefined) {
            if (this.getDefaultActive != item.rountPath) {
              this.$store.commit("setDefaultActive", item.rountPath);
              this.scrollTo(index);
              this.$router.push(item.rountPath);
            }
          } else {
            if (this.getDefaultActive != item.jspUrl) {
              this.$store.commit("setDefaultActive", item.jspUrl);
              this.scrollTo(index);
              this.$router.push(item.jspUrl);
            }
          }
        }
      }
      this.canClick = true;
    },
    /**
     * 自动滚动到指定下标的tab对象
     * @param {Object} index 目标对象的下标
     * @param {Object} callback 滚动完毕触发的回调
     */
    scrollTo(index, callback) {
      let _from = Math.abs(this.lastTouchX);
      let _this = this;
      if (this.scrolling == false) {
        if (this.isDrag == false) {
          if (this.offsetWidth < this.scrollWidth) {
            let to = Math.abs(index * (this.eachWidth + 20));
            let interval = (to - _from) / 20;
            let grow = false;
            if (to > _from) {
              grow = true;
            } else {
              grow = false;
            }
            let runScroll = () => {
              let rn = setTimeout(() => {
                _this.$refs.ptab.$el.scrollLeft = _from;
                _this.lastTouchX = _from * -1;
                _from += interval;
                if (grow) {
                  if (_from < to) {
                    runScroll();
                    return;
                  } else {
                    _from = to;
                    this.scrolling = false;
                    if (callback) {
                      callback();
                    }
                  }
                } else {
                  if (_from > to) {
                    runScroll();
                    return;
                  } else {
                    _from = to;
                    this.scrolling = false;
                    if (callback) {
                      callback();
                    }
                  }
                }
                _this.$refs.ptab.$el.scrollLeft = _from;
                _this.lastTouchX = _from * -1;
                clearTimeout(rn);
              }, 16);
            };
            this.scrolling = true;
            runScroll();
          }
        }
      }
    },
    mouseDown(e) {
      this.touchX = e.clientX;
      this.isDrag = true;
      this.mouseDownTime = new Date().getTime();
    },
    mouseMove(e) {
      if (this.isDrag && this.offsetWidth < this.scrollWidth) {
        this.moveX = e.clientX;
        let scrollLeft = this.moveX - this.touchX + this.lastTouchX;
        this.$refs.ptab.$el.scrollLeft = scrollLeft * -1;
        this.canClick = false;
      } else {
        this.moveX = 0;
        this.touchX = 0;
      }
    },
    mouseUp() {
      this.isDrag = false;
      if (this.moveX == 0) {
        this.touchX = 0;
      }
      this.lastTouchX = this.moveX - this.touchX + this.lastTouchX;
      if (this.lastTouchX <= this.offsetWidth - this.scrollWidth) {
        this.lastTouchX = this.offsetWidth - this.scrollWidth;
      }
      if (this.lastTouchX >= 0) {
        this.lastTouchX = 0;
      }
    },
    clickright(event, item, index) {
      this.tabsobj = item;
      this.rcbStatus = true;
      if (event.clientX + 200 > document.body.clientWidth) {
        this.cbox.left = event.clientX - 168 + "px";
      } else {
        this.cbox.left = event.clientX + "px";
      }
      this.cbox.top = event.clientY + "px";
    },
    closetab(v) {
      if (this.rcbStatus) {
        this.rcbStatus = false;
        let list = [];
        if (v == 1) {
          list.push(this.tabsobj);
          this.$store.commit("setTabList", list);
          this.$router.push(this.tabsobj.rountPath);
        } else if (v == 2) {
          for (let i = 0; i < this.$store.state.tabList.length; i++) {
            if (
              this.$store.state.tabList[i].name == this.tabsobj.name ||
              list.length > 0
            ) {
              list.push(this.$store.state.tabList[i]);
            }
          }
          this.$store.commit("setTabList", list);
          this.$router.push(this.tabsobj.rountPath);
        } else if (v == 3) {
          for (let i = 0; i < this.$store.state.tabList.length; i++) {
            list.push(this.$store.state.tabList[i]);
            if (this.$store.state.tabList[i].name == this.tabsobj.name) {
              this.$store.commit("setTabList", list);
              this.$router.push(this.tabsobj.rountPath);
              return;
            }
          }
        }
      }
    },
  },
};
</script>

<style scoped="scoped" lang="scss">
.rightCbox {
  position: absolute;
  z-index: 1000;

  .el-card__body {
    padding: 0 !important;
  }

  span {
    display: block;
    padding: 5px 10px;
  }

  span:hover {
    color: #409eff;
    background: #f4f4f4;
    cursor: pointer;
  }
}

.tab-move {
  transition: 0.5s;
}

.tab-enter-active {
  opacity: 1;
  transition: 0.5s;
  position: absolute;
}

.tab-leave-active {
  opacity: 0;
  transition: 0.5s;
  position: absolute !important;
}

.tab-leave {
  opacity: 1;
}

.tab-enter {
  opacity: 0;
}

.p-tabs {
  box-sizing: border-box;
  width: 100%;
  height: 38px;
  white-space: nowrap;
  overflow: hidden;
  margin-top: 15px;

  // padding-left: 40px;
  .tab-item {
    display: inline-block;
    height: 38px;
    line-height: 38px;
    color: black;
    position: relative;
    width: 134px;
    overflow: hidden;
    border-radius: 0px 5px 0px 0px;
    margin-left: 15px;
    cursor: pointer;

    .tab-item-shap {
      position: absolute;
      width: 100%;
      height: 38px;
      transition: 0.3s;
      background: rgba(255, 255, 255, 0.4);
      border-radius: 5px 5px 0px 0px;
      transform: skew(-30deg);
      left: 20px;
    }

    .text {
      text-align: center;
      overflow-x: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      // padding: 0px 16px;
      font-size: 14px;
      letter-spacing: 0;
      position: absolute;
      width: 100%;
      height: 38px;
      text-align: center;
      background-color: white;
    }

    .close {
      font-size: 12px;
      position: absolute;
      right: 3px;
      top: 3px;
      color: #fff;
    }

    .close:hover {
      color: #107cff;
    }
  }

  .tab-item:hover {
    .tab-item-shap {
      background: rgba(255, 255, 255, 0.7);
    }
  }

  .tab-item-active {
    .skew {
      background: #fff;
    }

    .tab-item-shap {
      background: #fff;
      font-family: PingFangSC-Regular;
      font-size: 14px;
      letter-spacing: 0;
    }

    .text {
      text-align: center;
      overflow-x: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      // padding: 0px 16px;
      color: #107cff;
    }

    .close {
      color: #107cff;
    }
  }

  .tab-item-active:hover {
    .tab-item-shap {
      background: rgba(255, 255, 255, 1);
    }
  }
}
</style>
