import { app } from "../../scripts/app.js"; import { api } from "../../scripts/api.js"; // 本地存储的 key const SETTINGS_STORAGE_KEY = "comfyui_publisher_settings"; // 获取本地设置 function getLocalSettings() { try { const stored = localStorage.getItem(SETTINGS_STORAGE_KEY); return stored ? JSON.parse(stored) : { host: "" }; } catch (error) { console.error("读取本地设置失败:", error); return { host: "" }; } } // 保存设置到本地 function saveLocalSettings(settings) { try { localStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(settings)); } catch (error) { console.error("保存本地设置失败:", error); } } // 自定义 fetchApi 函数,使用本地存储的 host async function customFetchApi(endpoint, options = {}) { try { // 从本地存储获取设置 const settings = getLocalSettings(); // 如果没有配置 host,回退到默认的 api.fetchApi if (!settings.host) { console.warn("未配置 host,使用默认的 ComfyUI API"); return await api.fetchApi(endpoint, options); } // 构建完整的 URL const host = settings.host.replace(/\/$/, ""); // 移除末尾的斜杠 const fullUrl = `${host}${endpoint}`; console.log(`使用本地存储的 host 请求: ${fullUrl}`); // 使用 fetch 发送请求 const response = await fetch(fullUrl, { ...options, headers: { "Content-Type": "application/json", ...options.headers, }, }); return response; } catch (error) { console.error("自定义 fetchApi 失败,回退到默认 API:", error); // 如果自定义请求失败,回退到默认的 api.fetchApi return await api.fetchApi(endpoint, options); } } function parseJson(text) { try { return JSON.parse(text); } catch (error) { console.error("JSON解析失败:", error, "原始数据:", text); return null; } } function createElement(tagName, props) { const element = document.createElement(tagName); if (props.style) element.style = props.style; if (props.className) element.className = props.className; if (props.id) element.id = props.id; if (props.textContent) element.textContent = props.textContent; if (props.innerHTML) element.innerHTML = props.innerHTML; if (props.onclick) element.onclick = props.onclick; if (props.children) { if (Array.isArray(props.children)) { props.children.forEach((child) => { element.appendChild(child); }); } else { element.appendChild(props.children); } } return element; } // 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 customFetchApi("/api/workflow"); if (!response.ok) { throw new Error( `服务器错误: ${response.status} ${response.statusText}` ); } const text = await response.text(); const workflows = parseJson(text); if (workflows.length === 0) { workflowListDialog.setContent( '服务器上没有找到任何工作流。
' ); return; } const accordionContainer = document.createElement("div"); accordionContainer.style.cssText = "display: flex; flex-direction: column; gap: 8px;"; workflows.forEach((workflow) => { const workflowLabel = document.createElement("span"); workflowLabel.textContent = workflow.name; workflowLabel.onclick = () => { if ( confirm( `确定要加载工作流 "${workflow.name}" 吗?\n这将覆盖当前画布。` ) ) { const file = new File( [JSON.stringify(workflow.workflow)], workflow.name, { type: "application/json" } ); app.handleFile(file); } }; accordionContainer.appendChild(workflowLabel); }); workflowListDialog.setContent(""); workflowListDialog.element .querySelector(".content") .appendChild(accordionContainer); } catch (error) { console.error("加载工作流失败:", error); workflowListDialog.setContent( `加载失败: ${error.message}
` ); } } async function publishWorkflow() { const flowName = document .getElementById("publisher-workflow-name") .value.trim(); if (!flowName) { alert("请输入工作流的基础名称。"); return; } const statusEl = document.getElementById("publisher-status"); statusEl.textContent = "正在准备发布..."; statusEl.style.color = "orange"; const versionString = new Date().toISOString(); try { const workflow = await app.graph.serialize(); const body = { name: flowName, workflow: workflow }; statusEl.textContent = `正在发布为 "${flowName}",版本号: ${versionString}...`; const response = await customFetchApi("/api/workflow", { 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 { // 首先尝试从本地存储获取设置 const settings = getLocalSettings(); 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 host = document.getElementById("publisher-host").value; // 构建新的设置对象 const newSettings = { host: host }; try { // 保存到本地存储 saveLocalSettings(newSettings); alert("设置已保存到本地!"); settingsDialog.hide(); } catch (error) { alert(`保存设置失败: ${error}`); } } async function showPublishDialog() { try { // 从本地存储获取设置 let settings = getLocalSettings(); // 如果本地没有设置,尝试从服务器获取 if (!settings.host) { try { const settingsResp = await customFetchApi("/publisher/settings", { cache: "no-store", }); if (settingsResp.ok) { const text = await settingsResp.text(); try { const serverSettings = text ? JSON.parse(text) : {}; settings = { ...settings, ...serverSettings }; // 保存到本地存储 saveLocalSettings(settings); } catch (parseError) { console.error("JSON解析失败:", parseError, "原始响应:", text); } } } catch (error) { console.error("从服务器获取设置失败:", error); } } // 确保设置对象有必需的字段 settings = { host: settings.host || "", ...settings, }; publishDialog.setContent( `` ); publishDialog.addButtons([ { label: "取消", callback: () => publishDialog.hide() }, { label: "确认发布", callback: publishWorkflow }, ]); publishDialog.show(); } catch (error) { console.error("加载设置失败:", error); alert(`加载设置失败: ${error.message}`); } } }, });