feat(canvas): manual node linking + no-model hint + render-hardening

- drag from a node's side port onto another node to create an edge
  (dashed live preview, dedupe, self-link rejected); click an edge to
  select (highlighted), Delete removes it, Ctrl+Z restores — all in
  undo history and autosave
- generate panel shows an explicit hint when the site has no image
  models instead of an empty dropdown
- render hardening: viewport-culling size now has a hard floor
  (max(stageSize, window, 1600x900)) so a delayed/degenerate
  ResizeObserver reading can never cull nodes out of the DOM; stage
  listeners attach with retry + rAF self-healing measure; pointer
  capture wrapped in try/catch for synthetic pointers
This commit is contained in:
dokploy-bot
2026-09-20 00:06:08 +08:00
parent 38367c36ab
commit 910651ddba
3 changed files with 224 additions and 26 deletions
@@ -99,6 +99,8 @@ defineExpose({ startEdit, commitNote })
:data-node-id="node.id"
@dblclick="onSelfDblClick"
>
<!-- 连线出口:拖到目标节点创建连线(舞台接管手势) -->
<span v-if="node.type !== 'gen'" class="cv-port" data-port="out" />
<!-- 图片节点 -->
<template v-if="node.type === 'image'">
<img
@@ -241,4 +243,24 @@ defineExpose({ startEdit, commitNote })
text-overflow: ellipsis;
white-space: nowrap;
}
.cv-port {
position: absolute;
right: -8px;
top: 50%;
transform: translateY(-50%);
width: 13px;
height: 13px;
border-radius: 50%;
background: #7c6cff;
border: 2.5px solid #0e1015;
opacity: 0;
transition: opacity 0.12s;
cursor: crosshair;
z-index: 2;
}
.cv-node:hover .cv-port,
.cv-node.is-selected .cv-port {
opacity: 1;
}
</style>