import { app } from "../../scripts/app.js"; import { api } from "../../scripts/api.js"; // Modal class (保持不变) class Modal { constructor(id, title, full_width = false) { this.id = id; this.element = document.createElement("div"); this.element.id = this.id; this.element.style.cssText = `position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: var(--comfy-menu-bg); color: var(--fg-color); padding: 20px; border-radius: 8px; box-shadow: 0 0 20px rgba(0,0,0,0.5); z-index: 1001; display: none; flex-direction: column; gap: 15px; min-width: ${ full_width ? "500px" : "350px" }; max-width: 600px; max-height: 80vh;`; this.element.innerHTML = `
正在从服务器加载工作流...
' ); workflowListDialog.addButtons([ { label: "关闭", callback: () => workflowListDialog.hide() }, ]); workflowListDialog.show(); try { const response = await api.fetchApi("/publisher/workflows"); if (!response.ok) { throw new Error( `服务器错误: ${response.status} ${response.statusText}` ); } const text = await response.text(); let workflows; try { workflows = text ? JSON.parse(text) : {}; } catch (parseError) { console.error("JSON解析失败:", parseError, "原始响应:", text); throw new Error("服务器返回的数据格式无效"); } const workflowKeys = Object.keys(workflows); if (workflowKeys.length === 0) { workflowListDialog.setContent( '服务器上没有找到任何工作流。
' ); return; } const accordionContainer = document.createElement("div"); accordionContainer.style.cssText = "display: flex; flex-direction: column; gap: 8px;"; workflowKeys.sort().forEach((baseName) => { const versions = workflows[baseName]; const header = document.createElement("button"); header.className = "jags-accordion-header"; header.innerHTML = `${baseName}${versions.length} 个版本`; const panel = document.createElement("div"); panel.className = "jags-accordion-panel"; versions.forEach((versionData) => { const fullVersionedName = versionData.version === "N/A" ? baseName : `${baseName} [${versionData.version}]`; const item = document.createElement("div"); item.className = "jags-version-item"; const label = document.createElement("span"); label.className = "jags-version-item-label"; label.textContent = `版本: ${versionData.version}`; // --- [核心升级] 使用 app.handleFile 加载工作流 --- label.onclick = () => { if ( confirm( `确定要加载工作流 "${baseName}" 的版本 [${versionData.version}] 吗?\n这将覆盖当前画布。` ) ) { // 1. 将工作流JSON对象转换为字符串 const jsonString = JSON.stringify( versionData.workflow, null, 2 ); // 格式化JSON // 2. 创建一个虚拟的File对象 const file = new File([jsonString], fullVersionedName, { type: "application/json", }); // 3. 调用ComfyUI的官方文件处理函数 app.handleFile(file); // 4. 关闭对话框 workflowListDialog.hide(); } }; const deleteBtn = document.createElement("button"); deleteBtn.className = "jags-delete-btn"; deleteBtn.innerHTML = "✖"; deleteBtn.title = `删除此版本`; deleteBtn.onclick = (e) => { e.stopPropagation(); deleteWorkflowVersion( baseName, versionData.version, fullVersionedName, item ); }; item.appendChild(label); item.appendChild(deleteBtn); panel.appendChild(item); }); header.onclick = () => { header.classList.toggle("active"); if (panel.style.maxHeight) { panel.style.maxHeight = null; panel.style.marginTop = "0px"; } else { panel.style.marginTop = "5px"; panel.style.maxHeight = panel.scrollHeight + "px"; } }; accordionContainer.appendChild(header); accordionContainer.appendChild(panel); }); workflowListDialog.setContent(""); workflowListDialog.element .querySelector(".content") .appendChild(accordionContainer); } catch (error) { console.error("加载工作流失败:", error); workflowListDialog.setContent( `加载失败: ${error.message}
` ); } } // ... (其余函数保持不变) ... async function publishWorkflow() { const baseName = document .getElementById("publisher-workflow-name") .value.trim(); if (!baseName) { alert("请输入工作流的基础名称。"); return; } const statusEl = document.getElementById("publisher-status"); statusEl.textContent = "正在准备发布..."; statusEl.style.color = "orange"; const d = new Date(); const versionString = `${d.getFullYear()}${(d.getMonth() + 1) .toString() .padStart(2, "0")}${d.getDate().toString().padStart(2, "0")}${d .getHours() .toString() .padStart(2, "0")}${d.getMinutes().toString().padStart(2, "0")}${d .getSeconds() .toString() .padStart(2, "0")}`; const finalName = `${baseName} [${versionString}]`; try { const workflow = await app.graph.serialize(); const body = { name: finalName, workflow: workflow }; statusEl.textContent = `正在发布为 "${finalName}"...`; const response = await api.fetchApi("/publisher/publish", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); if (!response.ok) { const errorText = await response.text(); throw new Error( `服务器返回错误: ${response.status} ${response.statusText}${ errorText ? ` - ${errorText}` : "" }` ); } const text = await response.text(); let result; try { result = text ? JSON.parse(text) : {}; } catch (parseError) { console.error("JSON解析失败:", parseError, "原始响应:", text); result = { message: "发布成功,但服务器返回的数据格式无效" }; } statusEl.textContent = `发布成功! ${result.message || ""}`; statusEl.style.color = "var(--success-color)"; setTimeout(() => publishDialog.hide(), 2000); } catch (error) { statusEl.textContent = `发布失败: ${error.message}`; statusEl.style.color = "var(--error-color)"; console.error("发布失败:", error); } } async function showSettingsDialog() { try { let settings = { api_url: "", host: "" }; await api .fetchApi("/publisher/settings", { cache: "no-store", }) .then(async (resp) => { if (!resp.ok) { console.error(`服务器错误: ${resp.status} ${resp.statusText}`); return; } const text = await resp.text(); try { settings = text ? JSON.parse(text) : {}; } catch (parseError) { console.error("JSON解析失败:", parseError, "原始响应:", text); settings = { api_url: "", host: "" }; } }); settingsDialog.setContent(` `); settingsDialog.addButtons([ { label: "取消", callback: () => settingsDialog.hide() }, { label: "保存", callback: saveSettings }, ]); settingsDialog.show(); } catch (error) { console.error("加载设置失败:", error); alert(`加载设置失败: ${error.message}`); } } async function saveSettings() { const apiUrl = document.getElementById("publisher-api-url").value; const host = document.getElementById("publisher-host").value; try { await api.fetchApi("/publisher/settings", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ api_url: apiUrl, host: host }), }); alert("设置已保存!"); settingsDialog.hide(); } catch (error) { alert(`保存设置失败: ${error}`); } } async function showPublishDialog() { try { const settingsResp = await api.fetchApi("/publisher/settings", { cache: "no-store", }); if (!settingsResp.ok) { throw new Error( `服务器错误: ${settingsResp.status} ${settingsResp.statusText}` ); } const text = await settingsResp.text(); let settings; try { settings = text ? JSON.parse(text) : {}; } catch (parseError) { console.error("JSON解析失败:", parseError, "原始响应:", text); settings = { api_url: "", host: "" }; } // 确保设置对象有必需的字段 settings = { api_url: settings.api_url || "", host: settings.host || "", ...settings, }; if (!settings.api_url) { alert("请先点击 ⚙️ 按钮设置发布API的URL。"); return; } publishDialog.setContent( `` ); publishDialog.addButtons([ { label: "取消", callback: () => publishDialog.hide() }, { label: "确认发布", callback: publishWorkflow }, ]); publishDialog.show(); } catch (error) { console.error("加载设置失败:", error); alert(`加载设置失败: ${error.message}`); } } }, });