@taocompany/magic-grid 0.1.0 → 0.1.1

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 (2) hide show
  1. package/README.md +1305 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,1305 @@
1
+ # Magic Grid
2
+
3
+ 面向 Vue 3 的高性能虚拟表格组件库。采用命令式渲染 + 行 DOM 池 + 双轴虚拟化,可稳定承载百万级行数据;API 设计对标 [AG Grid](https://www.ag-grid.com/) 社区版,覆盖排序、筛选、编辑、行分组、树形表格、框选、剪贴板等完整表格能力。
4
+
5
+ ## 目录
6
+
7
+ - [概述](#概述)
8
+ - [快速开始](#快速开始)
9
+ - [Props](#props)
10
+ - [MagicGrid Props](#magicgrid-props)
11
+ - [ColumnDef 列定义](#columndef-列定义)
12
+ - [Events](#events)
13
+ - [Expose](#expose)
14
+ - [Slots](#slots)
15
+ - [辅助组件](#辅助组件)
16
+ - [ColumnSettingsButton](#columnsettingsbutton)
17
+ - [ColumnSettingsPanel](#columnsettingspanel)
18
+ - [ColumnSettingsMenuItem](#columnsettingsmenuitem)
19
+ - [ColumnSettingsMenuIcon](#columnsettingsmenuicon)
20
+ - [相关文档](#相关文档)
21
+
22
+ ---
23
+
24
+ ## 概述
25
+
26
+ ### 特性
27
+
28
+ | 类别 | 能力 |
29
+ |------|------|
30
+ | **性能** | 行/列双轴虚拟化、DOM 池复用、RAF 帧预算分片、增量数据管线 |
31
+ | **数据** | 排序、列筛选、Quick Filter、事务增量更新(`applyTransaction`)、行 CRUD |
32
+ | **交互** | 单元格/行编辑、校验、行选择、索引列定位、框选与剪贴板 |
33
+ | **布局** | 固定列、列拖拽/调整宽度、合并单元格、动态行高、主从展开行 |
34
+ | **结构** | 行分组、树形表格(含懒加载)、表尾汇总 |
35
+ | **体验** | 溢出 Tooltip、单元格批注、空态 Overlay、暗色主题、底部状态栏 |
36
+
37
+ ### 环境要求
38
+
39
+ - Node.js >= 20.19
40
+ - Vue ^3.5.0
41
+ - async-validator ^4.2.0(校验功能 peer dependency)
42
+
43
+ ### 安装
44
+
45
+ ```bash
46
+ pnpm add @taocompany/magic-grid async-validator
47
+ ```
48
+
49
+ ### 引入样式
50
+
51
+ ```ts
52
+ import '@taocompany/magic-grid/style.css'
53
+ ```
54
+
55
+ ---
56
+
57
+ ## 快速开始
58
+
59
+ ```vue
60
+ <script setup lang="ts">
61
+ import { ref } from 'vue'
62
+ import { MagicGrid } from '@taocompany/magic-grid'
63
+ import type { ColumnDef, MagicGridExpose, RowData } from '@taocompany/magic-grid'
64
+ import '@taocompany/magic-grid/style.css'
65
+
66
+ const gridRef = ref<MagicGridExpose>()
67
+
68
+ const columns: ColumnDef[] = [
69
+ { prop: 'name', label: '姓名', width: 120, sortable: true },
70
+ { prop: 'age', label: '年龄', width: 80, sortable: true },
71
+ { prop: 'city', label: '城市', flex: 1, filterable: true },
72
+ ]
73
+
74
+ const data: RowData[] = [
75
+ { id: 1, name: '张三', age: 28, city: '上海' },
76
+ { id: 2, name: '李四', age: 32, city: '北京' },
77
+ ]
78
+
79
+ function onSelectionChanged(event: { selectedRowIds: readonly (string | number)[] }) {
80
+ console.log('选中行:', event.selectedRowIds)
81
+ }
82
+ </script>
83
+
84
+ <template>
85
+ <MagicGrid
86
+ ref="gridRef"
87
+ :columns="columns"
88
+ :data="data"
89
+ row-key="id"
90
+ height="400"
91
+ row-selection="multiple"
92
+ stripe
93
+ @selection-changed="onSelectionChanged"
94
+ />
95
+ </template>
96
+ ```
97
+
98
+ > **提示**:`data` 应为普通对象数组,避免对行数据使用 `reactive()` 深代理。
99
+
100
+ ---
101
+
102
+ ## Props
103
+
104
+ ### MagicGrid Props
105
+
106
+ #### 基础
107
+
108
+ | Prop | 类型 | 默认值 | 说明 |
109
+ |------|------|--------|------|
110
+ | `columns` | `ColumnDef[]` | — | **必填**。列定义数组 |
111
+ | `data` | `RowData[]` | — | **必填**。行数据(普通对象,禁止 reactive 深代理) |
112
+ | `rowKey` | `string` | `'id'` | 行主键字段名,用于行池复用与增量更新 |
113
+ | `height` | `string \| number` | `'100%'` | 容器高度 |
114
+ | `width` | `string \| number` | `'100%'` | 容器宽度 |
115
+
116
+ #### 外观
117
+
118
+ | Prop | 类型 | 默认值 | 说明 |
119
+ |------|------|--------|------|
120
+ | `stripe` | `boolean` | `false` | 斑马纹 |
121
+ | `border` | `'border' \| 'none' \| 'linear'` | `'border'` | 边框样式:`border` 全网格线;`none` 无单元格线;`linear` 仅底部分隔线 |
122
+ | `theme` | `'light' \| 'dark'` | `'light'` | 主题 preset |
123
+ | `size` | `'mini' \| 'small' \| 'default' \| 'large'` | `'default'` | 尺寸 preset(影响行高、字号、间距等) |
124
+ | `rounded` | `number \| boolean` | `false` | 容器圆角:`false`/`0` 无圆角;`true` 跟随 size;`number` 自定义 px |
125
+ | `rowHeight` | `number` | — | 固定行高(px);显式传入时覆盖 size preset |
126
+ | `headerHeight` | `number` | — | 表头高度(px);显式传入时覆盖 size preset |
127
+ | `rowStyle` | `RowStyle \| RowStyleFn` | — | 行级样式(对象=全表同色;函数=按行);作用于表体用户数据列与行选择列 |
128
+
129
+ #### 对齐(全局默认)
130
+
131
+ | Prop | 类型 | 默认值 | 说明 |
132
+ |------|------|--------|------|
133
+ | `headerAlign` | `'left' \| 'center' \| 'right'` | `'center'` | 表头水平对齐 |
134
+ | `headerValign` | `'top' \| 'center' \| 'bottom'` | `'center'` | 表头垂直对齐 |
135
+ | `align` | `'left' \| 'center' \| 'right'` | `'center'` | 表体水平对齐 |
136
+ | `valign` | `'top' \| 'center' \| 'bottom'` | `'center'` | 表体垂直对齐 |
137
+ | `footerAlign` | `'left' \| 'center' \| 'right'` | `'center'` | 表尾汇总水平对齐 |
138
+ | `footerValign` | `'top' \| 'center' \| 'bottom'` | `'center'` | 表尾汇总垂直对齐 |
139
+
140
+ #### 虚拟化与导航
141
+
142
+ | Prop | 类型 | 默认值 | 说明 |
143
+ |------|------|--------|------|
144
+ | `rowBuffer` | `number` | `10` | 行虚拟化缓冲行数 |
145
+ | `navigateHeader` | `boolean` | `false` | 是否允许键盘/鼠标将焦点导航到表头 |
146
+ | `navigateFooter` | `boolean` | `false` | 是否允许焦点导航到表尾汇总行(需 `showSummary: true`) |
147
+ | `enableHeaderHighlight` | `boolean` | `true` | 表头高亮 |
148
+ | `enableIndexColumnHighlight` | `boolean` | `true` | 索引列高亮 |
149
+
150
+ #### 索引列
151
+
152
+ | Prop | 类型 | 默认值 | 说明 |
153
+ |------|------|--------|------|
154
+ | `showIndexColumn` | `boolean` | `false` | 是否显示最左侧索引列 |
155
+ | `indexColumn` | `IndexColumnOptions` | — | 索引列配置(`showIndexColumn=true` 时生效) |
156
+
157
+ `IndexColumnOptions` 字段:
158
+
159
+ | 字段 | 类型 | 默认值 | 说明 |
160
+ |------|------|--------|------|
161
+ | `label` | `string` | `''` | 表头文案 |
162
+ | `width` | `number` | `40` | 列宽 px(最小 40) |
163
+ | `start` | `number` | `1` | 起始序号(1-based 展示 = rowIndex + start) |
164
+ | `focusMode` | `'single' \| 'multiple'` | `'multiple'` | 辅助定位模式 |
165
+ | `syncToSelectionColumn` | `boolean` | `false` | 索引列定位是否单向同步到行选择列 |
166
+ | `index` | `(rowIndex) => number \| string` | — | 自定义序号展示 |
167
+ | `showRowDragHandle` | `boolean` | `false` | 在索引列显示行拖拽把柄 |
168
+ | `enableRowResizer` | `boolean` | `false` | 索引列底边可拖拽调整行高 |
169
+ | `headerAlign` / `headerValign` / `align` / `valign` / `footerAlign` / `footerValign` | 对齐枚举 | `'center'` | 对齐配置 |
170
+
171
+ #### 行选择
172
+
173
+ | Prop | 类型 | 默认值 | 说明 |
174
+ |------|------|--------|------|
175
+ | `rowSelection` | `'single' \| 'multiple' \| false \| RowSelectionConfig` | `'single'` | 行选择模式;`false` 禁用 |
176
+ | `selectionColumn` | `SelectionColumnOptions` | — | 行选择列配置 |
177
+ | `selectable` | `SelectableFn` | — | 行 checkbox 是否可勾选;省略时全部可选 |
178
+ | `reserveSelection` | `boolean` | `false` | 数据刷新后是否保留选中行 |
179
+ | `isRowDisabled` | `boolean \| IsRowDisabledFn` | — | 行级禁用(该行全部数据列 disabled) |
180
+
181
+ `RowSelectionConfig`:
182
+
183
+ ```ts
184
+ interface RowSelectionConfig {
185
+ mode: 'single' | 'multiple'
186
+ groupSelectsChildren?: boolean // tree 模式下选中父节点是否级联子孙,默认 true
187
+ }
188
+ ```
189
+
190
+ `SelectionColumnOptions` 字段:
191
+
192
+ | 字段 | 类型 | 默认值 | 说明 |
193
+ |------|------|--------|------|
194
+ | `width` | `number` | `40` | 列宽 px(最小 40) |
195
+ | `selectAllLabel` | `string` | `'全选'` | 表头全选 checkbox 的 aria-label |
196
+ | `rowLabel` | `(rowIndex) => string` | — | 行 checkbox 的 aria-label 工厂 |
197
+
198
+ #### 表尾汇总
199
+
200
+ | Prop | 类型 | 默认值 | 说明 |
201
+ |------|------|--------|------|
202
+ | `showSummary` | `boolean` | `false` | 是否展示表尾汇总行 |
203
+ | `summaryScope` | `'displayed' \| 'all'` | `'displayed'` | 汇总范围:`displayed` 当前可见行;`all` 全量 sourceRows |
204
+ | `summaryRowHeight` | `number` | — | 汇总行高度 px;未传时跟随 rowHeight |
205
+ | `summaryMethod` | `SummaryMethod` | — | 全局汇总方法(优先级高于列级 `summaryAgg`) |
206
+
207
+ #### 排序
208
+
209
+ | Prop | 类型 | 默认值 | 说明 |
210
+ |------|------|--------|------|
211
+ | `defaultSort` | `SortModelItem[]` | — | 初始排序(挂载时应用一次;v1 仅使用首项) |
212
+ | `showUnsortedSortHintOnHover` | `boolean` | `false` | 未排序 sortable 列 hover 显示 faint 双三角 |
213
+
214
+ #### 列操作
215
+
216
+ | Prop | 类型 | 默认值 | 说明 |
217
+ |------|------|--------|------|
218
+ | `columnMovable` | `boolean` | `true` | 是否允许表头拖拽重排列 |
219
+ | `resizable` | `boolean` | `true` | 是否允许拖拽调整列宽(列级 `resizable` 优先) |
220
+ | `colResizeDefault` | `'shift'` | — | Shift 模式:拖拽列宽时相邻列反向补偿,总宽不变 |
221
+ | `skipHeaderOnAutoSize` | `boolean` | `false` | 双击 resize 把柄 auto-size 时跳过表头宽度 |
222
+ | `autoSizePadding` | `number` | — | auto-size 内容测量额外 padding(px) |
223
+ | `autoSizeStrategy` | `AutoSizeStrategy` | — | 挂载/首屏 auto-size 策略 |
224
+ | `suppressMoveWhenColumnDragging` | `boolean` | `false` | `true` → 仅 mouseup 提交列序 |
225
+ | `suppressColumnMoveAnimation` | `boolean` | `false` | 关闭列移动 transition |
226
+ | `allowCrossLaneColumnMove` | `boolean` | `false` | 允许 drag/API 跨 fixed lane 并更新列 `fixed` |
227
+
228
+ #### 筛选
229
+
230
+ | Prop | 类型 | 默认值 | 说明 |
231
+ |------|------|--------|------|
232
+ | `quickFilterText` | `string` | `''` | Grid 级 quick filter 文本 |
233
+ | `floatingFilter` | `boolean` | `false` | 是否显示 floating filter 行 |
234
+ | `filterSetValueMode` | `'reserve' \| 'current'` | `'current'` | 值选择搜索时的勾选投影模式 |
235
+ | `filterSetDateLayoutMode` | `'list' \| 'tree'` | `'tree'` | 日期列值选择展示方式 |
236
+
237
+ #### 编辑
238
+
239
+ | Prop | 类型 | 默认值 | 说明 |
240
+ |------|------|--------|------|
241
+ | `editMode` | `'cell' \| 'row'` | `'cell'` | 编辑范围:单格 / 整行 |
242
+ | `editType` | `CellEditType` | `'singleClick'` | 进入编辑态的触发方式 |
243
+ | `invalidEditValueMode` | `'block' \| 'revert'` | `'block'` | 校验失败后:`block` 保持编辑;`revert` 退出并恢复旧值 |
244
+ | `rowValidator` | `RowValidator` | — | 行编辑跨字段校验 |
245
+ | `cellEditorRegistry` | `Record<string, CellEditorFn>` | — | 实例级命名编辑器注册表 |
246
+ | `asyncRowMutation` | `AsyncRowMutationHandlers` | — | 异步行 CRUD 持久化钩子 |
247
+
248
+ #### 行拖拽与行高
249
+
250
+ | Prop | 类型 | 默认值 | 说明 |
251
+ |------|------|--------|------|
252
+ | `rowDragManaged` | `boolean` | `true` | managed 行拖拽:拖拽过程中实时改 source 顺序 |
253
+ | `rowDragCommitMode` | `'sync' \| 'deferred'` | `'sync'` | commit 策略:`sync` live move;`deferred` mouseup 后 await `onRowDragCommit` |
254
+ | `onRowDragCommit` | `RowDragCommitHandler` | — | deferred 模式:mouseup 后、apply 前调用;返回 `false` 则不写 source |
255
+ | `getRowHeight` | `GetRowHeightFn` | — | 行级动态高度(无 DOM) |
256
+ | `rowHeightMin` | `number` | — | 行高下限 px |
257
+ | `rowHeightMax` | `number` | — | 行高上限 px |
258
+
259
+ #### 合并单元格
260
+
261
+ | Prop | 类型 | 默认值 | 说明 |
262
+ |------|------|--------|------|
263
+ | `enableCellSpan` | `boolean` | `false` | 启用单元格合并(列级 `colSpan` / `rowSpan` / `spanRows`) |
264
+
265
+ #### 主从展开行
266
+
267
+ | Prop | 类型 | 默认值 | 说明 |
268
+ |------|------|--------|------|
269
+ | `masterDetail` | `boolean` | `false` | 启用主从展开行 |
270
+ | `isRowMaster` | `IsRowMasterFn` | — | 是否为主行(可展示 expand 控件) |
271
+ | `masterDefaultExpanded` | `number` | — | 默认展开层级:0=无;1=第一层;-1=全部 |
272
+ | `detailRowHeight` | `number \| DetailRowHeightFn` | — | 详情行固定高度 px |
273
+ | `detailRowAutoHeight` | `boolean` | — | 详情行按内容自动撑高 |
274
+ | `embedFullWidthRows` | `boolean` | — | `true`:详情嵌入 center lane 随横滚 |
275
+ | `showExpandColumn` | `boolean` | — | 最左展示专用展开列 |
276
+ | `getDetailRowData` | `GetDetailRowDataFn` | — | 异步提供详情区数据 |
277
+ | `detailCellRenderer` | `DetailCellRendererFn` | — | 自定义详情行渲染器(与 `#detail-row` 插槽二选一) |
278
+
279
+ #### 行分组
280
+
281
+ | Prop | 类型 | 默认值 | 说明 |
282
+ |------|------|--------|------|
283
+ | `rowGrouping` | `boolean` | `false` | 启用行分组 |
284
+ | `groupDefaultExpanded` | `number` | `-1` | 默认展开分组层级:0=全折叠;1=第一层;-1=全部 |
285
+ | `showGroupHeader` | `boolean` | `false` | 展示 groupHeader 分组标题行 |
286
+ | `showGroupFooter` | `boolean` | `false` | 为每个已展开分组展示 footer 汇总行 |
287
+ | `groupDisplayType` | `'singleColumn'` | `'singleColumn'` | 分组展示模式(v1 仅 singleColumn) |
288
+ | `showGroupColumn` | `boolean` | `false` | 展示 auto group 系统列 |
289
+ | `autoGroupColumnDef` | `Partial<ColumnDef>` | — | 覆盖 auto group 列 colDef |
290
+ | `groupKeyCreator` | `GroupKeyCreatorFn` | — | 分组键归一化 |
291
+ | `groupComparator` | `GroupComparatorFn` | — | 同级 group 节点排序 |
292
+ | `groupFooterLabel` | `string` | — | groupFooter 首列展示标签 |
293
+ | `groupCellRenderer` | `GroupCellRendererFn` | — | 自定义分组单元格渲染器 |
294
+
295
+ #### 树形表格
296
+
297
+ | Prop | 类型 | 默认值 | 说明 |
298
+ |------|------|--------|------|
299
+ | `tree` | `boolean` | `false` | 启用树形表格(与 `rowGrouping` 互斥) |
300
+ | `getDataPath` | `GetDataPathFn` | — | 树形路径回调(`tree: true` 时必填) |
301
+ | `treeDragScope` | `'siblings' \| 'hierarchy'` | `'siblings'` | 树形拖拽范围 |
302
+ | `setDataPath` | `SetDataPathFn` | — | hierarchy 模式下写回 dataPath |
303
+ | `showTreeColumn` | `boolean` | `true` | 展示 tree 系统列 |
304
+ | `autoTreeColumnDef` | `Partial<ColumnDef>` | — | 覆盖 tree 系统列 colDef |
305
+ | `treeValueGetter` | `TreeValueGetterFn` | — | 自定义 tree 列展示值 |
306
+ | `treeDisplayType` | `'singleColumn'` | — | 树节点展示列模式 |
307
+ | `treeLazyLoad` | `boolean` | `false` | 启用树形懒加载 |
308
+ | `hasTreeChildren` | `HasTreeChildrenFn` | — | lazy 模式:节点是否可能有未加载子行 |
309
+ | `loadTreeChildren` | `LoadTreeChildrenFn` | — | lazy 模式:首次展开时拉取子数据 |
310
+
311
+ #### 单元格批注
312
+
313
+ | Prop | 类型 | 默认值 | 说明 |
314
+ |------|------|--------|------|
315
+ | `cellCommentsDataSource` | `CellCommentsDataSource` | — | 批注数据源;提供即启用 |
316
+ | `suppressCellComments` | `boolean` | `false` | 全局抑制批注交互 |
317
+ | `cellCommentTrigger` | `'click' \| 'hover'` | `'click'` | 查看已有批注的触发方式 |
318
+ | `cellCommentShowDelay` | `number` | `180` | hover 模式展示延迟 ms |
319
+ | `cellCommentHideDelay` | `number` | `220` | 离开 cell/popup 后隐藏延迟 ms |
320
+
321
+ #### 框选与剪贴板
322
+
323
+ | Prop | 类型 | 默认值 | 说明 |
324
+ |------|------|--------|------|
325
+ | `cellSelection` | `boolean \| CellSelectionOptions` | `false` | 单元格框选 |
326
+ | `enableCellClipboard` | `boolean` | — | 启用剪贴板(通常随 cellSelection 开启) |
327
+ | `processCellForClipboard` | `ProcessCellForClipboardFn` | — | 复制单格时自定义导出值 |
328
+ | `processCellFromClipboard` | `ProcessCellFromClipboardFn` | — | 粘贴单格时预处理 clipboard 字符串 |
329
+ | `processDataFromClipboard` | `ProcessDataFromClipboardFn` | — | 整表粘贴前处理 TSV 矩阵;return null 取消粘贴 |
330
+
331
+ #### Tooltip
332
+
333
+ | Prop | 类型 | 默认值 | 说明 |
334
+ |------|------|--------|------|
335
+ | `enableTooltips` | `boolean` | `true` | 是否启用溢出 tooltip |
336
+ | `tooltipShowMode` | `'whenTruncated' \| 'always' \| 'never'` | `'whenTruncated'` | 溢出 tooltip 显示策略 |
337
+ | `tooltipShowDelay` | `number` | `500` | 首次 hover 展示延迟 ms |
338
+ | `tooltipSwitchShowDelay` | `number` | `200` | 格间切换展示延迟 ms |
339
+ | `tooltipHideDelay` | `number` | `3000` | 离开后隐藏延迟 ms |
340
+ | `tooltipInteraction` | `boolean` | — | tooltip 是否可交互 |
341
+ | `tooltipMouseTrack` | `boolean` | — | tooltip 是否跟随鼠标 |
342
+ | `tooltipComponent` | `TooltipComponentType` | — | 自定义 tooltip 组件(与 `#tooltip` 插槽二选一) |
343
+ | `tooltipComponentParams` | `Record<string, unknown>` | — | tooltip 组件额外参数 |
344
+
345
+ #### 空态 Overlay
346
+
347
+ | Prop | 类型 | 默认值 | 说明 |
348
+ |------|------|--------|------|
349
+ | `loading` | `boolean` | — | 显示 loading overlay;`undefined` 为挂载后首次 setData 前自动 loading |
350
+ | `suppressOverlays` | `OverlayType[]` | — | 逐项抑制内置 overlay |
351
+ | `suppressLoadingOverlay` | `boolean` | — | 抑制 loading overlay |
352
+ | `suppressNoRowsOverlay` | `boolean` | — | 抑制无数据 overlay |
353
+ | `suppressNoMatchingRowsOverlay` | `boolean` | — | 抑制筛选无匹配 overlay |
354
+ | `overlayLoadingTemplate` | `string` | — | loading 模板 HTML |
355
+ | `overlayNoRowsTemplate` | `string` | — | 无数据模板 HTML |
356
+ | `overlayNoMatchingRowsTemplate` | `string` | — | 筛选无匹配模板 HTML |
357
+ | `loadingOverlayComponent` | `OverlayComponentType` | — | 自定义 loading 组件 |
358
+ | `noRowsOverlayComponent` | `OverlayComponentType` | — | 自定义无数据组件 |
359
+ | `noMatchingRowsOverlayComponent` | `OverlayComponentType` | — | 自定义筛选无匹配组件 |
360
+ | `overlayComponent` | `OverlayComponentType` | — | 通用 overlay 组件 |
361
+ | `overlayInteraction` | `boolean` | — | overlay 内容是否可交互 |
362
+
363
+ #### 状态栏
364
+
365
+ | Prop | 类型 | 默认值 | 说明 |
366
+ |------|------|--------|------|
367
+ | `showStatusBar` | `boolean` | `true` | 是否显示底部状态栏 |
368
+ | `showDefaultStatusBarPanels` | `boolean` | `true` | 显示默认状态栏面板(行数/筛选态/选中数) |
369
+ | `showStatusBarRangeAggregation` | `boolean` | `true` | 框选时在状态栏展示平均值/计数/求和 |
370
+ | `statusBarRangeAggregationPrecision` | `number \| { average?: number; sum?: number }` | `2` | 平均值/求和展示小数位数 |
371
+
372
+ ---
373
+
374
+ ### ColumnDef 列定义
375
+
376
+ 每列通过 `columns` 数组传入。`key` 为列唯一标识,缺省等于 `prop`。
377
+
378
+ #### 标识与展示
379
+
380
+ | 字段 | 类型 | 说明 |
381
+ |------|------|------|
382
+ | `key` | `string` | 列唯一标识(colId),缺省等于 `prop` |
383
+ | `prop` | `string` | 数据字段 |
384
+ | `label` | `string` | 表头文案 |
385
+ | `hidden` | `boolean` | 是否隐藏该列(不渲染、不参与布局);默认 `false` |
386
+
387
+ #### 尺寸
388
+
389
+ | 字段 | 类型 | 说明 |
390
+ |------|------|------|
391
+ | `width` | `number` | 固定列宽 px |
392
+ | `minWidth` | `number` | 最小列宽 px |
393
+ | `maxWidth` | `number` | 最大列宽 px |
394
+ | `flex` | `number` | 弹性列宽权重 |
395
+
396
+ #### 行为
397
+
398
+ | 字段 | 类型 | 说明 |
399
+ |------|------|------|
400
+ | `sortable` | `boolean` | 是否可排序 |
401
+ | `comparator` | `ColumnComparatorFn` | 自定义排序比较器(asc 语义;desc 由内核取反) |
402
+ | `filterable` | `boolean` | 是否可筛选 |
403
+ | `filterType` | `ColumnDataFilterType` | 筛选数据类型;默认 `text` |
404
+ | `filterParams` | `FilterParams` | 列级 filter 参数 |
405
+ | `filterValueGetter` | `(row) => unknown` | 筛选用取值;缺省同 getter/prop |
406
+ | `editable` | `boolean \| (row) => boolean` | 是否可编辑 |
407
+ | `resizable` | `boolean` | 是否允许拖拽调整列宽;缺省继承 Grid `resizable` |
408
+ | `suppressAutoSize` | `boolean` | 禁止 resize 把柄 dblclick / API auto-size |
409
+ | `suppressSizeToFit` | `boolean` | 禁止参与 sizeColumnsToFit |
410
+ | `fixed` | `'left' \| 'right' \| null` | 固定列 |
411
+ | `movable` | `boolean` | 是否允许表头拖拽重排;默认继承 `columnMovable` |
412
+ | `rowDrag` | `boolean` | 该列单元格作为行拖拽起点 |
413
+ | `rowExpand` | `boolean` | 在该列渲染 expand/collapse 控件 |
414
+ | `autoHeight` | `boolean` | 该列内容撑开行高 |
415
+
416
+ #### 行分组(需 `rowGrouping: true`)
417
+
418
+ | 字段 | 类型 | 说明 |
419
+ |------|------|------|
420
+ | `rowGroup` | `boolean` | 该列参与行分组 |
421
+ | `rowGroupIndex` | `number` | 多级分组顺序(小者优先) |
422
+ | `groupAgg` | `SummaryAgg` | 分组 footer 行的聚合 |
423
+ | `showGroupHeaderCell` | `boolean` | 在该列渲染 groupHeader 单元格 |
424
+ | `showGroupFooterCell` | `boolean` | 在该列渲染 groupFooter 标签 |
425
+ | `groupFooterLabel` | `string` | 覆盖 Grid `groupFooterLabel` 的本列小计文案 |
426
+
427
+ #### 合并单元格(需 `enableCellSpan: true`)
428
+
429
+ | 字段 | 类型 | 说明 |
430
+ |------|------|------|
431
+ | `colSpan` | `ColSpanFn` | 横向合并列数(≥1) |
432
+ | `rowSpan` | `RowSpanFn` | 纵向合并行数(≥1);与 `spanRows` 互斥时本字段优先 |
433
+ | `spanRows` | `boolean \| SpanRowsFunc` | 相邻等值自动纵向合并 |
434
+
435
+ #### 数据转换与渲染
436
+
437
+ | 字段 | 类型 | 说明 |
438
+ |------|------|------|
439
+ | `getter` | `(row, value) => unknown` | 取值转换 |
440
+ | `formatter` | `(row, value) => string` | 展示格式化 |
441
+ | `cellRenderer` | `CellRendererFn` | 自定义单元格渲染器(函数;Vue 组件通过 `#cell-{colId}` 插槽) |
442
+ | `cellEditor` | `CellEditorDef` | 自定义单元格编辑器(函数、内置 `text`/`number`/`checkbox`、或命名引用) |
443
+ | `cellEditorMode` | `'overlay' \| 'inline'` | 编辑器呈现方式;默认 `overlay` |
444
+ | `valueParser` | `(value, params) => unknown` | 提交前解析编辑值 |
445
+ | `valueSetter` | `(params) => boolean \| Promise<boolean>` | 自定义写回逻辑;返回 `false` 拒绝提交 |
446
+ | `editType` | `CellEditType` | 编辑触发策略;缺省继承 grid 级配置 |
447
+
448
+ #### 校验
449
+
450
+ | 字段 | 类型 | 说明 |
451
+ |------|------|------|
452
+ | `cellValidator` | `CellValidator` | 手写校验(优先级高于 validationRules) |
453
+ | `validationRules` | `ValidationRules` | async-validator 规则 |
454
+ | `validationRequired` | `boolean` | 必填列标记 |
455
+
456
+ #### 剪贴板
457
+
458
+ | 字段 | 类型 | 说明 |
459
+ |------|------|------|
460
+ | `suppressPaste` | `boolean \| SuppressPasteFn` | 禁止粘贴 |
461
+ | `useParserForClipboard` | `boolean` | 粘贴是否走 valueParser;默认 `true` |
462
+ | `useFormatterForClipboard` | `boolean` | 复制是否走 formatter;默认 `true` |
463
+
464
+ #### 汇总
465
+
466
+ | 字段 | 类型 | 说明 |
467
+ |------|------|------|
468
+ | `summary` | `boolean` | 是否参与表尾汇总;缺省:有 `summaryAgg` 则为 true |
469
+ | `summaryAgg` | `SummaryAgg` | 表尾汇总聚合:`sum`/`avg`/`min`/`max`/`count` 或自定义函数 |
470
+ | `summaryFormatter` | `(value) => string` | 汇总格专用 formatter |
471
+
472
+ #### 对齐
473
+
474
+ | 字段 | 类型 | 说明 |
475
+ |------|------|------|
476
+ | `headerAlign` / `headerValign` | 对齐枚举 | 表头对齐;默认 `center` |
477
+ | `align` / `valign` | 对齐枚举 | 表体对齐;默认 `center` |
478
+ | `footerAlign` / `footerValign` | 对齐枚举 | 表尾对齐;默认 `center` |
479
+
480
+ #### 禁用与样式
481
+
482
+ | 字段 | 类型 | 说明 |
483
+ |------|------|------|
484
+ | `disabled` | `boolean` | 列级禁用:该列全部数据行 disabled |
485
+ | `cellDisabled` | `boolean \| CellDisabledFn` | 格级禁用;与 disabled / isRowDisabled 叠加 |
486
+ | `cellStyle` | `CellStyle \| CellStyleFn` | 列级静态背景或格级 cellStyle 回调 |
487
+ | `suppressCellComments` | `boolean \| SuppressCellCommentFn` | 抑制该列(或特定行)的批注新建/编辑/删除 |
488
+
489
+ #### Tooltip
490
+
491
+ | 字段 | 类型 | 说明 |
492
+ |------|------|------|
493
+ | `tooltipField` | `string` | 读 `row.data[field]` 作为 tooltip |
494
+ | `tooltipValueGetter` | `TooltipValueGetter` | 自定义 tooltip 文案 |
495
+ | `headerTooltip` | `string` | 表头静态 tooltip |
496
+ | `headerTooltipValueGetter` | `HeaderTooltipValueGetter` | 表头自定义 tooltip |
497
+ | `suppressTooltip` | `boolean` | 抑制该列溢出 tooltip |
498
+ | `tooltipComponent` | `TooltipComponentType` | 列级自定义 tooltip 组件 |
499
+ | `tooltipComponentParams` | `Record<string, unknown>` | tooltip 组件参数 |
500
+
501
+ ---
502
+
503
+ ## Events
504
+
505
+ MagicGrid 通过 Vue 事件向外暴露 Grid 内核事件。事件名采用 kebab-case。
506
+
507
+ ### 渲染与滚动
508
+
509
+ | 事件 | payload | 说明 |
510
+ |------|----------|------|
511
+ | `scroll` | `GridMetrics` | 滚动后触发(含 scrollTop、可见行范围等) |
512
+ | `data-rendered` | `GridMetrics` | 数据渲染完成后触发 |
513
+
514
+ ### 交互
515
+
516
+ | 事件 | payload | 说明 |
517
+ |------|---------|------|
518
+ | `cell-clicked` | `CellClickedEvent` | 单元格点击 |
519
+ | `row-click` | `RowClickedEvent` | 行点击 |
520
+ | `row-dblclick` | `RowDoubleClickedEvent` | 行双击 |
521
+ | `selection-changed` | `SelectionChangedEvent` | 行选择变更;含 `selectedRowIds` |
522
+ | `index-focus-changed` | `IndexFocusChangedEvent` | 索引列辅助定位变更 |
523
+
524
+ ### 编辑
525
+
526
+ | 事件 | payload | 说明 |
527
+ |------|---------|------|
528
+ | `cell-editing-started` | `CellEditingStartedEvent` | 单元格进入编辑态 |
529
+ | `cell-editing-stopped` | `CellEditingStoppedEvent` | 单元格退出编辑态 |
530
+ | `cell-value-changed` | `CellValueChangedEvent` | 单元格值已提交变更 |
531
+ | `cell-commit-started` | `CellCommitStartedEvent` | 单元格异步提交开始 |
532
+ | `cell-commit-finished` | `CellCommitFinishedEvent` | 单元格异步提交完成 |
533
+ | `edit-commit-aborted` | `EditCommitAbortedEvent` | 异步提交被中断 |
534
+ | `row-editing-started` | `RowEditingStartedEvent` | 行进入编辑态 |
535
+ | `row-editing-stopped` | `RowEditingStoppedEvent` | 行退出编辑态 |
536
+ | `row-value-changed` | `RowValueChangedEvent` | 行编辑整行提交 |
537
+ | `row-commit-started` | `RowCommitStartedEvent` | 行异步提交开始 |
538
+ | `row-commit-finished` | `RowCommitFinishedEvent` | 行异步提交完成 |
539
+
540
+ ### 校验
541
+
542
+ | 事件 | payload | 说明 |
543
+ |------|---------|------|
544
+ | `cell-validation-failed` | `CellValidationFailedEvent` | 单元格校验失败 |
545
+ | `row-validation-failed` | `RowValidationFailedEvent` | 行校验失败 |
546
+
547
+ ### 排序与筛选
548
+
549
+ | 事件 | payload | 说明 |
550
+ |------|---------|------|
551
+ | `sort-changed` | `SortModelItem[]` | 排序模型变更 |
552
+ | `filter-changed` | `FilterModel` | 筛选模型变更 |
553
+
554
+ ### 列
555
+
556
+ | 事件 | payload | 说明 |
557
+ |------|---------|------|
558
+ | `column-moved` | `ColumnMovedEvent` | 列拖拽重排完成 |
559
+ | `column-resized` | `ColumnResizedEvent` | 列宽调整 |
560
+ | `column-pinned` | `ColumnPinnedEvent` | 列固定状态变更 |
561
+ | `column-hidden-changed` | `ColumnHiddenChangedEvent` | 列显隐变更 |
562
+
563
+ ### 行 CRUD 与拖拽
564
+
565
+ | 事件 | payload | 说明 |
566
+ |------|---------|------|
567
+ | `rows-added` | `RowsAddedEvent` | 行新增 |
568
+ | `rows-removed` | `RowsRemovedEvent` | 行删除 |
569
+ | `row-id-promoted` | `RowIdPromotedEvent` | 临时行 ID 提升为正式主键 |
570
+ | `row-moved` | `RowMovedEvent` | 编程式或 UI 行移动 |
571
+ | `row-drag-end` | `RowDragEndEvent` | 行拖拽结束(`rowDragManaged: false` 时由业务改序) |
572
+ | `row-drag-commit-started` | `RowDragCommitStartedEvent` | deferred 模式 commit 开始 |
573
+ | `row-drag-commit-finished` | `RowDragCommitFinishedEvent` | deferred 模式 commit 完成 |
574
+ | `row-height-changed` | `RowHeightChangedEvent` | 行高变更 |
575
+
576
+ ### 展开行
577
+
578
+ | 事件 | payload | 说明 |
579
+ |------|---------|------|
580
+ | `row-expanded` | `RowExpansionChangedEvent` | 主行展开 |
581
+ | `row-collapsed` | `RowExpansionChangedEvent` | 主行折叠 |
582
+
583
+ ### 行分组
584
+
585
+ | 事件 | payload | 说明 |
586
+ |------|---------|------|
587
+ | `row-group-opened` | `RowGroupOpenedEvent` | 分组节点展开/折叠 |
588
+ | `row-group-changed` | `RowGroupChangedEvent` | 分组列配置变更 |
589
+
590
+ ### 树形表格
591
+
592
+ | 事件 | payload | 说明 |
593
+ |------|---------|------|
594
+ | `tree-node-opened` | `TreeNodeOpenedEvent` | 树节点展开/折叠 |
595
+ | `tree-children-loading` | `TreeChildrenLoadingEvent` | 懒加载子节点开始 |
596
+ | `tree-children-loaded` | `TreeChildrenLoadedEvent` | 懒加载子节点成功 |
597
+ | `tree-children-load-failed` | `TreeChildrenLoadFailedEvent` | 懒加载子节点失败 |
598
+
599
+ ### 批注
600
+
601
+ | 事件 | payload | 说明 |
602
+ |------|---------|------|
603
+ | `cell-comment-changed` | `CellCommentChangedEvent` | 单元格批注变更 |
604
+
605
+ ### 框选
606
+
607
+ | 事件 | payload | 说明 |
608
+ |------|---------|------|
609
+ | `cell-selection-changed` | `CellSelectionChangedEvent` | 框选范围变更 |
610
+ | `cell-selection-delete-start` | `CellSelectionDeleteStartEvent` | Delete 清空选区开始 |
611
+ | `cell-selection-delete-end` | `CellSelectionDeleteEndEvent` | Delete 清空选区结束 |
612
+
613
+ ### 空态
614
+
615
+ | 事件 | payload | 说明 |
616
+ |------|---------|------|
617
+ | `overlay-shown` | `OverlayShownEvent` | overlay 显示 |
618
+ | `overlay-hidden` | `OverlayHiddenEvent` | overlay 隐藏 |
619
+
620
+ ### 事件监听示例
621
+
622
+ ```vue
623
+ <MagicGrid
624
+ @cell-value-changed="({ rowId, colId, newValue, oldValue }) => { ... }"
625
+ @sort-changed="(model) => { ... }"
626
+ @filter-changed="(model) => { ... }"
627
+ />
628
+ ```
629
+
630
+ 除 Vue 事件外,也可通过 `gridRef.api` 订阅内核事件(见 [Expose](#expose))。
631
+
632
+ ---
633
+
634
+ ## Expose
635
+
636
+ 通过组件 `ref` 获取 `MagicGridExpose` 实例,进行命令式操作。
637
+
638
+ ### 类型定义
639
+
640
+ ```ts
641
+ interface MagicGridExpose {
642
+ /** GridApi 实例(Ref) */
643
+ api: Ref<GridApi | undefined>
644
+ /** 读取渲染与滚动指标 */
645
+ getMetrics: () => GridMetrics | undefined
646
+ /** 编程式滚动 */
647
+ scrollTo: (scrollTop: number, scrollLeft?: number) => void
648
+ /** 设置排序模型 */
649
+ setSortModel: (model: SortModelItem[]) => void
650
+ /** 读取排序模型 */
651
+ getSortModel: () => SortModelItem[]
652
+ /** 设置筛选模型 */
653
+ setFilterModel: (model: FilterModel) => void
654
+ /** 导出当前表格业务数据 */
655
+ getData: (options?: GetDataOptions) => RowData[]
656
+ /** 增量事务:add / update / remove */
657
+ applyTransaction: (transaction: RowTransaction) => Promise<RowNodeTransaction | undefined>
658
+ /** 开启批量更新(与 endUpdate 配对) */
659
+ beginUpdate: () => void
660
+ /** 结束批量更新并 flush */
661
+ endUpdate: () => void
662
+ /** 滚动使指定行下标进入视口 */
663
+ ensureIndexVisible: (index: number, position?: 'top' | 'bottom' | 'middle') => void
664
+ /** 强制 flush 待渲染帧 */
665
+ flushFrames: () => void
666
+ }
667
+ ```
668
+
669
+ ### 使用示例
670
+
671
+ ```vue
672
+ <script setup lang="ts">
673
+ import { ref } from 'vue'
674
+ import type { MagicGridExpose } from '@taocompany/magic-grid'
675
+
676
+ const gridRef = ref<MagicGridExpose>()
677
+
678
+ async function addRow() {
679
+ await gridRef.value?.applyTransaction({
680
+ add: [{ id: Date.now(), name: '新行' }],
681
+ })
682
+ }
683
+
684
+ function exportData() {
685
+ return gridRef.value?.getData({ sourceOrder: true })
686
+ }
687
+
688
+ function scrollToRow(index: number) {
689
+ gridRef.value?.ensureIndexVisible(index, 'middle')
690
+ }
691
+ </script>
692
+
693
+ <template>
694
+ <MagicGrid ref="gridRef" ... />
695
+ </template>
696
+ ```
697
+
698
+ ### GridApi(`gridRef.api`)
699
+
700
+ `api` 是完整的命令式 API 面,按职责分组如下。完整参考见 [`docs/16-grid-api-reference.md`](docs/16-grid-api-reference.md)。
701
+
702
+ #### 数据
703
+
704
+ | 方法 | 说明 |
705
+ |------|------|
706
+ | `setData(rows)` | 全量替换表格数据 |
707
+ | `applyTransaction(tx)` | 增量事务 add/update/remove |
708
+ | `addRows(options)` | 在指定位置插入行 |
709
+ | `removeRows(options)` | 按 rowId 或下标删除行 |
710
+ | `getData(options?)` | 导出业务层 RowData[] |
711
+ | `promoteRowId(options)` | 临时行 ID 提升为正式主键 |
712
+ | `moveRow(rowId, toIndex, indexMode?)` | 编程式移动行 |
713
+
714
+ #### 排序 / 筛选
715
+
716
+ | 方法 | 说明 |
717
+ |------|------|
718
+ | `setSortModel(model)` / `getSortModel()` | 排序模型读写 |
719
+ | `setFilterModel(model)` / `getFilterModel()` | 筛选模型读写 |
720
+ | `setColumnFilter(colId, condition)` | 设置单列筛选 |
721
+ | `getColumnFilter(colId)` | 读取单列筛选条件 |
722
+ | `isColumnFilterActive(colId)` | 单列是否有有效筛选 |
723
+ | `isAnyFilterActive()` | 任一列 filter 或 quick filter 是否 active |
724
+ | `setQuickFilterText(text)` / `getQuickFilterText()` | Quick filter 读写 |
725
+ | `clearAllFilters()` | 清除全部筛选 |
726
+ | `getColumnDistinctFilterValues(colId)` | 列 distinct 值(set filter 勾选列表) |
727
+
728
+ #### 列
729
+
730
+ | 方法 | 说明 |
731
+ |------|------|
732
+ | `moveColumn(colId, toIndex)` | 编程式移动列 |
733
+ | `resetColumnOrder()` | 各 lane 内用户列恢复 defOrder |
734
+ | `resetColumnWidths()` | 用户列恢复 defWidth/defFlex |
735
+ | `setColumnFixed(colId, fixed)` | 运行时改列 fixed |
736
+ | `setColumnsHidden(colIds, hidden)` | 批量设置列 hidden |
737
+ | `isColumnHidden(colId)` | 列是否 hidden |
738
+ | `getDisplayedColumnIds()` | 当前 UI 展示的列 id |
739
+ | `getColumns()` / `getDisplayedColumns()` | 全量列 / 展示列 |
740
+ | `setColumnWidth(colId, width, finished?, source?)` | 设置单列宽度 |
741
+ | `setColumnWidths(payloads, finished?, source?)` | 批量设置列宽 |
742
+ | `getColumnWidth(colId)` | 读取列当前像素宽度 |
743
+ | `autoSizeColumn(colId, skipHeader?)` | 按内容自动调整列宽 |
744
+ | `autoSizeColumns(colIds, skipHeader?)` | 批量 auto-size |
745
+ | `sizeColumnsToFit(params?)` | 列宽按比例分配至视口 |
746
+
747
+ #### 行高
748
+
749
+ | 方法 | 说明 |
750
+ |------|------|
751
+ | `setRowHeight(rowId, height, finished?)` | 设置单行高度 |
752
+ | `setRowHeights(changes, finished?)` | 批量设置行高 |
753
+ | `getRowHeight(rowId)` | 读取行当前有效高度 |
754
+ | `resetRowHeights(rowIds?)` | 清除 pinned 并重算行高 |
755
+ | `updateDimensions(params)` | 热更新默认行高与 clamp 边界 |
756
+
757
+ #### 渲染 / 视口
758
+
759
+ | 方法 | 说明 |
760
+ |------|------|
761
+ | `refreshCells(params?)` | 刷新指定行或列的单元格 DOM |
762
+ | `refreshCellSpans()` | 强制重建单元格合并 cache |
763
+ | `getCellSpan(rowId, colId)` | 查询 span 信息 |
764
+ | `ensureIndexVisible(index, position?)` | 滚动使行下标进入视口 |
765
+ | `getRowNode(id)` | 按 rowId 获取行节点快照 |
766
+ | `getMetrics()` | 读取渲染与滚动指标 |
767
+ | `beginUpdate()` / `endUpdate()` | 批量更新 |
768
+ | `scrollTo(scrollTop, scrollLeft?)` | 编程式滚动 |
769
+
770
+ #### 编辑
771
+
772
+ | 方法 | 说明 |
773
+ |------|------|
774
+ | `startEditingCell({ rowIndex, colKey })` | 编程式进入单元格编辑 |
775
+ | `stopEditing(cancel?)` | 结束当前编辑会话 |
776
+ | `isEditing()` | 是否存在编辑态 |
777
+ | `isCommitting()` | 是否正在异步提交 |
778
+ | `cancelCommit()` | 中断进行中的异步提交 |
779
+ | `getEditSessionPhase()` | 当前编辑会话阶段 |
780
+ | `getEditingCell()` | 当前主编辑单元格 |
781
+ | `getEditingCells()` | 行编辑模式下所有编辑单元格 |
782
+ | `registerCellEditor(name, editor)` | 注册命名单元格编辑器 |
783
+ | `unregisterCellEditor(name)` | 注销实例级编辑器 |
784
+
785
+ #### 校验
786
+
787
+ | 方法 | 说明 |
788
+ |------|------|
789
+ | `validate(options?)` | 校验全表或指定行 |
790
+ | `validateRows(options)` | 校验指定行列表 |
791
+ | `validateCells(options)` | 校验指定单元格列表 |
792
+ | `clearValidation(options?)` | 清除校验视觉反馈 |
793
+ | `clearRowValidation(options)` | 清除指定行校验反馈 |
794
+ | `clearCellValidation(options)` | 清除指定单元格校验反馈 |
795
+
796
+ #### 行选择 / 索引定位
797
+
798
+ | 方法 | 说明 |
799
+ |------|------|
800
+ | `toggleRowSelection(rowIds, selected?, force?)` | 切换或设置行 checkbox 选中 |
801
+ | `toggleAllSelection(selected?)` | 表头全选 checkbox 操作 |
802
+ | `setIndexFocus(rowIds)` | 设置索引列辅助定位 |
803
+
804
+ #### 展开 / 分组 / 树
805
+
806
+ | 方法 | 说明 |
807
+ |------|------|
808
+ | `expandRow(rowId)` / `collapseRow(rowId)` | 展开/折叠主行 |
809
+ | `isRowExpanded(rowId)` | 主行是否已展开 |
810
+ | `expandAll()` / `collapseAll()` | 全部展开/折叠 |
811
+ | `setRowGroupColumns(colIds)` / `getRowGroupColumns()` | 分组列读写 |
812
+ | `expandGroup(groupId)` / `collapseGroup(groupId)` | 展开/折叠分组节点 |
813
+ | `isGroupExpanded(groupId)` | 分组是否已展开 |
814
+ | `expandNode(rowId)` / `collapseNode(rowId)` | 展开/折叠 tree 节点 |
815
+ | `isNodeExpanded(rowId)` | tree 节点是否已展开 |
816
+ | `getDataPath(rowId)` | 查询行的 dataPath |
817
+
818
+ #### 批注 / 框选 / 空态
819
+
820
+ | 方法 | 说明 |
821
+ |------|------|
822
+ | `getCellComment(rowId, colId)` / `setCellComment(...)` | 批注读写 |
823
+ | `refreshCellComments(params?)` | 刷新批注角标 |
824
+ | `getCellRanges()` / `clearCellSelection()` / `addCellRange(params)` | 框选操作 |
825
+ | `getCellSelectionAggregation()` | 当前框选聚合统计 |
826
+ | `copySelectedRangeToClipboard()` / `pasteFromClipboard()` | 剪贴板操作 |
827
+ | `showLoadingOverlay()` / `showNoRowsOverlay()` / `hideOverlay()` | overlay 控制 |
828
+ | `isOverlayShowing()` / `getOverlayType()` | overlay 状态查询 |
829
+ | `refreshDisabledState(params?)` | 重算 disabled 投影 |
830
+ | `refreshCellStyles(params?)` | 重算 cellStyle 投影 |
831
+
832
+ #### 事件订阅
833
+
834
+ ```ts
835
+ const api = gridRef.value?.api
836
+ const off = api?.on('selectionChanged', (event) => {
837
+ console.log(event.selectedRowIds)
838
+ })
839
+ // 取消订阅
840
+ off?.()
841
+ ```
842
+
843
+ ### rowId 约定
844
+
845
+ - **入参**:接受 `string | number`,与 `data[rowKey]` 类型一致;API 边界自动 `String()`。
846
+ - **出参 / 事件**:内核 rowId 恒为 `string`(与 DOM `data-row-id` 一致)。
847
+ - **临时行**:新增时省略 `rowKey` 或值为 `null` 时生成 `__mg_tmp_*` 内部 id;`getData()` 导出时对应字段为 `null`。
848
+
849
+ ---
850
+
851
+ ## Slots
852
+
853
+ MagicGrid 提供静态插槽与动态列插槽两类。
854
+
855
+ ### 布局插槽
856
+
857
+ #### `#toolbar`
858
+
859
+ 表格顶部工具栏区域。
860
+
861
+ | 插槽 prop | 类型 | 说明 |
862
+ |-----------|------|------|
863
+ | `api` | `GridApi \| undefined` | GridApi 实例 |
864
+ | `size` | `MagicGridSize` | 当前尺寸 preset |
865
+ | `portalEl` | `HTMLElement \| undefined` | 浮层挂载 portal 元素 |
866
+
867
+ ```vue
868
+ <MagicGrid ...>
869
+ <template #toolbar="{ api, size }">
870
+ <button @click="api?.clearAllFilters()">清除筛选</button>
871
+ </template>
872
+ </MagicGrid>
873
+ ```
874
+
875
+ #### `#status-bar`
876
+
877
+ 完全自定义底部状态栏(提供时替换默认状态栏布局)。
878
+
879
+ | 插槽 prop | 类型 | 说明 |
880
+ |-----------|------|------|
881
+ | `api` | `GridApi \| undefined` | GridApi 实例 |
882
+ | `totalRowCount` | `number` | 源数据总行数(过滤前) |
883
+ | `displayedRowCount` | `number` | 当前展示行数 |
884
+ | `isFiltered` | `boolean` | 是否处于过滤态 |
885
+ | `selectedRowCount` | `number` | 当前选中行数 |
886
+ | `rowSelectionEnabled` | `boolean` | 是否启用行选择 |
887
+ | `cellSelectionEnabled` | `boolean` | cellSelection 是否启用 |
888
+ | `cellSelectionAggregation` | `CellSelectionAggregation \| null` | 当前选区聚合 |
889
+ | `statusBarRangeAggregationPrecision` | `{ average: number; sum: number }` | 聚合小数位数 |
890
+ | `metrics` | `GridMetrics \| undefined` | 最近一次 metrics |
891
+
892
+ #### `#status-bar-left` / `#status-bar-right`
893
+
894
+ 默认状态栏布局下的左右区域(未提供 `#status-bar` 时生效)。props 同 `#status-bar`。
895
+
896
+ ```vue
897
+ <MagicGrid ...>
898
+ <template #status-bar-left="{ displayedRowCount, totalRowCount }">
899
+ 共 {{ totalRowCount }} 行,显示 {{ displayedRowCount }} 行
900
+ </template>
901
+ <template #status-bar-right="{ selectedRowCount }">
902
+ 已选 {{ selectedRowCount }} 行
903
+ </template>
904
+ </MagicGrid>
905
+ ```
906
+
907
+ ### 列级动态插槽
908
+
909
+ 插槽名中的 `{colId}` 为列的 `key` 或 `prop`(与 `ColumnDef` 中 `resolveColId` 规则一致)。
910
+
911
+ #### `#cell-{colId}`
912
+
913
+ 自定义单元格渲染(等价于 `column.cellRenderer`,插槽优先)。
914
+
915
+ | 插槽 prop | 类型 | 说明 |
916
+ |-----------|------|------|
917
+ | `row` | `RowData` | 行数据 |
918
+ | `value` | `unknown` | 原始值 |
919
+ | `formattedValue` | `string` | 格式化后的值 |
920
+ | `rowIndex` | `number` | rowsToDisplay 中的行下标 |
921
+ | `rowId` | `BusinessRowId` | 行 id |
922
+ | `colId` | `string` | 列 id |
923
+ | `isSummaryRow` | `boolean` | 是否为表尾汇总格 |
924
+
925
+ ```vue
926
+ <MagicGrid :columns="[{ key: 'status', prop: 'status', label: '状态' }]" ...>
927
+ <template #cell-status="{ value, row }">
928
+ <span :class="value === 'active' ? 'text-green' : 'text-gray'">
929
+ {{ value }}
930
+ </span>
931
+ </template>
932
+ </MagicGrid>
933
+ ```
934
+
935
+ #### `#cell-editor-{colId}`
936
+
937
+ 自定义单元格编辑器(等价于 `column.cellEditor` 函数形式)。
938
+
939
+ | 插槽 prop | 类型 | 说明 |
940
+ |-----------|------|------|
941
+ | `row` | `RowData` | 行数据 |
942
+ | `value` | `unknown` | 当前值 |
943
+ | `formattedValue` | `string` | 格式化后的值 |
944
+ | `rowIndex` | `number` | 行下标 |
945
+ | `rowId` | `BusinessRowId` | 行 id |
946
+ | `colId` | `string` | 列 id |
947
+ | `stopEditing` | `(cancel?: boolean) => void` | 结束编辑 |
948
+
949
+ ### 功能插槽
950
+
951
+ #### `#detail-row`
952
+
953
+ 主从展开行的详情区渲染(与 `detailCellRenderer` prop 二选一)。
954
+
955
+ | 插槽 prop | 类型 | 说明 |
956
+ |-----------|------|------|
957
+ | `row` | `RowData` | 主行数据 |
958
+ | `rowId` | `string` | 详情行 id |
959
+ | `masterRowId` | `string` | 主行 id |
960
+ | `detailRowData` | `unknown` | 详情区数据 |
961
+ | `loading` | `boolean` | 是否加载中 |
962
+ | `loadFailed` | `boolean` | 是否加载失败 |
963
+ | `loadError` | `unknown` | 加载错误 |
964
+
965
+ ```vue
966
+ <MagicGrid master-detail :get-detail-row-data="fetchDetail" ...>
967
+ <template #detail-row="{ row, detailRowData, loading }">
968
+ <div v-if="loading">加载中...</div>
969
+ <pre v-else>{{ detailRowData }}</pre>
970
+ </template>
971
+ </MagicGrid>
972
+ ```
973
+
974
+ #### `#tooltip`
975
+
976
+ 全局自定义 tooltip 组件(与 `tooltipComponent` prop 二选一)。接收 `ITooltipParams`:
977
+
978
+ | 字段 | 类型 | 说明 |
979
+ |------|------|------|
980
+ | `location` | `'cell' \| 'header' \| 'footer' \| 'statusBar'` | 触发位置 |
981
+ | `value` | `unknown` | 原始值 |
982
+ | `valueFormatted` | `string \| null` | 格式化值 |
983
+ | `colId` / `rowId` | `string` | 列/行 id |
984
+ | `data` | `Record<string, unknown>` | 行数据 |
985
+ | `hideTooltipCallback` | `() => void` | 隐藏 tooltip |
986
+ | `api` | `GridApi` | GridApi 实例 |
987
+
988
+ #### `#loading` / `#no-rows` / `#no-matching-rows`
989
+
990
+ 空态 overlay 自定义内容(与对应 `*OverlayComponent` prop 二选一)。
991
+
992
+ | 插槽 prop | 类型 | 说明 |
993
+ |-----------|------|------|
994
+ | `overlayType` | `OverlayType` | `'loading' \| 'noRows' \| 'noMatchingRows'` |
995
+ | `api` | `GridApi` | GridApi 实例 |
996
+ | `overlayText` | `string` | 内置模板文案(可选) |
997
+
998
+ ```vue
999
+ <MagicGrid :data="[]" ...>
1000
+ <template #no-rows="{ api }">
1001
+ <div class="empty-state">
1002
+ <p>暂无数据</p>
1003
+ <button @click="api?.showLoadingOverlay()">刷新</button>
1004
+ </div>
1005
+ </template>
1006
+ </MagicGrid>
1007
+ ```
1008
+
1009
+ ### 插槽优先级说明
1010
+
1011
+ | 能力 | 插槽 | 等价 prop | 优先级 |
1012
+ |------|------|-----------|--------|
1013
+ | 单元格渲染 | `#cell-{colId}` | `column.cellRenderer` | 插槽覆盖函数 |
1014
+ | 单元格编辑 | `#cell-editor-{colId}` | `column.cellEditor`(函数) | 插槽覆盖函数 |
1015
+ | 详情行 | `#detail-row` | `detailCellRenderer` | 插槽优先 |
1016
+ | Tooltip | `#tooltip` | `tooltipComponent` | 插槽优先 |
1017
+ | Loading | `#loading` | `loadingOverlayComponent` | 插槽优先 |
1018
+ | 无数据 | `#no-rows` | `noRowsOverlayComponent` | 插槽优先 |
1019
+ | 筛选无匹配 | `#no-matching-rows` | `noMatchingRowsOverlayComponent` | 插槽优先 |
1020
+
1021
+ ---
1022
+
1023
+ ## 辅助组件
1024
+
1025
+ 表格列设置(Phase 27)提供一组**独立组件**,对标 AG Grid 的 Side Bar + Columns Tool Panel。只要持有 `GridApi` 即可使用,不强依赖 MagicGrid 内部 DOM。
1026
+
1027
+ | 组件 | 职责 |
1028
+ |------|------|
1029
+ | `ColumnSettingsButton` | 齿轮触发器 + 下拉菜单 + 列设置 Popover(推荐组合使用) |
1030
+ | `ColumnSettingsPanel` | 列设置面板本体(可单独嵌入自定义容器) |
1031
+ | `ColumnSettingsMenuItem` | 下拉菜单中的自定义菜单项 |
1032
+ | `ColumnSettingsMenuIcon` | 菜单项内置图标(Lucide 风格 SVG) |
1033
+
1034
+ ### 典型集成
1035
+
1036
+ 推荐放在 MagicGrid `#toolbar` 插槽内,并使用 `portalEl` 将 Popover Teleport 到 Grid 内部 portal,避免被表格容器 `overflow` 裁剪:
1037
+
1038
+ ```vue
1039
+ <script setup lang="ts">
1040
+ import { ref } from 'vue'
1041
+ import {
1042
+ MagicGrid,
1043
+ ColumnSettingsButton,
1044
+ ColumnSettingsMenuItem,
1045
+ ColumnSettingsMenuIcon,
1046
+ } from '@taocompany/magic-grid'
1047
+ import type { GridApi, ColumnDef, RowData } from '@taocompany/magic-grid'
1048
+
1049
+ const columns: ColumnDef[] = [/* ... */]
1050
+ const data: RowData[] = [/* ... */]
1051
+
1052
+ function onResetColumnOrder(api: GridApi) {
1053
+ api.resetColumnOrder()
1054
+ }
1055
+ </script>
1056
+
1057
+ <template>
1058
+ <MagicGrid :columns="columns" :data="data" row-key="id" height="400">
1059
+ <template #toolbar="{ api, size, portalEl }">
1060
+ <ColumnSettingsButton
1061
+ v-if="api"
1062
+ :grid-api="api"
1063
+ :size="size"
1064
+ :portal-el="portalEl"
1065
+ >
1066
+ <!-- 可选:在下拉菜单中追加自定义项 -->
1067
+ <template #menu>
1068
+ <ColumnSettingsMenuItem @click="onResetColumnOrder(api!)">
1069
+ <template #icon>
1070
+ <ColumnSettingsMenuIcon name="order" />
1071
+ </template>
1072
+ 重置列顺序
1073
+ </ColumnSettingsMenuItem>
1074
+ </template>
1075
+ </ColumnSettingsButton>
1076
+ </template>
1077
+ </MagicGrid>
1078
+ </template>
1079
+ ```
1080
+
1081
+ 也可单独使用面板(例如侧边栏、Drawer 内):
1082
+
1083
+ ```vue
1084
+ <ColumnSettingsPanel
1085
+ v-if="gridApi"
1086
+ :grid-api="gridApi"
1087
+ :open="panelOpen"
1088
+ @close="panelOpen = false"
1089
+ />
1090
+ ```
1091
+
1092
+ ---
1093
+
1094
+ ### ColumnSettingsButton
1095
+
1096
+ 表格设置齿轮按钮。点击后先展开**下拉菜单**(含「列设置」「重置」及可选自定义项),选择「列设置」后打开**列设置 Popover 面板**。
1097
+
1098
+ #### Props
1099
+
1100
+ | Prop | 类型 | 默认值 | 说明 |
1101
+ |------|------|--------|------|
1102
+ | `gridApi` | `GridApi` | — | **必填**。Grid 命令式 API |
1103
+ | `portalEl` | `HTMLElement` | `'body'` | Teleport 挂载点;MagicGrid `#toolbar` 提供 `portalEl`(`.magic-grid__portal`) |
1104
+ | `label` | `string` | `'表格设置'` | 无障碍标签(`aria-label` / `title`);按钮仅显示 settings 图标 |
1105
+ | `disabled` | `boolean` | `false` | 禁用触发器;已打开时不允许再次打开 |
1106
+ | `size` | `'mini' \| 'small' \| 'default' \| 'large'` | — | 按钮尺寸;与 MagicGrid `size` 对齐;省略时继承父级 `.magic-grid` CSS 变量 |
1107
+ | `open` | `boolean` | — | 受控:列设置面板打开态(`v-model:open`) |
1108
+ | `defaultOpen` | `boolean` | `false` | 非受控:列设置面板初始打开态 |
1109
+ | `showVisibility` | `boolean` | `true` | 传递给内嵌 `ColumnSettingsPanel`:是否展示列显隐 checkbox |
1110
+ | `showFilter` | `boolean` | `true` | 传递给内嵌 `ColumnSettingsPanel`:是否展示筛选展开区 |
1111
+
1112
+ #### Events
1113
+
1114
+ | 事件 | payload | 说明 |
1115
+ |------|---------|------|
1116
+ | `update:open` | `boolean` | 列设置面板打开态变更(配合 `v-model:open`) |
1117
+ | `open` | — | 列设置面板打开 |
1118
+ | `close` | — | 列设置面板关闭 |
1119
+
1120
+ > 下拉菜单的「重置」操作直接调用 `GridApi`,不额外 emit 事件;自定义 `#menu` 项的点击需自行处理。
1121
+
1122
+ #### Slots
1123
+
1124
+ | 插槽 | 说明 |
1125
+ |------|------|
1126
+ | `#menu` | 下拉菜单底部自定义菜单项区域;提供时会在内置项与自定义项之间显示分隔线 |
1127
+
1128
+ 内置下拉菜单项(无需自行实现):
1129
+
1130
+ | 菜单项 | 行为 |
1131
+ |--------|------|
1132
+ | **列设置** | 打开列设置 Popover 面板 |
1133
+ | **重置 → 排序** | 调用 `setSortModel([])` |
1134
+ | **重置 → 筛选** | 调用 `clearAllFilters()` |
1135
+ | **重置 → 列宽** | 调用 `resetColumnWidths()` |
1136
+ | **重置 → 列顺序** | 调用 `resetColumnOrder()` |
1137
+ | **重置 → 固定列** | 取消全部用户列 fixed |
1138
+ | **重置 → 全部** | 依次执行以上全部重置 |
1139
+
1140
+ 重置作用域类型 `ColumnSettingsResetScope`:`'sort' | 'filter' | 'width' | 'order' | 'pin' | 'all'`(已从包导出)。
1141
+
1142
+ #### Expose
1143
+
1144
+ 无。通过 Props / Events / Slots 交互即可。
1145
+
1146
+ #### 交互行为
1147
+
1148
+ - **Esc**:先关闭列设置面板,再关闭下拉菜单
1149
+ - **点击外部**:关闭菜单与面板(打开瞬间有短暂防抖,避免误触)
1150
+ - **滚动 / resize**:自动重新定位浮层
1151
+ - **`portalEl` / `size` 变更**:关闭所有浮层并重建 Teleport
1152
+
1153
+ ---
1154
+
1155
+ ### ColumnSettingsPanel
1156
+
1157
+ 列设置面板本体。按 **左固定 / 中心 / 右固定 / 隐藏** 四组展示用户列,每行支持拖拽排序、排序切换、筛选面板、固定列、显隐控制;面板头部提供「清除全部筛选」。
1158
+
1159
+ > 通常由 `ColumnSettingsButton` 内嵌使用;也可单独 import 嵌入任意容器。
1160
+
1161
+ #### 面板能力一览
1162
+
1163
+ | 能力 | 说明 | 对应 GridApi |
1164
+ |------|------|--------------|
1165
+ | 列顺序 | lane 内拖拽重排 | `moveColumn` |
1166
+ | 列排序 | 点击循环 none → asc → desc | `setSortModel` |
1167
+ | 列筛选 | 行内展开筛选面板(与表头 filter 同源) | `setColumnFilter` / `clearAllFilters` |
1168
+ | 列固定 | 切换 null / left / right | `setColumnFixed` |
1169
+ | 列显隐 | checkbox 切换 hidden | `setColumnsHidden` |
1170
+ | 清除全部筛选 | 面板头部按钮 | `clearAllFilters` |
1171
+ | 显示全部隐藏列 | hidden 分组底部操作 | `setColumnsHidden(colIds, false)` |
1172
+
1173
+ 面板打开时自动订阅以下 Grid 事件并刷新 UI,与表头 / 列操作菜单状态同源:
1174
+
1175
+ `sortChanged` · `filterChanged` · `columnMoved` · `columnPinned` · `columnHiddenChanged`
1176
+
1177
+ #### Props
1178
+
1179
+ | Prop | 类型 | 默认值 | 说明 |
1180
+ |------|------|--------|------|
1181
+ | `gridApi` | `GridApi` | — | **必填**。Grid 命令式 API |
1182
+ | `open` | `boolean` | `true` | 打开态;`false` 时不订阅 Grid 事件(节省开销) |
1183
+ | `showVisibility` | `boolean` | `true` | 是否展示列显隐 checkbox |
1184
+ | `showFilter` | `boolean` | `true` | 是否展示筛选展开按钮与内嵌筛选面板 |
1185
+
1186
+ #### Events
1187
+
1188
+ | 事件 | payload | 说明 |
1189
+ |------|---------|------|
1190
+ | `close` | — | 用户点击面板右上角关闭按钮 |
1191
+
1192
+ #### Slots
1193
+
1194
+ 无公开插槽。面板 UI 由组件内部组合(`ColumnSettingsGroupedLists` · `ColumnSettingsRow` · `ColumnFilterPanelEmbed` 等)。
1195
+
1196
+ #### Expose
1197
+
1198
+ 无。
1199
+
1200
+ #### 样式与主题
1201
+
1202
+ 面板使用 MagicGrid 语义 token(`--mg-color-bg` · `--mg-color-text` · `--mg-color-border` 等),在暗色主题下自动适配。Popover 容器类名:
1203
+
1204
+ - `.mg-column-settings` — 面板根
1205
+ - `.mg-column-settings-popover` — Popover 外层
1206
+ - `.mg-column-settings-portal` — Teleport portal 容器
1207
+
1208
+ ---
1209
+
1210
+ ### ColumnSettingsMenuItem
1211
+
1212
+ 下拉菜单中的可点击菜单项。用于 `#menu` 插槽扩展 `ColumnSettingsButton` 的自定义操作。
1213
+
1214
+ #### Props
1215
+
1216
+ | Prop | 类型 | 默认值 | 说明 |
1217
+ |------|------|--------|------|
1218
+ | `label` | `string` | — | 菜单项文案;也可通过默认插槽覆盖 |
1219
+
1220
+ #### Slots
1221
+
1222
+ | 插槽 | 说明 |
1223
+ |------|------|
1224
+ | 默认 | 菜单项文案(优先于 `label` prop) |
1225
+ | `#icon` | 菜单项左侧图标区域 |
1226
+
1227
+ #### Events
1228
+
1229
+ 无 Vue 自定义事件。根元素为 `<button>`,可监听原生 DOM 事件:
1230
+
1231
+ ```vue
1232
+ <ColumnSettingsMenuItem @click="handleExport">
1233
+ <template #icon>
1234
+ <ColumnSettingsMenuIcon name="filter" />
1235
+ </template>
1236
+ 导出当前视图
1237
+ </ColumnSettingsMenuItem>
1238
+ ```
1239
+
1240
+ > 点击自定义菜单项后,`ColumnSettingsButton` 会自动关闭下拉菜单(通过 `@custom-action` 内部处理)。
1241
+
1242
+ #### Expose
1243
+
1244
+ 无。
1245
+
1246
+ ---
1247
+
1248
+ ### ColumnSettingsMenuIcon
1249
+
1250
+ 菜单项内置 SVG 图标组件,渲染 Lucide 风格路径。
1251
+
1252
+ #### Props
1253
+
1254
+ | Prop | 类型 | 默认值 | 说明 |
1255
+ |------|------|--------|------|
1256
+ | `name` | `ColumnSettingsMenuIconName` | — | **必填**。图标名称 |
1257
+ | `size` | `number` | `16` | 图标尺寸 px |
1258
+
1259
+ #### `ColumnSettingsMenuIconName` 可选值
1260
+
1261
+ | name | 用途 |
1262
+ |------|------|
1263
+ | `sliders-vertical` | 列设置(内置菜单项) |
1264
+ | `list-restart` | 重置(内置子菜单) |
1265
+ | `sort` | 排序重置 |
1266
+ | `filter` | 筛选重置 |
1267
+ | `width` | 列宽重置 |
1268
+ | `order` | 列顺序重置 |
1269
+ | `pin` | 固定列重置 |
1270
+ | `all` | 全部重置 |
1271
+
1272
+ 类型 `ColumnSettingsMenuIconName` 已从包导出:
1273
+
1274
+ ```ts
1275
+ import type { ColumnSettingsMenuIconName } from '@taocompany/magic-grid'
1276
+ ```
1277
+
1278
+ #### Slots / Events / Expose
1279
+
1280
+ 无。
1281
+
1282
+ ---
1283
+
1284
+ ## 相关文档
1285
+
1286
+ | 文档 | 说明 |
1287
+ |------|------|
1288
+ | [`docs/README.md`](docs/README.md) | 内部设计文档索引(架构、里程碑、AG Grid 对照) |
1289
+ | [`docs/16-grid-api-reference.md`](docs/16-grid-api-reference.md) | GridApi 完整参考 |
1290
+ | [`docs/07-third-party-cell-editor-guide.md`](docs/07-third-party-cell-editor-guide.md) | 第三方编辑器接入(Element Plus 等) |
1291
+ | [`docs/39-phase27-table-settings-button.md`](docs/39-phase27-table-settings-button.md) | 列设置按钮设计文档(Phase 27) |
1292
+
1293
+ ### 校验子路径
1294
+
1295
+ ```ts
1296
+ import { enrichColumnsWithValidation } from '@taocompany/magic-grid/validation'
1297
+ ```
1298
+
1299
+ 配合 `ColumnDef.validationRules` 使用 async-validator 规则。
1300
+
1301
+ ---
1302
+
1303
+ ## License
1304
+
1305
+ MIT © [songjiuzhang](mailto:jiuzhang.song@taoandcompany02.com)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taocompany/magic-grid",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "A high-performance virtual table component library for Vue 3",
5
5
  "type": "module",
6
6
  "license": "MIT",