<template>
  <a-layout :class="$style.wrapper">
    <a-layout-header :class="$style.tabs">
      <a-tabs
        v-model="selected"
        hide-add
        type="editable-card"
        style="float:left;margin-left: 35px"
        @change="tabChange"
        @edit="onEdit"
      >
        <a-tab-pane v-for="(tab, index) in tabs" :key="tab.url" :closable="tabs.length > 1">
          <a-dropdown slot="tab" :trigger="['contextmenu']">
            <span :class="$style.tabTitle" @click.middle="tabs.length > 1 && removeTab(tab.url)">
              {{ tab.title }}
            </span>
            <a-menu slot="overlay" :class="$style.menu" @click="(evt) => menuClick(evt.key, index)">
              <a-menu-item key="reload" :disabled="tab.url !== selected">
                <a-icon type="reload" />刷新
              </a-menu-item>
              <a-menu-divider />
              <a-menu-item key="closeCurrent" :disabled="tabs.length === 1">
                <a-icon type="close" />关闭
              </a-menu-item>
              <a-menu-item key="closeRight" :disabled="index === tabs.length - 1">
                <a-icon />关闭右侧
              </a-menu-item>
              <a-menu-item key="closeLeft" :disabled="index === 0">
                <a-icon />关闭左侧
              </a-menu-item>
              <a-menu-item key="closeOther" :disabled="tabs.length === 1">
                <a-icon />关闭其他
              </a-menu-item>
            </a-menu>
          </a-dropdown>
        </a-tab-pane>
      </a-tabs>
      <div :class="$style.tools">
        <div><ext-header-tools-before /></div>
        <span :class="$style.links">
          <a-icon v-if="false" type="sd-home" title="首页" @click="$router.push('/sd-home')" />
          <span><a-icon type="phone" />运维电话: 010-66298888 &nbsp;&nbsp;&nbsp;&nbsp;</span>
          <a-icon
            v-if="showBusinessNavi"
            type="sd-module"
            title="工作台"
            @click="$router.push('/sd-frame/iam-content')"
          />
          <a-icon
            type="sd-bell"
            title="消息提醒"
            @click="$router.push('/sd-frame/sd-message-remind')"
          />
          <a-badge v-if="remindTotal > 0" dot :class="$style.headerbadge" />
          <!-- 导航菜单切换 -->
          <naviGroupsMenu :data-source="naviGroups" />
        </span>
        <sd-header-user-action />
      </div>
    </a-layout-header>
    <a-layout-content ref="content" class="sd-frame-main">
      <keep-alive :include="componentsInTabs">
        <router-view v-if="isRouterAlive" :key="selectedTabKey" ref="routerView" />
      </keep-alive>
    </a-layout-content>
  </a-layout>
</template>

<script>
import { getUserInfo } from '@/common/store-mixin'
import { Icon, Dropdown, Menu } from 'ant-design-vue'
import components from './_import-components/sd-tabbed-view-import'
import navMenuService from './nav-menu-service'
// 获取异步组件的信息
function getComponentInfo(route) {
  const lastMatched = route.matched[1] // 0是sd-frame，1是tab页内的内容
  return lastMatched.components.default.getComponentInfo()
}

