301301 position : relative;
302302 max-height : 90vh ;
303303 overflow-y : auto;
304+ overflow-x : hidden;
304305 }
305306
306307 .markdown-close {
307- position : absolute;
308- top : 15px ;
309- right : 20px ;
310- font-size : 30px ;
308+ position : fixed;
309+ top : 70px ;
310+ right : calc ((100% - 900px ) / 2 + 30px );
311+ width : 32px ;
312+ height : 32px ;
311313 cursor : pointer;
312- color : # 666 ;
313- transition : color 0.3s ;
314+ background : transparent;
315+ border-radius : 50% ;
316+ display : flex;
317+ align-items : center;
318+ justify-content : center;
319+ z-index : 1001 ;
320+ transition : all 0.2s cubic-bezier (0.4 , 0 , 0.2 , 1 );
321+ border : none;
322+ outline : none;
323+ padding : 0 ;
324+ opacity : 0.6 ;
325+ }
326+
327+ .markdown-close ::before {
328+ content : '' ;
329+ position : absolute;
330+ width : 40px ;
331+ height : 40px ;
332+ background : rgba (0 , 0 , 0 , 0.05 );
333+ border-radius : 50% ;
334+ transform : scale (0 );
335+ transition : transform 0.2s cubic-bezier (0.4 , 0 , 0.2 , 1 );
336+ }
337+
338+ .markdown-close svg {
339+ width : 16px ;
340+ height : 16px ;
341+ stroke : # 333 ;
342+ stroke-width : 2.5 ;
343+ transition : all 0.2s ease;
344+ position : relative;
345+ z-index : 1 ;
314346 }
315347
316348 .markdown-close : hover {
317- color : # 000 ;
349+ opacity : 1 ;
350+ }
351+
352+ .markdown-close : hover ::before {
353+ transform : scale (1 );
354+ }
355+
356+ .markdown-close : hover svg {
357+ stroke : # 000 ;
358+ transform : rotate (90deg );
359+ }
360+
361+ .markdown-close : active {
362+ transform : scale (0.95 );
363+ }
364+
365+ @media (max-width : 900px ) {
366+ .markdown-close {
367+ right : 20px ;
368+ top : 60px ;
369+ }
318370 }
319371
320372 /* Markdown 渲染樣式 */
352404 overflow-x : auto;
353405 margin : 15px 0 ;
354406 position : relative;
407+ max-width : 100% ;
355408 }
356409
357410 .markdown-content pre code {
413466 border-collapse : collapse;
414467 width : 100% ;
415468 margin : 15px 0 ;
469+ display : block;
470+ overflow-x : auto;
471+ white-space : nowrap;
472+ }
473+
474+ .markdown-content table td ,
475+ .markdown-content table th {
476+ white-space : normal;
477+ word-wrap : break-word;
416478 }
417479
418480 .markdown-content th , .markdown-content td {
@@ -499,7 +561,7 @@ <h2>📚 8 個學習場景</h2>
499561 < div class ="scenario-description "> 建立 Copilot 使用基礎,體驗傳統 Chat 功能</ div >
500562 < span class ="agent-indicator agent-0 "> Agent 0%</ span >
501563 < div class ="scenario-links ">
502- < a href ="# " onclick ="loadMarkdown('./01-first-experience/README .md', '場景 1:初次對話體驗'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
564+ < a href ="# " onclick ="loadMarkdown('./01-first-experience/LESSON_GUIDE .md', '場景 1:初次對話體驗'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
503565 < a href ="./01-first-experience/ " class ="btn btn-demo "> 🎯 實際應用</ a >
504566 </ div >
505567 </ div >
@@ -510,7 +572,7 @@ <h2>📚 8 個學習場景</h2>
510572 < div class ="scenario-description "> 掌握 @workspace 核心功能,理解專案結構</ div >
511573 < span class ="agent-indicator agent-0 "> Agent 0%</ span >
512574 < div class ="scenario-links ">
513- < a href ="# " onclick ="loadMarkdown('./02-code-explanation/README .md', '場景 2:程式碼解釋實作'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
575+ < a href ="# " onclick ="loadMarkdown('./02-code-explanation/LESSON_GUIDE .md', '場景 2:程式碼解釋實作'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
514576 < a href ="./02-code-explanation/ " class ="btn btn-demo "> 🎯 實際應用</ a >
515577 </ div >
516578 </ div >
@@ -521,7 +583,7 @@ <h2>📚 8 個學習場景</h2>
521583 < div class ="scenario-description "> 體驗 Agent 協助編程,對比手動 vs AI 效率</ div >
522584 < span class ="agent-indicator agent-20 "> Agent 20%</ span >
523585 < div class ="scenario-links ">
524- < a href ="# " onclick ="loadMarkdown('./03-function-generation/README .md', '場景 3:函數生成'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
586+ < a href ="# " onclick ="loadMarkdown('./03-function-generation/LESSON_GUIDE .md', '場景 3:函數生成'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
525587 < a href ="./03-function-generation/ " class ="btn btn-demo "> 🎯 實際應用</ a >
526588 </ div >
527589 </ div >
@@ -532,7 +594,7 @@ <h2>📚 8 個學習場景</h2>
532594 < div class ="scenario-description "> 讓 Agent 主動發現和修復程式問題</ div >
533595 < span class ="agent-indicator agent-30 "> Agent 30%</ span >
534596 < div class ="scenario-links ">
535- < a href ="# " onclick ="loadMarkdown('./04-debugging-assistant/README .md', '場景 4:偵錯輔助'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
597+ < a href ="# " onclick ="loadMarkdown('./04-debugging-assistant/LESSON_GUIDE .md', '場景 4:偵錯輔助'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
536598 < a href ="./04-debugging-assistant/ " class ="btn btn-demo "> 🎯 實際應用</ a >
537599 </ div >
538600 </ div >
@@ -543,7 +605,7 @@ <h2>📚 8 個學習場景</h2>
543605 < div class ="scenario-description "> Agent 自主設計測試架構和完整用例</ div >
544606 < span class ="agent-indicator agent-50 "> Agent 50%</ span >
545607 < div class ="scenario-links ">
546- < a href ="# " onclick ="loadMarkdown('./05-unit-testing/README .md', '場景 5:單元測試'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
608+ < a href ="# " onclick ="loadMarkdown('./05-unit-testing/LESSON_GUIDE .md', '場景 5:單元測試'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
547609 < a href ="./05-unit-testing/ " class ="btn btn-demo "> 🎯 實際應用</ a >
548610 </ div >
549611 </ div >
@@ -554,7 +616,7 @@ <h2>📚 8 個學習場景</h2>
554616 < div class ="scenario-description "> Agent 分析遺留代碼並執行重構策略</ div >
555617 < span class ="agent-indicator agent-60 "> Agent 60%</ span >
556618 < div class ="scenario-links ">
557- < a href ="# " onclick ="loadMarkdown('./06-code-refactoring/README .md', '場景 6:程式碼重構'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
619+ < a href ="# " onclick ="loadMarkdown('./06-code-refactoring/LESSON_GUIDE .md', '場景 6:程式碼重構'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
558620 < a href ="./06-code-refactoring/ " class ="btn btn-demo "> 🎯 實際應用</ a >
559621 </ div >
560622 </ div >
@@ -565,7 +627,7 @@ <h2>📚 8 個學習場景</h2>
565627 < div class ="scenario-description "> Agent 自動分析程式碼生成完整文件體系</ div >
566628 < span class ="agent-indicator agent-80 "> Agent 80%</ span >
567629 < div class ="scenario-links ">
568- < a href ="# " onclick ="loadMarkdown('./07-documentation/README .md', '場景 7:文件生成'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
630+ < a href ="# " onclick ="loadMarkdown('./07-documentation/LESSON_GUIDE .md', '場景 7:文件生成'); return false; " class ="btn btn-doc "> 📚 查看教學</ a >
569631 </ div >
570632 </ div >
571633
@@ -586,7 +648,7 @@ <h2>📚 8 個學習場景</h2>
586648 </ div >
587649 </ div >
588650 < div class ="scenario-links scenario-links-3 ">
589- < a href ="# " onclick ="loadMarkdown('./08-comprehensive-project/TEACHING_GUIDE .md', '場景 8:GitHub 自動化 Agent'); return false; " class ="btn btn-doc "> 📚 教學</ a >
651+ < a href ="# " onclick ="loadMarkdown('./08-comprehensive-project/LESSON_GUIDE .md', '場景 8:GitHub 自動化 Agent'); return false; " class ="btn btn-doc "> 📚 教學</ a >
590652 < a href ="https://github.com/yulin0629/copilot-agent-demo-todo " target ="_blank " class ="btn btn-repo "> 💻 GitHub</ a >
591653 < a href ="https://yulin0629.github.io/copilot-agent-demo-todo/ " target ="_blank " class ="btn btn-demo "> 🎯 Demo</ a >
592654 </ div >
@@ -603,18 +665,38 @@ <h2>📚 8 個學習場景</h2>
603665 <!-- Markdown Modal -->
604666 < div id ="markdownModal " class ="markdown-modal ">
605667 < div class ="markdown-content ">
606- < span class ="markdown-close " onclick ="closeMarkdown() "> ×</ span >
668+ < button class ="markdown-close " onclick ="closeMarkdown() " aria-label ="關閉 ">
669+ < svg viewBox ="0 0 24 24 " fill ="none " xmlns ="http://www.w3.org/2000/svg ">
670+ < path d ="M18 6L6 18M6 6l12 12 " stroke ="currentColor " stroke-linecap ="round " stroke-linejoin ="round "/>
671+ </ svg >
672+ </ button >
607673 < div id ="markdownBody ">
608674 < div class ="markdown-loading "> 📡 載入中...</ div >
609675 </ div >
610676 </ div >
611677 </ div >
612678
613679 < script >
680+ // 儲存和取得捲動位置
681+ function saveScrollPosition ( path , position ) {
682+ localStorage . setItem ( `scroll_${ path } ` , position ) ;
683+ }
684+
685+ function getScrollPosition ( path ) {
686+ return parseInt ( localStorage . getItem ( `scroll_${ path } ` ) || '0' ) ;
687+ }
688+
689+ // 儲存當前文件路徑
690+ let currentMarkdownPath = '' ;
691+
614692 // 載入並顯示 Markdown
615693 async function loadMarkdown ( path , title ) {
616694 const modal = document . getElementById ( 'markdownModal' ) ;
617695 const body = document . getElementById ( 'markdownBody' ) ;
696+ const container = body . parentElement ;
697+
698+ // 儲存當前路徑
699+ currentMarkdownPath = path ;
618700
619701 // 顯示 Modal
620702 modal . style . display = 'block' ;
@@ -641,8 +723,24 @@ <h2>📚 8 個學習場景</h2>
641723 // 為所有程式碼區塊添加複製按鈕
642724 addCopyButtons ( ) ;
643725
644- // 滾動到頂部
645- body . parentElement . scrollTop = 0 ;
726+ // 恢復上次的捲動位置
727+ const savedPosition = getScrollPosition ( path ) ;
728+ if ( savedPosition > 0 ) {
729+ // 使用 setTimeout 確保內容已經渲染
730+ setTimeout ( ( ) => {
731+ container . scrollTop = savedPosition ;
732+ } , 100 ) ;
733+ } else {
734+ // 如果沒有儲存的位置,滾動到頂部
735+ container . scrollTop = 0 ;
736+ }
737+
738+ // 監聽捲動事件,儲存位置
739+ container . onscroll = debounce ( ( ) => {
740+ if ( currentMarkdownPath ) {
741+ saveScrollPosition ( currentMarkdownPath , container . scrollTop ) ;
742+ }
743+ } , 300 ) ;
646744
647745 } catch ( error ) {
648746 body . innerHTML = `
@@ -655,9 +753,34 @@ <h2>❌ 載入失敗</h2>
655753 }
656754 }
657755
756+ // 防抖函數
757+ function debounce ( func , wait ) {
758+ let timeout ;
759+ return function executedFunction ( ...args ) {
760+ const later = ( ) => {
761+ clearTimeout ( timeout ) ;
762+ func ( ...args ) ;
763+ } ;
764+ clearTimeout ( timeout ) ;
765+ timeout = setTimeout ( later , wait ) ;
766+ } ;
767+ }
768+
658769 // 關閉 Markdown Modal
659770 function closeMarkdown ( ) {
660- document . getElementById ( 'markdownModal' ) . style . display = 'none' ;
771+ const modal = document . getElementById ( 'markdownModal' ) ;
772+ const container = document . getElementById ( 'markdownBody' ) . parentElement ;
773+
774+ // 儲存最後的捲動位置
775+ if ( currentMarkdownPath ) {
776+ saveScrollPosition ( currentMarkdownPath , container . scrollTop ) ;
777+ }
778+
779+ // 清理事件監聽器
780+ container . onscroll = null ;
781+
782+ // 關閉 Modal
783+ modal . style . display = 'none' ;
661784 }
662785
663786 // 點擊 Modal 外部關閉
0 commit comments