mirror of
				https://github.com/pure-admin/vue-pure-admin.git
				synced 2025-11-03 13:44:47 +08:00 
			
		
		
		
	refactor: 标签页重构,采用响应式storage
This commit is contained in:
		
							parent
							
								
									6a89af382f
								
							
						
					
					
						commit
						8177de106b
					
				
							
								
								
									
										14
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										14
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -27,7 +27,7 @@
 | 
				
			|||||||
        "path-to-regexp": "^6.2.0",
 | 
					        "path-to-regexp": "^6.2.0",
 | 
				
			||||||
        "pinia": "^2.0.0-beta.2",
 | 
					        "pinia": "^2.0.0-beta.2",
 | 
				
			||||||
        "resize-observer-polyfill": "^1.5.1",
 | 
					        "resize-observer-polyfill": "^1.5.1",
 | 
				
			||||||
        "responsive-storage": "^1.0.1",
 | 
					        "responsive-storage": "^1.0.4",
 | 
				
			||||||
        "v-contextmenu": "^3.0.0",
 | 
					        "v-contextmenu": "^3.0.0",
 | 
				
			||||||
        "vue": "^3.1.1",
 | 
					        "vue": "^3.1.1",
 | 
				
			||||||
        "vue-i18n": "^9.1.6",
 | 
					        "vue-i18n": "^9.1.6",
 | 
				
			||||||
