// --- static/api.js --- // ========================================== // 1. 鎖定管理 (Lock Management) // ========================================== export async function apiAcquireLock(path, userId, username, host) { const res = await fetch('/api/v1/locks/acquire', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path, user_id: userId, username, host }) }); const data = await res.json(); return { status: res.status, data }; } export async function apiReleaseLock(path, userId, host) { return fetch('/api/v1/locks/release', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path, user_id: userId, host }) }); } export async function apiSendHeartbeat(path, userId, host) { return fetch('/api/v1/locks/heartbeat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path, user_id: userId, host }) }); } export async function apiGetLockStatus(host) { // 帶入 host 參數,實現 IP 隔離查詢 const url = host ? `/api/v1/locks/status?host=${encodeURIComponent(host)}` : '/api/v1/locks/status'; const response = await fetch(url); return response.json(); } // ========================================== // 2. 樹狀圖與選項快取 (Tree & Options) // ========================================== export async function apiGetFullConfig(host, username, password, skipFilter = false, configType = 'running') { // 🌟 將 config_type 加入 URL 參數中 let url = `/api/v1/cmts-full-config?host=${encodeURIComponent(host)}&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}&config_type=${configType}`; if (skipFilter) url += '&skip_filter=true'; const response = await fetch(url); return response.json(); } // 🌟 1. 取得選項快取 (加上 configType 查詢參數) export async function apiGetLeafOptions(host, configType = 'running') { const response = await fetch(`/api/v1/cmts-leaf-options?host=${encodeURIComponent(host)}&config_type=${configType}`); return response.json(); } // 🌟 2. 同步選項快取 (將 config_type 塞入 Body) export async function apiSyncLeafOptions(host, paths, configType = 'running') { return fetch('/api/v1/cmts-leaf-options/sync', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ host, leaf_paths: paths, config_type: configType }) }); } // 🌟 3. 清除快取 (加上 configType 查詢參數) export async function apiClearCache(host, paths, configType = 'running') { const response = await fetch(`/api/v1/clear_cache?host=${encodeURIComponent(host)}&config_type=${configType}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(paths) }); if (!response.ok) throw new Error(`伺服器回應錯誤: ${response.status}`); return response.json(); } export async function apiGetCmtsVersion(host, username, password) { const url = `/api/v1/cmts-version?host=${encodeURIComponent(host)}&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`; const response = await fetch(url); return response.json(); } export async function apiGetScanStatus(host, configType = 'running') { try { const response = await fetch(`/api/v1/scan-status?host=${encodeURIComponent(host)}&config_type=${configType}`); const data = await response.json(); return data.is_scanning; } catch (e) { return false; } } // ========================================== // 3. 指令生成與執行 (CLI Generation & Execution) // ========================================== export async function apiGenerateCli(diffs, interfaces) { const response = await fetch('/api/v1/cmts-generate-cli', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ diffs, interfaces_with_admin_state: interfaces }) }); return response.json(); } export async function apiExecuteConfig(script, host, username, password) { const response = await fetch('/api/v1/cmts-config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ script, host, username, password }) }); return response.json(); } // ========================================== // 4. 系統設定與過濾器 (System Settings) // ========================================== // 🌟 加上 configType 參數 export async function apiGetTreeFilters(configType = 'running') { const response = await fetch(`/api/v1/settings/tree-filters?config_type=${configType}`); return response.json(); } // 🌟 加上 configType 參數 export async function apiSaveTreeFilters(hiddenKeys, configType = 'running') { const response = await fetch(`/api/v1/settings/tree-filters?config_type=${configType}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ hidden_keys: hiddenKeys, config_type: configType }) }); return response.json(); } // ========================================== // 5. MAC Domain 與綜合查詢 (MAC Domain & Query) // ========================================== export async function apiGetMacDomainList(host, username, password) { const url = `/api/v1/cmts-mac-domain-list?host=${encodeURIComponent(host)}&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`; const response = await fetch(url); return response.json(); } export async function apiGetMacDomainConfig(target, host, username, password) { const url = `/api/v1/cmts-mac-domain-config?target=${encodeURIComponent(target)}&host=${encodeURIComponent(host)}&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`; const response = await fetch(url); return response.json(); } export async function apiExecuteQuery(queryType, target, host, username, password) { const url = `/api/v1/cmts-query?query_type=${queryType}&target=${encodeURIComponent(target)}&host=${encodeURIComponent(host)}&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`; const response = await fetch(url); 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 可以即時更新) // ========================================== // 🌟 4. 串流掃描 API (將 config_type 塞入 Body) export async function apiSyncLeafOptionsStream(host, paths, onProgress, configType = 'running') { const response = await fetch('/api/v1/cmts-leaf-options/sync', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ host, leaf_paths: paths, config_type: configType }) }); if (!response.body) throw new Error("瀏覽器不支援 ReadableStream"); // 🌟 核心修改:讀取串流資料 const reader = response.body.getReader(); const decoder = new TextDecoder("utf-8"); while (true) { const { done, value } = await reader.read(); if (done) break; // 伺服器斷開連線 (任務完成) // 解碼二進位資料為文字 const chunk = decoder.decode(value, { stream: true }); // 因為一次可能收到多行 JSON,我們用換行符號切開 const lines = chunk.split("\n").filter(line => line.trim() !== ""); for (const line of lines) { try { const data = JSON.parse(line); onProgress(data); // 將解析後的資料傳給 UI 介面 } catch (e) { console.error("JSON 解析錯誤:", e, line); } } } } export async function apiGetCmDiagnostics(host, username, password, mac) { const url = `/api/v1/cm-diagnostics/?host=${encodeURIComponent(host)}&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}&mac=${encodeURIComponent(mac)}`; const response = await fetch(url); if (!response.ok) { const err = await response.json(); throw new Error(err.detail || "伺服器發生錯誤"); } return response.json(); } export async function apiGetLogLevels() { const response = await fetch('/api/v1/settings/logs'); return response.json(); } export async function apiSetLogLevel(module, level) { const response = await fetch('/api/v1/settings/logs', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ module, level }) }); return response.json(); }