<script setup>  
 | 
import { nextTick, ref, inject, onMounted, h, reactive } from 'vue';  
 | 
import { useRouter } from "vue-router";  
 | 
import { get, post, postForm } from '@/utils/request.js'  
 | 
import { logout } from '@/config.js';  
 | 
import * as Icons from "@ant-design/icons-vue";  
 | 
import { message } from 'ant-design-vue';  
 | 
// import type { MenuMode, MenuTheme } from 'ant-design-vue';  
 | 
// import { ItemType } from 'ant-design-vue';  
 | 
  
 | 
import {  
 | 
  MenuUnfoldOutlined,  
 | 
  MenuFoldOutlined,  
 | 
  HomeOutlined,  
 | 
  CloseOutlined,  
 | 
  RedoOutlined,  
 | 
  UserOutlined,  
 | 
  TranslationOutlined,  
 | 
  ApartmentOutlined,  
 | 
  CaretLeftOutlined,  
 | 
  CaretRightOutlined,  
 | 
} from "@ant-design/icons-vue";  
 | 
import { formatMessage, loadData } from '@/utils/localeUtils.js';  
 | 
import AiView from '@/components/ai/index.vue'  
 | 
  
 | 
const globalState = inject('globalState');  
 | 
const selectedKeys = ref([]);  
 | 
let openKeys = ref([]);  
 | 
const collapsed = ref(false);  
 | 
const router = useRouter();  
 | 
let routerCache = ref([]);  
 | 
let routerCacheList = ref([]);  
 | 
let currentCache = ref(null);  
 | 
let isRouterAlive = ref(true);  
 | 
const menuCache = ref([]);  
 | 
const hostList = ref([]);  
 | 
const tabsContent = ref(null);  
 | 
  
 | 
const components = {  
 | 
  ...Icons,  
 | 
};  
 | 
  
 | 
  
 | 
  
 | 
onMounted(() => {  
 | 
  let name = router.currentRoute.value.name;  
 | 
  let path = router.currentRoute.value.path;  
 | 
  if (currentCache.value == null && path != '/') {  
 | 
    get('/api/menu/get/route', {  
 | 
      route: path  
 | 
    }).then((resp) => {  
 | 
      let result = resp.data;  
 | 
      let data = result.data;  
 | 
      if (result.code == 200) {  
 | 
        currentCache.value = name;  
 | 
        routerCache.value.push(name)  
 | 
        routerCacheList.value.push({  
 | 
          key: path,  
 | 
          languageId: data.languageId,  
 | 
          name: name,  
 | 
        })  
 | 
      }  
 | 
    })  
 | 
  }  
 | 
})  
 | 
  
 | 
  
 | 
const state = reactive({  
 | 
    rootSubmenuKeys: [],  
 | 
    openKeys: ["/"],  
 | 
    selectedKeys: [],  
 | 
});  
 | 
  
 | 
getMenu()  
 | 
function getMenu() {  
 | 
  get('/api/auth/menu', {}).then((result) => {  
 | 
    menuCache.value = result.data.data;  
 | 
    let routes = menuCache.value.map(item =>{  
 | 
        return item.route  
 | 
    })  
 | 
      routes.unshift('/')  
 | 
      state.rootSubmenuKeys = routes  
 | 
      console.log(state.rootSubmenuKeys)  
 | 
  })  
 | 
}  
 | 
  
 | 
function menuSelect(item) {  
 | 
  router.push({  
 | 
    path: item.key  
 | 
  })  
 | 
  
 | 
  let name = item.item.name;  
 | 
  currentCache.value = name;  
 | 
  
 | 
  if (name != undefined && routerCache.value.indexOf(name) == -1) {  
 | 
    routerCache.value.push(item.item.name)  
 | 
    routerCacheList.value.push({  
 | 
      key: item.key,  
 | 
      languageId: item.item.languageId,  
 | 
      name: item.item.name,  
 | 
    })  
 | 
  }  
 | 
}  
 | 
  
 | 
