feat: 优化搜索功能,改进搜索历史管理和路由处理逻辑

This commit is contained in:
alger
2025-03-30 00:18:44 +08:00
parent 280fec1990
commit 477f8bb99b
2 changed files with 66 additions and 25 deletions
+24 -2
View File
@@ -105,7 +105,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, ref, watchEffect } from 'vue'; import { computed, onMounted, ref, watch, watchEffect } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
@@ -191,6 +191,18 @@ const isDark = computed({
// 搜索词 // 搜索词
const searchValue = ref(''); const searchValue = ref('');
// 使用 watch 代替 watchEffect 监听搜索值变化,确保深度监听
watch(
() => searchStore.searchValue,
(newValue) => {
if (newValue) {
searchValue.value = newValue;
}
},
{ immediate: true }
);
const search = () => { const search = () => {
const { value } = searchValue; const { value } = searchValue;
if (value === '') { if (value === '') {
@@ -215,7 +227,17 @@ const search = () => {
const selectSearchType = (key: number) => { const selectSearchType = (key: number) => {
searchStore.searchType = key; searchStore.searchType = key;
if (searchValue.value) { if (searchValue.value) {
search(); if (router.currentRoute.value.path === '/search') {
search();
} else {
router.push({
path: '/search',
query: {
keyword: searchValue.value,
type: key
}
});
}
} }
}; };
+42 -23
View File
@@ -111,7 +111,7 @@
@click="handleSearchHistory(item)" @click="handleSearchHistory(item)"
@close="handleCloseSearchHistory(item)" @close="handleCloseSearchHistory(item)"
> >
{{ item }} {{ item.keyword }}
</n-tag> </n-tag>
</div> </div>
</div> </div>
@@ -155,7 +155,7 @@ const searchStore = useSearchStore();
const searchDetail = ref<any>(); const searchDetail = ref<any>();
const searchType = computed(() => searchStore.searchType as number); const searchType = computed(() => searchStore.searchType as number);
const searchDetailLoading = ref(false); const searchDetailLoading = ref(false);
const searchHistory = ref<string[]>([]); const searchHistory = ref<Array<{ keyword: string; type: number }>>([]);
// 添加分页相关的状态 // 添加分页相关的状态
const ITEMS_PER_PAGE = 30; // 每页数量 const ITEMS_PER_PAGE = 30; // 每页数量
@@ -170,17 +170,17 @@ const loadSearchHistory = () => {
searchHistory.value = history ? JSON.parse(history) : []; searchHistory.value = history ? JSON.parse(history) : [];
}; };
// 保存搜索历史 // 保存搜索历史,改为保存关键词和类型
const saveSearchHistory = (keyword: string) => { const saveSearchHistory = (keyword: string, type: number) => {
if (!keyword) return; if (!keyword) return;
const history = searchHistory.value; const history = searchHistory.value;
// 移除重复的关键词 // 移除重复的关键词
const index = history.indexOf(keyword); const index = history.findIndex((item) => item.keyword === keyword);
if (index > -1) { if (index > -1) {
history.splice(index, 1); history.splice(index, 1);
} }
// 添加到开头 // 添加到开头
history.unshift(keyword); history.unshift({ keyword, type });
// 只保留最近的20条记录 // 只保留最近的20条记录
if (history.length > 20) { if (history.length > 20) {
history.pop(); history.pop();
@@ -196,8 +196,8 @@ const clearSearchHistory = () => {
}; };
// 删除搜索历史 // 删除搜索历史
const handleCloseSearchHistory = (keyword: string) => { const handleCloseSearchHistory = (item: { keyword: string; type: number }) => {
searchHistory.value = searchHistory.value.filter((item) => item !== keyword); searchHistory.value = searchHistory.value.filter((h) => h.keyword !== item.keyword);
localStorage.setItem('searchHistory', JSON.stringify(searchHistory.value)); localStorage.setItem('searchHistory', JSON.stringify(searchHistory.value));
}; };
@@ -211,7 +211,7 @@ const loadHotSearch = async () => {
onMounted(() => { onMounted(() => {
loadHotSearch(); loadHotSearch();
loadSearchHistory(); loadSearchHistory();
loadSearch(route.query.keyword); // 注意:路由参数的处理已经在 watch route.query 中处理了
}); });
const hotKeyword = ref(route.query.keyword || t('search.title.searchList')); const hotKeyword = ref(route.query.keyword || t('search.title.searchList'));
@@ -223,21 +223,26 @@ const currentBvid = ref('');
const loadSearch = async (keywords: any, type: any = null, isLoadMore = false) => { const loadSearch = async (keywords: any, type: any = null, isLoadMore = false) => {
if (!keywords) return; if (!keywords) return;
// 使用传入的类型或当前类型
const searchTypeToUse = type !== null ? type : searchType.value;
if (!isLoadMore) { if (!isLoadMore) {
hotKeyword.value = keywords; hotKeyword.value = keywords;
searchDetail.value = undefined; searchDetail.value = undefined;
page.value = 0; page.value = 0;
hasMore.value = true; hasMore.value = true;
currentKeyword.value = keywords; currentKeyword.value = keywords;
// 保存搜索历史
saveSearchHistory(keywords, searchTypeToUse);
// 始终更新搜索框内容和类型
searchStore.searchType = searchTypeToUse;
searchStore.searchValue = keywords;
} else if (isLoadingMore.value || !hasMore.value) { } else if (isLoadingMore.value || !hasMore.value) {
return; return;
} }
// 保存搜索历史
if (!isLoadMore) {
saveSearchHistory(keywords);
}
if (isLoadMore) { if (isLoadMore) {
isLoadingMore.value = true; isLoadingMore.value = true;
} else { } else {
@@ -246,7 +251,7 @@ const loadSearch = async (keywords: any, type: any = null, isLoadMore = false) =
try { try {
// B站搜索 // B站搜索
if ((type || searchType.value) === SEARCH_TYPE.BILIBILI) { if (searchTypeToUse === SEARCH_TYPE.BILIBILI) {
const response = await searchBilibili({ const response = await searchBilibili({
keyword: currentKeyword.value, keyword: currentKeyword.value,
page: page.value + 1, page: page.value + 1,
@@ -283,7 +288,7 @@ const loadSearch = async (keywords: any, type: any = null, isLoadMore = false) =
else { else {
const { data } = await getSearch({ const { data } = await getSearch({
keywords: currentKeyword.value, keywords: currentKeyword.value,
type: type || searchType.value, type: searchTypeToUse,
limit: ITEMS_PER_PAGE, limit: ITEMS_PER_PAGE,
offset: page.value * ITEMS_PER_PAGE offset: page.value * ITEMS_PER_PAGE
}); });
@@ -382,12 +387,21 @@ const handleScroll = (e: any) => {
}; };
watch( watch(
() => route.path, () => route.query,
async (path) => { (query) => {
if (path === '/search') { if (route.path === '/search' && query.keyword) {
searchStore.searchValue = route.query.keyword as string; const routeKeyword = query.keyword as string;
const routeType = query.type ? Number(query.type) : searchType.value;
// 更新搜索类型和值
searchStore.searchType = routeType;
searchStore.searchValue = routeKeyword;
// 加载搜索结果
loadSearch(routeKeyword, routeType);
} }
} },
{ immediate: true }
); );
const handlePlay = () => { const handlePlay = () => {
@@ -396,8 +410,13 @@ const handlePlay = () => {
}; };
// 点击搜索历史 // 点击搜索历史
const handleSearchHistory = (keyword: string) => { const handleSearchHistory = (item: { keyword: string; type: number }) => {
loadSearch(keyword, 1); // 更新搜索类型
searchStore.searchType = item.type;
// 先更新搜索值到 store
searchStore.searchValue = item.keyword;
// 使用关键词和类型加载搜索
loadSearch(item.keyword, item.type);
}; };
// 处理B站视频播放 // 处理B站视频播放