11<template >
2- <div class =" panel" >
2+ <div class =" panel" @pointerdown = " windowStore.setFocus('search') " >
33 <div class =" panel-header" >
44 <div class =" header-title" >
55 <h3 >搜索与筛选</h3 >
108108 找到 {{ searchResults.length }} 条结果
109109 </span >
110110 <button
111- class =" btn-primary btn-sm "
111+ class =" btn-primary"
112112 :disabled =" searchResults.length === 0"
113113 @click =" selectAllMatches"
114114 >
130130 'is-selected': filterStore.selectedMessageIds.value.has(
131131 msg.messageId,
132132 ),
133+ 'is-active':
134+ windowStore.currentActiveWindow.windowId === 'search',
133135 }"
134- @click =" filterStore.toggleMessageSelection( msg.messageId)"
136+ @click =" handleItemClick($event, msg.messageId)"
135137 >
136138 <div class =" result-meta" >
137139 <span class =" result-name" >
149151
150152<script setup lang="ts">
151153import { FunnelIcon , FunnelXIcon , RefreshCcw } from ' @lucide/vue' ;
152- import { ref , computed , reactive } from ' vue' ;
154+ import { ref , computed , reactive , onMounted , onUnmounted } from ' vue' ;
153155import { useLogStore } from ' @/stores/logStore' ;
154156import { useFilter } from ' @/composables/useFilter' ;
155157import { matchesMessageFilter } from ' @/editor/filter' ;
156158import type { MessageFilter } from ' @/types/log' ;
157159import { formatDate } from ' @/utils/date' ;
160+ import { useCommandDispatcher } from ' @/composables/useCommandDispatcher' ;
161+ import { useWindowStore } from ' @/stores/windowStore' ;
158162
159163const logStore = useLogStore ();
164+ const windowStore = useWindowStore ();
160165const filterStore = useFilter (' search' );
166+ const { dispatch } = useCommandDispatcher ();
161167
162168// 状态控制
163169const quickSearch = ref (' ' );
@@ -218,15 +224,34 @@ function handleSearch() {
218224 quickSearch .value = quickSearch .value .trim ();
219225}
220226
227+ function handleItemClick(event : MouseEvent , msgId : string ) {
228+ windowStore .setFocus (' search' );
229+
230+ dispatch (' messageSelect' , {
231+ event ,
232+ msgId ,
233+ messages: searchResults .value , // 将当前计算出的搜索结果快照传给调度器
234+ });
235+ }
236+
221237function selectAllMatches() {
222- const ids = searchResults .value .map ((m ) => m .messageId );
223- ids .forEach ((id ) => {
224- if (! filterStore .selectedMessageIds .value .has (id )) {
225- filterStore .toggleMessageSelection (id );
226- }
238+ dispatch (' selectAll' , {
239+ messages: searchResults .value ,
227240 });
228241}
229242
243+ const handleKeyDown = (e : KeyboardEvent ) => {
244+ if (windowStore .activeFocus !== ' search' ) return ;
245+
246+ if ((e .ctrlKey || e .metaKey ) && e .key === ' a' ) {
247+ e .preventDefault ();
248+ selectAllMatches ();
249+ }
250+ };
251+
252+ onMounted (() => window .addEventListener (' keydown' , handleKeyDown ));
253+ onUnmounted (() => window .removeEventListener (' keydown' , handleKeyDown ));
254+
230255function clearAllFilters() {
231256 quickSearch .value = ' ' ;
232257 filter .playerName = ' ' ;
@@ -351,14 +376,24 @@ const truncate = (str: string, len: number) => {
351376
352377.search-summary {
353378 flex-shrink : 0 ;
354- padding : 8 px 12 px ;
379+ padding : 4 px 8 px ;
355380 display : flex ;
356381 justify-content : space-between ;
357382 align-items : center ;
358383 background : var (--bg-secondary );
359- border-bottom : 1px solid var (--border-color );
360384}
361385
386+ .btn-primary {
387+ font-size : 12px ;
388+ color : var (--text-muted );
389+ background-color : var (--bg-secondary );
390+ border : 1px solid var (--border-color );
391+ border-radius : 4px ;
392+ }
393+
394+ .btn-primary :hover {
395+ background-color : var (--hover-bg );
396+ }
362397.count-text {
363398 font-size : 12px ;
364399 color : var (--text-secondary );
@@ -374,17 +409,20 @@ const truncate = (str: string, len: number) => {
374409.result-item {
375410 padding : 10px 10px 10px 8px ;
376411 cursor : pointer ;
377- border-bottom : 1px solid var (--border-color );
378412}
379413
380414.result-item :hover {
381415 background : var (--bg-secondary );
416+ outline-offset : -1px ;
417+ outline : 1px solid var (--active-accent );
382418}
383419
384- .result-item.is-selected {
420+ .result-item.is-selected.is-active {
385421 background : var (--selection-bg );
386- outline : 1px solid var (--active-accent );
387- outline-offset : -1px ;
422+ }
423+
424+ .result-item.is-selected :not (.is-active ) {
425+ background : var (--inactive-selection-bg );
388426}
389427
390428.result-meta {
0 commit comments