feat(canvas): 画布工作台 - 新增生成副本并修复大型画布性能、素材同步与删除校验
统一图片与视频副本的生成落点并保留参考连接。\n优化大型画布节点虚拟化、媒体懒加载、拖拽与详情进入路径。\n修复素材主版本 ID 同步及删除时的画布独立引用校验。
This commit is contained in:
1 parent
434f63e153
commit
3f4a9ea3d0
45 files changed
+1348
-286
No files matched your search
@@ -74,17 +74,56 @@ export function buildAssetMentionReferences(assets: Asset[]): CanvasResourceRefe
|
||||
});
|
||||
}
|
||||
|
||||
export function buildCanvasResourceReferences(nodes: CanvasNodeData[], connections: CanvasConnection[], contextNodeId?: string | null) {
|
||||
export function buildCanvasResourceReferences(nodes: CanvasNodeData[], connections: CanvasConnection[], contextNodeId?: string | null, targetNodes?: CanvasNodeData[]) {
|
||||
const contextNodes = contextNodeId ? getMentionResourceNodes(contextNodeId, nodes, connections) : [];
|
||||
const globalReferences = labelResourceNodes(nodes.filter(isResourceNode), false);
|
||||
const sourceNodes = targetNodes ? uniqueCanvasNodes([...targetNodes, ...contextNodes]) : nodes;
|
||||
const globalReferences = labelResourceNodes(sourceNodes.filter(isResourceNode), false);
|
||||
const activeByNodeId = new Map(labelResourceNodes(contextNodes, true).map((reference) => [reference.nodeId, reference]));
|
||||
return globalReferences.map((reference) => activeByNodeId.get(reference.nodeId) || reference);
|
||||
}
|
||||
|
||||
function uniqueCanvasNodes(nodes: CanvasNodeData[]) {
|
||||
const seen = new Set<string>();
|
||||
return nodes.filter((node) => {
|
||||
if (seen.has(node.id)) return false;
|
||||
seen.add(node.id);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
export function buildNodeMentionReferences(node: CanvasNodeData, nodes: CanvasNodeData[], connections: CanvasConnection[]) {
|
||||
return labelResourceNodes(getMentionResourceNodes(node.id, nodes, connections), true);
|
||||
}
|
||||
|
||||
export function buildCanvasNodeMentionReferenceMap(nodes: CanvasNodeData[], connections: CanvasConnection[], targetNodes: CanvasNodeData[] = nodes) {
|
||||
const nodeById = new Map(nodes.map((node) => [node.id, node]));
|
||||
const resourceInputsByTargetId = new Map<string, CanvasNodeData[]>();
|
||||
const configTargetBySourceId = new Map<string, string>();
|
||||
for (const connection of connections) {
|
||||
const source = nodeById.get(connection.fromNodeId);
|
||||
const target = nodeById.get(connection.toNodeId);
|
||||
if (!source || !target) continue;
|
||||
if (isResourceNode(source)) {
|
||||
const inputs = resourceInputsByTargetId.get(target.id) || [];
|
||||
inputs.push(source);
|
||||
resourceInputsByTargetId.set(target.id, inputs);
|
||||
}
|
||||
if (target.type === CanvasNodeType.Config && !configTargetBySourceId.has(source.id)) {
|
||||
configTargetBySourceId.set(source.id, target.id);
|
||||
}
|
||||
}
|
||||
|
||||
const referencesByNodeId = new Map<string, CanvasResourceReference[]>();
|
||||
for (const node of targetNodes) {
|
||||
const configTargetId = configTargetBySourceId.get(node.id);
|
||||
const configInputs = configTargetId ? (resourceInputsByTargetId.get(configTargetId) || []).filter((input) => input.id !== node.id) : [];
|
||||
const ownInputs = resourceInputsByTargetId.get(node.id) || [];
|
||||
const inputs = configInputs.length ? configInputs : ownInputs.length ? ownInputs : isResourceNode(node) ? [node] : [];
|
||||
referencesByNodeId.set(node.id, labelResourceNodes(inputs, true));
|
||||
}
|
||||
return referencesByNodeId;
|
||||
}
|
||||
|
||||
export function buildOrderedCanvasResourceReferences(nodes: CanvasNodeData[], active = true) {
|
||||
return labelResourceNodes(nodes.filter(isResourceNode), active);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user