@ -2476,9 +2476,9 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/responsive-storage": {
 | 
					    "node_modules/responsive-storage": {
 | 
				
			||||||
      "version": "1.0.1",
 | 
					      "version": "1.0.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/responsive-storage/-/responsive-storage-1.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/responsive-storage/-/responsive-storage-1.0.4.tgz",
 | 
				
			||||||
      "integrity": "sha512-p9HXODNHkdRUgaJ+mm6qKhsQCgWo1bGHAUlvbb4II5yJnb189Hrb8kKxHfG1KlbrnAQ2wR60a2BLq1AoDLp2nA==",
 | 
					      "integrity": "sha512-egiborkG1SMM5rQYMb0J0tdnDa/yH4h4ptA/fEcMAEoSaAe9j+Z4TMHFMb8x3BrM02StNuO8sNwbwVxLj+xzcA==",
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "vue": "^3.1.1"
 | 
					        "vue": "^3.1.1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -5067,9 +5067,9 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "responsive-storage": {
 | 
					    "responsive-storage": {
 | 
				
			||||||
      "version": "1.0.1",
 | 
					      "version": "1.0.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/responsive-storage/-/responsive-storage-1.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/responsive-storage/-/responsive-storage-1.0.4.tgz",
 | 
				
			||||||
      "integrity": "sha512-p9HXODNHkdRUgaJ+mm6qKhsQCgWo1bGHAUlvbb4II5yJnb189Hrb8kKxHfG1KlbrnAQ2wR60a2BLq1AoDLp2nA==",
 | 
					      "integrity": "sha512-egiborkG1SMM5rQYMb0J0tdnDa/yH4h4ptA/fEcMAEoSaAe9j+Z4TMHFMb8x3BrM02StNuO8sNwbwVxLj+xzcA==",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "vue": "^3.1.1"
 | 
					        "vue": "^3.1.1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  "husky": {
 | 
					  "husky": {
 | 
				
			||||||
    "hooks": {
 | 
					    "hooks": {
 | 
				
			||||||
      "commit-msg": "node scripts/verify-commit.ts"
 | 
					      "commit-msg": "node scripts/verify-commit.js"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
@ -35,7 +35,7 @@
 | 
				
			|||||||
    "path-to-regexp": "^6.2.0",
 | 
					    "path-to-regexp": "^6.2.0",
 | 
				
			||||||
    "pinia": "^2.0.0-beta.2",
 | 
					    "pinia": "^2.0.0-beta.2",
 | 
				
			||||||
    "resize-observer-polyfill": "^1.5.1",
 | 
					    "resize-observer-polyfill": "^1.5.1",
 | 
				
			||||||
    "responsive-storage": "^1.0.1",
 | 
					    "responsive-storage": "^1.0.4",
 | 
				
			||||||
    "v-contextmenu": "^3.0.0",
 | 
					    "v-contextmenu": "^3.0.0",
 | 
				
			||||||
    "vue": "^3.1.1",
 | 
					    "vue": "^3.1.1",
 | 
				
			||||||
    "vue-i18n": "^9.1.6",
 | 
					    "vue-i18n": "^9.1.6",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										22
									
								
								scripts/verify-commit.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								scripts/verify-commit.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					const chalk = require("chalk")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const msgPath = process.env.HUSKY_GIT_PARAMS
 | 
				
			||||||
 | 
					const msg = require("fs").readFileSync(msgPath, "utf-8").trim()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const commitRE = /^(revert: )?(feat|fix|polish|docs|style|refactor|perf|test|workflow|ci|chore|types)(\(.+\))?: .{1,50}/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!commitRE.test(msg)) {
 | 
				
			||||||
 | 
					  console.error(
 | 
				
			||||||
 | 
					    `  ${chalk.bgRed.white(" ERROR ")} ${chalk.red(
 | 
				
			||||||
 | 
					      "不合法的 commit 消息格式"
 | 
				
			||||||
 | 
					    )}\n\n` +
 | 
				
			||||||
 | 
					    chalk.red("  请使用正确的提交格式:\n\n") +
 | 
				
			||||||
 | 
					    `    ${chalk.green("feat: add 'comments' option")}\n` +
 | 
				
			||||||
 | 
					    `    ${chalk.green("fix: handle events on blur (close #28)")}\n\n` +
 | 
				
			||||||
 | 
					    chalk.red(
 | 
				
			||||||
 | 
					      "  请查看 git commit 提交规范:https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md \n"
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  process.exit(1)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,23 +0,0 @@
 | 
				
			|||||||
const chalk = require("chalk");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const msgPath = process.env.HUSKY_GIT_PARAMS;
 | 
					 | 
				
			||||||
const msg = require("fs").readFileSync(msgPath, "utf-8").trim();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const commitRE = /^(revert: )?(feat|fix|polish|docs|style|refactor|perf|test|workflow|ci|chore|types)(\(.+\))?: .{1,50}/;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (!commitRE.test(msg)) {
 | 
					 | 
				
			||||||
  console.log();
 | 
					 | 
				
			||||||
  console.error(
 | 
					 | 
				
			||||||
    `  ${chalk.bgRed.white(" ERROR ")} ${chalk.red(
 | 
					 | 
				
			||||||
      "不合法的 commit 消息格式"
 | 
					 | 
				
			||||||
    )}\n\n` +
 | 
					 | 
				
			||||||
      chalk.red("  请使用正确的提交格式:\n\n") +
 | 
					 | 
				
			||||||
      `    ${chalk.green("feat: add 'comments' option")}\n` +
 | 
					 | 
				
			||||||
      `    ${chalk.green("fix: handle events on blur (close #28)")}\n\n` +
 | 
					 | 
				
			||||||
      chalk.red(
 | 
					 | 
				
			||||||
        "  请查看 git commit 提交规范:https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md \n"
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  process.exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -34,7 +34,6 @@ import { useRoute, useRouter } from "vue-router";
 | 
				
			|||||||
import { useAppStoreHook } from "/@/store/modules/app";
 | 
					import { useAppStoreHook } from "/@/store/modules/app";
 | 
				
			||||||
import SidebarItem from "./SidebarItem.vue";
 | 
					import SidebarItem from "./SidebarItem.vue";
 | 
				
			||||||
import { algorithm } from "../../../utils/algorithm";
 | 
					import { algorithm } from "../../../utils/algorithm";
 | 
				
			||||||
import { useDynamicRoutesHook } from "../tag/tagsHook";
 | 
					 | 
				
			||||||
import { emitter } from "/@/utils/mitt";
 | 
					import { emitter } from "/@/utils/mitt";
 | 
				
			||||||
import Logo from "./Logo.vue";
 | 
					import Logo from "./Logo.vue";
 | 
				
			||||||
import { storageLocal } from "/@/utils/storage";
 | 
					import { storageLocal } from "/@/utils/storage";
 | 
				
			||||||
@ -62,8 +61,6 @@ export default defineComponent({
 | 
				
			|||||||
      return path;
 | 
					      return path;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { dynamicRouteTags } = useDynamicRoutesHook();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const menuSelect = (indexPath: string): void => {
 | 
					    const menuSelect = (indexPath: string): void => {
 | 
				
			||||||
      let parentPath = "";
 | 
					      let parentPath = "";
 | 
				
			||||||
      let parentPathIndex = indexPath.lastIndexOf("/");
 | 
					      let parentPathIndex = indexPath.lastIndexOf("/");
 | 
				
			||||||
@ -74,7 +71,11 @@ export default defineComponent({
 | 
				
			|||||||
      function findCurrentRoute(routes) {
 | 
					      function findCurrentRoute(routes) {
 | 
				
			||||||
        return routes.map((item, key) => {
 | 
					        return routes.map((item, key) => {
 | 
				
			||||||
          if (item.path === indexPath) {
 | 
					          if (item.path === indexPath) {
 | 
				
			||||||
            dynamicRouteTags(indexPath, parentPath, item);
 | 
					            // 切换左侧菜单 通知标签页
 | 
				
			||||||
 | 
					            emitter.emit("changLayoutRoute", {
 | 
				
			||||||
 | 
					              indexPath,
 | 
				
			||||||
 | 
					              parentPath
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            if (item.children) findCurrentRoute(item.children);
 | 
					            if (item.children) findCurrentRoute(item.children);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -82,7 +83,6 @@ export default defineComponent({
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      findCurrentRoute(algorithm.increaseIndexes(router));
 | 
					      findCurrentRoute(algorithm.increaseIndexes(router));
 | 
				
			||||||
      emitter.emit("changLayoutRoute", indexPath);
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onBeforeMount(() => {
 | 
					    onBeforeMount(() => {
 | 
				
			||||||
 | 
				
			|||||||
@ -72,8 +72,6 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang='ts'>
 | 
					<script lang='ts'>
 | 
				
			||||||
import { useDynamicRoutesHook } from "./tagsHook";
 | 
					 | 
				
			||||||
import { useRoute, useRouter } from "vue-router";
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  ref,
 | 
					  ref,
 | 
				
			||||||
  watchEffect,
 | 
					  watchEffect,
 | 
				
			||||||
@ -83,22 +81,39 @@ import {
 | 
				
			|||||||
  nextTick,
 | 
					  nextTick,
 | 
				
			||||||
  getCurrentInstance
 | 
					  getCurrentInstance
 | 
				
			||||||
} from "vue";
 | 
					} from "vue";
 | 
				
			||||||
 | 
					import { useRoute, useRouter } from "vue-router";
 | 
				
			||||||
import { storageLocal } from "/@/utils/storage";
 | 
					import { storageLocal } from "/@/utils/storage";
 | 
				
			||||||
import { emitter } from "/@/utils/mitt";
 | 
					import { emitter } from "/@/utils/mitt";
 | 
				
			||||||
import { toggleClass, removeClass, hasClass } from "/@/utils/operate";
 | 
					import { toggleClass, removeClass, hasClass } from "/@/utils/operate";
 | 
				
			||||||
import { templateRef } from "@vueuse/core";
 | 
					import { templateRef } from "@vueuse/core";
 | 
				
			||||||
import { homeRoute } from "./type";
 | 
					 | 
				
			||||||
let refreshButton = "refresh-button";
 | 
					let refreshButton = "refresh-button";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let routerArrays = [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: "/welcome",
 | 
				
			||||||
 | 
					    meta: {
 | 
				
			||||||
 | 
					      title: "message.hshome",
 | 
				
			||||||
 | 
					      icon: "el-icon-s-home",
 | 
				
			||||||
 | 
					      showLink: true,
 | 
				
			||||||
 | 
					      savedPosition: false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
 | 
					  computed: {
 | 
				
			||||||
 | 
					    dynamicTagList() {
 | 
				
			||||||
 | 
					      if (
 | 
				
			||||||
 | 
					        !this.$storage.routesInStorage ||
 | 
				
			||||||
 | 
					        this.$storage.routesInStorage.length === 0
 | 
				
			||||||
 | 
					      ) {
 | 
				
			||||||
 | 
					        this.$storage.routesInStorage = routerArrays;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return this.$storage.routesInStorage;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  setup() {
 | 
					  setup() {
 | 
				
			||||||
    let vm: any;
 | 
					    let vm: any;
 | 
				
			||||||
    const {
 | 
					    let st: any;
 | 
				
			||||||
      deleteDynamicTag,
 | 
					 | 
				
			||||||
      dynamicRouteTags,
 | 
					 | 
				
			||||||
      dRoutes,
 | 
					 | 
				
			||||||
      routesLength
 | 
					 | 
				
			||||||
    } = useDynamicRoutesHook();
 | 
					 | 
				
			||||||
    const route = useRoute();
 | 
					    const route = useRoute();
 | 
				
			||||||
    const router = useRouter();
 | 
					    const router = useRouter();
 | 
				
			||||||
    const showTags = ref(storageLocal.getItem("tagsVal") || false);
 | 
					    const showTags = ref(storageLocal.getItem("tagsVal") || false);
 | 
				
			||||||
@ -116,21 +131,21 @@ export default {
 | 
				
			|||||||
        icon: "el-icon-close",
 | 
					        icon: "el-icon-close",
 | 
				
			||||||
        text: "关闭当前标签页",
 | 
					        text: "关闭当前标签页",
 | 
				
			||||||
        divided: false,
 | 
					        divided: false,
 | 
				
			||||||
        disabled: unref(routesLength) > 1 ? false : true,
 | 
					        disabled: routerArrays.length > 1 ? false : true,
 | 
				
			||||||
        show: true
 | 
					        show: true
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        icon: "el-icon-more",
 | 
					        icon: "el-icon-more",
 | 
				
			||||||
        text: "关闭其他标签页",
 | 
					        text: "关闭其他标签页",
 | 
				
			||||||
        divided: true,
 | 
					        divided: true,
 | 
				
			||||||
        disabled: unref(routesLength) > 2 ? false : true,
 | 
					        disabled: routerArrays.length > 2 ? false : true,
 | 
				
			||||||
        show: true
 | 
					        show: true
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        icon: "el-icon-minus",
 | 
					        icon: "el-icon-minus",
 | 
				
			||||||
        text: "关闭全部标签页",
 | 
					        text: "关闭全部标签页",
 | 
				
			||||||
        divided: false,
 | 
					        divided: false,
 | 
				
			||||||
        disabled: unref(routesLength) > 1 ? false : true,
 | 
					        disabled: routerArrays.length > 1 ? false : true,
 | 
				
			||||||
        show: true
 | 
					        show: true
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]);
 | 
					    ]);
 | 
				
			||||||
@ -148,30 +163,33 @@ export default {
 | 
				
			|||||||
    // 当前右键选中的路由信息
 | 
					    // 当前右键选中的路由信息
 | 
				
			||||||
    let currentSelect = ref({});
 | 
					    let currentSelect = ref({});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function deleteMenu(item) {
 | 
					    function dynamicRouteTag(value: string, parentPath: string): void {
 | 
				
			||||||
      let tagslen = storageLocal.getItem("routesInStorage").length;
 | 
					      const hasValue = st.routesInStorage.some((item: any) => {
 | 
				
			||||||
      if (tagslen === 2) {
 | 
					        return item.path === value;
 | 
				
			||||||
        Array.from([1, 2, 3]).forEach(v => {
 | 
					      });
 | 
				
			||||||
          tagsViews.value[v].disabled = true;
 | 
					
 | 
				
			||||||
        });
 | 
					      function concatPath(arr: object[], value: string, parentPath: string) {
 | 
				
			||||||
 | 
					        if (!hasValue) {
 | 
				
			||||||
 | 
					          arr.forEach((arrItem: any) => {
 | 
				
			||||||
 | 
					            let pathConcat = parentPath + arrItem.path;
 | 
				
			||||||
 | 
					            if (arrItem.path === value || pathConcat === value) {
 | 
				
			||||||
 | 
					              routerArrays.push({
 | 
				
			||||||
 | 
					                path: value,
 | 
				
			||||||
 | 
					                meta: arrItem.meta
 | 
				
			||||||
 | 
					              });
 | 
				
			||||||
 | 
					              st.routesInStorage = routerArrays;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					              if (arrItem.children && arrItem.children.length > 0) {
 | 
				
			||||||
 | 
					                concatPath(arrItem.children, value, parentPath);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (tagslen === 3) {
 | 
					      concatPath(router.options.routes, value, parentPath);
 | 
				
			||||||
        tagsViews.value[2].disabled = true;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      deleteDynamicTag(item, route.path);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 初始化页面刷新保证当前路由tabview存在
 | 
					    // 重新加载
 | 
				
			||||||
    let stop = watchEffect(() => {
 | 
					 | 
				
			||||||
      let parentPath = route.path.slice(0, route.path.lastIndexOf("/"));
 | 
					 | 
				
			||||||
      dynamicRouteTags(route.path, parentPath, route);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    setTimeout(() => {
 | 
					 | 
				
			||||||
      // 监听只执行一次,但获取不到当前路由,需要下一个事件轮询中取消监听
 | 
					 | 
				
			||||||
      stop();
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function onFresh() {
 | 
					    function onFresh() {
 | 
				
			||||||
      toggleClass(true, refreshButton, document.querySelector(".rotate"));
 | 
					      toggleClass(true, refreshButton, document.querySelector(".rotate"));
 | 
				
			||||||
      const { path, fullPath } = unref(route);
 | 
					      const { path, fullPath } = unref(route);
 | 
				
			||||||
@ -183,6 +201,57 @@ export default {
 | 
				
			|||||||
      }, 600);
 | 
					      }, 600);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function deleteDynamicTag(obj: any, current: any, other: any) {
 | 
				
			||||||
 | 
					      let valueIndex: number = routerArrays.findIndex((item: any) => {
 | 
				
			||||||
 | 
					        return item.path === obj.path;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (other) {
 | 
				
			||||||
 | 
					        st.routesInStorage = routerArrays = [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            path: "/welcome",
 | 
				
			||||||
 | 
					            meta: {
 | 
				
			||||||
 | 
					              title: "message.hshome",
 | 
				
			||||||
 | 
					              icon: "el-icon-s-home",
 | 
				
			||||||
 | 
					              showLink: true,
 | 
				
			||||||
 | 
					              savedPosition: false
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          obj
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					        router.push(obj.path);
 | 
				
			||||||
 | 
					        Array.from([2]).forEach(v => {
 | 
				
			||||||
 | 
					          tagsViews.value[v].disabled = true;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        // 从当前匹配到的路径中删除
 | 
				
			||||||
 | 
					        routerArrays.splice(valueIndex, 1);
 | 
				
			||||||
 | 
					        st.routesInStorage = routerArrays;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (current === obj.path) {
 | 
				
			||||||
 | 
					        // 如果删除当前激活tag就自动切换到最后一个tag
 | 
				
			||||||
 | 
					        let newRoute: any = routerArrays.slice(-1);
 | 
				
			||||||
 | 
					        nextTick(() => {
 | 
				
			||||||
 | 
					          router.push({
 | 
				
			||||||
 | 
					            path: newRoute[0].path
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function deleteMenu(item, other = false) {
 | 
				
			||||||
 | 
					      if (routerArrays.length === 2) {
 | 
				
			||||||
 | 
					        Array.from([1, 2, 3]).forEach(v => {
 | 
				
			||||||
 | 
					          tagsViews.value[v].disabled = true;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (routerArrays.length === 3) {
 | 
				
			||||||
 | 
					        tagsViews.value[2].disabled = true;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      deleteDynamicTag(item, route.path, other);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function onClickDrop(key, item, selectRoute) {
 | 
					    function onClickDrop(key, item, selectRoute) {
 | 
				
			||||||
      if (item && item.disabled) return;
 | 
					      if (item && item.disabled) return;
 | 
				
			||||||
      // 当前路由信息
 | 
					      // 当前路由信息
 | 
				
			||||||
@ -199,17 +268,20 @@ export default {
 | 
				
			|||||||
          break;
 | 
					          break;
 | 
				
			||||||
        case 2:
 | 
					        case 2:
 | 
				
			||||||
          // 关闭其他标签页
 | 
					          // 关闭其他标签页
 | 
				
			||||||
          dRoutes.value = selectRoute
 | 
					          selectRoute
 | 
				
			||||||
            ? [homeRoute, { path: selectRoute.path, meta: selectRoute.meta }]
 | 
					            ? deleteMenu(
 | 
				
			||||||
            : [homeRoute, { path: route.path, meta: route.meta }];
 | 
					                {
 | 
				
			||||||
          storageLocal.setItem("routesInStorage", dRoutes.value);
 | 
					                  path: selectRoute.path,
 | 
				
			||||||
          tagsViews.value[2].disabled = true;
 | 
					                  meta: selectRoute.meta
 | 
				
			||||||
          if (selectRoute) router.push(selectRoute.path);
 | 
					                },
 | 
				
			||||||
 | 
					                true
 | 
				
			||||||
 | 
					              )
 | 
				
			||||||
 | 
					            : deleteMenu({ path: route.path, meta: route.meta }, true);
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        case 3:
 | 
					        case 3:
 | 
				
			||||||
          // 关闭全部标签页
 | 
					          // 关闭全部标签页
 | 
				
			||||||
          dRoutes.value = [homeRoute];
 | 
					          routerArrays.splice(1, routerArrays.length);
 | 
				
			||||||
          storageLocal.setItem("routesInStorage", dRoutes.value);
 | 
					          st.routesInStorage = routerArrays;
 | 
				
			||||||
          router.push("/welcome");
 | 
					          router.push("/welcome");
 | 
				
			||||||
          Array.from([1, 2, 3]).forEach(v => {
 | 
					          Array.from([1, 2, 3]).forEach(v => {
 | 
				
			||||||
            tagsViews.value[v].disabled = true;
 | 
					            tagsViews.value[v].disabled = true;
 | 
				
			||||||
@ -235,6 +307,12 @@ export default {
 | 
				
			|||||||
        Array.from([1, 2, 3]).forEach(v => {
 | 
					        Array.from([1, 2, 3]).forEach(v => {
 | 
				
			||||||
          tagsViews.value[v].show = true;
 | 
					          tagsViews.value[v].show = true;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					      } else if (st.routesInStorage.length === 2) {
 | 
				
			||||||
 | 
					        // 只有两个标签时不显示关闭其他标签页
 | 
				
			||||||
 | 
					        tagsViews.value[2].show = false;
 | 
				
			||||||
 | 
					        Array.from([0, 1, 3]).forEach(v => {
 | 
				
			||||||
 | 
					          tagsViews.value[v].show = true;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        Array.from([0, 1, 2, 3]).forEach(v => {
 | 
					        Array.from([0, 1, 2, 3]).forEach(v => {
 | 
				
			||||||
          tagsViews.value[v].show = true;
 | 
					          tagsViews.value[v].show = true;
 | 
				
			||||||
@ -260,17 +338,6 @@ export default {
 | 
				
			|||||||
      visible.value = false;
 | 
					      visible.value = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    watch(
 | 
					 | 
				
			||||||
      () => visible.value,
 | 
					 | 
				
			||||||
      val => {
 | 
					 | 
				
			||||||
        if (val) {
 | 
					 | 
				
			||||||
          document.body.addEventListener("click", closeMenu);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          document.body.removeEventListener("click", closeMenu);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // 鼠标移入
 | 
					    // 鼠标移入
 | 
				
			||||||
    function onMouseenter(item, index) {
 | 
					    function onMouseenter(item, index) {
 | 
				
			||||||
      if (index) activeIndex.value = index;
 | 
					      if (index) activeIndex.value = index;
 | 
				
			||||||
@ -299,8 +366,20 @@ export default {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    watch(
 | 
				
			||||||
 | 
					      () => visible.value,
 | 
				
			||||||
 | 
					      val => {
 | 
				
			||||||
 | 
					        if (val) {
 | 
				
			||||||
 | 
					          document.body.addEventListener("click", closeMenu);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          document.body.removeEventListener("click", closeMenu);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onBeforeMount(() => {
 | 
					    onBeforeMount(() => {
 | 
				
			||||||
      vm = getCurrentInstance();
 | 
					      vm = getCurrentInstance();
 | 
				
			||||||
 | 
					      st = vm.appContext.app.config.globalProperties.$storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      emitter.on("tagViewsChange", key => {
 | 
					      emitter.on("tagViewsChange", key => {
 | 
				
			||||||
        if (unref(showTags) === key) return;
 | 
					        if (unref(showTags) === key) return;
 | 
				
			||||||
@ -311,14 +390,16 @@ export default {
 | 
				
			|||||||
        showModel.value = key;
 | 
					        showModel.value = key;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      emitter.on("changLayoutRoute", indexPath => {
 | 
					      //  接收侧边栏切换传递过来的参数
 | 
				
			||||||
        let currentLen = storageLocal.getItem("routesInStorage").length;
 | 
					      emitter.on("changLayoutRoute", ({ indexPath, parentPath }) => {
 | 
				
			||||||
        if (currentLen === 1) {
 | 
					        dynamicRouteTag(indexPath, parentPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (routerArrays.length === 2) {
 | 
				
			||||||
          Array.from([1, 3]).forEach(v => {
 | 
					          Array.from([1, 3]).forEach(v => {
 | 
				
			||||||
            tagsViews.value[v].disabled = false;
 | 
					            tagsViews.value[v].disabled = false;
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (currentLen >= 2) {
 | 
					        if (routerArrays.length > 2) {
 | 
				
			||||||
          Array.from([1, 2, 3]).forEach(v => {
 | 
					          Array.from([1, 2, 3]).forEach(v => {
 | 
				
			||||||
            tagsViews.value[v].disabled = false;
 | 
					            tagsViews.value[v].disabled = false;
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
@ -327,7 +408,6 @@ export default {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      dynamicTagList: useDynamicRoutesHook().dRoutes,
 | 
					 | 
				
			||||||
      deleteMenu,
 | 
					      deleteMenu,
 | 
				
			||||||
      showTags,
 | 
					      showTags,
 | 
				
			||||||
      onFresh,
 | 
					      onFresh,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,120 +0,0 @@
 | 
				
			|||||||
import { reactive, toRefs, unref, nextTick, computed } from "vue";
 | 
					 | 
				
			||||||
import { storageLocal } from "/@/utils/storage";
 | 
					 | 
				
			||||||
import { useRouter } from "vue-router";
 | 
					 | 
				
			||||||
import { homeRoute } from "./type";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface InterDynamic {
 | 
					 | 
				
			||||||
  dRoutes: object[];
 | 
					 | 
				
			||||||
  [propName: string]: any;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 默认显示首页tag
 | 
					 | 
				
			||||||
let dynamic: InterDynamic = reactive({
 | 
					 | 
				
			||||||
  dRoutes: [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      path: "/welcome",
 | 
					 | 
				
			||||||
      meta: {
 | 
					 | 
				
			||||||
        title: "message.hshome",
 | 
					 | 
				
			||||||
        icon: "el-icon-s-home",
 | 
					 | 
				
			||||||
        showLink: true,
 | 
					 | 
				
			||||||
        savedPosition: false,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ],
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function useDynamicRoutesHook() {
 | 
					 | 
				
			||||||
  const router = useRouter();
 | 
					 | 
				
			||||||
  const routesLength = computed(() => {
 | 
					 | 
				
			||||||
    return storageLocal.getItem("routesInStorage")
 | 
					 | 
				
			||||||
      ? storageLocal.getItem("routesInStorage").length
 | 
					 | 
				
			||||||
      : 0;
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
  // 返回当前路由组成的数组
 | 
					 | 
				
			||||||
  const routesStorageLists = computed(() => {
 | 
					 | 
				
			||||||
    return storageLocal.getItem("routesInStorage")
 | 
					 | 
				
			||||||
      ? storageLocal.getItem("routesInStorage")
 | 
					 | 
				
			||||||
      : [];
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * @param value string 当前menu对应的路由path
 | 
					 | 
				
			||||||
   * @param parentPath string 当前路由中父级路由
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  const dynamicRouteTags = (
 | 
					 | 
				
			||||||
    value: string,
 | 
					 | 
				
			||||||
    parentPath: string,
 | 
					 | 
				
			||||||
    route: any
 | 
					 | 
				
			||||||
  ): void => {
 | 
					 | 
				
			||||||
    nextTick(() => {
 | 
					 | 
				
			||||||
      if (unref(routesStorageLists).length > 2) {
 | 
					 | 
				
			||||||
        dynamic.dRoutes = unref(routesStorageLists);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const hasValue = dynamic.dRoutes.some((item: any) => {
 | 
					 | 
				
			||||||
      return item.path === value;
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (route) {
 | 
					 | 
				
			||||||
      let ramStorage = storageLocal.getItem("routesInStorage");
 | 
					 | 
				
			||||||
      nextTick(() => {
 | 
					 | 
				
			||||||
        if (ramStorage) {
 | 
					 | 
				
			||||||
          let currentIndex = ramStorage.findIndex((v) => v.path === route.path);
 | 
					 | 
				
			||||||
          if (currentIndex !== -1) return;
 | 
					 | 
				
			||||||
          ramStorage.push({ path: route.path, meta: route.meta });
 | 
					 | 
				
			||||||
          storageLocal.setItem("routesInStorage", ramStorage);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function concatPath(arr: object[], value: string, parentPath: string) {
 | 
					 | 
				
			||||||
      if (!hasValue) {
 | 
					 | 
				
			||||||
        arr.forEach((arrItem: any) => {
 | 
					 | 
				
			||||||
          let pathConcat = parentPath + "/" + arrItem.path;
 | 
					 | 
				
			||||||
          if (arrItem.path === value || pathConcat === value) {
 | 
					 | 
				
			||||||
            dynamic.dRoutes.push({ path: value, meta: arrItem.meta });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            unref(routesLength) === 0
 | 
					 | 
				
			||||||
              ? storageLocal.setItem("routesInStorage", dynamic.dRoutes)
 | 
					 | 
				
			||||||
              : [];
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            if (arrItem.children && arrItem.children.length > 0) {
 | 
					 | 
				
			||||||
              concatPath(arrItem.children, value, parentPath);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    concatPath(router.options.routes, value, parentPath);
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * @param value any 当前删除tag路由
 | 
					 | 
				
			||||||
   * @param current objct 当前激活路由对象
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  const deleteDynamicTag = async (obj: any, current: any): Promise<any> => {
 | 
					 | 
				
			||||||
    let valueIndex: number = dynamic.dRoutes.findIndex((item: any) => {
 | 
					 | 
				
			||||||
      return item.path === obj.path;
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    // 从当前匹配到的路径中删除
 | 
					 | 
				
			||||||
    await dynamic.dRoutes.splice(valueIndex, 1);
 | 
					 | 
				
			||||||
    storageLocal.setItem("routesInStorage", dynamic.dRoutes);
 | 
					 | 
				
			||||||
    if (current === obj.path) {
 | 
					 | 
				
			||||||
      // 如果删除当前激活tag就自动切换到最后一个tag
 | 
					 | 
				
			||||||
      let newRoute: any = dynamic.dRoutes.slice(-1);
 | 
					 | 
				
			||||||
      nextTick(() => {
 | 
					 | 
				
			||||||
        router.push({
 | 
					 | 
				
			||||||
          path: newRoute[0].path,
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return {
 | 
					 | 
				
			||||||
    ...toRefs(dynamic),
 | 
					 | 
				
			||||||
    dynamicRouteTags,
 | 
					 | 
				
			||||||
    deleteDynamicTag,
 | 
					 | 
				
			||||||
    routesLength,
 | 
					 | 
				
			||||||
    routesStorageLists,
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,15 +0,0 @@
 | 
				
			|||||||
interface RouteModel {
 | 
					 | 
				
			||||||
  readonly path: string;
 | 
					 | 
				
			||||||
  readonly meta: object;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 固定首页路由
 | 
					 | 
				
			||||||
export const homeRoute: RouteModel = {
 | 
					 | 
				
			||||||
  path: "/welcome",
 | 
					 | 
				
			||||||
  meta: {
 | 
					 | 
				
			||||||
    title: "message.hshome",
 | 
					 | 
				
			||||||
    icon: "el-icon-s-home",
 | 
					 | 
				
			||||||
    showLink: true,
 | 
					 | 
				
			||||||
    savedPosition: false,
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@ -26,6 +26,7 @@ app.config.globalProperties.$config = getConfig();
 | 
				
			|||||||
import Storage from "responsive-storage";
 | 
					import Storage from "responsive-storage";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.use(Storage, {
 | 
					app.use(Storage, {
 | 
				
			||||||
 | 
					  // 默认显示首页tag
 | 
				
			||||||
  routesInStorage: {
 | 
					  routesInStorage: {
 | 
				
			||||||
    type: String,
 | 
					    type: String,
 | 
				
			||||||
    default: Storage.getData(undefined, "routesInStorage") ?? [
 | 
					    default: Storage.getData(undefined, "routesInStorage") ?? [
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ const nestedRouter = {
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  children: [
 | 
					  children: [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      path: "menu1",
 | 
					      path: "/nested/menu1",
 | 
				
			||||||
      component: () => import("/@/views/nested/menu1/index.vue"),
 | 
					      component: () => import("/@/views/nested/menu1/index.vue"),
 | 
				
			||||||
      name: "Menu1",
 | 
					      name: "Menu1",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
@ -25,7 +25,7 @@ const nestedRouter = {
 | 
				
			|||||||
      redirect: "/nested/menu1/menu1-1",
 | 
					      redirect: "/nested/menu1/menu1-1",
 | 
				
			||||||
      children: [
 | 
					      children: [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          path: "menu1-1",
 | 
					          path: "/nested/menu1/menu1-1",
 | 
				
			||||||
          component: () => import("/@/views/nested/menu1/menu1-1/index.vue"),
 | 
					          component: () => import("/@/views/nested/menu1/menu1-1/index.vue"),
 | 
				
			||||||
          name: "Menu1-1",
 | 
					          name: "Menu1-1",
 | 
				
			||||||
          meta: {
 | 
					          meta: {
 | 
				
			||||||
@ -35,7 +35,7 @@ const nestedRouter = {
 | 
				
			|||||||
          },
 | 
					          },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          path: "menu1-2",
 | 
					          path: "/nested/menu1/menu1-2",
 | 
				
			||||||
          component: () => import("/@/views/nested/menu1/menu1-2/index.vue"),
 | 
					          component: () => import("/@/views/nested/menu1/menu1-2/index.vue"),
 | 
				
			||||||
          name: "Menu1-2",
 | 
					          name: "Menu1-2",
 | 
				
			||||||
          redirect: "/nested/menu1/menu1-2/menu1-2-1",
 | 
					          redirect: "/nested/menu1/menu1-2/menu1-2-1",
 | 
				
			||||||
@ -46,7 +46,7 @@ const nestedRouter = {
 | 
				
			|||||||
          },
 | 
					          },
 | 
				
			||||||
          children: [
 | 
					          children: [
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
              path: "menu1-2-1",
 | 
					              path: "/nested/menu1/menu1-2/menu1-2-1",
 | 
				
			||||||
              component: () =>
 | 
					              component: () =>
 | 
				
			||||||
                import("/@/views/nested/menu1/menu1-2/menu1-2-1/index.vue"),
 | 
					                import("/@/views/nested/menu1/menu1-2/menu1-2-1/index.vue"),
 | 
				
			||||||
              name: "Menu1-2-1",
 | 
					              name: "Menu1-2-1",
 | 
				
			||||||
@ -57,7 +57,7 @@ const nestedRouter = {
 | 
				
			|||||||
              },
 | 
					              },
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
              path: "menu1-2-2",
 | 
					              path: "/nested/menu1/menu1-2/menu1-2-2",
 | 
				
			||||||
              component: () =>
 | 
					              component: () =>
 | 
				
			||||||
                import("/@/views/nested/menu1/menu1-2/menu1-2-2/index.vue"),
 | 
					                import("/@/views/nested/menu1/menu1-2/menu1-2-2/index.vue"),
 | 
				
			||||||
              name: "Menu1-2-2",
 | 
					              name: "Menu1-2-2",
 | 
				
			||||||
@ -70,7 +70,7 @@ const nestedRouter = {
 | 
				
			|||||||
          ],
 | 
					          ],
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          path: "menu1-3",
 | 
					          path: "/nested/menu1/menu1-3",
 | 
				
			||||||
          component: () => import("/@/views/nested/menu1/menu1-3/index.vue"),
 | 
					          component: () => import("/@/views/nested/menu1/menu1-3/index.vue"),
 | 
				
			||||||
          name: "Menu1-3",
 | 
					          name: "Menu1-3",
 | 
				
			||||||
          meta: {
 | 
					          meta: {
 | 
				
			||||||
@ -82,7 +82,7 @@ const nestedRouter = {
 | 
				
			|||||||
      ],
 | 
					      ],
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      path: "menu2",
 | 
					      path: "/nested/menu2",
 | 
				
			||||||
      name: "Menu2",
 | 
					      name: "Menu2",
 | 
				
			||||||
      component: () => import("/@/views/nested/menu2/index.vue"),
 | 
					      component: () => import("/@/views/nested/menu2/index.vue"),
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user