diff --git a/README.md b/README.md
index 1570fef..81599f7 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,9 @@
针对api接口开发补充的一些自定义节点和功能。
转成base64的节点都是输出节点,websocket消息中会包含base64Images和base64Type属性(具体格式请查看ImageNode.py中的ImageToBase64Advanced类源代码,或者自己搭建简单流程运行在浏览器开发者工具-->网络中查看)
+
+Tips: base64格式字符串比较长,会导致界面卡顿,接口请求带宽可能也会有瓶颈,条件允许可以把图片上传到OSS服务器得到URL,然后用LoadImageFromUrl加载,由于无相关OSS账号,上传OSS节点需自行编写,暂不支持。
+
## 安装
- 方式1:通过ComfyUI-Manager安装
- 方式2:在ComfyUI安装目录根目录下打开命令行终端,执行以下命令
@@ -60,8 +63,8 @@
| StringArea | 字符串文本框(多行输入区域) | |
| ForEachOpen | 循环开始节点 | |
| ForEachClose | 循环结束节点 | |
-
-Tips: base64格式字符串比较长,会导致界面卡顿,接口请求带宽可能也会有瓶颈,条件允许可以把图片上传到OSS服务器得到URL,然后用LoadImageFromUrl加载,由于无相关OSS账号,上传OSS节点需自行编写,暂不支持。
+| LoadJsonStrToList | json字符串转换为对象列表 | | |
+| GetValueFromJsonObj | 从对象中获取指定key的值 | |
### 示例
![save api extended](docs/example_note.png)
@@ -72,6 +75,9 @@ Tips: base64格式字符串比较长,会导致界面卡顿,接口请求带
![save api extended](example/example_3.png)
## 更新记录
+### 2024-09-26
+- 新增节点:GetValueFromJsonObj、 LoadJsonStrToList
+
### 2024-09-25 [示例](example/example_4.png)
- 新增节点:ForEachOpen、 ForEachClose
diff --git a/easyapi/UtilNode.py b/easyapi/UtilNode.py
index 79d6849..a9f8915 100644
--- a/easyapi/UtilNode.py
+++ b/easyapi/UtilNode.py
@@ -1,3 +1,4 @@
+import simplejson
import torch
from comfy.model_patcher import ModelPatcher
@@ -521,6 +522,79 @@ def execute(self, value):
return (value,)
+class ConvertTypeToAny:
+ @classmethod
+ def INPUT_TYPES(s):
+ return {
+ "required": {"any": (any_type, {"forceInput": True})},
+ }
+
+ RETURN_TYPES = (any_type,)
+ RETURN_NAMES = ("any",)
+
+ FUNCTION = "execute"
+
+ CATEGORY = "EasyApi/Utils"
+
+ def execute(self, any):
+ return (any,)
+
+
+class LoadJsonStrToList:
+ @classmethod
+ def INPUT_TYPES(s):
+ return {
+ "required": {
+ "json_str": ("STRING", {"default": "", "multiline": True}),
+ }
+ }
+
+ RETURN_TYPES = ("LIST",)
+ CATEGORY = "EasyApi/Utils"
+ FUNCTION = "load_json"
+
+ def load_json(self, json_str: str):
+ if len(json_str.strip()) == 0:
+ return ([{}],)
+ json = simplejson.loads(json_str)
+ if isinstance(json, list):
+ return (json,)
+ else:
+ return ([json],)
+
+
+class GetValueFromJsonObj:
+ @classmethod
+ def INPUT_TYPES(s):
+ return {
+ "required": {
+ "json": (any_type, {"forceInput": True, "tooltip": "json对象(非数组类型)"}),
+ "key": ("STRING", {"default": ""}),
+ "to_type": (["default", "str", "int", "float", "bool"], {"default": "default"}),
+ },
+ }
+
+ RETURN_TYPES = (any_type,)
+ RETURN_NAMES = ("any",)
+
+ FUNCTION = "execute"
+
+ CATEGORY = "EasyApi/Utils"
+
+ def execute(self, json, key, to_type):
+ if isinstance(json, dict) and key in json:
+ if to_type == "str":
+ return (str(json[key]),)
+ if to_type == "int":
+ return (int(json[key]),)
+ if to_type == "float":
+ return (float(json[key]),)
+ if to_type == "bool":
+ return (bool(json[key]),)
+ return (json[key],)
+ return (None,)
+
+
NODE_CLASS_MAPPINGS = {
"GetImageBatchSize": GetImageBatchSize,
"JoinList": JoinList,
@@ -542,6 +616,9 @@ def execute(self, value):
"IndexOfList": IndexOfList,
"IndexesOfList": IndexesOfList,
"StringArea": StringArea,
+ "ConvertTypeToAny": ConvertTypeToAny,
+ "GetValueFromJsonObj": GetValueFromJsonObj,
+ "LoadJsonStrToList": LoadJsonStrToList,
}
# A dictionary that contains the friendly/humanly readable titles for the nodes
@@ -566,4 +643,7 @@ def execute(self, value):
"IndexOfList": "IndexOfList",
"IndexesOfList": "IndexesOfList",
"StringArea": "StringArea",
+ "ConvertTypeToAny": "ConvertTypeToAny",
+ "GetValueFromJsonObj": "GetValueFromJsonObj",
+ "LoadJsonStrToList": "LoadJsonStrToList",
}
diff --git a/pyproject.toml b/pyproject.toml
index d564fdb..003e60c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,7 @@
[project]
name = "comfyui-easyapi-nodes"
description = "Provides some features and nodes related to API calls."
-version = "1.0.4"
+version = "1.0.5"
license = { file = "LICENSE" }
dependencies = ["segment_anything", "simple_lama_inpainting", "insightface"]
diff --git a/static/js/workflows.js b/static/js/workflows.js
index 15ff4a7..b66c80b 100644
--- a/static/js/workflows.js
+++ b/static/js/workflows.js
@@ -14,6 +14,71 @@ import('/scripts/ui/components/splitButton.js').then(module => {
// console.error('模块导入失败:', error);
});
+/**
+ * v2是否大于v1
+ *
+ * 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1
+ *
+ * code from: https://segmentfault.com/a/1190000044959793
+ * @param v1
+ * @param v2
+ * @returns {boolean}
+ */
+function compareVersion(v1, v2) {
+ function* getStepVersion(v) {
+ const matchReg = /(\.|\-)/; // 匹配到任意一项,则返回分段的版本号
+ // 将先行版本号,转换成数字,直接比大小
+ const specialVersionTransObj = {
+ alpha: -3,
+ beta: -2,
+ rc: -1,
+ };
+ let tmp = ""; // 存储每段版本的值
+ for (let i = 0; i <= v.length - 1; i++) {
+ let item = v[i];
+ if (matchReg.test(item)) {
+ yield specialVersionTransObj[tmp] || tmp;
+ tmp = "";
+ } else {
+ tmp += item;
+ }
+ }
+
+ // 遍历至最后一项,没有匹配到.-也要返回结果
+ if (tmp) {
+ yield specialVersionTransObj[tmp] || tmp;
+ }
+ }
+
+ const v1Iterator = getStepVersion(v1);
+ const v2Iterator = getStepVersion(v2);
+
+ let isEnd = false;
+ let isHighLevel = false;
+ // 每次遍历相当于,2个版本号分段间的比较
+ while (!isEnd) {
+ const item1 = v1Iterator.next();
+ const item2 = v2Iterator.next();
+ item1.value = item1.value || 0;
+ item2.value = item2.value || 0;
+
+ if (item1.done && item2.done) {
+ // 代表版本号一致
+ isEnd = true;
+ } else {
+ if (Number(item2.value) > Number(item1.value)) {
+ // v2 版本大于 v1
+ isHighLevel = true;
+ isEnd = true;
+ } else if (Number(item2.value) < Number(item1.value)) {
+ // v2 版本小于 v1
+ isHighLevel = false;
+ isEnd = true;
+ }
+ }
+ }
+ return isHighLevel;
+}
const style = `
@@ -236,7 +301,7 @@ class EasyApiWorkflows {
let copyButton = new ComfySplitButton(
{
primary: getCopyButton(),
- mode: "hover",
+ mode: !!app.menu.saveButton ? "hover" : "click",
position: "absolute",
},
getCopyButton("Copy"),
@@ -272,9 +337,13 @@ class EasyApiWorkflows {
app,
}),
);
- app.menu.saveButton.element.after(copyButton.element);
+ if (!!app.menu.saveButton) {
+ app.menu.saveButton.element.after(copyButton.element);
+ } else {
+ // version>=1.3.0
+ app.menu.actionsGroup.append(copyButton.element);
+ }
- let oldItems = app.menu.saveButton.items;
let exportEasyApiButton = new ComfyButton({
icon: "api",
content: "Export to Base64 (API Format)",
@@ -309,8 +378,14 @@ class EasyApiWorkflows {
visibilitySetting: { id: "Comfy.DevMode", showValue: true },
app,
})
- oldItems.push(exportEasyApiButton);
- app.menu.saveButton.items = oldItems;
+ if (!!app.menu.saveButton) {
+ let oldItems = app.menu.saveButton.items;
+ oldItems.push(exportEasyApiButton);
+ app.menu.saveButton.items = oldItems;
+ } else {
+ // version>=1.3.0
+ // app.menu.actionsGroup.append(copyButton.element);
+ }
}
const handleFile = app.handleFile;