<!--
 * @Author: fxs bjnsfxs@163.com
 * @Date: 2024-08-20 14:06:49
 * @LastEditors: fxs bjnsfxs@163.com
 * @LastEditTime: 2025-06-03
 * @Description: 
 * 
-->
<script setup lang="ts">
import type { DropDownInfo } from '@/types/dataAnalysis'

import { zhCn } from 'element-plus/es/locales.mjs'
import { type RouteRecordRaw, RouterView, useRoute } from 'vue-router'
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { getAllGameInfo } from '@/utils/table/table'

import { useCommonStore } from '@/stores/useCommon'
import { initLoadResource } from '@/utils/resource'
import { setLoginState } from '@/utils/localStorage/localStorage'
import { removeAllToken } from '@/utils/token/token'

import router from '@/router'
import DropDownSelection from '@/components/dataAnalysis/DropDownSelection.vue'

const route = useRoute()
const { selectInfo, allGameInfo, saveSelectInfo } = useCommonStore()

const isCollapse = ref(false)
const navBarSelect = ref<string>('Home')
const loadingState = ref(false) // 用来标记必要信息的加载状态

// 路由信息，同时也是侧边栏生成的依据信息
const menuList = reactive<Array<any>>([])

// 默认选中
const defaultActive = computed<string>(() => {
  return route.meta.activeMenu as string
})

// 顶部导航栏信息
const navBarMenuList = [
  {
    name: 'Home',
    title: '应用分析'
  },

  {
    name: 'AppManage',
    title: '应用管理'
  },
  {
    name: 'FileManage',
    title: '文件管理'
  },
  {
    name: 'MemberManage',
    title: '成员管理'
  }
]

/**
 * 侧边栏折叠改变
 */
const changeCollapse = () => {
  isCollapse.value = !isCollapse.value
}

/**
 * 退出登录
 *
 * 清除登录信息，跳转到登录页
 */
const logOut = () => {
  ElMessage({
    type: 'success',
    message: '退出成功',
    duration: 1000
  })
  setLoginState(false)
  removeAllToken()
  router.push('/login')
}

// 游戏下拉选择框需要的数据
const gameSelectInfo = reactive<DropDownInfo>({
  defaultSelect: '1001',
  title: '请选择游戏',
  optionsList: []
})

/**
 * 更新整个页面的游戏选择
 * @param {*} gid 游戏id
 */
const changeGame = (gid: string) => {
  selectInfo.gid = gid
  saveSelectInfo()
}

/**
 * 更新头部导航栏，跳转到对应页面
 * @param val 对应的name
 */
const changeNavBar = (val: string) => {
  navBarSelect.value = val

  router.push(`/${val}`)
  // createdMenuList()
}

// 资源的加载路径
const resourceInfo: Record<string, string> = {
  logo: `/img/logo.svg`,
  // logo: `/img/logoTest.svg`,
  defaultHead: `/img/default/defaultHead.png`
}

// 使用blob的资源路径信息
const blobUrlInfo = reactive<Record<string, string>>({})

// 侧边栏跳转路由的基本路由
const basePath = ref<string | undefined>()

/**
 * 创建侧边栏菜单
 */
const createdMenuList = (topRoute: RouteRecordRaw | null) => {
  if (!topRoute) return
  basePath.value = topRoute?.path // 找到需要激活的菜单的路由，后续用来拼接需要跳转的路由
  menuList.splice(0, menuList.length, ...(topRoute?.children as Array<any>)) // 清空原来的路由信息，并且加入新选中的
}

/**
 * 从URL中解析出路径片段
 * @param fullUrl 完整的 URL
 * @returns 路径片段组成的数组
 */
const parsePathFromUrl = (fullUrl: string): string[] => {
  const hashIndex = fullUrl.indexOf('#')
  const hashPart = hashIndex !== -1 ? fullUrl.slice(hashIndex + 1) : fullUrl
  const pathPart = hashPart.split('?')[0] // 去除查询参数
  return pathPart.split('/').filter(Boolean) // ['home', 'infoManage', 'gameManageView']
}

/**
 * 查找子路由所属的顶级路由
 * @param routes 路由数组
 * @param fullUrl 目标子路由的 name
 * @returns 顶级路由的 name 或 null
 */
const findTopRouteName = (routes: RouteRecordRaw[], fullUrl: string): RouteRecordRaw | null => {
  const pathSegments = parsePathFromUrl(fullUrl)
  if (pathSegments.length === 0) return null

  for (const route of routes) {
    const routeSegments = route.path.split('/').filter(Boolean)
    if (routeSegments[0] === pathSegments[0]) {
      return route || null
    }
  }
  return null
}

