6666 <!-- 右侧元素 -->
6767 <div class =" header-right" >
6868 <div class =" search-container" v-if =" $route.path === '/home' && !(isSuperAdmin && isSmallScreen)" >
69- <el-input v-model =" search" :placeholder =" $t('header.searchPlaceholder')" class =" custom-search-input"
70- @keyup.enter.native =" handleSearch" >
71- <i slot =" suffix" class =" el-icon-search search-icon" @click =" handleSearch" ></i >
72- </el-input >
69+ <div class =" search-wrapper" >
70+ <el-input v-model =" search" :placeholder =" $t('header.searchPlaceholder')" class =" custom-search-input"
71+ @keyup.enter.native =" handleSearch" @focus =" showSearchHistory" @blur =" hideSearchHistory" clearable
72+ ref =" searchInput" >
73+ <i slot =" suffix" class =" el-icon-search search-icon" @click =" handleSearch" ></i >
74+ </el-input >
75+ <!-- 搜索历史下拉框 -->
76+ <div v-if =" showHistory && searchHistory.length > 0" class =" search-history-dropdown" >
77+ <div class =" search-history-header" >
78+ <span >{{ $t('header.searchHistory') }}</span >
79+ <el-button type =" text" size =" small" class =" clear-history-btn" @click =" clearSearchHistory" >
80+ {{ $t('header.clearHistory') }}
81+ </el-button >
82+ </div >
83+ <div class =" search-history-list" >
84+ <div v-for =" (item, index) in searchHistory" :key =" index" class =" search-history-item"
85+ @click.stop =" selectSearchHistory(item)" >
86+ <span class =" history-text" >{{ item }}</span >
87+ <i class =" el-icon-close clear-item-icon" @click.stop =" removeSearchHistory(index)" ></i >
88+ </div >
89+ </div >
90+ </div >
91+ </div >
7392 </div >
7493
7594 <!-- 语言切换下拉菜单 -->
99118 </span >
100119 <el-dropdown-menu slot =" dropdown" >
101120 <el-dropdown-item @click.native =" showChangePasswordDialog" >{{ $t('header.changePassword')
102- }}</el-dropdown-item >
121+ }}</el-dropdown-item >
103122 <el-dropdown-item @click.native =" handleLogout" >{{ $t('header.logout') }}</el-dropdown-item >
104123 </el-dropdown-menu >
105124 </el-dropdown >
@@ -134,7 +153,12 @@ export default {
134153 userDropdownVisible: false ,
135154 paramDropdownVisible: false ,
136155 languageDropdownVisible: false ,
137- isSmallScreen: false
156+ isSmallScreen: false ,
157+ // 搜索历史相关
158+ searchHistory: [],
159+ showHistory: false ,
160+ SEARCH_HISTORY_KEY : ' xiaozhi_search_history' ,
161+ MAX_HISTORY_COUNT : 3
138162 }
139163 },
140164 computed: {
@@ -165,6 +189,8 @@ export default {
165189 this .fetchUserInfo ();
166190 this .checkScreenSize ();
167191 window .addEventListener (' resize' , this .checkScreenSize );
192+ // 从localStorage加载搜索历史
193+ this .loadSearchHistory ();
168194 },
169195 // 移除事件监听器
170196 beforeDestroy () {
@@ -222,6 +248,9 @@ export default {
222248 return ;
223249 }
224250
251+ // 保存搜索历史
252+ this .saveSearchHistory (searchValue);
253+
225254 try {
226255 // 创建不区分大小写的正则表达式
227256 const regex = new RegExp (searchValue, ' i' );
@@ -234,6 +263,85 @@ export default {
234263 showClose: true
235264 });
236265 }
266+
267+ // 搜索完成后让输入框失去焦点,从而触发blur事件隐藏搜索历史
268+ if (this .$refs .searchInput ) {
269+ this .$refs .searchInput .blur ();
270+ }
271+ },
272+
273+ // 显示搜索历史
274+ showSearchHistory () {
275+ this .showHistory = true ;
276+ },
277+
278+ // 隐藏搜索历史
279+ hideSearchHistory () {
280+ // 延迟隐藏,以便点击事件能够执行
281+ setTimeout (() => {
282+ this .showHistory = false ;
283+ }, 200 );
284+ },
285+
286+ // 加载搜索历史
287+ loadSearchHistory () {
288+ try {
289+ const history = localStorage .getItem (this .SEARCH_HISTORY_KEY );
290+ if (history) {
291+ this .searchHistory = JSON .parse (history);
292+ }
293+ } catch (error) {
294+ console .error (' 加载搜索历史失败:' , error);
295+ this .searchHistory = [];
296+ }
297+ },
298+
299+ // 保存搜索历史
300+ saveSearchHistory (keyword ) {
301+ if (! keyword || this .searchHistory .includes (keyword)) {
302+ return ;
303+ }
304+
305+ // 添加到历史记录开头
306+ this .searchHistory .unshift (keyword);
307+
308+ // 限制历史记录数量
309+ if (this .searchHistory .length > this .MAX_HISTORY_COUNT ) {
310+ this .searchHistory = this .searchHistory .slice (0 , this .MAX_HISTORY_COUNT );
311+ }
312+
313+ // 保存到localStorage
314+ try {
315+ localStorage .setItem (this .SEARCH_HISTORY_KEY , JSON .stringify (this .searchHistory ));
316+ } catch (error) {
317+ console .error (' 保存搜索历史失败:' , error);
318+ }
319+ },
320+
321+ // 选择搜索历史项
322+ selectSearchHistory (keyword ) {
323+ this .search = keyword;
324+ this .handleSearch ();
325+ },
326+
327+ // 移除单个搜索历史项
328+ removeSearchHistory (index ) {
329+ this .searchHistory .splice (index, 1 );
330+ try {
331+ localStorage .setItem (this .SEARCH_HISTORY_KEY , JSON .stringify (this .searchHistory ));
332+ } catch (error) {
333+ console .error (' 更新搜索历史失败:' , error);
334+ }
335+ },
336+
337+ // 清空所有搜索历史
338+ clearSearchHistory () {
339+ this .searchHistory = [];
340+ try {
341+ localStorage .removeItem (this .SEARCH_HISTORY_KEY );
342+ } catch (error) {
343+ console .error (' 清空搜索历史失败:' , error);
344+ }
237345 },
238346 // 显示修改密码弹窗
239347 showChangePasswordDialog () {
@@ -371,6 +479,77 @@ export default {
371479 max-width : none ;
372480}
373481
482+ .search-wrapper {
483+ position : relative ;
484+ }
485+
486+ .search-history-dropdown {
487+ position : absolute ;
488+ top : 100% ;
489+ left : 0 ;
490+ right : 0 ;
491+ background : white ;
492+ border : 1px solid #e4e6ef ;
493+ border-radius : 4px ;
494+ box-shadow : 0 2px 12px 0 rgba (0 , 0 , 0 , 0.1 );
495+ z-index : 1000 ;
496+ margin-top : 2px ;
497+ }
498+
499+ .search-history-header {
500+ display : flex ;
501+ justify-content : space-between ;
502+ align-items : center ;
503+ padding : 8px 12px ;
504+ border-bottom : 1px solid #f0f0f0 ;
505+ font-size : 12px ;
506+ color : #909399 ;
507+ }
508+
509+ .clear-history-btn {
510+ color : #909399 ;
511+ font-size : 11px ;
512+ padding : 0 ;
513+ height : auto ;
514+ }
515+
516+ .clear-history-btn :hover {
517+ color : #606266 ;
518+ }
519+
520+ .search-history-list {
521+ max-height : 200px ;
522+ overflow-y : auto ;
523+ }
524+
525+ .search-history-item {
526+ display : flex ;
527+ justify-content : space-between ;
528+ align-items : center ;
529+ padding : 8px 12px ;
530+ cursor : pointer ;
531+ font-size : 12px ;
532+ color : #606266 ;
533+ }
534+
535+ .search-history-item :hover {
536+ background-color : #f5f7fa ;
537+ }
538+
539+ .clear-item-icon {
540+ font-size : 10px ;
541+ color : #909399 ;
542+ visibility : hidden ;
543+ }
544+
545+ .search-history-item :hover .clear-item-icon {
546+ visibility : visible ;
547+ }
548+
549+ .clear-item-icon :hover {
550+ color : #ff4949 ;
551+ }
552+
374553.custom-search-input >>>.el-input__inner {
375554 height : 18px ;
376555 border-radius : 9px ;
0 commit comments