@@ -12,6 +12,7 @@ import { TTSPlayer, type TTSSentence } from "../utils/ttsService";
1212import { EmptyState } from "./EmptyState" ;
1313import { Icons } from "./Icons" ;
1414import { Select } from "./Select" ;
15+ import { logger } from "../utils/logger" ;
1516
1617export function ReaderPanel ( {
1718 showReadingModeToggle = false ,
@@ -152,12 +153,14 @@ export function ReaderPanel({
152153 /** TTS 控制 */
153154 const handleTTSToggle = useCallback ( ( ) => {
154155 if ( ttsPlaying ) {
156+ logger . tts ( "暂停播放" ) ;
155157 if ( ttsPlayerRef . current ) {
156158 ttsPlayerRef . current . pause ( ) ;
157159 setTtsPlaying ( false ) ;
158160 setTtsHighlightedPara ( - 1 ) ;
159161 }
160162 } else {
163+ logger . tts ( "开始播放, 段落数: " + paragraphs . length ) ;
161164 if ( ! ttsPlayerRef . current ) {
162165 ttsPlayerRef . current = new TTSPlayer ( ttsConfig ) ;
163166 ttsPlayerRef . current . setOnUpdate ( ( sentences ) => {
@@ -168,6 +171,7 @@ export function ReaderPanel({
168171 }
169172 } ) ;
170173 ttsPlayerRef . current . setOnComplete ( ( ) => {
174+ logger . tts ( "播放完成" ) ;
171175 setTtsPlaying ( false ) ;
172176 setTtsHighlightedPara ( - 1 ) ;
173177 } ) ;
@@ -305,16 +309,19 @@ export function ReaderPanel({
305309 setSearchResults ( [ ] ) ;
306310 return ;
307311 }
312+ logger . search ( `搜索: "${ query } "` ) ;
308313 const results : typeof searchResults = [ ] ;
309314 const lowerQuery = query . toLowerCase ( ) ;
310- paragraphs . forEach ( ( para , paraIndex ) => {
315+ paragraphs . forEach ( ( para , filteredIndex ) => {
316+ // 获取原始段落索引(用于行号显示和滚动定位)
317+ const originalIndex = paragraphIndexMap [ filteredIndex ] ;
311318 let startIndex = 0 ;
312319 const lowerPara = para . toLowerCase ( ) ;
313320 while ( startIndex < lowerPara . length ) {
314321 const matchIndex = lowerPara . indexOf ( lowerQuery , startIndex ) ;
315322 if ( matchIndex === - 1 ) break ;
316323 results . push ( {
317- paraIndex,
324+ paraIndex : originalIndex ,
318325 matchStart : matchIndex ,
319326 matchEnd : matchIndex + query . length ,
320327 text : para . slice ( Math . max ( 0 , matchIndex - 20 ) , matchIndex ) + "【" + para . slice ( matchIndex , matchIndex + query . length ) + "】" + para . slice ( matchIndex + query . length , Math . min ( para . length , matchIndex + query . length + 20 ) ) ,
@@ -324,7 +331,8 @@ export function ReaderPanel({
324331 } ) ;
325332 setSearchResults ( results ) ;
326333 setCurrentMatchIndex ( results . length > 0 ? 0 : - 1 ) ;
327- } , [ paragraphs ] ) ;
334+ logger . search ( `搜索完成, 找到 ${ results . length } 个匹配` ) ;
335+ } , [ paragraphs , paragraphIndexMap ] ) ;
328336
329337 /** 点击搜索结果:跳转并关闭 */
330338 const handleSearchResultClick = useCallback ( ( index : number ) => {
@@ -471,6 +479,13 @@ export function ReaderPanel({
471479 </ label >
472480 </ div >
473481 ) }
482+ < button
483+ className = "reader-search-btn"
484+ onClick = { ( ) => setShowSearch ( true ) }
485+ >
486+ < Icons . search size = { 18 } />
487+ < span > 搜索</ span >
488+ </ button >
474489 </ div >
475490 < div
476491 className = { `reader-content${ readingMode ? " reading-mode" : "" } ` }
@@ -1011,15 +1026,6 @@ export function ReaderPanel({
10111026
10121027 { /* 悬浮操作按钮 */ }
10131028 < div className = "reader-floating-actions" >
1014- { ! readingMode && (
1015- < button
1016- className = "reader-search-btn"
1017- onClick = { ( ) => setShowSearch ( true ) }
1018- >
1019- < Icons . search size = { 18 } />
1020- < span > 搜索</ span >
1021- </ button >
1022- ) }
10231029 { readingMode && ttsPlaying && (
10241030 < button
10251031 className = "reader-tts-btn playing"
0 commit comments