function closeTabs(param) {  
 | 
  let name = param.name;  
 | 
  let tmp = []  
 | 
  let tmpList = [];  
 | 
  routerCache.value.forEach((item) => {  
 | 
    if (item != name) {  
 | 
      tmp.push(item);  
 | 
    }  
 | 
  })  
 | 
  
 | 
  routerCacheList.value.forEach((item) => {  
 | 
    if (item.name != name) {  
 | 
      tmpList.push(item);  
 | 
    }  
 | 
  })  
 | 
  
 | 
  if (tmp == 0) {  
 | 
    router.push({  
 | 
      path: '/'  
 | 
    })  
 | 
    routerCache.value.push('home')  
 | 
    routerCacheList.value.push({  
 | 
      key: '/',  
 | 
      languageId: 'common.home',  
 | 
      name: '主页',  
 | 
    })  
 | 
    selectedKeys.value = ['/']  
 | 
  } else {  
 | 
    switchTabs(tmpList[0]);  
 | 
  }  
 | 
  routerCache.value = tmp;  
 | 
  routerCacheList.value = tmpList;  
 | 
}  
 | 
  
 | 
function reloadTabs() {  
 | 
  const hide = message.loading(formatMessage('common.loading', '加载中'));  
 | 
  try {  
 | 
    isRouterAlive.value = false;  
 | 
    nextTick(() => {  
 | 
      isRouterAlive.value = true;  
 | 
      // message.success(formatMessage('common.success', '加载成功'));  
 | 
    })  
 | 
  } catch (error) {  
 | 
    message.error(formatMessage('common.fail', '加载失败'));  
 | 
  } finally {  
 | 
    hide();  
 | 
  }  
 | 
}  
 | 
  
 | 
function closeAllTabs() {  
 | 
  routerCache.value = [];  
 | 
  routerCacheList.value = [];  
 | 
  router.push({  
 | 
    path: '/'  
 | 
  })  
 | 
}  
 | 
  
 | 
function switchTabs(item) {  
 | 
  router.push({  
 | 
    path: item.key  
 | 
  })  
 | 
  
 | 
  currentCache.value = item.name;  
 | 
  selectedKeys.value = [item.key]  
 | 
  
 | 
  // open menu  
 | 
  // let arr = item.key.split("/");  
 | 
  // let key = '/' + arr[1];  
 | 
  // openKeys.value = [key]  
 | 
}  
 | 
  
 | 
const switchLocale = async (locale) => {  
 | 
  globalState.locale = locale;  
 | 
  localStorage.setItem('locale', locale)  
 | 
  loadData(locale);  
 | 
  reloadTabs()  
 | 
}  
 | 
  
 | 
getHostList()  
 | 
function getHostList() {  
 | 
  post('/api/show/host.action', {}).then((resp) => {  
 | 
    let result = resp.data;  
 | 
    let data = result.data;  
 | 
    let hostId = data.hostId;  
 | 
    if (data.root) {  
 | 
      post('/api/host/list', {}).then((resp) => {  
 | 
        let result = resp.data;  
 | 
        let data = result.data;  
 | 
        hostList.value = data;  
 | 
        data.forEach((item) => {  
 | 
          if (item.id == hostId) {  
 | 
            globalState.currentHost = item;  
 | 
          }  
 | 
        })  
 | 
      })  
 | 
    }  
 | 
  })  
 | 
}  
 | 
  
 | 
const licenseDays = ref(365);  
 | 
getLicenseDays();  
 | 
function getLicenseDays() {  
 | 
  post('/api/license/getLicenseDays', {}).then((resp) => {  
 | 
    let result = resp.data;  
 | 
    let data = result.data;  
 | 
    if (result.code == 200) {  
 | 
      licenseDays.value = data;  
 | 
    }  
 | 
  })  
 | 
}  
 | 
  
 | 
