<template>
  <mega-config-provider :locale="$i18n.messages[$store.state.app.locale]">
    <a-layout id="app" class="app">
      <!-- 侧边栏 -->
      <app-menu />
      <div
        v-if="fixedSideBar && !isMobile"
        :style="{
          width: sideMenuWidth,
          minWidth: sideMenuWidth,
          maxWidth: sideMenuWidth,
        }"
        class="virtual-side"
      />

      <a-layout id="app-wrapper" class="app-wrapper">
        <!-- 头部 -->
        <app-header
          :class="[
            {
              'fixed-tabs': fixedTabs,
              'fixed-header': fixedHeader,
              'multi-page': multiPage,
            },
          ]"
          :style="headerStyle"
        />
        <a-layout-header
          v-show="fixedHeader"
          :class="[
            'virtual-header',
            {
              'fixed-tabs': fixedTabs,
              'fixed-header': fixedHeader,
              'multi-page': multiPage,
            },
          ]"
        />

        <!-- 页面内容 -->
        <app-main style="z-index: 1" />
      </a-layout>

      <!-- 菜单拖拽 -->
      <div
        id="app-split-drag"
        class="app-split-drag"
        :style="{
          left: sideMenuWidth,
        }"
        @mousedown.stop="onMouseDown"
      />

      <!-- 返回顶部 -->
      <div v-show="showBackTop" class="back-top" @click="handleBackTop">
        <svg-icon icon-class="back-top" style="width: 100%; height: 100%" />
      </div>
      <FloatingFrame></FloatingFrame>
    </a-layout>
  </mega-config-provider>
</template>

<script>
import { mapState, mapMutations, mapGetters } from "vuex";
import { ConfigProvider as MegaConfigProvider } from "@mega-design/ui-vue";
import themeUtil from "@/utils/theme/update";
import ApiConstant from "@/api/ApiConstant";
import screenfull from "@/utils/screenfull";
import { generateRouteKey } from "@/plugins/generateRouter";
import AppMenu from "@/components/AppMenu";
import AppHeader from "@/components/AppHeader";
import AppMain from "@/components/AppMain";
import Mixin from "./mixins";
import MenuDrag from "./draggable";
import FloatingFrame from "@/components/FloatingFrame";

