381 lines
29 KiB
HTML
381 lines
29 KiB
HTML
<!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>
|
||
<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>
|
||
|
||
<!-- 引入獨立的 CSS 樣式表 -->
|
||
<link rel="stylesheet" href="/static/style.css" />
|
||
</head>
|
||
<body>
|
||
|
||
<h1>🎙️ Harmonic CMTS Admin</h1>
|
||
|
||
<div class="global-settings">
|
||
<label><strong>🌐 目標設備:</strong></label>
|
||
<input type="text" id="cmtsHost" placeholder="IP 地址" value="10.14.110.4" style="width: 130px;">
|
||
<input type="text" id="cmtsUser" placeholder="帳號" value="admin" style="width: 100px;">
|
||
<input type="password" id="cmtsPass" placeholder="密碼" value="nsgadmin" style="width: 100px;">
|
||
|
||
<div style="margin-left: 15px; display: flex; align-items: center; gap: 10px;">
|
||
<button onclick="connectWebSocket()" id="btnConnect" style="background-color: #27ae60;">連線至 CMTS</button>
|
||
<button onclick="disconnectWebSocket()" id="btnDisconnect" style="background-color: #c0392b; display: none;">斷開連線</button>
|
||
<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>
|
||
<button class="tab-btn" onclick="switchTab('config-tab', this)">⚙️ CMTS 設備配置</button>
|
||
<!-- 💡 新增:系統設定頁籤 -->
|
||
<button class="tab-btn" onclick="switchTab('settings-tab', this); openSystemSettings();">⚙️ 系統設定</button>
|
||
</div>
|
||
|
||
<!-- Tab 1: True SSH Terminal -->
|
||
<div id="cli-tab" class="tab-content active">
|
||
<div class="control-group">
|
||
<label><strong>快捷指令:</strong></label>
|
||
<select id="fixedCmd">
|
||
<option value="show cable modem">數據機狀態 (show cable modem)</option>
|
||
<option value="show cable rpd">RPD 狀態 (show cable rpd)</option>
|
||
<option value="show running-config | nomore">系統實時設定檔 (show running-config | nomore)</option>
|
||
</select>
|
||
<button onclick="injectCommand()" style="background-color: #8e44ad;">送出指令</button>
|
||
|
||
<div style="margin-left: auto; display: flex; gap: 8px;">
|
||
<button onclick="downloadTerminal()" style="background-color: #7f8c8d;">💾 下載紀錄</button>
|
||
</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>
|
||
<select id="queryTask" onchange="switchQueryTask()" style="width: 400px; max-width: 100%; font-weight: bold; font-size: 15px; padding: 8px; background-color: #f8f9fa;">
|
||
<option value="form-cm-query">🔎 Cable 狀態綜合查詢</option>
|
||
<option value="form-rpd-query">📡 RPD 狀態綜合查詢</option>
|
||
</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">
|
||
<label>目標設備 (Cable Modem MAC)</label>
|
||
<input type="text" id="queryTargetCm" placeholder="例: 6467.7240.4076 (留白則查詢全體)">
|
||
</div>
|
||
<div class="form-row">
|
||
<label>查詢動作 (Action)</label>
|
||
<select id="queryTypeCm" onchange="toggleQueryInputs('Cm')">
|
||
<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">
|
||
<button onclick="executeQuery('Cm')">執行查詢</button>
|
||
<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">
|
||
<label>目標設備 (RPD VC:VS)</label>
|
||
<input type="text" id="queryTargetRpd" placeholder="例: 13:0 (留白則查詢全體)">
|
||
</div>
|
||
<div class="form-row">
|
||
<label>查詢動作 (Action)</label>
|
||
<select id="queryTypeRpd" onchange="toggleQueryInputs('Rpd')">
|
||
<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">
|
||
<button onclick="executeQuery('Rpd')" style="background-color: #e67e22;">執行查詢</button>
|
||
<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>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tab 3: CMTS 設備配置 -->
|
||
<div id="config-tab" class="tab-content" style="overflow-y: auto; background-color: #fdfefe;">
|
||
<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: #c0392b; font-size: 16px; margin-right: 10px;">🛠️ 選擇配置任務:</label>
|
||
<select id="configTask" onchange="switchConfigTask()" style="width: 400px; max-width: 100%; font-weight: bold; font-size: 15px; padding: 8px; background-color: #fcf3f2; border-color: #fadbd8;">
|
||
<option value="form-bonding-config">⚠️ MAC Domain 狀態感知配置精靈</option>
|
||
<option value="form-full-config">🌳 完整設備配置樹狀圖</option>
|
||
</select>
|
||
<button id="btn-load-task" onclick="startConfigTask()" style="background-color: #95a5a6; color: white; margin-left: 10px; cursor: not-allowed;" disabled>🚀 載入任務</button>
|
||
</div>
|
||
|
||
<!-- 表單 3:MAC Domain 配置精靈 -->
|
||
<div id="form-bonding-config" class="task-form active">
|
||
<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;">
|
||
<label style="font-weight: bold; color: #d35400;">1. 目標 MAC Domain:</label>
|
||
<select id="cfgMacDomain" style="width: 150px; padding: 6px; font-weight: bold; border: 1px solid #fadbd8; border-radius: 4px; background-color: #fff;">
|
||
<option value="">請先點擊上方載入任務...</option>
|
||
</select>
|
||
<button onclick="fetchMacDomainConfig()" style="background-color: #d35400;">🔍 讀取現有配置</button>
|
||
<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">
|
||
<div class="form-row"><label>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>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>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>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>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>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>US Dynamic Bonding Group</label><select id="g_us_dyn" onchange="toggleGroupVisibility()"><option value="enabled">enabled</option><option value="disabled">disabled</option></select></div>
|
||
</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">
|
||
<div class="form-row"><label>Admin State</label><select id="b_admin"><option value="up">up</option><option value="down">down</option></select></div>
|
||
<div class="form-row"><label>DS Primary Set (0..157)</label><input type="text" id="b_ds_pri" placeholder="例: 0-2"></div>
|
||
<div class="form-row"><label>DS Non-Primary Set (0..157)</label><input type="text" id="b_ds_non_pri" placeholder="例: 3-4"></div>
|
||
<div class="form-row"><label>US PHY Channel Set (0..255)</label><input type="text" id="b_us_phy" placeholder="例: 0-3"></div>
|
||
<div class="form-row"><label>DS OFDM Set (0..7)</label><input type="text" id="b_ds_ofdm" placeholder="例: 0"></div>
|
||
<div class="form-row"><label>US OFDMA Set (0..1)</label><input type="text" id="b_us_ofdma" placeholder="例: 0"></div>
|
||
</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;">
|
||
<label>選擇要編輯的 DS Group:</label>
|
||
<select id="select_ds_group" onchange="loadDsGroupData()" style="width: 200px;"></select>
|
||
<input type="text" id="input_new_ds_group" placeholder="輸入新 Group 名稱 (例: D4A)" style="display: none; width: 200px;">
|
||
</div>
|
||
<div class="form-grid">
|
||
<div class="form-row"><label>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>Down Channel Set (0..157)</label><input type="text" id="ds_g_down" placeholder="例: 0-4"></div>
|
||
<div class="form-row"><label>OFDM Channel Set (0..7)</label><input type="text" id="ds_g_ofdm" placeholder="例: 0-1"></div>
|
||
<div class="form-row"><label>FDX OFDM Channel Set (0..7)</label><input type="text" id="ds_g_fdx" placeholder="例: 0-2"></div>
|
||
</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;">
|
||
<label>選擇要編輯的 US Group:</label>
|
||
<select id="select_us_group" onchange="loadUsGroupData()" style="width: 200px;"></select>
|
||
<input type="text" id="input_new_us_group" placeholder="輸入新 Group 名稱 (例: U4A)" style="display: none; width: 200px;">
|
||
</div>
|
||
<div class="form-grid">
|
||
<div class="form-row"><label>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>US Channel Set</label><input type="text" id="us_g_us" placeholder="例: 0-3.0"></div>
|
||
<div class="form-row"><label>OFDMA Channel Set (0..1)</label><input type="text" id="us_g_ofdma" placeholder="例: 0"></div>
|
||
<div class="form-row"><label>FDX OFDMA Channel Set (0..5)</label><input type="text" id="us_g_fdx" placeholder="例: 0-5"></div>
|
||
</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">
|
||
<button id="btnRevert" onclick="revertFormChanges()" style="background-color: #7f8c8d; color: white; margin-right: 15px;">
|
||
🔄 復原重填
|
||
</button>
|
||
<button onclick="generateMacDomainCLI()" style="background-color: #f39c12; color: white;">⚙️ 產生絕對路徑指令預覽</button>
|
||
<button id="btnDeployConfig" onclick="executeBondingConfig()" style="background-color: #c0392b; color: white; display: none;" disabled>🚀 正式套用設定</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 表單 4:完整設備配置樹狀圖 -->
|
||
<div id="form-full-config" class="task-form" style="display: none;">
|
||
<h3 style="display: flex; align-items: center; margin-bottom: 15px;">
|
||
🌳 完整設備配置樹狀圖
|
||
|
||
<!-- 🌟 一鍵掃描按鈕 -->
|
||
<button id="global-scan-btn" onclick="scanAllMissingOptions()" disabled
|
||
style="padding: 6px 12px; background-color: #8e44ad; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; font-weight: bold; margin-left: 20px; transition: all 0.3s; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
||
🔍 一鍵掃描缺失選項
|
||
</button>
|
||
|
||
<!-- 🌟 請在這裡加入這段全新的按鈕 -->
|
||
<button id="clearCacheBtn" onclick="clearVisibleCache()"
|
||
style="padding: 6px 12px; background-color: #f39c12; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; font-weight: bold; margin-left: 10px; transition: all 0.3s; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
||
🔄 清除畫面選項快取
|
||
</button>
|
||
|
||
<!-- 🌟 新增:掃描進度提示 -->
|
||
<span id="scan-status" style="color: #7f8c8d; font-size: 14px; margin-left: 15px; font-weight: normal;"></span>
|
||
|
||
<span id="loading-message" style="display: none; color: #f39c12; font-size: 14px; margin-left: 15px; font-weight: normal;">
|
||
⏳ 正在從設備抓取完整配置,可能需要 30~60 秒,請耐心稍候...
|
||
</span>
|
||
</h3>
|
||
|
||
<!-- 🌟 左右分屏容器 -->
|
||
<div id="split-container" style="display: flex; align-items: flex-start; width: 100%; position: relative;">
|
||
|
||
<!-- 左側:樹狀圖 (預設滿版,顯示預覽時會被 JS 改為 50%) -->
|
||
<!-- <div id="tree-container" style="width: 100%; background-color: #ffffff; padding: 15px; border-radius: 5px; border: 1px solid #e0e0e0; min-height: 100px; box-sizing: border-box; overflow-x: auto;">
|
||
<span style="color: #7f8c8d;">尚未載入資料。請點擊上方「載入任務」按鈕開始。</span>
|
||
</div> -->
|
||
|
||
<!-- 左側:樹狀圖 (預設滿版,顯示預覽時會被 JS 改為 50%) -->
|
||
<div id="tree-container" style="width: 100%; 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;">
|
||
<span style="color: #7f8c8d;">尚未載入資料。請點擊上方「載入任務」按鈕開始。</span>
|
||
</div>
|
||
|
||
<!-- 🖱️ 拖曳分隔線 (預設隱藏) -->
|
||
<div id="drag-resizer" style="display: none; width: 12px; cursor: col-resize; margin: 0 5px; flex-shrink: 0; align-items: center; justify-content: center; position: sticky; top: 20px; height: 400px; z-index: 10;" title="左右拖曳調整寬度">
|
||
<div style="width: 4px; height: 40px; background-color: #bdc3c7; border-radius: 2px;"></div>
|
||
</div>
|
||
|
||
<!-- 右側:CLI 預覽與執行結果 (預設隱藏,顯示時佔 50%) -->
|
||
<div id="side-cli-preview" style="width: 50%; position: sticky; top: 20px; background: #2c3e50; padding: 12px 15px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); display: none; border: 1px solid #34495e; box-sizing: border-box; flex-shrink: 0;">
|
||
|
||
<!-- 頂部標題列 -->
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
||
<h4 id="side-pane-title" style="color: #f1c40f; margin: 0; font-size: 15px;">⚠️ 即將寫入的指令</h4>
|
||
|
||
<div style="display: flex; align-items: center; gap: 10px;">
|
||
<!-- 預覽模式按鈕 -->
|
||
<button id="btn-side-cancel" onclick="hideSideCLI()" style="background-color: #7f8c8d; padding: 5px 12px; font-size: 13px;">取消</button>
|
||
<button id="btn-side-confirm" onclick="executeSideCLI()" style="background-color: #27ae60; padding: 5px 12px; font-size: 13px;">🚀 確認寫入</button>
|
||
|
||
<!-- 執行結果模式按鈕 (預設隱藏) -->
|
||
<button id="btn-side-close" onclick="hideSideCLI()" style="background-color: #3498db; padding: 5px 12px; font-size: 13px; display: none;">✅ 完成並關閉</button>
|
||
|
||
<div style="width: 1px; height: 20px; background-color: #7f8c8d; margin: 0 5px;"></div>
|
||
<span onclick="hideSideCLI()" style="color: #bdc3c7; font-size: 26px; cursor: pointer; line-height: 1;" title="關閉面板">×</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 模式一:指令預覽框 (可編輯) -->
|
||
<textarea id="side-cli-textarea" style="width: 100%; height: 400px; background: #1e1e1e; color: #ecf0f1; font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 14px; line-height: 1.5; padding: 12px 15px; border: 1px solid #7f8c8d; border-radius: 4px; box-sizing: border-box; white-space: pre; overflow-wrap: normal; overflow-x: scroll; margin-bottom: 0; display: block;"></textarea>
|
||
|
||
<!-- 模式二:執行結果框 (唯讀,升級字體與行高) -->
|
||
<div id="side-execution-result" style="width: 100%; height: 400px; background: #1e1e1e; color: #ecf0f1; font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 14px; line-height: 1.5; padding: 12px 15px; border: 1px solid #7f8c8d; border-radius: 4px; box-sizing: border-box; overflow-y: auto; margin-bottom: 0; display: none; white-space: pre-wrap; word-wrap: break-word;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 💡 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>
|
||
|
||
<button onclick="loadRealConfigForFilters()" style="background-color: #3498db; color: white; padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; margin-bottom: 15px;">
|
||
📥 載入設備配置以設定過濾
|
||
</button>
|
||
<span id="filter-loading-msg" style="display: none; color: #e67e22; margin-left: 10px; font-weight: bold;">⏳ 正在抓取配置,請稍候...</span>
|
||
|
||
<!-- 樹狀 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;">
|
||
<button onclick="saveSystemSettings()" style="background-color: #27ae60; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 15px; font-weight: bold;">
|
||
💾 儲存並套用設定
|
||
</button>
|
||
<span id="settings-status" style="margin-left: 15px; color: #27ae60; font-weight: bold; display: none;">✅ 設定已成功儲存!</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 獨立的彈出式輸出視窗 (Modal) -->
|
||
<div id="outputModal" class="modal-overlay" onclick="closeModal(event)">
|
||
<div class="modal-container" onclick="event.stopPropagation()">
|
||
<div class="modal-header">
|
||
<div class="modal-title">
|
||
<span>📄 執行結果</span>
|
||
<span id="modalTargetInfo" style="font-size: 13px; color: #bdc3c7; font-weight: normal;"></span>
|
||
</div>
|
||
<button class="modal-close" onclick="closeModal()">×</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<pre id="modalOutput" class="readonly-terminal">等待執行中...</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 引入獨立的 JavaScript 邏輯 -->
|
||
<script type="module" src="/static/app.js"></script>
|
||
|
||
</body>
|
||
</html>
|