/**
 * 当路由地址改变的时候，去获取最新的导航栏位置，并且重新生成侧边栏，不然刷新后，侧边栏会无法选中
 */
watch(
  () => [router.currentRoute.value.fullPath],
  ([newFullPath]) => {
    let routes = router.options.routes // 获取路由信息
    let indexRoutesChild = routes.find((item) => item.name === 'Index')?.children
    if (!indexRoutesChild) {
      ElMessage.error('路由错误')
      return
    }
    const topRoute = findTopRouteName(indexRoutesChild, newFullPath)
    navBarSelect.value = topRoute?.name?.toString() || ''
    createdMenuList(topRoute)
  },
  {
    immediate: true
  }
)

/**
 * 获取所有游戏列表
 */
const getGameInfo = () => {
  getAllGameInfo()
    .then((data) => {
      if (data) {
        allGameInfo.splice(0, allGameInfo.length)
        gameSelectInfo.optionsList.splice(0, gameSelectInfo.optionsList.length)
        data.map((item) => {
          allGameInfo.push({
            gid: item.gid,
            gameName: item.gameName
          })
          gameSelectInfo.optionsList.push({
            value: item.gid,
            label: item.gameName
          })
        })
        gameSelectInfo.defaultSelect = data[0].gid
        // 去找本地的gid，如果有，就赋值，否则用请求回来的第一个gid

        changeGame(selectInfo.gid)
        gameSelectInfo.defaultSelect = selectInfo.gid

        loadingState.value = true
      } else {
        throw new Error('游戏信息获取失败')
      }
    })
    .catch((err) => {
      console.log(err)
    })
}

/**
 * 监听游戏列表的变化
 *
 * 此处只是声明，在后续加载完成后，会被赋值唯一一个监听器
 *
 */
let watchGameListChange: () => void = () => {}

/**
 * @description: 监听加载状态的变化，加载完成的时候，给游戏列表的监听器赋值,然后把自己这个监听器摧毁
 * @return {*}
 */
const watchLoadingState = watch(
  () => loadingState,
  (newVal) => {
    if (newVal) {
      // 用来监听游戏列表的变化
      watchGameListChange = watch(
        () => allGameInfo,
        (newGameInfo: Array<any>) => {
          gameSelectInfo.optionsList.splice(0, gameSelectInfo.optionsList.length)
          newGameInfo.forEach((item) => {
            gameSelectInfo.optionsList.push({
              value: item.gid,
              label: item.gameName
            })
          })
        },
        { deep: true }
      )
      watchLoadingState()
    } else {
      watchGameListChange()
    }
  },
  {
    deep: true
  }
)

getGameInfo()
onMounted(() => {
  // 去加载所有需要的资源
  initLoadResource(resourceInfo).then((data) => {
    Object.assign(blobUrlInfo, data)
  })
})
</script>

<template>
  <el-config-provider :locale="zhCn">
    <div class="body" v-if="loadingState">
      <div class="navBarBox">
        <div class="logoBox">
          <el-image :fit="'fill'" class="logoImg" :src="blobUrlInfo.logo"></el-image>
          <!--                    <span class="logoTitle">测试库</span>-->
          <span class="logoTitle">淳皓科技</span>
        </div>

        <div class="gameSelect">
          <el-icon class="gameIcon" :size="20">
            <icon-icon-park-game-three></icon-icon-park-game-three>
            <!--            <icon-icon-park-solid-ad></icon-icon-park-solid-ad>-->
          </el-icon>
          <DropDownSelection
            :default-select="gameSelectInfo.defaultSelect"
            :title="gameSelectInfo.title"
            :options-list="gameSelectInfo.optionsList"
            :size="'default'"
            @change-select="changeGame"
          ></DropDownSelection>
        </div>
        <!-- 顶部导航栏 -->

        <div class="navBarMenu">
          <el-menu
            :default-active="navBarSelect"
            class="el-menu-demo"
            mode="horizontal"
            @select="changeNavBar"
          >
            <el-menu-item
              v-for="item in navBarMenuList"
              :key="item.name"
              class="navBarMenuItem"
              :index="item.name"
              >{{ item.title }}</el-menu-item
            >
          </el-menu>
        </div>
        <div class="headPortraitBox">
          <el-popover popper-class="headPopper" placement="bottom-end" trigger="click">
            <template #reference>
              <el-image class="headPortrait" :src="blobUrlInfo.defaultHead"></el-image>
            </template>
            <div class="userTools">
              <span class="userToolsItem" @click="logOut">
                <icon-material-symbols-light-logout></icon-material-symbols-light-logout>
                <span> 退出登录</span>
              </span>
            </div>
          </el-popover>
        </div>
      </div>
      <!-- 侧边栏 -->
      <div class="sideBarBox">
        <el-menu :default-active="defaultActive" class="sideBar" :collapse="isCollapse">
          <!--          ref="sideBar"-->
          <template v-for="(item, index) in menuList">
            <el-sub-menu
              :index="`${index}`"
              v-if="item.children && item.showChild"
              :key="item.name"
            >
              <template #title>
                <el-icon><component :is="item.icon"></component></el-icon>
                <span>{{ item.cnName }}</span>
              </template>
              <router-link
                style="text-decoration: none"
                v-for="val in item.children"
                :to="{ path: basePath + '/' + item.path + '/' + val.path }"
                :key="val"
              >
                <el-menu-item :index="val.path">{{ val.cnName }}</el-menu-item>
              </router-link>
            </el-sub-menu>

            <router-link
              style="text-decoration: none"
              v-else
              :to="{ path: basePath + '/' + item.path }"
              :key="index"
            >
              <el-menu-item :index="item.path">
                <el-icon><component :is="item.icon" /></el-icon>
                <template #title>
                  <span class="menuTitle">{{ item.cnName }}</span>
                </template>
              </el-menu-item>
            </router-link>
          </template>
          <div class="sideBarFold" @click="changeCollapse">
            <el-icon :size="25"><Fold /></el-icon>
          </div>
        </el-menu>
      </div>

      <div class="content">
        <router-view v-slot="{ Component, route }">
          <keep-alive>
            <component
              :is="Component"
              :key="route.meta.activeMenu"
              v-if="route.meta.needKeepAlive == true"
            ></component>
          </keep-alive>
          <component
            :is="Component"
            :key="route.meta.activeMenu"
            v-if="route.meta.needKeepAlive == false"
          ></component>
        </router-view>
      </div>
    </div>
  </el-config-provider>
