<!--
 * @Author: fxs bjnsfxs@163.com
 * @Date: 2024-08-20 14:06:49
 * @LastEditors: fxs bjnsfxs@163.com
 * @LastEditTime: 2024-10-09 16:31:29
 * @FilePath: \Game-Backstage-Management-System\src\views\Index.vue
 * @Description: 
 * 
-->
<script setup lang="ts">
import { zhCn } from 'element-plus/es/locales.mjs'
import { RouterView } from 'vue-router'
import { onMounted, reactive, ref, computed, watch } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
import { getAllGameInfo } from '@/utils/table/table'
import router from '@/router'
import type { DropDownInfo } from '@/types/dataAnalysis'
import DropDownSelection from '@/components/dataAnalysis/DropDownSelection.vue'
import { useCommonStore } from '@/stores/useCommon'
import { initLoadResouce } from '@/utils/resource'

const route = useRoute()
const { selectInfo, allGameInfo, saveSelectInfo } = useCommonStore()
const isCollapse = ref(false)
const navBarSelect = ref<string>('Home')
const siderBarOpened = ref<Array<string>>(['数据总览'])
const siderBar = ref()
const loadingState = ref(false) // 用来标记必要信息的加载状态

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

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

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

  {
    name: 'AppManage',
    title: '应用管理'
  }
]

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

// 登出
const logOut = () => {
  ElMessage({
    type: 'success',
    message: '退出成功',
    duration: 1000
  })
  localStorage.removeItem('token')
  localStorage.removeItem('refreshToken')
  router.push('/login')
}

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

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

/**
 * @description: 头部导航栏改变
 * @param {*} val 对应的name
 * @return {*}
 */
const changeNavBar = (val: string) => {
  navBarSelect.value = val

  router.push(`/${val}`)
  createdMenuList()
  let title = navBarMenuList.find((item) => item.name === val)?.title
  if (title) {
    siderBarOpened.value.splice(0, 1, title)
  }
}

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

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

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

/**
 * @description: 创建侧边栏menu
 * @return {*}
 */
const createdMenuList = () => {
  let routes = router.options.routes // 获取路由信息
  let indexRoutesChild = routes.find((item) => item.name === 'Index')?.children
  let activeMenu = indexRoutesChild?.find((item) => {
    return item.name === navBarSelect.value // 根据顶部导航栏的选中情况来选择选中哪个具体的路由信息，可以打印自己看一下
  })
  basePath.value = activeMenu?.path // 找到需要激活的菜单的路由，后续用来拼接需要跳转的路由
  menuList.splice(0, menuList.length, ...(activeMenu?.children as Array<any>)) // 清空原来的路由信息，并且加入新选中的
}

/**
 * @description: 当路由地址改变的时候，去获取最新的导航栏位置，并且重新生成侧边栏，不然刷新后，侧边栏会无法选中
 * @param {*} router
 * @return {*}
 */
watch(
  () => [router.currentRoute.value.fullPath],
  ([newFullPath]) => {
    let routes = router.options.routes // 获取路由信息
    let indexRoutesChild = routes.find((item) => item.name === 'Index')?.children
    let activeMenu = indexRoutesChild?.find((item) => {
      return newFullPath.includes(item.path) // 根据顶部导航栏的选中情况来选择选中哪个具体的路由信息，可以打印自己看一下
    })
    navBarSelect.value = activeMenu?.name as string
    createdMenuList()
  },
  {
    immediate: true
  }
)

/**
 * @description: 获取所有游戏列表
 * @return {*}
 */
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)
    })
}

/**
 * @description: 监听游戏列表的变化
 * @return {*}
 */
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
            })
          })
          // getGameInfo()
          // newGameInfo.map((item) => console.log(item))
          // console.log(...newGameInfo)
          // gameSelectInfo.optionsList.splice(0, gameSelectInfo.optionsList.length, ...newGameInfo)
          // if (newGameInfo.length > oldGameInfo.length) {
          //   gameSelectInfo.optionsList.push({
          //     value: newGameInfo[newGameInfo.length - 1].gid,
          //     label: newGameInfo[newGameInfo.length - 1].gameName
          //   })
          // }else{
          // }
        },
        { deep: true }
      )
      watchLoadingState()
    } else {
      watchGameListChange()
    }
  },
  {
    deep: true
  }
)

getGameInfo()
onMounted(() => {
  // 去加载所有需要的资源
  initLoadResouce(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>淳皓科技</span>
        </div>

        <div class="gameSelect">
          <el-icon class="gameIcon" :size="20">
            <icon-icon-park-game-three></icon-icon-park-game-three>
          </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"
              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="siderBar"
        >
          <template v-for="(item, index) in menuList">
            <el-sub-menu :index="`${index}`" v-if="item.children && item.showChild">
              <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="index"
              >
                <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;
}

/* 设置弹出层的样式 */
.el-popper > .logoText {
  width: 100px;
  font-size: 16px;
  /* color: red; */
}

.logoImg {
  display: flex;
  align-items: center;
  width: 33px;
  /* margin-right: 20px; */
  /* height: 50px; */
}

.logoText {
  width: 80%;
  height: 100%;
  margin-left: 15%;
  display: flex;
  font-size: 18px;
  align-items: center;
  /* background-color: lightcoral; */
}

/* 主要用来调整整个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%;
  display: flex;
  align-items: center;
}

.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: 50px;
}

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

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

<!-- 为了让popper-class生效，需要的单独写一份 -->
<style>
.headPopper {
  padding: 0px !important;
  border: 1px solid #e5e6eb;

  background-color: white;
}
.el-menu--horizontal.el-menu {
  border-bottom: none;
}
</style>
