Bläddra i källkod

refactor(fileList、CustormForm、IndexView): 优化细节

1.文件管理补充了下载功能,暂时没有文件夹下载功能,后续补充
2.表单字段现在可以填充默认值
3.优化了导航栏选中的判断逻辑
4.事件管理相关页面部分下拉框补充默认自
fxs 3 dagar sedan
förälder
incheckning
3078393202

+ 2 - 0
components.d.ts

@@ -13,6 +13,7 @@ declare module 'vue' {
     CustomFilter: typeof import('./src/components/form/CustomFilter.vue')['default']
     CustomForm: typeof import('./src/components/form/CustomForm.vue')['default']
     CustomTable: typeof import('./src/components/table/CustomTable.vue')['default']
+    DownloadTipModal: typeof import('./src/components/common/DownloadTipModal.vue')['default']
     DropDownSelection: typeof import('./src/components/dataAnalysis/DropDownSelection.vue')['default']
     ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
     ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
@@ -40,6 +41,7 @@ declare module 'vue' {
     ElPopover: typeof import('element-plus/es')['ElPopover']
     ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
+    ElResult: typeof import('element-plus/es')['ElResult']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']

+ 89 - 0
package-lock.json

@@ -10,12 +10,14 @@
       "dependencies": {
         "@element-plus/icons-vue": "^2.3.1",
         "@types/crypto-js": "^4.2.2",
+        "@types/file-saver": "^2.0.7",
         "axios": "^1.7.4",
         "crypto-js": "^4.2.0",
         "echarts": "^5.5.1",
         "element-plus": "^2.8.0",
         "fast-glob": "^3.3.2",
         "file-saver": "^2.0.5",
+        "jszip": "^3.10.1",
         "less": "^4.2.0",
         "pinia": "^2.1.7",
         "save": "^2.9.0",
@@ -1597,6 +1599,12 @@
       "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
       "license": "MIT"
     },
+    "node_modules/@types/file-saver": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmmirror.com/@types/file-saver/-/file-saver-2.0.7.tgz",
+      "integrity": "sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==",
+      "license": "MIT"
+    },
     "node_modules/@types/lodash": {
       "version": "4.17.7",
       "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.7.tgz",
@@ -2950,6 +2958,12 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/core-util-is": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz",
+      "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+      "license": "MIT"
+    },
     "node_modules/cors": {
       "version": "2.8.5",
       "resolved": "https://registry.npmmirror.com/cors/-/cors-2.8.5.tgz",
@@ -4988,6 +5002,12 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/immediate": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmmirror.com/immediate/-/immediate-3.0.6.tgz",
+      "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
+      "license": "MIT"
+    },
     "node_modules/import-fresh": {
       "version": "3.3.0",
       "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -5759,6 +5779,48 @@
         "graceful-fs": "^4.1.6"
       }
     },
+    "node_modules/jszip": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmmirror.com/jszip/-/jszip-3.10.1.tgz",
+      "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
+      "license": "(MIT OR GPL-3.0-or-later)",
+      "dependencies": {
+        "lie": "~3.3.0",
+        "pako": "~1.0.2",
+        "readable-stream": "~2.3.6",
+        "setimmediate": "^1.0.5"
+      }
+    },
+    "node_modules/jszip/node_modules/readable-stream": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz",
+      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+      "license": "MIT",
+      "dependencies": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "node_modules/jszip/node_modules/safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "license": "MIT"
+    },
+    "node_modules/jszip/node_modules/string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "license": "MIT",
+      "dependencies": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
     "node_modules/keyv": {
       "version": "4.5.4",
       "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
@@ -5825,6 +5887,15 @@
         "node": ">= 0.8.0"
       }
     },
+    "node_modules/lie": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmmirror.com/lie/-/lie-3.3.0.tgz",
+      "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+      "license": "MIT",
+      "dependencies": {
+        "immediate": "~3.0.5"
+      }
+    },
     "node_modules/loader-utils": {
       "version": "1.4.2",
       "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz",
@@ -6642,6 +6713,12 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/pako": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz",
+      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+      "license": "(MIT AND Zlib)"
+    },
     "node_modules/parent-module": {
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz",
@@ -7014,6 +7091,12 @@
         "node": ">=6.0.0"
       }
     },
