bizydraft 0.1.29__py3-none-any.whl → 0.2.0__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/block_nodes.py +35 -0
- bizydraft/env.py +11 -0
- bizydraft/hijack_nodes.py +66 -6
- bizydraft/hijack_routes.py +87 -184
- bizydraft/oss_utils.py +227 -0
- bizydraft/patch_handlers.py +150 -0
- bizydraft/postload.py +26 -8
- bizydraft/server.py +2 -1
- bizydraft/static/js/aiAppHandler.js +540 -0
- bizydraft/static/js/freezeModeHandler.js +490 -0
- bizydraft/static/js/handleStyle.js +6 -0
- bizydraft/static/js/hookLoadImage.js +122 -82
- bizydraft/static/js/hookLoadModel.js +152 -0
- bizydraft/static/js/main.js +0 -1
- bizydraft/static/js/nodeFocusHandler.js +153 -0
- bizydraft/static/js/nodeParamsFilter.js +136 -0
- bizydraft/static/js/postEvent.js +336 -106
- bizydraft/static/js/socket.js +1 -1
- bizydraft/static/js/tool.js +61 -1
- bizydraft/static/js/uploadFile.js +22 -22
- bizydraft/workflow_io.py +30 -2
- {bizydraft-0.1.29.dist-info → bizydraft-0.2.0.dist-info}/METADATA +1 -1
- bizydraft-0.2.0.dist-info/RECORD +28 -0
- bizydraft-0.1.29.dist-info/RECORD +0 -19
- {bizydraft-0.1.29.dist-info → bizydraft-0.2.0.dist-info}/WHEEL +0 -0
- {bizydraft-0.1.29.dist-info → bizydraft-0.2.0.dist-info}/top_level.txt +0 -0
|
@@ -1,27 +1,50 @@
|
|
|
1
1
|
import { app } from "../../scripts/app.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { getCookie, computeIsLoadNode, computeExt, hideWidget } from './tool.js';
|
|
3
|
+
|
|
4
4
|
|
|
5
5
|
app.registerExtension({
|
|
6
6
|
name: "bizyair.image.to.oss",
|
|
7
7
|
async beforeRegisterNodeDef(nodeType, nodeData) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
let workflowParams = null
|
|
9
|
+
document.addEventListener('workflowLoaded', (event) => {
|
|
10
|
+
workflowParams = event.detail;
|
|
11
|
+
})
|
|
12
|
+
document.addEventListener('drop', (e) => {
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
const files = e.dataTransfer.files;
|
|
15
|
+
|
|
16
|
+
Array.from(files).forEach((file) => {
|
|
17
|
+
if (file.type === 'application/json' || file.name.endsWith('.json')) {
|
|
18
|
+
const reader = new FileReader();
|
|
19
|
+
reader.onload = function(event) {
|
|
20
|
+
try {
|
|
21
|
+
const jsonContent = JSON.parse(event.target.result);
|
|
22
|
+
if (jsonContent && jsonContent.nodes) {
|
|
23
|
+
window.currentWorkflowData = jsonContent;
|
|
24
|
+
}
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error('解析JSON文件失败:', error);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
reader.readAsText(file);
|
|
30
|
+
}
|
|
12
31
|
});
|
|
32
|
+
})
|
|
33
|
+
if (computeIsLoadNode(nodeData.name)) {
|
|
13
34
|
nodeType.prototype.onNodeCreated = async function() {
|
|
14
|
-
const image_widget = this.widgets.find(w => w.name === 'image');
|
|
15
|
-
console.log(image_widget)
|
|
16
|
-
// const apiHost = 'http://localhost:3000/api'
|
|
17
35
|
const apiHost = 'https://bizyair.cn/api'
|
|
18
|
-
const
|
|
36
|
+
const image_widget = this.widgets.find(w => {
|
|
37
|
+
return w.name === 'image'
|
|
38
|
+
|| w.name === 'file'
|
|
39
|
+
|| w.name === 'audio'
|
|
40
|
+
|| w.name === 'model_file'
|
|
41
|
+
});
|
|
42
|
+
let image_name_widget = this.widgets.find(w => w.name === 'image_name');
|
|
19
43
|
let image_list = []
|
|
20
44
|
const getData = async () => {
|
|
21
45
|
const res = await fetch(`${apiHost}/special/community/commit_input_resource?${
|
|
22
46
|
new URLSearchParams({
|
|
23
|
-
|
|
24
|
-
ext: '',
|
|
47
|
+
ext: computeExt(nodeData.name),
|
|
25
48
|
current: 1,
|
|
26
49
|
page_size: 100
|
|
27
50
|
|
|
@@ -38,96 +61,113 @@ app.registerExtension({
|
|
|
38
61
|
image_list = list.filter(item => item.name).map(item => {
|
|
39
62
|
return {
|
|
40
63
|
url: item.url,
|
|
64
|
+
id: item.id,
|
|
41
65
|
name: item.name
|
|
42
66
|
}
|
|
43
|
-
// return item.url
|
|
44
67
|
})
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
68
|
+
if (!image_name_widget) {
|
|
69
|
+
image_name_widget = this.addWidget("combo", "image_name", "", function(e){
|
|
70
|
+
const item = image_list.find(item => item.name === e)
|
|
71
|
+
const image_url = decodeURIComponent(item.url);
|
|
72
|
+
image_widget.value = image_url;
|
|
73
|
+
if (image_widget.callback) {
|
|
74
|
+
image_widget.callback(e);
|
|
75
|
+
}
|
|
76
|
+
}, {
|
|
77
|
+
serialize: true,
|
|
78
|
+
values: image_list.map(item => item.name)
|
|
52
79
|
});
|
|
53
|
-
image_path_widget.type = "hidden";
|
|
54
|
-
// image_path_widget.style = "hidden";
|
|
55
|
-
image_path_widget.computeSize = () => [0, 0]; // 隐藏显示
|
|
56
80
|
}
|
|
57
|
-
|
|
81
|
+
const val = image_list.find(item => item.url === image_widget.value)?.name || image_widget.value
|
|
82
|
+
image_name_widget.label = image_widget.label
|
|
83
|
+
image_name_widget.value = val
|
|
58
84
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (image_list[0] && image_list[0].url) {
|
|
64
|
-
image_widget.value = image_list[0].name
|
|
65
|
-
const defaultImageUrl = decodeURIComponent(image_list[0].url);
|
|
66
|
-
image_path_widget.value = defaultImageUrl;
|
|
67
|
-
|
|
68
|
-
previewImage(node, defaultImageUrl)
|
|
85
|
+
const currentIndex = this.widgets.indexOf(image_name_widget);
|
|
86
|
+
if (currentIndex > 1) {
|
|
87
|
+
this.widgets.splice(currentIndex, 1);
|
|
88
|
+
this.widgets.splice(1, 0, image_name_widget);
|
|
69
89
|
}
|
|
70
|
-
image_widget.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
90
|
+
hideWidget(this, image_widget.name)
|
|
91
|
+
image_widget.options.values = image_list.map(item => item.name);
|
|
92
|
+
|
|
93
|
+
const callback = image_widget.callback
|
|
94
|
+
image_widget.callback = async function(e) {
|
|
95
|
+
console.log(e)
|
|
96
|
+
if (typeof e == 'string') {
|
|
97
|
+
const item = e.includes('http') ?
|
|
98
|
+
image_list.find(item => item.url === e) :
|
|
99
|
+
image_list.find(item => item.name === e)
|
|
100
|
+
|
|
101
|
+
const image_url = item ? decodeURIComponent(item.url) : e;
|
|
102
|
+
|
|
103
|
+
image_name_widget.value = item ? item.name : e;
|
|
104
|
+
image_widget.value = image_url;
|
|
105
|
+
console.log('=================image_url=================')
|
|
106
|
+
console.log(image_url)
|
|
107
|
+
console.log(item)
|
|
108
|
+
console.log(await app.graphToPrompt())
|
|
109
|
+
callback([image_url])
|
|
110
|
+
console.log(await app.graphToPrompt())
|
|
111
|
+
} else {
|
|
112
|
+
const item = e[0].split('/')
|
|
113
|
+
image_name_widget.options.values.pop()
|
|
114
|
+
image_name_widget.options.values.push(item[item.length - 1])
|
|
115
|
+
image_name_widget.value = item[item.length - 1]
|
|
116
|
+
image_list.push({
|
|
117
|
+
name: item[item.length - 1],
|
|
118
|
+
url: e[0]
|
|
119
|
+
})
|
|
120
|
+
callback(e)
|
|
121
|
+
}
|
|
74
122
|
}
|
|
75
123
|
return true
|
|
76
124
|
}
|
|
77
|
-
|
|
78
125
|
await getData()
|
|
79
126
|
|
|
80
127
|
|
|
128
|
+
function applyWorkflowImageSettings(workflowParams, image_list, image_widget, image_name_widget) {
|
|
129
|
+
if (workflowParams && workflowParams.nodes) {
|
|
130
|
+
const imageNode = workflowParams.nodes.find(item => computeIsLoadNode(item.type))
|
|
131
|
+
if (imageNode && imageNode.widgets_values) {
|
|
132
|
+
const item = imageNode.widgets_values[0].split('/')
|
|
133
|
+
image_list.push({
|
|
134
|
+
name: item[item.length - 1],
|
|
135
|
+
url: imageNode.widgets_values[0]
|
|
136
|
+
})
|
|
137
|
+
image_widget.value = imageNode.widgets_values[0]
|
|
81
138
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const temp = {
|
|
86
|
-
name: imageNode.widgets_values[0],
|
|
87
|
-
url: imageNode.widgets_values[2]
|
|
139
|
+
image_widget.options.values = image_list.map(item => item.url)
|
|
140
|
+
image_name_widget.options.values = image_list.map(item => item.name)
|
|
141
|
+
image_widget.callback(imageNode.widgets_values[0])
|
|
88
142
|
}
|
|
89
|
-
image_list.push(temp)
|
|
90
|
-
image_widget.value = temp.name
|
|
91
|
-
image_widget.options.values = image_list.map(item => item.name)
|
|
92
|
-
previewImage(node, temp.url)
|
|
93
|
-
|
|
94
|
-
requestAnimationFrame(() => {
|
|
95
|
-
previewImage(node, temp.url)
|
|
96
|
-
})
|
|
97
143
|
}
|
|
98
144
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
getData()
|
|
109
|
-
}
|
|
110
|
-
input.click();
|
|
145
|
+
|
|
146
|
+
// 如果有存储的工作流数据,应用图像设置
|
|
147
|
+
if (window.currentWorkflowData) {
|
|
148
|
+
applyWorkflowImageSettings(window.currentWorkflowData, image_list, image_widget, image_name_widget);
|
|
149
|
+
// 清除存储的数据,避免重复处理
|
|
150
|
+
delete window.currentWorkflowData;
|
|
151
|
+
} else {
|
|
152
|
+
// 原有的调用
|
|
153
|
+
applyWorkflowImageSettings(workflowParams, image_list, image_widget, image_name_widget);
|
|
111
154
|
}
|
|
155
|
+
|
|
156
|
+
|
|
112
157
|
}
|
|
113
158
|
}
|
|
114
159
|
}
|
|
115
160
|
})
|
|
116
161
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
img.onerror = function(err) {
|
|
130
|
-
console.error('[BizyAir] 图片加载失败:', image_url, err);
|
|
131
|
-
};
|
|
132
|
-
img.src = image_url;
|
|
133
|
-
}
|
|
162
|
+
// app.api.addEventListener('graphChanged', (e) => {
|
|
163
|
+
// console.log('Graph 发生变化,当前 workflow JSON:', e.detail)
|
|
164
|
+
// window.parent.postMessage({
|
|
165
|
+
// type: 'functionResult',
|
|
166
|
+
// method: 'workflowChanged',
|
|
167
|
+
// result: e.detail
|
|
168
|
+
// }, '*');
|
|
169
|
+
|
|
170
|
+
// document.dispatchEvent(new CustomEvent('workflowLoaded', {
|
|
171
|
+
// detail: e.detail
|
|
172
|
+
// }));
|
|
173
|
+
// })
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { app } from "../../scripts/app.js";
|
|
2
|
+
import '../BizyAir/bizyair_frontend.js'
|
|
3
|
+
import { hideWidget } from './tool.js'
|
|
4
|
+
const possibleWidgetNames=[
|
|
5
|
+
"clip_name",
|
|
6
|
+
"clip_name1",
|
|
7
|
+
"clip_name2",
|
|
8
|
+
"ckpt_name",
|
|
9
|
+
"lora_name",
|
|
10
|
+
"control_net_name",
|
|
11
|
+
"ipadapter_file",
|
|
12
|
+
"unet_name",
|
|
13
|
+
"vae_name",
|
|
14
|
+
"model_name",
|
|
15
|
+
"instantid_file",
|
|
16
|
+
"pulid_file",
|
|
17
|
+
"style_model_name",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
// 根据节点名称匹配模型类型
|
|
21
|
+
function getModelTypeFromNodeName(nodeName) {
|
|
22
|
+
if (/bizyair/i.test(nodeName)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const regex = /^(\w+).*Loader.*/i;
|
|
27
|
+
const match = nodeName.match(regex);
|
|
28
|
+
if (match) {
|
|
29
|
+
return match[1];
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function createSetWidgetCallback(modelType, selectedBaseModels = []) {
|
|
35
|
+
return function setWidgetCallback() {
|
|
36
|
+
const targetWidget = this.widgets.find(widget => possibleWidgetNames.includes(widget.name));
|
|
37
|
+
if (targetWidget) {
|
|
38
|
+
targetWidget.value = targetWidget.value || "to choose"
|
|
39
|
+
targetWidget.mouse = function(e, pos, canvas) {
|
|
40
|
+
try {
|
|
41
|
+
if (e.type === "pointerdown" || e.type === "mousedown" || e.type === "click" || e.type === "pointerup") {
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
e.stopPropagation();
|
|
44
|
+
e.widgetClick = true;
|
|
45
|
+
|
|
46
|
+
const currentNode = this.node;
|
|
47
|
+
|
|
48
|
+
if (!currentNode || !currentNode.widgets) {
|
|
49
|
+
console.warn("Node or widgets not available");
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (typeof bizyAirLib !== 'undefined' && typeof bizyAirLib.showModelSelect === 'function') {
|
|
54
|
+
bizyAirLib.showModelSelect({
|
|
55
|
+
modelType: [modelType],
|
|
56
|
+
selectedBaseModels,
|
|
57
|
+
onApply: (version, model) => {
|
|
58
|
+
if (!currentNode || !currentNode.widgets) return;
|
|
59
|
+
|
|
60
|
+
const currentLora = currentNode.widgets.find(widget => possibleWidgetNames.includes(widget.name));
|
|
61
|
+
const currentModel = currentNode.widgets.find(w => w.name === "model_version_id");
|
|
62
|
+
|
|
63
|
+
if (model && currentModel && version) {
|
|
64
|
+
currentLora.value = model;
|
|
65
|
+
currentModel.value = version.id;
|
|
66
|
+
currentNode.setDirtyCanvas(true);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
console.error("bizyAirLib not available");
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error("Error handling mouse event:", error);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// targetWidget.node = this;
|
|
81
|
+
targetWidget.options = targetWidget.options || {};
|
|
82
|
+
targetWidget.options.values = () => [];
|
|
83
|
+
targetWidget.options.editable = false;
|
|
84
|
+
targetWidget.clickable = true;
|
|
85
|
+
targetWidget.processMouse = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function setupNodeMouseBehavior(node, modelType) {
|
|
91
|
+
hideWidget(node, "model_version_id");
|
|
92
|
+
|
|
93
|
+
// 只设置必要的状态信息,不修改onMouseDown(已在上面的扩展中处理)
|
|
94
|
+
if (!node._bizyairState) {
|
|
95
|
+
node._bizyairState = {
|
|
96
|
+
lastClickTime: 0,
|
|
97
|
+
DEBOUNCE_DELAY: 300,
|
|
98
|
+
modelType: modelType
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
app.registerExtension({
|
|
104
|
+
name: "bizyair.hook.load.model",
|
|
105
|
+
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
|
106
|
+
|
|
107
|
+
localStorage.removeItem('workflow')
|
|
108
|
+
sessionStorage.clear()
|
|
109
|
+
const interval = setInterval(() => {
|
|
110
|
+
if (window.switchLanguage) {
|
|
111
|
+
window.switchLanguage('zh')
|
|
112
|
+
clearInterval(interval)
|
|
113
|
+
}
|
|
114
|
+
}, 100)
|
|
115
|
+
|
|
116
|
+
const modelType = getModelTypeFromNodeName(nodeData.name);
|
|
117
|
+
if (modelType) {
|
|
118
|
+
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
|
119
|
+
nodeType.prototype.onNodeCreated = function() {
|
|
120
|
+
try {
|
|
121
|
+
let model_version_id = this.widgets.find(w => w.name === "model_version_id");
|
|
122
|
+
if (!model_version_id) {
|
|
123
|
+
model_version_id = this.addWidget("hidden", "model_version_id", "", function(e){
|
|
124
|
+
console.log(e)
|
|
125
|
+
}, {
|
|
126
|
+
serialize: true,
|
|
127
|
+
values: []
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
console.log(model_version_id)
|
|
131
|
+
const result = onNodeCreated?.apply(this, arguments);
|
|
132
|
+
let selectedBaseModels = [];
|
|
133
|
+
// if (modelType === 'Checkpoint') {
|
|
134
|
+
// selectedBaseModels = ['SDXL', 'Pony', 'SD 3.5', 'Illustrious']
|
|
135
|
+
// }
|
|
136
|
+
createSetWidgetCallback(modelType, selectedBaseModels).call(this);
|
|
137
|
+
return result;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error("Error in node creation:", error);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
async nodeCreated(node) {
|
|
146
|
+
const modelType = getModelTypeFromNodeName(node?.comfyClass);
|
|
147
|
+
|
|
148
|
+
if (modelType) {
|
|
149
|
+
setupNodeMouseBehavior(node, modelType);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
})
|
bizydraft/static/js/main.js
CHANGED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { app } from "../../scripts/app.js";
|
|
2
|
+
|
|
3
|
+
// 全局变量引用(从aiAppHandler.js中引用)
|
|
4
|
+
let freezeOverlay = null;
|
|
5
|
+
let globalEventBlocked = false;
|
|
6
|
+
let keyboardListener = null;
|
|
7
|
+
let contextMenuListener = null;
|
|
8
|
+
|
|
9
|
+
// 设置全局变量引用
|
|
10
|
+
export function setGlobalReferences(overlay, eventBlocked, kListener, cListener) {
|
|
11
|
+
freezeOverlay = overlay;
|
|
12
|
+
globalEventBlocked = eventBlocked;
|
|
13
|
+
keyboardListener = kListener;
|
|
14
|
+
contextMenuListener = cListener;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 只聚焦节点,不高亮
|
|
18
|
+
export function focusNodeOnly(nodeId) {
|
|
19
|
+
console.log('[nodeFocusHandler] focusNodeOnly called with nodeId:', nodeId);
|
|
20
|
+
|
|
21
|
+
if (!app || !app.graph) {
|
|
22
|
+
console.error('[nodeFocusHandler] app or app.graph not available');
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const node = app.graph.getNodeById(parseInt(nodeId, 10));
|
|
27
|
+
if (!node) {
|
|
28
|
+
console.error('[nodeFocusHandler] 找不到节点:', nodeId);
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
console.log('[nodeFocusHandler] 找到节点:', node);
|
|
33
|
+
|
|
34
|
+
// 临时禁用冻结模式
|
|
35
|
+
const wasFreezed = !!freezeOverlay;
|
|
36
|
+
let originalOverlayDisplay = null;
|
|
37
|
+
|
|
38
|
+
if (wasFreezed && freezeOverlay) {
|
|
39
|
+
originalOverlayDisplay = freezeOverlay.style.display;
|
|
40
|
+
freezeOverlay.style.display = 'none';
|
|
41
|
+
|
|
42
|
+
// 临时解除事件阻止
|
|
43
|
+
if (globalEventBlocked) {
|
|
44
|
+
document.removeEventListener('keydown', keyboardListener, true);
|
|
45
|
+
document.removeEventListener('contextmenu', contextMenuListener, true);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 只设置节点的 selected 属性,不改变颜色
|
|
50
|
+
for (const n of app.graph._nodes) {
|
|
51
|
+
n.selected = n.id === node.id;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 设置 selected_nodes
|
|
55
|
+
if (app.canvas) {
|
|
56
|
+
app.canvas.selected_nodes = [node];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 聚焦到节点 - 使用与selectNodeAndFocus相同的方法
|
|
60
|
+
if (app.canvas && typeof app.canvas.centerOnNode === 'function') {
|
|
61
|
+
console.log('[nodeFocusHandler] 使用 centerOnNode 方法聚焦节点');
|
|
62
|
+
app.canvas.centerOnNode(node);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 刷新画布
|
|
66
|
+
if (app.canvas) {
|
|
67
|
+
app.canvas.setDirty(true, true);
|
|
68
|
+
if (typeof app.canvas.draw === 'function') {
|
|
69
|
+
app.canvas.draw(true, true);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 恢复冻结模式
|
|
74
|
+
setTimeout(() => {
|
|
75
|
+
if (wasFreezed && freezeOverlay) {
|
|
76
|
+
freezeOverlay.style.display = originalOverlayDisplay;
|
|
77
|
+
|
|
78
|
+
// 恢复事件阻止
|
|
79
|
+
if (globalEventBlocked) {
|
|
80
|
+
document.addEventListener('keydown', keyboardListener, true);
|
|
81
|
+
document.addEventListener('contextmenu', contextMenuListener, true);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 再次刷新画布
|
|
86
|
+
if (app.canvas) {
|
|
87
|
+
app.canvas.setDirty(true, true);
|
|
88
|
+
if (typeof app.canvas.draw === 'function') {
|
|
89
|
+
app.canvas.draw(true, true);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}, 100);
|
|
93
|
+
|
|
94
|
+
console.log('[nodeFocusHandler] focusNodeOnly 完成');
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 处理画布节点点击事件
|
|
99
|
+
export function handleCanvasNodeClick(e) {
|
|
100
|
+
if (!app || !app.graph) return;
|
|
101
|
+
|
|
102
|
+
// 获取点击的节点
|
|
103
|
+
const nodeUnderMouse = getNodeUnderMouse(e);
|
|
104
|
+
if (!nodeUnderMouse) return;
|
|
105
|
+
|
|
106
|
+
console.log('[nodeFocusHandler] 画布点击节点:', nodeUnderMouse.id, nodeUnderMouse.title);
|
|
107
|
+
|
|
108
|
+
// 发送消息到前端,通知节点被点击
|
|
109
|
+
window.parent.postMessage({
|
|
110
|
+
type: 'CANVAS_NODE_CLICKED',
|
|
111
|
+
nodeId: nodeUnderMouse.id,
|
|
112
|
+
nodeTitle: nodeUnderMouse.title,
|
|
113
|
+
nodeType: nodeUnderMouse.type
|
|
114
|
+
}, '*');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// 获取鼠标下方的节点
|
|
118
|
+
function getNodeUnderMouse(e) {
|
|
119
|
+
if (!app || !app.graph) return null;
|
|
120
|
+
|
|
121
|
+
// 获取画布位置
|
|
122
|
+
const canvas = document.querySelector('canvas');
|
|
123
|
+
if (!canvas) return null;
|
|
124
|
+
|
|
125
|
+
// 转换为图形坐标
|
|
126
|
+
const pos = app.canvas.convertEventToCanvasOffset(e);
|
|
127
|
+
|
|
128
|
+
// 检查点击位置是否在某个节点上
|
|
129
|
+
const node = app.graph.getNodeOnPos(pos[0], pos[1]);
|
|
130
|
+
return node;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 设置画布点击事件监听
|
|
134
|
+
export function setupCanvasClickHandler() {
|
|
135
|
+
// 移除现有的事件监听器
|
|
136
|
+
removeCanvasClickHandler();
|
|
137
|
+
|
|
138
|
+
// 添加画布点击事件监听
|
|
139
|
+
const canvas = document.querySelector('canvas');
|
|
140
|
+
if (canvas) {
|
|
141
|
+
canvas.addEventListener('click', handleCanvasNodeClick);
|
|
142
|
+
console.log('[nodeFocusHandler] 画布点击事件监听器已设置');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 移除画布点击事件监听
|
|
147
|
+
export function removeCanvasClickHandler() {
|
|
148
|
+
const canvas = document.querySelector('canvas');
|
|
149
|
+
if (canvas) {
|
|
150
|
+
canvas.removeEventListener('click', handleCanvasNodeClick);
|
|
151
|
+
console.log('[nodeFocusHandler] 画布点击事件监听器已移除');
|
|
152
|
+
}
|
|
153
|
+
}
|