@@ -29,6 +29,9 @@ type ApiDocumentItem = {
2929 description : string ;
3030} ;
3131
32+ const READER_KEYBOARD_PAGE_SCROLL_RATIO = 0.88 ;
33+ const READER_KEYBOARD_MIN_SCROLL_DISTANCE = 320 ;
34+
3235function formatDateLabel ( value : string ) : string {
3336 if ( ! value ) {
3437 return "未标注时间" ;
@@ -1432,6 +1435,26 @@ function ReaderPanel() {
14321435 scrollArticleViewportToTop ( ) ;
14331436 }
14341437
1438+ function scrollArticleViewportByPage ( direction : 1 | - 1 ) {
1439+ const scrollContainer = articleScrollRef . current ;
1440+
1441+ if ( ! scrollContainer ) {
1442+ return false ;
1443+ }
1444+
1445+ const scrollDistance = Math . max (
1446+ READER_KEYBOARD_MIN_SCROLL_DISTANCE ,
1447+ Math . floor ( scrollContainer . clientHeight * READER_KEYBOARD_PAGE_SCROLL_RATIO ) ,
1448+ ) ;
1449+
1450+ scrollContainer . scrollBy ( {
1451+ top : direction * scrollDistance ,
1452+ behavior : "smooth" ,
1453+ } ) ;
1454+
1455+ return true ;
1456+ }
1457+
14351458 function handleSelectReaderNavigationMode ( nextMode : ReaderBaseNavigationMode ) {
14361459 setReaderBaseNavigationMode ( nextMode ) ;
14371460
@@ -1460,14 +1483,24 @@ function ReaderPanel() {
14601483 return ;
14611484 }
14621485
1463- if ( event . key !== "ArrowLeft" && event . key !== "ArrowRight" ) {
1486+ if ( ! [ "ArrowLeft" , "ArrowRight" , "ArrowUp" , "ArrowDown" ] . includes ( event . key ) ) {
14641487 return ;
14651488 }
14661489
14671490 if ( isKeyboardEventFromEditableTarget ( event ) || document . querySelector ( ".reader-image-viewer" ) ) {
14681491 return ;
14691492 }
14701493
1494+ if ( event . key === "ArrowUp" || event . key === "ArrowDown" ) {
1495+ const didScroll = scrollArticleViewportByPage ( event . key === "ArrowDown" ? 1 : - 1 ) ;
1496+
1497+ if ( didScroll ) {
1498+ event . preventDefault ( ) ;
1499+ }
1500+
1501+ return ;
1502+ }
1503+
14711504 const targetItem = event . key === "ArrowLeft" ? previousItem : nextItem ;
14721505
14731506 if ( ! targetItem ) {
0 commit comments