Skip to content

审批单详情页按钮栏小分辨率溢出根本解决方案议题(关联 #584, steedos-plugins#311) #592

@yinlianghui

Description

@yinlianghui

背景与历史问题

新的技术方案

根据经验及业界通用做法,**推荐方案为:

  1. 用 CSS 限死按钮容器高度 & overflow: hidden(始终保证 header 不换行/撑高)
  2. 在运行时(浏览器端)用 ResizeObserver/MutationObserver 监听实际宽度、动态调整按钮折叠/收起(用 clientWidth/scrollWidth、display:none/ellipsis、dropdown)
  3. 组件解耦 schema 生成与实际渲染,所有横向溢出检测必须在渲染后、非 schema 阶段做处理

TODO

  • 评估 amis/steedos-header 是否支持运行时折叠按钮,抽象 dropdown 触发逻辑
  • 草拟 DEMO,用 CSS + JS 方式原型实现,仅控制 DOM/样式,不动按钮 schema
  • 技术调研:amis、antd、element-ui 等桌面 UI 如何做 toolbar 溢出折叠
  • 迁移老 header 逻辑,保证 65px 高度、所有功能按钮均可达到、兼顾多国语言与权限
  • 充分测试不同分辨率/多语言/按钮数量组合

重要历史分支/PR/Issue 关联

关键代码结构与约束(补充)

按钮容器 DOM 结构

header.jsgetObjectRecordDetailHeader 函数最终将按钮数组包裹在 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 审批页面专用样式

硬约束���不可破坏)

  1. header 高度 65pxflow.jscalc(100% - 65px) 写死了 body 高度,不能让按钮换行撑高 header
  2. 滚动触发审批 drawerflow.js 依赖 .steedos-amis-instance-view-bodyscrollHeight/clientHeight/scrollTop
  3. 不能用 flex-wrap — 换行会破坏上述两个约束

之前方案失败的根因总结

问题 根因
贪心算法在 schema 阶段运行 DOM 未渲染,offsetWidth 始终为 0,fallback 估算偏差 196-406px
用全量 action 计算宽度 uiSchema 返回 24 个 action,但运行时 visibleOn 会隐藏大部分,实际只显示 ~8 个
字符宽度估算不可靠 uiSchema 返回中文 label(如"保存"),但 UI 显示英文(如"Save"),宽度完全不同
moreButtonsVisibleOn 拼接逻辑 空字符串 '' 被 amis 视为始终显示,导致空 dropdown

推荐的新方案思路

核心原则:schema 阶段不做任何宽度限制,全部交给运行时处理。

  1. CSS 兜底:给按钮容器加 overflow: hidden; max-height: 65px; flex-wrap: nowrap;,确保无论如��� header 不撑高
  2. 运行时检测:在 AmisRecordDetailHeader 组件的 React 生命周期(或 amis 的 onMount 事件)中,用 ResizeObserver 监听按钮容器
  3. 动态折叠:当 scrollWidth > clientWidth 时,从右往左将按钮移入一个运行时创建的 dropdown,直到不再溢出
  4. 响应式恢复:窗口放大时,从 dropdown 中取出按钮放回容器,直到再次溢出

这个方案的优势:

  • 完全基于真实渲染后的 DOM 宽度,零估算误差
  • 自动适配 i18n(中/英/日文按钮宽度不同)
  • 自动适配 visibleOn(只计算实际可见的按钮)
  • 自动适配任意分辨率,包括浏览器缩放

需要修改的文件

文件 修改内容
AmisRecordDetailHeader.lessobject.less 添加按钮容器 overflow: hidden 兜底样式
AmisRecordDetailHeader.tsx 添加 ResizeObserver 运行时折叠逻辑
buttons.js 不需要修改(保持还原后的原始逻辑)
header.js 不需要修改(保持还原后的原始逻辑)

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions