mirror of https://github.com/halo-dev/halo
refactor: improve visible condition of global search component (#5976)
#### What type of PR is this? /area ui /kind improvement /milestone 2.16.x #### What this PR does / why we need it: 优化 Console 的全局搜索对话框显示逻辑,改为未开启时不渲染组件。 #### Does this PR introduce a user-facing change? ```release-note None ```pull/5977/head
parent
4d289c0a45
commit
34981f95ba
|
@ -295,7 +295,10 @@ onMounted(() => {
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<GlobalSearchModal v-model:visible="globalSearchVisible" />
|
<GlobalSearchModal
|
||||||
|
v-if="globalSearchVisible"
|
||||||
|
@close="globalSearchVisible = false"
|
||||||
|
/>
|
||||||
<LoginModal />
|
<LoginModal />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,25 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useRoute, useRouter, type RouteLocationRaw } from "vue-router";
|
import { type RouteLocationRaw, useRoute, useRouter } from "vue-router";
|
||||||
import {
|
import {
|
||||||
VModal,
|
|
||||||
VEntity,
|
|
||||||
VEntityField,
|
|
||||||
IconLink,
|
|
||||||
IconBookRead,
|
IconBookRead,
|
||||||
IconFolder,
|
IconFolder,
|
||||||
IconSettings,
|
IconLink,
|
||||||
IconPalette,
|
|
||||||
IconPages,
|
IconPages,
|
||||||
|
IconPalette,
|
||||||
|
IconSettings,
|
||||||
IconUserSettings,
|
IconUserSettings,
|
||||||
|
VEntity,
|
||||||
|
VEntityField,
|
||||||
|
VModal,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
import { computed, markRaw, ref, watch, type Component } from "vue";
|
import { type Component, computed, markRaw, onMounted, ref, watch } from "vue";
|
||||||
import Fuse from "fuse.js";
|
import Fuse from "fuse.js";
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
import { usePermission } from "@/utils/permission";
|
import { usePermission } from "@/utils/permission";
|
||||||
import { useThemeStore } from "@console/stores/theme";
|
import { useThemeStore } from "@console/stores/theme";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useEventListener } from "@vueuse/core";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -27,19 +28,11 @@ const { t } = useI18n();
|
||||||
const { currentUserHasPermission } = usePermission();
|
const { currentUserHasPermission } = usePermission();
|
||||||
const { activatedTheme } = storeToRefs(useThemeStore());
|
const { activatedTheme } = storeToRefs(useThemeStore());
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
visible: boolean;
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
visible: false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "update:visible", visible: boolean): void;
|
(e: "close"): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const modal = ref<InstanceType<typeof VModal>>();
|
||||||
const globalSearchInput = ref<HTMLInputElement | null>(null);
|
const globalSearchInput = ref<HTMLInputElement | null>(null);
|
||||||
const keyword = ref("");
|
const keyword = ref("");
|
||||||
|
|
||||||
|
@ -288,10 +281,6 @@ const handleBuildSearchIndex = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleKeydown = (e: KeyboardEvent) => {
|
const handleKeydown = (e: KeyboardEvent) => {
|
||||||
if (!props.visible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { key, ctrlKey } = e;
|
const { key, ctrlKey } = e;
|
||||||
|
|
||||||
if (key === "ArrowUp" || (key === "k" && ctrlKey)) {
|
if (key === "ArrowUp" || (key === "k" && ctrlKey)) {
|
||||||
|
@ -313,7 +302,7 @@ const handleKeydown = (e: KeyboardEvent) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === "Escape") {
|
if (key === "Escape") {
|
||||||
onVisibleChange(false);
|
modal.value?.close();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -328,7 +317,7 @@ const handleRoute = async (item: SearchableItem) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
router.push(item.route);
|
router.push(item.route);
|
||||||
emit("update:visible", false);
|
modal.value?.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
@ -349,39 +338,26 @@ watch(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
onMounted(() => {
|
||||||
() => props.visible,
|
handleBuildSearchIndex();
|
||||||
(visible) => {
|
|
||||||
if (visible) {
|
|
||||||
handleBuildSearchIndex();
|
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
globalSearchInput.value?.focus();
|
globalSearchInput.value?.focus();
|
||||||
}, 100);
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
document.addEventListener("keydown", handleKeydown);
|
useEventListener("keydown", handleKeydown);
|
||||||
} else {
|
|
||||||
document.removeEventListener("keydown", handleKeydown);
|
|
||||||
keyword.value = "";
|
|
||||||
selectedIndex.value = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const onVisibleChange = (visible: boolean) => {
|
|
||||||
emit("update:visible", visible);
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VModal
|
<VModal
|
||||||
:visible="visible"
|
ref="modal"
|
||||||
:body-class="['!p-0']"
|
:body-class="['!p-0']"
|
||||||
:mount-to-body="true"
|
:mount-to-body="true"
|
||||||
:width="650"
|
:width="650"
|
||||||
:centered="false"
|
:centered="false"
|
||||||
:layer-closable="true"
|
:layer-closable="true"
|
||||||
@update:visible="onVisibleChange"
|
@close="emit('close')"
|
||||||
>
|
>
|
||||||
<div id="search-input" class="border-b border-gray-100 px-4 py-2.5">
|
<div id="search-input" class="border-b border-gray-100 px-4 py-2.5">
|
||||||
<input
|
<input
|
||||||
|
|
Loading…
Reference in New Issue