@jc-times/business-ui 0.2.43 → 0.2.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/AGENTS.md +6 -6
  2. package/CHANGELOG.md +51 -14
  3. package/README.md +7 -7
  4. package/THIRD_PARTY_NOTICES.md +12 -10
  5. package/dist/Cascader.js +8 -0
  6. package/dist/Combobox.js +104 -61
  7. package/dist/DataTableHorizontalScrollbar.js +14 -11
  8. package/dist/FloatingControls.js +14 -13
  9. package/dist/MultilineAutoComplete.js +80 -0
  10. package/dist/SortableList.js +105 -32
  11. package/dist/UserProfilePopover.js +69 -0
  12. package/dist/_virtual/_rolldown/runtime.js +17 -0
  13. package/dist/business-ui.js +41 -38
  14. package/dist/document-viewer/PdfWorkspace.js +14 -12
  15. package/dist/document-viewer-v2/HeadlessPdfViewer.js +147 -142
  16. package/dist/sortable-transfer-scope.js +33 -0
  17. package/dist/styles.css +1 -1
  18. package/dist/types/Combobox.d.ts +1 -0
  19. package/dist/types/FloatingControls.d.ts +2 -1
  20. package/dist/types/MultilineAutoComplete.d.ts +20 -0
  21. package/dist/types/SortableList.d.ts +10 -2
  22. package/dist/types/UserProfilePopover.d.ts +20 -0
  23. package/dist/types/document-viewer/PdfWorkspace.d.ts +2 -1
  24. package/dist/types/document-viewer-v2/HeadlessPdfViewer.d.ts +1 -0
  25. package/dist/types/index.d.ts +2 -0
  26. package/dist/types/sortable-transfer-scope.d.ts +27 -0
  27. package/dist/vendor/embedpdf-zoom-react.js +187 -0
  28. package/docs/agent-guide.md +26 -3
  29. package/docs/api.md +39 -14
  30. package/docs/cascader.md +2 -0
  31. package/docs/component-strategy.md +1 -1
  32. package/docs/data-table.md +124 -120
  33. package/docs/dependencies.md +57 -57
  34. package/docs/document-viewer-v2.md +8 -0
  35. package/docs/document-viewer.md +28 -28
  36. package/docs/file-preparation.md +11 -11
  37. package/docs/maturity-migration.md +62 -62
  38. package/docs/mrt-poc.md +204 -204
  39. package/docs/release.md +32 -32
  40. package/docs/user-profile.md +17 -0
  41. package/docs/viewport-qa.md +37 -7
  42. package/licenses/embedpdf-MIT.txt +21 -0
  43. package/package.json +164 -161
  44. package/patches/@embedpdf__plugin-zoom@2.15.0.patch +77 -0
