Skip to content

Commit 9e5aa75

Browse files
author
Taois
committed
feat:优化搜索前界面的布局和执行事件
1 parent 2bd389a commit 9e5aa75

File tree

2 files changed

+197
-52
lines changed

2 files changed

+197
-52
lines changed

dashboard/src/components/Header.vue

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,12 @@
3838
v-model="searchValue"
3939
placeholder="搜索内容..."
4040
enter-button="搜索"
41+
allow-clear
4142
@search="onSearch"
43+
@keyup.enter="onSearch(searchValue)"
4244
@click="handleSearchClick"
4345
@input="handleSearchInput"
46+
@clear="handleSearchClear"
4447
/>
4548
<a-button
4649
class="search-settings-btn"
@@ -183,7 +186,13 @@ export default defineComponent({
183186
},
184187
goBackFromSearch() {
185188
// 从聚合搜索页面返回到上一页
186-
this.$router.go(-1);
189+
// 检查是否有历史记录可以返回
190+
if (window.history.length > 1) {
191+
this.$router.back();
192+
} else {
193+
// 如果没有历史记录,返回到首页
194+
this.$router.push({ name: 'Home' });
195+
}
187196
},
188197
goForward() {
189198
Message.info("后退按钮");
@@ -222,8 +231,19 @@ export default defineComponent({
222231
}
223232
},
224233
handleSearchInput(value) {
225-
// 搜索输入时的处理(可以用于实时搜索建议等)
226-
// 暂时不做特殊处理
234+
// 搜索输入时的处理:在聚合搜索页写入草稿以生成建议
235+
if (this.isSearchAggregationPage) {
236+
const query = { ...this.$route.query, keywordDraft: value };
237+
this.$router.push({ name: 'SearchAggregation', query });
238+
}
239+
},
240+
handleSearchClear() {
241+
// 清除输入内容,同时清空聚搜页的草稿
242+
if (this.isSearchAggregationPage) {
243+
const query = { ...this.$route.query };
244+
delete query.keywordDraft;
245+
this.$router.push({ name: 'SearchAggregation', query });
246+
}
227247
},
228248
openSearchSettings() {
229249
// 打开搜索设置弹窗

dashboard/src/views/SearchAggregation.vue

Lines changed: 174 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,54 @@
44

55
<!-- 主要内容区域 -->
66
<div class="search-content">
7-
<!-- 搜索前的状态:热门搜索 -->
8-
<div v-if="!hasSearched && !searchKeyword" class="search-home">
7+
<!-- 最近搜索记录(仅在搜索前显示,有记录时) -->
8+
<div v-if="!hasSearched && recentSearches.length > 0" class="recent-search-floating">
9+
<div class="recent-search-section">
10+
<div class="section-header">
11+
<h3 class="section-title">
12+
<icon-history class="title-icon"/>
13+
最近搜索记录
14+
</h3>
15+
<a-button type="text" size="small" class="refresh-btn" @click="clearRecentSearches">清空</a-button>
16+
</div>
17+
<div class="recent-search-tags">
18+
<a-tag
19+
v-for="tag in recentSearches"
20+
:key="tag"
21+
class="recent-tag"
22+
@click="performSearch(tag)"
23+
>
24+
{{ tag }}
25+
</a-tag>
26+
</div>
27+
</div>
28+
</div>
29+
30+
<!-- 搜索前的状态:建议+热门 -->
31+
<div v-if="!hasSearched" class="search-home">
32+
<!-- 猜你想搜(有输入草稿时显示) -->
33+
<div v-if="suggestions.length > 0" class="search-suggestions">
34+
<div class="section-header">
35+
<h3 class="section-title">
36+
<icon-bulb class="title-icon"/>
37+
猜你想搜
38+
</h3>
39+
</div>
40+
<div class="suggestions-tags">
41+
<a-tag
42+
v-for="suggestion in suggestions"
43+
:key="suggestion"
44+
class="suggestion-tag"
45+
@click="searchSuggestion(suggestion)"
46+
>
47+
{{ suggestion }}
48+
</a-tag>
49+
</div>
50+
</div>
51+
52+
53+
54+
<!-- 热门搜索 -->
955
<div class="hot-search-section">
1056
<div class="section-header">
1157
<h3 class="section-title">
@@ -37,27 +83,6 @@
3783
</div>
3884
</div>
3985

40-
<!-- 搜索输入时的状态:猜你喜欢 -->
41-
<div v-if="!hasSearched && searchKeyword && searchKeyword.trim()" class="search-suggestions">
42-
<div class="suggestions-section">
43-
<h3 class="section-title">
44-
<icon-heart class="title-icon"/>
45-
猜你喜欢
46-
</h3>
47-
<div class="suggestions-list">
48-
<div
49-
v-for="suggestion in suggestions"
50-
:key="suggestion"
51-
class="suggestion-item"
52-
@click="searchSuggestion(suggestion)"
53-
>
54-
<icon-search class="suggestion-icon"/>
55-
<span class="suggestion-text">{{ suggestion }}</span>
56-
</div>
57-
</div>
58-
</div>
59-
</div>
60-
6186
<!-- 搜索结果页面 -->
6287
<div v-if="hasSearched" class="search-results">
6388
<div class="results-layout">
@@ -152,7 +177,7 @@
152177

153178
<!-- 加载状态 -->
154179
<div v-else-if="activeSource && loadingStates[activeSource]" class="loading-state">
155-
<a-spin size="large"/>
180+
<a-spin :size="32"/>
156181
<p>正在搜索 {{ getSourceName(activeSource) }}...</p>
157182
</div>
158183

@@ -185,14 +210,32 @@
185210
import { defineComponent, ref, computed, onMounted, watch } from 'vue';
186211
import { useRoute, useRouter } from 'vue-router';
187212
import { Message } from '@arco-design/web-vue';
213+
import {
214+
IconHistory,
215+
IconBulb,
216+
IconFire,
217+
IconRefresh,
218+
IconCheckCircle,
219+
IconCloseCircle,
220+
IconExclamationCircle,
221+
IconEmpty
222+
} from '@arco-design/web-vue/es/icon';
188223
import SearchSettingsModal from '@/components/SearchSettingsModal.vue';
189224
import siteService from '@/api/services/site';
190225
import videoService from '@/api/services/video';
191226
192227
export default defineComponent({
193228
name: 'SearchAggregation',
194229
components: {
195-
SearchSettingsModal
230+
SearchSettingsModal,
231+
IconHistory,
232+
IconBulb,
233+
IconFire,
234+
IconRefresh,
235+
IconCheckCircle,
236+
IconCloseCircle,
237+
IconExclamationCircle,
238+
IconEmpty
196239
},
197240
setup() {
198241
const route = useRoute();
@@ -202,6 +245,7 @@ export default defineComponent({
202245
const searchKeyword = ref('');
203246
const hasSearched = ref(false);
204247
const showSearchSettings = ref(false);
248+
const recentSearches = ref([]);
205249
206250
// 搜索源和结果
207251
const searchSources = ref([]);
@@ -323,6 +367,29 @@ export default defineComponent({
323367
);
324368
325369
await Promise.allSettled(searchPromises);
370+
// 记录最近搜索
371+
try {
372+
const HISTORY_KEY = 'drplayer_search_history';
373+
const stored = localStorage.getItem(HISTORY_KEY);
374+
let history = [];
375+
try { history = stored ? JSON.parse(stored) : []; } catch { history = []; }
376+
const k = searchKeyword.value;
377+
// 过滤空字符串和无效值
378+
if (k && k.trim()) {
379+
const idx = history.findIndex(item => item === k);
380+
if (idx !== -1) history.splice(idx, 1);
381+
history.unshift(k);
382+
// 过滤历史记录中的空字符串
383+
history = history.filter(item => item && item.trim());
384+
if (history.length > 10) history = history.slice(0, 10);
385+
localStorage.setItem(HISTORY_KEY, JSON.stringify(history));
386+
// console.log('保存搜索历史记录:',history);
387+
// 直接更新最近搜索记录
388+
recentSearches.value = [...history];
389+
}
390+
} catch (e) {
391+
console.error('保存搜索历史失败:', e);
392+
}
326393
};
327394
328395
const searchSource = async (source, keyword) => {
@@ -485,18 +552,51 @@ export default defineComponent({
485552
hotSearchTags.value = shuffled.slice(0, 12); // 显示12个标签
486553
};
487554
555+
// 最近搜索读取与清空
556+
const loadRecentSearches = () => {
557+
try {
558+
const HISTORY_KEY = 'drplayer_search_history';
559+
const stored = localStorage.getItem(HISTORY_KEY);
560+
let history = stored ? JSON.parse(stored) : [];
561+
if (!Array.isArray(history)) history = [];
562+
// 过滤空字符串和无效值
563+
recentSearches.value = history.filter(item => item && item.trim());
564+
// 如果过滤后的数据与原数据不同,更新localStorage
565+
if (recentSearches.value.length !== history.length) {
566+
localStorage.setItem(HISTORY_KEY, JSON.stringify(recentSearches.value));
567+
}
568+
} catch {
569+
recentSearches.value = [];
570+
}
571+
};
572+
const clearRecentSearches = () => {
573+
localStorage.removeItem('drplayer_search_history');
574+
recentSearches.value = [];
575+
Message.success('已清空最近搜索记录');
576+
};
577+
488578
// 监听路由参数
489579
watch(() => route.query.keyword, (keyword) => {
490580
if (keyword) {
491581
searchKeyword.value = keyword;
492582
performSearch(keyword);
493583
}
494584
}, { immediate: true });
585+
// 监听输入草稿用于生成建议
586+
watch(() => route.query.keywordDraft, (draft) => {
587+
const val = typeof draft === 'string' ? draft : '';
588+
// 只有在没有进行搜索时才更新searchKeyword.value,避免在搜索过程中被重置
589+
if (!hasSearched.value) {
590+
searchKeyword.value = val;
591+
}
592+
onSearchInput(val);
593+
});
495594
496595
// 组件挂载时初始化
497596
onMounted(() => {
498597
loadSearchSources();
499598
randomizeHotSearchTags();
599+
loadRecentSearches();
500600
501601
// 显示当前配置状态
502602
const settings = getSearchSettings();
@@ -532,7 +632,10 @@ export default defineComponent({
532632
handleImageError,
533633
onPageChange,
534634
onPageSizeChange,
535-
randomizeHotSearchTags
635+
randomizeHotSearchTags,
636+
// 最近搜索
637+
recentSearches,
638+
clearRecentSearches
536639
};
537640
}
538641
});
@@ -562,7 +665,32 @@ export default defineComponent({
562665
}
563666
564667
.hot-search-section {
668+
padding: 20px;
669+
max-width: 800px;
670+
margin: 0 auto;
565671
margin-bottom: 40px;
672+
margin-top: 0;
673+
}
674+
675+
.recent-search-section {
676+
padding: 20px;
677+
max-width: 800px;
678+
margin: 0 auto 20px auto;
679+
}
680+
.recent-search-tags {
681+
display: flex;
682+
flex-wrap: wrap;
683+
gap: 12px;
684+
}
685+
.recent-tag {
686+
cursor: pointer;
687+
transition: all 0.2s ease;
688+
border-radius: 16px;
689+
padding: 6px 16px;
690+
}
691+
.recent-tag:hover {
692+
background: var(--color-fill-2);
693+
transform: translateY(-1px);
566694
}
567695
568696
.section-header {
@@ -616,43 +744,40 @@ export default defineComponent({
616744
transform: translateY(-1px);
617745
}
618746
747+
/* 最近搜索记录浮动区域 */
748+
.recent-search-floating {
749+
padding: 20px;
750+
max-width: 800px;
751+
margin: 0 auto;
752+
margin-bottom: 8px;
753+
}
754+
619755
/* 搜索建议样式 */
620756
.search-suggestions {
621757
padding: 20px;
622758
max-width: 800px;
623759
margin: 0 auto;
760+
margin-bottom: 8px;
624761
}
625762
626-
.suggestions-list {
763+
.suggestions-tags {
627764
display: flex;
628-
flex-direction: column;
629-
gap: 8px;
765+
flex-wrap: wrap;
766+
gap: 12px;
630767
}
631768
632-
.suggestion-item {
633-
display: flex;
634-
align-items: center;
635-
gap: 12px;
636-
padding: 12px 16px;
637-
border-radius: 8px;
769+
.suggestion-tag {
638770
cursor: pointer;
639771
transition: all 0.2s ease;
640-
background: var(--color-bg-2);
641-
}
642-
643-
.suggestion-item:hover {
644-
background: var(--color-fill-2);
645-
transform: translateX(4px);
646-
}
647-
648-
.suggestion-icon {
649-
color: var(--color-text-3);
650-
font-size: 14px;
772+
border-radius: 16px;
773+
padding: 6px 16px;
651774
}
652775
653-
.suggestion-text {
654-
color: var(--color-text-1);
655-
font-size: 14px;
776+
.suggestion-tag:hover {
777+
background: var(--color-primary-1);
778+
border-color: var(--color-primary-6);
779+
color: var(--color-primary-6);
780+
transform: translateY(-1px);
656781
}
657782
658783
/* 搜索结果样式 */

0 commit comments

Comments
 (0)