Skip to content

Commit 95be7ea

Browse files
authored
add BizyBot (#53)
* agent对话 * auto prettier format code * 添加key * auto prettier format code * fix * fix * 改字 * 修改记录的消息数,方式请求体过大 * 压缩图片 * 删除workflow * fix:点击生成图片后聚焦、回答后移除图片、改名 * auto prettier format code * 修改iocn图标、版本号 * auto prettier format code * fix:修复model引起关闭按钮失效问题、enter+shift键改为换行 * auto prettier format code
1 parent 46db081 commit 95be7ea

11 files changed

Lines changed: 2503 additions & 75 deletions

File tree

bizyui/js/apply_image_to_node.js

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import { app } from "../../scripts/app.js";
2+
3+
4+
function inspectNode(node) {
5+
console.log('节点信息:', {
6+
id: node.id,
7+
type: node.type,
8+
title: node.title,
9+
size: node.size
10+
});
11+
}
12+
13+
// 节点类型与图片类型的映射
14+
const NODE_TYPE_MAPPING = {
15+
'PreviewImage': { type: 'temp', path: 'temp' },
16+
'SaveImage': { type: 'output', path: 'output' },
17+
'LoadImage': { type: 'input', path: 'input' }
18+
};
19+
20+
// 监听来自iframe的消息
21+
window.addEventListener('message', async function(event) {
22+
23+
if (event.data && event.data.type === 'APPLY_IMAGE_TO_NODE') {
24+
const { nodeId, base64Data } = event.data.data;
25+
26+
console.log('收到应用图片到节点请求:', nodeId);
27+
28+
if (!nodeId || !base64Data) {
29+
console.error('应用图片到节点失败: 缺少必要的参数');
30+
return;
31+
}
32+
33+
try {
34+
// 找到目标节点
35+
const targetNode = app.graph.getNodeById(parseInt(nodeId));
36+
if (!targetNode) {
37+
console.error('应用图片到节点失败: 找不到指定ID的节点', nodeId);
38+
return;
39+
}
40+
41+
// 保存原始节点大小
42+
const originalSize = targetNode.size ? [...targetNode.size] : null;
43+
44+
// 记录节点基本信息
45+
inspectNode(targetNode);
46+
47+
// 确定节点类型和对应的图片类型
48+
const nodeType = targetNode.type || targetNode.comfyClass;
49+
const mapping = NODE_TYPE_MAPPING[nodeType] || { type: 'temp', path: 'temp' };
50+
const imageType = mapping.type;
51+
52+
console.log(`节点类型: ${nodeType}, 使用图片类型: ${imageType}`);
53+
54+
// 提取base64
55+
const cleanBase64Data = base64Data.includes('base64,')
56+
? base64Data.split('base64,')[1]
57+
: base64Data;
58+
59+
// 创建一个临时图片文件名
60+
const timestamp = new Date().getTime();
61+
const randomStr = Math.random().toString(36).substring(2, 10);
62+
const filename = `bizyair_${imageType}_${timestamp}_${randomStr}.png`;
63+
64+
// 从base64创建Blob对象
65+
const byteCharacters = atob(cleanBase64Data);
66+
const byteArrays = [];
67+
68+
for (let offset = 0; offset < byteCharacters.length; offset += 512) {
69+
const slice = byteCharacters.slice(offset, offset + 512);
70+
71+
const byteNumbers = new Array(slice.length);
72+
for (let i = 0; i < slice.length; i++) {
73+
byteNumbers[i] = slice.charCodeAt(i);
74+
}
75+
76+
const byteArray = new Uint8Array(byteNumbers);
77+
byteArrays.push(byteArray);
78+
}
79+
80+
const blob = new Blob(byteArrays, {type: 'image/png'});
81+
82+
// 创建FormData对象
83+
const formData = new FormData();
84+
formData.append('image', blob, filename);
85+
formData.append('type', imageType);
86+
formData.append('filename', filename);
87+
88+
// 发送请求
89+
const response = await fetch('/upload/image', {
90+
method: 'POST',
91+
body: formData
92+
});
93+
94+
if (!response.ok) {
95+
throw new Error(`保存图片失败: ${response.status} ${response.statusText}`);
96+
}
97+
98+
const data = await response.json();
99+
console.log('保存图片成功:', data);
100+
101+
// 使用服务器返回的文件名
102+
const serverFilename = data.name || filename;
103+
const serverType = data.type || imageType;
104+
105+
// 创建图片对象
106+
const imageObj = {
107+
filename: serverFilename,
108+
type: serverType,
109+
subfolder: data.subfolder || ''
110+
};
111+
112+
// 只有LoadImage类型的节点需要更新节点内容
113+
if (nodeType === 'LoadImage') {
114+
console.log('处理LoadImage节点,将更新节点内容...');
115+
// 更新节点的图片数据
116+
if (!targetNode.images) {
117+
targetNode.images = [];
118+
}
119+
targetNode.images[0] = imageObj;
120+
121+
if (targetNode.widgets) {
122+
// 更新filename widget
123+
const imageWidget = targetNode.widgets.find(w =>
124+
w.name === 'image' || w.name === 'filename');
125+
if (imageWidget) {
126+
imageWidget.value = serverFilename;
127+
if (typeof imageWidget.callback === "function") {
128+
imageWidget.callback(serverFilename);
129+
}
130+
}
131+
132+
// 确保type widget设置为input
133+
const typeWidget = targetNode.widgets.find(w => w.name === 'type');
134+
if (typeWidget) {
135+
typeWidget.value = 'input';
136+
if (typeof typeWidget.callback === "function") {
137+
typeWidget.callback('input');
138+
}
139+
}
140+
}
141+
142+
// 标记重绘但不改变大小
143+
targetNode.setDirtyCanvas(true, true);
144+
145+
// 恢复原始大小
146+
if (originalSize) {
147+
targetNode.size = originalSize;
148+
}
149+
150+
// 通知重绘
151+
app.canvas && app.canvas.draw(true, true);
152+
153+
console.log(`图片已成功应用到LoadImage节点 ${targetNode.title} (ID: ${targetNode.id})`);
154+
} else {
155+
// 对于其他类型节点,保存图片
156+
if (nodeType === 'SaveImage') {
157+
console.log(`图片已成功保存到output目录: ${serverFilename}`);
158+
alert(`图片已保存到output目录: ${serverFilename}`);
159+
} else if (nodeType === 'PreviewImage') {
160+
console.log(`图片已成功保存到temp目录: ${serverFilename}`);
161+
alert(`图片已保存到temp目录: ${serverFilename}`);
162+
} else {
163+
console.log(`图片已成功保存到${imageType}目录: ${serverFilename}`);
164+
alert(`图片已保存到${imageType}目录: ${serverFilename}`);
165+
}
166+
}
167+
} catch (error) {
168+
console.error('应用图片到节点时发生异常:', error);
169+
alert('处理图片请求失败: ' + error.message);
170+
}
171+
}
172+
});
173+
174+
console.log('已设置消息监听器,可接收iframe发送的图片更新请求');
175+
176+
export { app };

0 commit comments

Comments
 (0)