Files
jinshen-website/app/pages/search.vue
R2m1liA 660892f9e7
All checks were successful
deploy to server / build-and-deploy (push) Successful in 3m11s
fix: 将原项目的console输出改为logger输出
- 添加eslint,不允许使用console输出
2025-11-08 14:40:41 +08:00

132 lines
2.9 KiB
Vue

<template>
<div class="search-page">
<search-header v-model="keyword" />
<div v-if="loading" class="search-state">
<el-skeleton :rows="4" animated />
</div>
<search-tabs v-else-if="hasResults" :search-items="searchItems" />
<div v-else class="search-state">
<el-empty
:description="
route.query.query
? $t('search.no-results', { query: route.query?.query })
: $t('search.no-query')
"
/>
</div>
</div>
</template>
<script setup lang="ts">
// i18n相关
const { t } = useI18n();
const { getDirectusLocale } = useLocalizations();
const directusLocale = getDirectusLocale();
// 路由相关
const route = useRoute();
// 搜索相关
const { search } = useMeilisearch();
const keyword = ref('');
const {
data: sections,
pending: loading,
error,
refresh,
} = await useAsyncData(
() => `search-${directusLocale}-${route.query.query ?? ''}`,
async () => {
const q = String(route.query.query ?? '').trim();
if (!q) return [];
return await search(q, { limit: 12 }, directusLocale);
}
);
// 空Section过滤
const filteredSections = computed(() =>
sections.value.filter((section) => section.hits.length > 0)
);
const typeMap = {
products: 'products',
solutions: 'solutions',
questions: 'questions',
product_documents: 'product_documents',
} as const;
// 展平hits
const hits = computed(() =>
filteredSections.value.flatMap((section) => {
const type = typeMap[section.rawIndex as keyof typeof typeMap];
if (!type) return [];
return section.hits.map((hit) => ({ type, content: hit }));
})
);
const searchItems = computed(() =>
hits.value.map((hit) => {
return toSearchItemView(hit.content, hit.type);
})
);
const hasResults = computed(() =>
filteredSections.value.some((section) => section.hits.length > 0)
);
watch(
() => route.query.query,
async (newQuery) => {
if (typeof newQuery === 'string' && newQuery.trim()) {
keyword.value = newQuery;
await refresh();
}
}
);
watch(error, (value) => {
if (value) {
logger.error('数据获取失败: ', value);
}
});
onMounted(() => {
if (typeof route.query.query === 'string' && route.query.query.trim())
keyword.value = route.query.query;
});
useHead(() => ({
title: t('search.head-title'),
}));
</script>
<style scoped>
.search-page {
margin: 0 auto;
max-width: 960px;
padding: 2.5rem 1.5rem 3rem;
min-height: 70vh;
}
.search-state {
display: flex;
justify-content: center;
padding: 3rem 0;
}
@media (max-width: 640px) {
.search-page {
padding: 2rem 1rem;
}
.search-bar {
flex-direction: column;
align-items: stretch;
}
.search-input {
width: 100%;
}
}
</style>