+    "node_modules/process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+      "license": "MIT"
+    },
     "node_modules/proxy-from-env": {
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -7552,6 +7635,12 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
+      "license": "MIT"
+    },
     "node_modules/sharp": {
       "version": "0.33.5",
       "resolved": "https://registry.npmmirror.com/sharp/-/sharp-0.33.5.tgz",

+ 2 - 0
package.json

@@ -17,12 +17,14 @@
   "dependencies": {
     "@element-plus/icons-vue": "^2.3.1",
     "@types/crypto-js": "^4.2.2",
+    "@types/file-saver": "^2.0.7",
     "axios": "^1.7.4",
     "crypto-js": "^4.2.0",
     "echarts": "^5.5.1",
     "element-plus": "^2.8.0",
     "fast-glob": "^3.3.2",
     "file-saver": "^2.0.5",
+    "jszip": "^3.10.1",
     "less": "^4.2.0",
     "pinia": "^2.1.7",
     "save": "^2.9.0",

+ 64 - 0
src/components/common/DownloadTipModal.vue

@@ -0,0 +1,64 @@
+<template>
+  <el-dialog
+    v-model="visible"
+    :append-to-body="true"
+    :lock-scroll="true"
+    :show-close="true"
+    class="download-progress-dialog"
+  >
+    <el-result
+      icon="success"
+      title="下载已开始"
+      sub-title="完成后会将会有提示,期间你可以处理其他事情"
+    >
+      <template #extra>
+        <el-button type="primary" @click="hide">棒极了</el-button>
+      </template>
+    </el-result>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+
+const visible = ref(false)
+
+const show = () => {
+  visible.value = true
+}
+
+const hide = () => {
+  visible.value = false
+}
+
+defineExpose({ show, hide })
+</script>
+
+<style scoped>
+.download-progress-dialog :deep(.el-dialog__content) {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100%;
+}
+
+.progress-container {
+  text-align: center;
+  width: 100%;
+}
+
+.progress-bar {
+  width: 100%;
+  height: 10px;
+  background: #eee;
+  border-radius: 5px;
+  overflow: hidden;
+  margin: 20px 0;
+}
+
+.progress {
+  height: 100%;
+  background: #4caf50;
+  transition: width 0.3s ease;
+}
+</style>

+ 19 - 2
src/components/form/CustomForm.vue

@@ -10,11 +10,11 @@
 import type { FormInstance } from 'element-plus'
 import type { FormConfig } from '@/types/form'
 import { FormFieldType } from '@/types/form'
-import { reactive, ref } from 'vue'
+import { onMounted, reactive, ref } from 'vue'
 import { useForm } from '@/hooks/useForm'
 
 // import CryptoJS from 'crypto-js'
-import { HmacMD5, MD5 } from 'crypto-js'
+import { MD5 } from 'crypto-js'
 
 const { submitForm } = useForm()
 interface FormProp {
@@ -141,6 +141,23 @@ const getFormData = () => {
   return JSON.parse(JSON.stringify(formData))
 }
 
+/**
+ * 为所有有默认值的字段,添加默认值
+ */
+const setDefaultValue = () => {
+  const fieldsInfo = [...props.config.fieldsInfo]
+  fieldsInfo.forEach((item) => {
+    const fieldName = item.name
+    if (item.defaultValue) {
+      formData[fieldName] = item.defaultValue
+    }
+  })
+}
+
+onMounted(() => {
+  setDefaultValue()
+})
+
 defineExpose({
   submitFormData,
   resetForm,

+ 1 - 0
src/types/form.ts

@@ -14,6 +14,7 @@ export interface FormField {
   cnName: string
   type: FormFieldType
   valueType?: ValueTypes
+  defaultValue?: any
   otherOptions?: {
     placeholder?: string
     options?: Array<{ name: string; label: string; value: any }>

+ 2 - 0
src/views/AppManage/EventDetailsView.vue

@@ -274,6 +274,7 @@ const dialogFormFields: Array<FormField> = [
     name: 'status',
     cnName: '选项状态',
     type: FormFieldType.SELECT,
+    defaultValue: 1,
     otherOptions: {
       placeholder: '请选择状态',
       options: [
@@ -294,6 +295,7 @@ const dialogFormFields: Array<FormField> = [
     name: 'optionType',
     cnName: '选项类型',
     type: FormFieldType.SELECT,
+    defaultValue: 'string',
     otherOptions: {
       placeholder: '请选择类型',
       options: [

+ 1 - 1
src/views/AppManage/EventMangeTable.vue

@@ -223,6 +223,7 @@ const FormFields: Array<FormField> = [
     name: 'status',
     cnName: '是否启用',
     type: FormFieldType.SELECT,
+    defaultValue: 1,
     otherOptions: {
       placeholder: '请选择启用状态',
       options: [
@@ -280,7 +281,6 @@ const addNewEvent = () => {
  * 表单提交
  */
 const subForm = () => {
-  console.log('体')
   if (eventTable.value) {
     eventTable.value.updateTableData()
   }

+ 121 - 5
src/views/FileManage/FileList.vue

@@ -1,4 +1,5 @@
 <script setup lang="ts">
+import DownloadTipModal from '@/components/common/DownloadTipModal.vue'
 import CommonFileUpload from '@/components/form/CommonFileUpload.vue'
 
 import { useRequest } from '@/hooks/useRequest.ts'
@@ -6,8 +7,13 @@ import { useRequest } from '@/hooks/useRequest.ts'
 import { FilterType, type QueryInfo } from '@/types/table.ts'
 import axiosInstance from '@/utils/axios/axiosInstance.ts'
 import { ElMessageBox, type FormInstance } from 'element-plus'
+import FileSaver from 'file-saver'
+import JSZip from 'jszip'
+
 import { ref, onMounted } from 'vue'
 
+type DownloadProgressInstance = InstanceType<typeof DownloadTipModal>
+
 interface PaginationConfig {
   curPage: number
   curSize: number
@@ -97,6 +103,9 @@ const makeDirDialogConfig = ref({
   }
 })
 
+// 下载文件进度条
+const downloadProgressRef = ref<DownloadProgressInstance>()
+
 /**
  * 获取当前文件路径的完整路径
  * @returns 返回完整路径字符串,如 /a/b/
@@ -236,8 +245,13 @@ const handleDbClick = (id: number) => {
     ElMessage.warning('未选中文件,请重试')
     return
   }
-  // 是文件就返回
-  if (selectedItem.type === 1) return
+  // 是文件就触发下载
+  if (selectedItem.type === 1) {
+    const url = selectedItem.cos_path
+    // downloadSingleFile(url)
+    downloadFiles(url)
+    return
+  }
   breadcrumbList.value.push(selectedItem.file_name)
 
   getFileList()
@@ -259,6 +273,7 @@ const handleSelectAll = (isSelected: boolean) => {
 const handleOver = () => {
   selectedAble.value = false
   selectedRecord.value = {}
+  selectedAll.value = false
 }
 
 /**
@@ -372,6 +387,93 @@ const handleDel = async () => {
 }
 
 /**
+ * 获取选中的文件信息
+ * @returns 选中的文件信息
+ */
+const getSelectedInfo = () => {
+  const allIds = Object.keys(selectedRecord.value).map((item) => parseInt(item))
+  return fileListData.value.filter((item) => allIds.includes(item.id))
+}
+
+/**
+ * 单个文件下载
+ * @param url 文件下载地址
+ */
+const downloadSingleFile = async (url: string) => {
+  const response = await fetch(url)
+  const blob = await response.blob()
+  const fileName = url.split('/').pop()?.split('?')[0] ?? `文件`
+  FileSaver.saveAs(blob, fileName)
+}
+
+/**
+ * 批量下载文件
+ * @param urls 文件下载地址列表
+ */
+const handleBatchDownload = async (urls: string[]) => {
+  const zip = new JSZip()
+
+  const promises = urls.map(async (url, i) => {
+    const response = await fetch(url)
+    const blob = await response.blob()
+    const fileName = url.split('/').pop()?.split('?')[0] ?? `文件${i}`
+    zip.file(fileName, blob)
+  })
+  await Promise.all(promises)
+  const content = await zip.generateAsync({ type: 'blob' })
+  FileSaver.saveAs(content, `${new Date().getTime()}.zip`)
+}
+
+/**
+ * 下载文件
+ * 当单个文件时,直接下载
+ * 多个文件则会打包为zip进行下载
+ */
+const downloadFiles = async (singleFileDownloadUrl?: string) => {
+  try {
+    const info = getSelectedInfo()
+    // 文件夹需要单独去请求一下里面包含的所有url,然后合并到fileDownloadPaths中
+    // const folderId = info.filter((item) => item.type === 2).map((item) => item.id) // 筛选出文件夹ID
+    const fileDownloadPaths = info.filter((item) => item.type === 1).map((item) => item.cos_path)
+
+    const totalNums = fileDownloadPaths.length
+    // 总的文件下载数量,单个或者传入了单个文件的下载地址的话直接下,否则打包下
+    const isSingle = singleFileDownloadUrl || totalNums === 1
+
+    downloadProgressRef.value?.show()
+
+    if (isSingle) {
+      const url = singleFileDownloadUrl || fileDownloadPaths[0]
+      await downloadSingleFile(url)
+      return
+    }
+    // 这里防止意外情况
+    if (fileDownloadPaths.length === 0) {
+      ElMessage.warning('请至少选择一个文件进行下载')
+      return
+    }
+    await handleBatchDownload(fileDownloadPaths)
+
+    ElNotification({
+      title: 'Success',
+      message: '下载完成',
+      type: 'success',
+      duration: 5000
+    })
+  } catch (err) {
+    console.error(err)
+    ElNotification({
+      title: 'Error',
+      message: '下载失败,请稍后重试',
+      type: 'error',
+      duration: 0
+    })
+  } finally {
+    handleOver()
+  }
+}
+
+/**
  * 页面加载完成后,获取文件列表
  */
 onMounted(async () => {
@@ -390,9 +492,10 @@ onMounted(async () => {
     </div>
     <div :class="['toolContainer', isLoadData ? 'disableHandle' : '']">
       <el-button class="toolBtn" color="#197afb" @click="openUploadFile">上传文件</el-button>
+
       <el-button class="toolBtn" color="#197afb" plain @click="openCreateFolder"
-        >新建文件夹</el-button
-      >
+        >新建文件夹
+      </el-button>
       <el-button class="toolBtn" color="#197afb" plain @click="manageFile">管理</el-button>
     </div>
 
@@ -406,6 +509,13 @@ onMounted(async () => {
           </div>
           <div class="operationGroup">
             <el-button
+              class="toolBtn"
+              color="#197afb"
+              @click="() => downloadFiles()"
+              :disabled="Object.values(selectedRecord).filter((item) => item).length < 1"
+              >下载
+            </el-button>
+            <el-button
               class="toolBtn delBtn"
               color="#F56C6C"
               :disabled="Object.values(selectedRecord).filter((item) => item).length !== 1"
@@ -493,13 +603,19 @@ onMounted(async () => {
 
           <template #footer>
             <div class="make-dir-footer" :style="{ textAlign: 'right', padding: '10px 20px' }">
-              <el-button class="make-dir-btn confirm" type="primary" @click="handleCreate">确定</el-button>
+              <el-button class="make-dir-btn confirm" type="primary" @click="handleCreate"
+                >确定
+              </el-button>
               <el-button class="make-dir-btn cancel" @click="handleClose">取消</el-button>
             </div>
           </template>
         </el-dialog>
       </div>
     </div>
+
+    <!--下载进度-->
+
+    <DownloadTipModal ref="downloadProgressRef"></DownloadTipModal>
   </div>
 </template>
 

+ 45 - 17
src/views/IndexView.vue

@@ -10,7 +10,7 @@
 import type { DropDownInfo } from '@/types/dataAnalysis'
 
 import { zhCn } from 'element-plus/es/locales.mjs'
-import { RouterView, useRoute } from 'vue-router'
+import { type RouteRecordRaw, RouterView, useRoute } from 'vue-router'
 import { computed, onMounted, reactive, ref, watch } from 'vue'
 import { ElMessage } from 'element-plus'
 import { getAllGameInfo } from '@/utils/table/table'
@@ -100,13 +100,13 @@ const changeGame = (gid: string) => {
 
 /**
  * 更新头部导航栏,跳转到对应页面
- * @param {*} val 对应的name
+ * @param val 对应的name
  */
 const changeNavBar = (val: string) => {
   navBarSelect.value = val
 
   router.push(`/${val}`)
-  createdMenuList()
+  // createdMenuList()
 }
 
 // 资源的加载路径
@@ -125,15 +125,41 @@ const basePath = ref<string | undefined>()
 /**
  * 创建侧边栏菜单
  */
-const createdMenuList = () => {
-  let routes = router.options.routes // 获取路由信息
-  let indexRoutesChild = routes.find((item) => item.name === 'Index')?.children
-  let activeMenu = indexRoutesChild?.find((item) => {
-    return item.name === navBarSelect.value // 根据顶部导航栏的选中情况来选择选中哪个具体的路由信息,可以打印自己看一下
-  })
-  basePath.value = activeMenu?.path // 找到需要激活的菜单的路由,后续用来拼接需要跳转的路由
-  console.log(indexRoutesChild)
-  menuList.splice(0, menuList.length, ...(activeMenu?.children as Array<any>)) // 清空原来的路由信息,并且加入新选中的
+const createdMenuList = (topRoute: RouteRecordRaw | null) => {
+  if (!topRoute) return
+  basePath.value = topRoute?.path // 找到需要激活的菜单的路由,后续用来拼接需要跳转的路由
+  menuList.splice(0, menuList.length, ...(topRoute?.children as Array<any>)) // 清空原来的路由信息,并且加入新选中的
+}
+
+/**
+ * 从URL中解析出路径片段
+ * @param fullUrl 完整的 URL
+ * @returns 路径片段组成的数组
+ */
+const parsePathFromUrl = (fullUrl: string): string[] => {
+  const hashIndex = fullUrl.indexOf('#')
+  const hashPart = hashIndex !== -1 ? fullUrl.slice(hashIndex + 1) : fullUrl
+  const pathPart = hashPart.split('?')[0] // 去除查询参数
+  return pathPart.split('/').filter(Boolean) // ['home', 'infoManage', 'gameManageView']
+}
+
+/**
+ * 查找子路由所属的顶级路由
+ * @param routes 路由数组
+ * @param fullUrl 目标子路由的 name
+ * @returns 顶级路由的 name 或 null
+ */
+const findTopRouteName = (routes: RouteRecordRaw[], fullUrl: string): RouteRecordRaw | null => {
+  const pathSegments = parsePathFromUrl(fullUrl)
+  if (pathSegments.length === 0) return null
+
+  for (const route of routes) {
+    const routeSegments = route.path.split('/').filter(Boolean)
+    if (routeSegments[0] === pathSegments[0]) {
+      return route || null
+    }
+  }
+  return null
 }
 
 /**
@@ -144,11 +170,13 @@ watch(
   ([newFullPath]) => {
     let routes = router.options.routes // 获取路由信息
     let indexRoutesChild = routes.find((item) => item.name === 'Index')?.children
-    let activeMenu = indexRoutesChild?.find((item) => {
-      return newFullPath.includes(item.path) // 根据顶部导航栏的选中情况来选择选中哪个具体的路由信息,可以打印自己看一下
-    })
-    navBarSelect.value = activeMenu?.name as string
-    createdMenuList()
+    if (!indexRoutesChild) {
+      ElMessage.error('路由错误')
+      return
+    }
+    const topRoute = findTopRouteName(indexRoutesChild, newFullPath)
+    navBarSelect.value = topRoute?.name?.toString() || ''
+    createdMenuList(topRoute)
   },
   {
     immediate: true