mirror of
				https://github.com/pure-admin/vue-pure-admin.git
				synced 2025-11-03 13:44:47 +08:00 
			
		
		
		
	
							parent
							
								
									a2dde02994
								
							
						
					
					
						commit
						ef05b2b614
					
				@ -126,13 +126,13 @@ If you think this project is helpful to you, you can help the author buy a cup o
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## License
 | 
					## License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In principle, no fees and copyrights are charged, so you can use it with confidence
 | 
					In principle, no fees and copyrights are charged, and you can use it with confidence, but if you need secondary open source, please contact the author for permission!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[MIT © xiaoxian521-2020](./LICENSE)
 | 
					[MIT © xiaoxian521-2020](./LICENSE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Backers
 | 
					## Backers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Thank you very much for your support, I believe the project will get better and better! ! ! :heart:
 | 
					Thank you very much for your support, I believe the project will get better and better :heart:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
|                                                                xueyuheng                                                                 |                                                                taolei1990                                                                 |                                                                hang-kim                                                                 |                                                               madwolfcrazy                                                                |                                                                limuen                                                                 |
 | 
					|                                                                xueyuheng                                                                 |                                                                taolei1990                                                                 |                                                                hang-kim                                                                 |                                                               madwolfcrazy                                                                |                                                                limuen                                                                 |
 | 
				
			||||||
| :--------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------: |
 | 
					| :--------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------: |
 | 
				
			||||||
@ -140,6 +140,6 @@ Thank you very much for your support, I believe the project will get better and
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Contributors
 | 
					## Contributors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This project exists thanks to all the people who contribute!!! :heart:
 | 
					This project exists thanks to all the people who contribute :heart:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<a href="https://github.com/xiaoxian521/vue-pure-admin/graphs/contributors"><img src="https://contrib.rocks/image?repo=xiaoxian521/vue-pure-admin" /></a>
 | 
					<a href="https://github.com/xiaoxian521/vue-pure-admin/graphs/contributors"><img src="https://contrib.rocks/image?repo=xiaoxian521/vue-pure-admin" /></a>
 | 
				
			||||||
 | 
				
			|||||||
@ -132,13 +132,13 @@ pnpm build
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## 许可证
 | 
					## 许可证
 | 
				
			||||||
 | 
					
 | 
				
			||||||
原则上不收取任何费用及版权,可以放心使用
 | 
					原则上不收取任何费用及版权,可以放心使用,不过如需二次开源(比如用此平台二次开发并开源)请联系作者获取许可!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[MIT © xiaoxian521-2020](./LICENSE)
 | 
					[MIT © xiaoxian521-2020](./LICENSE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 捐赠者
 | 
					## 捐赠者
 | 
				
			||||||
 | 
					
 | 
				
			||||||
非常感谢你们的支持,相信项目会越来越好!!!:heart:
 | 
					非常感谢你们的支持,相信项目会越来越好 :heart:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
|                                                                xueyuheng                                                                 |                                                                taolei1990                                                                 |                                                                hang-kim                                                                 |                                                               madwolfcrazy                                                                |                                                                limuen                                                                 |
 | 
					|                                                                xueyuheng                                                                 |                                                                taolei1990                                                                 |                                                                hang-kim                                                                 |                                                               madwolfcrazy                                                                |                                                                limuen                                                                 |
 | 
				
			||||||
| :--------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------: |
 | 
					| :--------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------: |
 | 
				
			||||||
@ -146,6 +146,6 @@ pnpm build
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## 贡献者
 | 
					## 贡献者
 | 
				
			||||||
 | 
					
 | 
				
			||||||
这个项目的存在感谢所有做出贡献的人!!!:heart:
 | 
					这个项目的存在感谢所有做出贡献的人 :heart:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<a href="https://github.com/xiaoxian521/vue-pure-admin/graphs/contributors"><img src="https://contrib.rocks/image?repo=xiaoxian521/vue-pure-admin" /></a>
 | 
					<a href="https://github.com/xiaoxian521/vue-pure-admin/graphs/contributors"><img src="https://contrib.rocks/image?repo=xiaoxian521/vue-pure-admin" /></a>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										24
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								package.json
									
									
									
									
									
								
							@ -33,17 +33,17 @@
 | 
				
			|||||||
    "@ctrl/tinycolor": "^3.4.0",
 | 
					    "@ctrl/tinycolor": "^3.4.0",
 | 
				
			||||||
    "@logicflow/core": "0.7.1",
 | 
					    "@logicflow/core": "0.7.1",
 | 
				
			||||||
    "@logicflow/extension": "0.7.1",
 | 
					    "@logicflow/extension": "0.7.1",
 | 
				
			||||||
    "@vueuse/core": "^7.5.5",
 | 
					    "@vueuse/core": "^7.6.2",
 | 
				
			||||||
    "@vueuse/motion": "^2.0.0-beta.9",
 | 
					    "@vueuse/motion": "^2.0.0-beta.9",
 | 
				
			||||||
    "@vueuse/shared": "^7.5.5",
 | 
					    "@vueuse/shared": "^7.6.2",
 | 
				
			||||||
    "animate.css": "^4.1.1",
 | 
					    "animate.css": "^4.1.1",
 | 
				
			||||||
    "axios": "^0.25.0",
 | 
					    "axios": "^0.25.0",
 | 
				
			||||||
    "cropperjs": "^1.5.11",
 | 
					    "cropperjs": "^1.5.11",
 | 
				
			||||||
    "css-color-function": "^1.3.3",
 | 
					    "css-color-function": "^1.3.3",
 | 
				
			||||||
    "dayjs": "^1.10.7",
 | 
					    "dayjs": "^1.10.7",
 | 
				
			||||||
    "driver.js": "^0.9.8",
 | 
					    "driver.js": "^0.9.8",
 | 
				
			||||||
    "echarts": "^5.2.1",
 | 
					    "echarts": "^5.3.0",
 | 
				
			||||||
    "element-plus": "^2.0.0",
 | 
					    "element-plus": "^2.0.2",
 | 
				
			||||||
    "element-resize-detector": "^1.2.3",
 | 
					    "element-resize-detector": "^1.2.3",
 | 
				
			||||||
    "js-cookie": "^3.0.1",
 | 
					    "js-cookie": "^3.0.1",
 | 
				
			||||||
    "lodash-es": "^4.17.21",
 | 
					    "lodash-es": "^4.17.21",
 | 
				
			||||||
@ -57,7 +57,7 @@
 | 
				
			|||||||
    "responsive-storage": "^1.0.11",
 | 
					    "responsive-storage": "^1.0.11",
 | 
				
			||||||
    "rgb-hex": "^4.0.0",
 | 
					    "rgb-hex": "^4.0.0",
 | 
				
			||||||
    "v-contextmenu": "3.0.0",
 | 
					    "v-contextmenu": "3.0.0",
 | 
				
			||||||
    "vue": "^3.2.29",
 | 
					    "vue": "^3.2.31",
 | 
				
			||||||
    "vue-i18n": "^9.2.0-beta.30",
 | 
					    "vue-i18n": "^9.2.0-beta.30",
 | 
				
			||||||
    "vue-json-pretty": "^2.0.2",
 | 
					    "vue-json-pretty": "^2.0.2",
 | 
				
			||||||
    "vue-router": "^4.0.12",
 | 
					    "vue-router": "^4.0.12",
 | 
				
			||||||
@ -84,9 +84,9 @@
 | 
				
			|||||||
    "@types/qs": "^6.9.7",
 | 
					    "@types/qs": "^6.9.7",
 | 
				
			||||||
    "@typescript-eslint/eslint-plugin": "^5.10.2",
 | 
					    "@typescript-eslint/eslint-plugin": "^5.10.2",
 | 
				
			||||||
    "@typescript-eslint/parser": "^5.10.2",
 | 
					    "@typescript-eslint/parser": "^5.10.2",
 | 
				
			||||||
    "@vitejs/plugin-legacy": "^1.6.4",
 | 
					    "@vitejs/plugin-legacy": "^1.7.0",
 | 
				
			||||||
    "@vitejs/plugin-vue": "^2.1.0",
 | 
					    "@vitejs/plugin-vue": "^2.2.0",
 | 
				
			||||||
    "@vitejs/plugin-vue-jsx": "^1.3.3",
 | 
					    "@vitejs/plugin-vue-jsx": "^1.3.4",
 | 
				
			||||||
    "@vue/eslint-config-prettier": "^7.0.0",
 | 
					    "@vue/eslint-config-prettier": "^7.0.0",
 | 
				
			||||||
    "@vue/eslint-config-typescript": "^10.0.0",
 | 
					    "@vue/eslint-config-typescript": "^10.0.0",
 | 
				
			||||||
    "@zougt/vite-plugin-theme-preprocessor": "^1.4.4",
 | 
					    "@zougt/vite-plugin-theme-preprocessor": "^1.4.4",
 | 
				
			||||||
@ -97,7 +97,7 @@
 | 
				
			|||||||
    "eslint-plugin-vue": "^8.4.1",
 | 
					    "eslint-plugin-vue": "^8.4.1",
 | 
				
			||||||
    "husky": "^7.0.4",
 | 
					    "husky": "^7.0.4",
 | 
				
			||||||
    "lint-staged": "11.1.2",
 | 
					    "lint-staged": "11.1.2",
 | 
				
			||||||
    "postcss": "8.2.6",
 | 
					    "postcss": "^8.4.6",
 | 
				
			||||||
    "postcss-html": "^1.3.0",
 | 
					    "postcss-html": "^1.3.0",
 | 
				
			||||||
    "postcss-import": "14.0.0",
 | 
					    "postcss-import": "14.0.0",
 | 
				
			||||||
    "postcss-scss": "^4.0.3",
 | 
					    "postcss-scss": "^4.0.3",
 | 
				
			||||||
@ -115,12 +115,12 @@
 | 
				
			|||||||
    "stylelint-order": "^5.0.0",
 | 
					    "stylelint-order": "^5.0.0",
 | 
				
			||||||
    "typescript": "^4.5.5",
 | 
					    "typescript": "^4.5.5",
 | 
				
			||||||
    "unplugin-element-plus": "^0.2.0",
 | 
					    "unplugin-element-plus": "^0.2.0",
 | 
				
			||||||
    "vite": "^2.7.13",
 | 
					    "vite": "^2.8.1",
 | 
				
			||||||
    "vite-plugin-live-reload": "^2.1.0",
 | 
					    "vite-plugin-live-reload": "^2.1.0",
 | 
				
			||||||
    "vite-plugin-mock": "^2.9.6",
 | 
					    "vite-plugin-mock": "^2.9.6",
 | 
				
			||||||
    "vite-plugin-remove-console": "^0.0.6",
 | 
					    "vite-plugin-remove-console": "^0.0.6",
 | 
				
			||||||
    "vite-plugin-style-import": "^1.4.1",
 | 
					    "vite-plugin-style-import": "1.4.1",
 | 
				
			||||||
    "vite-plugin-windicss": "^1.6.1",
 | 
					    "vite-plugin-windicss": "^1.7.0",
 | 
				
			||||||
    "vite-svg-loader": "2.2.0",
 | 
					    "vite-svg-loader": "2.2.0",
 | 
				
			||||||
    "vue-eslint-parser": "^8.2.0",
 | 
					    "vue-eslint-parser": "^8.2.0",
 | 
				
			||||||
    "windicss": "^3.4.3"
 | 
					    "windicss": "^3.4.3"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1216
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1216
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -1,71 +1,43 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { computed } from "vue";
 | 
					 | 
				
			||||||
import { useI18n } from "vue-i18n";
 | 
					import { useI18n } from "vue-i18n";
 | 
				
			||||||
import { emitter } from "/@/utils/mitt";
 | 
					import { useNav } from "../hooks/nav";
 | 
				
			||||||
 | 
					import { useRoute } from "vue-router";
 | 
				
			||||||
import Notice from "./notice/index.vue";
 | 
					import Notice from "./notice/index.vue";
 | 
				
			||||||
 | 
					import mixNav from "./sidebar/mixNav.vue";
 | 
				
			||||||
import avatars from "/@/assets/avatars.jpg";
 | 
					import avatars from "/@/assets/avatars.jpg";
 | 
				
			||||||
import { transformI18n } from "/@/plugins/i18n";
 | 
					 | 
				
			||||||
import Hamburger from "./sidebar/hamBurger.vue";
 | 
					import Hamburger from "./sidebar/hamBurger.vue";
 | 
				
			||||||
import { useRouter, useRoute } from "vue-router";
 | 
					import { watch, getCurrentInstance } from "vue";
 | 
				
			||||||
import { storageSession } from "/@/utils/storage";
 | 
					 | 
				
			||||||
import Breadcrumb from "./sidebar/breadCrumb.vue";
 | 
					import Breadcrumb from "./sidebar/breadCrumb.vue";
 | 
				
			||||||
import { useAppStoreHook } from "/@/store/modules/app";
 | 
					 | 
				
			||||||
import { unref, watch, getCurrentInstance } from "vue";
 | 
					 | 
				
			||||||
import { deviceDetection } from "/@/utils/deviceDetection";
 | 
					import { deviceDetection } from "/@/utils/deviceDetection";
 | 
				
			||||||
import screenfull from "../components/screenfull/index.vue";
 | 
					import screenfull from "../components/screenfull/index.vue";
 | 
				
			||||||
import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
 | 
					 | 
				
			||||||
import globalization from "/@/assets/svg/globalization.svg?component";
 | 
					import globalization from "/@/assets/svg/globalization.svg?component";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const route = useRoute();
 | 
				
			||||||
 | 
					const { locale } = useI18n();
 | 
				
			||||||
const instance =
 | 
					const instance =
 | 
				
			||||||
  getCurrentInstance().appContext.config.globalProperties.$storage;
 | 
					  getCurrentInstance().appContext.config.globalProperties.$storage;
 | 
				
			||||||
const pureApp = useAppStoreHook();
 | 
					const {
 | 
				
			||||||
const router = useRouter();
 | 
					  logout,
 | 
				
			||||||
const route = useRoute();
 | 
					  onPanel,
 | 
				
			||||||
let usename = storageSession.getItem("info")?.username;
 | 
					  changeTitle,
 | 
				
			||||||
const { locale } = useI18n();
 | 
					  toggleSideBar,
 | 
				
			||||||
 | 
					  pureApp,
 | 
				
			||||||
const getDropdownItemStyle = computed(() => {
 | 
					  usename,
 | 
				
			||||||
  return t => {
 | 
					  getDropdownItemStyle
 | 
				
			||||||
    return {
 | 
					} = useNav();
 | 
				
			||||||
      background: locale.value === t ? useEpThemeStoreHook().epThemeColor : "",
 | 
					 | 
				
			||||||
      color: locale.value === t ? "#f4f4f5" : "#000"
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(
 | 
					watch(
 | 
				
			||||||
  () => locale.value,
 | 
					  () => locale.value,
 | 
				
			||||||
  () => {
 | 
					  () => {
 | 
				
			||||||
    //@ts-ignore
 | 
					    changeTitle(route.meta);
 | 
				
			||||||
    document.title = transformI18n(
 | 
					 | 
				
			||||||
      //@ts-ignore
 | 
					 | 
				
			||||||
      unref(route.meta.title),
 | 
					 | 
				
			||||||
      unref(route.meta.i18n)
 | 
					 | 
				
			||||||
    ); // 动态title
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 退出登录
 | 
					 | 
				
			||||||
const logout = (): void => {
 | 
					 | 
				
			||||||
  storageSession.removeItem("info");
 | 
					 | 
				
			||||||
  router.push("/login");
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function onPanel() {
 | 
					 | 
				
			||||||
  emitter.emit("openPanel");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function toggleSideBar() {
 | 
					 | 
				
			||||||
  pureApp.toggleSideBar();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 简体中文
 | 
					 | 
				
			||||||
function translationCh() {
 | 
					function translationCh() {
 | 
				
			||||||
  instance.locale = { locale: "zh" };
 | 
					  instance.locale = { locale: "zh" };
 | 
				
			||||||
  locale.value = "zh";
 | 
					  locale.value = "zh";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// English
 | 
					 | 
				
			||||||
function translationEn() {
 | 
					function translationEn() {
 | 
				
			||||||
  instance.locale = { locale: "en" };
 | 
					  instance.locale = { locale: "en" };
 | 
				
			||||||
  locale.value = "en";
 | 
					  locale.value = "en";
 | 
				
			||||||
@ -75,14 +47,17 @@ function translationEn() {
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="navbar">
 | 
					  <div class="navbar">
 | 
				
			||||||
    <Hamburger
 | 
					    <Hamburger
 | 
				
			||||||
 | 
					      v-if="pureApp.layout !== 'mix'"
 | 
				
			||||||
      :is-active="pureApp.sidebar.opened"
 | 
					      :is-active="pureApp.sidebar.opened"
 | 
				
			||||||
      class="hamburger-container"
 | 
					      class="hamburger-container"
 | 
				
			||||||
      @toggleClick="toggleSideBar"
 | 
					      @toggleClick="toggleSideBar"
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <Breadcrumb class="breadcrumb-container" />
 | 
					    <Breadcrumb v-if="pureApp.layout !== 'mix'" class="breadcrumb-container" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="vertical-header-right">
 | 
					    <mixNav v-if="pureApp.layout === 'mix'" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div v-if="pureApp.layout === 'vertical'" class="vertical-header-right">
 | 
				
			||||||
      <!-- 通知 -->
 | 
					      <!-- 通知 -->
 | 
				
			||||||
      <Notice id="header-notice" />
 | 
					      <Notice id="header-notice" />
 | 
				
			||||||
      <!-- 全屏 -->
 | 
					      <!-- 全屏 -->
 | 
				
			||||||
@ -93,7 +68,7 @@ function translationEn() {
 | 
				
			|||||||
        <template #dropdown>
 | 
					        <template #dropdown>
 | 
				
			||||||
          <el-dropdown-menu class="translation">
 | 
					          <el-dropdown-menu class="translation">
 | 
				
			||||||
            <el-dropdown-item
 | 
					            <el-dropdown-item
 | 
				
			||||||
              :style="getDropdownItemStyle('zh')"
 | 
					              :style="getDropdownItemStyle(locale, 'zh')"
 | 
				
			||||||
              @click="translationCh"
 | 
					              @click="translationCh"
 | 
				
			||||||
              ><IconifyIconOffline
 | 
					              ><IconifyIconOffline
 | 
				
			||||||
                class="check-zh"
 | 
					                class="check-zh"
 | 
				
			||||||
@ -102,7 +77,7 @@ function translationEn() {
 | 
				
			|||||||
              />简体中文</el-dropdown-item
 | 
					              />简体中文</el-dropdown-item
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
            <el-dropdown-item
 | 
					            <el-dropdown-item
 | 
				
			||||||
              :style="getDropdownItemStyle('en')"
 | 
					              :style="getDropdownItemStyle(locale, 'en')"
 | 
				
			||||||
              @click="translationEn"
 | 
					              @click="translationEn"
 | 
				
			||||||
              ><el-icon class="check-en" v-show="locale === 'en'"
 | 
					              ><el-icon class="check-en" v-show="locale === 'en'"
 | 
				
			||||||
                ><IconifyIconOffline icon="check" /></el-icon
 | 
					                ><IconifyIconOffline icon="check" /></el-icon
 | 
				
			||||||
 | 
				
			|||||||
@ -61,6 +61,7 @@ let themeColors = ref<Array<themeColorsType>>([
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const verticalRef = templateRef<HTMLElement | null>("verticalRef", null);
 | 
					const verticalRef = templateRef<HTMLElement | null>("verticalRef", null);
 | 
				
			||||||
const horizontalRef = templateRef<HTMLElement | null>("horizontalRef", null);
 | 
					const horizontalRef = templateRef<HTMLElement | null>("horizontalRef", null);
 | 
				
			||||||
 | 
					const mixRef = templateRef<HTMLElement | null>("mixRef", null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let layoutTheme =
 | 
					let layoutTheme =
 | 
				
			||||||
  ref(storageLocal.getItem("responsive-layout")) ||
 | 
					  ref(storageLocal.getItem("responsive-layout")) ||
 | 
				
			||||||
@ -101,7 +102,7 @@ const getThemeColorStyle = computed(() => {
 | 
				
			|||||||
  };
 | 
					  };
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function changeStorageConfigure(key, val) {
 | 
					function storageConfigureChange<T>(key: string, val: T): void {
 | 
				
			||||||
  const storageConfigure = instance.configure;
 | 
					  const storageConfigure = instance.configure;
 | 
				
			||||||
  storageConfigure[key] = val;
 | 
					  storageConfigure[key] = val;
 | 
				
			||||||
  instance.configure = storageConfigure;
 | 
					  instance.configure = storageConfigure;
 | 
				
			||||||
@ -117,7 +118,7 @@ function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
 | 
				
			|||||||
// 灰色模式设置
 | 
					// 灰色模式设置
 | 
				
			||||||
const greyChange = (value): void => {
 | 
					const greyChange = (value): void => {
 | 
				
			||||||
  toggleClass(settings.greyVal, "html-grey", document.querySelector("html"));
 | 
					  toggleClass(settings.greyVal, "html-grey", document.querySelector("html"));
 | 
				
			||||||
  changeStorageConfigure("grey", value);
 | 
					  storageConfigureChange("grey", value);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 色弱模式设置
 | 
					// 色弱模式设置
 | 
				
			||||||
@ -127,29 +128,30 @@ const weekChange = (value): void => {
 | 
				
			|||||||
    "html-weakness",
 | 
					    "html-weakness",
 | 
				
			||||||
    document.querySelector("html")
 | 
					    document.querySelector("html")
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
  changeStorageConfigure("weak", value);
 | 
					  storageConfigureChange("weak", value);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const tagsChange = () => {
 | 
					const tagsChange = () => {
 | 
				
			||||||
  let showVal = settings.tabsVal;
 | 
					  let showVal = settings.tabsVal;
 | 
				
			||||||
  changeStorageConfigure("hideTabs", showVal);
 | 
					  storageConfigureChange("hideTabs", showVal);
 | 
				
			||||||
  emitter.emit("tagViewsChange", showVal);
 | 
					  emitter.emit("tagViewsChange", showVal);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const multiTagsCacheChange = () => {
 | 
					const multiTagsCacheChange = () => {
 | 
				
			||||||
  let multiTagsCache = settings.multiTagsCache;
 | 
					  let multiTagsCache = settings.multiTagsCache;
 | 
				
			||||||
  changeStorageConfigure("multiTagsCache", multiTagsCache);
 | 
					  storageConfigureChange("multiTagsCache", multiTagsCache);
 | 
				
			||||||
  useMultiTagsStoreHook().multiTagsCacheChange(multiTagsCache);
 | 
					  useMultiTagsStoreHook().multiTagsCacheChange(multiTagsCache);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 清空缓存并返回登录页
 | 
					// 清空缓存并返回登录页
 | 
				
			||||||
function onReset() {
 | 
					function onReset() {
 | 
				
			||||||
  toggleClass(getConfig().Grey, "html-grey", document.querySelector("html"));
 | 
					  router.push("/login");
 | 
				
			||||||
  toggleClass(
 | 
					  const { Grey, Weak, MultiTagsCache, EpThemeColor, Layout } = getConfig();
 | 
				
			||||||
    getConfig().Weak,
 | 
					  useAppStoreHook().setLayout(Layout);
 | 
				
			||||||
    "html-weakness",
 | 
					  useEpThemeStoreHook().setEpThemeColor(EpThemeColor);
 | 
				
			||||||
    document.querySelector("html")
 | 
					  useMultiTagsStoreHook().multiTagsCacheChange(MultiTagsCache);
 | 
				
			||||||
  );
 | 
					  toggleClass(Grey, "html-grey", document.querySelector("html"));
 | 
				
			||||||
 | 
					  toggleClass(Weak, "html-weakness", document.querySelector("html"));
 | 
				
			||||||
  useMultiTagsStoreHook().handleTags("equal", [
 | 
					  useMultiTagsStoreHook().handleTags("equal", [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      path: "/welcome",
 | 
					      path: "/welcome",
 | 
				
			||||||
@ -161,23 +163,20 @@ function onReset() {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]);
 | 
					  ]);
 | 
				
			||||||
  useMultiTagsStoreHook().multiTagsCacheChange(getConfig().MultiTagsCache);
 | 
					 | 
				
			||||||
  useEpThemeStoreHook().setEpThemeColor(getConfig().EpThemeColor);
 | 
					 | 
				
			||||||
  storageLocal.clear();
 | 
					  storageLocal.clear();
 | 
				
			||||||
  storageSession.clear();
 | 
					  storageSession.clear();
 | 
				
			||||||
  router.push("/login");
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function onChange(label) {
 | 
					function onChange(label) {
 | 
				
			||||||
  changeStorageConfigure("showModel", label);
 | 
					  storageConfigureChange("showModel", label);
 | 
				
			||||||
  emitter.emit("tagViewsShowModel", label);
 | 
					  emitter.emit("tagViewsShowModel", label);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 侧边栏Logo
 | 
					// 侧边栏Logo
 | 
				
			||||||
function logoChange() {
 | 
					function logoChange() {
 | 
				
			||||||
  unref(logoVal)
 | 
					  unref(logoVal)
 | 
				
			||||||
    ? changeStorageConfigure("showLogo", true)
 | 
					    ? storageConfigureChange("showLogo", true)
 | 
				
			||||||
    : changeStorageConfigure("showLogo", false);
 | 
					    : storageConfigureChange("showLogo", false);
 | 
				
			||||||
  emitter.emit("logoChange", unref(logoVal));
 | 
					  emitter.emit("logoChange", unref(logoVal));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -192,10 +191,17 @@ watch(instance, ({ layout }) => {
 | 
				
			|||||||
    case "vertical":
 | 
					    case "vertical":
 | 
				
			||||||
      toggleClass(true, isSelect, unref(verticalRef));
 | 
					      toggleClass(true, isSelect, unref(verticalRef));
 | 
				
			||||||
      debounce(setFalse([horizontalRef]), 50);
 | 
					      debounce(setFalse([horizontalRef]), 50);
 | 
				
			||||||
 | 
					      debounce(setFalse([mixRef]), 50);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    case "horizontal":
 | 
					    case "horizontal":
 | 
				
			||||||
      toggleClass(true, isSelect, unref(horizontalRef));
 | 
					      toggleClass(true, isSelect, unref(horizontalRef));
 | 
				
			||||||
      debounce(setFalse([verticalRef]), 50);
 | 
					      debounce(setFalse([verticalRef]), 50);
 | 
				
			||||||
 | 
					      debounce(setFalse([mixRef]), 50);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case "mix":
 | 
				
			||||||
 | 
					      toggleClass(true, isSelect, unref(mixRef));
 | 
				
			||||||
 | 
					      debounce(setFalse([verticalRef]), 50);
 | 
				
			||||||
 | 
					      debounce(setFalse([horizontalRef]), 50);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
@ -315,7 +321,7 @@ nextTick(() => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <el-divider>导航栏模式</el-divider>
 | 
					    <el-divider>导航栏模式</el-divider>
 | 
				
			||||||
    <ul class="pure-theme">
 | 
					    <ul class="pure-theme">
 | 
				
			||||||
      <el-tooltip class="item" content="左侧菜单模式" placement="bottom">
 | 
					      <el-tooltip class="item" content="左侧模式" placement="bottom">
 | 
				
			||||||
        <li
 | 
					        <li
 | 
				
			||||||
          :class="layoutTheme.layout === 'vertical' ? $style.isSelect : ''"
 | 
					          :class="layoutTheme.layout === 'vertical' ? $style.isSelect : ''"
 | 
				
			||||||
          ref="verticalRef"
 | 
					          ref="verticalRef"
 | 
				
			||||||
@ -326,7 +332,7 @@ nextTick(() => {
 | 
				
			|||||||
        </li>
 | 
					        </li>
 | 
				
			||||||
      </el-tooltip>
 | 
					      </el-tooltip>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <el-tooltip class="item" content="顶部菜单模式" placement="bottom">
 | 
					      <el-tooltip class="item" content="顶部模式" placement="bottom">
 | 
				
			||||||
        <li
 | 
					        <li
 | 
				
			||||||
          :class="layoutTheme.layout === 'horizontal' ? $style.isSelect : ''"
 | 
					          :class="layoutTheme.layout === 'horizontal' ? $style.isSelect : ''"
 | 
				
			||||||
          ref="horizontalRef"
 | 
					          ref="horizontalRef"
 | 
				
			||||||
@ -336,6 +342,17 @@ nextTick(() => {
 | 
				
			|||||||
          <div></div>
 | 
					          <div></div>
 | 
				
			||||||
        </li>
 | 
					        </li>
 | 
				
			||||||
      </el-tooltip>
 | 
					      </el-tooltip>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <el-tooltip class="item" content="混合模式" placement="bottom">
 | 
				
			||||||
 | 
					        <li
 | 
				
			||||||
 | 
					          :class="layoutTheme.layout === 'mix' ? $style.isSelect : ''"
 | 
				
			||||||
 | 
					          ref="mixRef"
 | 
				
			||||||
 | 
					          @click="setLayoutModel('mix')"
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <div></div>
 | 
				
			||||||
 | 
					          <div></div>
 | 
				
			||||||
 | 
					        </li>
 | 
				
			||||||
 | 
					      </el-tooltip>
 | 
				
			||||||
    </ul>
 | 
					    </ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <el-divider v-show="!dataTheme">主题色</el-divider>
 | 
					    <el-divider v-show="!dataTheme">主题色</el-divider>
 | 
				
			||||||
@ -481,15 +498,14 @@ nextTick(() => {
 | 
				
			|||||||
.pure-theme {
 | 
					.pure-theme {
 | 
				
			||||||
  margin-top: 25px;
 | 
					  margin-top: 25px;
 | 
				
			||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
  height: 100px;
 | 
					  height: 50px;
 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  flex-wrap: wrap;
 | 
					  flex-wrap: wrap;
 | 
				
			||||||
  justify-content: space-around;
 | 
					  justify-content: space-around;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  li {
 | 
					  li {
 | 
				
			||||||
    margin: 10px;
 | 
					    width: 18%;
 | 
				
			||||||
    width: 36%;
 | 
					    height: 45px;
 | 
				
			||||||
    height: 70px;
 | 
					 | 
				
			||||||
    background: #f0f2f5;
 | 
					    background: #f0f2f5;
 | 
				
			||||||
    position: relative;
 | 
					    position: relative;
 | 
				
			||||||
    overflow: hidden;
 | 
					    overflow: hidden;
 | 
				
			||||||
@ -527,6 +543,27 @@ nextTick(() => {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &:nth-child(3) {
 | 
				
			||||||
 | 
					      div {
 | 
				
			||||||
 | 
					        &:nth-child(1) {
 | 
				
			||||||
 | 
					          width: 100%;
 | 
				
			||||||
 | 
					          height: 30%;
 | 
				
			||||||
 | 
					          background: #1b2a47;
 | 
				
			||||||
 | 
					          box-shadow: 0 0 1px #888;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        &:nth-child(2) {
 | 
				
			||||||
 | 
					          width: 30%;
 | 
				
			||||||
 | 
					          height: 70%;
 | 
				
			||||||
 | 
					          bottom: 0;
 | 
				
			||||||
 | 
					          left: 0;
 | 
				
			||||||
 | 
					          background: #fff;
 | 
				
			||||||
 | 
					          box-shadow: 0 0 1px #888;
 | 
				
			||||||
 | 
					          position: absolute;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,126 +1,61 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import {
 | 
					 | 
				
			||||||
  computed,
 | 
					 | 
				
			||||||
  unref,
 | 
					 | 
				
			||||||
  watch,
 | 
					 | 
				
			||||||
  nextTick,
 | 
					 | 
				
			||||||
  onMounted,
 | 
					 | 
				
			||||||
  getCurrentInstance
 | 
					 | 
				
			||||||
} from "vue";
 | 
					 | 
				
			||||||
import { useI18n } from "vue-i18n";
 | 
					import { useI18n } from "vue-i18n";
 | 
				
			||||||
import { emitter } from "/@/utils/mitt";
 | 
					import { useNav } from "../../hooks/nav";
 | 
				
			||||||
import Notice from "../notice/index.vue";
 | 
					import Notice from "../notice/index.vue";
 | 
				
			||||||
import { templateRef } from "@vueuse/core";
 | 
					import { templateRef } from "@vueuse/core";
 | 
				
			||||||
import SidebarItem from "./sidebarItem.vue";
 | 
					import SidebarItem from "./sidebarItem.vue";
 | 
				
			||||||
import avatars from "/@/assets/avatars.jpg";
 | 
					import avatars from "/@/assets/avatars.jpg";
 | 
				
			||||||
import screenfull from "../screenfull/index.vue";
 | 
					import screenfull from "../screenfull/index.vue";
 | 
				
			||||||
import { useRoute, useRouter } from "vue-router";
 | 
					import { useRoute, useRouter } from "vue-router";
 | 
				
			||||||
import { storageSession } from "/@/utils/storage";
 | 
					 | 
				
			||||||
import { deviceDetection } from "/@/utils/deviceDetection";
 | 
					import { deviceDetection } from "/@/utils/deviceDetection";
 | 
				
			||||||
 | 
					import { watch, nextTick, onMounted, getCurrentInstance } from "vue";
 | 
				
			||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
					import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
				
			||||||
import globalization from "/@/assets/svg/globalization.svg?component";
 | 
					import globalization from "/@/assets/svg/globalization.svg?component";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const route = useRoute();
 | 
				
			||||||
 | 
					const { locale } = useI18n();
 | 
				
			||||||
 | 
					const routers = useRouter().options.routes;
 | 
				
			||||||
 | 
					const menuRef = templateRef<ElRef | null>("menu", null);
 | 
				
			||||||
const instance =
 | 
					const instance =
 | 
				
			||||||
  getCurrentInstance().appContext.config.globalProperties.$storage;
 | 
					  getCurrentInstance().appContext.config.globalProperties.$storage;
 | 
				
			||||||
 | 
					 | 
				
			||||||
const title =
 | 
					const title =
 | 
				
			||||||
  getCurrentInstance().appContext.config.globalProperties.$config?.Title;
 | 
					  getCurrentInstance().appContext.config.globalProperties.$config?.Title;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const menuRef = templateRef<ElRef | null>("menu", null);
 | 
					const {
 | 
				
			||||||
const route = useRoute();
 | 
					  logout,
 | 
				
			||||||
const router = useRouter();
 | 
					  backHome,
 | 
				
			||||||
const routers = useRouter().options.routes;
 | 
					  onPanel,
 | 
				
			||||||
let usename = storageSession.getItem("info")?.username;
 | 
					  changeTitle,
 | 
				
			||||||
const { locale, t } = useI18n();
 | 
					  handleResize,
 | 
				
			||||||
 | 
					  menuSelect,
 | 
				
			||||||
 | 
					  usename,
 | 
				
			||||||
 | 
					  getDropdownItemStyle
 | 
				
			||||||
 | 
					} = useNav();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getDropdownItemStyle = computed(() => {
 | 
					onMounted(() => {
 | 
				
			||||||
  return t => {
 | 
					  nextTick(() => {
 | 
				
			||||||
    return {
 | 
					    handleResize(menuRef.value);
 | 
				
			||||||
      background: locale.value === t ? "#1b2a47" : "",
 | 
					  });
 | 
				
			||||||
      color: locale.value === t ? "#f4f4f5" : "#000"
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(
 | 
					watch(
 | 
				
			||||||
  () => locale.value,
 | 
					  () => locale.value,
 | 
				
			||||||
  () => {
 | 
					  () => {
 | 
				
			||||||
    //@ts-ignore
 | 
					    changeTitle(route.meta);
 | 
				
			||||||
    // 动态title
 | 
					 | 
				
			||||||
    document.title = t(unref(route.meta.title));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 退出登录
 | 
					 | 
				
			||||||
const logout = (): void => {
 | 
					 | 
				
			||||||
  storageSession.removeItem("info");
 | 
					 | 
				
			||||||
  router.push("/login");
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function onPanel() {
 | 
					 | 
				
			||||||
  emitter.emit("openPanel");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const activeMenu = computed((): string => {
 | 
					 | 
				
			||||||
  const { meta, path } = route;
 | 
					 | 
				
			||||||
  if (meta.activeMenu) {
 | 
					 | 
				
			||||||
    // @ts-ignore
 | 
					 | 
				
			||||||
    return meta.activeMenu;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return path;
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const menuSelect = (indexPath: string): void => {
 | 
					 | 
				
			||||||
  let parentPath = "";
 | 
					 | 
				
			||||||
  let parentPathIndex = indexPath.lastIndexOf("/");
 | 
					 | 
				
			||||||
  if (parentPathIndex > 0) {
 | 
					 | 
				
			||||||
    parentPath = indexPath.slice(0, parentPathIndex);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  // 找到当前路由的信息
 | 
					 | 
				
			||||||
  function findCurrentRoute(routes) {
 | 
					 | 
				
			||||||
    return routes.map(item => {
 | 
					 | 
				
			||||||
      if (item.path === indexPath) {
 | 
					 | 
				
			||||||
        // 切换左侧菜单 通知标签页
 | 
					 | 
				
			||||||
        emitter.emit("changLayoutRoute", {
 | 
					 | 
				
			||||||
          indexPath,
 | 
					 | 
				
			||||||
          parentPath
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        if (item.children) findCurrentRoute(item.children);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  findCurrentRoute(routers);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function backHome() {
 | 
					 | 
				
			||||||
  router.push("/welcome");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function handleResize() {
 | 
					 | 
				
			||||||
  // @ts-ignore
 | 
					 | 
				
			||||||
  menuRef.value.handleResize();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 简体中文
 | 
					 | 
				
			||||||
function translationCh() {
 | 
					function translationCh() {
 | 
				
			||||||
  instance.locale = { locale: "zh" };
 | 
					  instance.locale = { locale: "zh" };
 | 
				
			||||||
  locale.value = "zh";
 | 
					  locale.value = "zh";
 | 
				
			||||||
  handleResize();
 | 
					  handleResize(menuRef.value);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// English
 | 
					 | 
				
			||||||
function translationEn() {
 | 
					function translationEn() {
 | 
				
			||||||
  instance.locale = { locale: "en" };
 | 
					  instance.locale = { locale: "en" };
 | 
				
			||||||
  locale.value = "en";
 | 
					  locale.value = "en";
 | 
				
			||||||
  handleResize();
 | 
					  handleResize(menuRef.value);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
onMounted(() => {
 | 
					 | 
				
			||||||
  nextTick(() => {
 | 
					 | 
				
			||||||
    handleResize();
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
@ -135,12 +70,11 @@ onMounted(() => {
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <el-menu
 | 
					    <el-menu
 | 
				
			||||||
      ref="menu"
 | 
					      ref="menu"
 | 
				
			||||||
      :default-active="activeMenu"
 | 
					 | 
				
			||||||
      unique-opened
 | 
					 | 
				
			||||||
      router
 | 
					 | 
				
			||||||
      class="horizontal-header-menu"
 | 
					      class="horizontal-header-menu"
 | 
				
			||||||
      mode="horizontal"
 | 
					      mode="horizontal"
 | 
				
			||||||
      @select="menuSelect"
 | 
					      :default-active="route.path"
 | 
				
			||||||
 | 
					      router
 | 
				
			||||||
 | 
					      @select="indexPath => menuSelect(indexPath, routers)"
 | 
				
			||||||
    >
 | 
					    >
 | 
				
			||||||
      <sidebar-item
 | 
					      <sidebar-item
 | 
				
			||||||
        v-for="route in usePermissionStoreHook().wholeMenus"
 | 
					        v-for="route in usePermissionStoreHook().wholeMenus"
 | 
				
			||||||
@ -160,14 +94,14 @@ onMounted(() => {
 | 
				
			|||||||
        <template #dropdown>
 | 
					        <template #dropdown>
 | 
				
			||||||
          <el-dropdown-menu class="translation">
 | 
					          <el-dropdown-menu class="translation">
 | 
				
			||||||
            <el-dropdown-item
 | 
					            <el-dropdown-item
 | 
				
			||||||
              :style="getDropdownItemStyle('zh')"
 | 
					              :style="getDropdownItemStyle(locale, 'zh')"
 | 
				
			||||||
              @click="translationCh"
 | 
					              @click="translationCh"
 | 
				
			||||||
              ><el-icon class="check-zh" v-show="locale === 'zh'"
 | 
					              ><el-icon class="check-zh" v-show="locale === 'zh'"
 | 
				
			||||||
                ><IconifyIconOffline icon="check" /></el-icon
 | 
					                ><IconifyIconOffline icon="check" /></el-icon
 | 
				
			||||||
              >简体中文</el-dropdown-item
 | 
					              >简体中文</el-dropdown-item
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
            <el-dropdown-item
 | 
					            <el-dropdown-item
 | 
				
			||||||
              :style="getDropdownItemStyle('en')"
 | 
					              :style="getDropdownItemStyle(locale, 'en')"
 | 
				
			||||||
              @click="translationEn"
 | 
					              @click="translationEn"
 | 
				
			||||||
              ><el-icon class="check-en" v-show="locale === 'en'"
 | 
					              ><el-icon class="check-en" v-show="locale === 'en'"
 | 
				
			||||||
                ><IconifyIconOffline icon="check" /></el-icon
 | 
					                ><IconifyIconOffline icon="check" /></el-icon
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										239
									
								
								src/layout/components/sidebar/mixNav.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								src/layout/components/sidebar/mixNav.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,239 @@
 | 
				
			|||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import { useI18n } from "vue-i18n";
 | 
				
			||||||
 | 
					import Notice from "../notice/index.vue";
 | 
				
			||||||
 | 
					import { useNav } from "../../hooks/nav";
 | 
				
			||||||
 | 
					import { templateRef } from "@vueuse/core";
 | 
				
			||||||
 | 
					import avatars from "/@/assets/avatars.jpg";
 | 
				
			||||||
 | 
					import { transformI18n } from "/@/plugins/i18n";
 | 
				
			||||||
 | 
					import screenfull from "../screenfull/index.vue";
 | 
				
			||||||
 | 
					import { useRoute, useRouter } from "vue-router";
 | 
				
			||||||
 | 
					import { deviceDetection } from "/@/utils/deviceDetection";
 | 
				
			||||||
 | 
					import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
 | 
				
			||||||
 | 
					import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
 | 
				
			||||||
 | 
					import { getParentPaths, findRouteByPath } from "/@/router/utils";
 | 
				
			||||||
 | 
					import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
				
			||||||
 | 
					import globalization from "/@/assets/svg/globalization.svg?component";
 | 
				
			||||||
 | 
					import { ref, watch, nextTick, onMounted, getCurrentInstance } from "vue";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const route = useRoute();
 | 
				
			||||||
 | 
					const { locale } = useI18n();
 | 
				
			||||||
 | 
					const routers = useRouter().options.routes;
 | 
				
			||||||
 | 
					const menuRef = templateRef<ElRef | null>("menu", null);
 | 
				
			||||||
 | 
					const instance =
 | 
				
			||||||
 | 
					  getCurrentInstance().appContext.config.globalProperties.$storage;
 | 
				
			||||||
 | 
					const wholeMenus = usePermissionStoreHook().wholeMenus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const {
 | 
				
			||||||
 | 
					  logout,
 | 
				
			||||||
 | 
					  onPanel,
 | 
				
			||||||
 | 
					  changeTitle,
 | 
				
			||||||
 | 
					  toggleSideBar,
 | 
				
			||||||
 | 
					  handleResize,
 | 
				
			||||||
 | 
					  menuSelect,
 | 
				
			||||||
 | 
					  resolvePath,
 | 
				
			||||||
 | 
					  pureApp,
 | 
				
			||||||
 | 
					  usename,
 | 
				
			||||||
 | 
					  getDropdownItemStyle
 | 
				
			||||||
 | 
					} = useNav();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let defaultActive = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getDefaultActive(routePath) {
 | 
				
			||||||
 | 
					  // 当前路由的父级路径
 | 
				
			||||||
 | 
					  const parentRoutes = getParentPaths(routePath, wholeMenus)[0];
 | 
				
			||||||
 | 
					  defaultActive.value = findRouteByPath(
 | 
				
			||||||
 | 
					    parentRoutes,
 | 
				
			||||||
 | 
					    wholeMenus
 | 
				
			||||||
 | 
					  )?.children[0]?.path;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					onMounted(() => {
 | 
				
			||||||
 | 
					  getDefaultActive(route.path);
 | 
				
			||||||
 | 
					  nextTick(() => {
 | 
				
			||||||
 | 
					    handleResize(menuRef.value);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(
 | 
				
			||||||
 | 
					  () => locale.value,
 | 
				
			||||||
 | 
					  () => {
 | 
				
			||||||
 | 
					    changeTitle(route.meta);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(
 | 
				
			||||||
 | 
					  () => route.path,
 | 
				
			||||||
 | 
					  () => {
 | 
				
			||||||
 | 
					    getDefaultActive(route.path);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function translationCh() {
 | 
				
			||||||
 | 
					  instance.locale = { locale: "zh" };
 | 
				
			||||||
 | 
					  locale.value = "zh";
 | 
				
			||||||
 | 
					  handleResize(menuRef.value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function translationEn() {
 | 
				
			||||||
 | 
					  instance.locale = { locale: "en" };
 | 
				
			||||||
 | 
					  locale.value = "en";
 | 
				
			||||||
 | 
					  handleResize(menuRef.value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <div class="horizontal-header">
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      :class="classes.container"
 | 
				
			||||||
 | 
					      :title="pureApp.sidebar.opened ? '点击折叠' : '点击展开'"
 | 
				
			||||||
 | 
					      @click="toggleSideBar"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <svg
 | 
				
			||||||
 | 
					        :fill="useEpThemeStoreHook().fill"
 | 
				
			||||||
 | 
					        :class="[
 | 
				
			||||||
 | 
					          'hamburger',
 | 
				
			||||||
 | 
					          pureApp.sidebar.opened ? 'is-active-hamburger' : ''
 | 
				
			||||||
 | 
					        ]"
 | 
				
			||||||
 | 
					        viewBox="0 0 1024 1024"
 | 
				
			||||||
 | 
					        xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					        width="64"
 | 
				
			||||||
 | 
					        height="64"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <path
 | 
				
			||||||
 | 
					          d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </svg>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <el-menu
 | 
				
			||||||
 | 
					      ref="menu"
 | 
				
			||||||
 | 
					      class="horizontal-header-menu"
 | 
				
			||||||
 | 
					      mode="horizontal"
 | 
				
			||||||
 | 
					      :default-active="defaultActive"
 | 
				
			||||||
 | 
					      router
 | 
				
			||||||
 | 
					      @select="indexPath => menuSelect(indexPath, routers)"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <el-menu-item
 | 
				
			||||||
 | 
					        v-for="route in wholeMenus"
 | 
				
			||||||
 | 
					        :key="route.path"
 | 
				
			||||||
 | 
					        :index="resolvePath(route) || route.redirect"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <template #title>
 | 
				
			||||||
 | 
					          <el-icon v-show="route.meta.icon" :class="route.meta.icon">
 | 
				
			||||||
 | 
					            <component
 | 
				
			||||||
 | 
					              :is="useRenderIcon(route.meta && route.meta.icon)"
 | 
				
			||||||
 | 
					            ></component>
 | 
				
			||||||
 | 
					          </el-icon>
 | 
				
			||||||
 | 
					          <span>{{ transformI18n(route.meta.title, route.meta.i18n) }}</span>
 | 
				
			||||||
 | 
					          <FontIcon
 | 
				
			||||||
 | 
					            v-if="route.meta.extraIcon"
 | 
				
			||||||
 | 
					            width="30px"
 | 
				
			||||||
 | 
					            height="30px"
 | 
				
			||||||
 | 
					            style="position: absolute; right: 10px"
 | 
				
			||||||
 | 
					            :icon="route.meta.extraIcon.name"
 | 
				
			||||||
 | 
					            :svg="route.meta.extraIcon.svg ? true : false"
 | 
				
			||||||
 | 
					          ></FontIcon>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					      </el-menu-item>
 | 
				
			||||||
 | 
					    </el-menu>
 | 
				
			||||||
 | 
					    <div class="horizontal-header-right">
 | 
				
			||||||
 | 
					      <!-- 通知 -->
 | 
				
			||||||
 | 
					      <Notice id="header-notice" />
 | 
				
			||||||
 | 
					      <!-- 全屏 -->
 | 
				
			||||||
 | 
					      <screenfull id="header-screenfull" v-show="!deviceDetection()" />
 | 
				
			||||||
 | 
					      <!-- 国际化 -->
 | 
				
			||||||
 | 
					      <el-dropdown id="header-translation" trigger="click">
 | 
				
			||||||
 | 
					        <globalization />
 | 
				
			||||||
 | 
					        <template #dropdown>
 | 
				
			||||||
 | 
					          <el-dropdown-menu class="translation">
 | 
				
			||||||
 | 
					            <el-dropdown-item
 | 
				
			||||||
 | 
					              :style="getDropdownItemStyle(locale, 'zh')"
 | 
				
			||||||
 | 
					              @click="translationCh"
 | 
				
			||||||
 | 
					              ><el-icon class="check-zh" v-show="locale === 'zh'"
 | 
				
			||||||
 | 
					                ><IconifyIconOffline icon="check" /></el-icon
 | 
				
			||||||
 | 
					              >简体中文</el-dropdown-item
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					            <el-dropdown-item
 | 
				
			||||||
 | 
					              :style="getDropdownItemStyle(locale, 'en')"
 | 
				
			||||||
 | 
					              @click="translationEn"
 | 
				
			||||||
 | 
					              ><el-icon class="check-en" v-show="locale === 'en'"
 | 
				
			||||||
 | 
					                ><IconifyIconOffline icon="check" /></el-icon
 | 
				
			||||||
 | 
					              >English</el-dropdown-item
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					          </el-dropdown-menu>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					      </el-dropdown>
 | 
				
			||||||
 | 
					      <!-- 退出登陆 -->
 | 
				
			||||||
 | 
					      <el-dropdown trigger="click">
 | 
				
			||||||
 | 
					        <span class="el-dropdown-link">
 | 
				
			||||||
 | 
					          <img :src="avatars" />
 | 
				
			||||||
 | 
					          <p>{{ usename }}</p>
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
 | 
					        <template #dropdown>
 | 
				
			||||||
 | 
					          <el-dropdown-menu class="logout">
 | 
				
			||||||
 | 
					            <el-dropdown-item @click="logout">
 | 
				
			||||||
 | 
					              <IconifyIconOffline
 | 
				
			||||||
 | 
					                icon="logout-circle-r-line"
 | 
				
			||||||
 | 
					                style="margin: 5px"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					              {{ $t("buttons.hsLoginOut") }}</el-dropdown-item
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					          </el-dropdown-menu>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					      </el-dropdown>
 | 
				
			||||||
 | 
					      <el-icon
 | 
				
			||||||
 | 
					        class="el-icon-setting"
 | 
				
			||||||
 | 
					        :title="$t('buttons.hssystemSet')"
 | 
				
			||||||
 | 
					        @click="onPanel"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <IconifyIconOffline icon="setting" />
 | 
				
			||||||
 | 
					      </el-icon>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style module="classes" scoped>
 | 
				
			||||||
 | 
					.container {
 | 
				
			||||||
 | 
					  padding: 0 15px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.hamburger {
 | 
				
			||||||
 | 
					  width: 20px;
 | 
				
			||||||
 | 
					  height: 20px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &:hover {
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.is-active-hamburger {
 | 
				
			||||||
 | 
					  transform: rotate(180deg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.translation {
 | 
				
			||||||
 | 
					  ::v-deep(.el-dropdown-menu__item) {
 | 
				
			||||||
 | 
					    padding: 5px 40px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .check-zh {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    left: 20px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .check-en {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    left: 20px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.logout {
 | 
				
			||||||
 | 
					  max-width: 120px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::v-deep(.el-dropdown-menu__item) {
 | 
				
			||||||
 | 
					    min-width: 100%;
 | 
				
			||||||
 | 
					    display: inline-flex;
 | 
				
			||||||
 | 
					    flex-wrap: wrap;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -1,21 +1,14 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import {
 | 
					import { ref, PropType, nextTick, computed, CSSProperties } from "vue";
 | 
				
			||||||
  ref,
 | 
					 | 
				
			||||||
  PropType,
 | 
					 | 
				
			||||||
  nextTick,
 | 
					 | 
				
			||||||
  computed,
 | 
					 | 
				
			||||||
  CSSProperties,
 | 
					 | 
				
			||||||
  getCurrentInstance
 | 
					 | 
				
			||||||
} from "vue";
 | 
					 | 
				
			||||||
import path from "path";
 | 
					import path from "path";
 | 
				
			||||||
 | 
					import { useNav } from "../../hooks/nav";
 | 
				
			||||||
import { childrenType } from "../../types";
 | 
					import { childrenType } from "../../types";
 | 
				
			||||||
import { transformI18n } from "/@/plugins/i18n";
 | 
					import { transformI18n } from "/@/plugins/i18n";
 | 
				
			||||||
import { useAppStoreHook } from "/@/store/modules/app";
 | 
					import { useAppStoreHook } from "/@/store/modules/app";
 | 
				
			||||||
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
 | 
					import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const instance = getCurrentInstance().appContext.app.config.globalProperties;
 | 
					const { pureApp } = useNav();
 | 
				
			||||||
const menuMode = instance.$storage.layout?.layout === "vertical";
 | 
					const menuMode = ["vertical", "mix"].includes(pureApp.layout);
 | 
				
			||||||
const pureApp = useAppStoreHook();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps({
 | 
					const props = defineProps({
 | 
				
			||||||
  item: {
 | 
					  item: {
 | 
				
			||||||
@ -105,7 +98,6 @@ function hoverMenu(key) {
 | 
				
			|||||||
      : Object.assign(key, {
 | 
					      : Object.assign(key, {
 | 
				
			||||||
          showTooltip: false
 | 
					          showTooltip: false
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					 | 
				
			||||||
    hoverMenuMap.set(key, true);
 | 
					    hoverMenuMap.set(key, true);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -132,8 +124,8 @@ function hasOneShowingChild(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function resolvePath(routePath) {
 | 
					function resolvePath(routePath) {
 | 
				
			||||||
  const httpReg = /^http(s?):\/\//;
 | 
					  const httpReg = /^http(s?):\/\//;
 | 
				
			||||||
  if (httpReg.test(routePath)) {
 | 
					  if (httpReg.test(routePath) || httpReg.test(props.basePath)) {
 | 
				
			||||||
    return props.basePath + "/" + routePath;
 | 
					    return routePath || props.basePath;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    return path.resolve(props.basePath, routePath);
 | 
					    return path.resolve(props.basePath, routePath);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -162,6 +154,18 @@ function resolvePath(routePath) {
 | 
				
			|||||||
          "
 | 
					          "
 | 
				
			||||||
        ></component>
 | 
					        ></component>
 | 
				
			||||||
      </el-icon>
 | 
					      </el-icon>
 | 
				
			||||||
 | 
					      <div
 | 
				
			||||||
 | 
					        v-if="
 | 
				
			||||||
 | 
					          !pureApp.sidebar.opened &&
 | 
				
			||||||
 | 
					          pureApp.layout === 'mix' &&
 | 
				
			||||||
 | 
					          props.item?.pathList?.length === 2
 | 
				
			||||||
 | 
					        "
 | 
				
			||||||
 | 
					        :style="getDivStyle"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <span :style="getMenuTextStyle">
 | 
				
			||||||
 | 
					          {{ transformI18n(onlyOneChild.meta.title, onlyOneChild.meta.i18n) }}
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
      <template #title>
 | 
					      <template #title>
 | 
				
			||||||
        <div :style="getDivStyle">
 | 
					        <div :style="getDivStyle">
 | 
				
			||||||
          <span v-if="!menuMode">{{
 | 
					          <span v-if="!menuMode">{{
 | 
				
			||||||
 | 
				
			|||||||
@ -1,60 +1,56 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import Logo from "./logo.vue";
 | 
					import Logo from "./logo.vue";
 | 
				
			||||||
import { emitter } from "/@/utils/mitt";
 | 
					import { emitter } from "/@/utils/mitt";
 | 
				
			||||||
 | 
					import { useNav } from "../../hooks/nav";
 | 
				
			||||||
import SidebarItem from "./sidebarItem.vue";
 | 
					import SidebarItem from "./sidebarItem.vue";
 | 
				
			||||||
import { storageLocal } from "/@/utils/storage";
 | 
					import { storageLocal } from "/@/utils/storage";
 | 
				
			||||||
import { useRoute, useRouter } from "vue-router";
 | 
					import { useRoute, useRouter } from "vue-router";
 | 
				
			||||||
import { computed, ref, onBeforeMount } from "vue";
 | 
					import { ref, computed, watch, onBeforeMount } from "vue";
 | 
				
			||||||
import { useAppStoreHook } from "/@/store/modules/app";
 | 
					import { findRouteByPath, getParentPaths } from "/@/router/utils";
 | 
				
			||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
					import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const route = useRoute();
 | 
					const route = useRoute();
 | 
				
			||||||
const pureApp = useAppStoreHook();
 | 
					const routers = useRouter().options.routes;
 | 
				
			||||||
const router = useRouter().options.routes;
 | 
					 | 
				
			||||||
const showLogo = ref(
 | 
					const showLogo = ref(
 | 
				
			||||||
  storageLocal.getItem("responsive-configure")?.showLogo ?? true
 | 
					  storageLocal.getItem("responsive-configure")?.showLogo ?? true
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
const isCollapse = computed(() => {
 | 
					
 | 
				
			||||||
  return !pureApp.getSidebarStatus;
 | 
					const { pureApp, isCollapse, menuSelect } = useNav();
 | 
				
			||||||
});
 | 
					
 | 
				
			||||||
const activeMenu = computed((): string => {
 | 
					let subMenuData = ref([]);
 | 
				
			||||||
  const { meta, path } = route;
 | 
					
 | 
				
			||||||
  if (meta.activeMenu) {
 | 
					const menuData = computed(() => {
 | 
				
			||||||
    // @ts-ignore
 | 
					  return pureApp.layout === "mix"
 | 
				
			||||||
    return meta.activeMenu;
 | 
					    ? subMenuData.value
 | 
				
			||||||
  }
 | 
					    : usePermissionStoreHook().wholeMenus;
 | 
				
			||||||
  return path;
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const menuSelect = (indexPath: string): void => {
 | 
					function getSubMenuData(path) {
 | 
				
			||||||
  let parentPath = "";
 | 
					  // path的上级路由组成的数组
 | 
				
			||||||
  let parentPathIndex = indexPath.lastIndexOf("/");
 | 
					  const parentPathArr = getParentPaths(
 | 
				
			||||||
  if (parentPathIndex > 0) {
 | 
					    path,
 | 
				
			||||||
    parentPath = indexPath.slice(0, parentPathIndex);
 | 
					    usePermissionStoreHook().wholeMenus
 | 
				
			||||||
  }
 | 
					  );
 | 
				
			||||||
  // 找到当前路由的信息
 | 
					  // 当前路由的父级路由信息
 | 
				
			||||||
  // eslint-disable-next-line no-inner-declarations
 | 
					  const parenetRoute = findRouteByPath(
 | 
				
			||||||
  function findCurrentRoute(routes) {
 | 
					    parentPathArr[0] || path,
 | 
				
			||||||
    return routes.map(item => {
 | 
					    usePermissionStoreHook().wholeMenus
 | 
				
			||||||
      if (item.path === indexPath) {
 | 
					  );
 | 
				
			||||||
        // 切换左侧菜单 通知标签页
 | 
					  if (!parenetRoute?.children) return;
 | 
				
			||||||
        emitter.emit("changLayoutRoute", {
 | 
					  subMenuData.value = parenetRoute?.children;
 | 
				
			||||||
          indexPath,
 | 
					}
 | 
				
			||||||
          parentPath
 | 
					getSubMenuData(route.path);
 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        if (item.children) findCurrentRoute(item.children);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  findCurrentRoute(router);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
onBeforeMount(() => {
 | 
					onBeforeMount(() => {
 | 
				
			||||||
  emitter.on("logoChange", key => {
 | 
					  emitter.on("logoChange", key => {
 | 
				
			||||||
    showLogo.value = key;
 | 
					    showLogo.value = key;
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(
 | 
				
			||||||
 | 
					  () => route.path,
 | 
				
			||||||
 | 
					  () => getSubMenuData(route.path)
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
@ -62,21 +58,21 @@ onBeforeMount(() => {
 | 
				
			|||||||
    <Logo v-if="showLogo" :collapse="isCollapse" />
 | 
					    <Logo v-if="showLogo" :collapse="isCollapse" />
 | 
				
			||||||
    <el-scrollbar wrap-class="scrollbar-wrapper">
 | 
					    <el-scrollbar wrap-class="scrollbar-wrapper">
 | 
				
			||||||
      <el-menu
 | 
					      <el-menu
 | 
				
			||||||
        :default-active="activeMenu"
 | 
					        :default-active="route.path"
 | 
				
			||||||
        :collapse="isCollapse"
 | 
					        :collapse="isCollapse"
 | 
				
			||||||
        unique-opened
 | 
					        unique-opened
 | 
				
			||||||
        router
 | 
					        router
 | 
				
			||||||
        :collapse-transition="false"
 | 
					        :collapse-transition="false"
 | 
				
			||||||
        mode="vertical"
 | 
					        mode="vertical"
 | 
				
			||||||
        class="outer-most"
 | 
					        class="outer-most"
 | 
				
			||||||
        @select="menuSelect"
 | 
					        @select="indexPath => menuSelect(indexPath, routers)"
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
        <sidebar-item
 | 
					        <sidebar-item
 | 
				
			||||||
          v-for="route in usePermissionStoreHook().wholeMenus"
 | 
					          v-for="routes in menuData"
 | 
				
			||||||
          :key="route.path"
 | 
					          :key="routes.path"
 | 
				
			||||||
          :item="route"
 | 
					          :item="routes"
 | 
				
			||||||
          class="outer-most"
 | 
					          class="outer-most"
 | 
				
			||||||
          :base-path="route.path"
 | 
					          :base-path="routes.path"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
      </el-menu>
 | 
					      </el-menu>
 | 
				
			||||||
    </el-scrollbar>
 | 
					    </el-scrollbar>
 | 
				
			||||||
 | 
				
			|||||||
@ -106,7 +106,11 @@ const iconIsActive = computed(() => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const dynamicTagView = () => {
 | 
					const dynamicTagView = () => {
 | 
				
			||||||
  const index = multiTags.value.findIndex(item => {
 | 
					  const index = multiTags.value.findIndex(item => {
 | 
				
			||||||
    return item.path === route.path;
 | 
					    if (item?.query) {
 | 
				
			||||||
 | 
					      return isEqual(route?.query, item?.query);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      return item.path === route.path;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  moveToView(index);
 | 
					  moveToView(index);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -423,6 +427,11 @@ function onClickDrop(key, item, selectRoute?: RouteConfigs) {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function handleCommand(command: object) {
 | 
				
			||||||
 | 
					  const { key, item } = command;
 | 
				
			||||||
 | 
					  onClickDrop(key, item);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 触发右键中菜单的点击事件
 | 
					// 触发右键中菜单的点击事件
 | 
				
			||||||
function selectTag(key, item) {
 | 
					function selectTag(key, item) {
 | 
				
			||||||
  onClickDrop(key, item, currentSelect.value);
 | 
					  onClickDrop(key, item, currentSelect.value);
 | 
				
			||||||
@ -709,7 +718,11 @@ const getContextMenuStyle = computed((): CSSProperties => {
 | 
				
			|||||||
        </el-icon>
 | 
					        </el-icon>
 | 
				
			||||||
      </li>
 | 
					      </li>
 | 
				
			||||||
      <li>
 | 
					      <li>
 | 
				
			||||||
        <el-dropdown trigger="click" placement="bottom-end">
 | 
					        <el-dropdown
 | 
				
			||||||
 | 
					          trigger="click"
 | 
				
			||||||
 | 
					          placement="bottom-end"
 | 
				
			||||||
 | 
					          @command="handleCommand"
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
          <el-icon>
 | 
					          <el-icon>
 | 
				
			||||||
            <IconifyIconOffline icon="arrow-down" />
 | 
					            <IconifyIconOffline icon="arrow-down" />
 | 
				
			||||||
          </el-icon>
 | 
					          </el-icon>
 | 
				
			||||||
@ -718,9 +731,9 @@ const getContextMenuStyle = computed((): CSSProperties => {
 | 
				
			|||||||
              <el-dropdown-item
 | 
					              <el-dropdown-item
 | 
				
			||||||
                v-for="(item, key) in tagsViews"
 | 
					                v-for="(item, key) in tagsViews"
 | 
				
			||||||
                :key="key"
 | 
					                :key="key"
 | 
				
			||||||
 | 
					                :command="{ key, item }"
 | 
				
			||||||
                :divided="item.divided"
 | 
					                :divided="item.divided"
 | 
				
			||||||
                :disabled="item.disabled"
 | 
					                :disabled="item.disabled"
 | 
				
			||||||
                @click="onClickDrop(key, item)"
 | 
					 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
                <component
 | 
					                <component
 | 
				
			||||||
                  :is="item.icon"
 | 
					                  :is="item.icon"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										110
									
								
								src/layout/hooks/nav.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/layout/hooks/nav.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,110 @@
 | 
				
			|||||||
 | 
					import { computed } from "vue";
 | 
				
			||||||
 | 
					import { router } from "/@/router";
 | 
				
			||||||
 | 
					import { emitter } from "/@/utils/mitt";
 | 
				
			||||||
 | 
					import { routeMetaType } from "../types";
 | 
				
			||||||
 | 
					import { transformI18n } from "/@/plugins/i18n";
 | 
				
			||||||
 | 
					import { storageSession } from "/@/utils/storage";
 | 
				
			||||||
 | 
					import { useAppStoreHook } from "/@/store/modules/app";
 | 
				
			||||||
 | 
					import { Title } from "../../../public/serverConfig.json";
 | 
				
			||||||
 | 
					import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function useNav() {
 | 
				
			||||||
 | 
					  const pureApp = useAppStoreHook();
 | 
				
			||||||
 | 
					  // 用户名
 | 
				
			||||||
 | 
					  const usename: string = storageSession.getItem("info")?.username;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 设置国际化选中后的样式
 | 
				
			||||||
 | 
					  const getDropdownItemStyle = computed(() => {
 | 
				
			||||||
 | 
					    return (locale, t) => {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        background: locale === t ? useEpThemeStoreHook().epThemeColor : "",
 | 
				
			||||||
 | 
					        color: locale === t ? "#f4f4f5" : "#000"
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const isCollapse = computed(() => {
 | 
				
			||||||
 | 
					    return !pureApp.getSidebarStatus;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 动态title
 | 
				
			||||||
 | 
					  function changeTitle(meta: routeMetaType) {
 | 
				
			||||||
 | 
					    if (Title)
 | 
				
			||||||
 | 
					      document.title = `${transformI18n(meta.title, meta.i18n)} | ${Title}`;
 | 
				
			||||||
 | 
					    else document.title = transformI18n(meta.title, meta.i18n);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 退出登录
 | 
				
			||||||
 | 
					  function logout() {
 | 
				
			||||||
 | 
					    storageSession.removeItem("info");
 | 
				
			||||||
 | 
					    router.push("/login");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function backHome() {
 | 
				
			||||||
 | 
					    router.push("/welcome");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function onPanel() {
 | 
				
			||||||
 | 
					    emitter.emit("openPanel");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function toggleSideBar() {
 | 
				
			||||||
 | 
					    pureApp.toggleSideBar();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function handleResize(menuRef) {
 | 
				
			||||||
 | 
					    menuRef.handleResize();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function resolvePath(route) {
 | 
				
			||||||
 | 
					    const httpReg = /^http(s?):\/\//;
 | 
				
			||||||
 | 
					    const routeChildPath = route.children[0]?.path;
 | 
				
			||||||
 | 
					    if (httpReg.test(routeChildPath)) {
 | 
				
			||||||
 | 
					      return route.path + "/" + routeChildPath;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      return routeChildPath;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function menuSelect(indexPath: string, routers): void {
 | 
				
			||||||
 | 
					    let parentPath = "";
 | 
				
			||||||
 | 
					    const parentPathIndex = indexPath.lastIndexOf("/");
 | 
				
			||||||
 | 
					    if (parentPathIndex > 0) {
 | 
				
			||||||
 | 
					      parentPath = indexPath.slice(0, parentPathIndex);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // 找到当前路由的信息
 | 
				
			||||||
 | 
					    function findCurrentRoute(indexPath: string, routes) {
 | 
				
			||||||
 | 
					      return routes.map(item => {
 | 
				
			||||||
 | 
					        if (item.path === indexPath) {
 | 
				
			||||||
 | 
					          if (item.redirect) {
 | 
				
			||||||
 | 
					            findCurrentRoute(item.redirect, item.children);
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            // 切换左侧菜单 通知标签页
 | 
				
			||||||
 | 
					            emitter.emit("changLayoutRoute", {
 | 
				
			||||||
 | 
					              indexPath,
 | 
				
			||||||
 | 
					              parentPath
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          if (item.children) findCurrentRoute(indexPath, item.children);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    findCurrentRoute(indexPath, routers);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    logout,
 | 
				
			||||||
 | 
					    backHome,
 | 
				
			||||||
 | 
					    onPanel,
 | 
				
			||||||
 | 
					    changeTitle,
 | 
				
			||||||
 | 
					    toggleSideBar,
 | 
				
			||||||
 | 
					    menuSelect,
 | 
				
			||||||
 | 
					    handleResize,
 | 
				
			||||||
 | 
					    resolvePath,
 | 
				
			||||||
 | 
					    isCollapse,
 | 
				
			||||||
 | 
					    pureApp,
 | 
				
			||||||
 | 
					    usename,
 | 
				
			||||||
 | 
					    getDropdownItemStyle
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -171,7 +171,8 @@ const layoutHeader = defineComponent({
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        default: () => [
 | 
					        default: () => [
 | 
				
			||||||
          !pureSetting.hiddenSideBar && layout.value.includes("vertical")
 | 
					          !pureSetting.hiddenSideBar &&
 | 
				
			||||||
 | 
					          (layout.value.includes("vertical") || layout.value.includes("mix"))
 | 
				
			||||||
            ? h(navbar)
 | 
					            ? h(navbar)
 | 
				
			||||||
            : h("div"),
 | 
					            : h("div"),
 | 
				
			||||||
          !pureSetting.hiddenSideBar && layout.value.includes("horizontal")
 | 
					          !pureSetting.hiddenSideBar && layout.value.includes("horizontal")
 | 
				
			||||||
@ -213,7 +214,10 @@ const layoutHeader = defineComponent({
 | 
				
			|||||||
      @click="useAppStoreHook().toggleSideBar()"
 | 
					      @click="useAppStoreHook().toggleSideBar()"
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
    <Vertical
 | 
					    <Vertical
 | 
				
			||||||
      v-show="!pureSetting.hiddenSideBar && layout.includes('vertical')"
 | 
					      v-show="
 | 
				
			||||||
 | 
					        !pureSetting.hiddenSideBar &&
 | 
				
			||||||
 | 
					        (layout.includes('vertical') || layout.includes('mix'))
 | 
				
			||||||
 | 
					      "
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
    <div
 | 
					    <div
 | 
				
			||||||
      :class="[
 | 
					      :class="[
 | 
				
			||||||
 | 
				
			|||||||
@ -11,18 +11,20 @@ export const routerArrays: Array<RouteConfigs> = [
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type routeMetaType = {
 | 
				
			||||||
 | 
					  title?: string;
 | 
				
			||||||
 | 
					  i18n?: boolean;
 | 
				
			||||||
 | 
					  icon?: string;
 | 
				
			||||||
 | 
					  showLink?: boolean;
 | 
				
			||||||
 | 
					  savedPosition?: boolean;
 | 
				
			||||||
 | 
					  authority?: Array<string>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type RouteConfigs = {
 | 
					export type RouteConfigs = {
 | 
				
			||||||
  path?: string;
 | 
					  path?: string;
 | 
				
			||||||
  parentPath?: string;
 | 
					  parentPath?: string;
 | 
				
			||||||
  query?: object;
 | 
					  query?: object;
 | 
				
			||||||
  meta?: {
 | 
					  meta?: routeMetaType;
 | 
				
			||||||
    title?: string;
 | 
					 | 
				
			||||||
    i18n?: boolean;
 | 
					 | 
				
			||||||
    icon?: string;
 | 
					 | 
				
			||||||
    showLink?: boolean;
 | 
					 | 
				
			||||||
    savedPosition?: boolean;
 | 
					 | 
				
			||||||
    authority?: Array<string>;
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  children?: RouteConfigs[];
 | 
					  children?: RouteConfigs[];
 | 
				
			||||||
  name?: string;
 | 
					  name?: string;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -71,6 +73,8 @@ export type childrenType = {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  showTooltip?: boolean;
 | 
					  showTooltip?: boolean;
 | 
				
			||||||
 | 
					  parentId?: number;
 | 
				
			||||||
 | 
					  pathList?: number[];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type themeColorsType = {
 | 
					export type themeColorsType = {
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,10 @@ import { storageLocal } from "/@/utils/storage";
 | 
				
			|||||||
 * @param isI18n  如果true,获取对应的消息,否则返回本身
 | 
					 * @param isI18n  如果true,获取对应的消息,否则返回本身
 | 
				
			||||||
 * @returns message
 | 
					 * @returns message
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function transformI18n(message: string | object = "", isI18n = false) {
 | 
					export function transformI18n(
 | 
				
			||||||
 | 
					  message: string | unknown | object = "",
 | 
				
			||||||
 | 
					  isI18n: boolean | unknown = false
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
  if (!message) {
 | 
					  if (!message) {
 | 
				
			||||||
    return "";
 | 
					    return "";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@ import { split, findIndex } from "lodash-es";
 | 
				
			|||||||
import { transformI18n } from "/@/plugins/i18n";
 | 
					import { transformI18n } from "/@/plugins/i18n";
 | 
				
			||||||
import remainingRouter from "./modules/remaining";
 | 
					import remainingRouter from "./modules/remaining";
 | 
				
			||||||
import { storageSession } from "/@/utils/storage";
 | 
					import { storageSession } from "/@/utils/storage";
 | 
				
			||||||
 | 
					import { Title } from "../../public/serverConfig.json";
 | 
				
			||||||
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
 | 
					import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
 | 
				
			||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
					import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
				
			||||||
import { Router, RouteMeta, createRouter, RouteRecordName } from "vue-router";
 | 
					import { Router, RouteMeta, createRouter, RouteRecordName } from "vue-router";
 | 
				
			||||||
@ -54,12 +55,13 @@ router.beforeEach((to: toRouteType, _from, next) => {
 | 
				
			|||||||
  const externalLink = to?.redirectedFrom?.fullPath;
 | 
					  const externalLink = to?.redirectedFrom?.fullPath;
 | 
				
			||||||
  if (!externalLink)
 | 
					  if (!externalLink)
 | 
				
			||||||
    to.matched.some(item => {
 | 
					    to.matched.some(item => {
 | 
				
			||||||
      item.meta.title
 | 
					      if (!item.meta.title) return "";
 | 
				
			||||||
        ? (document.title = transformI18n(
 | 
					      if (Title)
 | 
				
			||||||
            item.meta.title as string,
 | 
					        document.title = `${transformI18n(
 | 
				
			||||||
            item.meta?.i18n as boolean
 | 
					          item.meta.title,
 | 
				
			||||||
          ))
 | 
					          item.meta?.i18n
 | 
				
			||||||
        : "";
 | 
					        )} | ${Title}`;
 | 
				
			||||||
 | 
					      else document.title = transformI18n(item.meta.title, item.meta?.i18n);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  if (name) {
 | 
					  if (name) {
 | 
				
			||||||
    if (_from?.name) {
 | 
					    if (_from?.name) {
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@ import {
 | 
				
			|||||||
  formatTwoStageRoutes,
 | 
					  formatTwoStageRoutes,
 | 
				
			||||||
  formatFlatteningRoutes
 | 
					  formatFlatteningRoutes
 | 
				
			||||||
} from "../utils";
 | 
					} from "../utils";
 | 
				
			||||||
 | 
					import { buildHierarchyTree } from "/@/utils/tree";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 原始静态路由(未做任何处理)
 | 
					// 原始静态路由(未做任何处理)
 | 
				
			||||||
const routes = [
 | 
					const routes = [
 | 
				
			||||||
@ -32,7 +33,7 @@ const routes = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// 导出处理后的静态路由(三级及以上的路由全部拍成二级)
 | 
					// 导出处理后的静态路由(三级及以上的路由全部拍成二级)
 | 
				
			||||||
export const constantRoutes: Array<RouteRecordRaw> = formatTwoStageRoutes(
 | 
					export const constantRoutes: Array<RouteRecordRaw> = formatTwoStageRoutes(
 | 
				
			||||||
  formatFlatteningRoutes(ascending(routes))
 | 
					  formatFlatteningRoutes(buildHierarchyTree(ascending(routes)))
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 用于渲染菜单,保持原始层级
 | 
					// 用于渲染菜单,保持原始层级
 | 
				
			||||||
 | 
				
			|||||||
@ -8,16 +8,29 @@ export const useEpThemeStore = defineStore({
 | 
				
			|||||||
  state: () => ({
 | 
					  state: () => ({
 | 
				
			||||||
    epThemeColor:
 | 
					    epThemeColor:
 | 
				
			||||||
      storageLocal.getItem("responsive-layout")?.epThemeColor ??
 | 
					      storageLocal.getItem("responsive-layout")?.epThemeColor ??
 | 
				
			||||||
      getConfig().EpThemeColor
 | 
					      getConfig().EpThemeColor,
 | 
				
			||||||
 | 
					    epTheme:
 | 
				
			||||||
 | 
					      storageLocal.getItem("responsive-layout")?.theme ?? getConfig().Theme
 | 
				
			||||||
  }),
 | 
					  }),
 | 
				
			||||||
  getters: {
 | 
					  getters: {
 | 
				
			||||||
    getEpThemeColor() {
 | 
					    getEpThemeColor() {
 | 
				
			||||||
      return this.epThemeColor;
 | 
					      return this.epThemeColor;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    // 用于mix导航模式下hamburger-svg的fill属性
 | 
				
			||||||
 | 
					    fill() {
 | 
				
			||||||
 | 
					      if (this.epTheme === "light") {
 | 
				
			||||||
 | 
					        return "#409eff";
 | 
				
			||||||
 | 
					      } else if (this.epTheme === "yellow") {
 | 
				
			||||||
 | 
					        return "#d25f00";
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        return "#fff";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  actions: {
 | 
					  actions: {
 | 
				
			||||||
    setEpThemeColor(newColor) {
 | 
					    setEpThemeColor(newColor) {
 | 
				
			||||||
      const layout = storageLocal.getItem("responsive-layout");
 | 
					      const layout = storageLocal.getItem("responsive-layout");
 | 
				
			||||||
 | 
					      this.epTheme = layout?.theme;
 | 
				
			||||||
      this.epThemeColor = newColor;
 | 
					      this.epThemeColor = newColor;
 | 
				
			||||||
      layout.epThemeColor = newColor;
 | 
					      layout.epThemeColor = newColor;
 | 
				
			||||||
      storageLocal.setItem("responsive-layout", layout);
 | 
					      storageLocal.setItem("responsive-layout", layout);
 | 
				
			||||||
 | 
				
			|||||||
@ -638,3 +638,64 @@ body[layout="horizontal"] {
 | 
				
			|||||||
    transition: none !important;
 | 
					    transition: none !important;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					body[layout="mix"] {
 | 
				
			||||||
 | 
					  $sideBarWidth: 210px;
 | 
				
			||||||
 | 
					  @include merge-style($sideBarWidth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .el-menu {
 | 
				
			||||||
 | 
					    --el-menu-hover-bg-color: transparent !important;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .hideSidebar {
 | 
				
			||||||
 | 
					    .fixed-header {
 | 
				
			||||||
 | 
					      width: calc(100% - 54px);
 | 
				
			||||||
 | 
					      transition: width 0.28s;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .sidebar-container {
 | 
				
			||||||
 | 
					      width: 54px !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .main-container {
 | 
				
			||||||
 | 
					      margin-left: 54px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .submenu-title-noDropdown {
 | 
				
			||||||
 | 
					      padding: 0 !important;
 | 
				
			||||||
 | 
					      position: relative;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      .el-tooltip {
 | 
				
			||||||
 | 
					        padding: 0 !important;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 菜单折叠 */
 | 
				
			||||||
 | 
					    .el-menu--collapse {
 | 
				
			||||||
 | 
					      .el-sub-menu {
 | 
				
			||||||
 | 
					        & > .el-sub-menu__title {
 | 
				
			||||||
 | 
					          & > span {
 | 
				
			||||||
 | 
					            height: 0;
 | 
				
			||||||
 | 
					            width: 0;
 | 
				
			||||||
 | 
					            overflow: hidden;
 | 
				
			||||||
 | 
					            visibility: hidden;
 | 
				
			||||||
 | 
					            display: inline-block;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /* 无子菜单 */
 | 
				
			||||||
 | 
					      .el-menu-item [class^="el-icon"] {
 | 
				
			||||||
 | 
					        right: 5px;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      .el-sub-menu__title [class^="el-icon"] {
 | 
				
			||||||
 | 
					        right: 2px;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      .submenu-title-noDropdown {
 | 
				
			||||||
 | 
					        background: transparent !important;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -46,3 +46,22 @@ export function deleteChildren(menuTree, pathList = []) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  return menuTree;
 | 
					  return menuTree;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建层级关系
 | 
				
			||||||
 | 
					export function buildHierarchyTree(menuTree, pathList = []) {
 | 
				
			||||||
 | 
					  if (!Array.isArray(menuTree)) {
 | 
				
			||||||
 | 
					    console.warn("menuTree must be an array");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!menuTree || menuTree.length === 0) return;
 | 
				
			||||||
 | 
					  for (const [key, node] of menuTree.entries()) {
 | 
				
			||||||
 | 
					    node.id = key;
 | 
				
			||||||
 | 
					    node.parentId = pathList.length ? pathList[pathList.length - 1] : null;
 | 
				
			||||||
 | 
					    node.pathList = [...pathList, node.id];
 | 
				
			||||||
 | 
					    const hasChildren = node.children && node.children.length > 0;
 | 
				
			||||||
 | 
					    if (hasChildren) {
 | 
				
			||||||
 | 
					      buildHierarchyTree(node.children, node.pathList);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return menuTree;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -140,6 +140,7 @@ onMounted(() => {
 | 
				
			|||||||
.item-cut {
 | 
					.item-cut {
 | 
				
			||||||
  font-size: 1.5em;
 | 
					  font-size: 1.5em;
 | 
				
			||||||
  height: 77px;
 | 
					  height: 77px;
 | 
				
			||||||
 | 
					  line-height: 77px;
 | 
				
			||||||
  text-align: center;
 | 
					  text-align: center;
 | 
				
			||||||
  border: 1px solid #e5e4e9;
 | 
					  border: 1px solid #e5e4e9;
 | 
				
			||||||
  cursor: move;
 | 
					  cursor: move;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user