Skip to content

Commit

Permalink
feat(frontend): 全站搜索优化 TencentBlueKing#7951
Browse files Browse the repository at this point in the history
  • Loading branch information
3octaves authored and hLinx committed Nov 20, 2024
1 parent 245b806 commit 53e5df3
Show file tree
Hide file tree
Showing 15 changed files with 435 additions and 176 deletions.
93 changes: 73 additions & 20 deletions dbm-ui/frontend/src/components/system-search/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,18 @@
v-model="serach"
class="search-input"
clearable
:placeholder="t('全站搜索 Ctrl + K')"
:placeholder="t('全站搜索,支持多对象,Enter开启搜索')"
:type="isFocused ? 'text' : 'search'"
@enter="handleEnter"
@focus="handleFocus"
@paste="handlePaste">
<template #prefix>
<FilterTypeSelect
v-model="filterType"
icon-type="down-big"
title-color="#fff"
trigger-class-name="system-search-top-filter-type-select" />
</template>
<template
v-if="isFocused"
#suffix>
Expand All @@ -52,7 +59,8 @@
<SearchResult
v-if="isPopMenuShow"
ref="searchResultRef"
v-model="serach">
v-model="serach"
:filter-type="filterType">
<SearchHistory
v-if="!serach"
v-model="serach" />
Expand All @@ -61,11 +69,14 @@
</template>
<script setup lang="ts">
import tippy, { type Instance, type SingleTarget } from 'tippy.js';
import { computed, onBeforeUnmount, ref } from 'vue';
import { computed, onBeforeUnmount, ref, type UnwrapRef } from 'vue';
import { useI18n } from 'vue-i18n';

import { quickSearch } from '@services/source/quickSearch';

import { batchSplitRegex } from '@common/regex';

import FilterTypeSelect, { FilterType } from './components/FilterTypeSelect.vue';
import SearchResult from './components/search-result/Index.vue';
import SearchHistory from './components/SearchHistory.vue';
import useKeyboard from './hooks/useKeyboard';
Expand All @@ -74,22 +85,23 @@
const route = useRoute();
const router = useRouter();

let tippyIns: Instance | undefined;

const serach = ref('');
const rootRef = ref<HTMLElement>();
const popRef = ref();
const searchResultRef = ref();
const searchResultRef = ref<InstanceType<typeof SearchResult>>();
const isFocused = ref(false);
const popContentStyle = ref({});
const isPopMenuShow = ref(false);
const filterType = ref(FilterType.EXACT);

const styles = computed(() => ({
flex: isFocused.value ? '1' : '0 0 auto',
}));

const { activeIndex } = useKeyboard(rootRef, popRef);

let tippyIns: Instance | undefined;

const handlePaste = () => {
setTimeout(() => {
serach.value = serach.value.replace(batchSplitRegex, '|');
Expand Down Expand Up @@ -137,28 +149,39 @@
};

const handleSearch = () => {
// 页面跳转参数处理
const options = searchResultRef.value.getFilterOptions();
const query = Object.keys(options).reduce((prevQuery, optionKey) => {
const optionItem = options[optionKey];
const getQuery = (options: UnwrapRef<typeof formData> & { short_code?: string }) =>
Object.keys(options).reduce((prevQuery, optionKey) => {
const optionItem = options[optionKey as keyof typeof options];

if (optionItem !== '' && !(Array.isArray(optionItem) && optionItem.length === 0)) {
if (Array.isArray(optionItem)) {
if (optionItem !== '' && !(Array.isArray(optionItem) && optionItem.length === 0)) {
return {
...prevQuery,
[optionKey]: optionItem.join(','),
[optionKey]: Array.isArray(optionItem) ? optionItem.join(',') : optionItem,
};
}

return {
...prevQuery,
[optionKey]: optionItem,
};
}
return prevQuery;
}, {});

return prevQuery;
}, {});
// 页面跳转参数处理
const { formData, keyword } = searchResultRef.value!.getFilterOptions();
if (keyword) {
quickSearch({
...formData,
keyword,
}).then((quickSearchResult) => {
const options = {
...formData,
short_code: quickSearchResult.short_code,
};
handleRedirect(getQuery(options));
});
} else {
handleRedirect(getQuery(formData));
}
};

const handleRedirect = (query = {}) => {
const url = router.resolve({
name: 'QuickSearch',
query: {
Expand Down Expand Up @@ -224,6 +247,36 @@
width: auto !important;
}

.system-search-top-filter-type-select {
display: flex;
width: 80px;
height: 30px;
color: #fff;
cursor: pointer;
background: #3b4b68;
align-items: center;
justify-content: space-around;

.label-content {
position: relative;

.more-icon {
display: inline-block;
font-size: 14px;
transform: rotate(0deg);
transition: all 0.5s;
}

.more-icon-active {
transform: rotate(-180deg);
}

.icon-disabled {
color: #c4c6cc;
}
}
}

.search-input {
overflow: hidden;
border: 1px solid transparent;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<template>
<BkSelect
v-model="modelValue"
:filterable="false"
@change="handleChooseType"
@toggle="handleTogglePopover">
<template #trigger>
<div :class="triggerClassName">
<span class="label-content">
<BkButton
class="mr-4"
:style="{ color: titleColor }"
text>
{{ currentTitle }}
</BkButton>
<DbIcon
class="more-icon"
:class="{
'more-icon-active': isRotate,
}"
:type="iconType" />
</span>
</div>
</template>
<BkOption
v-for="item in dropdownList"
:id="item.value"
:key="item.value"
:name="item.label" />
</BkSelect>
</template>

<script lang="ts">
export enum FilterType {
EXACT = 'EXACT',
CONTAINS = 'CONTAINS',
}
</script>
<script setup lang="ts">
import { useI18n } from 'vue-i18n';

interface Props {
titleColor: string;
iconType: string;
triggerClassName: string;
}

defineProps<Props>();

const modelValue = defineModel<string>({
required: true,
});

const { t } = useI18n();

const dropdownList = [
{
label: t('精确搜索'),
value: FilterType.EXACT,
},
{
label: t('模糊搜索'),
value: FilterType.CONTAINS,
},
];

const isRotate = ref(false);

const currentTitle = computed(() =>
modelValue.value === FilterType.EXACT ? dropdownList[0].label : dropdownList[1].label,
);

const handleChooseType = (type: string) => {
modelValue.value = type;
};

const handleTogglePopover = (isShow: boolean) => {
isRotate.value = isShow;
};
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
</BkCheckboxGroup>
</div>
</div>
<div class="filter-item">
<!-- <div class="filter-item">
<div class="filter-title">
{{ t('检索类型') }}
</div>
Expand All @@ -97,7 +97,7 @@
{{ t('精确') }}
</BkRadio>
</BkRadioGroup>
</div>
</div> -->
</div>
</template>
<script setup lang="ts">
Expand Down
Loading

0 comments on commit 53e5df3

Please sign in to comment.