<template>
  <div v-if="multiPage" class="app-tabs-view">
    <div :class="['tabs-head', layout, pageWidth]">
      <a-tabs
        type="editable-card"
        :class="[
          'tabs-container',
          layout,
          pageWidth,
          {
            affixed: affixed,
            'fixed-header': fixedHeader,
            collapsed: defaultLayout.collapsed,
          },
        ]"
        :active-key="active"
        :hide-add="true"
        :style="tabsContainerStyle"
      >
        <!-- 锁定按钮 -->
        <a-tooltip
          slot="tabBarExtraContent"
          placement="left"
          :title="lockTitle"
        >
          <a-icon
            theme="filled"
            class="header-lock"
            :type="fixedTabs ? 'lock' : 'unlock'"
            @click="onLockClick"
          />
        </a-tooltip>
        <a-tab-pane v-for="(route, index) in visitedViews" :key="route.path">
          <div
            slot="tab"
            class="tab"
            :class="{
              tabFault: activeIndex != index && activeIndex != index + 1,
            }"
            @contextmenu="(e) => onContextmenu(route, e)"
          >
            <!-- 标签卡 -->
            <div class="title" @click="() => goRoute(route)">
              {{ getTabName(route.meta) }}
            </div>
            <!-- 关闭按钮 -->
            <a-icon
              v-if="!route.meta.affix"
              class="icon-close"
              type="close"
              @click="() => closeOne(route, index)"
            />
            <div
              v-show="activeIndex != index && activeIndex != index + 1"
              class="tabs-line"
            ></div>
          </div>
        </a-tab-pane>
      </a-tabs>
      <!-- <div v-if="affixed" class="virtual-tabs"></div> -->
    </div>

    <a-menu
      v-show="visible"
      class="contextmenu"
      :style="style"
      @click="contextmenuClick"
    >
      <a-menu-item
        v-for="item in contextmenuList"
        :key="item.key"
        :style="{ borderTop: item.key === '5' ? 'solid 1px #eef1f4' : 'none' }"
      >
        <Icon :type="item.icon" :size="16" style="color: #005087" />
        <span>{{ item.text }}</span>
      </a-menu-item>
    </a-menu>
  </div>
</template>

<script>
import { mapState, mapMutations, mapActions } from "vuex";
import { Icon } from "@mega-design/ui-vue";
import { staticRoutes, generateTabName } from "@/plugins/generateRouter";
import ApiConstant from "@/api/ApiConstant";

