From 2627f37078243e5a04712e5feb329fd07dbfe2fa Mon Sep 17 00:00:00 2001 From: tangguancheng Date: Wed, 29 Apr 2026 14:05:09 +0800 Subject: [PATCH] =?UTF-8?q?[u]=20=E6=96=B0=E5=A2=9E=E8=8A=82=E7=82=B9?= =?UTF-8?q?=EF=BC=9Atoggle=EF=BC=8C=E4=BF=AE=E6=94=B9=E7=9F=A5=E8=A1=A3?= =?UTF-8?q?=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- src/Comfyui_Fd_Nodes/nodes.py | 3 + src/Comfyui_Fd_Nodes/toggle.py | 65 +++++++++++++++++++ src/Comfyui_Fd_Nodes/zhiyi_image_text_node.py | 13 +++- .../zhiyi_image_to_image_node.py | 18 +++-- src/Comfyui_Fd_Nodes/zhiyi_text_node.py | 13 +++- 6 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 src/Comfyui_Fd_Nodes/toggle.py diff --git a/pyproject.toml b/pyproject.toml index e25222a..da7bf00 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "Comfyui_Fd_Nodes" -version = "36.0.0" # 999开头的版本是debug版 +version = "37.0.0" # 999开头的版本是debug版 description = "Custom nodes for fd project" authors = [ {name = "xuyucai", email = "986327386@qq.com"} diff --git a/src/Comfyui_Fd_Nodes/nodes.py b/src/Comfyui_Fd_Nodes/nodes.py index 7899211..684e56b 100644 --- a/src/Comfyui_Fd_Nodes/nodes.py +++ b/src/Comfyui_Fd_Nodes/nodes.py @@ -50,6 +50,7 @@ from .prompt_nodes import EcommercePromptGenerator, PromptListSelector from .zhiyi_text_node import ZhiYiTextGenNode from .zhiyi_image_text_node import ZhiYiImageTextNode from .zhiyi_image_to_image_node import ZhiYiImageToImageNode +from .toggle import NodeToggleByID logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) @@ -1152,6 +1153,7 @@ NODE_CLASS_MAPPINGS = { "ZhiYiImageTextNode": ZhiYiImageTextNode, "ZhiYiImageToImageNode": ZhiYiImageToImageNode, "ZhiYiTextGenNode": ZhiYiTextGenNode, + "NodeToggleByID": NodeToggleByID, } # A dictionary that contains the friendly/humanly readable titles for the nodes @@ -1170,4 +1172,5 @@ NODE_DISPLAY_NAME_MAPPINGS = { "ZhiYiImageTextNode": "知衣-图生文", "ZhiYiImageToImageNode": "知衣-图生图", "ZhiYiTextGenNode": "知衣-文生文", + "NodeToggleByID": "节点开关 (按ID)", } diff --git a/src/Comfyui_Fd_Nodes/toggle.py b/src/Comfyui_Fd_Nodes/toggle.py new file mode 100644 index 0000000..80cbcf9 --- /dev/null +++ b/src/Comfyui_Fd_Nodes/toggle.py @@ -0,0 +1,65 @@ +class NodeToggleByID: + """ + 根据节点 ID 标签批量开启或关闭工作流中的节点。 + node_switch: 0=关闭目标节点,1=开启目标节点 + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "node_switch": ("INT", { + "default": 1, + "min": 0, + "max": 1, + "step": 1, + "display": "number", + }), + "node_ids": ("STRING", { + "default": "", + "multiline": False, + "placeholder": "节点ID列表,由前端动态管理", + }), + }, + "hidden": { + "prompt": "PROMPT", + "unique_id": "UNIQUE_ID", + } + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("status",) + FUNCTION = "toggle_nodes" + CATEGORY = "utils/node_control" + OUTPUT_NODE = True + + def toggle_nodes(self, node_switch, node_ids, prompt=None, unique_id=None): + ids = [nid.strip() for nid in node_ids.split(",") if nid.strip()] + + if not ids: + return ("未指定任何节点 ID",) + + enable = node_switch == 1 + action = "开启" if enable else "关闭" + + if not prompt: + return (f"将对 {len(ids)} 个节点执行{action}操作",) + + status_parts = [] + for node_id in ids: + if node_id in prompt: + class_type = prompt[node_id].get("class_type", "未知") + status_parts.append(f"节点 {node_id} ({class_type}): {action}") + else: + status_parts.append(f"节点 {node_id}: 未找到") + + return ("\n".join(status_parts),) + + +NODE_CLASS_MAPPINGS = { + "NodeToggleByID": NodeToggleByID, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "NodeToggleByID": "节点开关 (按ID)", +} diff --git a/src/Comfyui_Fd_Nodes/zhiyi_image_text_node.py b/src/Comfyui_Fd_Nodes/zhiyi_image_text_node.py index c200744..77b148d 100644 --- a/src/Comfyui_Fd_Nodes/zhiyi_image_text_node.py +++ b/src/Comfyui_Fd_Nodes/zhiyi_image_text_node.py @@ -21,6 +21,13 @@ class ZhiYiImageTextNode: }), }, "optional": { + "node_switch": ("INT", { + "default": 0, + "min": 0, + "max": 1, + "step": 1, + "display": "number", + }), "system_prompt": ("STRING", { "default": "", "multiline": True, @@ -47,15 +54,17 @@ class ZhiYiImageTextNode: OUTPUT_NODE = False def _image_tensor_to_base64(self, image_tensor): - # ComfyUI IMAGE: shape (B, H, W, C), float32, 0~1 arr = (image_tensor[0].numpy() * 255).clip(0, 255).astype(np.uint8) pil_img = Image.fromarray(arr) buf = io.BytesIO() pil_img.save(buf, format="PNG") return base64.b64encode(buf.getvalue()).decode("utf-8") - def generate(self, image, prompt, + def generate(self, image, prompt, node_switch=1, system_prompt="", temperature=0.7, max_tokens=2048): + if node_switch == 1: + return ("",) + cfg = load_config() base_url = cfg["base_url"] api_key = cfg["api_key"] diff --git a/src/Comfyui_Fd_Nodes/zhiyi_image_to_image_node.py b/src/Comfyui_Fd_Nodes/zhiyi_image_to_image_node.py index fd4959e..caeb0c2 100644 --- a/src/Comfyui_Fd_Nodes/zhiyi_image_to_image_node.py +++ b/src/Comfyui_Fd_Nodes/zhiyi_image_to_image_node.py @@ -48,6 +48,13 @@ class ZhiYiImageToImageNode: }), }, "optional": { + "node_switch": ("INT", { + "default": 0, + "min": 0, + "max": 1, + "step": 1, + "display": "number", + }), "image_2": ("IMAGE",), "image_3": ("IMAGE",), "image_4": ("IMAGE",), @@ -89,28 +96,23 @@ class ZhiYiImageToImageNode: raise RuntimeError("内容被过滤 (content_filter),请修改提示词或输入图片后重试") msg = choice["message"] - # 格式1: message.images[0].image_url.url if "images" in msg and msg["images"]: return msg["images"][0]["image_url"]["url"] - # 格式2: message.content 列表中含 image_url 类型 content = msg.get("content", []) if isinstance(content, list): for part in content: if isinstance(part, dict): if part.get("type") == "image_url": return part["image_url"]["url"] - # 格式3: type=image, 直接含 base64 if part.get("type") == "image": return part.get("url") or part.get("data", "") - # 格式4: content 直接是 base64 字符串 if isinstance(content, str) and len(content) > 100: return content raise KeyError(f"无法从响应中提取图片,响应结构: {list(msg.keys())}") - # gemini image-preview 系列不支持 seed 参数 MODELS_NO_SEED = {"gemini-3-pro-image-preview", "gemini-3.1-flash-image-preview"} def _single_request(self, url, api_key, messages, model, aspect_ratio, image_size, seed): @@ -142,9 +144,13 @@ class ZhiYiImageToImageNode: return self._base64_to_tensor(out_data_url) def generate(self, image_1, prompt, model, aspect_ratio, image_size, - batch_size=1, seed_mode="随机种子", seed=0, + batch_size=1, seed_mode="随机种子", seed=0, node_switch=1, image_2=None, image_3=None, image_4=None, image_5=None, image_6=None, system_prompt=""): + if node_switch == 1: + # 返回原图和 seed=0,保持输出类型一致 + return (image_1, 0) + cfg = load_config() base_url = cfg["base_url"] api_key = cfg["api_key"] diff --git a/src/Comfyui_Fd_Nodes/zhiyi_text_node.py b/src/Comfyui_Fd_Nodes/zhiyi_text_node.py index ece191c..b910a14 100644 --- a/src/Comfyui_Fd_Nodes/zhiyi_text_node.py +++ b/src/Comfyui_Fd_Nodes/zhiyi_text_node.py @@ -16,6 +16,13 @@ class ZhiYiTextGenNode: }), }, "optional": { + "node_switch": ("INT", { + "default": 0, + "min": 0, + "max": 1, + "step": 1, + "display": "number", + }), "system_prompt": ("STRING", { "default": "", "multiline": True, @@ -41,7 +48,11 @@ class ZhiYiTextGenNode: CATEGORY = "知衣/文生文" OUTPUT_NODE = False - def generate(self, prompt, system_prompt="", temperature=0.7, max_tokens=2048): + def generate(self, prompt, node_switch=1, + system_prompt="", temperature=0.7, max_tokens=2048): + if node_switch == 1: + return ("",) + cfg = load_config() base_url = cfg["base_url"] api_key = cfg["api_key"]