const naviGroupsMenu = {
  props: ['dataSource'],
  methods: {
    changeNavi(menu) {
      const { href } = this.$router.resolve({ path: '/sd-frame' })
      const url = `?menuGroupCode=${encodeURIComponent(menu.code)}${href}`
      if (menu.target === '_blank') {
        window.open(url, '_blank')
      } else {
        location.replace(url)
      }
    },
  },
  render() {
    let menu = ''
    const data = this.dataSource[0]
    if (this.dataSource.length === 1) {
      menu = (
        <Icon
          type={data.icon || 'sd-module'}
          title={data.tooltip || data.text}
          vOn:click={() => this.changeNavi(data)}
        />
      )
    } else if (this.dataSource.length > 1) {
      menu = (
        <Dropdown>
          <Icon type={data.icon || 'sd-module'} />
          <Menu slot='overlay'>
            {this.dataSource.map((item) => (
              <Menu.Item vOn:click={() => this.changeNavi(item)}>
                {item.tooltip || item.text}
              </Menu.Item>
            ))}
          </Menu>
        </Dropdown>
      )
    }
    return menu
  },
}
export default {
  name: 'SdTabbedView',
  components: {
    ...components,
    naviGroupsMenu,
  },
  props: {
    showBusinessNavi: {
      type: Boolean,
      default: true,
    },
    remindTotal: {
      type: Number,
      default: 0,
    },
    naviGroups: {
      type: Array,
      default: () => [],
    },
    dataSource: {
      type: Array,
      default: undefined,
    },
  },
  data() {
    return {
      // 打开的tab列表
      tabs: [],
      // 当前选中的tab页
      selected: '',
      isRouterAlive: true,
    }
  },
  provide() {
    return {
      SdTabbedView: this,
    }
  },
  computed: {
    // 计算所有tab页包含的view组件名
    componentsInTabs() {
      return (
        this.tabs
          // 需要刷新的当前页面，排除（按组件名排除，否则其他tab页有同名组件，就无法刷新了）
          .filter(
            (tab, index) =>
              !(tab.componentName === this.selectedTab.componentName && !this.isRouterAlive)
          )
          .map((tab) => tab.componentName)
          .join(',')
      )
    },
    selectedTab() {
      return this.tabs.find((tab) => tab.url === this.selected)
    },
    selectedTabKey() {
      return this.selectedTab?.tabKey
    },
    selectedTabTitle() {
      return this.selectedTab?.title
    },
  },
  watch: {
    $route: {
      handler(newVal, oldVal) {
        this.handleRouteChange(newVal, oldVal)
      },
      immediate: true,
    },
  },
  mounted() {},
  methods: {
    // 处理关闭页签的操作
    menuClick(type, index) {
      switch (type) {
        case 'closeCurrent':
          this.tabs.splice(index, 1)
          break
        case 'closeOther':
          this.tabs = [this.tabs[index]]
          break
        case 'closeLeft':
          this.tabs.splice(0, index)
          break
        case 'closeRight':
          this.tabs.splice(index + 1)
          break
        case 'reload':
          this.reload()
          break
      }
      this.updateSelect()
    },
    onEdit(targetKey, action) {
      if (action === 'remove') this.removeTab(targetKey)
    },
    // 关闭当前页
    closeCurrent() {
      if (this.tabs.length > 1) this.removeTab(this.selected)
    },
    // 关闭tab
    removeTab(url) {
      this.tabs = this.tabs.filter((tab) => tab.url !== url)
      this.updateSelect()
    },
    tabChange() {
      this.$router.push({ path: this.selected })
    },
    // 跟踪路由变化，新增对应的tab页
    handleRouteChange(newVal, oldVal) {
      const newUrl = newVal.fullPath
      const tabKey = newVal.meta.getTabKey?.(newVal) ?? newUrl
      const contentEl = this.$refs.content?.$el
      // 保存前一个tab页的滚动位置
      if (oldVal) {
        const oldTab = this.tabs.find((tab) => tab.url === oldVal.fullPath)
        if (oldTab) {
          oldTab.scroll = {
            x: contentEl.scrollLeft,
            y: contentEl.scrollTop,
          }
        }
      }

      // 选中当前路由对应的tab
      this.selected = newUrl
      const newTab = this.tabs.find((tab) => tab.tabKey === tabKey)
      // 已经在tab列表里，恢复原有滚动位置后退出
      if (newTab) {
        newTab.url = newUrl
        this.$nextTick(() => {
          contentEl.scrollTop = newTab.scroll.y
          contentEl.scrollLeft = newTab.scroll.x
        })
        return
      }

      // 新创建的tab页，滚动到最上面
      if (contentEl)
        this.$nextTick(() => {
          contentEl.scrollTop = contentEl.scrollLeft = 0
        })

      // 路由信息中标记了不创建tab，退出
      const lastMatched = newVal.matched[newVal.matched.length - 1]
      if (lastMatched.meta.createTab === false) return

      // 新增tab页
      const tab = {
        url: newUrl,
        tabKey,
        page: newVal,
        scroll: {
          x: 0,
          y: 0,
        },
      }
      this.tabs = [tab]
      // this.tabs.push(tab)
      getComponentInfo(newVal).then((info) => {
        const tabs = this.tabs
        // 组件title，作为tab页的label
        let metaInfo = info.metaInfo
        // 组件name，作为keep-alive的key
        tab.componentName = info.name

        this.$nextTick(() => {
          navMenuService
            .getNavTitleByUrl(newVal.fullPath)
            .then((navTitle) => {
              // 从导航里取到title，把它更新回组件的属性
              tab.title = navTitle
              if (metaInfo.title) {
                metaInfo.title = navTitle
              }
            })
            .catch(() => {
              // 导航里没有，从组件属性获取
              if (typeof metaInfo === 'function') metaInfo = metaInfo.apply(this.$refs.routerView)
              tab.title = metaInfo.title
            })
            .finally(() => {
              this.tabs = [...tabs]
            })
        })
      })
    },
    updateSelect() {
      // 判断当前选中的页签是否还在列表里
      if (!this.tabs.some((tab) => tab.url === this.selected)) {
        // 已经不在了就选中最后一个页签
        this.selected = this.tabs[this.tabs.length - 1].url
        this.tabChange()
      }
    },
    // 刷新
    reload() {
      this.isRouterAlive = false
      this.$nextTick(() => (this.isRouterAlive = true))
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;

$link-icon-size: 22px;
$line-height-theme: 66px;
$theme-check: #fff;
$icon-size: 15px;
.wrapper {
  height: 100%;
  .tabs {
    height: auto;
    padding: 0;
    background-color: $body-background;
    :global(.ant-tabs-bar) {
      margin: 0;
    }

    :global(.ant-tabs-nav-container) {
      margin: 14px $padding-lg -1px;
    }

    :global .ant-tabs.ant-tabs-card .ant-tabs-card-bar {
      .ant-tabs-tab-active {
        font-weight: 600;
      }
      .ant-tabs-tab-active,
      .ant-tabs-tab:hover {
        color: $text-color;
        background: $layout-body-background;
        border-bottom-color: $layout-body-background;
        border-radius: 8px 8px 0 0;
      }
    }
    :global .ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab:not(.ant-tabs-tab-active) {
      background: transparent;
      border-color: transparent;
    }

    .tab-title {
      display: inline-block;
      padding: 0 16px;
      margin: 0 -16px;
    }
  }
}
.menu {
  :global .ant-dropdown-menu-item {
    padding-right: 30px;
  }
}
.tools {
  display: flex;
  float: right;
  color: #000 !important;
}

.links {
  display: flex;
  align-items: center;
  margin: 0 $link-icon-size / 2;
  li:global(.ant-menu-item) {
    padding: 0;
  }
  i:global(.anticon) {
    padding: 0 $link-icon-size / 2;
    margin: 0;
    font-size: $link-icon-size;
    line-height: $layout-header-height;
    vertical-align: middle;
    &:hover {
      // 悬浮的颜色，与主题无关
      /* stylelint-disable-next-line */
      background-color: rgba(0, 0, 0, 0.2);
    }
  }
}
</style>
