@nokecy/qc-ui 1.1.50 → 1.1.51

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.
@@ -0,0 +1,39 @@
1
+ /**
2
+ * ArrayTable 分组表头(多级表头)。
3
+ *
4
+ * 背景:schema 里的每个 ArrayTable.Column 被抽成「扁平」列定义(buildArrayTableColumns),
5
+ * 内部一批逻辑(懒挂载列识别、列方案还原、首列拖拽等)都按扁平列取值,不能改。
6
+ * 所以分组只在「交给 AG-Grid 的那一份 columnDefs」上做:
7
+ * 1. buildArrayTableColumns 生成列定义时,用 markHeaderGroup 把列声明的 headerGroup 记下来;
8
+ * 2. index.tsx 把扁平列定义交给 groupColumnDefs,得到含列组的 columnDefs 传给 AgGridReact。
9
+ *
10
+ * 分组名记在模块内的 WeakMap 里,不往 colDef 上塞自定义字段——AG-Grid 会把未知属性当作错误告警。
11
+ *
12
+ * 只支持一级分组;分组名相同但不相邻的列各自成组。
13
+ *
14
+ * @author nokecy
15
+ */
16
+ import type { ColDef, ColGroupDef } from 'ag-grid-community';
17
+ /**
18
+ * 记下列定义所属的表头分组。
19
+ * headerGroup 不是非空字符串(没声明、空串、纯空白)时不做任何事,该列按无分组处理。
20
+ * 返回传入的 colDef 本身,方便链式使用。
21
+ */
22
+ export declare const markHeaderGroup: <T extends object>(colDef: T, headerGroup: unknown) => T;
23
+ /**
24
+ * 把扁平列定义按「相邻且 headerGroup 相同」合并成 AG-Grid 列组。
25
+ *
26
+ * - 相邻同名的列 -> 一个 { headerName, groupId, children } 列组;
27
+ * - 同名但被别的列隔开 -> 各自成组,groupId 各不相同;
28
+ * - 没声明分组的列原样保留(同一个对象);
29
+ * - 一个分组也没有时直接返回传入的数组本身,没用到分组的表格行为零变化。
30
+ *
31
+ * groupId 由分组名派生(同名第 N 次出现追加 _N),同样的输入永远得到同样的 id:
32
+ * columnDefs 因别的原因重建时,AG-Grid 靠 groupId 认出还是那个列组,列组状态不丢。
33
+ *
34
+ * 有意不设 marryChildren:设了以后,任何打破组内相邻的列顺序(用户旧的扁平列方案、
35
+ * 列设置面板里跨组拖动的实时预览)都会被 AG-Grid 整体丢弃并报 error #39;不设则顺序照常生效,
36
+ * 组被隔开时表头显示成多段。
37
+ * openByDefault:列组默认展开(只对配了 columnGroupShow 的可折叠列组有意义)。
38
+ */
39
+ export declare const groupColumnDefs: (colDefs: ColDef[]) => (ColDef | ColGroupDef)[];
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.markHeaderGroup = exports.groupColumnDefs = void 0;
7
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
8
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
9
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
10
+ /**
11
+ * ArrayTable 分组表头(多级表头)。
12
+ *
13
+ * 背景:schema 里的每个 ArrayTable.Column 被抽成「扁平」列定义(buildArrayTableColumns),
14
+ * 内部一批逻辑(懒挂载列识别、列方案还原、首列拖拽等)都按扁平列取值,不能改。
15
+ * 所以分组只在「交给 AG-Grid 的那一份 columnDefs」上做:
16
+ * 1. buildArrayTableColumns 生成列定义时,用 markHeaderGroup 把列声明的 headerGroup 记下来;
17
+ * 2. index.tsx 把扁平列定义交给 groupColumnDefs,得到含列组的 columnDefs 传给 AgGridReact。
18
+ *
19
+ * 分组名记在模块内的 WeakMap 里,不往 colDef 上塞自定义字段——AG-Grid 会把未知属性当作错误告警。
20
+ *
21
+ * 只支持一级分组;分组名相同但不相邻的列各自成组。
22
+ *
23
+ * @author nokecy
24
+ */
25
+
26
+ /** 列定义 -> 它在 schema 里声明的 headerGroup */
27
+ var headerGroupOf = new WeakMap();
28
+
29
+ /** 列组 id 前缀,与列方案里生成的 col_N 区分开 */
30
+ var GROUP_ID_PREFIX = 'arrayTableGroup_';
31
+
32
+ /**
33
+ * 记下列定义所属的表头分组。
34
+ * headerGroup 不是非空字符串(没声明、空串、纯空白)时不做任何事,该列按无分组处理。
35
+ * 返回传入的 colDef 本身,方便链式使用。
36
+ */
37
+ var markHeaderGroup = exports.markHeaderGroup = function markHeaderGroup(colDef, headerGroup) {
38
+ if (typeof headerGroup === 'string' && headerGroup.trim() !== '') {
39
+ headerGroupOf.set(colDef, headerGroup);
40
+ }
41
+ return colDef;
42
+ };
43
+
44
+ /**
45
+ * 把扁平列定义按「相邻且 headerGroup 相同」合并成 AG-Grid 列组。
46
+ *
47
+ * - 相邻同名的列 -> 一个 { headerName, groupId, children } 列组;
48
+ * - 同名但被别的列隔开 -> 各自成组,groupId 各不相同;
49
+ * - 没声明分组的列原样保留(同一个对象);
50
+ * - 一个分组也没有时直接返回传入的数组本身,没用到分组的表格行为零变化。
51
+ *
52
+ * groupId 由分组名派生(同名第 N 次出现追加 _N),同样的输入永远得到同样的 id:
53
+ * columnDefs 因别的原因重建时,AG-Grid 靠 groupId 认出还是那个列组,列组状态不丢。
54
+ *
55
+ * 有意不设 marryChildren:设了以后,任何打破组内相邻的列顺序(用户旧的扁平列方案、
56
+ * 列设置面板里跨组拖动的实时预览)都会被 AG-Grid 整体丢弃并报 error #39;不设则顺序照常生效,
57
+ * 组被隔开时表头显示成多段。
58
+ * openByDefault:列组默认展开(只对配了 columnGroupShow 的可折叠列组有意义)。
59
+ */
60
+ var groupColumnDefs = exports.groupColumnDefs = function groupColumnDefs(colDefs) {
61
+ if (!colDefs.some(function (colDef) {
62
+ return headerGroupOf.has(colDef);
63
+ })) return colDefs;
64
+ var usedGroupIds = new Set();
65
+ var makeGroupId = function makeGroupId(name) {
66
+ var id = "".concat(GROUP_ID_PREFIX).concat(name);
67
+ for (var n = 2; usedGroupIds.has(id); n++) {
68
+ id = "".concat(GROUP_ID_PREFIX).concat(name, "_").concat(n);
69
+ }
70
+ usedGroupIds.add(id);
71
+ return id;
72
+ };
73
+ var result = [];
74
+ var current = null;
75
+ var _iterator = _createForOfIteratorHelper(colDefs),
76
+ _step;
77
+ try {
78
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
79
+ var colDef = _step.value;
80
+ var name = headerGroupOf.get(colDef);
81
+ if (name === undefined) {
82
+ current = null;
83
+ result.push(colDef);
84
+ } else if (current && current.name === name) {
85
+ current.group.children.push(colDef);
86
+ } else {
87
+ var group = {
88
+ headerName: name,
89
+ groupId: makeGroupId(name),
90
+ openByDefault: true,
91
+ children: [colDef]
92
+ };
93
+ current = {
94
+ name: name,
95
+ group: group
96
+ };
97
+ result.push(group);
98
+ }
99
+ }
100
+ } catch (err) {
101
+ _iterator.e(err);
102
+ } finally {
103
+ _iterator.f();
104
+ }
105
+ return result;
106
+ };
@@ -10,6 +10,7 @@ var _agGridReact = require("ag-grid-react");
10
10
  var _react2 = require("@formily/react");
