From 19d5a30305a256475ad4dbb68c6a2f26f0669be9 Mon Sep 17 00:00:00 2001 From: swpa Date: Fri, 5 Jun 2026 13:45:34 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20UX=20=E8=BC=B8=E5=85=A5=E6=AC=84?= =?UTF-8?q?=E4=BD=8D=E5=84=AA=E5=8C=96=EF=BC=81=E9=80=8F=E9=81=8E=20HTML5?= =?UTF-8?q?=20=20=E7=B5=90=E5=90=88=E8=83=8C=E6=99=AF=E9=9D=9E?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=8A=93=E5=8F=96=EF=BC=8C=E4=BF=9D=E7=95=99?= =?UTF-8?q?=E5=8E=9F=E6=9C=AC=E7=B4=94=E6=96=87=E5=AD=97=E8=BC=B8=E5=85=A5?= =?UTF-8?q?=E7=9A=84=E5=BD=88=E6=80=A7=EF=BC=88=E6=94=AF=E6=8F=B4=E6=A8=A1?= =?UTF-8?q?=E7=B3=8A=E6=90=9C=E5=B0=8B=E8=88=87=E6=89=8B=E5=8B=95=E8=BC=B8?= =?UTF-8?q?=E5=85=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- all_code.txt | 224 ++++++++++- index.html | 14 +- routers/query.py | 53 +++ static/api.js | 13 + static/app.js | 102 ++++- static/mac-domain.js | 33 +- static/style.css | 3 +- static/terminal.js | 6 + target_code.txt | 935 +------------------------------------------ 9 files changed, 423 insertions(+), 960 deletions(-) diff --git a/all_code.txt b/all_code.txt index 70b8f27..78b44b7 100644 --- a/all_code.txt +++ b/all_code.txt @@ -751,7 +751,8 @@ FILE: index.html
- + +
@@ -800,7 +801,8 @@ FILE: index.html
- + +
@@ -836,7 +838,8 @@ FILE: index.html
- + +
@@ -920,9 +923,8 @@ FILE: index.html
- + + 請先讀取設備狀態...
@@ -2056,6 +2058,19 @@ export async function apiExecuteQuery(queryType, target, host, username, passwor return response.json(); } +// 🌟 新增:動態抓取設備清單 API +export async function apiListCms(host, username, password) { + const url = `/api/v1/list-cms?host=${encodeURIComponent(host)}&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`; + const response = await fetch(url); + return response.json(); +} + +export async function apiListRpds(host, username, password) { + const url = `/api/v1/list-rpds?host=${encodeURIComponent(host)}&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`; + const response = await fetch(url); + return response.json(); +} + // ========================================== // 6. 專門處理串流的 API 呼叫函數 (UI 可以即時更新) // ========================================== @@ -2123,7 +2138,8 @@ import { apiGetTreeFilters, apiSaveTreeFilters, apiSyncLeafOptionsStream, apiGetCmtsVersion, apiGetScanStatus, apiGetLockStatus, - apiGetCmDiagnostics + apiGetCmDiagnostics, + apiListCms, apiListRpds } from './api.js'; // 3. 共用工具模組 (Utils) @@ -2384,12 +2400,97 @@ function switchTab(tabId, element) { if(tabId === 'cli-tab' && typeof fitAddon !== 'undefined' && fitAddon) setTimeout(() => fitAddon.fit(), 50); } +// 切換「設備查詢」內的子任務表單 +// ============================================================================ +// 🌟 設備查詢動態清單快取 (新增) +// ============================================================================ +let cachedDeviceLists = { cms: null, rpds: null, host: null }; + // 切換「設備查詢」內的子任務表單 function switchQueryTask() { document.querySelectorAll('#query-tab .task-form').forEach(form => form.classList.remove('active')); const selectedTaskId = document.getElementById('queryTask').value; const targetForm = document.getElementById(selectedTaskId); if (targetForm) targetForm.classList.add('active'); + + // 🌟 觸發背景動態載入 Datalist + loadDynamicDatalist(selectedTaskId); +} + +// 🌟 新增:背景載入 Datalist 邏輯 +async function loadDynamicDatalist(taskType) { + // 若尚未連線,則不觸發背景抓取 (不跳警告,默默 return) + if (!isConnected) return; + + const host = document.getElementById('cmtsHost').value.trim(); + const user = document.getElementById('cmtsUser').value.trim(); + const pass = document.getElementById('cmtsPass').value.trim(); + if (!host || !user || !pass) return; + + // 若切換了設備 IP,清空舊快取 + if (cachedDeviceLists.host !== host) { + cachedDeviceLists = { cms: null, rpds: null, host: host }; + } + + if (taskType === 'form-cm-query' || taskType === 'form-cm-diagnostics') { + const inputId = taskType === 'form-cm-query' ? 'queryTargetCm' : 'diagMacInput'; + const listId = taskType === 'form-cm-query' ? 'cm-mac-list' : 'diag-cm-mac-list'; + const defaultPlaceholder = taskType === 'form-cm-query' ? "例: 6467.7240.4076 (留白則查詢全體)" : "例如: 6467.7240.4076"; + + await fetchAndBindList('cms', inputId, listId, defaultPlaceholder, host, user, pass); + } else if (taskType === 'form-rpd-query') { + await fetchAndBindList('rpds', 'queryTargetRpd', 'rpd-vcvs-list', "例: 13:0 (留白則查詢全體)", host, user, pass); + } +} + +// 🌟 新增:執行 API 呼叫與 UX 狀態切換 +async function fetchAndBindList(type, inputId, listId, defaultPlaceholder, host, user, pass) { + const inputEl = document.getElementById(inputId); + const datalistEl = document.getElementById(listId); + if (!inputEl || !datalistEl) return; + + // 如果已經有快取,直接綁定並結束 + if (cachedDeviceLists[type]) { + populateDatalist(datalistEl, cachedDeviceLists[type]); + return; + } + + // 狀態 1:發出請求前 (鎖定輸入框,提示載入中) + inputEl.disabled = true; + inputEl.placeholder = "🔄 載入設備清單中..."; + inputEl.style.backgroundColor = "#fdfefe"; + + try { + let data; + if (type === 'cms') { + data = await apiListCms(host, user, pass); + cachedDeviceLists.cms = data.cms || []; + } else { + data = await apiListRpds(host, user, pass); + cachedDeviceLists.rpds = data.rpds || []; + } + + // 狀態 2:請求成功 (塞入選項,恢復輸入框) + populateDatalist(datalistEl, cachedDeviceLists[type]); + inputEl.placeholder = defaultPlaceholder; + } catch (error) { + console.error(`[Background Task] Failed to load ${type}:`, error); + // 狀態 3:請求失敗 (提示失敗,但仍解鎖讓使用者手動輸入) + inputEl.placeholder = "⚠️ 清單載入失敗,請手動輸入"; + } finally { + inputEl.disabled = false; + inputEl.style.backgroundColor = ""; // 恢復預設背景色 + } +} + +// 🌟 新增:將陣列轉換為