Files
aidec-Comfyui_TextBatch_aidec/js/textbatch.js
T
2025-04-10 04:26:09 +08:00

257 lines
9.1 KiB
JavaScript

import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
// 用於存儲節點 ID 映射
const nodeIdMap = new Map();
// 註冊自定義事件處理器
api.addEventListener("textbatch-node-feedback", (event) => {
console.log("Received node feedback:", event);
try {
// 從 CustomEvent 中獲取 data
const data = event.detail;
// 檢查 data 物件的完整性
if (!data || !data.node_id) {
console.error("Invalid data received:", data);
return;
}
const nodeId = data.node_id;
console.log("Looking for node:", nodeId, "Data received:", data);
// 嘗試從 nodeIdMap 中獲取節點
let node = nodeIdMap.get(nodeId);
// 如果在 Map 中找不到,再嘗試其他方法
if (!node) {
node = app.graph._nodes_by_id?.[nodeId] ||
app.graph.getNodeById?.(parseInt(nodeId)) ||
[...(app.graph?.nodes || [])].find(n => n?.id == nodeId);
}
if (!node) {
console.warn("Node not found by ID:", nodeId, "Available nodes:",
Array.from(nodeIdMap.keys()));
return;
}
console.log("Found node:", node);
const widget = node.widgets?.find(w => w.name === data.widget_name);
if (!widget) {
console.warn("Widget not found:", data.widget_name);
return;
}
if (data.type === "int") {
console.log("Updating widget value:", data.value);
widget.value = parseInt(data.value);
} else {
widget.value = data.value;
}
// 觸發小部件的變更事件
if (widget.callback) {
widget.callback(widget.value);
}
} catch (error) {
console.error("Error in node feedback handler:", error);
}
});
// 註冊佇列事件處理器
api.addEventListener("textbatch-add-queue", (data) => {
try {
console.log("Received queue event:", data);
// 檢查是否正在處理中
if (app.isProcessing) {
console.log("Already processing, queueing next prompt");
}
// 獲取當前工作流程
const workflow = app.graph?.serialize?.(); // ✅ 安全访问
console.log("Current workflow:", workflow);
// 確保在下一個事件循環中執行
setTimeout(() => {
try {
console.log("Executing queued prompt");
// 使用 queuePrompt 的完整參數
app.queuePrompt?.(0, 1); // ✅ 兼容性检查
console.log("Queue prompt executed");
} catch (queueError) {
console.error("Error queueing prompt:", queueError);
}
}, 100);
} catch (error) {
console.error("Error in textbatch-add-queue handler:", error);
console.error("Error details:", {
message: error.message,
stack: error.stack
});
}
});
// 為特定節點添加自定義行為
app.registerExtension({
name: "TextBatch.TextBatchNode",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
//console.log("Registering node type:", nodeData.name);
if (nodeData.name === "TextBatch" ||
nodeData.name === "TextQueueProcessor" ||
nodeData.name === "ZippedPromptBatch" ||
nodeData.name === "ZippedPromptBatchAdvanced") {
console.log("Adding custom behavior to node:", nodeData.name);
// 添加自定義小部件行為
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function() {
const r = onNodeCreated?.apply?.(this, arguments); // ✅ 安全访问
// 確保節點有有效的 ID
if (!this?.id || this.id === -1) { // ✅ 可选链检查
console.warn("Invalid node ID detected, waiting for proper initialization");
// 等待下一個事件循環再進行初始化
setTimeout(() => {
console.log("Retrying node initialization:", nodeData.name, "ID:", this.id);
// 存儲節點 ID
if (this?.id && this.id !== -1) { // ✅ 双重检查
nodeIdMap.set(this.id, this);
// 為節點添加自定義標題
this.addWidget?.("text", "status", "", (v) => { // ✅ 兼容性检查
console.log("Status widget updated:", v);
this.status = v;
});
}
}, 0);
} else {
console.log("Node created:", nodeData.name, "ID:", this.id);
nodeIdMap.set(this.id, this);
this.addWidget?.("text", "status", "", (v) => { // ✅ 兼容性检查
console.log("Status widget updated:", v);
this.status = v;
});
}
return r;
};
// 添加節點刪除處理
const onNodeRemoved = nodeType.prototype.onRemoved;
nodeType.prototype.onRemoved = function() {
console.log("Node removed:", this.id);
if (this?.id) { // ✅ 关键修复:添加存在性检查
console.log("Node removed:", this.id);
nodeIdMap.delete(this.id);
}
onNodeRemoved?.apply?.(this, arguments); // ✅ 安全调用
};
}
}
});
// api.addEventListener('executed', async ({ detail }) => {
// console.log('#executed', detail)
// console.log(output)
// })
// TextQueueProcessor 節點擴展
class TextQueueProcessorNode {
constructor() {
if (!this.properties) {
this.properties = {};
}
this.addCustomWidgets?.(); // ✅ 兼容性检查
}
addCustomWidgets() {
// 添加重置按鈕
this.addWidget?.("button", "🔄 Reset", null, () => { // ✅ 安全访问
this.triggerReset?.(); // ✅ 兼容性检查
});
// 添加跳到開頭按鈕
this.addWidget("button", "⏮️ To Start", null, () => {
// 將 start_index 設為 0
this.widgets.find(w => w.name === "start_index").value = 0;
});
// 添加跳到結尾按鈕
this.addWidget("button", "⏭️ To End", null, () => {
// 獲取 total 值(如果有的話)
const total = this.outputs?.[2]?.value ?? 0;
if (total > 0) {
this.widgets.find(w => w.name === "start_index").value = total - 1;
}
});
}
triggerReset() {
// 發送重置事件到後端
const nodeId = this?.id; // ✅ 安全访问
app.graphToPrompt?.().then(workflow => { // ✅ 兼容性检查
if (workflow.output) {
app.queuePrompt(workflow.output, workflow.workflow);
}
});
}
}
// ImageQueueProcessor 節點擴展
class ImageQueueProcessorNode {
constructor() {
if (!this.properties) {
this.properties = {};
}
this.addCustomWidgets();
}
addCustomWidgets() {
// 添加重置按鈕
this.addWidget("button", "🔄 Reset", null, () => {
// 觸發重置
this.triggerReset();
});
// 添加跳到開頭按鈕
this.addWidget("button", "⏮️ To Start", null, () => {
// 將 start_index 設為 0
this.widgets.find(w => w.name === "start_index").value = 0;
});
// 添加跳到結尾按鈕
this.addWidget("button", "⏭️ To End", null, () => {
// 獲取 total 值(如果有的話)
const total = this.outputs?.[3]?.value ?? 0;
if (total > 0) {
this.widgets.find(w => w.name === "start_index").value = total - 1;
}
});
}
triggerReset() {
// 發送重置事件到後端
const nodeId = this.id;
app.graphToPrompt().then(workflow => {
if (workflow.output) {
app.queuePrompt(workflow.output, workflow.workflow);
}
});
}
}
// 註冊節點擴展
app.registerExtension({
name: "rgthree.TextBatch",
async beforeRegisterNodeDef(nodeType, nodeData) {
if (nodeData.name === "TextQueueProcessor") {
Object.assign(nodeType.prototype, TextQueueProcessorNode.prototype);
}
else if (nodeData.name === "ImageQueueProcessor") {
Object.assign(nodeType.prototype, ImageQueueProcessorNode.prototype);
}
}
});