@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.
- package/dist/cjs/array-table/columnGroup.d.ts +39 -0
- package/dist/cjs/array-table/columnGroup.js +106 -0
- package/dist/cjs/array-table/index.js +14 -5
- package/dist/cjs/array-table/interface.d.ts +21 -2
- package/dist/cjs/array-table/utils.js +21 -8
- package/dist/esm/array-table/columnGroup.d.ts +39 -0
- package/dist/esm/array-table/columnGroup.js +100 -0
- package/dist/esm/array-table/index.js +14 -5
- package/dist/esm/array-table/interface.d.ts +21 -2
- package/dist/esm/array-table/utils.js +21 -8
- package/dist/umd/qc-ui.min.js +1 -1
- package/package.json +1 -1
|
@@ -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
|
|
230
|
-
gridApiState.setGridOption('columnDefs',
|
|
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:
|
|
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
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
226
|
-
gridApiState.setGridOption('columnDefs',
|
|
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:
|
|
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 };
|