2026-04-29 10:00:40 +00:00
<!DOCTYPE html>
< html lang = "zh-TW" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > Harmonic CMTS Manager< / title >
2026-05-19 10:25:10 +00:00
< link rel = "icon" type = "image/png" href = "/static/my_icon.png" >
2026-04-29 10:00:40 +00:00
< link rel = "stylesheet" href = "https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css" / >
< script src = "https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js" > < / script >
< script src = "https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js" > < / script >
2026-06-04 10:09:45 +00:00
< script src = "https://cdn.jsdelivr.net/npm/chart.js" > < / script >
2026-04-29 10:00:40 +00:00
2026-04-30 08:27:18 +00:00
<!-- 引入獨立的 CSS 樣式表 -->
2026-04-29 10:00:40 +00:00
< link rel = "stylesheet" href = "/static/style.css" / >
< / head >
< body >
2026-05-14 07:42:18 +00:00
<!-- 1. 標題加上 id="app - title" -->
< h1 id = "app-title" style = "cursor: default;" > 🎙️ Harmonic CMTS Admin< / h1 >
2026-04-29 10:00:40 +00:00
< div class = "global-settings" >
< label > < strong > 🌐 目標設備:< / strong > < / label >
2026-06-10 06:37:16 +00:00
<!-- 🌟 修改後 (徹底淨化) -->
2026-06-11 02:24:09 +00:00
< input type = "text" id = "cmtsHost" aria-label = "IP 地址" placeholder = "IP 地址" style = "width: 130px;" >
< input type = "text" id = "cmtsUser" aria-label = "帳號" placeholder = "帳號" style = "width: 100px;" >
< input type = "password" id = "cmtsPass" aria-label = "密碼" placeholder = "密碼" style = "width: 100px;" >
2026-04-29 10:00:40 +00:00
< div style = "margin-left: 15px; display: flex; align-items: center; gap: 10px;" >
2026-05-18 03:51:23 +00:00
< button onclick = "connectWebSocket()" id = "btnConnect" class = "btn-modern btn-connect" > 連線至 CMTS< / button >
< button onclick = "disconnectWebSocket()" id = "btnDisconnect" class = "btn-modern btn-disconnect" style = "display: none;" > 斷開連線< / button >
2026-04-29 10:00:40 +00:00
< span id = "wsStatus" style = "color: #7f8c8d; font-size: 14px; font-weight: bold;" > 狀態:未連線< / span >
< / div >
< / div >
< div class = "tabs" >
< button class = "tab-btn active" onclick = "switchTab('cli-tab', this)" > 💻 True SSH Terminal< / button >
< button class = "tab-btn" onclick = "switchTab('query-tab', this)" > 🔍 CMTS 狀態查詢< / button >
2026-05-27 03:33:01 +00:00
< button class = "tab-btn" onclick = "switchTab('config-tab', this)" > 🛠️ CMTS 設備配置< / button >
2026-04-30 08:27:18 +00:00
<!-- 💡 新增:系統設定頁籤 -->
< button class = "tab-btn" onclick = "switchTab('settings-tab', this); openSystemSettings();" > ⚙️ 系統設定< / button >
2026-05-26 10:30:10 +00:00
<!-- 💡 新增:備份與還原頁籤 -->
< button class = "tab-btn" onclick = "switchTab('backup-tab', this); loadBackupHistory();" > 💾 設備備份與還原< / button >
2026-04-29 10:00:40 +00:00
< / div >
<!-- Tab 1: True SSH Terminal -->
< div id = "cli-tab" class = "tab-content active" >
< div class = "control-group" >
< label > < strong > 快捷指令:< / strong > < / label >
2026-06-11 02:24:09 +00:00
< select id = "fixedCmd" aria-label = "選擇快捷指令" >
2026-05-19 10:25:10 +00:00
< option value = "show cable modem | nomore" > 數據機狀態 (show cable modem | nomore)< / option >
< option value = "show cable rpd | nomore" > RPD 狀態 (show cable rpd | nomore)< / option >
2026-04-29 10:00:40 +00:00
< option value = "show running-config | nomore" > 系統實時設定檔 (show running-config | nomore)< / option >
< / select >
2026-05-15 07:17:28 +00:00
< button onclick = "injectCommand()" class = "btn-modern btn-load" > 送出指令< / button >
2026-04-29 10:00:40 +00:00
< div style = "margin-left: auto; display: flex; gap: 8px;" >
2026-05-15 07:17:28 +00:00
< button onclick = "downloadTerminal()" class = "btn-modern btn-slate" > 💾 下載紀錄< / button >
2026-04-29 10:00:40 +00:00
< / div >
< / div >
< div id = "terminal-container" > < / div >
< / div >
<!-- Tab 2: CMTS 狀態查詢 -->
< div id = "query-tab" class = "tab-content" style = "overflow-y: auto; background-color: #f5f7fa;" >
< div class = "manager-container" >
< div class = "control-group" style = "background: #ffffff; padding: 15px 25px; border-radius: 8px; margin-bottom: 0; box-shadow: 0 2px 4px rgba(0,0,0,0.02); border: 1px solid #e2e8f0;" >
< label style = "font-weight: bold; color: #2c3e50; font-size: 16px; margin-right: 10px;" > 📌 選擇查詢任務:< / label >
2026-06-11 02:24:09 +00:00
< select id = "queryTask" onchange = "switchQueryTask()" aria-label = "選擇查詢任務" style = "width: 400px; max-width: 100%; font-weight: bold; font-size: 15px; padding: 8px; background-color: #f8f9fa;" >
2026-04-29 10:00:40 +00:00
< option value = "form-cm-query" > 🔎 Cable 狀態綜合查詢< / option >
< option value = "form-rpd-query" > 📡 RPD 狀態綜合查詢< / option >
2026-06-04 10:09:45 +00:00
< option value = "form-cm-diagnostics" > 🩺 CM 一鍵診斷中心< / option >
2026-04-29 10:00:40 +00:00
< / select >
< / div >
<!-- 表單 1: Cable 狀態綜合查詢 -->
< div id = "form-cm-query" class = "task-form active" >
< h3 style = "margin-top: 0; font-size: 18px; color: #2980b9; border-bottom: 2px solid #ecf0f1; padding-bottom: 10px; margin-bottom: 20px;" > Cable 狀態綜合查詢 (show cable modem...)< / h3 >
< div class = "form-grid" >
< div class = "form-row" >
2026-06-11 02:24:09 +00:00
< label for = "queryTargetCm" > 目標設備 (Cable Modem MAC)< / label >
2026-06-05 05:45:34 +00:00
< input type = "text" id = "queryTargetCm" list = "cm-mac-list" placeholder = "例: 6467.7240.4076 (留白則查詢全體)" >
< datalist id = "cm-mac-list" > < / datalist >
2026-04-29 10:00:40 +00:00
< / div >
< div class = "form-row" >
< label > 查詢動作 (Action)< / label >
2026-06-11 02:24:09 +00:00
< select id = "queryTypeCm" onchange = "toggleQueryInputs('Cm')" aria-label = "選擇 Cable Modem 查詢動作" >
2026-04-29 10:00:40 +00:00
< optgroup label = "Cable Modem 查詢 (支援特定目標或全體)" >
< option value = "base" > 基本狀態 (show cable modem)< / option >
< option value = "cpe" > CPE 資訊 (cpe)< / option >
< option value = "cpe_dhcp" > CPE DHCP (cpe dhcp)< / option >
< option value = "cpe_ipv6" > CPE IPv6 (cpe ipv6)< / option >
< option value = "bonding" > 綁定摘要 (bonding)< / option >
< option value = "bonding_ds" > 下行綁定 (bonding downstream)< / option >
< option value = "bonding_us" > 上行綁定 (bonding upstream)< / option >
< option value = "phy" > 實體層狀態 (phy)< / option >
< option value = "verbose" > 詳細資訊 (verbose)< / option >
< option value = "ofdm_profile" > OFDM Profile (ofdm-profile)< / option >
< option value = "ofdma_profile" > OFDMA Profile (ofdma-profile)< / option >
< option value = "dhcp_verbose" > DHCP 詳細資訊 (dhcp verbose)< / option >
< option value = "service_flow" > Service Flow (service-flow)< / option >
< option value = "service_flow_verbose" > Service Flow 詳細 (service-flow verbose)< / option >
< option value = "qos" > QoS 資訊 (qos)< / option >
< option value = "uptime" > 運行時間 (uptime)< / option >
< option value = "ugs" > UGS 資訊 (ugs)< / option >
< option value = "cm_status" > CM 狀態 (cm-status)< / option >
< / optgroup >
< optgroup label = "全域狀態查詢 (不分特定目標)" >
< option value = "partial_mode" > Partial Mode (partial-mode)< / option >
< option value = "hop" > Cable Hop (show cable hop)< / option >
< option value = "flap_list" > Flap List (show cable flap-list)< / option >
< option value = "flap_sum" > Flap Summary (show cable flap-sum)< / option >
< / optgroup >
< / select >
< / div >
< / div >
< div class = "form-actions" >
2026-05-15 07:17:28 +00:00
< button onclick = "executeQuery('Cm')" class = "btn-modern btn-load" > 執行查詢< / button >
2026-04-29 10:00:40 +00:00
< div style = "display: flex; align-items: center;" >
< input type = "checkbox" id = "debugQueryCm" style = "width: 18px; height: 18px; margin: 0; cursor: pointer;" >
< label for = "debugQueryCm" style = "cursor: pointer; color: #7f8c8d; margin-left: 8px; font-size: 14px;" > 🐞 顯示底層指令 (Debug)< / label >
< / div >
< / div >
< / div >
<!-- 表單 2: RPD 狀態綜合查詢 -->
< div id = "form-rpd-query" class = "task-form" >
< h3 style = "margin-top: 0; font-size: 18px; color: #e67e22; border-bottom: 2px solid #ecf0f1; padding-bottom: 10px; margin-bottom: 20px;" > RPD 狀態綜合查詢 (show cable rpd...)< / h3 >
< div class = "form-grid" >
< div class = "form-row" >
2026-06-11 02:24:09 +00:00
< label for = "queryTargetRpd" > 目標設備 (RPD VC:VS)< / label >
2026-06-05 05:45:34 +00:00
< input type = "text" id = "queryTargetRpd" list = "rpd-vcvs-list" placeholder = "例: 13:0 (留白則查詢全體)" >
< datalist id = "rpd-vcvs-list" > < / datalist >
2026-04-29 10:00:40 +00:00
< / div >
< div class = "form-row" >
< label > 查詢動作 (Action)< / label >
2026-06-11 02:24:09 +00:00
< select id = "queryTypeRpd" onchange = "toggleQueryInputs('Rpd')" aria-label = "選擇 RPD 查詢動作" >
2026-04-29 10:00:40 +00:00
< option value = "rpd_base" > 基本狀態 (show cable rpd)< / option >
< option value = "rpd_verbose" > 詳細資訊 (verbose)< / option >
< option value = "rpd_ptp_time" > PTP Time Property (ptp time-property)< / option >
< option value = "rpd_ptp_verbose" > PTP 詳細資訊 (ptp verbose)< / option >
< option value = "rpd_counters_map" > Counters Map (counters map)< / option >
< option value = "rpd_capabilities" > 能力資訊 (capabilities)< / option >
< option value = "rpd_video_counters" > Video Counters (video-channel counters)< / option >
< option value = "rpd_env_temp" > 環境溫度 (environment temperature)< / option >
< option value = "rpd_env_volt" > 環境電壓 (environment voltage)< / option >
< option value = "rpd_session" > Session (session)< / option >
< option value = "rpd_reset_history" > 重啟歷史 (reset-history)< / option >
< option value = "rpd_port_transceiver" > 光模組資訊 (port-transceiver)< / option >
< / select >
< / div >
< / div >
< div class = "form-actions" >
2026-05-15 07:17:28 +00:00
< button onclick = "executeQuery('Rpd')" class = "btn-modern btn-load" > 執行查詢< / button >
2026-04-29 10:00:40 +00:00
< div style = "display: flex; align-items: center;" >
< input type = "checkbox" id = "debugQueryRpd" style = "width: 18px; height: 18px; margin: 0; cursor: pointer;" >
< label for = "debugQueryRpd" style = "cursor: pointer; color: #7f8c8d; margin-left: 8px; font-size: 14px;" > 🐞 顯示底層指令 (Debug)< / label >
< / div >
< / div >
< / div >
2026-06-04 10:09:45 +00:00
<!-- 表單 3: CM 一鍵診斷中心 -->
< div id = "form-cm-diagnostics" class = "task-form" >
< h3 style = "margin-top: 0; font-size: 18px; color: #9b59b6; border-bottom: 2px solid #ecf0f1; padding-bottom: 10px; margin-bottom: 20px;" > CM 深度診斷與 MER 分析< / h3 >
<!-- 搜尋區塊 -->
< div class = "control-group" style = "background: #fdfefe; padding: 15px; border-radius: 6px; border: 1px solid #e8daef; margin-bottom: 20px;" >
2026-06-11 02:24:09 +00:00
< label for = "diagMacInput" style = "font-weight: bold; color: #2c3e50; font-size: 15px;" > 🎯 目標 CM MAC: < / label >
2026-06-05 05:45:34 +00:00
< input type = "text" id = "diagMacInput" list = "diag-cm-mac-list" placeholder = "例如: 6467.7240.4076" style = "width: 200px; padding: 6px 8px; font-size: 14px; margin: 0 10px; border: 1px solid #bdc3c7; border-radius: 4px;" >
< datalist id = "diag-cm-mac-list" > < / datalist >
2026-06-04 10:09:45 +00:00
< button onclick = "runCmDiagnostics()" id = "btnRunDiag" class = "btn-modern btn-scan" style = "background-color: #8e44ad;" > 🚀 執行深度診斷< / button >
< span id = "diagStatusMsg" style = "margin-left: 15px; font-weight: bold; color: #f39c12; display: none;" > ⏳ 正在透過 SSH 採集設備數據...< / span >
< / div >
<!-- 結果顯示區塊 (預設隱藏) -->
< div id = "diagResultArea" style = "display: none; gap: 20px; flex-direction: column;" >
<!-- 上半部:基本資訊與 PHY 狀態 -->
< div style = "display: flex; gap: 20px; flex-wrap: wrap;" >
<!-- 基本資訊卡片 -->
< div style = "flex: 1; min-width: 300px; background: #fff; padding: 15px 20px; border-radius: 8px; border: 1px solid #e2e8f0; border-top: 4px solid #3498db; box-shadow: 0 2px 4px rgba(0,0,0,0.02);" >
< h4 style = "margin-top: 0; color: #2c3e50; margin-bottom: 15px;" > 📄 基本資訊< / h4 >
< table style = "width: 100%; text-align: left; border-collapse: collapse; font-size: 14px;" >
< tr style = "border-bottom: 1px solid #ecf0f1;" > < th style = "padding: 8px 0; color: #7f8c8d; width: 40%;" > MAC Address< / th > < td id = "diagResMac" style = "font-weight: bold; color: #2c3e50;" > -< / td > < / tr >
< tr style = "border-bottom: 1px solid #ecf0f1;" > < th style = "padding: 8px 0; color: #7f8c8d;" > IP Address< / th > < td id = "diagResIp" style = "color: #2980b9; font-family: monospace;" > -< / td > < / tr >
< tr style = "border-bottom: 1px solid #ecf0f1;" > < th style = "padding: 8px 0; color: #7f8c8d;" > State< / th > < td id = "diagResState" style = "font-weight: bold;" > -< / td > < / tr >
< tr > < th style = "padding: 8px 0; color: #7f8c8d;" > CPE Count< / th > < td id = "diagResCpe" > -< / td > < / tr >
< / table >
< / div >
<!-- PHY 狀態卡片 -->
< div style = "flex: 1; min-width: 300px; background: #fff; padding: 15px 20px; border-radius: 8px; border: 1px solid #e2e8f0; border-top: 4px solid #2ecc71; box-shadow: 0 2px 4px rgba(0,0,0,0.02);" >
< h4 style = "margin-top: 0; color: #2c3e50; margin-bottom: 15px;" > 📡 TX / RX 綜合實體層狀態< / h4 >
< table style = "width: 100%; text-align: left; border-collapse: collapse; font-size: 14px;" >
< tr style = "border-bottom: 1px solid #ecf0f1;" >
< th style = "padding: 8px 0; color: #7f8c8d; width: 50%;" > Avg TX Power (dBmV)< / th >
< td id = "diagResTx" style = "font-weight: bold;" > -< / td >
< / tr >
< tr >
< th style = "padding: 8px 0; color: #7f8c8d;" > Avg RX Power (dBmV)< / th >
< td id = "diagResRx" style = "font-weight: bold;" > -< / td >
< / tr >
< / table >
<!-- 🌟 新增:上行通道標籤區塊 -->
< div style = "margin-top: 15px; padding-top: 15px; border-top: 1px dashed #bdc3c7;" >
< div style = "color: #7f8c8d; font-size: 13px; font-weight: bold; margin-bottom: 8px;" > 上行通道 SNR (dB) 分布:< / div >
< div id = "upstreamSnrContainer" style = "display: flex; flex-wrap: wrap; gap: 8px;" >
<!-- 動態生成標籤 -->
< / div >
< / div >
< / div >
< / div >
<!-- 下半部: Chart.js MER 圖表 -->
< div style = "background: #fff; padding: 15px 20px; border-radius: 8px; border: 1px solid #e2e8f0; border-top: 4px solid #9b59b6; box-shadow: 0 2px 4px rgba(0,0,0,0.02);" >
< h4 style = "margin-top: 0; color: #2c3e50; display: flex; flex-direction: column; gap: 10px; margin-bottom: 15px;" >
< span > 📊 OFDM MER 分布圖 < span style = "font-size: 13px; color: #7f8c8d; font-weight: normal;" > (點擊頻道切換圖表,最低 MER ≥ 41dB 判定為優)< / span > < / span >
<!-- 🌟 新增:動態 OFDM 頻道切換按鈕區塊 -->
< div id = "ofdmChannelTabs" style = "display: flex; gap: 10px; flex-wrap: wrap;" >
<!-- 動態生成按鈕 -->
< / div >
< / h4 >
< div style = "position: relative; height: 280px; width: 100%;" >
< canvas id = "merChart" > < / canvas >
< / div >
< / div >
< / div >
< / div >
2026-04-30 08:27:18 +00:00
< / div >
2026-06-04 10:09:45 +00:00
< / div >
2026-04-29 10:00:40 +00:00
<!-- Tab 3: CMTS 設備配置 -->
< div id = "config-tab" class = "tab-content" style = "overflow-y: auto; background-color: #fdfefe;" >
< div class = "manager-container" >
2026-05-14 07:42:18 +00:00
< div class = "control-group" style = "background: #ffffff; padding: 10px 15px; border-radius: 8px; margin-bottom: 0; box-shadow: 0 2px 4px rgba(0,0,0,0.02); border: 1px solid #e2e8f0;" >
2026-05-27 03:33:01 +00:00
< label style = "font-weight: bold; color: #c0392b; font-size: 16px; margin-right: 10px;" > 📌 選擇配置任務:< / label >
2026-06-11 02:24:09 +00:00
< select id = "configTask" aria-label = "選擇配置任務" onchange = "switchConfigTask()" style = "width: 400px; max-width: 100%; font-weight: bold; font-size: 15px; padding: 8px; background-color: #fcf3f2; border-color: #fadbd8;" >
2026-05-19 10:25:10 +00:00
<!-- 🌟 拆分為兩個獨立的選項 -->
< option value = "form-running-config" > 🌳 設備配置樹狀圖 (running-config)< / option >
< option value = "form-full-config" > 🌳 完整設備配置樹狀圖 (full configuration)< / option >
2026-04-29 10:00:40 +00:00
< option value = "form-bonding-config" > ⚠️ MAC Domain 狀態感知配置精靈< / option >
< / select >
2026-05-15 07:17:28 +00:00
< button id = "btn-load-task" onclick = "startConfigTask()" class = "btn-modern btn-load" style = "margin-left: 10px;" disabled > 🚀 載入任務< / button >
2026-04-29 10:00:40 +00:00
< / div >
2026-04-30 08:27:18 +00:00
<!-- 表單 3: MAC Domain 配置精靈 -->
< div id = "form-bonding-config" class = "task-form active" >
2026-04-29 10:00:40 +00:00
< h3 style = "margin-top: 0; font-size: 18px; color: #c0392b; border-bottom: 2px solid #ecf0f1; padding-bottom: 10px; margin-bottom: 20px;" > ⚠️ MAC Domain 狀態感知配置精靈< / h3 >
< div class = "control-group" style = "background: #fdf2e9; padding: 15px; border-radius: 6px; border: 1px solid #fadbd8;" >
2026-06-11 02:24:09 +00:00
< label for = "cfgMacDomain" style = "font-weight: bold; color: #d35400;" > 1. 目標 MAC Domain: < / label >
2026-06-05 05:45:34 +00:00
< input type = "text" id = "cfgMacDomain" list = "mac-domain-list" placeholder = "請先點擊上方載入任務..." style = "width: 220px; padding: 6px; font-weight: bold; border: 1px solid #fadbd8; border-radius: 4px; background-color: #fff;" >
< datalist id = "mac-domain-list" > < / datalist >
2026-05-15 07:17:28 +00:00
< button onclick = "fetchMacDomainConfig()" class = "btn-modern btn-load" > 🔍 讀取現有配置< / button >
2026-04-29 10:00:40 +00:00
< span id = "fetchStatus" style = "margin-left: 10px; font-size: 14px; color: #7f8c8d;" > 請先讀取設備狀態...< / span >
< / div >
< div id = "macDomainConfigArea" style = "display: none; margin-top: 20px;" >
<!-- Common Settings -->
< h4 style = "color: #2980b9; border-left: 4px solid #2980b9; padding-left: 8px;" > Common Settings< / h4 >
< div class = "form-grid" >
2026-06-11 02:24:09 +00:00
< div class = "form-row" > < label for = "g_ip_prov" > IP Provisioning Mode< / label > < select id = "g_ip_prov" > < option value = "alternate" > alternate< / option > < option value = "dual-stack" > dual-stack< / option > < option value = "ipv4-only" > ipv4-only< / option > < option value = "ipv6-only" > ipv6-only< / option > < / select > < / div >
< div class = "form-row" > < label for = "g_diplexer" > Diplexer Band Edge Control< / label > < select id = "g_diplexer" > < option value = "enabled" > enabled< / option > < option value = "disabled" > disabled< / option > < / select > < / div >
< div class = "form-row" > < label for = "g_bat31" > CM Battery Mode 3.1< / label > < select id = "g_bat31" > < option value = "enabled" > enabled< / option > < option value = "disabled" > disabled< / option > < / select > < / div >
< div class = "form-row" > < label for = "g_bat30" > CM Battery Mode 3.0< / label > < select id = "g_bat30" > < option value = "enabled" > enabled< / option > < option value = "disabled" > disabled< / option > < / select > < / div >
< div class = "form-row" > < label for = "g_docsis40" > DOCSIS 4.0< / label > < select id = "g_docsis40" > < option value = "enabled" > enabled< / option > < option value = "disabled" > disabled< / option > < / select > < / div >
< div class = "form-row" > < label for = "g_ds_dyn" > DS Dynamic Bonding Group< / label > < select id = "g_ds_dyn" onchange = "toggleGroupVisibility()" > < option value = "enabled" > enabled< / option > < option value = "disabled" > disabled< / option > < / select > < / div >
< div class = "form-row" > < label for = "g_us_dyn" > US Dynamic Bonding Group< / label > < select id = "g_us_dyn" onchange = "toggleGroupVisibility()" > < option value = "enabled" > enabled< / option > < option value = "disabled" > disabled< / option > < / select > < / div >
2026-04-29 10:00:40 +00:00
< / div >
<!-- [Basic] DS/US Channel Sets -->
< h4 style = "color: #27ae60; border-left: 4px solid #27ae60; padding-left: 8px; margin-top: 30px;" > [Basic] DS/US Channel Sets< / h4 >
< div class = "form-grid" >
2026-06-11 02:24:09 +00:00
< div class = "form-row" > < label for = "b_admin" > Admin State< / label > < select id = "b_admin" > < option value = "up" > up< / option > < option value = "down" > down< / option > < / select > < / div >
< div class = "form-row" > < label for = "b_ds_pri" > DS Primary Set (0..157)< / label > < input type = "text" id = "b_ds_pri" placeholder = "例: 0-2" > < / div >
< div class = "form-row" > < label for = "b_ds_non_pri" > DS Non-Primary Set (0..157)< / label > < input type = "text" id = "b_ds_non_pri" placeholder = "例: 3-4" > < / div >
< div class = "form-row" > < label for = "b_us_phy" > US PHY Channel Set (0..255)< / label > < input type = "text" id = "b_us_phy" placeholder = "例: 0-3" > < / div >
< div class = "form-row" > < label for = "b_ds_ofdm" > DS OFDM Set (0..7)< / label > < input type = "text" id = "b_ds_ofdm" placeholder = "例: 0" > < / div >
< div class = "form-row" > < label for = "b_us_ofdma" > US OFDMA Set (0..1)< / label > < input type = "text" id = "b_us_ofdma" placeholder = "例: 0" > < / div >
2026-04-29 10:00:40 +00:00
< / div >
<!-- [Static] Downstream Bonding Groups -->
< div id = "section_group_ds" style = "margin-top: 30px;" >
< h4 style = "color: #8e44ad; border-left: 4px solid #8e44ad; padding-left: 8px;" > [Static] Downstream Bonding Groups< / h4 >
< div class = "control-group" style = "background: #f4f6f7; padding: 10px; border-radius: 4px;" >
2026-06-11 02:24:09 +00:00
< label for = "select_ds_group" > 選擇要編輯的 DS Group: < / label >
2026-04-29 10:00:40 +00:00
< select id = "select_ds_group" onchange = "loadDsGroupData()" style = "width: 200px;" > < / select >
2026-06-11 02:24:09 +00:00
< input type = "text" id = "input_new_ds_group" aria-label = "輸入新 DS Group 名稱" placeholder = "輸入新 Group 名稱 (例: D4A)" style = "display: none; width: 200px;" >
2026-04-29 10:00:40 +00:00
< / div >
< div class = "form-grid" >
2026-06-11 02:24:09 +00:00
< div class = "form-row" > < label for = "ds_g_admin" > Admin State< / label > < select id = "ds_g_admin" > < option value = "up" > up< / option > < option value = "down" > down< / option > < / select > < / div >
< div class = "form-row" > < label for = "ds_g_down" > Down Channel Set (0..157)< / label > < input type = "text" id = "ds_g_down" placeholder = "例: 0-4" > < / div >
< div class = "form-row" > < label for = "ds_g_ofdm" > OFDM Channel Set (0..7)< / label > < input type = "text" id = "ds_g_ofdm" placeholder = "例: 0-1" > < / div >
< div class = "form-row" > < label for = "ds_g_fdx" > FDX OFDM Channel Set (0..7)< / label > < input type = "text" id = "ds_g_fdx" placeholder = "例: 0-2" > < / div >
2026-04-29 10:00:40 +00:00
< / div >
< / div >
<!-- [Static] Upstream Bonding Groups -->
< div id = "section_group_us" style = "margin-top: 30px;" >
< h4 style = "color: #f39c12; border-left: 4px solid #f39c12; padding-left: 8px;" > [Static] Upstream Bonding Groups< / h4 >
< div class = "control-group" style = "background: #f4f6f7; padding: 10px; border-radius: 4px;" >
2026-06-11 02:24:09 +00:00
< label for = "select_us_group" > 選擇要編輯的 US Group: < / label >
2026-04-29 10:00:40 +00:00
< select id = "select_us_group" onchange = "loadUsGroupData()" style = "width: 200px;" > < / select >
2026-06-11 02:24:09 +00:00
< input type = "text" id = "input_new_us_group" aria-label = "輸入新 US Group 名稱" placeholder = "輸入新 Group 名稱 (例: U4A)" style = "display: none; width: 200px;" >
2026-04-29 10:00:40 +00:00
< / div >
< div class = "form-grid" >
2026-06-11 02:24:09 +00:00
< div class = "form-row" > < label for = "us_g_admin" > Admin State< / label > < select id = "us_g_admin" > < option value = "up" > up< / option > < option value = "down" > down< / option > < / select > < / div >
< div class = "form-row" > < label for = "us_g_us" > US Channel Set< / label > < input type = "text" id = "us_g_us" placeholder = "例: 0-3.0" > < / div >
< div class = "form-row" > < label for = "us_g_ofdma" > OFDMA Channel Set (0..1)< / label > < input type = "text" id = "us_g_ofdma" placeholder = "例: 0" > < / div >
< div class = "form-row" > < label for = "us_g_fdx" > FDX OFDMA Channel Set (0..5)< / label > < input type = "text" id = "us_g_fdx" placeholder = "例: 0-5" > < / div >
2026-04-29 10:00:40 +00:00
< / div >
< / div >
<!-- CLI 預覽區塊 -->
< div id = "cliPreviewContainer" style = "display: none; background: #2c3e50; color: #ecf0f1; padding: 15px; border-radius: 6px; margin-top: 30px; margin-bottom: 20px; font-family: monospace; white-space: pre-wrap;" > < / div >
< div class = "form-actions" >
2026-05-15 07:17:28 +00:00
< button id = "btnRevert" onclick = "revertFormChanges()" class = "btn-modern btn-disconnect" style = "margin-right: 15px;" > 🔄 復原重填< / button >
< button onclick = "generateMacDomainCLI()" class = "btn-modern btn-scan" > ⚙️ 產生絕對路徑指令預覽< / button >
< button id = "btnDeployConfig" onclick = "executeBondingConfig()" class = "btn-modern btn-save" style = "display: none;" disabled > 🚀 正式套用設定< / button >
2026-04-29 10:00:40 +00:00
< / div >
< / div >
< / div >
2026-04-30 08:27:18 +00:00
2026-05-19 10:25:10 +00:00
<!-- 表單 4: 設備配置樹狀圖 (共用容器) -->
< div id = "form-tree-config" class = "task-form" style = "display: none;" >
2026-05-29 16:42:13 +00:00
<!-- 頂部:標題與按鈕區塊 (維持原樣) -->
2026-05-27 03:33:01 +00:00
< div style = "display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #ecf0f1; padding-bottom: 10px; margin-bottom: 15px; width: 100%;" >
< div style = "display: flex; align-items: center; gap: 15px;" >
< h3 style = "margin: 0; font-size: 16px; color: #2c3e50;" >
2026-05-29 16:42:13 +00:00
< span id = "tree-form-title" > 🌲 設備配置樹狀圖< / span >
2026-05-27 03:33:01 +00:00
< / h3 >
< span id = "scan-status" style = "color: #7f8c8d; font-size: 14px; font-weight: normal;" > < / span >
< span id = "loading-message" style = "display: none; color: #f39c12; font-size: 14px; font-weight: normal;" >
⏳ 正在從設備抓取完整配置,可能需要 30~60 秒,請耐心稍候...
< / span >
< / div >
< div style = "display: flex; gap: 10px;" >
2026-06-10 06:37:16 +00:00
< button id = "btn-scan-options" onclick = "scanMissingOptions()" class = "btn-modern btn-scan" disabled style = "display: none;" > 🚀 掃描缺失選項< / button >
< button id = "btn-clear-options" onclick = "clearOptionsCache()" class = "btn-modern btn-clear" style = "display: none;" > 🗑️ 清除選項快取< / button >
2026-05-27 03:33:01 +00:00
< / div >
< / div >
2026-04-30 10:52:55 +00:00
2026-05-29 16:42:13 +00:00
<!-- 🌟 左右分屏容器 (關鍵修改: align - items: stretch 讓左右強制等高) -->
< div id = "split-container" style = "display: flex; align-items: stretch; width: 100%; position: relative; gap: 10px;" >
2026-05-04 10:26:12 +00:00
2026-05-29 16:42:13 +00:00
<!-- 左側:樹狀圖 (保留 max - height: 600px, 超過才出捲軸) -->
< div id = "tree-container-running" class = "tree-view-instance" style = "flex: 1; min-width: 400px; background-color: #ffffff; padding: 15px; border-radius: 5px; border: 1px solid #e0e0e0; min-height: 100px; max-height: 600px; box-sizing: border-box; overflow-x: auto; overflow-y: auto;" >
2026-05-19 10:25:10 +00:00
< span style = "color: #7f8c8d;" > 尚未載入 Running 資料。請點擊上方「載入任務」按鈕開始。< / span >
< / div >
2026-05-08 08:50:12 +00:00
2026-05-29 16:42:13 +00:00
< div id = "tree-container-full" class = "tree-view-instance" style = "display: none; flex: 1; min-width: 400px; background-color: #ffffff; padding: 15px; border-radius: 5px; border: 1px solid #e0e0e0; min-height: 100px; max-height: 600px; box-sizing: border-box; overflow-x: auto; overflow-y: auto;" >
2026-05-19 10:25:10 +00:00
< span style = "color: #7f8c8d;" > 尚未載入 Full 資料。請點擊上方「載入任務」按鈕開始。< / span >
2026-05-04 10:26:12 +00:00
< / div >
2026-05-29 16:42:13 +00:00
<!-- 🖱️ 拖曳分隔線 (拔除寫死的 height: 400px) -->
< div id = "drag-resizer" style = "display: none; width: 12px; cursor: col-resize; flex-shrink: 0; align-items: center; justify-content: center; z-index: 10;" title = "左右拖曳調整寬度" >
2026-05-04 10:26:12 +00:00
< div style = "width: 4px; height: 40px; background-color: #bdc3c7; border-radius: 2px;" > < / div >
< / div >
2026-04-30 08:27:18 +00:00
2026-05-29 16:42:13 +00:00
<!-- 右側: CLI 預覽與執行結果外框 -->
< div id = "side-cli-preview" style = "flex: 1; min-width: 300px; max-width: 50%; display: none; box-sizing: border-box;" >
2026-05-04 10:26:12 +00:00
2026-05-29 16:42:13 +00:00
<!-- 🌟 內部黑底容器 (使用 flex column 與 height: 100% 完美填滿外框) -->
< div style = "display: flex; flex-direction: column; height: 100%; background: #1e1e1e; padding: 15px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); border: 1px solid #34495e; box-sizing: border-box;" >
2026-05-04 10:26:12 +00:00
2026-05-29 16:42:13 +00:00
<!-- 頂部標題列 -->
< div style = "display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; border-bottom: 1px solid #34495e; padding-bottom: 10px; flex-shrink: 0;" >
< h4 id = "side-pane-title" style = "color: #f1c40f; margin: 0; font-size: 15px;" > ⚠️ 即將寫入的指令< / h4 >
2026-06-01 08:20:34 +00:00
< div style = "display: flex; align-items: center; gap: 20px;" >
2026-05-29 16:42:13 +00:00
< button id = "btn-side-cancel" onclick = "hideSideCLI()" class = "btn-modern btn-disconnect" style = "padding: 5px 12px; font-size: 13px;" > 取消< / button >
< button id = "btn-side-confirm" onclick = "executeSideCLI()" class = "btn-modern btn-save" style = "padding: 5px 12px; font-size: 13px;" > 🚀 確認寫入< / button >
< button id = "btn-side-close" onclick = "hideSideCLI()" class = "btn-modern btn-load" style = "padding: 5px 12px; font-size: 13px; display: none;" > ✅ 完成並關閉< / button >
< / div >
2026-05-04 10:26:12 +00:00
< / div >
2026-05-29 16:42:13 +00:00
<!-- 模式一:指令預覽框 (🌟 拔除 height: 400px, 改用 flex: 1 自動填滿) -->
< textarea id = "side-cli-textarea" style = "flex: 1; width: 100%; background: transparent; color: #ecf0f1; font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 14px; line-height: 1.5; padding: 0; border: none; outline: none; box-sizing: border-box; white-space: pre; overflow-x: auto; overflow-y: auto; margin: 0; display: block; resize: none; min-height: 150px;" > < / textarea >
<!-- 模式二:執行結果框 (🌟 拔除 height: 400px, 改用 flex: 1 自動填滿) -->
< div id = "side-execution-result" style = "flex: 1; width: 100%; background: transparent; color: #ecf0f1; font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 14px; line-height: 1.5; padding: 0; border: none; box-sizing: border-box; overflow-x: auto; overflow-y: auto; margin: 0; display: none; white-space: pre; min-height: 150px;" > < / div >
2026-05-04 10:26:12 +00:00
< / div >
< / div >
2026-04-30 08:27:18 +00:00
< / div >
2026-05-04 10:26:12 +00:00
< / div >
2026-04-29 10:00:40 +00:00
< / div >
< / div >
2026-04-30 08:27:18 +00:00
<!-- 💡 Tab 4: 系統設定 (System Settings) -->
< div id = "settings-tab" class = "tab-content" style = "overflow-y: auto; background-color: #fdfefe; text-align: left;" >
< div class = "manager-container" style = "display: block; max-width: 100%;" >
< div class = "control-group" style = "background: #ffffff; padding: 25px 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); border: 1px solid #e2e8f0; text-align: left; display: block;" >
< h3 style = "margin-top: 0; font-size: 18px; color: #2c3e50; border-bottom: 2px solid #ecf0f1; padding-bottom: 10px; margin-bottom: 20px;" >
⚙️ 全域系統設定 (God Mode Filters)
< / h3 >
< div style = "background: #f8f9fa; border-left: 4px solid #3498db; padding: 12px 15px; border-radius: 4px; margin-bottom: 20px;" >
< p style = "color: #2c3e50; font-size: 15px; margin: 0;" >
請勾選您希望在「完整設備配置樹狀圖」中 < b > 隱藏< / b > 的設定項目。< br >
< span style = "color: #7f8c8d; font-size: 14px;" > 💡 點擊下方按鈕載入設備實時配置,您可以深入展開並勾選任何層級的節點進行過濾。< / span >
< / p >
< / div >
2026-05-19 10:25:10 +00:00
<!-- 🌟 新增:過濾器模式切換下拉選單 -->
< div style = "margin-bottom: 15px; display: flex; align-items: center; gap: 10px;" >
2026-06-11 02:24:09 +00:00
< label for = "filter-mode-select" style = "font-weight: bold; color: #2c3e50;" > 🎯 選擇要編輯的過濾器:< / label >
2026-05-19 10:25:10 +00:00
< select id = "filter-mode-select" onchange = "switchFilterMode()" style = "padding: 6px 10px; border-radius: 4px; border: 1px solid #bdc3c7; font-weight: bold; font-size: 14px; background-color: #fcf3f2; color: #c0392b;" >
< option value = "running" > Running 配置過濾器< / option >
< option value = "full" > Full 配置過濾器< / option >
< / select >
2026-05-27 03:33:01 +00:00
< button onclick = "loadRealConfigForFilters()" class = "btn-modern btn-load" >
2026-05-19 10:25:10 +00:00
📥 載入設備配置以設定過濾
< / button >
< span id = "filter-loading-msg" style = "display: none; color: #e67e22; margin-left: 10px; font-weight: bold;" > ⏳ 正在抓取配置,請稍候...< / span >
< / div >
2026-04-30 08:27:18 +00:00
<!-- 樹狀 Checkbox 容器 -->
< div id = "filter-checkboxes" style = "margin: 15px 0; border: 1px solid #bdc3c7; padding: 15px; border-radius: 5px; background-color: #ffffff; overflow-x: auto; max-height: 500px; overflow-y: auto; display: none;" >
< / div >
< div style = "margin-top: 20px; border-top: 1px solid #ecf0f1; padding-top: 20px;" >
2026-05-27 03:33:01 +00:00
< button onclick = "saveSystemSettings()" class = "btn-modern btn-connect" style = "padding: 10px 20px; font-size: 15px;" >
2026-04-30 08:27:18 +00:00
💾 儲存並套用設定
< / button >
< span id = "settings-status" style = "margin-left: 15px; color: #27ae60; font-weight: bold; display: none;" > ✅ 設定已成功儲存!< / span >
< / div >
< / div >
2026-06-05 10:29:04 +00:00
<!-- 🌟 新增:伺服器日誌管控面板 -->
< div class = "control-group" style = "background: #ffffff; padding: 25px 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); border: 1px solid #e2e8f0; text-align: left; display: block; margin-top: 20px;" >
< h3 style = "margin-top: 0; font-size: 18px; color: #2c3e50; border-bottom: 2px solid #ecf0f1; padding-bottom: 10px; margin-bottom: 20px;" >
🎛️ 伺服器日誌管控 (Server Log Management)
< / h3 >
< div style = "background: #f8f9fa; border-left: 4px solid #8e44ad; padding: 12px 15px; border-radius: 4px; margin-bottom: 20px;" >
< p style = "color: #2c3e50; font-size: 15px; margin: 0;" >
在此動態調整各個後端模組的日誌輸出等級。設定會立即生效,< b > 無需重啟伺服器< / b > 。< br >
< span style = "color: #7f8c8d; font-size: 14px;" > 💡 建議平時保持在 < b > INFO< / b > 或 < b > ERROR< / b > ,僅在需要排查問題時開啟 < b > DEBUG< / b > 。< / span >
< / p >
< / div >
<!-- 矩陣式下拉選單容器 -->
< div id = "log-settings-container" style = "display: grid; grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); gap: 15px;" >
< span style = "color: #7f8c8d;" > ⏳ 正在載入日誌設定...< / span >
< / div >
< / div >
2026-06-15 10:04:20 +00:00
<!-- 🌟 新增:🎙️ 系統實時日誌面板 (System Live Logs) -->
< div class = "control-group" style = "background: #ffffff; padding: 25px 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); border: 1px solid #e2e8f0; text-align: left; display: block; margin-top: 20px;" >
< h3 style = "margin-top: 0; font-size: 18px; color: #2c3e50; border-bottom: 2px solid #ecf0f1; padding-bottom: 10px; margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center;" >
< span > 🎙️ 系統實時日誌 (System Live Logs)< / span >
< div style = "display: flex; align-items: center; gap: 15px;" >
< span id = "log-ws-status" style = "font-size: 13px; color: #7f8c8d; font-weight: normal;" > 狀態:已暫停 ⚪< / span >
< button id = "btnToggleLog" onclick = "toggleLogStream()" class = "btn-modern btn-disconnect" style = "padding: 4px 12px; font-size: 12px;" > 🔌 啟動監聽< / button >
< / div >
< / h3 >
<!-- 日誌終端機容器 -->
< div id = "log-terminal-container" style = "width: 100%; height: 300px; border-radius: 6px; background-color: #1e1e1e; box-shadow: inset 0 0 10px rgba(0,0,0,0.8); overflow: hidden; position: relative; padding: 10px; box-sizing: border-box;" > < / div >
< / div >
2026-04-30 08:27:18 +00:00
< / div >
< / div >
2026-05-26 10:30:10 +00:00
<!-- 💡 Tab 5: 設備備份與還原 -->
< div id = "backup-tab" class = "tab-content" style = "overflow-y: auto; background-color: #f5f7fa;" >
< div class = "manager-container" >
<!-- 上半部:建立新快照 -->
2026-05-28 14:24:57 +00:00
< div class = "control-group" style = "background: #ffffff; padding: 25px 30px; border-radius: 8px; margin-bottom: 15px; box-shadow: 0 2px 4px rgba(0,0,0,0.02); border: 1px solid #e2e8f0; display: block;" >
<!-- 💡 修正:移除負 margin, 讓底線與內容邊界對齊 (如同系統設定頁籤) -->
< div style = "display: flex; justify-content: flex-start; align-items: center; gap: 15px; border-bottom: 2px solid #ecf0f1; padding-bottom: 12px; margin-bottom: 20px;" >
< h3 style = "margin: 0; font-size: 18px; color: #2c3e50; display: flex; align-items: center; gap: 8px;" >
📸 建立新快照
< / h3 >
< button onclick = "createSnapshot()" id = "btnCreateSnapshot" class = "btn-modern btn-save" style = "padding: 8px 20px; font-size: 14px; background-color: #2980b9; border: none; box-shadow: 0 2px 4px rgba(41, 128, 185, 0.3);" >
🚀 立即執行備份
< / button >
< span id = "backup-status-msg" style = "color: #e67e22; font-size: 14px; display: none; font-weight: bold;" >
⏳ 正在連線設備並抓取設定,請稍候...
< / span >
< / div >
<!-- 表單網格區 -->
< div style = "display: grid; grid-template-columns: 2fr 1fr; gap: 20px; margin-bottom: 15px;" >
< div >
2026-06-11 02:24:09 +00:00
< label for = "snapshotName" style = "display: block; font-size: 14px; font-weight: bold; color: #34495e; margin-bottom: 8px;" >
2026-05-28 14:24:57 +00:00
快照名稱 < span style = "color: #e74c3c;" > *< / span >
< / label >
< input type = "text" id = "snapshotName" placeholder = "例如: 例行備份、升級前備份" style = "width: 100%; padding: 10px 12px; border: 1px solid #bdc3c7; border-radius: 5px; box-sizing: border-box; font-size: 14px; transition: border-color 0.2s;" >
< / div >
< div >
2026-06-11 02:24:09 +00:00
< label for = "backupConfigType" style = "display: block; font-size: 14px; font-weight: bold; color: #34495e; margin-bottom: 8px;" >
2026-05-28 14:24:57 +00:00
配置類型
< / label >
< select id = "backupConfigType" style = "width: 100%; padding: 10px 12px; border: 1px solid #bdc3c7; border-radius: 5px; box-sizing: border-box; font-size: 14px; background-color: #f8f9fa; cursor: pointer;" >
< option value = "running" > Running Config (運行中配置)< / option >
< option value = "full" > Full Config (完整配置)< / option >
< / select >
< / div >
< / div >
<!-- 描述區 -->
< div style = "margin-bottom: 0;" >
< label style = "display: block; font-size: 14px; font-weight: bold; color: #34495e; margin-bottom: 8px;" >
備份描述 < span style = "color: #7f8c8d; font-weight: normal; font-size: 13px;" > (選填)< / span >
< / label >
< input type = "text" id = "snapshotDescription" placeholder = "請簡述此次備份的目的,例如:升級至 Unify FDD firmware, 驗收通過" style = "width: 100%; padding: 10px 12px; border: 1px solid #bdc3c7; border-radius: 5px; box-sizing: border-box; font-size: 14px;" >
2026-05-26 10:30:10 +00:00
< / div >
< / div >
<!-- 下半部:歷史紀錄列表 -->
2026-05-28 14:24:57 +00:00
< div class = "control-group" style = "background: #ffffff; padding: 25px 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.02); border: 1px solid #e2e8f0; display: block;" >
2026-05-27 03:33:01 +00:00
2026-05-28 14:24:57 +00:00
<!-- 💡 修正:移除負 margin, 讓底線與內容邊界對齊 -->
< div style = "display: flex; align-items: center; gap: 20px; border-bottom: 2px solid #ecf0f1; padding-bottom: 12px; margin-bottom: 20px; flex-wrap: wrap;" >
< h3 style = "margin: 0; font-size: 18px; color: #2c3e50; display: flex; align-items: center; gap: 8px; white-space: nowrap;" >
📁 歷史備份紀錄
2026-05-27 03:33:01 +00:00
< / h3 >
2026-05-28 14:24:57 +00:00
< div style = "display: flex; gap: 10px; align-items: center;" >
2026-06-11 02:24:09 +00:00
< input type = "text" id = "filter-keyword" aria-label = "搜尋名稱或描述" placeholder = "🔍 搜尋名稱或描述..." class = "edit-input" style = "width: 180px; padding: 6px 10px; border: 1px solid #bdc3c7; border-radius: 4px; font-size: 13px;" onkeyup = "applyBackupFilters()" >
2026-05-28 14:24:57 +00:00
2026-06-11 02:24:09 +00:00
< select id = "filter-type" aria-label = "選擇過濾類型" class = "edit-input" style = "width: 110px; padding: 6px 10px; border: 1px solid #bdc3c7; border-radius: 4px; font-size: 13px;" onchange = "applyBackupFilters()" >
2026-05-28 14:24:57 +00:00
< option value = "" > 所有類型< / option >
< option value = "running" > running< / option >
< option value = "full" > full< / option >
< / select >
<!-- 💡 修正:回歸原生 type="date",交由系統決定語系顯示 -->
< div style = "display: flex; align-items: center; gap: 5px; border-left: 1px solid #bdc3c7; padding-left: 10px; margin-left: 2px;" >
2026-06-11 02:24:09 +00:00
< input type = "date" id = "filter-date-start" aria-label = "開始日期" class = "edit-input" style = "padding: 5px 8px; border: 1px solid #bdc3c7; border-radius: 4px; font-size: 13px; color: #7f8c8d;" onchange = "applyBackupFilters()" >
2026-05-28 14:24:57 +00:00
< span style = "color: #7f8c8d; font-size: 13px;" > 至< / span >
2026-06-11 02:24:09 +00:00
< input type = "date" id = "filter-date-end" aria-label = "結束日期" class = "edit-input" style = "padding: 5px 8px; border: 1px solid #bdc3c7; border-radius: 4px; font-size: 13px; color: #7f8c8d;" onchange = "applyBackupFilters()" >
2026-05-28 14:24:57 +00:00
< / div >
< button onclick = "loadBackupHistory()" class = "btn-modern btn-slate" style = "margin-left: 5px; padding: 8px 20px; font-size: 14px;" >
🔄 重新整理
< / button >
< / div >
2026-05-26 10:30:10 +00:00
< / div >
2026-05-28 14:24:57 +00:00
<!-- 表格區塊 -->
2026-05-26 10:30:10 +00:00
< table style = "width: 100%; border-collapse: collapse; text-align: left;" >
< thead >
< tr style = "background-color: #f8f9fa; border-bottom: 2px solid #bdc3c7;" >
2026-05-28 14:24:57 +00:00
< th style = "padding: 10px; color: #34495e; width: 20%;" > 時間< / th >
2026-06-15 06:45:54 +00:00
< th style = "padding: 10px; color: #34495e; width: 8%; text-align: center;" > 保護< / th > <!-- 🌟 新增:獨立的保護欄位 -->
< th style = "padding: 10px; color: #34495e; width: 22%;" > 快照名稱< / th >
< th style = "padding: 10px; color: #34495e; width: 22%;" > 描述< / th >
2026-05-28 14:24:57 +00:00
< th style = "padding: 10px; color: #34495e; width: 10%;" > 類型< / th >
2026-06-15 06:45:54 +00:00
< th style = "padding: 10px; color: #34495e; text-align: right; width: 18%;" > 操作< / th >
2026-05-26 10:30:10 +00:00
< / tr >
< / thead >
< tbody id = "backup-history-tbody" >
< tr >
2026-05-28 14:24:57 +00:00
< td colspan = "5" style = "padding: 20px; text-align: center; color: #7f8c8d;" > 請點擊「重新整理」載入歷史紀錄...< / td >
2026-05-26 10:30:10 +00:00
< / tr >
< / tbody >
< / table >
< / div >
< / div >
< / div >
2026-04-29 10:00:40 +00:00
<!-- 獨立的彈出式輸出視窗 (Modal) -->
2026-06-01 08:20:34 +00:00
< div id = "outputModal" class = "modal-overlay" >
< div class = "modal-container" >
2026-04-29 10:00:40 +00:00
< div class = "modal-header" >
2026-06-01 08:20:34 +00:00
< div class = "modal-title" style = "flex-grow: 1; display: flex; align-items: center;" >
2026-04-29 10:00:40 +00:00
< span > 📄 執行結果< / span >
2026-06-01 08:20:34 +00:00
< span id = "modalTargetInfo" style = "font-size: 13px; color: #bdc3c7; font-weight: normal; margin-left: 10px; flex-grow: 1;" > < / span >
< / div >
< div id = "modal-action-container" style = "display: flex; gap: 20px; align-items: center;" >
< button id = "btn-modal-close" class = "btn-modern btn-disconnect" onclick = "closeModal()" > 關閉視窗< / button >
2026-04-29 10:00:40 +00:00
< / div >
< / div >
< div class = "modal-body" >
< pre id = "modalOutput" class = "readonly-terminal" > 等待執行中...< / pre >
< / div >
< / div >
< / div >
2026-06-08 09:01:55 +00:00
<!-- 🌟 新增: God Mode 授權視窗 (Modal) -->
< div id = "godModeModal" class = "modal-overlay" >
<!-- 將對話框置中,限制最大寬度,改變一下配色風格 -->
< div class = "modal-container" style = "max-width: 350px; height: auto; transform: translateY(20px);" >
< div class = "modal-header" style = "background-color: #8e44ad; border-bottom: none;" >
< div class = "modal-title" style = "justify-content: center; width: 100%;" >
< span > 🔐 系統進階授權< / span >
< / div >
< / div >
< div class = "modal-body" style = "padding: 25px 20px !important; background: #fdfefe; text-align: center;" >
< p style = "color: #2c3e50; font-size: 14px; margin-top: 0; margin-bottom: 20px; font-weight: bold;" >
請輸入維護者密碼以解鎖隱藏功能
< / p >
< input type = "password" id = "godModePassword" placeholder = "Enter Password..." style = "width: 100%; box-sizing: border-box; padding: 12px; border: 2px solid #bdc3c7; border-radius: 6px; font-size: 16px; text-align: center; margin-bottom: 10px; transition: border-color 0.2s; outline: none;" onfocus = "this.style.borderColor='#8e44ad'" onblur = "this.style.borderColor='#bdc3c7'" >
< span id = "god-mode-error" style = "color: #e74c3c; font-size: 13px; font-weight: bold; display: block; min-height: 18px; margin-bottom: 15px;" > < / span >
< div style = "display: flex; gap: 15px; justify-content: center;" >
< button onclick = "closeGodModeModal()" class = "btn-modern btn-disconnect" style = "flex: 1; padding: 10px;" > 取消< / button >
< button id = "btn-unlock-godmode" onclick = "verifyGodMode()" class = "btn-modern btn-save" style = "flex: 1; background-color: #8e44ad; padding: 10px;" > 🚀 解鎖< / button >
< / div >
< / div >
< / div >
< / div >
2026-04-30 08:27:18 +00:00
<!-- 引入獨立的 JavaScript 邏輯 -->
2026-05-13 03:09:19 +00:00
< script type = "module" src = "/static/app.js" > < / script >
2026-04-30 08:27:18 +00:00
2026-04-29 10:00:40 +00:00
< / body >
< / html >