diff --git a/src/assets/icons/svg/enter.svg b/src/assets/icons/svg/enter.svg
new file mode 100644
index 0000000..f7cabf2
--- /dev/null
+++ b/src/assets/icons/svg/enter.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/HeaderSearch/index.vue b/src/components/HeaderSearch/index.vue
index b57fe69..d325951 100644
--- a/src/components/HeaderSearch/index.vue
+++ b/src/components/HeaderSearch/index.vue
@@ -16,12 +16,15 @@
prefix-icon="Search"
placeholder="菜单搜索,支持标题、URL模糊查询"
clearable
+ @keyup.enter="selectActiveResult"
+ @keydown.up.prevent="navigateResult('up')"
+ @keydown.down.prevent="navigateResult('down')"
>
-
+
@@ -33,6 +36,7 @@
{{ item.path }}
+
@@ -44,15 +48,18 @@
import Fuse from 'fuse.js'
import { getNormalPath } from '@/utils/ruoyi'
import { isHttp } from '@/utils/validate'
+import useSettingsStore from '@/store/modules/settings'
import usePermissionStore from '@/store/modules/permission'
const search = ref('')
const options = ref([])
const searchPool = ref([])
+const activeIndex = ref(-1)
const show = ref(false)
const fuse = ref(undefined)
const headerSearchSelectRef = ref(null)
const router = useRouter()
+const theme = computed(() => useSettingsStore().theme)
const routes = computed(() => usePermissionStore().defaultRoutes)
function click() {
@@ -68,6 +75,7 @@ function close() {
search.value = ''
options.value = []
show.value = false
+ activeIndex.value = -1
}
function change(val) {
@@ -149,6 +157,7 @@ function generateRoutes(routes, basePath = '', prefixTitle = []) {
}
function querySearch(query) {
+ activeIndex.value = -1
if (query !== '') {
options.value = fuse.value.search(query).map((item) => item.item) ?? searchPool.value
} else {
@@ -156,6 +165,28 @@ function querySearch(query) {
}
}
+function activeStyle(index) {
+ if (index !== activeIndex.value) return {}
+ return {
+ "background-color": theme.value,
+ "color": "#fff"
+ }
+}
+
+function navigateResult(direction) {
+ if (direction === "up") {
+ activeIndex.value = activeIndex.value <= 0 ? options.value.length - 1 : activeIndex.value - 1
+ } else if (direction === "down") {
+ activeIndex.value = activeIndex.value >= options.value.length - 1 ? 0 : activeIndex.value + 1
+ }
+}
+
+function selectActiveResult() {
+ if (options.value.length > 0 && activeIndex.value >= 0) {
+ change(options.value[activeIndex.value])
+ }
+}
+
onMounted(() => {
searchPool.value = generateRoutes(routes.value)
})
@@ -174,13 +205,15 @@ watch(searchPool, (list) => {
}
}
-.result-wrap {
+.result-wrap {
height: 280px;
- margin: 10px 0;
+ margin: 6px 0;
.search-item {
display: flex;
height: 48px;
+ align-items: center;
+ padding-right: 10px;
.left {
width: 60px;
@@ -189,16 +222,17 @@ watch(searchPool, (list) => {
.menu-icon {
width: 18px;
height: 18px;
- margin-top: 5px;
}
}
.search-info {
padding-left: 5px;
+ margin-top: 10px;
width: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
+ flex: 1;
.menu-title,
.menu-path {