* fix(canvas): 分镜脚本节点文字溢出与视频模型下拉异常 #84 - CompactInput 补齐 overflow-y-auto/whitespace-pre-wrap/break-words,长文本不再横向溢出撑开列宽 - filterModelsByCapability 增加 modelCosts[].protocol 协议层回退,未显式配置 capability 时通过协议识别能力 - isVideoModelName 扩展 pika/runway/gen-3/hunyuan-video 等主流视频模型名关键字 - ModelPicker.options 保留当前选中 value,避免过滤后 options 为空触发跳转设置页 * fix(canvas): 模型过滤协议反向排除 + 分镜脚本节点模型选择提示 #84 - filterModelsByCapability 协议层提升至最高优先级,协议明确属于其他能力时直接排除, 防止 video/image/audio 协议的模型被误标为 text 后混入文本下拉 - isVideoModelName 补充 cogvideo/mochi/latte/stable-video/svd/animatediff/ltx-video/minimax-video/abab-video 等关键字 - isImageModelName 补充 nano-banana/ideogram/recraft/playground/leonardo 等关键字 - 分镜脚本节点 ModelPicker 包裹 Tooltip,提示"脚本生成仅支持文本模型" * fix(canvas): 节点标题截断修复 — flex min-width 约束 + 宽度边界 + hover tooltip - NodeExternalHeader: 容器增加 max-w-full 双重约束,窄节点时不越界,宽节点时上限 240px - NodeExternalHeader: 标题 span 增加 min-w-0,解决 flex min-width:auto 导致 truncate 失效 - 所有节点标题(绘图/技能/角色参考/音频/分镜脚本)增加 title 属性,hover 显示完整标题 - AudioNodeContent: 标题 span 增加 min-w-0,修复 flex 子项截断 * fix(canvas): 节点顶部标题真正截断 — JS 计算 maxWidth + overflow-hidden + flex-1 - NodeExternalHeader 容器: 移除 Tailwind 级联冲突的 max-w-[240px]/max-w-full, 改用 JS 计算 Math.min(240, node.width) 作为 inline style maxWidth, 从根本上解决两个 max-width 声明的优先级不确定问题 - 容器增加 overflow-hidden 作为第二道防线 - 内部 text/input/button 元素改用 flex-1 + min-w-0 替代固定 max-w-[Npx], 让 flex 子项自动填充可用空间,文本在剩余空间内截断 * fix(canvas): 节点标题缩放溢出 — 考虑 canvas zoom scale - maxHeaderWidth 改为 Math.min(240, node.width * scale), 因为 header 的视觉宽度 = maxHeaderWidth(inverseScale 与 canvas scale 抵消), 而节点的视觉宽度 = node.width * scale,两者必须比较同一维度 - 修复 zoom 缩小时(scale < 1)header 视觉宽度超过节点视觉宽度的溢出问题 --------- Co-authored-by: sikongyue <3155157671@qq.com>
This commit is contained in:
@@ -126,7 +126,7 @@ export function CanvasScriptNodeContent({ node, batch, pipeline, scale, mentionR
|
||||
<div className="relative flex h-full w-full flex-col overflow-visible" style={{ color: theme.node.text }} onDoubleClick={(event) => event.stopPropagation()}>
|
||||
<div className="relative flex h-10 shrink-0 items-center gap-2 rounded-t-[17px] border-b px-4" style={{ borderColor: theme.node.stroke, background: theme.node.panel }}>
|
||||
<Clapperboard className="size-4" />
|
||||
<span className="min-w-0 flex-1 truncate text-sm font-semibold">{node.title || "分镜脚本"}</span>
|
||||
<span className="min-w-0 flex-1 truncate text-sm font-semibold" title={node.title || "分镜脚本"}>{node.title || "分镜脚本"}</span>
|
||||
{batchSummary ? <span className="min-w-0 max-w-[42%] truncate text-[11px] font-medium" title={batchSummary} style={{ color: batch?.status === "partial_failed" ? theme.accent.danger : theme.node.muted }}>{batchSummary}</span> : taskFeedback ? <span className="min-w-0 max-w-[38%] truncate text-[11px] font-medium" title={taskFeedback} style={{ color: node.metadata?.status === "error" ? theme.accent.danger : theme.node.muted }}>{taskFeedback}</span> : null}
|
||||
<span className="text-xs font-medium" style={{ color: theme.node.muted }}>{rows.length} 镜 · {totalDuration}s</span>
|
||||
{batch ? <>
|
||||
@@ -210,19 +210,21 @@ export function CanvasScriptNodeContent({ node, batch, pipeline, scale, mentionR
|
||||
onWheel={(event) => event.stopPropagation()}
|
||||
/>
|
||||
<div className="flex min-w-0 items-center justify-end gap-2" onMouseDown={(event) => event.stopPropagation()} onPointerDown={(event) => event.stopPropagation()}>
|
||||
<div className="mr-auto min-w-36 max-w-56 flex-1">
|
||||
<ModelPicker
|
||||
className="!h-7 !w-full !min-w-0 !text-[10px] !font-normal [&_img]:!size-3 [&_.lucide]:!size-3"
|
||||
fullWidth
|
||||
config={generationConfig}
|
||||
value={generationConfig.model}
|
||||
capability="text"
|
||||
placeholder="选择文本模型"
|
||||
showSelectedPrice={false}
|
||||
onChange={onModelChange}
|
||||
onMissingConfig={() => navigateToSettings({ continueCreation: true })}
|
||||
/>
|
||||
</div>
|
||||
<Tooltip title="脚本生成需要文本理解与结构化输出能力,仅展示文本模型;视频/图片模型无法生成分镜表" placement="topLeft">
|
||||
<div className="mr-auto min-w-36 max-w-56 flex-1">
|
||||
<ModelPicker
|
||||
className="!h-7 !w-full !min-w-0 !text-[10px] !font-normal [&_img]:!size-3 [&_.lucide]:!size-3"
|
||||
fullWidth
|
||||
config={generationConfig}
|
||||
value={generationConfig.model}
|
||||
capability="text"
|
||||
placeholder="选择文本模型"
|
||||
showSelectedPrice={false}
|
||||
onChange={onModelChange}
|
||||
onMissingConfig={() => navigateToSettings({ continueCreation: true })}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
{simpleMode ? <span className="text-[11px]" style={{ color: theme.node.muted }}>自动拆分 · 默认时长</span> : <Select<StoryboardShotCount>
|
||||
className="min-w-32"
|
||||
size="small"
|
||||
@@ -448,7 +450,7 @@ export function CanvasScriptEditor({ node, open, onClose, onUpdateRows, onVisibl
|
||||
}
|
||||
|
||||
function CompactInput({ value, placeholder, borderColor, onChange }: { value: string; placeholder: string; borderColor: string; onChange: (value: string) => void }) {
|
||||
return <textarea className="h-full resize-none border-r bg-transparent px-4 py-2.5 text-xs leading-5 outline-none transition placeholder:opacity-35 focus:bg-black/[0.02] dark:focus:bg-white/[0.025]" style={{ borderColor }} value={value} placeholder={placeholder} onChange={(event) => onChange(event.target.value)} onMouseDown={(event) => event.stopPropagation()} onPointerDown={(event) => event.stopPropagation()} />;
|
||||
return <textarea className="thin-scrollbar h-full w-full resize-none overflow-y-auto overflow-x-hidden whitespace-pre-wrap break-words border-r bg-transparent px-4 py-2.5 text-xs leading-5 outline-none transition placeholder:opacity-35 focus:bg-black/[0.02] dark:focus:bg-white/[0.025]" style={{ borderColor }} value={value} placeholder={placeholder} onChange={(event) => onChange(event.target.value)} onMouseDown={(event) => event.stopPropagation()} onPointerDown={(event) => event.stopPropagation()} />;
|
||||
}
|
||||
|
||||
function HeaderCell({ children, borderColor, align = "left" }: { children: ReactNode; borderColor: string; align?: "left" | "center" }) {
|
||||
|
||||
Reference in New Issue
Block a user