export default {
  components: {
    MegaConfigProvider,
    AppMenu,
    AppHeader,
    AppMain,
    FloatingFrame,
  },
  mixins: [Mixin, MenuDrag],
  provide() {
    return {
      defaultLayout: this,
    };
  },
  data() {
    return {
      collapsed: true,
      showBackTop: false,
      sideMenuWidth: "256px",
      searchActive: false,
      scrollNode: null,
      timer: null,
    };
  },
  computed: {
    ...mapState({
      systemConfig: (state) => state.app.systemConfig,
    }),
    ...mapState("setting", [
      "isMobile",
      "theme",
      "layout",
      "fixedHeader",
      "fixedSideBar",
      "fixedTabs",
      "hideSetting",
      "multiPage",
      "weekMode",
      "sideMenuDefaultWidth",
    ]),
    ...mapGetters([
      "firstMenu",
      "subMenu",
      "menuData",
      "headMenuData",
      "sideMenuData",
    ]),
    headerStyle() {
      const width =
        this.fixedHeader &&
        this.layout !== "head" &&
        !this.isMobile &&
        !this.collapsed
          ? `calc(100% - ${this.sideMenuWidth})`
          : "100%";
      const position = this.fixedHeader ? "fixed" : "static";
      return `width: ${width}; position: ${position};`;
    },
  },
  watch: {
    "theme.mode": function (val) {
      const closeMessage = this.$message.loading(this.$t("THEME_IS_SWITCHING"));
      themeUtil.changeThemeColor(this.theme.color, val).then(closeMessage);
    },
    "theme.color": function (val) {
      const closeMessage = this.$message.loading(this.$t("THEME_IS_SWITCHING"));
      themeUtil.changeThemeColor(val, this.theme.mode).then(closeMessage);
    },
    weekMode(val) {
      this.setWeekModeTheme(val);
    },
    layout() {
      window.dispatchEvent(new Event("resize"));
    },
  },
  beforeMount() {
    this.getFacoriteMenu();
    this.sideMenuWidth = this.getHistorySideMenuWidth();
    this.collapsed = parseFloat(this.sideMenuWidth, 10) <= 3;
  },
  mounted() {
    this.setLogoOpacity(this.sideMenuWidth);
    this.scrollNode = document.getElementById("__layout");
    this.scrollNode.addEventListener("scroll", (e) => {
      const { scrollTop } = e.target;
      if (scrollTop > 400) {
        if (this.setT) {
          clearTimeout(this.setT);
        }
        this.setT = setTimeout(() => {
          this.showBackTop = true;
        }, 300);
      } else {
        if (this.setT) {
          clearTimeout(this.setT);
        }
        this.setT = setTimeout(() => {
          this.showBackTop = false;
        }, 300);
      }
    });
  },
  methods: {
    ...mapMutations(["setActivatedFirst"]),
    updateSearchActive(val) {
      this.searchActive = val;
    },
    getHistorySideMenuWidth() {
      const width = localStorage.getItem("APP_SIDE_MENU_WIDTH");
      if (width && width.endsWith("px")) {
        return width;
      }
      return this.sideMenuDefaultWidth;
    },
    setWeekModeTheme(weekMode) {
      if (weekMode) {
        document.body.classList.add("week-mode");
      } else {
        document.body.classList.remove("week-mode");
      }
    },
    toggleCollapse() {
      this.collapsed = !this.collapsed;
      if (this.collapsed) {
        this.sideMenuWidth = "0";
      } else {
        const width = this.getHistorySideMenuWidth();
        this.sideMenuWidth =
          parseFloat(width, 10) < 100 ? this.sideMenuDefaultWidth : width;
        this.setSideMenuWidth(this.sideMenuWidth);
      }
    },
    onMenuSelect() {
      this.toggleCollapse();
    },
    // 跳转页面
    goRoute(data) {
      if (!["", "/", null, undefined].includes(data.menuPath)) {
        // 非外链
        if (
          data.isFrame === "N" ||
          data.isFrame === null ||
          data.isFrame === undefined
        ) {
          this.$router.push({
            path: data.menuPath,
          });
        } else if (data.isFrame === "Y") {
          // 外链
          this.goRouteFrame(data);
        }
        this.$axios.put(
          `${ApiConstant.PREFIX_CORE}/api/sys/user-menu-statistics?menuId=${data.id}`
        );
      }
    },
    // 外链
    goRouteFrame(data) {
      if (data.frameType === "ORDINARY") {
        try {
          // 外链打开网址携带token处理
          const { origin, hash, href, search } = new URL(data.menuPath);
          let path = `token=${this.$auth.getToken("local")}`;
          const arr = search.split("&");
          if (arr.length && arr[0].includes("=")) {
            path = `${href}&${path}`;
          } else {
            path = `${origin}${hash ? "/#" : ""}?${path}`;
          }
          this.goRouteOpen({
            ...data,
            path,
          });
        } catch (e) {
          this.goRouteOpen({
            ...data,
            path: data.menuPath,
          });
        }
      } else if (data.frameType === "BI") {
        this.$axios
          .get(
            `${ApiConstant.PREFIX_CORE}/api/report/report-server/get-out-link-url?menuId=${data.id}`
          )
          .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;
            let menuPath = data.menuPath?.startsWith("/")
              ? data.menuPath.substr(1, data.menuPath?.length)
              : data.menuPath;
            menuPath = menuPath?.endsWith("/")
              ? menuPath.substr(0, (menuPath?.length ?? 1) - 1)
              : menuPath;
            const token = this.$auth?.getToken("local")?.substr(7) || "";
            const params = `ticket=${token}&type=external`;
            try {
              const { search } = new URL(`${biPath}/${menuPath}`);
              this.goRouteOpen({
                ...data,
                path: search
                  ? `${biPath}/${menuPath}&${params}`
                  : `${biPath}/${menuPath}?${params}`,
              });
            } catch (_err) {}
          });
      }
    },
    // 打开方式
    goRouteOpen(data) {
      // 打开类型
      if (data.openType === "INNER") {
        const innerPath = `/external-view/${data.id}`;
        const params =
          data.frameType === "BI"
            ? {
                isBiFrame: "Y",
                menuPath: data.menuPath,
              }
            : {};
        this.$router.push({
          path: innerPath,
          query: {
            url: `${data.path}`, // 外接系统的链接：例如：https://www.bing.com
            title: data.menuName?.trim(),
            ...generateRouteKey(data),
            ...params,
          },
        });
      } else {
        window.open(data.path);
      }
    },
    handleBackTop() {
      clearTimeout(this.setT);
      this.scrollNode.scrollTop = 0;
    },
    // 菜单收藏
    toggleCollect(data, collect) {
      this.$axios
        .put(
          `${
            ApiConstant.PREFIX_CORE
          }/api/sys/user-favorite/edit-collection?menuId=${
            data.id
          }&isCollection=${collect ? 1 : 0}`
        )
        .then(() => {
          this.$message.success(
            collect ? this.$t("COLLECT_SUCCESS") : this.$t("CANCEL_SUCCESS")
          );
          this.getFacoriteMenu();
        });
    },
    // 获取收藏列表
    getFacoriteMenu() {
      this.$axios.get(`${ApiConstant.PREFIX_CORE}/api/sys/home`).then((res) => {
        this.$store.commit(
          "account/SET_FAVORITE_MENUS",
          res.data.data?.collection || []
        );
        this.$store.commit(
          "account/SET_MOST_USED",
          res.data.data?.mostUsed || []
        );
      });
    },
    // 全屏
    fullScreen(docElm) {
      if (!docElm) return;
      screenfull.onchange(this.fullScreenBack);
      screenfull.toggle(docElm);
    },
    fullScreenBack(e) {
      this.$store.commit("app/SET_FULL_SMALL", screenfull.isFullscreen);
    },
  },
};
</script>

<style lang="less" scoped>
@import (optional, once) "../theme";
.app {
  min-height: 100vh;
  .app-wrapper {
    min-height: 100vh;
  }
  .virtual-side {
    transition: all 0s ease 0s;
  }
  .virtual-header {
    transition: all 0s ease 0s;
    opacity: 0;
    height: 50px;
    &.fixed-tabs.multi-page:not(.fixed-header) {
      height: 0;
    }
  }
  .back-top {
    width: 56px;
    height: 56px;
    position: fixed;
    bottom: 101px;
    right: 8px;
    z-index: 1000;
    cursor: pointer;
  }
  .app-split-drag {
    position: fixed;
    top: 0;
    height: 100%;
    width: 6px;
    cursor: e-resize;
    transform: translate(-50%);
    z-index: 50;
  }
}
</style>
