bizydraft 0.2.76.dev20251027100756__py3-none-any.whl → 0.2.78.dev20251029103128__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bizydraft might be problematic. Click here for more details.
- bizydraft/oss_utils.py +23 -4
- bizydraft/static/js/disableComfyWebSocket.js +28 -0
- bizydraft/static/js/handleStyle.js +4 -0
- bizydraft/static/js/hookLoad/configLoader.js +68 -0
- bizydraft/static/js/hookLoad/media.js +35 -22
- bizydraft/static/js/hookLoad/model.js +10 -28
- bizydraft/static/js/{hookLoadImage.js → hookLoadMedia.js} +159 -89
- bizydraft/static/js/main.js +1 -1
- bizydraft/static/js/postEvent.js +30 -1
- bizydraft/static/js/tool.js +2 -1
- {bizydraft-0.2.76.dev20251027100756.dist-info → bizydraft-0.2.78.dev20251029103128.dist-info}/METADATA +1 -1
- {bizydraft-0.2.76.dev20251027100756.dist-info → bizydraft-0.2.78.dev20251029103128.dist-info}/RECORD +14 -13
- {bizydraft-0.2.76.dev20251027100756.dist-info → bizydraft-0.2.78.dev20251029103128.dist-info}/WHEEL +0 -0
- {bizydraft-0.2.76.dev20251027100756.dist-info → bizydraft-0.2.78.dev20251029103128.dist-info}/top_level.txt +0 -0
bizydraft/oss_utils.py
CHANGED
|
@@ -95,7 +95,13 @@ async def get_upload_token(
|
|
|
95
95
|
filename: str,
|
|
96
96
|
api_key: str,
|
|
97
97
|
) -> Dict[str, Any]:
|
|
98
|
-
|
|
98
|
+
from urllib.parse import quote
|
|
99
|
+
|
|
100
|
+
# 对文件名进行URL编码,避免特殊字符导致问题
|
|
101
|
+
encoded_filename = quote(filename, safe="")
|
|
102
|
+
url = (
|
|
103
|
+
f"{BIZYDRAFT_SERVER}/upload/token?file_name={encoded_filename}&file_type=inputs"
|
|
104
|
+
)
|
|
99
105
|
|
|
100
106
|
headers = {
|
|
101
107
|
"Content-Type": "application/json",
|
|
@@ -412,9 +418,22 @@ async def upload_mask(request):
|
|
|
412
418
|
|
|
413
419
|
|
|
414
420
|
def _should_clean(name: str) -> bool:
|
|
415
|
-
"""True ->
|
|
416
|
-
|
|
417
|
-
|
|
421
|
+
"""True -> 包含非白名单字符;False -> 正常
|
|
422
|
+
|
|
423
|
+
使用白名单机制:只允许安全字符(中英文、数字、下划线、连字符、点、空格)
|
|
424
|
+
如果文件名包含白名单之外的字符,则需要清理
|
|
425
|
+
"""
|
|
426
|
+
if not name:
|
|
427
|
+
return False
|
|
428
|
+
|
|
429
|
+
# 分离文件名和扩展名
|
|
430
|
+
if "." not in name:
|
|
431
|
+
return False
|
|
432
|
+
|
|
433
|
+
# 白名单:允许中英文、数字、下划线、连字符、点、空格、圆括号
|
|
434
|
+
safe_pattern = r"^[\w\u4e00-\u9fa5\s\-().]+$"
|
|
435
|
+
|
|
436
|
+
return not bool(re.match(safe_pattern, name))
|
|
418
437
|
|
|
419
438
|
|
|
420
439
|
def clean_filename(bad: str) -> (bool, str):
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
// 保存原始的 WebSocket 构造函数
|
|
2
2
|
const OriginalWebSocket = window.WebSocket;
|
|
3
3
|
|
|
4
|
+
// 保存原始的 fetch 函数
|
|
5
|
+
const OriginalFetch = window.fetch;
|
|
6
|
+
|
|
7
|
+
// 需要跳过的 URL 数组
|
|
8
|
+
const skipFetchUrls = [
|
|
9
|
+
'manager/badge_mode',
|
|
10
|
+
'pysssss/autocomplete'
|
|
11
|
+
];
|
|
12
|
+
|
|
4
13
|
class FakeWebSocket {
|
|
5
14
|
constructor(url) {
|
|
6
15
|
this.url = url;
|
|
@@ -35,3 +44,22 @@ window.WebSocket.prototype = OriginalWebSocket.prototype;
|
|
|
35
44
|
configurable: true
|
|
36
45
|
});
|
|
37
46
|
});
|
|
47
|
+
|
|
48
|
+
// 拦截 fetch 请求
|
|
49
|
+
window.fetch = function(url) {
|
|
50
|
+
// 将 URL 转换为字符串进行比较
|
|
51
|
+
const urlString = typeof url === 'string' ? url : url.toString();
|
|
52
|
+
// 检查 URL 是否在跳过列表中
|
|
53
|
+
if (skipFetchUrls.some(skipUrl => urlString.includes(skipUrl))) {
|
|
54
|
+
console.warn('[BizyDraft] 已阻止 fetch 请求:', urlString);
|
|
55
|
+
// 返回一个模拟的 Response 对象,状态为 200
|
|
56
|
+
return Promise.resolve(new Response(null, {
|
|
57
|
+
status: 200,
|
|
58
|
+
statusText: 'OK',
|
|
59
|
+
headers: new Headers({ 'Content-Type': 'application/json' })
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 其他请求正常发送
|
|
64
|
+
return OriginalFetch.apply(this, arguments);
|
|
65
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// 统一的配置加载器 - 合并 model.js 和 media.js 的配置请求
|
|
2
|
+
// 只发送一次 API 请求,同时获取 weight_load_nodes 和 media_load_nodes
|
|
3
|
+
|
|
4
|
+
// 统一的配置缓存
|
|
5
|
+
let fullConfigCache = null;
|
|
6
|
+
let configLoadPromise = null;
|
|
7
|
+
|
|
8
|
+
// API配置(统一使用一个域名,根据实际需要调整)
|
|
9
|
+
const CONFIG_API_URL = 'https://bizyair.cn/api/special/comfyagent_node_config?t=' + Math.floor(Date.now() / 60000);
|
|
10
|
+
|
|
11
|
+
// 获取完整配置的API函数(返回包含 weight_load_nodes 和 media_load_nodes 的完整对象)
|
|
12
|
+
export async function fetchFullConfig() {
|
|
13
|
+
if (fullConfigCache) {
|
|
14
|
+
return fullConfigCache;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (configLoadPromise) {
|
|
18
|
+
return configLoadPromise;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
configLoadPromise = (async () => {
|
|
22
|
+
try {
|
|
23
|
+
console.log('正在从API获取完整节点配置...');
|
|
24
|
+
const response = await fetch(CONFIG_API_URL, { credentials: 'include' });
|
|
25
|
+
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const result = await response.json();
|
|
31
|
+
|
|
32
|
+
if (result.code === 20000 && result.data) {
|
|
33
|
+
fullConfigCache = {
|
|
34
|
+
weight_load_nodes: result.data.weight_load_nodes || {},
|
|
35
|
+
media_load_nodes: result.data.media_load_nodes || {}
|
|
36
|
+
};
|
|
37
|
+
console.log('完整配置加载成功:', {
|
|
38
|
+
weight_nodes: Object.keys(fullConfigCache.weight_load_nodes).length,
|
|
39
|
+
media_nodes: Object.keys(fullConfigCache.media_load_nodes).length
|
|
40
|
+
});
|
|
41
|
+
return fullConfigCache;
|
|
42
|
+
} else {
|
|
43
|
+
throw new Error('API返回数据格式不正确');
|
|
44
|
+
}
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error('获取完整配置失败:', error);
|
|
47
|
+
fullConfigCache = null;
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
})();
|
|
51
|
+
|
|
52
|
+
return configLoadPromise;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 获取模型节点配置(从完整配置中提取 weight_load_nodes)
|
|
56
|
+
export async function fetchNodeConfig() {
|
|
57
|
+
const fullConfig = await fetchFullConfig();
|
|
58
|
+
return fullConfig ? fullConfig.weight_load_nodes : null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 获取媒体节点配置(从完整配置中提取 media_load_nodes)
|
|
62
|
+
export async function fetchMediaConfig() {
|
|
63
|
+
const fullConfig = await fetchFullConfig();
|
|
64
|
+
return fullConfig ? fullConfig.media_load_nodes : null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 启动时后台预取(不阻塞后续逻辑)
|
|
68
|
+
try { void fetchFullConfig(); } catch (e) { /* noop */ }
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
// 媒体节点配置获取与工具函数(与 hookLoad/model.js 结构一致,面向 media_load_nodes)
|
|
2
|
+
import { fetchMediaConfig } from './configLoader.js'
|
|
2
3
|
|
|
3
4
|
// 动态配置缓存(仅缓存媒体部分)
|
|
4
5
|
let mediaConfigCache = null;
|
|
5
6
|
let mediaConfigLoadPromise = null;
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
export const mediaNodeList = [
|
|
9
|
+
'LoadImage',
|
|
10
|
+
'LoadImageMask',
|
|
11
|
+
'LoadAudio',
|
|
12
|
+
'LoadVideo',
|
|
13
|
+
'Load3D',
|
|
14
|
+
'VHS_LoadVideo',
|
|
15
|
+
'VHS_LoadAudioUpload'
|
|
16
|
+
]
|
|
10
17
|
// 常见的媒体输入字段名(作为回退匹配)
|
|
11
18
|
export const possibleMediaWidgetNames = [
|
|
12
19
|
"image",
|
|
@@ -16,28 +23,17 @@ export const possibleMediaWidgetNames = [
|
|
|
16
23
|
"model_file"
|
|
17
24
|
];
|
|
18
25
|
|
|
19
|
-
// 获取媒体配置的API
|
|
20
|
-
export async function
|
|
26
|
+
// 获取媒体配置的API函数(使用共享配置加载器)
|
|
27
|
+
export async function fetchMediaConfigWithCache() {
|
|
21
28
|
if (mediaConfigCache) return mediaConfigCache;
|
|
22
29
|
if (mediaConfigLoadPromise) return mediaConfigLoadPromise;
|
|
23
30
|
|
|
24
31
|
mediaConfigLoadPromise = (async () => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
throw new Error('HTTP error ' + (response && response.status));
|
|
29
|
-
}
|
|
30
|
-
const result = await response.json();
|
|
31
|
-
if (result && result.code === 20000 && result.data && result.data.media_load_nodes) {
|
|
32
|
-
mediaConfigCache = result.data.media_load_nodes;
|
|
33
|
-
return mediaConfigCache;
|
|
34
|
-
}
|
|
35
|
-
throw new Error('API返回数据不包含 media_load_nodes');
|
|
36
|
-
} catch (err) {
|
|
37
|
-
console.error('获取媒体配置失败:', err);
|
|
38
|
-
mediaConfigCache = null;
|
|
39
|
-
return null;
|
|
32
|
+
const config = await fetchMediaConfig();
|
|
33
|
+
if (config) {
|
|
34
|
+
mediaConfigCache = config;
|
|
40
35
|
}
|
|
36
|
+
return config;
|
|
41
37
|
})();
|
|
42
38
|
|
|
43
39
|
return mediaConfigLoadPromise;
|
|
@@ -46,7 +42,7 @@ export async function fetchMediaConfig() {
|
|
|
46
42
|
// 根据节点名称获取媒体节点配置(仅使用缓存,不阻塞返回;触发后台预取)
|
|
47
43
|
export async function getMediaNodeConfig(nodeName) {
|
|
48
44
|
// 后台触发一次预取
|
|
49
|
-
if (!mediaConfigLoadPromise) { try { void
|
|
45
|
+
if (!mediaConfigLoadPromise) { try { void fetchMediaConfigWithCache(); } catch (e) {} }
|
|
50
46
|
|
|
51
47
|
if (mediaConfigCache && mediaConfigCache[nodeName]) {
|
|
52
48
|
return { nodeName, config: mediaConfigCache[nodeName] };
|
|
@@ -66,5 +62,22 @@ export function getMediaInputKeys(mediaNodeConfig) {
|
|
|
66
62
|
return keys;
|
|
67
63
|
}
|
|
68
64
|
|
|
65
|
+
|
|
66
|
+
export async function computeIsMediaNode(nodeName) {
|
|
67
|
+
if (mediaNodeList.includes(nodeName)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 2. 检查media_load_nodes的keys
|
|
72
|
+
const config = await fetchMediaConfigWithCache();
|
|
73
|
+
if (config) {
|
|
74
|
+
if (config.hasOwnProperty(nodeName)) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
69
82
|
// 启动时后台预取(不阻塞后续逻辑)
|
|
70
|
-
try { void
|
|
83
|
+
try { void fetchMediaConfigWithCache(); } catch (e) {}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { hideWidget } from '../tool.js'
|
|
2
|
+
import { fetchNodeConfig } from './configLoader.js'
|
|
2
3
|
|
|
3
4
|
// 动态配置缓存
|
|
4
5
|
let nodeConfigCache = null;
|
|
5
6
|
let configLoadPromise = null;
|
|
6
7
|
let storageClearedOnce = false;
|
|
7
8
|
|
|
8
|
-
// API配置
|
|
9
|
-
const CONFIG_API_URL = 'https://bizyair.cn/api/special/comfyagent_node_config?t=' + Math.floor(Date.now() / 60000);
|
|
10
|
-
|
|
11
9
|
const HAZY_WHITELIST_NODES = {
|
|
12
10
|
|
|
13
11
|
}
|
|
@@ -64,8 +62,8 @@ export const possibleWidgetNames=[
|
|
|
64
62
|
"grounding_dino_model"
|
|
65
63
|
]
|
|
66
64
|
|
|
67
|
-
// 获取节点配置的API
|
|
68
|
-
|
|
65
|
+
// 获取节点配置的API函数(使用共享配置加载器)
|
|
66
|
+
async function fetchNodeConfigWithCache() {
|
|
69
67
|
if (nodeConfigCache) {
|
|
70
68
|
return nodeConfigCache;
|
|
71
69
|
}
|
|
@@ -75,28 +73,12 @@ export async function fetchNodeConfig() {
|
|
|
75
73
|
}
|
|
76
74
|
|
|
77
75
|
configLoadPromise = (async () => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (!response.ok) {
|
|
83
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const result = await response.json();
|
|
87
|
-
|
|
88
|
-
if (result.code === 20000 && result.data && result.data.weight_load_nodes) {
|
|
89
|
-
nodeConfigCache = result.data.weight_load_nodes;
|
|
90
|
-
console.log('节点配置加载成功:', Object.keys(nodeConfigCache).length, '个节点');
|
|
91
|
-
return nodeConfigCache;
|
|
92
|
-
} else {
|
|
93
|
-
throw new Error('API返回数据格式不正确');
|
|
94
|
-
}
|
|
95
|
-
} catch (error) {
|
|
96
|
-
console.error('获取节点配置失败:', error);
|
|
97
|
-
nodeConfigCache = null;
|
|
98
|
-
return null;
|
|
76
|
+
const config = await fetchNodeConfig();
|
|
77
|
+
if (config) {
|
|
78
|
+
nodeConfigCache = config;
|
|
79
|
+
console.log('节点配置加载成功:', Object.keys(nodeConfigCache).length, '个节点');
|
|
99
80
|
}
|
|
81
|
+
return config;
|
|
100
82
|
})();
|
|
101
83
|
|
|
102
84
|
return configLoadPromise;
|
|
@@ -122,7 +104,7 @@ export async function getNodeConfig(nodeName) {
|
|
|
122
104
|
}
|
|
123
105
|
|
|
124
106
|
// 若尚未发起请求,后台发起一次
|
|
125
|
-
if (!configLoadPromise) { try { void
|
|
107
|
+
if (!configLoadPromise) { try { void fetchNodeConfigWithCache(); } catch (e) {} }
|
|
126
108
|
|
|
127
109
|
// 2) 正则补充:如 XxxLoader => Xxx(立即返回,不等待API)
|
|
128
110
|
const regex = /^(\w+).*Loader.*/i;
|
|
@@ -293,4 +275,4 @@ export function addBadge(node) {
|
|
|
293
275
|
}
|
|
294
276
|
|
|
295
277
|
// 启动时后台预取(不阻塞后续逻辑)
|
|
296
|
-
try { void
|
|
278
|
+
try { void fetchNodeConfigWithCache(); } catch (e) { /* noop */ }
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { app } from "../../scripts/app.js";
|
|
2
|
-
import { getCookie,
|
|
3
|
-
import { getMediaNodeConfig, getMediaInputKeys, possibleMediaWidgetNames } from './hookLoad/media.js';
|
|
2
|
+
import { getCookie, computeExt, hideWidget } from './tool.js';
|
|
3
|
+
import { getMediaNodeConfig, getMediaInputKeys, possibleMediaWidgetNames, computeIsMediaNode, mediaNodeList, fetchMediaConfigWithCache } from './hookLoad/media.js';
|
|
4
|
+
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
app.registerExtension({
|
|
7
8
|
name: "bizyair.image.to.oss",
|
|
8
|
-
|
|
9
|
+
beforeRegisterNodeDef(nodeType, nodeData) {
|
|
9
10
|
let workflowParams = null
|
|
10
11
|
document.addEventListener('workflowLoaded', (event) => {
|
|
11
12
|
workflowParams = event.detail;
|
|
@@ -31,8 +32,8 @@ app.registerExtension({
|
|
|
31
32
|
}
|
|
32
33
|
});
|
|
33
34
|
})
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
nodeType.prototype.onNodeCreated = async function() {
|
|
36
|
+
if (await computeIsMediaNode(nodeData.name)) {
|
|
36
37
|
const apiHost = 'https://bizyair.cn/api'
|
|
37
38
|
// 优先使用 API 的媒体输入键匹配到具体的 widget;若未命中则回退到原有字段集合
|
|
38
39
|
let media_widget = null;
|
|
@@ -95,26 +96,35 @@ app.registerExtension({
|
|
|
95
96
|
name: item.name
|
|
96
97
|
}
|
|
97
98
|
})
|
|
99
|
+
|
|
100
|
+
// 📊 方案:使用 Map 缓存 URL→Name 映射(O(1) 查找)
|
|
101
|
+
const urlToNameMap = new Map();
|
|
102
|
+
const nameToItemMap = new Map();
|
|
103
|
+
image_list.forEach(item => {
|
|
104
|
+
urlToNameMap.set(item.url, item.name);
|
|
105
|
+
nameToItemMap.set(item.name, item);
|
|
106
|
+
});
|
|
107
|
+
|
|
98
108
|
// 如果找到va_widgets,处理它们
|
|
99
109
|
if (va_widgets.length > 0) {
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
hideWidget(this, va_widget.name);
|
|
103
|
-
});
|
|
110
|
+
// 标志位:防止批量更新时触发监听
|
|
111
|
+
let isBatchUpdating = false;
|
|
104
112
|
|
|
105
113
|
// 创建image_name_widget来替代显示
|
|
106
114
|
if (!image_name_widget) {
|
|
107
115
|
image_name_widget = this.addWidget("combo", "image_name", "", function(e){
|
|
108
|
-
const item =
|
|
116
|
+
const item = nameToItemMap.get(e);
|
|
109
117
|
if (item) {
|
|
110
118
|
const image_url = decodeURIComponent(item.url);
|
|
111
|
-
//
|
|
119
|
+
// 批量更新时跳过监听
|
|
120
|
+
isBatchUpdating = true;
|
|
112
121
|
va_widgets.forEach(va_widget => {
|
|
113
122
|
va_widget.value = image_url;
|
|
114
123
|
if (va_widget.callback) {
|
|
115
|
-
va_widget.callback(
|
|
124
|
+
va_widget.callback(image_url);
|
|
116
125
|
}
|
|
117
126
|
});
|
|
127
|
+
isBatchUpdating = false;
|
|
118
128
|
}
|
|
119
129
|
}, {
|
|
120
130
|
serialize: true,
|
|
@@ -122,104 +132,153 @@ app.registerExtension({
|
|
|
122
132
|
});
|
|
123
133
|
}
|
|
124
134
|
|
|
135
|
+
// 隐藏所有va_widgets 并设置监听
|
|
136
|
+
va_widgets.forEach(va_widget => {
|
|
137
|
+
hideWidget(this, va_widget.name);
|
|
138
|
+
let _value = va_widget.value;
|
|
139
|
+
|
|
140
|
+
// 检查并删除现有的 value 属性描述符(如果存在)
|
|
141
|
+
const existingDescriptor = Object.getOwnPropertyDescriptor(va_widget, 'value');
|
|
142
|
+
if (existingDescriptor && !existingDescriptor.configurable) {
|
|
143
|
+
// 如果不可配置,跳过重新定义
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 删除现有属性(如果存在)
|
|
148
|
+
if (existingDescriptor) {
|
|
149
|
+
delete va_widget.value;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
Object.defineProperty(va_widget, 'value', {
|
|
153
|
+
get: function() {
|
|
154
|
+
return _value;
|
|
155
|
+
},
|
|
156
|
+
set: function(newValue) {
|
|
157
|
+
_value = newValue;
|
|
158
|
+
|
|
159
|
+
// 批量更新时跳过监听逻辑
|
|
160
|
+
if (isBatchUpdating) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// 使用 Map 快速查找(O(1))
|
|
164
|
+
const name = urlToNameMap.get(newValue);
|
|
165
|
+
if (name) {
|
|
166
|
+
image_name_widget.value = name;
|
|
167
|
+
} else {
|
|
168
|
+
// 如果没找到,从URL提取文件名
|
|
169
|
+
const fileName = newValue.split('/').pop();
|
|
170
|
+
image_name_widget.value = fileName;
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
enumerable: true,
|
|
174
|
+
configurable: true
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
|
|
125
179
|
// 为每个va_widget重写callback
|
|
126
180
|
va_widgets.forEach(va_widget => {
|
|
127
181
|
// 保存va_widget的原始callback
|
|
128
182
|
const originalVaCallback = va_widget.callback;
|
|
129
|
-
|
|
130
183
|
// 重写va_widget的callback,当被触发时给image_name_widget赋值
|
|
131
184
|
va_widget.callback = function(e) {
|
|
132
|
-
// 调用原始callback
|
|
133
|
-
if (originalVaCallback) {
|
|
134
|
-
originalVaCallback(e);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// 给image_name_widget赋值
|
|
138
185
|
if (image_name_widget) {
|
|
139
186
|
if (typeof e === 'string') {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
187
|
+
// 使用 Map 快速查找(O(1))
|
|
188
|
+
const name = urlToNameMap.get(e);
|
|
189
|
+
if (name) {
|
|
190
|
+
image_name_widget.value = name;
|
|
143
191
|
} else {
|
|
144
|
-
//
|
|
192
|
+
// 如果没找到,从URL提取文件名
|
|
145
193
|
const fileName = e.split('/').pop();
|
|
146
194
|
image_name_widget.value = fileName;
|
|
147
195
|
}
|
|
148
196
|
}
|
|
149
197
|
}
|
|
150
|
-
};
|
|
151
198
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
// 当value变化时,更新image_name_widget
|
|
159
|
-
if (image_name_widget && value) {
|
|
160
|
-
if (typeof value === 'string') {
|
|
161
|
-
const item = image_list.find(item => item.url === value);
|
|
162
|
-
if (item) {
|
|
163
|
-
image_name_widget.value = item.name;
|
|
164
|
-
} else {
|
|
165
|
-
const fileName = value.split('/').pop();
|
|
166
|
-
image_name_widget.value = fileName;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
}
|
|
199
|
+
// 调用原始callback
|
|
200
|
+
if (originalVaCallback) {
|
|
201
|
+
originalVaCallback(e);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
172
204
|
});
|
|
173
205
|
}
|
|
174
206
|
|
|
175
207
|
// 如果va_widgets没有创建image_name_widget,使用原有逻辑创建
|
|
176
208
|
if (!image_name_widget && media_widget) {
|
|
177
209
|
image_name_widget = this.addWidget("combo", "image_name", "", function(e){
|
|
178
|
-
const item =
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
media_widget.callback
|
|
210
|
+
const item = nameToItemMap.get(e);
|
|
211
|
+
if (item) {
|
|
212
|
+
const image_url = decodeURIComponent(item.url);
|
|
213
|
+
media_widget.value = image_url;
|
|
214
|
+
if (media_widget.callback) {
|
|
215
|
+
media_widget.callback(image_url);
|
|
216
|
+
}
|
|
183
217
|
}
|
|
184
218
|
}, {
|
|
185
219
|
serialize: true,
|
|
186
220
|
values: image_list.map(item => item.name)
|
|
187
221
|
});
|
|
188
222
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
+
|
|
224
|
+
// 如果进入了va_widgets分支,使用va_widgets中第一个作为media_widget的替代
|
|
225
|
+
const actualMediaWidget = va_widgets.length > 0 ? va_widgets[0] : media_widget;
|
|
226
|
+
|
|
227
|
+
if (image_name_widget && actualMediaWidget) {
|
|
228
|
+
const val = urlToNameMap.get(actualMediaWidget.value) || actualMediaWidget.value
|
|
229
|
+
image_name_widget.label = actualMediaWidget.label
|
|
230
|
+
image_name_widget.value = val
|
|
231
|
+
|
|
232
|
+
const currentIndex = this.widgets.indexOf(image_name_widget);
|
|
233
|
+
if (currentIndex > 1) {
|
|
234
|
+
this.widgets.splice(currentIndex, 1);
|
|
235
|
+
this.widgets.splice(1, 0, image_name_widget);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// 如果没有进入va_widgets分支,才隐藏media_widget
|
|
239
|
+
if (va_widgets.length === 0) {
|
|
240
|
+
hideWidget(this, media_widget.name)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
actualMediaWidget.options.values = image_list.map(item => item.name);
|
|
244
|
+
|
|
245
|
+
// 对于va_widgets的情况,callback已经在上面重写过了,不需要再次重写
|
|
246
|
+
if (va_widgets.length === 0 && media_widget) {
|
|
247
|
+
const callback = media_widget.callback
|
|
248
|
+
media_widget.callback = function(e) {
|
|
249
|
+
if (typeof e == 'string') {
|
|
250
|
+
// 使用 Map 快速查找(O(1))
|
|
251
|
+
const item = e.includes('http') ?
|
|
252
|
+
(urlToNameMap.has(e) ? {url: e, name: urlToNameMap.get(e)} : null) :
|
|
253
|
+
(nameToItemMap ? nameToItemMap.get(e) : null);
|
|
254
|
+
|
|
255
|
+
const image_url = item ? decodeURIComponent(item.url) : e;
|
|
256
|
+
|
|
257
|
+
image_name_widget.value = item ? item.name : e;
|
|
258
|
+
media_widget.value = image_url;
|
|
259
|
+
if (callback) {
|
|
260
|
+
callback([image_url])
|
|
261
|
+
}
|
|
262
|
+
} else {
|
|
263
|
+
const item = e[0].split('/')
|
|
264
|
+
const fileName = item[item.length - 1];
|
|
265
|
+
image_name_widget.options.values.pop()
|
|
266
|
+
image_name_widget.options.values.push(fileName)
|
|
267
|
+
image_name_widget.value = fileName
|
|
268
|
+
image_list.push({
|
|
269
|
+
name: fileName,
|
|
270
|
+
url: e[0]
|
|
271
|
+
})
|
|
272
|
+
// 同步更新 Map
|
|
273
|
+
urlToNameMap.set(e[0], fileName);
|
|
274
|
+
if (nameToItemMap) {
|
|
275
|
+
nameToItemMap.set(fileName, {url: e[0], name: fileName});
|
|
276
|
+
}
|
|
277
|
+
if (callback) {
|
|
278
|
+
callback(e)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
223
282
|
}
|
|
224
283
|
}
|
|
225
284
|
return true
|
|
@@ -227,13 +286,24 @@ app.registerExtension({
|
|
|
227
286
|
await getData()
|
|
228
287
|
|
|
229
288
|
|
|
230
|
-
function applyWorkflowImageSettings(workflowParams, image_list, media_widget, image_name_widget, currentNodeId) {
|
|
289
|
+
async function applyWorkflowImageSettings(workflowParams, image_list, media_widget, image_name_widget, currentNodeId) {
|
|
231
290
|
if (workflowParams && workflowParams.nodes) {
|
|
232
|
-
//
|
|
291
|
+
// 先获取配置,然后将 mediaNodeList 和配置的 keys 合并
|
|
292
|
+
const config = await fetchMediaConfigWithCache();
|
|
293
|
+
const allMediaNodeTypes = new Set(mediaNodeList);
|
|
294
|
+
if (config) {
|
|
295
|
+
// 将配置中的 keys 添加到集合中
|
|
296
|
+
for (const key of Object.keys(config)) {
|
|
297
|
+
allMediaNodeTypes.add(key);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// 使用同步的 includes 查找匹配的节点(完全避免循环中的异步)
|
|
233
302
|
const imageNode = workflowParams.nodes.find(item =>
|
|
234
|
-
|
|
303
|
+
item.id === currentNodeId && allMediaNodeTypes.has(item.type)
|
|
235
304
|
)
|
|
236
|
-
|
|
305
|
+
|
|
306
|
+
if (imageNode && imageNode.widgets_values && imageNode.widgets_values[0]) {
|
|
237
307
|
const item = imageNode.widgets_values[0].split('/')
|
|
238
308
|
image_list.push({
|
|
239
309
|
name: item[item.length - 1],
|
|
@@ -250,12 +320,12 @@ app.registerExtension({
|
|
|
250
320
|
|
|
251
321
|
// 如果有存储的工作流数据,应用图像设置
|
|
252
322
|
if (window.currentWorkflowData) {
|
|
253
|
-
applyWorkflowImageSettings(window.currentWorkflowData, image_list, media_widget, image_name_widget, this.id);
|
|
323
|
+
await applyWorkflowImageSettings(window.currentWorkflowData, image_list, media_widget, image_name_widget, this.id);
|
|
254
324
|
// 清除存储的数据,避免重复处理
|
|
255
325
|
delete window.currentWorkflowData;
|
|
256
326
|
} else {
|
|
257
327
|
// 原有的调用
|
|
258
|
-
applyWorkflowImageSettings(workflowParams, image_list, media_widget, image_name_widget, this.id);
|
|
328
|
+
await applyWorkflowImageSettings(workflowParams, image_list, media_widget, image_name_widget, this.id);
|
|
259
329
|
}
|
|
260
330
|
//在这里发个postmessage
|
|
261
331
|
window.parent.postMessage({
|
bizydraft/static/js/main.js
CHANGED
bizydraft/static/js/postEvent.js
CHANGED
|
@@ -510,7 +510,9 @@ app.registerExtension({
|
|
|
510
510
|
|
|
511
511
|
const customErrorStyles = new Map()
|
|
512
512
|
|
|
513
|
-
|
|
513
|
+
// 用于节流的时间戳
|
|
514
|
+
let lastRunWorkflowTime = 0;
|
|
515
|
+
const THROTTLE_TIME = 2000; // 2秒
|
|
514
516
|
|
|
515
517
|
// 方法映射
|
|
516
518
|
const methods = {
|
|
@@ -1032,6 +1034,33 @@ app.registerExtension({
|
|
|
1032
1034
|
window.saveOriginalNodeColors(params.workflowId);
|
|
1033
1035
|
}
|
|
1034
1036
|
};
|
|
1037
|
+
|
|
1038
|
+
// 监听 Ctrl+Enter 快捷键执行工作流
|
|
1039
|
+
document.addEventListener('keydown', (event) => {
|
|
1040
|
+
if (event.ctrlKey && event.key === 'Enter') {
|
|
1041
|
+
event.preventDefault();
|
|
1042
|
+
|
|
1043
|
+
// 节流:检查距离上次执行是否已经过了2秒
|
|
1044
|
+
const now = Date.now();
|
|
1045
|
+
if (now - lastRunWorkflowTime < THROTTLE_TIME) {
|
|
1046
|
+
console.log('触发频率过高,请稍后再试');
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
// 更新上次执行时间
|
|
1051
|
+
lastRunWorkflowTime = now;
|
|
1052
|
+
|
|
1053
|
+
if (methods.runWorkflow) {
|
|
1054
|
+
window.parent.postMessage({
|
|
1055
|
+
type: 'functionResult',
|
|
1056
|
+
method: 'ctrlEnter',
|
|
1057
|
+
result: true
|
|
1058
|
+
}, '*');
|
|
1059
|
+
methods.runWorkflow();
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
1063
|
+
|
|
1035
1064
|
window.addEventListener('message', function (event) {
|
|
1036
1065
|
if (event.data && event.data.type === 'callMethod') {
|
|
1037
1066
|
const methodName = event.data.method;
|
bizydraft/static/js/tool.js
CHANGED
{bizydraft-0.2.76.dev20251027100756.dist-info → bizydraft-0.2.78.dev20251029103128.dist-info}/RECORD
RENAMED
|
@@ -3,7 +3,7 @@ bizydraft/block_nodes.py,sha256=Lqn3oSCaGDHR2OICc8a2iRoRCVVK9v1-9MM3r-qIZgA,1092
|
|
|
3
3
|
bizydraft/env.py,sha256=VFmGopVL2TGWA6hwxyFhIglCEcQxy6iVvL_raMNd6u4,407
|
|
4
4
|
bizydraft/hijack_nodes.py,sha256=riHsp4DhU60E60bfXUl8kVqjs1QvQWmx_FsgQAdWTa4,4197
|
|
5
5
|
bizydraft/hijack_routes.py,sha256=TVK7zdSIe4wN5dusjnAr1we43K6B_Zup5-dWcBj5rxo,3545
|
|
6
|
-
bizydraft/oss_utils.py,sha256=
|
|
6
|
+
bizydraft/oss_utils.py,sha256=XM08pOXGo2jsJlJYmctjL9ZSLUZK8NZuhHCUROXt6GA,16171
|
|
7
7
|
bizydraft/patch_handlers.py,sha256=JWIEK4yKOPpzs3KLAiBCEYfBohyoVUOdlsVOTt3ULeY,9657
|
|
8
8
|
bizydraft/postload.py,sha256=XFElKcmCajT_oO7SVJJBaN04XcWro54N5HB5cSCxfvI,1308
|
|
9
9
|
bizydraft/prestartup_patch.py,sha256=4FGjmRcDHELjtlQOrfTfk2Un5OS89QIqfq-gEcB9WDs,998
|
|
@@ -12,22 +12,23 @@ bizydraft/server.py,sha256=L2zoJgOisr65IRphOyko74AdsLel59gh55peyMaUrO8,2102
|
|
|
12
12
|
bizydraft/workflow_io.py,sha256=MYhJbpgkv8hrA5k_aolijOTrWpTtu62nzRznA4hv8JE,4298
|
|
13
13
|
bizydraft/static/js/aiAppHandler.js,sha256=OQRhhoqvc8iZeCvHTtdaD2VTYBGzkeAGdCk1UMO2RZs,17525
|
|
14
14
|
bizydraft/static/js/clipspaceToOss.js,sha256=brfEPs71Tky5Dnc47UXNEFeFlESDE3kQvUH8ducpIew,14265
|
|
15
|
-
bizydraft/static/js/disableComfyWebSocket.js,sha256=
|
|
15
|
+
bizydraft/static/js/disableComfyWebSocket.js,sha256=ZDOVlU3v3EvWpMRkD8s_AnO43vuWojVLLjkF2pNEVrA,1957
|
|
16
16
|
bizydraft/static/js/freezeModeHandler.js,sha256=SjpHD2nYymR-E13B0YcqkA6e4WycZOVI3c48Ts9qvWE,18027
|
|
17
|
-
bizydraft/static/js/handleStyle.js,sha256=
|
|
18
|
-
bizydraft/static/js/
|
|
17
|
+
bizydraft/static/js/handleStyle.js,sha256=YvafKzypgXH8nD-7Fwwf_lXUSU80OWk7D4Emqj-PV88,3700
|
|
18
|
+
bizydraft/static/js/hookLoadMedia.js,sha256=JYKKqapidi6PUIyRhyPhdGNqQW90nnLANk6qnvojIlU,17725
|
|
19
19
|
bizydraft/static/js/hookLoadModel.js,sha256=TWVmfKp45ta-nE6U5rY3Bv9wiaEBp0QMNt2xaQ3fs9g,6720
|
|
20
|
-
bizydraft/static/js/main.js,sha256
|
|
20
|
+
bizydraft/static/js/main.js,sha256=-pMeAG8vkKO6yq9zXCeHI78KezGn0r9AhYm65DuZrVI,188
|
|
21
21
|
bizydraft/static/js/nodeFocusHandler.js,sha256=24xXbS4Q-GjJdRqf11i-1pBo8MkOJ24F7MHFV44EG6Q,4683
|
|
22
22
|
bizydraft/static/js/nodeParamsFilter.js,sha256=H7lBB0G8HNqoGhOCH1hNXqPU-rPlrFyTxg_f_JgLEMk,4168
|
|
23
|
-
bizydraft/static/js/postEvent.js,sha256=
|
|
23
|
+
bizydraft/static/js/postEvent.js,sha256=_EyA71m5DwGbhHsuf1amKhpLUBxfBWZaMMxViNhuYzU,43481
|
|
24
24
|
bizydraft/static/js/socket.js,sha256=VE3fTAgEfM0FZhL526Skt7OCRokOa3mzTCAjAomI_tE,2432
|
|
25
|
-
bizydraft/static/js/tool.js,sha256=
|
|
25
|
+
bizydraft/static/js/tool.js,sha256=2Hhv2J18OaFZRWmHIlseahjd5Ot7ZVxUPb5z46YeXIo,2928
|
|
26
26
|
bizydraft/static/js/uploadFile.js,sha256=WvglKzHMeOzDhOH3P-fLcPHxCLbKOJpo4DntoRxeJtI,4908
|
|
27
27
|
bizydraft/static/js/workflow_io.js,sha256=FWAjncvWhvy-3nN_legD2fpRwgnIncpRLHU5X016a-U,5236
|
|
28
|
-
bizydraft/static/js/hookLoad/
|
|
29
|
-
bizydraft/static/js/hookLoad/
|
|
30
|
-
bizydraft
|
|
31
|
-
bizydraft-0.2.
|
|
32
|
-
bizydraft-0.2.
|
|
33
|
-
bizydraft-0.2.
|
|
28
|
+
bizydraft/static/js/hookLoad/configLoader.js,sha256=R1k0GKdEmv4IIxdT2F-oOI9X9I19ECe77P_1tO3XxgY,2525
|
|
29
|
+
bizydraft/static/js/hookLoad/media.js,sha256=_JhQhXmNiwfCEBtrQLrsIhEzdjL_mdY-9s5bXXjzB7Y,2439
|
|
30
|
+
bizydraft/static/js/hookLoad/model.js,sha256=aHvEPt9k3CcrawHSYnQYcvbtTRwIztk-XDRA3lvgXvA,9890
|
|
31
|
+
bizydraft-0.2.78.dev20251029103128.dist-info/METADATA,sha256=CZUbnuHbXd_6SSMdbqpFqDDBWKXeu64U4R3XiFwJODg,180
|
|
32
|
+
bizydraft-0.2.78.dev20251029103128.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
33
|
+
bizydraft-0.2.78.dev20251029103128.dist-info/top_level.txt,sha256=XtoBq6hjZhXIM7aas4GtPDtAiKo8FdLzMABXW8qqQ8M,10
|
|
34
|
+
bizydraft-0.2.78.dev20251029103128.dist-info/RECORD,,
|
{bizydraft-0.2.76.dev20251027100756.dist-info → bizydraft-0.2.78.dev20251029103128.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|