Spaces:
Sleeping
Sleeping
E3:清除 scenario_btn_col 死碼 wiring
Browse filesPhase 8 留下的空 Column(純為既有可見性 wiring 保留,selection buttons
早已搬到 homepage_col/scenario_select_row),整段移除:
- 宣告本身與對應 CSS(.scenario-buttons 相關規則,含收合狀態覆寫)
- on_scenario_pick 四個 yield/outputs 清單移除該 output slot
- on_reset_confirm 移除該 output slot,回傳 tuple 9→8 個元素
Playwright 驗證:情境選擇(1/3)、格式要求文案、重新選擇研究情境、
回首頁重置後再選情境,皆正常無 console/server error。
- app_agent.py +23 -56
app_agent.py
CHANGED
|
@@ -2658,12 +2658,6 @@ div[role="log"][aria-label="chatbot conversation"],
|
|
| 2658 |
padding-top: .6rem !important;
|
| 2659 |
border-top: 1px solid var(--c-border) !important;
|
| 2660 |
}
|
| 2661 |
-
/* 5-D:scenario_btn_col 是 Phase 8 留下的空 Column(只為既有可見性 wiring
|
| 2662 |
-
保留,E3 待清)。它夾在頂端列與「開始新分析」之間,即使沒內容,flex gap
|
| 2663 |
-
仍會在它前後各插一份間距,把兩者推遠(這正是千卉回報的「間距太遠」)。
|
| 2664 |
-
直接 display:none 讓它退出 flex 排版、間距歸零;wiring 對它設 visible 仍
|
| 2665 |
-
可跑、只是視覺無效果(本來就空的)。 */
|
| 2666 |
-
.scenario-buttons { display: none !important; }
|
| 2667 |
/* 真因排查記錄:Gradio 的 .column 預設會帶 flex-wrap:wrap。平常沒設高度時
|
| 2668 |
不會有事,但這裡額外設了固定 height 讓內容用捲動取代撐高,一旦內容總高
|
| 2669 |
度超過這個 height,flex-wrap:wrap 會把「排不下」的子元件換到*右邊新開一
|
|
@@ -2801,20 +2795,6 @@ div[role="log"][aria-label="chatbot conversation"],
|
|
| 2801 |
flex-shrink: 0 !important;
|
| 2802 |
}
|
| 2803 |
|
| 2804 |
-
/* ── 5c. SCENARIO BUTTONS(取代原本打字輸入研究情境的輸入列)────────── */
|
| 2805 |
-
.scenario-buttons {
|
| 2806 |
-
margin-top: .6rem !important;
|
| 2807 |
-
gap: .5rem !important;
|
| 2808 |
-
}
|
| 2809 |
-
.scenario-buttons button {
|
| 2810 |
-
width: 100% !important;
|
| 2811 |
-
justify-content: flex-start !important;
|
| 2812 |
-
text-align: left !important;
|
| 2813 |
-
padding: .85rem 1.1rem !important;
|
| 2814 |
-
border-radius: 10px !important;
|
| 2815 |
-
font-weight: 600 !important;
|
| 2816 |
-
font-size: var(--font-size-base) !important;
|
| 2817 |
-
}
|
| 2818 |
/* ── 5d. HOMEPAGE(Phase 8:首頁 4 張情境卡片)──────────────────── */
|
| 2819 |
/* 隱藏版情境按鈕:純作 JS 橋接目標(見 _APP_HEAD_SCRIPT),
|
| 2820 |
點卡片=模擬點這裡的按鈕,Python 端 .click() 綁定完全不動。
|
|
@@ -3085,7 +3065,6 @@ img.button-icon { opacity: .82; }
|
|
| 3085 |
/* .reset-confirm 已於 2026-07-24 搬出 nav-col 改成全螢幕 modal,
|
| 3086 |
不再需要在收合狀態下隱藏;.result-nav-accordion 同日隨「統計比較
|
| 3087 |
分析」手風琴一起移除。 */
|
| 3088 |
-
.nav-col.collapsed .scenario-buttons,
|
| 3089 |
.nav-col.collapsed .result-nav-divider { display: none !important; }
|
| 3090 |
/* 選擇器裡的 #result_nav_col 是為了贏過下方 nav-underline 樣式的
|
| 3091 |
`#result_nav_col .result-nav-btn`(1 個 id + 1 個 class = 1,1,0)。
|
|
@@ -4900,20 +4879,10 @@ def create_app():
|
|
| 4900 |
elem_id="nav_top_html",
|
| 4901 |
)
|
| 4902 |
|
| 4903 |
-
# 中段可捲動區:
|
| 4904 |
-
#
|
| 4905 |
-
#
|
| 4906 |
with gr.Column(elem_classes=["nav-items-scroll"]) as nav_items_scroll:
|
| 4907 |
-
# 研究情境是封閉式的固定四選一,改用可點擊按鈕取代打字輸入
|
| 4908 |
-
# 數字再解析,選定後即隱藏,對話視窗回歸純輸出角色
|
| 4909 |
-
# Phase 8:情境選擇按鈕已搬到 homepage_col(見上方,理由是
|
| 4910 |
-
# Gradio 對建構時 visible=False 的容器不掛載進 DOM,見該處
|
| 4911 |
-
# 註解)。這個 Column 目前是空的,只留來讓 on_scenario_pick/
|
| 4912 |
-
# on_reset_confirm 既有的可見性輸出繼續運作,不動更多 wiring;
|
| 4913 |
-
# Phase 8-F 全站清理時一併拿掉。
|
| 4914 |
-
with gr.Column(elem_classes=["scenario-buttons"]) as scenario_btn_col:
|
| 4915 |
-
pass
|
| 4916 |
-
|
| 4917 |
# 「回首頁」連結與其確認彈窗:換情境/回首頁都走這一套共用
|
| 4918 |
# 機制。情境是封閉式按鈕選擇,不透過對話框打字,所以「換
|
| 4919 |
# 情境」也統一走這顆按鈕,不恢復文字解析路徑。
|
|
@@ -5845,7 +5814,7 @@ def create_app():
|
|
| 5845 |
# 值,不管它是怎麼還原回來的。
|
| 5846 |
def on_scenario_pick(sc_num, chat_history, log_history, state):
|
| 5847 |
if state is None:
|
| 5848 |
-
yield (chat_history, log_history, state, gr.update(), gr.update(), gr.update(),
|
| 5849 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
| 5850 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
| 5851 |
gr.update())
|
|
@@ -5862,7 +5831,7 @@ def create_app():
|
|
| 5862 |
# 東西可看,不用透過 _populate_tabs 的檔案存在判斷來決定可見性。
|
| 5863 |
# 這幾個 visibility 只需要在第一個 yield 就切換一次,後續 yield
|
| 5864 |
# 沿用 gr.update() 不動即可,不用每次都重複賦值。
|
| 5865 |
-
yield (chat_history, log_history, state, gr.update(), gr.update(), gr.update(),
|
| 5866 |
gr.update(visible=False), gr.update(visible=True), gr.update(visible=True),
|
| 5867 |
gr.update(visible=True),
|
| 5868 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
|
@@ -5881,7 +5850,7 @@ def create_app():
|
|
| 5881 |
# 自己對它們下的 visible=False 更新互相打架、我們的更新輸了。
|
| 5882 |
# 等 workspace_row 的翻轉已經在前一個 yield 處理完、沉澱下來,
|
| 5883 |
# 這一個 yield 才不會再觸發同一種還原,我們的 False 才是最後贏家。
|
| 5884 |
-
yield (chat_history, log_history, state, gr.update(), _todo_update(state), gr.update(),
|
| 5885 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
| 5886 |
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
|
| 5887 |
gr.update(visible=False),
|
|
@@ -5897,19 +5866,17 @@ def create_app():
|
|
| 5897 |
state["current_step"] = 2
|
| 5898 |
state["state"] = "UPLOAD_WAIT"
|
| 5899 |
log_history = _log_append(log_history, "⏳ 等待上傳文本……")
|
| 5900 |
-
# 情境已選定,研究選擇區塊收起、換上傳卡片出現
|
| 5901 |
-
#
|
| 5902 |
-
#
|
| 5903 |
-
#
|
| 5904 |
-
#
|
| 5905 |
-
# 對話視窗
|
| 5906 |
-
# (upload_hint_md),使用者不用往上捲回對話視窗找 AI 剛剛說過的
|
| 5907 |
-
# 規則——卡片本身就要自己講清楚。
|
| 5908 |
hint = (
|
| 5909 |
f"**格式要求**\n\n{sc_info['upload_prompt']}"
|
| 5910 |
)
|
| 5911 |
yield (chat_history, log_history, state, gr.update(visible=True),
|
| 5912 |
-
_todo_update(state), gr.update(
|
| 5913 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
| 5914 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
| 5915 |
gr.update(visible=False))
|
|
@@ -5918,7 +5885,7 @@ def create_app():
|
|
| 5918 |
_sc_btn.click(
|
| 5919 |
fn=functools.partial(on_scenario_pick, _sc_num),
|
| 5920 |
inputs=[chatbot, exec_log, session_state],
|
| 5921 |
-
outputs=[chatbot, exec_log, session_state, upload_row, app_header_html,
|
| 5922 |
upload_hint_md, homepage_col, workspace_row, result_nav_col, canvas_exec_col,
|
| 5923 |
metadata_row, canvas_idx_col, canvas_stat_col, canvas_report_col,
|
| 5924 |
scenario_select_row],
|
|
@@ -5928,10 +5895,10 @@ def create_app():
|
|
| 5928 |
outputs=_TAB_OUTPUTS,
|
| 5929 |
)
|
| 5930 |
|
| 5931 |
-
# ── 「開始新分析」:Bug1 修復——
|
| 5932 |
-
#
|
| 5933 |
-
#
|
| 5934 |
-
#
|
| 5935 |
# Bug 4-C 修復(2026-07-30):Gradio 6 的 gr.Column/Row(visible=False)
|
| 5936 |
# 會把��元件整段從 DOM 卸載,不只是 CSS 隱藏。原本 on_reset_confirm
|
| 5937 |
# 在同一個 return 裡,一邊把 workspace_row 設 visible=False,一邊又要
|
|
@@ -5974,7 +5941,6 @@ def create_app():
|
|
| 5974 |
new_log, # exec_log
|
| 5975 |
state, # session_state
|
| 5976 |
gr.update(value=_build_header_html()), # app_header_html
|
| 5977 |
-
gr.update(visible=True), # scenario_btn_col(Bug1 關鍵一行)
|
| 5978 |
gr.update(visible=False), # upload_row(Phase 8:正式上傳入口改這張卡片)
|
| 5979 |
gr.update(visible=False), # reset_confirm_row(關掉確認彈窗自己)
|
| 5980 |
gr.update(visible=True), # homepage_col(Phase 8:重新開始=回到首頁選情境)
|
|
@@ -5991,11 +5957,12 @@ def create_app():
|
|
| 5991 |
).then(
|
| 5992 |
fn=on_reset_confirm,
|
| 5993 |
# 2026-07-30(2-C 第 5 項):chat_upload 這輪常駐隱藏、不再接任何
|
| 5994 |
-
# wiring(見 chat_upload_col 定義處註解),這裡把它從 outputs 移除
|
| 5995 |
-
#
|
| 5996 |
-
#
|
|
|
|
| 5997 |
outputs=[chatbot, exec_log, session_state, app_header_html,
|
| 5998 |
-
|
| 5999 |
reset_confirm_row, homepage_col, workspace_row],
|
| 6000 |
)
|
| 6001 |
|
|
|
|
| 2658 |
padding-top: .6rem !important;
|
| 2659 |
border-top: 1px solid var(--c-border) !important;
|
| 2660 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2661 |
/* 真因排查記錄:Gradio 的 .column 預設會帶 flex-wrap:wrap。平常沒設高度時
|
| 2662 |
不會有事,但這裡額外設了固定 height 讓內容用捲動取代撐高,一旦內容總高
|
| 2663 |
度超過這個 height,flex-wrap:wrap 會把「排不下」的子元件換到*右邊新開一
|
|
|
|
| 2795 |
flex-shrink: 0 !important;
|
| 2796 |
}
|
| 2797 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2798 |
/* ── 5d. HOMEPAGE(Phase 8:首頁 4 張情境卡片)──────────────────── */
|
| 2799 |
/* 隱藏版情境按鈕:純作 JS 橋接目標(見 _APP_HEAD_SCRIPT),
|
| 2800 |
點卡片=模擬點這裡的按鈕,Python 端 .click() 綁定完全不動。
|
|
|
|
| 3065 |
/* .reset-confirm 已於 2026-07-24 搬出 nav-col 改成全螢幕 modal,
|
| 3066 |
不再需要在收合狀態下隱藏;.result-nav-accordion 同日隨「統計比較
|
| 3067 |
分析」手風琴一起移除。 */
|
|
|
|
| 3068 |
.nav-col.collapsed .result-nav-divider { display: none !important; }
|
| 3069 |
/* 選擇器裡的 #result_nav_col 是為了贏過下方 nav-underline 樣式的
|
| 3070 |
`#result_nav_col .result-nav-btn`(1 個 id + 1 個 class = 1,1,0)。
|
|
|
|
| 4879 |
elem_id="nav_top_html",
|
| 4880 |
)
|
| 4881 |
|
| 4882 |
+
# 中段可捲動區:回首頁連結、結果導覽全部包進來,只有這個
|
| 4883 |
+
# Column 自己 overflow-y:auto(見 .nav-items-scroll CSS),
|
| 4884 |
+
# 不影響上下兩段固定區塊。
|
| 4885 |
with gr.Column(elem_classes=["nav-items-scroll"]) as nav_items_scroll:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4886 |
# 「回首頁」連結與其確認彈窗:換情境/回首頁都走這一套共用
|
| 4887 |
# 機制。情境是封閉式按鈕選擇,不透過對話框打字,所以「換
|
| 4888 |
# 情境」也統一走這顆按鈕,不恢復文字解析路徑。
|
|
|
|
| 5814 |
# 值,不管它是怎麼還原回來的。
|
| 5815 |
def on_scenario_pick(sc_num, chat_history, log_history, state):
|
| 5816 |
if state is None:
|
| 5817 |
+
yield (chat_history, log_history, state, gr.update(), gr.update(), gr.update(),
|
| 5818 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
| 5819 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
| 5820 |
gr.update())
|
|
|
|
| 5831 |
# 東西可看,不用透過 _populate_tabs 的檔案存在判斷來決定可見性。
|
| 5832 |
# 這幾個 visibility 只需要在第一個 yield 就切換一次,後續 yield
|
| 5833 |
# 沿用 gr.update() 不動即可,不用每次都重複賦值。
|
| 5834 |
+
yield (chat_history, log_history, state, gr.update(), gr.update(), gr.update(),
|
| 5835 |
gr.update(visible=False), gr.update(visible=True), gr.update(visible=True),
|
| 5836 |
gr.update(visible=True),
|
| 5837 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
|
|
|
| 5850 |
# 自己對它們下的 visible=False 更新互相打架、我們的更新輸了。
|
| 5851 |
# 等 workspace_row 的翻轉已經在前一個 yield 處理完、沉澱下來,
|
| 5852 |
# 這一個 yield 才不會再觸發同一種還原,我們的 False 才是最後贏家。
|
| 5853 |
+
yield (chat_history, log_history, state, gr.update(), _todo_update(state), gr.update(),
|
| 5854 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
| 5855 |
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
|
| 5856 |
gr.update(visible=False),
|
|
|
|
| 5866 |
state["current_step"] = 2
|
| 5867 |
state["state"] = "UPLOAD_WAIT"
|
| 5868 |
log_history = _log_append(log_history, "⏳ 等待上傳文本……")
|
| 5869 |
+
# 情境已選定,研究選擇區塊收起、換上傳卡片出現。這個 yield 離
|
| 5870 |
+
# workspace_row 自身的 True/False 翻轉已經隔了兩個 yield,不受
|
| 5871 |
+
# 本函式上方記錄的 Gradio 6 still-mounted-snapback 地雷影響,
|
| 5872 |
+
# 可以放心跟其他更新同批。對話視窗自此回歸純輸出角色。格式要求
|
| 5873 |
+
# 直接寫進上傳卡片本身(upload_hint_md),使用者不用往上捲回
|
| 5874 |
+
# 對話視窗找 AI 剛剛說過的規則——卡片本身就要自己講清楚。
|
|
|
|
|
|
|
| 5875 |
hint = (
|
| 5876 |
f"**格式要求**\n\n{sc_info['upload_prompt']}"
|
| 5877 |
)
|
| 5878 |
yield (chat_history, log_history, state, gr.update(visible=True),
|
| 5879 |
+
_todo_update(state), gr.update(value=hint),
|
| 5880 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
| 5881 |
gr.update(), gr.update(), gr.update(), gr.update(),
|
| 5882 |
gr.update(visible=False))
|
|
|
|
| 5885 |
_sc_btn.click(
|
| 5886 |
fn=functools.partial(on_scenario_pick, _sc_num),
|
| 5887 |
inputs=[chatbot, exec_log, session_state],
|
| 5888 |
+
outputs=[chatbot, exec_log, session_state, upload_row, app_header_html,
|
| 5889 |
upload_hint_md, homepage_col, workspace_row, result_nav_col, canvas_exec_col,
|
| 5890 |
metadata_row, canvas_idx_col, canvas_stat_col, canvas_report_col,
|
| 5891 |
scenario_select_row],
|
|
|
|
| 5895 |
outputs=_TAB_OUTPUTS,
|
| 5896 |
)
|
| 5897 |
|
| 5898 |
+
# ── 「開始新分析」:Bug1 修復——選定情境後先前完全沒有任何路徑能
|
| 5899 |
+
# 回頭變更,使用者選錯情境後卡住。這裡補上共用的重置機制:換情境
|
| 5900 |
+
# =重新開始,統一走這顆按鈕回到首頁重新選(不恢復對話框打字選
|
| 5901 |
+
# 情境的舊路徑)────────────────────────────────────────────────
|
| 5902 |
# Bug 4-C 修復(2026-07-30):Gradio 6 的 gr.Column/Row(visible=False)
|
| 5903 |
# 會把��元件整段從 DOM 卸載,不只是 CSS 隱藏。原本 on_reset_confirm
|
| 5904 |
# 在同一個 return 裡,一邊把 workspace_row 設 visible=False,一邊又要
|
|
|
|
| 5941 |
new_log, # exec_log
|
| 5942 |
state, # session_state
|
| 5943 |
gr.update(value=_build_header_html()), # app_header_html
|
|
|
|
| 5944 |
gr.update(visible=False), # upload_row(Phase 8:正式上傳入口改這張卡片)
|
| 5945 |
gr.update(visible=False), # reset_confirm_row(關掉確認彈窗自己)
|
| 5946 |
gr.update(visible=True), # homepage_col(Phase 8:重新開始=回到首頁選情境)
|
|
|
|
| 5957 |
).then(
|
| 5958 |
fn=on_reset_confirm,
|
| 5959 |
# 2026-07-30(2-C 第 5 項):chat_upload 這輪常駐隱藏、不再接任何
|
| 5960 |
+
# wiring(見 chat_upload_col 定義處註解),這裡把它從 outputs 移除。
|
| 5961 |
+
# E3(2026-08-05):scenario_btn_col 空 Column 已整段拿掉,一併從
|
| 5962 |
+
# outputs 移除。回傳 tuple 的元素個數/順序已同步調整為 8 個,
|
| 5963 |
+
# 跟這份 outputs 清單一一對應。
|
| 5964 |
outputs=[chatbot, exec_log, session_state, app_header_html,
|
| 5965 |
+
upload_row,
|
| 5966 |
reset_confirm_row, homepage_col, workspace_row],
|
| 5967 |
)
|
| 5968 |
|