</template>

<style scoped>
.body {
  width: 100%;
  display: flex;
  height: 100vh;
}

/* 设置宽度后，content无法适应宽度，只能去间接的调整内部元素的宽度 */
.sideBarBox {
  position: relative;
  /* width: 12%; */
  z-index: 1;
  height: 93vh;
  margin-top: 7vh;
  top: 0;
}

.sideBar {
  /* width: 12vw; */
  height: 93vh;
  position: relative;
  overflow: scroll;
}

.logoImg {
  display: flex;
  align-items: center;
  width: 33px;
  margin-right: 10px;
}

.logoTitle {
  font-family: 'Helvetica Neue', 'Hiragino Sans GB', 'Segoe UI', 'Microsoft Yahei', '微软雅黑',
    Tahoma, Arial, STHeiti, sans-serif;
  font-size: 18px;
  font-weight: 600;
}

/* 主要用来调整整个menu的宽度 */
.menuTitle {
  margin-right: 40px;
}

.sideBarFold {
  width: 5%;
  height: 3%;
  position: absolute;
  right: 40px;
  bottom: 20px;
}

.navBarBox {
  position: fixed;
  display: flex;
  align-items: center;
  width: 100vw;
  z-index: 2;
  height: 7vh;
  top: 0;
  background-color: white;
  right: 0;
  border-bottom: 1px solid gainsboro;
}

/* 调整LOGO */
.logoBox {
  box-sizing: border-box;
  left: 30px;
  position: relative;

  display: flex;
  justify-content: space-between;
  align-items: center;
}

.gameSelect {
  position: relative;

  height: 80%;
  display: flex;
  align-items: center;
  left: 5%;
}

.gameIcon {
  /* box-sizing: border-box; */
  /* padding-right: 12px; */
  margin-right: 12px;
}

.navBarMenu {
  width: 60%;
  position: relative;
  left: 6%;
}

.headPortraitBox {
  position: absolute;
  right: 3%;
  top: 50%;
  transform: translateY(-50%);
}

.userTools {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
}

.userToolsItem {
  cursor: pointer;
  width: 100%;
  height: 4vh;
  display: flex;
  align-items: center;
  justify-content: center;
  /* padding: 10px; */
  margin: 2%;
}

.userToolsItem > span {
  margin-left: 10%;
}

.userToolsItem:hover {
  background-color: #f2f3f5;
}

.headPortrait {
  cursor: pointer;
  width: 30px;
}

.content {
  /* flex-grow: 1; */
  /* position: absolute; */

  width: 100%;
  /* height: 93%; */
  margin-top: 7vh;
  overflow: scroll;
  background-color: #f2f3f5;
  right: 0;
  top: 0;
}
</style>

<!-- 为了让popper-class生效，需要的单独写一份 -->
<style>
.headPopper {
  padding: 0 !important;
  border: 1px solid #e5e6eb;
  background-color: white;
}
.el-menu--horizontal.el-menu {
  border-bottom: none;
}
</style>
