Spaces:
Sleeping
Sleeping
| # ui/layouts.py (最終完整版) | |
| import gradio as gr | |
| from config import content, data, defaults | |
| from core import callbacks | |
| def create_ui(visit_count_html: str, theme: gr.Theme): | |
| """ | |
| Creates and returns the Gradio UI Blocks. | |
| Args: | |
| visit_count_html: The Markdown string to display the visit count. | |
| theme: The Gradio theme object to apply to the UI. | |
| """ | |
| with gr.Blocks(theme=theme, title="地球物理學") as demo: | |
| # --- 自訂頂部 Header --- | |
| gr.Markdown( | |
| """ | |
| <style> | |
| .custom-header { | |
| background: linear-gradient(135deg, #005f73, #0a9396); | |
| color: #fff; | |
| padding: 4rem 2rem; | |
| text-align: center; | |
| border-radius: 0 0 20px 20px; | |
| margin-bottom: 2rem; | |
| box-shadow: 0 8px 15px rgba(0,0,0,0.1); | |
| } | |
| .custom-header h1 { | |
| font-size: 3.5rem; | |
| font-weight: 700; | |
| margin-bottom: 0.8rem; | |
| line-height: 1.2; | |
| } | |
| .custom-header p { | |
| font-size: 1.6rem; | |
| font-weight: 400; | |
| opacity: 0.9; | |
| margin-top: 0; | |
| } | |
| @media (max-width: 768px) { | |
| .custom-header { | |
| padding: 3rem 1rem; | |
| border-radius: 0; | |
| } | |
| .custom-header h1 { | |
| font-size: 2.5rem; | |
| } | |
| .custom-header p { | |
| font-size: 1.2rem; | |
| } | |
| } | |
| </style> | |
| <div class="custom-header"> | |
| <h1>地球物理概論</h1> | |
| <p>在這裡,您不僅能學習理論,更能透過「互動實驗室」親手編寫程式碼、視覺化地震資料,並隨時向「AI 助教」提問,獲取課程解答與即時的全球地震資訊。立即開始您的地球物理探索之旅吧!</p> | |
| </div> | |
| """ | |
| ) | |
| # --- 主導覽列 Tab 容器 --- | |
| with gr.Tabs(selected=0): | |
| with gr.TabItem("🎯 課程目標"): | |
| gr.Markdown(content.course_goals_md) | |
| with gr.TabItem("🗓️ 課程進度"): | |
| gr.Markdown("### 每週課程安排") | |
| gr.DataFrame(data.schedule_df, wrap=True) | |
| with gr.TabItem("💯 成績計算"): | |
| gr.Markdown(content.grading_policy_md) | |
| with gr.TabItem("🚀 互動體驗區 (程式碼實驗室)"): | |
| gr.Markdown("## 🚀 互動程式碼實驗室") | |
| gr.Markdown("歡迎來到這裡!直接修改下方的 Python 程式碼,點擊「執行」,即可在右側看到成果。這是學習程式與地球物理最直接的方式!") | |
| gr.Info("注意:執行環境已受限,僅支援資料視覺化相關操作。請勿嘗試檔案讀寫或網路請求。") | |
| with gr.Accordion("🌍 地圖繪製實驗室 (PyGMT/Cartopy 概念)", open=True): | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| gr.Markdown("### 說明\n這段程式碼使用 `cartopy` 和 `matplotlib` 函式庫來繪製地理地圖。\n\n**您可以試著:**\n1. 修改 `center_lon`, `center_lat` 來改變地圖中心。\n2. 調整 `extent_lon`, `extent_lat` 來縮放地圖。\n3. 將 `coastline_color` 改成 'red' 或其他顏色。\n4. **在 `symbols` 列表中新增或修改字典,來繪製自訂的符號(例如:標示您所在的城市)。**") | |
| map_code = gr.Code(label="可編輯的 Python 程式碼", value=defaults.DEFAULT_MAP_CODE, language="python", lines=25) | |
| map_run_button = gr.Button("執行程式碼", variant="primary") | |
| with gr.Column(scale=3): | |
| map_plot_output = gr.Plot(label="地圖輸出") | |
| map_console_output = gr.Textbox(label="執行結果 / 錯誤訊息", lines=8, interactive=False) | |
| with gr.Accordion("📈 震波圖繪製實驗室 (ObsPy 概念)", open=False): | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| gr.Markdown("### 說明\n這段程式碼使用 `numpy` 產生模擬的地震波數據,並用 `matplotlib` 將其視覺化。\n\n**您可以試著:**\n1. 修改 `p_wave_arrival` 和 `s_wave_arrival` 來改變 P/S 波的抵達時間。\n2. 調整 `main_freq` 來改變地震波的頻率(數值越大,波形越密集)。\n3. 將 `decay_rate` 調小,觀察振幅衰減變慢的效果。") | |
| seismo_code = gr.Code(label="可編輯的 Python 程式碼", value=defaults.DEFAULT_SEISMO_CODE, language="python", lines=25) | |
| seismo_run_button = gr.Button("執行程式碼", variant="primary") | |
| with gr.Column(scale=3): | |
| seismo_plot_output = gr.Plot(label="震波圖輸出") | |
| seismo_console_output = gr.Textbox(label="執行結果 / 錯誤訊息", lines=8, interactive=False) | |
| with gr.TabItem("🤖 AI 課程助教"): | |
| with gr.Group(): | |
| gr.Markdown("### 🤖 AI 課程助教 (知識庫 & 即時資訊強化版)") | |
| gr.Markdown(""" | |
| 歡迎使用課程 AI 助教!我整合了靜態的課程知識與多種即時資訊來源,您可以隨時向我提問。 | |
| --- | |
| #### 📚 **課程知識庫** | |
| 我可以回答關於本課程的各種問題,例如:`「這門課的評分標準是什麼?」` | |
| --- | |
| #### ⚡ **即時資訊查詢** | |
| 我還能幫您查詢最新的動態資訊,試著問我: | |
| - **📰 今日新聞**:`「今天有什麼重要新聞?」` | |
| - **🚨 地震報告**:`「最新的 CWA 顯著地震報告」` 或 `「最近全球有哪些大地震?」` | |
| - **📢 災害預警**:`「現在有地震預警嗎?」` | |
| --- | |
| #### 🔎 **進階地震查詢** | |
| 您也可以指定日期與規模來查詢全球地震紀錄,請**完全依照以下格式**提問: | |
| - `查詢 2024-04-01 到 2024-04-07 規模 6.0 以上地震` | |
| """) | |
| custom_textbox = gr.Textbox( | |
| placeholder="對課程有什麼問題嗎?或查詢即時資訊...", | |
| show_label=False, | |
| container=False, | |
| ) | |
| gr.ChatInterface( | |
| callbacks.ai_chatbot_with_kb, | |
| chatbot=gr.Chatbot(height=450, type="messages", avatar_images=(None, "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png")), | |
| title="課程AI助教", | |
| description="由結構化知識庫與即時工具驅動的問答機器人", | |
| textbox=custom_textbox, | |
| ) | |
| # --- 連接按鈕與後端執行函式 --- | |
| map_run_button.click( | |
| fn=lambda code: callbacks.execute_user_code(code, "地圖繪製"), | |
| inputs=[map_code], | |
| outputs=[map_plot_output, map_console_output] | |
| ) | |
| seismo_run_button.click( | |
| fn=lambda code: callbacks.execute_user_code(code, "震波圖"), | |
| inputs=[seismo_code], | |
| outputs=[seismo_plot_output, seismo_console_output] | |
| ) | |
| return demo | |