const switchHost = (item) => {  
 | 
  globalState.currentHost = item;  
 | 
  postForm('/api/root/change/host/auth', {  
 | 
    hostId: item.id  
 | 
  }).then((resp) => {  
 | 
    let result = resp.data;  
 | 
    if (result.code == 200) {  
 | 
      window.location.reload();  
 | 
    } else {  
 | 
      message.error(formatMessage('common.fail', '加载失败'));  
 | 
    }  
 | 
  })  
 | 
}  
 | 
  
 | 
const windowReload = () => {  
 | 
  window.location.reload();  
 | 
}  
 | 
  
 | 
const handleScroll = (data) => {  
 | 
  let position = tabsContent.value.scrollLeft;  
 | 
  let offset = position * 0.1 + 30;  
 | 
  if (data == 'left') {  
 | 
    tabsContent.value.scrollLeft = position - offset;  
 | 
  } else {  
 | 
    tabsContent.value.scrollLeft = position + offset;  
 | 
  }  
 | 
}  
 | 
  
 | 
const onOpenChange = (openKeys) => {  
 | 
    const latestOpenKey = openKeys.find(  
 | 
        (key) => state.openKeys.indexOf(key) === -1  
 | 
    );  
 | 
    if (state.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {  
 | 
        state.openKeys = openKeys  
 | 
    } else {  
 | 
        state.openKeys = latestOpenKey ? [latestOpenKey] : [];  
 | 
    }  
 | 
    console.log(state.openKeys)  
 | 
}  
 | 
  
 | 
</script>  
 | 
  
 | 
<template>  
 | 
  <a-flex gap="middle" horizontal>  
 | 
      <div class="sider-style">  
 | 
        <a-layout-sider class="main-sider" v-model:collapsed="collapsed" :trigger="null"  theme="dark">  
 | 
        <div class="logo" />  
 | 
        <a-menu v-model:openKeys="state.openKeys" v-model:selectedKeys="state.selectedKeys"  @select="menuSelect"  theme="dark"  
 | 
                mode="inline" @openChange="onOpenChange">  
 | 
          <div>  
 | 
            <a-menu-item key="/" name="主页">  
 | 
              <HomeOutlined /> {{ formatMessage('common.home', '主页') }}  
 | 
            </a-menu-item>  
 | 
          </div>  
 | 
  
 | 
          <div v-for="(item, index) in menuCache" :key="index">  
 | 
            <a-sub-menu :key="item.route" v-if="item.type == 0">  
 | 
              <template #title>  
 | 
              <span>  
 | 
                <component :is="components[ref(item.icon).value]" />  
 | 
                {{ formatMessage(item.languageId, item.name) }}  
 | 
              </span>  
 | 
              </template>  
 | 
              <div v-for="(child, idx) in item.children">  
 | 
                <a-menu-item v-if="child.status == 1" :key="child.route" :name="child.name"  
 | 
                             :languageId="child.languageId">  
 | 
                  {{ formatMessage(child.languageId, child.name) }}  
 | 
                </a-menu-item>  
 | 
              </div>  
 | 
            </a-sub-menu>  
 | 
          </div>  
 | 
        </a-menu>  
 | 
      </a-layout-sider>  
 | 
      </div>  
 | 
    <a-layout class="main">  
 | 
      <a-layout>  
 | 
        <a-layout-header style="background: #fff; padding: 0;">  
 | 
          <div class="header-top">  
 | 
            <div class="header-top-left">  
 | 
              <MenuUnfoldOutlined v-if="collapsed" class="trigger triggerLarge" @click="() => (collapsed = !collapsed)" />  
 | 
              <MenuFoldOutlined v-else class="trigger" @click="() => (collapsed = !collapsed)" />  
 | 
              <RedoOutlined class="trigger" @click="windowReload()" />  
 | 
            </div>  
 | 
            <div class="header-top-right">  
 | 
              <div class="trigger" style="color: red;" v-if="licenseDays <= 30">  
 | 
                许可证有效期:{{ licenseDays }}天  
 | 
              </div>  
 | 
              <div class="trigger" v-if="globalState.currentHost">  
 | 
                <a-dropdown>  
 | 
                  <div>  
 | 
                    <ApartmentOutlined />  
 | 
                    {{ globalState.currentHost?.name }}  
 | 
                  </div>  
 | 
                  <template #overlay>  
 | 
                    <a-menu>  
 | 
                      <a-menu-item v-for="(item, index) in hostList" :key="index" @click="switchHost(item)"  
 | 
                                   :class="globalState.currentHost?.id == item.id ? 'active' : ''">{{ item.name }}</a-menu-item>  
 | 
                    </a-menu>  
 | 
                  </template>  
 | 
                </a-dropdown>  
 | 
              </div>  
 | 
              <div class="trigger">  
 | 
                <a-dropdown>  
 | 
                  <div>  
 | 
                    <TranslationOutlined />  
 | 
                    {{ globalState.localeList[globalState.locale]?.desc }}  
 | 
                  </div>  
 | 
                  <template #overlay>  
 | 
                    <a-menu>  
 | 
                      <div v-for="(item, key) in globalState.localeList" :key="key">  
 | 
                        <a-menu-item @click="switchLocale(key)" :class="globalState.locale == key ? 'active' : ''">{{  
 | 
                          item.desc }}</a-menu-item>  
 | 
                      </div>  
 | 
                    </a-menu>  
 | 
                  </template>  
 | 
                </a-dropdown>  
 | 
              </div>  
 | 
              <div>  
 | 
                <a-dropdown>  
 | 
                  <a class="header-user" @click.prevent>  
 | 
                    <UserOutlined />  
 | 
                    <span>{{ globalState.user.username }}</span>  
 | 
                  </a>  
 | 
                  <template #overlay>  
 | 
                    <a-menu @click="logout">  
 | 
                      <a-menu-item key="logout">{{ formatMessage('common.account.logout', '退出') }}</a-menu-item>  
 | 
                    </a-menu>  
 | 
                  </template>  
 | 
                </a-dropdown>  
 | 
              </div>  
 | 
            </div>  
 | 
          </div>  
 | 
        </a-layout-header>  
 | 
        <a-layout-content class="content-view">  
 | 
          <div class="tabs-fixed">  
 | 
            <div class="tabs-arrow-left" @click="handleScroll('left')">  
 | 
              <CaretLeftOutlined />  
 | 
            </div>  
 | 
  
 | 
            <div class="tabs-content" ref="tabsContent">  
 | 
              <div class="tabs-content-item">  
 | 
                <div v-for="(item, index) in routerCacheList" :key="index" @click="switchTabs(item)" class="tabs-item"  
 | 
                     :class="currentCache == item.name ? 'tabs-item-active' : ''">  
 | 
                  <div :class="currentCache == item.name ? '' : 'tabs-item-reload-none'" @click="reloadTabs" @click.stop>  
 | 
                    <RedoOutlined />  
 | 
                  </div>  
 | 
                  <div>{{ formatMessage(item.languageId, item.name) }}</div>  
 | 
                  <div @click="closeTabs(item)" @click.stop>  
 | 
                    <CloseOutlined />  
 | 
                  </div>  
 | 
                </div>  
 | 
              </div>  
 | 
            </div>  
 | 
  
 | 
            <div class="tabs-arrow-right" @click="handleScroll('right')">  
 | 
              <CaretRightOutlined />  
 | 
            </div>  
 | 
          </div>  
 | 
  
 | 
          <router-view v-slot="{ Component, route }" v-if="isRouterAlive">  
 | 
            <keep-alive :include="routerCache">  
 | 
              <component :is="Component" @pageReload="reloadTabs" />  
 | 
            </keep-alive>  
 | 
          </router-view>  
 | 
        </a-layout-content>  
 | 
      </a-layout>  
 | 
    </a-layout>  
 | 
  </a-flex>  
 | 
  <!--<AiView />-->  
 | 
</template>  
 | 
  
 | 
<style scoped>  
 | 
  .ant-layout-sider ant-layout-sider-dark main-sider {  
 | 
     max-height: 100vh;  
 | 
    background: #01101E;  
 | 
  }  
 | 
  
 | 
</style>  
 |