diff --git a/static/src/components/chat/MinimalBlocks.vue b/static/src/components/chat/MinimalBlocks.vue index bf922368..d31bc0ab 100644 --- a/static/src/components/chat/MinimalBlocks.vue +++ b/static/src/components/chat/MinimalBlocks.vue @@ -1216,6 +1216,18 @@ onBeforeUnmount(() => { .steps-wrapper { overflow: hidden; min-height: 0; + /* content-visibility 进过渡列表:收起动画(grid 0.3s)播完才跳过子树渲染, + 展开时立即恢复渲染;不支持的引擎退化为收起时立即跳过 */ + transition: content-visibility 0.3s; + transition-behavior: allow-discrete; +} + +/* 折叠态跳过整个子树渲染:0fr 折叠只裁视觉,DOM 仍全量参与布局, + 几千节点的步骤组会在窗口拖拽时逐帧重排导致卡顿。 + 隐藏翻转由上方过渡延迟到收起动画结束后生效 */ +.steps-container:not(.show) .steps-wrapper { + content-visibility: hidden; + contain-intrinsic-size: 0; } .steps-wrapper.height-limited { diff --git a/static/src/styles/components/chat/_chat-area.scss b/static/src/styles/components/chat/_chat-area.scss index 3ad8647a..71c40260 100644 --- a/static/src/styles/components/chat/_chat-area.scss +++ b/static/src/styles/components/chat/_chat-area.scss @@ -1364,9 +1364,15 @@ body[data-theme='dark'] .collapsible-header:hover { max-height: 0; overflow: hidden; opacity: 0; + /* content-visibility 也进过渡列表:收起动画播完才跳过子树渲染, + 展开时立即恢复渲染(离散属性的方向性插值),收起动画得以完整呈现 */ transition: max-height 260ms cubic-bezier(0.4, 0, 0.2, 1), - opacity 220ms cubic-bezier(0.4, 0, 0.2, 1); + opacity 220ms cubic-bezier(0.4, 0, 0.2, 1), + content-visibility 260ms; + /* 让离散属性可过渡;不支持的引擎忽略此属性,退化为收起时立即跳过渲染, + max-height/opacity 动画本体不受影响 */ + transition-behavior: allow-discrete; /* 始终隐藏滚动条,避免堆叠模式展开时闪现 */ scrollbar-width: none; -ms-overflow-style: none; @@ -1377,6 +1383,15 @@ body[data-theme='dark'] .collapsible-header:hover { display: none; } +/* 折叠态跳过整个子树渲染:max-height:0 只裁视觉,DOM 仍全量参与布局, + 大步骤组/长思维链会在窗口拖拽时逐帧重排导致卡顿。 + 隐藏翻转由上方过渡延迟到收起动画结束后生效;展开时立即恢复渲染, + 由 rAF 测量强制同步布局取真实高度,不受影响。 */ +.collapsible-block:not(.expanded) .collapsible-content { + content-visibility: hidden; + contain-intrinsic-size: 0; +} + .collapsible-block.expanded .collapsible-content { max-height: var(--collapse-max, 600px); overflow-y: auto; @@ -1550,10 +1565,12 @@ body[data-theme='dark'] .more-icon { transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1); } +/* 堆叠块收起/展开不做淡出:内容保持不透明,由收缩的容器自然裁切(与极简模式一致)。 + 注意:不要再给 .stacked-block .collapsible-content 重声明 transition—— + 它会以更高特异性覆盖 .collapsible-content 基础规则(含 content-visibility 过渡), + 曾因漏写 content-visibility 导致收起时内容瞬间消失、块高瞬间坍塌。 */ .stacked-block .collapsible-content { - transition: - max-height 260ms cubic-bezier(0.4, 0, 0.2, 1), - opacity 220ms cubic-bezier(0.4, 0, 0.2, 1); + opacity: 1; } .progress-indicator {