背景与历史问题
新的技术方案
根据经验及业界通用做法,**推荐方案为:
- 用 CSS 限死按钮容器高度 &
overflow: hidden(始终保证 header 不换行/撑高)
- 在运行时(浏览器端)用
ResizeObserver/MutationObserver 监听实际宽度、动态调整按钮折叠/收起(用 clientWidth/scrollWidth、display:none/ellipsis、dropdown)
- 组件解耦 schema 生成与实际渲染,所有横向溢出检测必须在渲染后、非 schema 阶段做处理
TODO
重要历史分支/PR/Issue 关联
关键代码结构与约束(补充)
按钮容器 DOM 结构
header.js 的 getObjectRecordDetailHeader 函数最终将按钮数组包裹在 amis flex 组件中:
gridBody.push({
"body": {
"type": "flex",
"items": amisButtonsSchema, // ← 所有按钮在此横向排列
},
"md": "auto",
"columnClassName": "flex justify-center items-center"
})
外层最终输出的 class 为 steedos-object-record-detail-header。
已有的按钮间距样式
packages/@steedos-widgets/amis-object/src/styles/object.less:
.steedos-object-record-detail-header {
button[class~="steedos-object-button"] {
margin-left: 4px;
}
}
可修改的样式文件
| 文件 |
说明 |
packages/@steedos-widgets/amis-object/src/amis/AmisRecordDetailHeader.less |
header 组件专用样式,含 compact-layouts、mobile 响应式 |
packages/@steedos-widgets/amis-object/src/styles/object.less |
通用对象样式,含按钮间距 |
packages/@steedos-widgets/amis-object/src/amis/AmisInstanceDetail.less |
审批页面专用样式 |
硬约束���不可破坏)
- header 高度 65px —
flow.js 中 calc(100% - 65px) 写死了 body 高度,不能让按钮换行撑高 header
- 滚动触发审批 drawer —
flow.js 依赖 .steedos-amis-instance-view-body 的 scrollHeight/clientHeight/scrollTop
- 不能用
flex-wrap — 换行会破坏上述两个约束
之前方案失败的根因总结
| 问题 |
根因 |
| 贪心算法在 schema 阶段运行 |
DOM 未渲染,offsetWidth 始终为 0,fallback 估算偏差 196-406px |
| 用全量 action 计算宽度 |
uiSchema 返回 24 个 action,但运行时 visibleOn 会隐藏大部分,实际只显示 ~8 个 |
| 字符宽度估算不可靠 |
uiSchema 返回中文 label(如"保存"),但 UI 显示英文(如"Save"),宽度完全不同 |
moreButtonsVisibleOn 拼接逻辑 |
空字符串 '' 被 amis 视为始终显示,导致空 dropdown |
推荐的新方案思路
核心原则:schema 阶段不做任何宽度限制,全部交给运行时处理。
- CSS 兜底:给按钮容器加
overflow: hidden; max-height: 65px; flex-wrap: nowrap;,确保无论如��� header 不撑高
- 运行时检测:在
AmisRecordDetailHeader 组件的 React 生命周期(或 amis 的 onMount 事件)中,用 ResizeObserver 监听按钮容器
- 动态折叠:当
scrollWidth > clientWidth 时,从右往左将按钮移入一个运行时创建的 dropdown,直到不再溢出
- 响应式恢复:窗口放大时,从 dropdown 中取出按钮放回容器,直到再次溢出
这个方案的优势:
- 完全基于真实渲染后的 DOM 宽度,零估算误差
- 自动适配 i18n(中/英/日文按钮宽度不同)
- 自动适配
visibleOn(只计算实际可见的按钮)
- 自动适配任意分辨率,包括浏览器缩放
需要修改的文件
| 文件 |
修改内容 |
AmisRecordDetailHeader.less 或 object.less |
添加按钮容器 overflow: hidden 兜底样式 |
AmisRecordDetailHeader.tsx |
添加 ResizeObserver 运行时折叠逻辑 |
buttons.js |
不需要修改(保持还原后的原始逻辑) |
header.js |
不需要修改(保持还原后的原始逻辑) |
背景与历史问题
新的技术方案
根据经验及业界通用做法,**推荐方案为:
overflow: hidden(始终保证 header 不换行/撑高)ResizeObserver/MutationObserver监听实际宽度、动态调整按钮折叠/收起(用 clientWidth/scrollWidth、display:none/ellipsis、dropdown)TODO
重要历史分支/PR/Issue 关联
关键代码结构与约束(补充)
按钮容器 DOM 结构
header.js的getObjectRecordDetailHeader函数最终将按钮数组包裹在 amisflex组件中:外层最终输出的 class 为
steedos-object-record-detail-header。已有的按钮间距样式
packages/@steedos-widgets/amis-object/src/styles/object.less:可修改的样式文件
packages/@steedos-widgets/amis-object/src/amis/AmisRecordDetailHeader.lesspackages/@steedos-widgets/amis-object/src/styles/object.lesspackages/@steedos-widgets/amis-object/src/amis/AmisInstanceDetail.less硬约束���不可破坏)
flow.js中calc(100% - 65px)写死了 body 高度,不能让按钮换行撑高 headerflow.js依赖.steedos-amis-instance-view-body的scrollHeight/clientHeight/scrollTopflex-wrap— 换行会破坏上述两个约束之前方案失败的根因总结
offsetWidth始终为 0,fallback 估算偏差 196-406pxvisibleOn会隐藏大部分,实际只显示 ~8 个moreButtonsVisibleOn拼接逻辑''被 amis 视为始终显示,导致空 dropdown推荐的新方案思路
核心原则:schema 阶段不做任何宽度限制,全部交给运行时处理。
overflow: hidden; max-height: 65px; flex-wrap: nowrap;,确保无论如��� header 不撑高AmisRecordDetailHeader组件的 React 生命周期(或 amis 的onMount事件)中,用ResizeObserver监听按钮容器scrollWidth > clientWidth时,从右往左将按钮移入一个运行时创建的 dropdown,直到不再溢出这个方案的优势:
visibleOn(只计算实际可见的按钮)需要修改的文件
AmisRecordDetailHeader.less或object.lessoverflow: hidden兜底样式AmisRecordDetailHeader.tsxResizeObserver运行时折叠逻辑buttons.jsheader.js