package/docs/mrt-poc.md CHANGED
@@ -1,205 +1,205 @@
1
- # 表格能力与 MRT 验证样例
2
-
3
- 更新日期:2026-09-12。已决定采用MRT,当前工作树已替代公共DataTable渲染内核并提供独立入口;对应0.2.31;其他服务需单独升级。当前公共API见 [DataTable迁移](data-table.md)。以下合同包装仍是业务验证样例。本文区分现有公共 `DataTable` 与样例能力,不把工作树功能视为已发布 API。
4
-
5
- ## 选用入口
6
-
7
- | 场景 | 当前实现 | 调用边界 |
8
- | --- | --- | --- |
9
- | 普通列表、排序、选择、加载/空态 | 公共 `DataTable` | 从实际安装版本导入,完整参数以类型声明为准 |
10
- | 列筛选、列设置、拖动/固定/缩放 | MRT 本地样例 | 仅 `examples/mrt-poc`,无 npm 导出 |
11
- | 一条主记录包含多条明细,主字段跨行合并 | MRT 样例 `productDisplay="inline"` | 原生 `rowSpan`,按主记录分页 |
12
- | 点击主记录箭头展开明细 | MRT 样例 `productDisplay="expanded"` | MRT 详情面板,默认收起 |
13
-
14
- 公共 `DataTable` 的旧参数兼容层保留原生行渲染,表格外壳已使用MRT,支持 `hiddenColumnIds`、客户端/服务端排序、受控行选择和行级 memo。列顺序由传入 `columns` 决定;筛选、分页取数及切片由调用方组合。旧参数不自动启用高级能力;完整配置及合并渲染器见DataTable迁移文档。参见 [公共 API](api.md#数据表移动端契约) 和 [成熟度迁移](maturity-migration.md)。
15
-
16
- 现有 `DataTable` 的移动布局可以选择 `scroll` / `cards`;MRT 样例仅使用表格容器内横向滚动,没有卡片模式。
17
-
18
- ## 本地启动
19
-
20
- ```powershell
21
- pnpm dev:mrt
22
- # http://127.0.0.1:4186/
23
- pnpm test:mrt
24
- pnpm build:mrt
25
- # 仅用于与简表做构建体积对照
26
- pnpm exec vite build --config examples/mrt-poc/vite.config.ts --mode baseline
27
- ```
28
-
29
- 样例提供 120 份模拟合同和 5,000 份规模体验,每份合同默认三条模拟产品。没有生产接口或真实客户/员工数据。MRT 3.2.1、MUI material/icons 7.3.11、x-date-pickers 9.13.0、Emotion react 11.14.0 / styled 11.14.1 已迁为正式依赖;公共data-table入口使用这些依赖。
30
-
31
- ## 表格交互
32
-
33
- | 能力 | 当前行为 |
34
- | --- | --- |
35
- | 搜索 | 按合同字段做本地全局搜索,不搜索产品明细 |
36
- | 列筛选 | 文本、金额区间、状态下拉;筛选结果按合同计数 |
37
- | 排序 | 单击表头;产品字段没有独立排序语义,已关闭排序 |
38
- | 表头拖动 | 按住表头文字拖动,无独立手柄;有效放下才更新顺序,拖后不触发排序 |
39
- | 列设置 | 字段勾选、左侧轻量手柄排序、左/右固定;与表头共用顺序状态 |
40
- | 列显隐 | 合同编号必选;部门默认隐藏;显示字段不是业务权限控制 |
41
- | 列宽 | 拖动列边缘;金额默认180px、最小140px |
42
- | 选择/分页 | 以合同为单位,跨页保留选择;一份合同的产品不拆到不同页 |
43
- | 默认视图 | 表格底部重置搜索、筛选、排序、列顺序、显隐和选择,不重置全部表格状态 |
44
- | 列设置恢复默认 | 重置列顺序、显隐、固定位置及列宽,不清空业务筛选和选择 |
45
-
46
- 输入框、列菜单及缩放边缘保留各自交互,不触发表头拖列。表头拖动用原生 HTML drag 事件;列设置复用公共 `SortableList`。已验证桌面鼠标拖动,不能据此宣称本样例的真实手机/键盘列排序已验收。
47
-
48
- ## 产品展示配置
49
-
50
- ### 参数
51
-
52
- 独立样例组件为 `examples/mrt-poc/ContractTable.tsx`,参数如下。它依赖示例的 `TableTheme` 和样式环境,不能从已发布 `@jc-times/business-ui` 直接导入。
53
-
54
- | 参数 | 类型 | 默认值 | 说明 |
55
- | --- | --- | --- | --- |
56
- | `rows` | `Contract[]` | 必填 | 调用方提供合同及产品数据 |
57
- | `productDisplay` | `'none' \| 'inline' \| 'expanded'` | `'none'` | 调用服务按页面需求固定选择 |
58
- | `inModal` | `boolean` | `false` | 使用弹窗内表格高度;自身不创建弹窗 |
59
- | `searchMemoryKey` | `string` | 不启用 | 按服务/租户/用户/列表提供稳定标识,启用本地搜索记忆;变更标识时重建组件 |
60
- | `virtual` | `boolean` | `false` | 常规/展开模式可启用行虚拟化;合并模式始终分页 |
61
-
62
- 在当前示例的主题和样式上下文内:
63
-
64
- ```tsx
65
- // 三个真实产品行,合同字段跨行合并
66
- <ContractTable rows={contracts} productDisplay="inline" />
67
-
68
- // 主行默认收起,点击箭头查看产品
69
- <ContractTable rows={contracts} productDisplay="expanded" />
70
-
71
- // 普通合同列表
72
- <ContractTable rows={contracts} productDisplay="none" />
73
- ```
74
-
75
- 模式由调用方选择,不要求最终用户必须看到切换器。演示页面的“产品展示”选择器仅便于体验,切换时通过 React key 重建表格,选择等未持久化状态会重置,配置相同searchMemoryKey时恢复搜索和列筛选;弹窗沿用页面选择的模式。其他调用场景动态切换时应同样重建,或显式协调列顺序等受控状态。
76
-
77
- ### 数据契约
78
-
79
- ```ts
80
- type ContractProduct = {
81
- id: string; // 同一合同内稳定唯一
82
- name: string;
83
- specification: string;
84
- quantity: number;
85
- unit: string;
86
- };
87
-
88
- type Contract = {
89
- id: string; // 合同稳定唯一,作为选择和行标识
90
- name: string;
91
- customer: string;
92
- amount: number; // 样例以元表示,用 Intl.NumberFormat 格式化
93
- owner: string;
94
- status: string;
95
- signedAt: string;
96
- department: string;
97
- products: ContractProduct[];
98
- };
99
- ```
100
-
101
- 产品数组长度不限于三条;调用方没有产品时传 `[]`。当前状态徽标映射仍是样例业务逻辑。正式通用化需要明细数据/渲染插槽和调用方状态映射,不应把合同字段或产品模型固化为公共库契约。
102
-
103
- ### 同行模式:原生行合并
104
-
105
- 每个产品渲染为主表 `tbody` 中的一个真实 `tr`,产品名称、规格、数量各占独立列。合同信息和选择框使用 `rowSpan=产品数` 跨行显示、纵向居中;没有嵌套表格。
106
-
107
- 实现使用 MRT 的 `semantic` 布局与 `muiTableBodyProps.children`,自定义 `MergedProductRows` 复用 MRT 单元格渲染和列状态。这是样例适配,不是 MRT 开箱提供的自动合并能力。
108
-
109
- - 根据每份合同的产品数合并,不把不同合同中相同文本自动合并。
110
- - 无产品时保留一个主行,产品位置显示“暂无产品”和占位符。
111
- - 隐藏全部产品列时,每份合同恢复为一行。
112
- - 产品列可以调整顺序、显隐和宽度;合同仍是选择、搜索、排序与分页单位。
113
- - 尚未提供任意单元格 `rowSpan` / `colSpan` 配置,也未做跨合同合并。
114
- - 合并模式关闭行虚拟化,以免截断跨行单元格;5,000份数据也按合同分页。
115
-
116
- ### 展开模式
117
-
118
- 通过行首按钮展开/收起产品,使用 `renderDetailPanel`,默认收起且未提供展开全部。详情内使用独立产品小表,合同主列表行高保持紧凑。展开模式保留虚拟化选项,但带产品详情的5,000行场景尚无专项性能结论。
119
-
120
- 两种模式都没有产品独立筛选、排序、编辑或选择功能。
121
-
122
- ## 样式与弹窗约定
123
-
124
- 颜色、边框、圆角和焦点使用 `--ui-*`;复用 Button、Checkbox、Badge、Pagination、SortableList、ModalShell,图标采用 Lucide 适配。公共组件源码不因 POC 而改变。
125
-
126
- - 文本默认左对齐,金额和数量右对齐,金额采用等宽数字。
127
- - 表头完全不透明;排序/列菜单图标保持清晰,菜单无边框透明底,仅悬停或键盘聚焦显示浅色背景。
128
- - 表头筛选桌面32px、粗指针44px,缩短占位符并保留完整无障碍字段名。
129
- - 金额列保留单行“金额范围”入口,点击弹出最小/最大金额输入;已设置时显示范围摘要。不再上下堆叠输入撑高整行表头,列仍可缩至140px。
130
- - 窄屏在表格内部横向滚动,列设置内部纵向滚动。
131
-
132
- MUI Popover/Popper 通过 `useOverlayContainer` 进入现有 ModalShell 边界,避免浮层落到模态外。嵌套 Popover 关闭自己的 enforceFocus,保留外层焦点约束。示例包装层捕获 Escape:有内层 Popover 时先由内层处理,否则关闭外层并恢复触发器焦点。此包装在 `main.tsx`,`ContractTable` 本身不负责创建主题或模态焦点边界。
133
-
134
- ## 性能与验证
135
-
136
- 现有公共 `DataTable` 会渲染所有传入行,单元格规模约为行数乘可见列数。稳定的列定义、行对象和回调有助于行级 memo;大数据应由调用方分页,不能把行缓存视为虚拟化。
137
-
138
- 截至2026-09-12,MRT样例类型检查、14项浏览器回归和样例构建通过。覆盖搜索/筛选、跨页选择、表头及列设置拖动、列显隐、金额缩列、页面/弹窗、Escape、合并行结构、展开收起和常规5,000行虚拟DOM控制。五档视口为1440×900、768×1024、390×844、320×480、844×390;产品模式还检查了390px弹窗显示。
139
-
140
- 初版生产构建测量:常规5,000行虚拟模式首尾仅渲染21/22个DOM行、可达末条且无控制台error。这是初版普通模式的测量,不能套用到新增合并/展开产品模式;不代表首屏耗时、帧率、内存或真实低端机性能。
141
-
142
- | 构建 | JS gzip | 说明 |
143
- | --- | ---: | --- |
144
- | 当前完整样例(2026-09-12) | 约380.8KB | 包含MRT/MUI、SortableList、弹窗及产品展示;CSS gzip约11.0KB |
145
- | 初版简表基线(2026-09-11) | 约50KB | 现有DataTable最小页面,未在本次文档整理中重测 |
146
-
147
- 两者功能不等价,不能据此计算MRT单包成本或推断运行速度。样例当前单入口打包,正式接入应评估页面懒加载。公共包没有导出这些MRT示例。
148
-
149
- 生产测量入口(需先构建,端口占用时另选并同步测量脚本):
150
-
151
- ```powershell
152
- pnpm exec vite preview --config examples/mrt-poc/vite.config.ts --host 127.0.0.1 --port 4187 --strictPort
153
- node examples/mrt-poc/measure.mjs
154
- ```
155
-
156
- 截图/测量输出在 `artifacts/mrt-qa/`,失败trace在 `artifacts/mrt-test-results/`,均为忽略产物。性能结论应注明模式、记录数、视口、构建和测量环境。
157
-
158
- ## 文件与后续接入
159
-
160
- | 文件 | 职责 |
161
- | --- | --- |
162
- | `examples/mrt-poc/main.tsx` | 页面、模式选择、主题和现有弹窗适配 |
163
- | `examples/mrt-poc/ContractTable.tsx` | MRT配置、合同列、筛选/排序/拖动/分页 |
164
- | `examples/mrt-poc/MergedProductRows.tsx` | 主表真实产品行及合同rowSpan |
165
- | `examples/mrt-poc/ProductRows.tsx` | 展开详情小表及模式类型 |
166
- | `examples/mrt-poc/ColumnSettings.tsx` | 显隐、排序、固定及列恢复默认 |
167
- | `examples/mrt-poc/data.ts` | 模拟数据与样例类型 |
168
- | `examples/mrt-poc/styles.css`、`icons.tsx`、`tokens.ts` | 局部视觉适配 |
169
- | `examples/mrt-poc/mrt.browser.ts` | 可重复的浏览器回归 |
170
-
1
+ # 表格能力与 MRT 验证样例
2
+
3
+ 更新日期:2026-09-12。已决定采用MRT,当前工作树已替代公共DataTable渲染内核并提供独立入口;对应0.2.31;其他服务需单独升级。当前公共API见 [DataTable迁移](data-table.md)。以下合同包装仍是业务验证样例。本文区分现有公共 `DataTable` 与样例能力,不把工作树功能视为已发布 API。
4
+
5
+ ## 选用入口
6
+
7
+ | 场景 | 当前实现 | 调用边界 |
8
+ | --- | --- | --- |
9
+ | 普通列表、排序、选择、加载/空态 | 公共 `DataTable` | 从实际安装版本导入,完整参数以类型声明为准 |
10
+ | 列筛选、列设置、拖动/固定/缩放 | MRT 本地样例 | 仅 `examples/mrt-poc`,无 npm 导出 |
11
+ | 一条主记录包含多条明细,主字段跨行合并 | MRT 样例 `productDisplay="inline"` | 原生 `rowSpan`,按主记录分页 |
12
+ | 点击主记录箭头展开明细 | MRT 样例 `productDisplay="expanded"` | MRT 详情面板,默认收起 |
13
+
14
+ 公共 `DataTable` 的旧参数兼容层保留原生行渲染,表格外壳已使用MRT,支持 `hiddenColumnIds`、客户端/服务端排序、受控行选择和行级 memo。列顺序由传入 `columns` 决定;筛选、分页取数及切片由调用方组合。旧参数不自动启用高级能力;完整配置及合并渲染器见DataTable迁移文档。参见 [公共 API](api.md#数据表移动端契约) 和 [成熟度迁移](maturity-migration.md)。
15
+
16
+ 现有 `DataTable` 的移动布局可以选择 `scroll` / `cards`;MRT 样例仅使用表格容器内横向滚动,没有卡片模式。
17
+
18
+ ## 本地启动
19
+
20
+ ```powershell
21
+ pnpm dev:mrt
22
+ # http://127.0.0.1:4186/
23
+ pnpm test:mrt
24
+ pnpm build:mrt
25
+ # 仅用于与简表做构建体积对照
26
+ pnpm exec vite build --config examples/mrt-poc/vite.config.ts --mode baseline
27
+ ```
28
+
29
+ 样例提供 120 份模拟合同和 5,000 份规模体验,每份合同默认三条模拟产品。没有生产接口或真实客户/员工数据。MRT 3.2.1、MUI material/icons 7.3.11、x-date-pickers 9.13.0、Emotion react 11.14.0 / styled 11.14.1 已迁为正式依赖;公共data-table入口使用这些依赖。
30
+
31
+ ## 表格交互
32
+
33
+ | 能力 | 当前行为 |
34
+ | --- | --- |
35
+ | 搜索 | 按合同字段做本地全局搜索,不搜索产品明细 |
36
+ | 列筛选 | 文本、金额区间、状态下拉;筛选结果按合同计数 |
37
+ | 排序 | 单击表头;产品字段没有独立排序语义,已关闭排序 |
38
+ | 表头拖动 | 按住表头文字拖动,无独立手柄;有效放下才更新顺序,拖后不触发排序 |
39
+ | 列设置 | 字段勾选、左侧轻量手柄排序、左/右固定;与表头共用顺序状态 |
40
+ | 列显隐 | 合同编号必选;部门默认隐藏;显示字段不是业务权限控制 |
41
+ | 列宽 | 拖动列边缘;金额默认180px、最小140px |
42
+ | 选择/分页 | 以合同为单位,跨页保留选择;一份合同的产品不拆到不同页 |
43
+ | 默认视图 | 表格底部重置搜索、筛选、排序、列顺序、显隐和选择,不重置全部表格状态 |
44
+ | 列设置恢复默认 | 重置列顺序、显隐、固定位置及列宽,不清空业务筛选和选择 |
45
+
46
+ 输入框、列菜单及缩放边缘保留各自交互,不触发表头拖列。表头拖动用原生 HTML drag 事件;列设置复用公共 `SortableList`。已验证桌面鼠标拖动,不能据此宣称本样例的真实手机/键盘列排序已验收。
47
+
48
+ ## 产品展示配置
49
+
50
+ ### 参数
51
+
52
+ 独立样例组件为 `examples/mrt-poc/ContractTable.tsx`,参数如下。它依赖示例的 `TableTheme` 和样式环境,不能从已发布 `@jc-times/business-ui` 直接导入。
53
+
54
+ | 参数 | 类型 | 默认值 | 说明 |
55
+ | --- | --- | --- | --- |
56
+ | `rows` | `Contract[]` | 必填 | 调用方提供合同及产品数据 |
57
+ | `productDisplay` | `'none' \| 'inline' \| 'expanded'` | `'none'` | 调用服务按页面需求固定选择 |
58
+ | `inModal` | `boolean` | `false` | 使用弹窗内表格高度;自身不创建弹窗 |
59
+ | `searchMemoryKey` | `string` | 不启用 | 按服务/租户/用户/列表提供稳定标识,启用本地搜索记忆;变更标识时重建组件 |
60
+ | `virtual` | `boolean` | `false` | 常规/展开模式可启用行虚拟化;合并模式始终分页 |
61
+
62
+ 在当前示例的主题和样式上下文内:
63
+
64
+ ```tsx
65
+ // 三个真实产品行,合同字段跨行合并
66
+ <ContractTable rows={contracts} productDisplay="inline" />
67
+
68
+ // 主行默认收起,点击箭头查看产品
69
+ <ContractTable rows={contracts} productDisplay="expanded" />
70
+
71
+ // 普通合同列表
72
+ <ContractTable rows={contracts} productDisplay="none" />
73
+ ```
74
+
75
+ 模式由调用方选择,不要求最终用户必须看到切换器。演示页面的“产品展示”选择器仅便于体验,切换时通过 React key 重建表格,选择等未持久化状态会重置,配置相同searchMemoryKey时恢复搜索和列筛选;弹窗沿用页面选择的模式。其他调用场景动态切换时应同样重建,或显式协调列顺序等受控状态。
76
+
77
+ ### 数据契约
78
+
79
+ ```ts
80
+ type ContractProduct = {
81
+ id: string; // 同一合同内稳定唯一
82
+ name: string;
83
+ specification: string;
84
+ quantity: number;
85
+ unit: string;
86
+ };
87
+
88
+ type Contract = {
89
+ id: string; // 合同稳定唯一,作为选择和行标识
90
+ name: string;
91
+ customer: string;
92
+ amount: number; // 样例以元表示,用 Intl.NumberFormat 格式化
93
+ owner: string;
94
+ status: string;
95
+ signedAt: string;
96
+ department: string;
97
+ products: ContractProduct[];
98
+ };
99
+ ```
100
+
101
+ 产品数组长度不限于三条;调用方没有产品时传 `[]`。当前状态徽标映射仍是样例业务逻辑。正式通用化需要明细数据/渲染插槽和调用方状态映射,不应把合同字段或产品模型固化为公共库契约。
102
+
103
+ ### 同行模式:原生行合并
104
+
105
+ 每个产品渲染为主表 `tbody` 中的一个真实 `tr`,产品名称、规格、数量各占独立列。合同信息和选择框使用 `rowSpan=产品数` 跨行显示、纵向居中;没有嵌套表格。
106
+
107
+ 实现使用 MRT 的 `semantic` 布局与 `muiTableBodyProps.children`,自定义 `MergedProductRows` 复用 MRT 单元格渲染和列状态。这是样例适配,不是 MRT 开箱提供的自动合并能力。
108
+
109
+ - 根据每份合同的产品数合并,不把不同合同中相同文本自动合并。
110
+ - 无产品时保留一个主行,产品位置显示“暂无产品”和占位符。
111
+ - 隐藏全部产品列时,每份合同恢复为一行。
112
+ - 产品列可以调整顺序、显隐和宽度;合同仍是选择、搜索、排序与分页单位。
113
+ - 尚未提供任意单元格 `rowSpan` / `colSpan` 配置,也未做跨合同合并。
114
+ - 合并模式关闭行虚拟化,以免截断跨行单元格;5,000份数据也按合同分页。
115
+
116
+ ### 展开模式
117
+
118
+ 通过行首按钮展开/收起产品,使用 `renderDetailPanel`,默认收起且未提供展开全部。详情内使用独立产品小表,合同主列表行高保持紧凑。展开模式保留虚拟化选项,但带产品详情的5,000行场景尚无专项性能结论。
119
+
120
+ 两种模式都没有产品独立筛选、排序、编辑或选择功能。
121
+
122
+ ## 样式与弹窗约定
123
+
124
+ 颜色、边框、圆角和焦点使用 `--ui-*`;复用 Button、Checkbox、Badge、Pagination、SortableList、ModalShell,图标采用 Lucide 适配。公共组件源码不因 POC 而改变。
125
+
126
+ - 文本默认左对齐,金额和数量右对齐,金额采用等宽数字。
127
+ - 表头完全不透明;排序/列菜单图标保持清晰,菜单无边框透明底,仅悬停或键盘聚焦显示浅色背景。
128
+ - 表头筛选桌面32px、粗指针44px,缩短占位符并保留完整无障碍字段名。
129
+ - 金额列保留单行“金额范围”入口,点击弹出最小/最大金额输入;已设置时显示范围摘要。不再上下堆叠输入撑高整行表头,列仍可缩至140px。
130
+ - 窄屏在表格内部横向滚动,列设置内部纵向滚动。
131
+
132
+ MUI Popover/Popper 通过 `useOverlayContainer` 进入现有 ModalShell 边界,避免浮层落到模态外。嵌套 Popover 关闭自己的 enforceFocus,保留外层焦点约束。示例包装层捕获 Escape:有内层 Popover 时先由内层处理,否则关闭外层并恢复触发器焦点。此包装在 `main.tsx`,`ContractTable` 本身不负责创建主题或模态焦点边界。
133
+
134
+ ## 性能与验证
135
+
136
+ 现有公共 `DataTable` 会渲染所有传入行,单元格规模约为行数乘可见列数。稳定的列定义、行对象和回调有助于行级 memo;大数据应由调用方分页,不能把行缓存视为虚拟化。
137
+
138
+ 截至2026-09-12,MRT样例类型检查、14项浏览器回归和样例构建通过。覆盖搜索/筛选、跨页选择、表头及列设置拖动、列显隐、金额缩列、页面/弹窗、Escape、合并行结构、展开收起和常规5,000行虚拟DOM控制。五档视口为1440×900、768×1024、390×844、320×480、844×390;产品模式还检查了390px弹窗显示。
139
+
140
+ 初版生产构建测量:常规5,000行虚拟模式首尾仅渲染21/22个DOM行、可达末条且无控制台error。这是初版普通模式的测量,不能套用到新增合并/展开产品模式;不代表首屏耗时、帧率、内存或真实低端机性能。
141
+
142
+ | 构建 | JS gzip | 说明 |
143
+ | --- | ---: | --- |
144
+ | 当前完整样例(2026-09-12) | 约380.8KB | 包含MRT/MUI、SortableList、弹窗及产品展示;CSS gzip约11.0KB |
145
+ | 初版简表基线(2026-09-11) | 约50KB | 现有DataTable最小页面,未在本次文档整理中重测 |
146
+
147
+ 两者功能不等价,不能据此计算MRT单包成本或推断运行速度。样例当前单入口打包,正式接入应评估页面懒加载。公共包没有导出这些MRT示例。
148
+
149
+ 生产测量入口(需先构建,端口占用时另选并同步测量脚本):
150
+
151
+ ```powershell
152
+ pnpm exec vite preview --config examples/mrt-poc/vite.config.ts --host 127.0.0.1 --port 4187 --strictPort
153
+ node examples/mrt-poc/measure.mjs
154
+ ```
155
+
156
+ 截图/测量输出在 `artifacts/mrt-qa/`,失败trace在 `artifacts/mrt-test-results/`,均为忽略产物。性能结论应注明模式、记录数、视口、构建和测量环境。
157
+
158
+ ## 文件与后续接入
159
+
160
+ | 文件 | 职责 |
161
+ | --- | --- |
162
+ | `examples/mrt-poc/main.tsx` | 页面、模式选择、主题和现有弹窗适配 |
163
+ | `examples/mrt-poc/ContractTable.tsx` | MRT配置、合同列、筛选/排序/拖动/分页 |
164
+ | `examples/mrt-poc/MergedProductRows.tsx` | 主表真实产品行及合同rowSpan |
165
+ | `examples/mrt-poc/ProductRows.tsx` | 展开详情小表及模式类型 |
166
+ | `examples/mrt-poc/ColumnSettings.tsx` | 显隐、排序、固定及列恢复默认 |
167
+ | `examples/mrt-poc/data.ts` | 模拟数据与样例类型 |
168
+ | `examples/mrt-poc/styles.css`、`icons.tsx`、`tokens.ts` | 局部视觉适配 |
169
+ | `examples/mrt-poc/mrt.browser.ts` | 可重复的浏览器回归 |
170
+
171
171
  已决定采用MRT;其他服务接入前,需确定通用列/明细插槽、模式选择、受控选择与查询状态、列偏好持久化、服务端契约和权限边界,再完成公共导出、版本发布及实际消费验证。当前样例未连接接口;仅搜索条件可本地记忆,列顺序/显隐/宽度等偏好尚未持久化,未验证React 19组合或真实手机/键盘拖列。不要跨仓库复制样例冒充已发布能力。
172
-
173
- ## 搜索条件记忆
174
-
175
- `searchMemoryKey` 启用后,将生效的全局关键词、列筛选(含金额范围)及筛选栏状态保存到当前浏览器localStorage,刷新或重建时恢复。页面日常列表、5,000条体验与选择弹窗使用不同标识,产品显示模式共用所属列表的搜索记忆。
176
-
177
- ```tsx
178
- <ContractTable rows={contracts} searchMemoryKey={`${serviceId}:${tenantId}:${userId}:contracts`} />
179
- ```
180
-
181
- 存储键前缀为 `business-ui:mrt-search:v1:`。不传参数即不持久化;调用方切换用户或列表标识时,应以key重建组件。损坏数据、未知字段或浏览器存储不可用时回退,搜索仍可用。“恢复默认视图”强制清空筛选而非回到挂载时的已恢复条件,同时删除该列表的搜索记忆。列设置中的恢复默认不清除搜索。仅限当前浏览器,不同步到账号或其他设备;分页、选择、排序及列布局没有在此保存。
182
-
183
- ## 2026-09-12 性能专项复核
184
-
185
- Material/MRT提供基础能力,不免除调用侧性能设计。现有公共DataTable并不基于Material;MRT样例的UI由MUI提供,行模型由TanStack处理。
186
-
187
- 生产构建、Chromium、1440×900、本机无CPU节流,3次“搜索唯一合同并等待匹配数更新”观测:
188
-
189
- | 模式 | 合同数 | 初始实际tbody行 | 搜索端到端观测(ms) |
190
- | --- | ---: | ---: | --- |
191
- | 普通分页 | 120 | 20 | 314 / 340 / 310 |
192
- | 普通虚拟 | 5,000 | 19 | 321 / 311 / 313 |
193
- | 合并、每合同3产品、每页20合同 | 5,000 | 60 | 315 / 337 / 343 |
194
-
195
- 这些时间包含MRT输入的250ms防抖、自动化操作及等待,不能当作纯筛选CPU时间或正式基准。记录位于忽略产物 `artifacts/mrt-qa/performance-review.json`。未测真实网络、低端机、内存峰值及滚动帧率;本次没有足够证据宣称已出现计算瓶颈。
196
-
197
- 优先级判断:
198
-
199
- 1. 正式接入优先页面懒加载:当前完整样例JS gzip约381KB,不能让所有业务页面首屏都承担此成本。
200
- 2. 更大数据量优先服务端筛选/排序/分页:虚拟化只减少DOM,5,000条仍在浏览器内参与过滤。没有测量依据时不规定统一行数阈值。
201
- 3. 合并模式的DOM规模为当前页产品数之和。每合同3产品时受控,但单份合同数百产品会放大渲染,届时优先展开详情并对明细分页。
202
- 4. 公共DataTable已有行级memo、稳定选择回调和排序结果缓存,排序键每行预取一次;不能用“全部重写”代替分页。调用方应保持rows/columns引用稳定,重型单元格需单独分析。
203
- 5. MRT样例的自定义合并body会在表格状态更新时遍历当前页,尚未做逐合同渲染隔离;当前60行没有测出明显恶化,不宜直接打开全表memo以牺牲列拖动/缩放等响应。后续复杂产品单元格先用Profiler定位再优化。
204
-
205
- 公共DataTable相关三个测试文件共24项通过,MRT样例14项浏览器回归、类型和构建通过。本轮未改公共DataTable的性能实现;搜索记忆仅在搜索状态改变时写入小对象,不随单纯勾选触发写入。
172
+
173
+ ## 搜索条件记忆
174
+
175
+ `searchMemoryKey` 启用后,将生效的全局关键词、列筛选(含金额范围)及筛选栏状态保存到当前浏览器localStorage,刷新或重建时恢复。页面日常列表、5,000条体验与选择弹窗使用不同标识,产品显示模式共用所属列表的搜索记忆。
176
+
177
+ ```tsx
178
+ <ContractTable rows={contracts} searchMemoryKey={`${serviceId}:${tenantId}:${userId}:contracts`} />
179
+ ```
180
+
181
+ 存储键前缀为 `business-ui:mrt-search:v1:`。不传参数即不持久化;调用方切换用户或列表标识时,应以key重建组件。损坏数据、未知字段或浏览器存储不可用时回退,搜索仍可用。“恢复默认视图”强制清空筛选而非回到挂载时的已恢复条件,同时删除该列表的搜索记忆。列设置中的恢复默认不清除搜索。仅限当前浏览器,不同步到账号或其他设备;分页、选择、排序及列布局没有在此保存。
182
+
183
+ ## 2026-09-12 性能专项复核
184
+
185
+ Material/MRT提供基础能力,不免除调用侧性能设计。现有公共DataTable并不基于Material;MRT样例的UI由MUI提供,行模型由TanStack处理。
186
+
187
+ 生产构建、Chromium、1440×900、本机无CPU节流,3次“搜索唯一合同并等待匹配数更新”观测:
188
+
189
+ | 模式 | 合同数 | 初始实际tbody行 | 搜索端到端观测(ms) |
190
+ | --- | ---: | ---: | --- |
191
+ | 普通分页 | 120 | 20 | 314 / 340 / 310 |
192
+ | 普通虚拟 | 5,000 | 19 | 321 / 311 / 313 |
193
+ | 合并、每合同3产品、每页20合同 | 5,000 | 60 | 315 / 337 / 343 |
194
+
195
+ 这些时间包含MRT输入的250ms防抖、自动化操作及等待,不能当作纯筛选CPU时间或正式基准。记录位于忽略产物 `artifacts/mrt-qa/performance-review.json`。未测真实网络、低端机、内存峰值及滚动帧率;本次没有足够证据宣称已出现计算瓶颈。
196
+
197
+ 优先级判断:
198
+
199
+ 1. 正式接入优先页面懒加载:当前完整样例JS gzip约381KB,不能让所有业务页面首屏都承担此成本。
200
+ 2. 更大数据量优先服务端筛选/排序/分页:虚拟化只减少DOM,5,000条仍在浏览器内参与过滤。没有测量依据时不规定统一行数阈值。
201
+ 3. 合并模式的DOM规模为当前页产品数之和。每合同3产品时受控,但单份合同数百产品会放大渲染,届时优先展开详情并对明细分页。
202
+ 4. 公共DataTable已有行级memo、稳定选择回调和排序结果缓存,排序键每行预取一次;不能用“全部重写”代替分页。调用方应保持rows/columns引用稳定,重型单元格需单独分析。
203
+ 5. MRT样例的自定义合并body会在表格状态更新时遍历当前页,尚未做逐合同渲染隔离;当前60行没有测出明显恶化,不宜直接打开全表memo以牺牲列拖动/缩放等响应。后续复杂产品单元格先用Profiler定位再优化。
204
+
205
+ 公共DataTable相关三个测试文件共24项通过,MRT样例14项浏览器回归、类型和构建通过。本轮未改公共DataTable的性能实现;搜索记忆仅在搜索状态改变时写入小对象,不随单纯勾选触发写入。
package/docs/release.md CHANGED
@@ -1,32 +1,32 @@
1
- # 内部发布流程
2
-
3
- ## 发布位置与权限
4
-
5
- - Git 仓库:`https://github.com/jc-times/business-ui`
6
- - npm registry:GitHub Packages,`https://npm.pkg.github.com`
7
- - npm 包:`@jc-times/business-ui`
8
- - Release workflow 仅授予 `contents: read` 和 `packages: write`。
9
- - 发布使用 GitHub Actions 自动提供的仓库级 `GITHUB_TOKEN`,无需创建或保存长期 `NPM_TOKEN`。
10
-
11
- 仓库不会保存令牌或带令牌的 `.npmrc`。发布脚本只在执行期间创建临时配置,并在成功或失败后删除。消费私有包所需的 `read:packages` 凭据由各消费仓库或开发者环境分别管理。
12
-
13
- ## 发布规则
14
-
15
- 1. 更新 `package.json` 版本和 `CHANGELOG.md`。
16
- 2. 合并到 `main`,等待 CI 的类型检查、测试、构建和打包全部通过。
17
- 3. 在已验证的提交上创建并推送注释标签 `v<package.version>`。
18
- 4. Release workflow 再次执行完整验证,校验标签与包版本完全一致后发布。
19
- 5. 消费项目以精确版本安装,并在各自仓库提交 lockfile;不使用 `latest`、范围版本或源码路径。
20
-
21
- `workflow_dispatch` 只用于重试同一标签的失败任务;普通分支或无匹配标签的提交会被发布脚本拒绝。
22
-
23
- ## 本地安全演练
24
-
25
- 不设置真实令牌时,可验证拒绝路径:
26
-
27
- ```powershell
28
- $env:NPM_REGISTRY_URL = "https://npm.pkg.github.com"
29
- pnpm publish:release
30
- ```
31
-
32
- 脚本应在发布前因缺少 `NPM_TOKEN` 或标签不匹配而退出。不要把真实令牌写入命令历史、仓库文件或文档。
1
+ # 内部发布流程
2
+
3
+ ## 发布位置与权限
4
+
5
+ - Git 仓库:`https://github.com/jc-times/business-ui`
6
+ - npm registry:GitHub Packages,`https://npm.pkg.github.com`
7
+ - npm 包:`@jc-times/business-ui`
8
+ - Release workflow 仅授予 `contents: read` 和 `packages: write`。
9
+ - 发布使用 GitHub Actions 自动提供的仓库级 `GITHUB_TOKEN`,无需创建或保存长期 `NPM_TOKEN`。
10
+
11
+ 仓库不会保存令牌或带令牌的 `.npmrc`。发布脚本只在执行期间创建临时配置,并在成功或失败后删除。消费私有包所需的 `read:packages` 凭据由各消费仓库或开发者环境分别管理。
12
+
13
+ ## 发布规则
14
+
15
+ 1. 更新 `package.json` 版本和 `CHANGELOG.md`。
16
+ 2. 合并到 `main`,等待 CI 的类型检查、测试、构建和打包全部通过。
17
+ 3. 在已验证的提交上创建并推送注释标签 `v<package.version>`。
18
+ 4. Release workflow 再次执行完整验证,校验标签与包版本完全一致后发布。
19
+ 5. 消费项目以精确版本安装,并在各自仓库提交 lockfile;不使用 `latest`、范围版本或源码路径。
20
+
21
+ `workflow_dispatch` 只用于重试同一标签的失败任务;普通分支或无匹配标签的提交会被发布脚本拒绝。
22
+
23
+ ## 本地安全演练
24
+
25
+ 不设置真实令牌时,可验证拒绝路径:
26
+
27
+ ```powershell
28
+ $env:NPM_REGISTRY_URL = "https://npm.pkg.github.com"
29
+ pnpm publish:release
30
+ ```
31
+
32
+ 脚本应在发布前因缺少 `NPM_TOKEN` 或标签不匹配而退出。不要把真实令牌写入命令历史、仓库文件或文档。
@@ -0,0 +1,17 @@
1
+ # 人员资料卡
2
+
3
+ `UserProfilePopover` 将紧凑人员标签和只读资料卡组合在一起。默认点击标签打开,键盘可用 Enter 或空格打开、Escape 关闭,关闭后焦点返回标签。弹层会避开视口边缘,并在窄屏中换行显示较长的部门路径。
4
+
5
+ ```tsx
6
+ import { UserProfilePopover } from "@jc-times/business-ui";
7
+ import "@jc-times/business-ui/styles.css";
8
+
9
+ <UserProfilePopover name="章晨露" code="ZhangChenLu"
10
+ department="示例集团 / 项目管理部 / 项目运营组" tag="内部成员" avatarColor="#e94b50"/>;
11
+ ```
12
+
13
+ `name` 必填,其余资料字段可省略。没有头像图片时取姓名首字符;`avatarUrl` 可提供图片地址。`code`、`department` 和 `tag` 只负责展示,业务层决定具体含义及是否有权显示。`codeLabel`、`departmentLabel` 可以修改字段标题。`avatarColor` 或 CSS 变量 `--ui-user-avatar-bg` 控制头像背景;不传时使用主题主色。
14
+
15
+ 资料卡默认宽度随视口变化:`clamp(300px, 15vw, 560px)`,并受浮层实际可用宽度限制。普通桌面网页约 300px,宽屏业务页面可逐步放大;手机上会收缩到可用视口,长部门名称自动换行。页面需要固定宽度时,可在主题根节点设置 `--ui-user-profile-width`,或通过 `className` 给弹层设置该变量。
16
+
17
+ 默认触发器是一个人员标签按钮。需要放进其他布局时,使用 `trigger={<button>...</button>}` 提供可转发 ref 的交互元素。`side`、`align`、`open`、`defaultOpen` 和 `onOpenChange` 与公共 `Popover` 一致;`className` 作用于弹层。组件不获取人员资料或处理业务权限。
@@ -1,5 +1,13 @@
1
1
  # 发布前多视口验收
2
2
 
3
+ ## 2026-09-18 — 人员资料卡
4
+
5
+ - Chromium Desktop Chrome 与 Pixel 7 模拟共 4 项:人员标签打开只读资料卡,长部门路径可见,弹层位于视口内、页面无横向溢出;Escape 关闭后焦点返回标签。包含 320px 窄屏检查;默认宽度随视口按 300–560px 缩放。
6
+
7
+ ## 2026-09-14 — PDFium 0.2.45 批注显示
8
+ - Desktop Chrome / Pixel 7 模拟视口4项通过:仅存在于Stamp/FreeText批注层的测试图形在正文和缩略图均可见;本地真实审核PDF第一页原生印章与签章提示可见。真实文件不提交、不上传;自动测试支持本地环境变量注入。
9
+ - 141项单测、类型/库/矩阵/按需构建通过。仅改变原生批注显示,不启用批注编辑或改写文件;浏览器模拟不替代真机验收。
10
+
3
11
  运行 `pnpm dev:matrix -- --host 127.0.0.1`,在受控浏览器中检查以下矩阵:
4
12
 
5
13
  | 档位 | 视口 | 核心检查 |
@@ -29,13 +37,13 @@
29
37
 
30
38
  验收结论只记录日期、浏览器、视口和结果,不记录账号、Cookie 或其他会话数据。
31
39
 
32
- ## 验收记录
33
-
34
- ### 2026-09-12 — V2 原生 Headless 页面层候选
35
-
36
- - Chromium 桌面/手机查看器 14 项回归通过;原生模式覆盖五档视口,底栏可见、正文可滚动、页面无横向溢出,手机缩放旋转叠层截图目检通过。
37
- - 验证受控跳页与手动滚动、原生叠层点击、缩放旋转、单页互切、全屏、切换文档与失败恢复;138 项单测、类型和库/矩阵构建通过。未发布;真实多指手势与消费业务印章端到端仍需消费方验收。
38
-
40
+ ## 验收记录
41
+
42
+ ### 2026-09-12 — V2 原生 Headless 页面层候选
43
+
44
+ - Chromium 桌面/手机查看器 14 项回归通过;原生模式覆盖五档视口,底栏可见、正文可滚动、页面无横向溢出,手机缩放旋转叠层截图目检通过。
45
+ - 验证受控跳页与手动滚动、原生叠层点击、缩放旋转、单页互切、全屏、切换文档与失败恢复;138 项单测、类型和库/矩阵构建通过。未发布;真实多指手势与消费业务印章端到端仍需消费方验收。
46
+
39
47
  ### 2026-09-06 — 0.2.13 输入装饰
40
48
 
41
49
  - 浏览器:Codex 内置 Chromium;桌面验收页实际测得三个装饰组合外框均为 40px、内层 input 为 38px,宽度无溢出。
@@ -97,3 +105,25 @@
97
105
  - 部门父子独立多选、地址路径搜索与叶子选中后详细地址聚焦、弹窗内 portal、键盘选择及 Escape 分层关闭通过。输入占位不与摘要重叠,清空归一与必填搜索未选中由单测覆盖。
98
106
  - 新增级联 6 项浏览器测试通过;全量 36 项浏览器、25 文件 133 项单测、类型、库与视觉矩阵构建通过;打包演练包含声明、专题和 MIT 许可。
99
107
  - 本地待发布;尚未升级消费项目。触屏测试是浏览器模拟,非真实手机软键盘验收。复测:`pnpm exec playwright test e2e/cascader.spec.ts`。
108
+
109
+ ### 2026-09-14 PDFium 0.2.44
110
+ - Playwright Desktop Chrome / Pixel 7 六项定向验收通过:默认侧栏收起与往返开关、双指连续缩放、最小/最大比例、松手前后页面几何一致、业务叠层不误触。属于模拟触控,真实手机待消费方验收。
111
+
112
+ ### 2026-09-14 PDFium 0.2.46
113
+ - Desktop Chrome / Pixel 7 的8项手势专项通过:连续Ctrl/Meta滚轮、触屏缩放上下限、侧栏。77%起始跨越适宽边界,回传页码不再触发额外跳页,手势期间0次引擎缩放提交,每次结束仅1次。位置误差小于5 CSS像素、宽度误差小于0.5 CSS像素。原生路径复现额外跳页约304px,修复接入层后通过。
114
+ - pnpm精确补丁仅为官方2.15.0 React手势预览增加引擎一致的上下限和精度,保留官方CSS预览、虚拟滚动、延迟清晰重绘;未新增逐帧PDFium渲染。真机仍待用户复验。
115
+
116
+ ## 2026-09-14 — 0.2.47 横向滚动
117
+
118
+ Desktop Chrome / Pixel 7模拟视口共4项通过:50行8列表格,连续横向wheel位置不回退,同步条双向操作与固定高度原生滚动;原生模式无额外吸附条,纵向滚动表头仍可见。3项同步生命周期单测覆盖异步回传、每帧合并和卸载取消;修复前异步回传测试从140回退100,修复后保持140。模拟wheel不能替代真实触控板验收。
119
+
120
+ ## 2026-09-15 — SortableList目标项接收
121
+
122
+ Chromium桌面与Pixel 7视口,鼠标拖入目标、键盘选择目标/取消、禁止投放普通项、禁用手柄与宽度回归共6项通过;触屏视口为模拟,未宣称实机多指验证。2项排序单测及TypeScript通过。目标高亮复用主题令牌;领域移动由消费方处理。
123
+
124
+ ## 2026-09-15 / 0.2.50 嵌套拖动
125
+ - sortable-drop.spec.ts 与 sortable-width.spec.ts:桌面/Pixel7 模拟共14项通过,覆盖鼠标来源占位尺寸不变、进入组高亮、成员插入线、键盘移出/移回/组内排序与禁用宽度;TypeScript通过。键盘测试先等待嵌套列表的漫游焦点真正落到所选手柄,再按Enter,避免测试自身在焦点转移时启动拖动。不是实际触屏验收。
126
+ - 新增禁用切换页面错误捕获,避免误将组件崩溃当成隐藏手柄成功。React Aria hooks有无改变时通过显式GridList key切换。
127
+ - 嵌套指示器可能把目标key交给祖先回调,scope仅路由至唯一当前所属列表;一次拖动只消费一次。
128
+
129
+ - 首轮矩阵CI34971182111发现隐藏占位span使content不再是only-child,禁用行缩宽;占位仅在可拖动状态渲染,sortable-width回归验证。
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 CloudPDF
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.