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" >
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" >
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
185210import { defineComponent , ref , computed , onMounted , watch } from ' vue' ;
186211import { useRoute , useRouter } from ' vue-router' ;
187212import { 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' ;
188223import SearchSettingsModal from ' @/components/SearchSettingsModal.vue' ;
189224import siteService from ' @/api/services/site' ;
190225import videoService from ' @/api/services/video' ;
191226
192227export 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 : 8 px ;
765+ flex-wrap : wrap ;
766+ gap : 12 px ;
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