JMOS 第二批改进样张 · motion-batch2(候选,未并入 app/jmos)
留档说明(2026-10-09):样张代码在
prototypes/motion-batch2/,未并入主应用。文中提到的*.patch是当时交付的补丁,内容就是该目录;补丁文件本身不入库。
- 基线:6782659 +
prototypes/motion-batch1(第一批修正后的版本)。样张在prototypes/motion-batch2/,运行node server.mjs后打开 (本机预览地址) 。 - 对照:
/before/<页面>是第一批样张,/sample/<页面>是第一批 + 第二批,/demo.html是组件演示页。 - 产出:
motion-batch2.png(1960×4942,左原 / 右改后;第 ⑦ 段为修订后的逐帧截图)、motion-batch2.mp4(约 69 秒,5.0MB;含组件演示、07 指示器与 ⌘K、10 详情、03 KPI、13 修复、390 搜索、手机 07)、motion-batch2-sample.patch(只含prototypes/motion-batch2/)、preview-index-footer.patch。 - 没有改 app/jmos、05 的已批准角度和参数,也没有新增依赖。
- 数值和做法参考 RhineLabUI(MIT):reference.md 3.2–3.5 和 4.1 中第 1、2、4、10、11 项。代码都是新写的,没有复制片段,所以不需要附 MIT 声明;没有使用莱茵生命的名称、配色或字体。
- 颜色只用 v1 语义 token,没有新增 HEX、rgba、color-mix 或具名颜色,也没有模糊效果(已用 grep 检查)。
0. 第二批修订(10-09,北京时间)
在第一版之后补了四处:(a)(b) 两项小改,加上复看录屏发现的两个问题。都只改 prototypes/motion-batch2/。
| # | 问题 | 原因 | 改法 |
|---|---|---|---|
| 1 | ⌘K 回车选中结果(旧录屏约 0:25):列表一下子没了,只剩带阴影的空白盒子停几帧才退场;遮罩和外壳也没有平滑淡出 | 面板自己做透明度淡出,又放在同样在淡出的遮罩里,实际透明度是两者相乘,内容提前看不见;同时导航和对话框退场同时开始,07 切舞台的重活抢了退场的帧 | 回车和 Esc 走同一套退场:面板只做位移(shift),透明度只由遮罩做,200ms 线性,内容跟容器一起淡出;退场结束后才清空、才执行导航;退场期间用 prepare 在幕后准备目标(同页就地选中、07 里预先让 A-02 选中新项) |
| 2 | 窄屏 ⌘K 回车跳到待确认队列(旧录屏约 0:51–0:52):画面闪一下,内容瞬间错位 | 单独打开的 10 里「去确认」会重新加载本页(闪一下);手机 07 跨应用跳转时舞台从中间的应用一路扫过去;飞入时显示的是旧截图,落地后才换成真实界面(错位、旧选中项) | 目标是本页时就地选中,不重新加载;手机 07 用第一批的切页规则做相邻滑入:目标先放到当前页旁边,中间的应用不带过渡地让开,只看到当前页和目标页;飞入时直接显示已经选中新项的真实界面(mb2-live),不再先显示截图 |
| (a) | 手机 / 竖屏 07 没有可见的搜索入口 | — | 顶部聚焦条加 44×44 搜索按钮(aria-label 全局搜索,键盘可达),点开全局搜索 |
| (b) | 「去确认」→ 10 时先显示旧选中项约 0.4s | 同 2 | 同 2:一出现就是新选中项 |
新增自动检查(verify.mjs behave):
- 回车选中时内容跟随容器退场:逐帧记录面板 × 遮罩的实际透明度、结果行数、列表高度。要求:可见期间行数和高度不变;透明度单调下降,60ms 内就低于 0.98;20–180ms 与线性
1 − t/200的偏差 < 0.12;170–320ms 之间隐藏。07(1440)、单独打开的 10(390)、手机 07 各测一次。 - 390 · 10 回车「去确认」:不重新加载,首帧就是新选中项。
- 手机 07:搜索按钮 44px;跳到队列时不扫过中间应用;飞入期间显示的是选中新项的真实界面。
修订后全量重跑,两个引擎的结果见第 6 节。重录的 motion-batch2.mp4 里这两处在 0:26 前后(07 回车)和 0:58–1:06(390 的 10、手机 07);逐帧检查记录见第 7 节。还剩一处:07 里退场结束到舞台开始移动之间约有 250ms 停顿(等目标窗口准备好),不闪、不错位,先保留。
1. 长短竖线页码指示器(JMTicks)
| 项 | 取值 |
|---|---|
| 线 | 2px 宽;未选 12px --jm-border-strong,选中 28px --jm-text-1,悬停 20px --jm-text-3;同组线间距更紧 |
| 区分选中 | 靠长度(28 对 12,相差 16px),颜色只是辅助;选中不用琥珀,避免和 #af541a 主按钮语义混淆 |
| 数字 | 始终显示「03 / 12」,等宽数字;切换时数字滚动 |
| 触控 | 轨道 44px 高,点在线附近即命中最近一根;可拖动;前后按钮 44×44 |
| 键盘 / 读屏 | role=slider,←/→、Home/End;aria-valuenow/aria-valuetext 带名称 |
| 动效 | 180ms;「工作区」分组关闭或系统减少动态效果时直接切换 |
接入位置:
- 05 应用中心底部:只改原刻度尺的选中表达(原来选中靠琥珀色,改为正文色长线),热区扩到 44px,点刻度附近即切到最近的应用。卡片角度、键盘、点击行为与原页逐项比对一致(1440/2560/390 各 2 项,共 6/6)。
- 07 工作台:桌面在左侧条底部,每个应用一根,按窗口组分组,顺序稳定;手机放在顶部聚焦条里。点刻度切换舞台应用,复用 07 原有的切换逻辑。
2. 数字滚动(JMRoll)
- 规则:
- 变化时只滚动变化的那几位:240ms,入场曲线,只用位移,不模糊,等宽数字;变大向上滚,变小向下滚。
- 结束后变回纯文本,读屏只读最终值。
- 同值不播;距上次变化不到 500ms(快于 2Hz)直接跳;告警值直接显示。
- 第一批「数字滚动」开关关闭或系统减少动态效果时直接显示(设置面板里这一项不再标「预留」)。
- 接入:
- 03 的实际产量、OEE:演示时钟推数;演示规则把 OEE < 75% 记为告警。
- 07 顶栏待确认角标,01 角标。
- 10 / 04 详情眉标编号(01 / 05)。
- 搜索分类计数,以及新生成的待确认单号。
- 页面第一次接管时,以原有文字为起点,不会从空白滚入。
3. 详情页结构(JMDetail,10 队列详情、04 查看器设备详情)
- 结构依次是:
- 编号眉标「01 / 05 · A-02 · 来源」;
- 大标题(≥26px);
- 副标题;
- 2px 线;
- 两列属性表:键名 12px,中文优先,例如「控制程序(PLC)」;容器 ≥720px 时每行两组,窄时上下排;
- 编号页签:01 概述 / 02 记录 / 03 日志,用第一批的页签下划线动效,支持键盘;
- 正文;
- 主操作条。
- 主按钮沿用现有的 #af541a 变量,白字。
- 长内容跟整页(或整栏)一起滚动,不在小区域里内嵌滚动条(自动检查确认没有内层滚动区)。04 侧栏整栏滚动,操作条吸底。
- 深色下小字对比度最低 5.11(10 / 04)。
4. 全局搜索(⌘K / Ctrl K,JMSearch)
4.1 键位归属(默认,待确认)
旧问题:嵌在 07 里的 13 按 / 后整个舞台切到 12,没有就地打开小锦。
| 键 | 归属 | 说明 |
|---|---|---|
/ | 问小锦 | 有对象焦点时就地问这个对象。03、13 没有对象焦点时就地打开整页小锦面板,嵌在 07 里也一样,这修复了 13 的旧问题。其他嵌入页仍唤起工作台小锦(行为不变) |
| ⌘K / Ctrl K | 全局搜索 | 头部抢先注册监听;嵌在 07 时交给 07 打开对话框(只有一个),单独打开时在本页打开 |
| 例外 | 05 单独打开时 / 仍是它原有的本地搜索;12 的 / 仍是它自己的命令面板 | 两页按 ⌘K 都打开全局搜索 |
- 12 去掉了 ⌘K 提示,01「新对话」上的 Ctrl K 标记也去掉,避免一键两义。
- 07 顶部搜索框获得焦点就打开全局搜索,框内提示 ⌘K。原来按回车进应用中心的行为,改为结果行操作「在应用中心查看」。
- 07「问小锦」按钮的提示改为「唤起小锦(/)…⌘K 是全局搜索」。
与问小锦的关系:搜索负责找东西和跳转,问小锦负责理解、判断和起草。搜索结果下方固定有「问小锦:「关键词」」按钮,把当前查询交给小锦(嵌在 07 时唤起工作台小锦,单独打开时页面有小锦面板就原位打开,否则跳到 12)。两者是两个入口,不重复。
4.2 对话框
- 结构:
- 眉标「⌘K · 全局」、标题「搜索」;
- 16px 下划线输入框(防止 iOS 缩放);
- 分类筛选(全部 / 应用 / 工位 / 报警 / 待确认 / 工单 / 知识),计数会滚动;
- 结果表:编号、名称、状态色标签、位置、操作;
- 底部状态行:结果数、数据来源(演示数据)、数据时间、键位提示。
- 键盘:Esc 关闭,焦点限制在对话框内,↑/↓ 选行,回车执行主操作。
- 动效用第一批 token:进 300ms / 12px;出 200ms,透明度线性、位移 (0.4,0,0.6,1);可中途打断反向。
- 手机(≤720):全屏,结果改为卡片行,按钮 44px。
- 分层:
- 视图
global-search.js只调用用例search-usecase.js(JMSearchCore); - 用例只依赖适配器接口;演示适配器是
search-adapter.demo.js(固定数据,sessionStorage 演示命名空间); boot.js显式选择适配器,并注入宿主(07 的JMHost,或单独打开时的跳转);- 页面和组件不读其他页面的全局变量。
- 写操作:结果行上的「生成待确认」只创建待确认项(演示从 A-1009-041 开始),行内显示单号,单号会滚动,并给出「去确认」。对话框不完成任何业务命令。07 角标 4 → 5 会滚动,「去确认」打开 10 并选中新项,确认仍在队列里由值班人员完成。
5. 预览首页页脚(preview-index-footer.patch)
- 问题:手机宽度下,
tools/pages/build.mjs生成的首页页脚链接是普通行内文字,触控目标不足 44px。 - 修正:页脚 ≤600px 时改为纵向排列,链接最小高度 44px。只改这一处样式。
- 检查:在 6782659 的临时副本上
git apply --check通过。
6. 验证(Chromium + WebKit)
| 项 | 结果 |
|---|---|
| 矩阵 | 144/144(两引擎 × 浅/深 × 390 触屏/768/1440/2560;6 个独立页各自打开 ⌘K + 07 内嵌 10 / 03 / 13):0 报错、0 横向溢出、对话框内无溢出且输入框 16px;07 切主题后内嵌页跟随;07 指示器存在且有选中项 |
| 行为 | 70/70(每个引擎 35 项):数字滚动规则(240ms、只位移、同值 / 快变 / 告警 / 开关关闭);指示器(长度、颜色、44px、「03 / 12」、最近刻度、键盘);03 KPI 与告警;01 角标 4→5;07 指示器;⌘K 搜索与就地生成待确认(角标滚动,10 选中新项且仍为待确认);嵌入页 ⌘K 交给 07;07 / 仍唤起小锦;13 嵌入 / 原 = 换舞台,改后 = 原位;05 / 本地搜索 + ⌘K;12 / 命令面板 + ⌘K;10 / 04 详情结构 × 1440/390;搜索开关时长和线性退出、中途打断;系统减少动态效果;修订新增:回车选中时内容跟随容器退场(07 1440、10 390、手机 07 三处)、390 的 10 就地选中、手机 07 搜索按钮与相邻滑入 |
| 对比度(计算值) | 28/28(10 / 04 详情、搜索框、07 指示器、05 刻度 × 浅/深,正文小字 ≥4.5:1)。最低值:浅色 4.86;深色搜索 4.65(选中行副文字改为 text-2 后)、10 / 04 5.11、指示器 / 刻度 6.04 |
| 05 一致性 | 6/6(1440 / 2560 / 390 下卡片变换、键盘、刻度点击与原页一致) |
| 仓库检查 | npm run check、npm run center:check(4/4)、npm run motion:check(4/4)通过 |
| 截图 / 录屏 | 截图和 png 已逐张看过;录屏逐帧慢放检查过,见第 7 节 |
修订后(10-09 19:35–20:00,北京时间)两引擎全量重跑:矩阵 144/144、行为 70/70、对比度 28/28、05 一致性 6/6。
修正记录:第一次跑矩阵时 132/144,WebKit 2560 下 12 项失败。原因是 2560 时页面 zoom 为 1.25,搜索框 1px 边框让内容宽变成半像素,WebKit 报对话框内 1px 横向溢出(看不出来,但算失败)。描边改用 box-shadow: 0 0 0 1px var(--jm-border) 后,内容宽为整数,然后全量重跑,上面是重跑结果(10-09 19:00 前后,北京时间)。
7. 录屏慢放检查(按第一批暴露过的问题逐帧看)
- 退场拖滞:⌘K 对话框按 Esc 或回车后,约 200ms(5 帧)收完,第一帧就明显变淡。13 里的小锦面板也一样。390 全屏搜索也一样,打开 140ms 时按 Esc,从当前值反向,不跳变。
- 内容提前消失(修订重点,0:26 前后逐帧):回车后列表和外壳一起变淡、一起位移,最后一帧仍能看到完整的结果行,没有空白盒子;遮罩同步淡出。之后 A-02 飞上舞台,飞的过程中显示的已经是选中新项的真实界面。
- 空盒子 / 闪烁 / 错位(修订重点,0:58–1:06 逐帧):390 单独打开的 10 里「去确认」不再重新加载,对话框淡出时底下已经是新选中项;手机 07 跳到队列时只看到当前页和目标页相邻滑入,没有扫过中间应用,没有先显示旧选中项。
- 指示器切换舞台应用时,新窗口一出现就有内容。
8. 局限
- 10 的列表不是由搜索适配器直接供数,新生成的待确认项是经 07 的队列桥加进去的;单独打开 10 时只在角标和计数里体现。
- 07 顶栏角标数字来自 07 自己的计数器,演示适配器通过广播同步。
- 04 页签 02 / 03 的内容是演示数据;10 桌面右栏和 04 侧栏是整栏滚动(列布局本来如此),不是整页滚动。
- 03 的告警规则(OEE < 75%)是演示规则;正式接入时应由数据适配给出显式告警字段,页面不推断。
- 录屏和截图在软件渲染(SwiftShader)下完成,动画时长以
getAnimations()的读数为准。 - 07 里回车选中后,退场结束到舞台开始移动之间约有 250ms 停顿(等目标窗口准备好)。
9. 待决事项(已按默认做,请确认)
/与 ⌘K 的分工:按 4.1 的表。05 单独打开时/仍是本地搜索,算例外。- 01 的「Ctrl K」标记:已去掉。如需保留,应改指全局搜索。
- 10 / 04 没有对象焦点时按
/:目前仍唤起工作台小锦;是否也像 03 / 13 一样就地打开。 - 第一批退出曲线:透明度线性 + 位移 (0.4,0,0.6,1),与原契约的单条 (0.4,0,1,1) 不同,需要更新 motion 契约文档。
- 指示器选中长度:28px(参考值 33px)。为 44px 热区内留出余量,选了 28px。