export default {
  name: "TabsView",
  components: { Icon },
  inject: ["defaultLayout"],
  data() {
    return {
      activeIndex: -1,
      visible: false,
      left: 0,
      top: 0,
      targetRouter: null,
      affixed: false,
      rect: null,
    };
  },
  computed: {
    ...mapState("setting", [
      "layout",
      "pageWidth",
      "fixedHeader",
      "fixedTabs",
      "multiPage",
    ]),
    ...mapState("tagsView", ["visitedViews", "cachedViews"]),
    ...mapState({
      systemConfig: (state) => state.app.systemConfig,
      locale: (state) => state.app.locale,
    }),
    // 锁定tabs区域
    lockTitle() {
      return this.$t(
        this.fixedTabs ? "CLICK_TO_UNLOCK" : "CLICK_TO_LOCK_THE_TABS_HEAD"
      );
    },
    // tabs 选中菜单的 key
    active() {
      const { path } = this.$route;
      return path.endsWith("/") && path !== "/"
        ? path.substring(0, path.length - 1)
        : path;
    },
    style() {
      return {
        left: `${this.left}px`,
        top: `${this.top}px`,
      };
    },
    contextmenuList() {
      return [
        {
          key: "1",
          icon: "icon-dir-f-vertical-right",
          text: this.$t("CLOSE_LEFT"),
        },
        {
          key: "2",
          icon: "icon-dir-f-vertical-left",
          text: this.$t("CLOSE_RIGHT"),
        },
        {
          key: "3",
          icon: "icon-ins-close-circle",
          text: this.$t("CLOSE_OTHERS"),
        },
        { key: "4", icon: "icon-ins-close", text: this.$t("CLOSE_ALL") },
        {
          key: "5",
          icon: "icon-dir-f-fullscreen",
          text: this.$t("FULL_SCREEN"),
        },
        { key: "6", icon: "icon-cur-reload", text: this.$t("REFRESH") },
        // {
        //   key: "7",
        //   icon: "icon-xinchuangkoudakai",
        //   text: this.$t("NEW_WINDOW"),
        // },
      ];
    },
    tabsContainerStyle() {
      const style = {};
      if (this.affixed) {
        style.left = this.defaultLayout.sideMenuWidth;
        if (this.defaultLayout.collapsed) {
          style.left = 0;
        }
      }
      return style;
    },
  },
  watch: {
    $route() {
      this.addTags();
      this.setActivated(this.$route);
    },
    active(newValue, oldValue) {
      this.activeIndex = this.visitedViews.findIndex(
        (item) => item.path === newValue
      );
    },
  },
  created() {
    this.affixed = this.fixedTabs;
    const { path } = this.$route;
    this.activeIndex = this.visitedViews.findIndex(
      (item) => item.path === path
    );
    this.initTags();
    this.addTags();
    this.setActivated(this.$route);
    this.$nextTick(() => {
      this.$EventBus.$on("nextRefresh", () => {
        this.visitedViews.forEach((item) => {
          if (item.path === this.$nuxt._route.path) {
            this.targetRouter = item;
            this.refresh();
          }
        });
      });
    });
  },
  mounted() {
    window.addEventListener("click", this.closeContextmenu);
    window.addEventListener("contextmenu", this.setPosition);
  },
  beforeDestroy() {
    window.removeEventListener("click", this.closeContextmenu);
    window.removeEventListener("contextmenu", this.setPosition);
  },
  methods: {
    ...mapMutations("setting", ["setFixedTabs"]),
    getTabName(meta) {
      return (
        generateTabName(
          this.systemConfig.MENU_SUFFIX,
          meta,
          this.$i18n,
          this.locale
        ) || "no-name"
      );
    },
    // 锁定tab区
    onLockClick() {
      this.setFixedTabs(!this.fixedTabs);
      if (this.fixedTabs) {
        setTimeout(() => {
          this.affixed = true;
        }, 200);
      } else {
        this.affixed = false;
      }
    },
    // 判断tableau刷新
    judgeJumperMethod(route, callback) {
      const search = route.fullPath?.substring(
        route.fullPath?.indexOf("?") || 0
      );
      const query = search
        ?.substring(1)
        ?.split("&")
        ?.reduce((res, item) => {
          const [key, value] = item?.split("=") || [];
          if (res[key]) {
            res[key] = [res[key], value];
          } else {
            res[key] = value;
          }
          return res;
        }, {});
      if (query?.isBiFrame === "Y") {
        this.$axios
          .get(
            `${ApiConstant.PREFIX_CORE}/api/report/report-server/get-out-link-url?menuId=${query.key}`
          )
          .then((res) => {
            const biPath = res.data.data.url?.endsWith("/")
              ? (res?.data?.data?.url ?? "").substr(
                  0,
                  (res?.data?.data?.url?.length ?? 1) - 1
                )
              : res.data.data.url;
            try {
              let menuPath = decodeURIComponent(query.menuPath);
              menuPath = menuPath?.startsWith("/")
                ? menuPath.substr(1, menuPath?.length)
                : menuPath;
              menuPath = menuPath?.endsWith("/")
                ? menuPath.substr(0, (menuPath?.length ?? 1) - 1)
                : menuPath;
              const token = this.$auth?.getToken("local")?.substr(7) || "";
              const toParams = `ticket=${token}&type=external`;
              const { search: toSearch } = new URL(`${biPath}/${menuPath}`);
              this.$router.push({
                path: `/external-view/${query.key}`,
                query: {
                  ...query,
                  url: toSearch
                    ? `${biPath}/${menuPath}&${toParams}`
                    : `${biPath}/${menuPath}?${toParams}`,
                },
              });
            } catch (_err) {}
          });
      } else {
        const path = route.fullPath || route.path;
        callback(path);
      }
    },
    // 跳转页面
    goRoute(route) {
      this.setActivated(route);
      this.targetRouter = route;
      this.refresh();
      this.judgeJumperMethod(route, (toPath) => {
        this.$router.push(toPath);
      });
    },
    // 设置模块和一层选中菜单
    setActivated(route) {
      if (route.path.startsWith("/redirect")) {
        return;
      }
      if (staticRoutes.findIndex((item) => item.path === route.path) !== -1) {
        return;
      }
      let keyPath = route?.meta?.keyPath || route?.query?.keyPath || undefined;
      if (typeof keyPath === "string") {
        keyPath = [keyPath];
      }
      this.$store.commit("setActivatedModule", keyPath[0] || null);
      this.$store.commit("setActivatedFirst", keyPath[1] || null);
    },
    // 初始化 固定tags
    initTags() {
      const fn = (data, res = []) => {
        data.forEach((route) => {
          if (route?.meta?.affix) {
            res.push(route);
          }
          if (route?.children?.length) {
            fn(route, res);
          }
        });
        return res;
      };
      const affixView = fn(staticRoutes);
      affixView.forEach((item) =>
        this.$store.dispatch("tagsView/addView", item)
      );
    },
    // 添加 tag
    addTags() {
      if (this.$route.path.startsWith("/redirect")) {
        return;
      }
      this.$store.dispatch("tagsView/addView", this.$route);
    },
    // 去相邻路由
    toSiblingView(visitedViews, index) {
      let siblingView = visitedViews[index];

      if (!siblingView) {
        siblingView = visitedViews[index - 1];
      }

      const path = siblingView.fullPath || siblingView.path;
      this.$router.push(path);
    },
    // 关闭一个
    closeOne(view, index) {
      this.$store
        .dispatch("tagsView/delView", view)
        .then(({ visitedViews }) => {
          if (view.path === this.active) {
            this.toSiblingView(visitedViews, index);
          }
        });
    },
    // 关闭左边
    closeLeft() {
      this.$store
        .dispatch("tagsView/delLeftViews", this.targetRouter)
        .then(({ visitedViews }) => {
          if (!visitedViews.find((item) => item.path === this.active)) {
            const { fullPath, path } = this.targetRouter;
            this.$router.push({ path: fullPath || path });
          }
        });
    },
    // 关闭右边
    closeRight() {
      this.$store
        .dispatch("tagsView/delRightViews", this.targetRouter)
        .then(({ visitedViews }) => {
          if (!visitedViews.find((item) => item.path === this.active)) {
            const { fullPath, path } = this.targetRouter;
            this.$router.push({ path: fullPath || path });
          }
        });
    },
    // 关闭其他
    closeOthers() {
      this.$store
        .dispatch("tagsView/delOthersViews", this.targetRouter)
        .then(({ visitedViews }) => {
          if (this.targetRouter.path !== this.active) {
            const { fullPath, path } = this.targetRouter;
            this.$router.push({ path: fullPath || path });
          }
        });
    },
    // 关闭所有
    closeAlls() {
      this.$store.dispatch("tagsView/delAllViews").then(() => {
        this.$router.push({ path: "/home" });
      });
    },
    // 全屏
    fullScreen() {
      const dom = document.getElementById("app-content");
      this.defaultLayout?.fullScreen(dom);
    },
    // 刷新
    refresh() {
      this.$store
        .dispatch("tagsView/delCachedView", this.targetRouter)
        .then(() => {
          this.judgeJumperMethod(this.targetRouter, (toPath) => {
            this.$router.replace({
              path: `/redirect${toPath}`,
            });
          });
        });
    },
    // 打开新窗口
    openNewWindow() {
      const { fullPath, path } = this.targetRouter;
      window.open(fullPath || path);
    },
    // 右键
    onContextmenu(route, e) {
      e.preventDefault();
      this.setPosition(e);
      this.targetRouter = route;
    },
    // 右键菜单
    contextmenuClick({ key }) {
      this.closeContextmenu();
      switch (key) {
        case "1":
          this.closeLeft();
          break;
        case "2":
          this.closeRight();
          break;
        case "3":
          this.closeOthers();
          break;
        case "4":
          this.closeAlls();
          break;
        case "5":
          this.fullScreen();
          break;
        case "6":
          this.refresh();
          break;
        // case "7":
        //   this.openNewWindow();
        //   break;
        default:
          break;
      }
    },
    setPosition(e) {
      this.left = e.clientX;
      this.top = e.clientY;
      // 右键点击区域 显示自定义右键菜单
      const dom = document.querySelector(
        ".app-tabs-view > .tabs-head .ant-tabs-nav-container"
      );
      const { x, y, height } = dom?.getBoundingClientRect() || {};
      const { width } =
        dom?.querySelector(".ant-tabs-nav")?.getBoundingClientRect() || {};

      this.visible = !!(
        x &&
        y &&
        width &&
        height &&
        e.clientX >= x &&
        e.clientX <= x + width &&
        e.clientY >= y &&
        e.clientY <= y + height
      );
    },
    closeContextmenu() {
      this.visible = false;
    },
  },
};
</script>

<style scoped lang="less">
@import (optional, once) "../../../theme";
.app-tabs-view {
  /deep/.ant-tabs.ant-tabs-card {
    .ant-tabs-card-bar {
      padding: 0 14px 0 0;
      border: none;
      .ant-tabs-tab {
        background: #fff;
        border: none;
        border-radius: 0;
        margin: 0;
      }
      .ant-tabs-tab-active {
        background: @layout-body-background;
        border-bottom: none;
      }
    }
    .ant-tabs-tab {
      height: 32px;
      line-height: 30px;
    }
    .ant-tabs-nav-container {
      height: 32px;
    }
    .ant-tabs-extra-content {
      line-height: 32px;
    }
  }
  /deep/.ant-menu-vertical {
    padding: 5px 0;
    .ant-menu-item {
      margin: 0;
      height: 30px;
      line-height: 30px;
    }
  }
}
.tab {
  margin: 0 -16px;
  padding: 0 16px;
  font-size: 14px;
  user-select: none;
  // transition: all 0.2s;
  position: relative;
  .title {
    display: inline-block;
    height: 100%;
  }
  .icon-close {
    font-size: 12px;
    margin-left: 6px;
    margin-right: -4px !important;
    color: @text-color-second;
    &:hover {
      color: @text-color;
    }
  }
  .icon-sync {
    margin-left: -4px;
    color: @primary-4;
    transition: all 0.3s ease-in-out;
    font-size: 14px;
    &:hover {
      color: @primary-color;
    }
    &.hide {
      font-size: 0;
    }
  }
}
.tabFault {
  .tabs-line {
    position: absolute;
    right: 0;
    top: 7px;
    width: 1px;
    height: 18px;
    background: #f0f0f0;
  }
}
.tabs-head {
  height: 44px;
  margin: 0 auto;
  &.head.static {
    width: 1400px;
  }
}
.tabs-container {
  transition: top, left 0.2s;
  /deep/.ant-tabs-bar {
    background: #fff;
    margin: 0 0 12px 0;
  }
  .header-lock {
    font-size: 18px;
    cursor: pointer;
    color: @primary-3;
    &:hover {
      color: @primary-color;
    }
  }
  &.affixed {
    margin: 0 auto;
    top: 0;
    // padding: 0 14px 0 0;
    position: fixed;
    height: 44px;
    z-index: 1;
    background-color: @layout-body-background;
    &.side,
    &.mix {
      right: 0;
      &.collapsed {
        left: 0;
      }
    }
    &.head {
      width: inherit;
      padding: 8px 0 0;
      &.fluid {
        left: 0;
        right: 0;
        padding: 8px 12px 0;
      }
    }
    &.fixed-header {
      top: 50px;
    }
  }
}
.virtual-tabs {
  height: 44px;
}
.contextmenu {
  position: fixed;
  z-index: 1000;
  border-radius: 4px;
  box-shadow: -4px 4px 16px 1px @shadow-color !important;
  .tab-icon {
    color: @primary-color;
    margin-right: 8px;
  }
}
</style>