11
11
  var _uniqueId = _interopRequireDefault(require("lodash/uniqueId"));
12
12
  var _utils = require("./utils");
13
+ var _columnGroup = require("./columnGroup");
13
14
  var _hooks = require("./hooks");
14
15
  var _arrayBase = _interopRequireDefault(require("./arrayBase"));
15
16
  var _arrayAddBtn = _interopRequireDefault(require("./arrayAddBtn"));
@@ -82,14 +83,16 @@ var ArrayTableInner = (0, _react2.observer)(function (props) {
82
83
  // 通过 JSON.stringify 比较内容,只有内容真正变化时才返回新引用
83
84
  var sourcesKey = (0, _react.useMemo)(function () {
84
85
  return JSON.stringify(rawSources.map(function (s) {
85
- var _s$columnProps$header, _s$columnProps, _s$columnProps2;
86
+ var _s$columnProps$header, _s$columnProps, _s$columnProps2, _s$columnProps3;
86
87
  return {
87
88
  name: s.name,
88
89
  display: s.display,
89
90
  // 列标题可由 reactions 运行时改写,纳入 key 才能让 stableColumnDefs 跟着重建。
90
91
  // 宽度/隐藏/固定由 applyColumnState(方案)管,故意不纳入,避免行编辑时列状态被重置。
91
92
  // 可编辑性:带 x-reactions 的列在 buildArrayTableColumns 里已强制走 AgField 全树(尊重运行时 pattern),无需进 key。@author nokecy
92
- headerName: (_s$columnProps$header = (_s$columnProps = s.columnProps) === null || _s$columnProps === void 0 ? void 0 : _s$columnProps.headerName) !== null && _s$columnProps$header !== void 0 ? _s$columnProps$header : (_s$columnProps2 = s.columnProps) === null || _s$columnProps2 === void 0 ? void 0 : _s$columnProps2.title
93
+ headerName: (_s$columnProps$header = (_s$columnProps = s.columnProps) === null || _s$columnProps === void 0 ? void 0 : _s$columnProps.headerName) !== null && _s$columnProps$header !== void 0 ? _s$columnProps$header : (_s$columnProps2 = s.columnProps) === null || _s$columnProps2 === void 0 ? void 0 : _s$columnProps2.title,
94
+ // 分组名变了列组结构就变,同样要重建。@author nokecy
95
+ headerGroup: (_s$columnProps3 = s.columnProps) === null || _s$columnProps3 === void 0 ? void 0 : _s$columnProps3.headerGroup
93
96
  };
94
97
  }));
95
98
  }, [rawSources]);
@@ -150,6 +153,12 @@ var ArrayTableInner = (0, _react2.observer)(function (props) {
150
153
  return cols;
151
154
  }, [sources, props.onRowDrag]); // 移除 field 依赖,避免数据变化时重新计算
152
155
 
156
+ // 交给 AgGridReact 的列定义:按 x-component-props.headerGroup 把相邻同组的列合并成列组(多级表头)。
157
+ // stableColumnDefs 保持扁平,懒列识别、列方案还原等内部逻辑仍用它;只有喂给 AG-Grid 的这一份带分组。@author nokecy
158
+ var gridColumnDefs = (0, _react.useMemo)(function () {
159
+ return (0, _columnGroup.groupColumnDefs)(stableColumnDefs);
160
+ }, [stableColumnDefs]);
161
+
153
162
  // 懒挂载:把激活态 Set 通过 AG-Grid context 暴露给 LazyAgField(引用稳定,原地 mutate)。@author nokecy
154
163
  var gridContext = (0, _react.useMemo)(function () {
155
164
  return {
@@ -226,8 +235,8 @@ var ArrayTableInner = (0, _react2.observer)(function (props) {
226
235
  if (hasGroups) {
227
236
  // 传入 stableColumnDefs 作为原始定义,保留 cellRenderer(AgField/LazyAgField)及其
228
237
  // cellRendererParams——否则分组方案重建出的是裸列,单元格退化为纯文本、编辑失效。@author nokecy
229
- var gridColumnDefs = (0, _columnGroupUtils.flatConfigToGridState)(currentScheme.columnConfig, stableColumnDefs);
230
- gridApiState.setGridOption('columnDefs', gridColumnDefs);
238
+ var _gridColumnDefs = (0, _columnGroupUtils.flatConfigToGridState)(currentScheme.columnConfig, stableColumnDefs);
239
+ gridApiState.setGridOption('columnDefs', _gridColumnDefs);
231
240
  }
232
241
 
233
242
  // 2. 应用列状态(列顺序、宽度、隐藏、固定等)
@@ -420,7 +429,7 @@ var ArrayTableInner = (0, _react2.observer)(function (props) {
420
429
  ,
421
430
  rowHeight: 38,
422
431
  pagination: false,
423
- columnDefs: stableColumnDefs,
432
+ columnDefs: gridColumnDefs,
424
433
  rowData: dataSource
425
434
  })), sources.map(function (column, key) {
426
435
  //专门用来承接对Column的状态管理
@@ -3,9 +3,28 @@ import { FieldDisplayTypes, GeneralField } from "@formily/core";
3
3
  import { Schema } from "@formily/json-schema";
4
4
  import { AgGridReactProps } from "ag-grid-react";
5
5
  import React from "react";
6
+ /**
7
+ * ArrayTable.Column 的 x-component-props 里 qc-ui 自己认的扩展属性;
8
+ * 其余属性(width、headerName、pinned 等)按 AG-Grid 列定义处理。
9
+ *
10
+ * @author nokecy
11
+ */
12
+ interface ArrayTableColumnProps {
13
+ /**
14
+ * 表头分组名(多级表头,仅一级)。
15
+ * 相邻且 headerGroup 相同的列合并成一个列组,分组名作为组头;
16
+ * 同名但不相邻的列各自成组;不写则该列不分组。
17
+ */
18
+ headerGroup?: string;
19
+ /**
20
+ * 默认隐藏:为 true 时该列首次出现时是隐藏的,用户可在列设置里打开,列方案(applyColumnState)优先。
21
+ * 对应 AG-Grid 的 initialHide。注意 hide 在 ArrayTable 里不生效(状态归列方案管),要默认隐藏请用它。
22
+ */
23
+ defaultHide?: boolean;
24
+ }
6
25
  interface ObservableColumnSource {
7
26
  field: GeneralField;
8
- columnProps: any;
27
+ columnProps: ArrayTableColumnProps & Record<string, any>;
9
28
  schema: Schema;
10
29
  display: FieldDisplayTypes;
11
30
  name: string;
@@ -13,4 +32,4 @@ interface ObservableColumnSource {
13
32
  type ComposedArrayTable = React.FC<React.PropsWithChildren<AgGridReactProps>> & ArrayBaseMixins & {
14
33
  Column?: any;
15
34
  };
16
- export { ComposedArrayTable, ObservableColumnSource };
35
+ export { ComposedArrayTable, ObservableColumnSource, ArrayTableColumnProps };
@@ -12,7 +12,8 @@ var _shared = require("@formily/shared");
12
12
  var _jsonSchema = require("@formily/json-schema");
13
13
  var _arrayBase = _interopRequireDefault(require("./arrayBase"));
14
14
  var _readOnlyFormatters = require("./readOnlyFormatters");
15
- var _excluded = ["hide", "sort", "sortIndex", "forceAgField"];
15
+ var _columnGroup = require("./columnGroup");
16
+ var _excluded = ["hide", "sort", "sortIndex", "forceAgField", "headerGroup", "defaultHide"];
16
17
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
18
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
18
19
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -212,10 +213,12 @@ var resolveLazyCellPattern = function resolveLazyCellPattern(arrayField, record,
212
213
  try {
213
214
  var _arrayField$value$ind, _arrayField$value, _arrayField$value$ind2;
214
215
  var index = (_arrayField$value$ind = (_arrayField$value = arrayField.value) === null || _arrayField$value === void 0 || (_arrayField$value$ind2 = _arrayField$value.indexOf) === null || _arrayField$value$ind2 === void 0 ? void 0 : _arrayField$value$ind2.call(_arrayField$value, record)) !== null && _arrayField$value$ind !== void 0 ? _arrayField$value$ind : -1;
215
- var path = arrayField.address.concat(index).concat(dataKey);
216
+ // 与真字段一致:path 是数据路径(不含 void 容器),address 含 void 容器;表达式里 getValuesIn($self.path...) 靠前者
217
+ var path = arrayField.path.concat(index).concat(dataKey);
218
+ var address = arrayField.address.concat(index).concat(dataKey);
216
219
  var self = {
217
220
  path: path,
218
- address: path,
221
+ address: address,
219
222
  index: index,
220
223
  form: form,
221
224
  parent: arrayField,
@@ -420,6 +423,8 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
420
423
  sort = columnProps.sort,
421
424
  sortIndex = columnProps.sortIndex,
422
425
  forceAgField = columnProps.forceAgField,
426
+ headerGroup = columnProps.headerGroup,
427
+ defaultHide = columnProps.defaultHide,
423
428
  safeColumnProps = _objectWithoutProperties(columnProps, _excluded);
424
429
  var base = _objectSpread(_objectSpread({}, safeColumnProps), {}, {
425
430
  // 保留 width 作为列的初始宽度
@@ -427,7 +432,15 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
427
432
  //@ts-ignore
428
433
  headerName: columnProps.headerName || columnProps.title,
429
434
  field: name
430
- });
435
+ }, defaultHide === true ? {
436
+ initialHide: true
437
+ } : {});
438
+
439
+ // 记下分组名再输出列定义;真正合并成列组在 index.tsx 交给 AG-Grid 之前(groupColumnDefs)做,
440
+ // 这里产出的仍是扁平列定义。@author nokecy
441
+ var emit = function emit(colDef) {
442
+ return buf.concat((0, _columnGroup.markHeaderGroup)(colDef, headerGroup));
443
+ };
431
444
 
432
445
  // 三分流渲染策略:@author nokecy
433
446
  // ① 只读纯文本(永不可编辑):只读列 + 有格式化器 -> valueFormatter,不挂 Formily 树。
@@ -463,7 +476,7 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
463
476
  // 读 AG-Grid 缓存值不刷新 → 反应式只读渲染。整表 readPretty(明细/详情页,数据 setValues 整体加载、
464
477
  // 行引用整体替换、AG-Grid 自然刷新)仍走更廉价的静态 valueFormatter 快路径。@author nokecy
465
478
  if (arrayPattern !== 'readPretty') {
466
- return buf.concat(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
479
+ return emit(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
467
480
  valueGetter: valueGetter
468
481
  } : {}), {}, {
469
482
  cellRenderer: LazyReadOnlyText,
@@ -474,7 +487,7 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
474
487
  }
475
488
  }));
476
489
  }
477
- return buf.concat(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
490
+ return emit(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
478
491
  valueGetter: valueGetter
479
492
  } : {}), {}, {
480
493
  // 显式清掉可能从 safeColumnProps 漏带的 cellRenderer(AG-Grid 中 renderer 优先级高于 formatter)
@@ -490,7 +503,7 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
490
503
 
491
504
  // ② 可编辑懒挂载(排除单击直控的 Switch/Checkbox:须 eager 出真控件)
492
505
  if (!readOnly && formatter && !hasReactions && !forceEager && !isInlineToggle && canFastPath) {
493
- return buf.concat(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
506
+ return emit(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
494
507
  valueGetter: valueGetter
495
508
  } : {}), {}, {
496
509
  cellRenderer: LazyAgField,
@@ -507,7 +520,7 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
507
520
  }
508
521
 
509
522
  // ③ 兜底全树
510
- return buf.concat(_objectSpread(_objectSpread({}, base), {}, {
523
+ return emit(_objectSpread(_objectSpread({}, base), {}, {
511
524
  cellRendererParams: {
512
525
  dataSource: dataSource,
513
526
  schema: schema,
@@ -0,0 +1,39 @@
1
+ /**
2
+ * ArrayTable 分组表头(多级表头)。
3
+ *
4
+ * 背景:schema 里的每个 ArrayTable.Column 被抽成「扁平」列定义(buildArrayTableColumns),
5
+ * 内部一批逻辑(懒挂载列识别、列方案还原、首列拖拽等)都按扁平列取值,不能改。
6
+ * 所以分组只在「交给 AG-Grid 的那一份 columnDefs」上做:
7
+ * 1. buildArrayTableColumns 生成列定义时,用 markHeaderGroup 把列声明的 headerGroup 记下来;
8
+ * 2. index.tsx 把扁平列定义交给 groupColumnDefs,得到含列组的 columnDefs 传给 AgGridReact。
9
+ *
10
+ * 分组名记在模块内的 WeakMap 里,不往 colDef 上塞自定义字段——AG-Grid 会把未知属性当作错误告警。
11
+ *
12
+ * 只支持一级分组;分组名相同但不相邻的列各自成组。
13
+ *
14
+ * @author nokecy
15
+ */
16
+ import type { ColDef, ColGroupDef } from 'ag-grid-community';
17
+ /**
18
+ * 记下列定义所属的表头分组。
19
+ * headerGroup 不是非空字符串(没声明、空串、纯空白)时不做任何事,该列按无分组处理。
20
+ * 返回传入的 colDef 本身,方便链式使用。
21
+ */
22
+ export declare const markHeaderGroup: <T extends object>(colDef: T, headerGroup: unknown) => T;
23
+ /**
24
+ * 把扁平列定义按「相邻且 headerGroup 相同」合并成 AG-Grid 列组。
25
+ *
26
+ * - 相邻同名的列 -> 一个 { headerName, groupId, children } 列组;
27
+ * - 同名但被别的列隔开 -> 各自成组,groupId 各不相同;
28
+ * - 没声明分组的列原样保留(同一个对象);
29
+ * - 一个分组也没有时直接返回传入的数组本身,没用到分组的表格行为零变化。
30
+ *
31
+ * groupId 由分组名派生(同名第 N 次出现追加 _N),同样的输入永远得到同样的 id:
32
+ * columnDefs 因别的原因重建时,AG-Grid 靠 groupId 认出还是那个列组,列组状态不丢。
33
+ *
34
+ * 有意不设 marryChildren:设了以后,任何打破组内相邻的列顺序(用户旧的扁平列方案、
35
+ * 列设置面板里跨组拖动的实时预览)都会被 AG-Grid 整体丢弃并报 error #39;不设则顺序照常生效,
36
+ * 组被隔开时表头显示成多段。
37
+ * openByDefault:列组默认展开(只对配了 columnGroupShow 的可折叠列组有意义)。
38
+ */
39
+ export declare const groupColumnDefs: (colDefs: ColDef[]) => (ColDef | ColGroupDef)[];
@@ -0,0 +1,100 @@
1
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
2
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
3
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
4
+ /**
5
+ * ArrayTable 分组表头(多级表头)。
6
+ *
7
+ * 背景:schema 里的每个 ArrayTable.Column 被抽成「扁平」列定义(buildArrayTableColumns),
8
+ * 内部一批逻辑(懒挂载列识别、列方案还原、首列拖拽等)都按扁平列取值,不能改。
9
+ * 所以分组只在「交给 AG-Grid 的那一份 columnDefs」上做:
10
+ * 1. buildArrayTableColumns 生成列定义时,用 markHeaderGroup 把列声明的 headerGroup 记下来;
11
+ * 2. index.tsx 把扁平列定义交给 groupColumnDefs,得到含列组的 columnDefs 传给 AgGridReact。
12
+ *
13
+ * 分组名记在模块内的 WeakMap 里,不往 colDef 上塞自定义字段——AG-Grid 会把未知属性当作错误告警。
14
+ *
15
+ * 只支持一级分组;分组名相同但不相邻的列各自成组。
16
+ *
17
+ * @author nokecy
18
+ */
19
+
20
+ /** 列定义 -> 它在 schema 里声明的 headerGroup */
21
+ var headerGroupOf = new WeakMap();
22
+
23
+ /** 列组 id 前缀,与列方案里生成的 col_N 区分开 */
24
+ var GROUP_ID_PREFIX = 'arrayTableGroup_';
25
+
26
+ /**
27
+ * 记下列定义所属的表头分组。
28
+ * headerGroup 不是非空字符串(没声明、空串、纯空白)时不做任何事,该列按无分组处理。
29
+ * 返回传入的 colDef 本身,方便链式使用。
30
+ */
31
+ export var markHeaderGroup = function markHeaderGroup(colDef, headerGroup) {
32
+ if (typeof headerGroup === 'string' && headerGroup.trim() !== '') {
33
+ headerGroupOf.set(colDef, headerGroup);
34
+ }
35
+ return colDef;
36
+ };
37
+
38
+ /**
39
+ * 把扁平列定义按「相邻且 headerGroup 相同」合并成 AG-Grid 列组。
40
+ *
41
+ * - 相邻同名的列 -> 一个 { headerName, groupId, children } 列组;
42
+ * - 同名但被别的列隔开 -> 各自成组,groupId 各不相同;
43
+ * - 没声明分组的列原样保留(同一个对象);
44
+ * - 一个分组也没有时直接返回传入的数组本身,没用到分组的表格行为零变化。
45
+ *
46
+ * groupId 由分组名派生(同名第 N 次出现追加 _N),同样的输入永远得到同样的 id:
47
+ * columnDefs 因别的原因重建时,AG-Grid 靠 groupId 认出还是那个列组,列组状态不丢。
48
+ *
49
+ * 有意不设 marryChildren:设了以后,任何打破组内相邻的列顺序(用户旧的扁平列方案、
50
+ * 列设置面板里跨组拖动的实时预览)都会被 AG-Grid 整体丢弃并报 error #39;不设则顺序照常生效,
51
+ * 组被隔开时表头显示成多段。
52
+ * openByDefault:列组默认展开(只对配了 columnGroupShow 的可折叠列组有意义)。
53
+ */
54
+ export var groupColumnDefs = function groupColumnDefs(colDefs) {
55
+ if (!colDefs.some(function (colDef) {
56
+ return headerGroupOf.has(colDef);
57
+ })) return colDefs;
58
+ var usedGroupIds = new Set();
59
+ var makeGroupId = function makeGroupId(name) {
60
+ var id = "".concat(GROUP_ID_PREFIX).concat(name);
61
+ for (var n = 2; usedGroupIds.has(id); n++) {
62
+ id = "".concat(GROUP_ID_PREFIX).concat(name, "_").concat(n);
63
+ }
64
+ usedGroupIds.add(id);
65
+ return id;
66
+ };
67
+ var result = [];
68
+ var current = null;
69
+ var _iterator = _createForOfIteratorHelper(colDefs),
70
+ _step;
71
+ try {
72
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
73
+ var colDef = _step.value;
74
+ var name = headerGroupOf.get(colDef);
75
+ if (name === undefined) {
76
+ current = null;
77
+ result.push(colDef);
78
+ } else if (current && current.name === name) {
79
+ current.group.children.push(colDef);
80
+ } else {
81
+ var group = {
82
+ headerName: name,
83
+ groupId: makeGroupId(name),
84
+ openByDefault: true,
85
+ children: [colDef]
86
+ };
87
+ current = {
88
+ name: name,
89
+ group: group
90
+ };
91
+ result.push(group);
92
+ }
93
+ }
94
+ } catch (err) {
95
+ _iterator.e(err);
96
+ } finally {
97
+ _iterator.f();
98
+ }
99
+ return result;
100
+ };
@@ -18,6 +18,7 @@ import { useFieldSchema } from "@formily/react";
18
18
  import { connect, mapProps, mapReadPretty } from "@formily/react";
19
19
  import uniqueId from "lodash/uniqueId";
20
20
  import { useAddition, buildArrayTableColumns, useArrayTableSources, useArrayTableActions, isColumnComponent } from "./utils";
21
+ import { groupColumnDefs } from "./columnGroup";
21
22
  import { useCellFocus, useKeyboardNavigation, useRowDrag } from "./hooks";
22
23
  import ArrayBase from "./arrayBase";
23
24
  import ArrayAddBtn from "./arrayAddBtn";
@@ -78,14 +79,16 @@ var ArrayTableInner = observer(function (props) {
78
79
  // 通过 JSON.stringify 比较内容,只有内容真正变化时才返回新引用
79
80
  var sourcesKey = useMemo(function () {
80
81
  return JSON.stringify(rawSources.map(function (s) {
81
- var _s$columnProps$header, _s$columnProps, _s$columnProps2;
82
+ var _s$columnProps$header, _s$columnProps, _s$columnProps2, _s$columnProps3;
82
83
  return {
83
84
  name: s.name,
84
85
  display: s.display,
85
86
  // 列标题可由 reactions 运行时改写,纳入 key 才能让 stableColumnDefs 跟着重建。
86
87
  // 宽度/隐藏/固定由 applyColumnState(方案)管,故意不纳入,避免行编辑时列状态被重置。
87
88
  // 可编辑性:带 x-reactions 的列在 buildArrayTableColumns 里已强制走 AgField 全树(尊重运行时 pattern),无需进 key。@author nokecy
88
- headerName: (_s$columnProps$header = (_s$columnProps = s.columnProps) === null || _s$columnProps === void 0 ? void 0 : _s$columnProps.headerName) !== null && _s$columnProps$header !== void 0 ? _s$columnProps$header : (_s$columnProps2 = s.columnProps) === null || _s$columnProps2 === void 0 ? void 0 : _s$columnProps2.title
89
+ headerName: (_s$columnProps$header = (_s$columnProps = s.columnProps) === null || _s$columnProps === void 0 ? void 0 : _s$columnProps.headerName) !== null && _s$columnProps$header !== void 0 ? _s$columnProps$header : (_s$columnProps2 = s.columnProps) === null || _s$columnProps2 === void 0 ? void 0 : _s$columnProps2.title,
90
+ // 分组名变了列组结构就变,同样要重建。@author nokecy
91
+ headerGroup: (_s$columnProps3 = s.columnProps) === null || _s$columnProps3 === void 0 ? void 0 : _s$columnProps3.headerGroup
89
92
  };
90
93
  }));
91
94
  }, [rawSources]);
@@ -146,6 +149,12 @@ var ArrayTableInner = observer(function (props) {
146
149
  return cols;
147
150
  }, [sources, props.onRowDrag]); // 移除 field 依赖,避免数据变化时重新计算
148
151
 
152
+ // 交给 AgGridReact 的列定义:按 x-component-props.headerGroup 把相邻同组的列合并成列组(多级表头)。
153
+ // stableColumnDefs 保持扁平,懒列识别、列方案还原等内部逻辑仍用它;只有喂给 AG-Grid 的这一份带分组。@author nokecy
154
+ var gridColumnDefs = useMemo(function () {
155
+ return groupColumnDefs(stableColumnDefs);
156
+ }, [stableColumnDefs]);
157
+
149
158
  // 懒挂载:把激活态 Set 通过 AG-Grid context 暴露给 LazyAgField(引用稳定,原地 mutate)。@author nokecy
150
159
  var gridContext = useMemo(function () {
151
160
  return {
@@ -222,8 +231,8 @@ var ArrayTableInner = observer(function (props) {
222
231
  if (hasGroups) {
223
232
  // 传入 stableColumnDefs 作为原始定义,保留 cellRenderer(AgField/LazyAgField)及其
224
233
  // cellRendererParams——否则分组方案重建出的是裸列,单元格退化为纯文本、编辑失效。@author nokecy
225
- var gridColumnDefs = flatConfigToGridState(currentScheme.columnConfig, stableColumnDefs);
226
- gridApiState.setGridOption('columnDefs', gridColumnDefs);
234
+ var _gridColumnDefs = flatConfigToGridState(currentScheme.columnConfig, stableColumnDefs);
235
+ gridApiState.setGridOption('columnDefs', _gridColumnDefs);
227
236
  }
228
237
 
229
238
  // 2. 应用列状态(列顺序、宽度、隐藏、固定等)
@@ -416,7 +425,7 @@ var ArrayTableInner = observer(function (props) {
416
425
  ,
417
426
  rowHeight: 38,
418
427
  pagination: false,
419
- columnDefs: stableColumnDefs,
428
+ columnDefs: gridColumnDefs,
420
429
  rowData: dataSource
421
430
  })), sources.map(function (column, key) {
422
431
  //专门用来承接对Column的状态管理
@@ -3,9 +3,28 @@ import { FieldDisplayTypes, GeneralField } from "@formily/core";
3
3
  import { Schema } from "@formily/json-schema";
4
4
  import { AgGridReactProps } from "ag-grid-react";
5
5
  import React from "react";
6
+ /**
7
+ * ArrayTable.Column 的 x-component-props 里 qc-ui 自己认的扩展属性;
8
+ * 其余属性(width、headerName、pinned 等)按 AG-Grid 列定义处理。
9
+ *
10
+ * @author nokecy
11
+ */
12
+ interface ArrayTableColumnProps {
13
+ /**
14
+ * 表头分组名(多级表头,仅一级)。
15
+ * 相邻且 headerGroup 相同的列合并成一个列组,分组名作为组头;
16
+ * 同名但不相邻的列各自成组;不写则该列不分组。
17
+ */
18
+ headerGroup?: string;
19
+ /**
20
+ * 默认隐藏:为 true 时该列首次出现时是隐藏的,用户可在列设置里打开,列方案(applyColumnState)优先。
21
+ * 对应 AG-Grid 的 initialHide。注意 hide 在 ArrayTable 里不生效(状态归列方案管),要默认隐藏请用它。
22
+ */
23
+ defaultHide?: boolean;
24
+ }
6
25
  interface ObservableColumnSource {
7
26
  field: GeneralField;
8
- columnProps: any;
27
+ columnProps: ArrayTableColumnProps & Record<string, any>;
9
28
  schema: Schema;
10
29
  display: FieldDisplayTypes;
11
30
  name: string;
@@ -13,4 +32,4 @@ interface ObservableColumnSource {
13
32
  type ComposedArrayTable = React.FC<React.PropsWithChildren<AgGridReactProps>> & ArrayBaseMixins & {
14
33
  Column?: any;
15
34
  };
16
- export { ComposedArrayTable, ObservableColumnSource };
35
+ export { ComposedArrayTable, ObservableColumnSource, ArrayTableColumnProps };