diff --git a/.vscode/settings.json b/.vscode/settings.json
index 3036ebf1..5b3aa477 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -8,7 +8,7 @@
     "source.fixAll.eslint": true
   },
   "[vue]": {
-    "editor.defaultFormatter": "esbenp.prettier-vscode"
+    "editor.defaultFormatter": "Vue.volar"
   },
   "[javascript]": {
     "editor.defaultFormatter": "esbenp.prettier-vscode"
diff --git a/src/App.vue b/src/App.vue
index 75edd24f..f75478cd 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -3,6 +3,7 @@ import { isDark } from '@/utils/is'
 import { useAppStore } from '@/store/modules/app'
 import { useDesign } from '@/hooks/web/useDesign'
 import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+import routerSearch from '@/components/RouterSearch/index.vue'
 
 const { getPrefixCls } = useDesign()
 const prefixCls = getPrefixCls('app')
@@ -24,10 +25,12 @@ setDefaultTheme()
 <template>
   <ConfigGlobal :size="currentSize">
     <RouterView :class="greyMode ? `${prefixCls}-grey-mode` : ''" />
+    <routerSearch />
   </ConfigGlobal>
 </template>
 <style lang="scss">
 $prefix-cls: #{$namespace}-app;
+
 .size {
   width: 100%;
   height: 100%;
diff --git a/src/components/RouterSearch/index.vue b/src/components/RouterSearch/index.vue
new file mode 100644
index 00000000..d44ce267
--- /dev/null
+++ b/src/components/RouterSearch/index.vue
@@ -0,0 +1,76 @@
+<template>
+  <ElDialog v-model="showSearch" :show-close="false" title="菜单搜索">
+    <el-select
+      filterable
+      :reserve-keyword="false"
+      remote
+      placeholder="请输入菜单内容"
+      :remote-method="remoteMethod"
+      style="width: 100%"
+      @change="handleChange"
+    >
+      <el-option
+        v-for="item in options"
+        :key="item.value"
+        :label="item.label"
+        :value="item.value"
+      />
+    </el-select>
+  </ElDialog>
+</template>
+
+<script setup lang="ts">
+const router = useRouter() // 路由对象
+const showSearch = ref(false) // 是否显示弹框
+const value: Ref = ref('') // 用户输入的值
+
+const routers = router.getRoutes() // 路由对象
+const options = computed(() => {
+  // 提示选项
+  if (!value.value) {
+    return []
+  }
+  const list = routers.filter((item: any) => {
+    if (item.meta.title?.indexOf(value.value) > -1 || item.path.indexOf(value.value) > -1) {
+      return true
+    }
+  })
+  return list.map((item) => {
+    return {
+      label: `${item.meta.title}${item.path}`,
+      value: item.path
+    }
+  })
+})
+
+function remoteMethod(data) {
+  // 这里可以执行相应的操作(例如打开搜索框等)
+  value.value = data
+}
+
+function handleChange(path) {
+  router.push({ path })
+}
+
+onMounted(() => {
+  window.addEventListener('keydown', listenKey)
+})
+
+onUnmounted(() => {
+  window.removeEventListener('keydown', listenKey)
+})
+
+// 监听 ctrl + k
+function listenKey(event) {
+  if ((event.ctrlKey || event.metaKey) && event.key === 'k') {
+    showSearch.value = !showSearch.value
+    // 这里可以执行相应的操作(例如打开搜索框等)
+  }
+}
+
+defineExpose({
+  openSearch: () => {
+    showSearch.value = true
+  }
+})
+</script>