Files
jinshen-website/app/pages/search.vue
R2m1liA 17bb8adee3
All checks were successful
deploy to server / build-and-deploy (push) Successful in 3m7s
fix: 修复Server搜索问题
- 将meilisearch搜索服务移至Server端
2025-11-14 14:57:55 +08:00

117 lines
2.4 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 locale = getDirectusLocale();
// 路由相关
const route = useRoute();
// 搜索相关
const keyword = ref('');
if (typeof route.query.query === 'string' && route.query.query.trim()) {
keyword.value = route.query.query;
}
const {
data: searchItems,
pending: loading,
error,
refresh,
} = useAsyncData(`meilisearch-${keyword.value}-${locale}`, async () => {
try {
const data = await $fetch(`/api/search?query=${keyword.value}`, {
headers: { 'x-locale': locale },
});
return data;
} catch (error) {
logger.error('Error fetching search results: ', error);
throw error;
}
});
const hasResults = computed(() => searchItems.value.length > 0);
watch(
() => route.query.query,
async (newQuery) => {
if (typeof newQuery === 'string' && newQuery.trim()) {
keyword.value = newQuery;
await refresh();
}
}
);
watch(
() => locale,
async () => {
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>