2024-03-24 04:31:33 +08:00

152 lines
4.2 KiB
Vue

<template>
<div class="tree-view-search-wrapper">
<div>
<el-input
:placeholder="t('search-signal')"
size="large"
v-model="searchManage.content"
input-style="font-size: 16px;"
@input="safeSearch"
@focus="searchManage.displayResult = true"
@blur="searchManage.displayResult = false"
/>
</div>
<div class="search-result-wrapper" v-if="searchManage.displayResult">
<div class="search-result">
<div v-if="searchManage.searchResult.length > 0">
<div v-for="(searchResult, index) in searchManage.searchResult"
:key="index"
:class="globalLookup.currentWires.has(searchResult.module) ? 'vcd-treeview-selected' : ''"
@click="toggleRender(searchResult.module)">
<div v-html="searchResult.htmlString" class="search-result-item"></div>
</div>
</div>
<div v-else>
{{ t('search-nothing') }}
</div>
</div>
</div>
</div>
</template>
<script>
import { reactive } from 'vue';
import { useI18n } from 'vue-i18n';
import { globalSetting, globalLookup, emitter } from '@/hook/global';
import { debounceWrapper, makeSearchResultItem } from '@/hook/utils';
import { toggleRender } from '@/hook/render';
export default {
name: 'tree-view-search',
setup() {
const { t } = useI18n();
const searchManage = reactive({
content: '',
displayResult: false,
searchResult: []
});
function search() {
const searchString = searchManage.content.trim();
if (searchString.length === 0) {
searchManage.displayResult = false;
return;
}
searchManage.displayResult = true;
searchManage.searchResult = [];
const stacks = [ { name: '', body: globalLookup.topModules } ];
const searchRule = new Set(globalSetting.searchScope);
const caseSensitivity = globalSetting.caseSensitivity;
const displayParentOnly = globalSetting.displayParentOnly;
while (stacks.length > 0) {
const p = stacks.pop();
if (p.body && p.body.length) {
p.body.forEach(mod => stacks.push(mod));
}
const searchResultItem = makeSearchResultItem(searchString, p, searchRule, caseSensitivity, displayParentOnly);
if (searchResultItem) {
emitter.emit('signal-search', searchResultItem);
}
}
}
emitter.on('signal-search', searchResultItem => {
searchManage.searchResult.push(searchResultItem);
});
const safeSearch = debounceWrapper(search, 500);
return {
searchManage,
safeSearch,
globalLookup,
debounceWrapper,
t,
toggleRender
}
}
}
</script>
<style>
.tree-view-search-wrapper {
min-height: 30px;
padding: 10px;
transition: flex .5s ease-in-out;
}
.search-result-wrapper {
position: absolute;
padding: 10px;
margin: 10px;
background-color: var(--sidebar);
border: 1.5px solid var(--main-color);
color: var(--sidebar-item-text);
border-radius: .5em;
min-width: 500px;
z-index: 10;
}
.search-result {
overflow-x: scroll;
overflow-y: scroll;
max-height: 80vh;
max-width: 600px;
padding-right: 5px;
}
.search-result-item {
display: flex;
align-items: center;
height: 25px;
margin: 3px;
width: 800px;
padding-left: 3px;
cursor: pointer;
}
.search-result-item:hover {
background-color: var(--sidebar-item-selected);
border-radius: .3em;
}
.dep-arrow {
height: 7px;
width: 7px;
border-top: solid 1.7px var(--sidebar-item-text);
border-left: solid 1.7px var(--sidebar-item-text);
transform: rotate(135deg);
margin-right: 8px;
margin-left: 3px;
}
</style>