@nokecy/qc-ui 1.1.81 → 1.1.83
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/index.js +9 -0
- package/dist/cjs/array-table/readOnlyFormatters.d.ts +5 -0
- package/dist/cjs/array-table/readOnlyFormatters.js +57 -13
- package/dist/cjs/array-table/utils.d.ts +17 -0
- package/dist/cjs/array-table/utils.js +100 -10
- package/dist/cjs/array-table-index/index.js +5 -3
- package/dist/esm/array-table/index.js +10 -1
- package/dist/esm/array-table/readOnlyFormatters.d.ts +5 -0
- package/dist/esm/array-table/readOnlyFormatters.js +57 -13
- package/dist/esm/array-table/utils.d.ts +17 -0
- package/dist/esm/array-table/utils.js +101 -10
- package/dist/esm/array-table-index/index.js +5 -3
- package/dist/umd/qc-ui.min.js +1 -1
- package/package.json +1 -1
|
@@ -150,6 +150,15 @@ var ArrayTableInner = (0, _react2.observer)(function (props) {
|
|
|
150
150
|
return cols;
|
|
151
151
|
}, [sources, props.onRowDrag]); // 移除 field 依赖,避免数据变化时重新计算
|
|
152
152
|
|
|
153
|
+
// 懒挂载的格子不创建 Formily 字段,schema 的 default 不会自己写进值:行出现时补一次(每行只补一次)。@author nokecy
|
|
154
|
+
var lazyDefaults = (0, _react.useMemo)(function () {
|
|
155
|
+
return (0, _utils.collectLazyDefaults)(stableColumnDefs);
|
|
156
|
+
}, [stableColumnDefs]);
|
|
157
|
+
var defaultedRowsRef = (0, _react.useRef)(new WeakSet());
|
|
158
|
+
(0, _react.useEffect)(function () {
|
|
159
|
+
if (lazyDefaults.length > 0) (0, _utils.applyLazyDefaults)(field, lazyDefaults, defaultedRowsRef.current);
|
|
160
|
+
});
|
|
161
|
+
|
|
153
162
|
// 交给 AgGridReact 的列定义:按 x-component-props.headerGroup 把相邻同组的列合并成列组(多级表头)。
|
|
154
163
|
// stableColumnDefs 保持扁平,懒列识别、列方案还原等内部逻辑仍用它;只有喂给 AG-Grid 的这一份带分组。@author nokecy
|
|
155
164
|
var gridColumnDefs = (0, _react.useMemo)(function () {
|
|
@@ -4,6 +4,11 @@ export type ReadOnlyFormatterCtx = {
|
|
|
4
4
|
columnProps: any;
|
|
5
5
|
/** 内层数据字段的 schema(可读 enum / x-component-props) */
|
|
6
6
|
fieldSchema: any;
|
|
7
|
+
/**
|
|
8
|
+
* 运行时才确定的选项(field.setDataSource / setFieldState 写入的 dataSource)。
|
|
9
|
+
* 懒挂载格子没有自己的 Formily 字段时,由调用方取同列已创建字段的选项带进来;有值时优先于 schema 静态选项。
|
|
10
|
+
*/
|
|
11
|
+
dataSource?: any[];
|
|
7
12
|
};
|
|
8
13
|
export type ReadOnlyFormatter = (value: any, ctx: ReadOnlyFormatterCtx) => string;
|
|
9
14
|
/**
|
|
@@ -32,6 +32,7 @@ var resolveOptions = function resolveOptions(ctx) {
|
|
|
32
32
|
var _ref, _ref2, _ref3, _fieldSchema$enum, _fieldSchema$xCompon, _fieldSchema$xCompon2;
|
|
33
33
|
var columnProps = ctx.columnProps,
|
|
34
34
|
fieldSchema = ctx.fieldSchema;
|
|
35
|
+
if (Array.isArray(ctx.dataSource) && ctx.dataSource.length > 0) return ctx.dataSource;
|
|
35
36
|
var candidate = (_ref = (_ref2 = (_ref3 = (_fieldSchema$enum = fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.enum) !== null && _fieldSchema$enum !== void 0 ? _fieldSchema$enum : fieldSchema === null || fieldSchema === void 0 || (_fieldSchema$xCompon = fieldSchema['x-component-props']) === null || _fieldSchema$xCompon === void 0 ? void 0 : _fieldSchema$xCompon.options) !== null && _ref3 !== void 0 ? _ref3 : fieldSchema === null || fieldSchema === void 0 || (_fieldSchema$xCompon2 = fieldSchema['x-component-props']) === null || _fieldSchema$xCompon2 === void 0 ? void 0 : _fieldSchema$xCompon2.dataSource) !== null && _ref2 !== void 0 ? _ref2 : columnProps === null || columnProps === void 0 ? void 0 : columnProps.options) !== null && _ref !== void 0 ? _ref : columnProps === null || columnProps === void 0 ? void 0 : columnProps.dataSource;
|
|
36
37
|
return Array.isArray(candidate) ? candidate : [];
|
|
37
38
|
};
|
|
@@ -64,20 +65,63 @@ var selectFormatter = function selectFormatter(value, ctx) {
|
|
|
64
65
|
}
|
|
65
66
|
return mapOptionLabel(value, options);
|
|
66
67
|
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 日期/时间控件没写 format 时的默认显示格式,与 antd 控件自己的默认一致:
|
|
71
|
+
* TimePicker 只显示时间;showTime 带到秒;按月/按年选择器只显示到月/年。
|
|
72
|
+
* 文本态与点开后的控件看到同一个格式,不然 showTime 的列平时只见日期、点开才见时间。
|
|
73
|
+
*/
|
|
74
|
+
var defaultDateFormat = function defaultDateFormat(component, props) {
|
|
75
|
+
if (component === 'TimePicker') return props !== null && props !== void 0 && props.use12Hours ? 'hh:mm:ss a' : 'HH:mm:ss';
|
|
76
|
+
if ((props === null || props === void 0 ? void 0 : props.picker) === 'month') return 'YYYY-MM';
|
|
77
|
+
if ((props === null || props === void 0 ? void 0 : props.picker) === 'year') return 'YYYY';
|
|
78
|
+
if (props !== null && props !== void 0 && props.showTime) return 'YYYY-MM-DD HH:mm:ss';
|
|
79
|
+
return 'YYYY-MM-DD';
|
|
80
|
+
};
|
|
67
81
|
var dateFormatter = function dateFormatter(value, ctx) {
|
|
68
|
-
var
|
|
82
|
+
var _ctx$fieldSchema, _ctx$columnProps, _ctx$fieldSchema2;
|
|
69
83
|
if (value == null || value === '') return '';
|
|
70
|
-
var
|
|
84
|
+
var props = (_ctx$fieldSchema = ctx.fieldSchema) === null || _ctx$fieldSchema === void 0 ? void 0 : _ctx$fieldSchema['x-component-props'];
|
|
85
|
+
// antd 的 format 还可以是数组/函数,文本态只认字符串,其余回到默认
|
|
86
|
+
var configured = [(_ctx$columnProps = ctx.columnProps) === null || _ctx$columnProps === void 0 ? void 0 : _ctx$columnProps.format, props === null || props === void 0 ? void 0 : props.format].find(function (f) {
|
|
87
|
+
return typeof f === 'string' && f;
|
|
88
|
+
});
|
|
89
|
+
var fmt = configured !== null && configured !== void 0 ? configured : defaultDateFormat((_ctx$fieldSchema2 = ctx.fieldSchema) === null || _ctx$fieldSchema2 === void 0 ? void 0 : _ctx$fieldSchema2['x-component'], props);
|
|
71
90
|
if (typeof value.format === 'function') return value.format(fmt);
|
|
72
91
|
// 后端回来的多是 ISO 串(2024-10-19T00:00:00)或时间戳:与 Formily readPretty 一致,按 dayjs(value).format(fmt) 显示;
|
|
73
|
-
// 解析不了的文本(
|
|
92
|
+
// 解析不了的文本(如「待定」、纯时间 08:30:00)原样显示,不吞掉。dayjs 随 antd 传递依赖引入,本库其他模块已直接使用。
|
|
74
93
|
var parsed = (0, _dayjs.default)(value);
|
|
75
94
|
return parsed.isValid() ? parsed.format(fmt) : String(value);
|
|
76
95
|
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 数字格:按控件的 precision 补齐小数位、按 formatter 属性(千分位、百分号等)显示,
|
|
99
|
+
* 与点开后的 InputNumber 一致;没配这两项时与原样输出相同。
|
|
100
|
+
*/
|
|
101
|
+
var numberFormatter = function numberFormatter(value, ctx) {
|
|
102
|
+
var _ctx$fieldSchema$xCo, _ctx$fieldSchema3, _ctx$columnProps$prec, _ctx$columnProps2, _ctx$columnProps$form, _ctx$columnProps3;
|
|
103
|
+
if (value == null || value === '') return '';
|
|
104
|
+
var props = (_ctx$fieldSchema$xCo = (_ctx$fieldSchema3 = ctx.fieldSchema) === null || _ctx$fieldSchema3 === void 0 ? void 0 : _ctx$fieldSchema3['x-component-props']) !== null && _ctx$fieldSchema$xCo !== void 0 ? _ctx$fieldSchema$xCo : {};
|
|
105
|
+
var precision = (_ctx$columnProps$prec = (_ctx$columnProps2 = ctx.columnProps) === null || _ctx$columnProps2 === void 0 ? void 0 : _ctx$columnProps2.precision) !== null && _ctx$columnProps$prec !== void 0 ? _ctx$columnProps$prec : props.precision;
|
|
106
|
+
var num = Number(value);
|
|
107
|
+
var base = typeof precision === 'number' && precision >= 0 && Number.isFinite(num) ? num.toFixed(precision) : String(value);
|
|
108
|
+
var formatter = (_ctx$columnProps$form = (_ctx$columnProps3 = ctx.columnProps) === null || _ctx$columnProps3 === void 0 ? void 0 : _ctx$columnProps3.formatter) !== null && _ctx$columnProps$form !== void 0 ? _ctx$columnProps$form : props.formatter;
|
|
109
|
+
if (typeof formatter === 'function') {
|
|
110
|
+
try {
|
|
111
|
+
return String(formatter(base, {
|
|
112
|
+
userTyping: false,
|
|
113
|
+
input: ''
|
|
114
|
+
}));
|
|
115
|
+
} catch (_unused) {
|
|
116
|
+
return base;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return base;
|
|
120
|
+
};
|
|
77
121
|
var booleanFormatter = function booleanFormatter(value, ctx) {
|
|
78
|
-
var _ctx$fieldSchema$
|
|
122
|
+
var _ctx$fieldSchema$xCo2, _ctx$fieldSchema4, _props$checkedChildre, _props$unCheckedChild;
|
|
79
123
|
if (value == null || value === '') return '';
|
|
80
|
-
var props = (_ctx$fieldSchema$
|
|
124
|
+
var props = (_ctx$fieldSchema$xCo2 = (_ctx$fieldSchema4 = ctx.fieldSchema) === null || _ctx$fieldSchema4 === void 0 ? void 0 : _ctx$fieldSchema4['x-component-props']) !== null && _ctx$fieldSchema$xCo2 !== void 0 ? _ctx$fieldSchema$xCo2 : {};
|
|
81
125
|
var truthy = (_props$checkedChildre = props.checkedChildren) !== null && _props$checkedChildre !== void 0 ? _props$checkedChildre : '是';
|
|
82
126
|
var falsy = (_props$unCheckedChild = props.unCheckedChildren) !== null && _props$unCheckedChild !== void 0 ? _props$unCheckedChild : '否';
|
|
83
127
|
return value ? String(truthy) : String(falsy);
|
|
@@ -93,8 +137,8 @@ var registry = {
|
|
|
93
137
|
Password: textFormatter,
|
|
94
138
|
Text: textFormatter,
|
|
95
139
|
Preview: textFormatter,
|
|
96
|
-
NumberPicker:
|
|
97
|
-
InputNumber:
|
|
140
|
+
NumberPicker: numberFormatter,
|
|
141
|
+
InputNumber: numberFormatter,
|
|
98
142
|
Select: selectFormatter,
|
|
99
143
|
TreeSelect: selectFormatter,
|
|
100
144
|
Cascader: selectFormatter,
|
|
@@ -152,17 +196,17 @@ var registerReadOnlyLabels = exports.registerReadOnlyLabels = function registerR
|
|
|
152
196
|
if (o && o.value != null) map.set(String(o.value), String((_o$label = o.label) !== null && _o$label !== void 0 ? _o$label : o.value));
|
|
153
197
|
});
|
|
154
198
|
} else {
|
|
155
|
-
Object.entries(labels !== null && labels !== void 0 ? labels : {}).forEach(function (
|
|
156
|
-
var
|
|
157
|
-
k =
|
|
158
|
-
v =
|
|
199
|
+
Object.entries(labels !== null && labels !== void 0 ? labels : {}).forEach(function (_ref6) {
|
|
200
|
+
var _ref7 = _slicedToArray(_ref6, 2),
|
|
201
|
+
k = _ref7[0],
|
|
202
|
+
v = _ref7[1];
|
|
159
203
|
return map.set(String(k), String(v));
|
|
160
204
|
});
|
|
161
205
|
}
|
|
162
206
|
var toText = function toText(v) {
|
|
163
|
-
var
|
|
207
|
+
var _ref8, _v$label, _map$get;
|
|
164
208
|
if (v == null || v === '') return '';
|
|
165
|
-
if (_typeof(v) === 'object') return String((
|
|
209
|
+
if (_typeof(v) === 'object') return String((_ref8 = (_v$label = v.label) !== null && _v$label !== void 0 ? _v$label : v.value) !== null && _ref8 !== void 0 ? _ref8 : '');
|
|
166
210
|
return (_map$get = map.get(String(v))) !== null && _map$get !== void 0 ? _map$get : String(v);
|
|
167
211
|
};
|
|
168
212
|
var formatter = function formatter(value) {
|
|
@@ -41,3 +41,20 @@ declare const LazyReadOnlyText: (params: any) => React.JSX.Element;
|
|
|
41
41
|
declare const buildArrayTableColumns: (dataSource: any[], field: ArrayField, sources: ObservableColumnSource[]) => AgGridReactProps['columnDefs'];
|
|
42
42
|
declare const useAddition: () => React.JSX.Element | null;
|
|
43
43
|
export { isColumnComponent, useArrayTableSources, useArrayTableActions, buildArrayTableColumns, useAddition, LazyAgField, LazyReadOnlyText };
|
|
44
|
+
export type LazyColumnDefault = {
|
|
45
|
+
key: string;
|
|
46
|
+
value: any;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* 收集懒挂载列上声明了 default 的字段。
|
|
50
|
+
*
|
|
51
|
+
* Formily 在字段创建时把 schema 的 default 写进值(值为空时)。懒挂载的格子不创建字段,
|
|
52
|
+
* 老记录里缺的列、代码直接 push 的行就拿不到默认值,保存时是 null。
|
|
53
|
+
* 表达式形态的默认值({{...}})要求值上下文,这里不处理。@author nokecy
|
|
54
|
+
*/
|
|
55
|
+
export declare const collectLazyDefaults: (columns: any[]) => LazyColumnDefault[];
|
|
56
|
+
/**
|
|
57
|
+
* 给还没处理过的新增行补默认值:值为空(null/undefined)才写,每行只补一次——
|
|
58
|
+
* 用户之后把格子清空是有意的,不能再被填回去。已落库的行(带 id)不动。@author nokecy
|
|
59
|
+
*/
|
|
60
|
+
export declare const applyLazyDefaults: (arrayField: any, defaults: LazyColumnDefault[], handled: WeakSet<object>) => void;
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.useArrayTableSources = exports.useArrayTableActions = exports.useAddition = exports.isColumnComponent = exports.buildArrayTableColumns = exports.LazyReadOnlyText = exports.LazyAgField = void 0;
|
|
6
|
+
exports.useArrayTableSources = exports.useArrayTableActions = exports.useAddition = exports.isColumnComponent = exports.collectLazyDefaults = exports.buildArrayTableColumns = exports.applyLazyDefaults = exports.LazyReadOnlyText = exports.LazyAgField = void 0;
|
|
7
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
8
|
var _antd = require("antd");
|
|
9
9
|
var _react2 = require("@formily/react");
|
|
10
|
+
var _reactive = require("@formily/reactive");
|
|
10
11
|
var _shared = require("@formily/shared");
|
|
11
12
|
var _jsonSchema = require("@formily/json-schema");
|
|
12
13
|
var _arrayBase = _interopRequireDefault(require("./arrayBase"));
|
|
@@ -306,6 +307,20 @@ var hasRequiredRule = function hasRequiredRule(rule) {
|
|
|
306
307
|
return false;
|
|
307
308
|
};
|
|
308
309
|
|
|
310
|
+
/**
|
|
311
|
+
* 数据字段是否挂了任何校验规则。
|
|
312
|
+
*
|
|
313
|
+
* 懒挂载的格子没有 Formily 字段,提交时 form.validate 碰不到它。必填规则能静态识别,
|
|
314
|
+
* 但「自定义 validator 函数里判空」「必填写在校验规则的其他形态里」识别不了——
|
|
315
|
+
* 这类列的空格子若不挂真控件,空值会绕过校验直接提交。故有校验规则的列,空格子按必填一样挂真控件。
|
|
316
|
+
* 有值的格子里不合格式的内容不在此列(要挂全部校验过的格子等于取消懒挂载)。@author nokecy
|
|
317
|
+
*/
|
|
318
|
+
var hasValidatorRule = function hasValidatorRule(fieldSchema) {
|
|
319
|
+
var validator = fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema['x-validator'];
|
|
320
|
+
if (validator == null || validator === '') return false;
|
|
321
|
+
return Array.isArray(validator) ? validator.length > 0 : true;
|
|
322
|
+
};
|
|
323
|
+
|
|
309
324
|
/**
|
|
310
325
|
* 数据字段是否必填(静态判定):字段上写了 required,或 x-validator 里带 required 规则。
|
|
311
326
|
*
|
|
@@ -420,6 +435,28 @@ var LazyAgField = exports.LazyAgField = function LazyAgField(params) {
|
|
|
420
435
|
};
|
|
421
436
|
}();
|
|
422
437
|
|
|
438
|
+
/**
|
|
439
|
+
* 运行时设置的选项(field.setDataSource / setFieldState dataSource)。
|
|
440
|
+
*
|
|
441
|
+
* 只取本格自己的字段:点开过的格子字段还在,失焦卸回文本后仍按名称显示。
|
|
442
|
+
* 不借同列其他格的选项——选项常常按行不同(如标签类型跟随同行的打印功能),借来的选项会把值映射成别的名称,
|
|
443
|
+
* 比显示原编码更糟。从未点开过的格子没有字段,要显示名称请把选项写进 Schema(x-component-props.options)。
|
|
444
|
+
* 仅选项类组件且有值时才查;按精确地址取、放在 untracked 里,不让每个格子都订阅整张字段表。@author nokecy
|
|
445
|
+
*/
|
|
446
|
+
var liveDataSource = function liveDataSource(liveValue) {
|
|
447
|
+
var _field$value$indexOf4, _field$value4, _field$value4$indexOf;
|
|
448
|
+
var form = field === null || field === void 0 ? void 0 : field.form;
|
|
449
|
+
// 只有用「选项映射」格式化器的列(Select 一族,或登记为同一格式化器的组件)才需要运行时选项
|
|
450
|
+
if (!form || !dataKey || isBlank(liveValue) || formatter !== (0, _readOnlyFormatters.getReadOnlyFormatter)('Select')) return undefined;
|
|
451
|
+
var index = (_field$value$indexOf4 = field === null || field === void 0 || (_field$value4 = field.value) === null || _field$value4 === void 0 || (_field$value4$indexOf = _field$value4.indexOf) === null || _field$value4$indexOf === void 0 ? void 0 : _field$value4$indexOf.call(_field$value4, record)) !== null && _field$value$indexOf4 !== void 0 ? _field$value$indexOf4 : -1;
|
|
452
|
+
if (index < 0) return undefined;
|
|
453
|
+
var own = (0, _reactive.untracked)(function () {
|
|
454
|
+
return form.query(field.path.concat(index).concat(dataKey)).take();
|
|
455
|
+
});
|
|
456
|
+
var source = own === null || own === void 0 ? void 0 : own.dataSource;
|
|
457
|
+
return Array.isArray(source) && source.length > 0 ? source : undefined;
|
|
458
|
+
};
|
|
459
|
+
|
|
423
460
|
// Observer 让本格反应式跟随内层 Formily 字段值。
|
|
424
461
|
// record 即 field.value[index] 的可观察对象;在 Observer 里按内层字段名直接读 record[dataKey]
|
|
425
462
|
// (而非 AG-Grid 渲染时快照的 params.value)建立依赖后,onFieldValueChange/setValuesIn 程序化原地
|
|
@@ -452,10 +489,12 @@ var LazyAgField = exports.LazyAgField = function LazyAgField(params) {
|
|
|
452
489
|
node: node
|
|
453
490
|
}));
|
|
454
491
|
}
|
|
455
|
-
var
|
|
492
|
+
var ctx = {
|
|
456
493
|
columnProps: columnProps,
|
|
457
|
-
fieldSchema: fieldSchema
|
|
458
|
-
|
|
494
|
+
fieldSchema: fieldSchema,
|
|
495
|
+
dataSource: activated ? undefined : liveDataSource(liveValue)
|
|
496
|
+
};
|
|
497
|
+
var text = formatter ? formatter(liveValue, ctx) : liveValue == null ? '' : String(liveValue);
|
|
459
498
|
// 纯文本占满单元格,点击交给 AG-Grid onCellClicked 激活;样式尽量贴近 Editable 只读态避免点开跳动
|
|
460
499
|
// 只读态(readPretty/disabled/readOnly)的空格不出编辑提示,留空与只读快路径一致
|
|
461
500
|
var pattern = text === '' ? resolveLazyCellPattern(field, record, dataKey, fieldSchema, scope) : undefined;
|
|
@@ -472,10 +511,7 @@ var LazyAgField = exports.LazyAgField = function LazyAgField(params) {
|
|
|
472
511
|
}, resolveEmptyPlaceholder(fieldSchema));
|
|
473
512
|
}
|
|
474
513
|
// 登记了只读渲染器的组件(如带颜色的 Tag)按渲染器出内容,与组件自己的阅读态一致
|
|
475
|
-
var shown = renderer && text !== '' ? renderer(liveValue,
|
|
476
|
-
columnProps: columnProps,
|
|
477
|
-
fieldSchema: fieldSchema
|
|
478
|
-
}) : text;
|
|
514
|
+
var shown = renderer && text !== '' ? renderer(liveValue, ctx) : text;
|
|
479
515
|
return /*#__PURE__*/_react.default.createElement("span", {
|
|
480
516
|
className: "ag-array-table-lazy-text",
|
|
481
517
|
style: {
|
|
@@ -653,6 +689,9 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
|
|
|
653
689
|
// 懒挂载会把它降成「是/否」纯文本(点击才挂出开关),用户会以为开关消失。故可编辑态强制 eager。
|
|
654
690
|
// 只读态(下方 ① 路径)仍走「是/否」文本快路径不受影响。@author nokecy
|
|
655
691
|
var isInlineToggle = component === 'Switch' || component === 'Checkbox';
|
|
692
|
+
// ArrayTableIndex 靠「挂载时 useEffect 调 onChange(index+1)」把行号写进数据字段(如工艺路线的 sort)。
|
|
693
|
+
// 懒挂载只出文本、不挂真组件,effect 永远不执行,新增行的行号字段就是空的,故强制 eager。@author nokecy
|
|
694
|
+
var isIndexWriter = component === 'ArrayTableIndex';
|
|
656
695
|
|
|
657
696
|
// formatter 路径(只读快路径/懒挂载)经 AG-Grid params.value 取值,而 params.value 由 colDef.field(=name)驱动。
|
|
658
697
|
// 但设计器生成的 schema 里 Column key 多为随机 designable-id 且无 dataIndex,真实数据键在内层字段 name 上,
|
|
@@ -719,7 +758,7 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
|
|
|
719
758
|
}
|
|
720
759
|
|
|
721
760
|
// ② 可编辑懒挂载(排除单击直控的 Switch/Checkbox:须 eager 出真控件)
|
|
722
|
-
if (!readOnly && formatter && !hasReactions && !forceEager && !isInlineToggle && canFastPath) {
|
|
761
|
+
if (!readOnly && formatter && !hasReactions && !forceEager && !isInlineToggle && !isIndexWriter && canFastPath) {
|
|
723
762
|
return emit(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
|
|
724
763
|
valueGetter: valueGetter
|
|
725
764
|
} : {}), {}, {
|
|
@@ -734,7 +773,8 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
|
|
|
734
773
|
fieldSchema: dataField,
|
|
735
774
|
lazyEditable: true,
|
|
736
775
|
// 供 index.tsx 识别懒列(激活/导航用)
|
|
737
|
-
|
|
776
|
+
// 必填、或带校验规则且为空的格必须挂真控件,否则没有字段节点,提交时没人校验它,见 LazyAgField
|
|
777
|
+
required: isRequiredSchema(dataField) || hasValidatorRule(dataField)
|
|
738
778
|
}
|
|
739
779
|
}));
|
|
740
780
|
}
|
|
@@ -761,4 +801,54 @@ var useAddition = exports.useAddition = function useAddition() {
|
|
|
761
801
|
}
|
|
762
802
|
return addition;
|
|
763
803
|
}, null);
|
|
804
|
+
};
|
|
805
|
+
/** 简单字段名(非路径、非解构),默认值回填只处理这一种 */
|
|
806
|
+
var SIMPLE_FIELD_NAME = /^[A-Za-z_$][\w$]*$/;
|
|
807
|
+
/**
|
|
808
|
+
* 收集懒挂载列上声明了 default 的字段。
|
|
809
|
+
*
|
|
810
|
+
* Formily 在字段创建时把 schema 的 default 写进值(值为空时)。懒挂载的格子不创建字段,
|
|
811
|
+
* 老记录里缺的列、代码直接 push 的行就拿不到默认值,保存时是 null。
|
|
812
|
+
* 表达式形态的默认值({{...}})要求值上下文,这里不处理。@author nokecy
|
|
813
|
+
*/
|
|
814
|
+
var collectLazyDefaults = exports.collectLazyDefaults = function collectLazyDefaults(columns) {
|
|
815
|
+
return (columns !== null && columns !== void 0 ? columns : []).filter(function (col) {
|
|
816
|
+
var _col$cellRendererPara;
|
|
817
|
+
return col === null || col === void 0 || (_col$cellRendererPara = col.cellRendererParams) === null || _col$cellRendererPara === void 0 ? void 0 : _col$cellRendererPara.lazyEditable;
|
|
818
|
+
}).map(function (col) {
|
|
819
|
+
var _fieldSchema$name3;
|
|
820
|
+
var fieldSchema = col.cellRendererParams.fieldSchema;
|
|
821
|
+
return {
|
|
822
|
+
key: String((_fieldSchema$name3 = fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.name) !== null && _fieldSchema$name3 !== void 0 ? _fieldSchema$name3 : col.field),
|
|
823
|
+
value: fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.default
|
|
824
|
+
};
|
|
825
|
+
}).filter(function (_ref7) {
|
|
826
|
+
var key = _ref7.key,
|
|
827
|
+
value = _ref7.value;
|
|
828
|
+
return SIMPLE_FIELD_NAME.test(key) && value !== undefined && value !== null && !(typeof value === 'string' && value.includes('{{'));
|
|
829
|
+
});
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* 给还没处理过的新增行补默认值:值为空(null/undefined)才写,每行只补一次——
|
|
834
|
+
* 用户之后把格子清空是有意的,不能再被填回去。已落库的行(带 id)不动。@author nokecy
|
|
835
|
+
*/
|
|
836
|
+
var applyLazyDefaults = exports.applyLazyDefaults = function applyLazyDefaults(arrayField, defaults, handled) {
|
|
837
|
+
var rows = arrayField === null || arrayField === void 0 ? void 0 : arrayField.value;
|
|
838
|
+
var form = arrayField === null || arrayField === void 0 ? void 0 : arrayField.form;
|
|
839
|
+
if (!Array.isArray(rows) || !form || defaults.length === 0) return;
|
|
840
|
+
rows.forEach(function (row, index) {
|
|
841
|
+
if (row == null || _typeof(row) !== 'object' || handled.has(row)) return;
|
|
842
|
+
handled.add(row);
|
|
843
|
+
// 已落库的行(带 id)保持库里的样子:补默认值会让受控字段凭空出现「变更」,
|
|
844
|
+
// 已审批的数据保存时还会被要求填变更原因。只补新增行(按钮之外的途径推进来的行)。
|
|
845
|
+
if (row.id != null || row._id != null) return;
|
|
846
|
+
defaults.forEach(function (_ref8) {
|
|
847
|
+
var key = _ref8.key,
|
|
848
|
+
value = _ref8.value;
|
|
849
|
+
if (row[key] == null) {
|
|
850
|
+
form.setValuesIn(arrayField.path.concat(index).concat(key), _typeof(value) === 'object' ? JSON.parse(JSON.stringify(value)) : value);
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
});
|
|
764
854
|
};
|
|
@@ -10,10 +10,12 @@ var _arrayBase = require("../array-table/arrayBase");
|
|
|
10
10
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
11
11
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
12
12
|
var _default = exports.default = function _default(props) {
|
|
13
|
-
var onChange = props.onChange
|
|
13
|
+
var onChange = props.onChange,
|
|
14
|
+
value = props.value;
|
|
14
15
|
var index = _arrayBase.ArrayBase.useIndex();
|
|
15
16
|
(0, _react.useEffect)(function () {
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
// 行号变了、或字段值被外部覆盖/清空(如 setValues、重置)而不等于行号时,重新写入
|
|
18
|
+
if (value !== index + 1) onChange(index + 1);
|
|
19
|
+
}, [index, value]);
|
|
18
20
|
return /*#__PURE__*/_react.default.createElement("span", props, "#", index + 1, ".");
|
|
19
21
|
};
|
|
@@ -17,7 +17,7 @@ import { useField, observer, RecursionField } from "@formily/react";
|
|
|
17
17
|
import { useFieldSchema } from "@formily/react";
|
|
18
18
|
import { connect, mapProps, mapReadPretty } from "@formily/react";
|
|
19
19
|
import uniqueId from "lodash/uniqueId";
|
|
20
|
-
import { useAddition, buildArrayTableColumns, useArrayTableSources, useArrayTableActions, isColumnComponent } from "./utils";
|
|
20
|
+
import { useAddition, buildArrayTableColumns, useArrayTableSources, useArrayTableActions, isColumnComponent, collectLazyDefaults, applyLazyDefaults } from "./utils";
|
|
21
21
|
import { groupColumnDefs } from "./columnGroup";
|
|
22
22
|
import { ARRAY_TABLE_INDEX_FIELD, hasOwnIndexColumn, makeIndexColumn } from "./indexColumn";
|
|
23
23
|
import { useCellFocus, useKeyboardNavigation, useRowDrag, suppressNativeInputKeys } from "./hooks";
|
|
@@ -146,6 +146,15 @@ var ArrayTableInner = observer(function (props) {
|
|
|
146
146
|
return cols;
|
|
147
147
|
}, [sources, props.onRowDrag]); // 移除 field 依赖,避免数据变化时重新计算
|
|
148
148
|
|
|
149
|
+
// 懒挂载的格子不创建 Formily 字段,schema 的 default 不会自己写进值:行出现时补一次(每行只补一次)。@author nokecy
|
|
150
|
+
var lazyDefaults = useMemo(function () {
|
|
151
|
+
return collectLazyDefaults(stableColumnDefs);
|
|
152
|
+
}, [stableColumnDefs]);
|
|
153
|
+
var defaultedRowsRef = useRef(new WeakSet());
|
|
154
|
+
useEffect(function () {
|
|
155
|
+
if (lazyDefaults.length > 0) applyLazyDefaults(field, lazyDefaults, defaultedRowsRef.current);
|
|
156
|
+
});
|
|
157
|
+
|
|
149
158
|
// 交给 AgGridReact 的列定义:按 x-component-props.headerGroup 把相邻同组的列合并成列组(多级表头)。
|
|
150
159
|
// stableColumnDefs 保持扁平,懒列识别、列方案还原等内部逻辑仍用它;只有喂给 AG-Grid 的这一份带分组。@author nokecy
|
|
151
160
|
var gridColumnDefs = useMemo(function () {
|
|
@@ -4,6 +4,11 @@ export type ReadOnlyFormatterCtx = {
|
|
|
4
4
|
columnProps: any;
|
|
5
5
|
/** 内层数据字段的 schema(可读 enum / x-component-props) */
|
|
6
6
|
fieldSchema: any;
|
|
7
|
+
/**
|
|
8
|
+
* 运行时才确定的选项(field.setDataSource / setFieldState 写入的 dataSource)。
|
|
9
|
+
* 懒挂载格子没有自己的 Formily 字段时,由调用方取同列已创建字段的选项带进来;有值时优先于 schema 静态选项。
|
|
10
|
+
*/
|
|
11
|
+
dataSource?: any[];
|
|
7
12
|
};
|
|
8
13
|
export type ReadOnlyFormatter = (value: any, ctx: ReadOnlyFormatterCtx) => string;
|
|
9
14
|
/**
|
|
@@ -26,6 +26,7 @@ var resolveOptions = function resolveOptions(ctx) {
|
|
|
26
26
|
var _ref, _ref2, _ref3, _fieldSchema$enum, _fieldSchema$xCompon, _fieldSchema$xCompon2;
|
|
27
27
|
var columnProps = ctx.columnProps,
|
|
28
28
|
fieldSchema = ctx.fieldSchema;
|
|
29
|
+
if (Array.isArray(ctx.dataSource) && ctx.dataSource.length > 0) return ctx.dataSource;
|
|
29
30
|
var candidate = (_ref = (_ref2 = (_ref3 = (_fieldSchema$enum = fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.enum) !== null && _fieldSchema$enum !== void 0 ? _fieldSchema$enum : fieldSchema === null || fieldSchema === void 0 || (_fieldSchema$xCompon = fieldSchema['x-component-props']) === null || _fieldSchema$xCompon === void 0 ? void 0 : _fieldSchema$xCompon.options) !== null && _ref3 !== void 0 ? _ref3 : fieldSchema === null || fieldSchema === void 0 || (_fieldSchema$xCompon2 = fieldSchema['x-component-props']) === null || _fieldSchema$xCompon2 === void 0 ? void 0 : _fieldSchema$xCompon2.dataSource) !== null && _ref2 !== void 0 ? _ref2 : columnProps === null || columnProps === void 0 ? void 0 : columnProps.options) !== null && _ref !== void 0 ? _ref : columnProps === null || columnProps === void 0 ? void 0 : columnProps.dataSource;
|
|
30
31
|
return Array.isArray(candidate) ? candidate : [];
|
|
31
32
|
};
|
|
@@ -58,20 +59,63 @@ var selectFormatter = function selectFormatter(value, ctx) {
|
|
|
58
59
|
}
|
|
59
60
|
return mapOptionLabel(value, options);
|
|
60
61
|
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 日期/时间控件没写 format 时的默认显示格式,与 antd 控件自己的默认一致:
|
|
65
|
+
* TimePicker 只显示时间;showTime 带到秒;按月/按年选择器只显示到月/年。
|
|
66
|
+
* 文本态与点开后的控件看到同一个格式,不然 showTime 的列平时只见日期、点开才见时间。
|
|
67
|
+
*/
|
|
68
|
+
var defaultDateFormat = function defaultDateFormat(component, props) {
|
|
69
|
+
if (component === 'TimePicker') return props !== null && props !== void 0 && props.use12Hours ? 'hh:mm:ss a' : 'HH:mm:ss';
|
|
70
|
+
if ((props === null || props === void 0 ? void 0 : props.picker) === 'month') return 'YYYY-MM';
|
|
71
|
+
if ((props === null || props === void 0 ? void 0 : props.picker) === 'year') return 'YYYY';
|
|
72
|
+
if (props !== null && props !== void 0 && props.showTime) return 'YYYY-MM-DD HH:mm:ss';
|
|
73
|
+
return 'YYYY-MM-DD';
|
|
74
|
+
};
|
|
61
75
|
var dateFormatter = function dateFormatter(value, ctx) {
|
|
62
|
-
var
|
|
76
|
+
var _ctx$fieldSchema, _ctx$columnProps, _ctx$fieldSchema2;
|
|
63
77
|
if (value == null || value === '') return '';
|
|
64
|
-
var
|
|
78
|
+
var props = (_ctx$fieldSchema = ctx.fieldSchema) === null || _ctx$fieldSchema === void 0 ? void 0 : _ctx$fieldSchema['x-component-props'];
|
|
79
|
+
// antd 的 format 还可以是数组/函数,文本态只认字符串,其余回到默认
|
|
80
|
+
var configured = [(_ctx$columnProps = ctx.columnProps) === null || _ctx$columnProps === void 0 ? void 0 : _ctx$columnProps.format, props === null || props === void 0 ? void 0 : props.format].find(function (f) {
|
|
81
|
+
return typeof f === 'string' && f;
|
|
82
|
+
});
|
|
83
|
+
var fmt = configured !== null && configured !== void 0 ? configured : defaultDateFormat((_ctx$fieldSchema2 = ctx.fieldSchema) === null || _ctx$fieldSchema2 === void 0 ? void 0 : _ctx$fieldSchema2['x-component'], props);
|
|
65
84
|
if (typeof value.format === 'function') return value.format(fmt);
|
|
66
85
|
// 后端回来的多是 ISO 串(2024-10-19T00:00:00)或时间戳:与 Formily readPretty 一致,按 dayjs(value).format(fmt) 显示;
|
|
67
|
-
// 解析不了的文本(
|
|
86
|
+
// 解析不了的文本(如「待定」、纯时间 08:30:00)原样显示,不吞掉。dayjs 随 antd 传递依赖引入,本库其他模块已直接使用。
|
|
68
87
|
var parsed = dayjs(value);
|
|
69
88
|
return parsed.isValid() ? parsed.format(fmt) : String(value);
|
|
70
89
|
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 数字格:按控件的 precision 补齐小数位、按 formatter 属性(千分位、百分号等)显示,
|
|
93
|
+
* 与点开后的 InputNumber 一致;没配这两项时与原样输出相同。
|
|
94
|
+
*/
|
|
95
|
+
var numberFormatter = function numberFormatter(value, ctx) {
|
|
96
|
+
var _ctx$fieldSchema$xCo, _ctx$fieldSchema3, _ctx$columnProps$prec, _ctx$columnProps2, _ctx$columnProps$form, _ctx$columnProps3;
|
|
97
|
+
if (value == null || value === '') return '';
|
|
98
|
+
var props = (_ctx$fieldSchema$xCo = (_ctx$fieldSchema3 = ctx.fieldSchema) === null || _ctx$fieldSchema3 === void 0 ? void 0 : _ctx$fieldSchema3['x-component-props']) !== null && _ctx$fieldSchema$xCo !== void 0 ? _ctx$fieldSchema$xCo : {};
|
|
99
|
+
var precision = (_ctx$columnProps$prec = (_ctx$columnProps2 = ctx.columnProps) === null || _ctx$columnProps2 === void 0 ? void 0 : _ctx$columnProps2.precision) !== null && _ctx$columnProps$prec !== void 0 ? _ctx$columnProps$prec : props.precision;
|
|
100
|
+
var num = Number(value);
|
|
101
|
+
var base = typeof precision === 'number' && precision >= 0 && Number.isFinite(num) ? num.toFixed(precision) : String(value);
|
|
102
|
+
var formatter = (_ctx$columnProps$form = (_ctx$columnProps3 = ctx.columnProps) === null || _ctx$columnProps3 === void 0 ? void 0 : _ctx$columnProps3.formatter) !== null && _ctx$columnProps$form !== void 0 ? _ctx$columnProps$form : props.formatter;
|
|
103
|
+
if (typeof formatter === 'function') {
|
|
104
|
+
try {
|
|
105
|
+
return String(formatter(base, {
|
|
106
|
+
userTyping: false,
|
|
107
|
+
input: ''
|
|
108
|
+
}));
|
|
109
|
+
} catch (_unused) {
|
|
110
|
+
return base;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return base;
|
|
114
|
+
};
|
|
71
115
|
var booleanFormatter = function booleanFormatter(value, ctx) {
|
|
72
|
-
var _ctx$fieldSchema$
|
|
116
|
+
var _ctx$fieldSchema$xCo2, _ctx$fieldSchema4, _props$checkedChildre, _props$unCheckedChild;
|
|
73
117
|
if (value == null || value === '') return '';
|
|
74
|
-
var props = (_ctx$fieldSchema$
|
|
118
|
+
var props = (_ctx$fieldSchema$xCo2 = (_ctx$fieldSchema4 = ctx.fieldSchema) === null || _ctx$fieldSchema4 === void 0 ? void 0 : _ctx$fieldSchema4['x-component-props']) !== null && _ctx$fieldSchema$xCo2 !== void 0 ? _ctx$fieldSchema$xCo2 : {};
|
|
75
119
|
var truthy = (_props$checkedChildre = props.checkedChildren) !== null && _props$checkedChildre !== void 0 ? _props$checkedChildre : '是';
|
|
76
120
|
var falsy = (_props$unCheckedChild = props.unCheckedChildren) !== null && _props$unCheckedChild !== void 0 ? _props$unCheckedChild : '否';
|
|
77
121
|
return value ? String(truthy) : String(falsy);
|
|
@@ -87,8 +131,8 @@ var registry = {
|
|
|
87
131
|
Password: textFormatter,
|
|
88
132
|
Text: textFormatter,
|
|
89
133
|
Preview: textFormatter,
|
|
90
|
-
NumberPicker:
|
|
91
|
-
InputNumber:
|
|
134
|
+
NumberPicker: numberFormatter,
|
|
135
|
+
InputNumber: numberFormatter,
|
|
92
136
|
Select: selectFormatter,
|
|
93
137
|
TreeSelect: selectFormatter,
|
|
94
138
|
Cascader: selectFormatter,
|
|
@@ -146,17 +190,17 @@ export var registerReadOnlyLabels = function registerReadOnlyLabels(component, l
|
|
|
146
190
|
if (o && o.value != null) map.set(String(o.value), String((_o$label = o.label) !== null && _o$label !== void 0 ? _o$label : o.value));
|
|
147
191
|
});
|
|
148
192
|
} else {
|
|
149
|
-
Object.entries(labels !== null && labels !== void 0 ? labels : {}).forEach(function (
|
|
150
|
-
var
|
|
151
|
-
k =
|
|
152
|
-
v =
|
|
193
|
+
Object.entries(labels !== null && labels !== void 0 ? labels : {}).forEach(function (_ref6) {
|
|
194
|
+
var _ref7 = _slicedToArray(_ref6, 2),
|
|
195
|
+
k = _ref7[0],
|
|
196
|
+
v = _ref7[1];
|
|
153
197
|
return map.set(String(k), String(v));
|
|
154
198
|
});
|
|
155
199
|
}
|
|
156
200
|
var toText = function toText(v) {
|
|
157
|
-
var
|
|
201
|
+
var _ref8, _v$label, _map$get;
|
|
158
202
|
if (v == null || v === '') return '';
|
|
159
|
-
if (_typeof(v) === 'object') return String((
|
|
203
|
+
if (_typeof(v) === 'object') return String((_ref8 = (_v$label = v.label) !== null && _v$label !== void 0 ? _v$label : v.value) !== null && _ref8 !== void 0 ? _ref8 : '');
|
|
160
204
|
return (_map$get = map.get(String(v))) !== null && _map$get !== void 0 ? _map$get : String(v);
|
|
161
205
|
};
|
|
162
206
|
var formatter = function formatter(value) {
|
|
@@ -41,3 +41,20 @@ declare const LazyReadOnlyText: (params: any) => React.JSX.Element;
|
|
|
41
41
|
declare const buildArrayTableColumns: (dataSource: any[], field: ArrayField, sources: ObservableColumnSource[]) => AgGridReactProps['columnDefs'];
|
|
42
42
|
declare const useAddition: () => React.JSX.Element | null;
|
|
43
43
|
export { isColumnComponent, useArrayTableSources, useArrayTableActions, buildArrayTableColumns, useAddition, LazyAgField, LazyReadOnlyText };
|
|
44
|
+
export type LazyColumnDefault = {
|
|
45
|
+
key: string;
|
|
46
|
+
value: any;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* 收集懒挂载列上声明了 default 的字段。
|
|
50
|
+
*
|
|
51
|
+
* Formily 在字段创建时把 schema 的 default 写进值(值为空时)。懒挂载的格子不创建字段,
|
|
52
|
+
* 老记录里缺的列、代码直接 push 的行就拿不到默认值,保存时是 null。
|
|
53
|
+
* 表达式形态的默认值({{...}})要求值上下文,这里不处理。@author nokecy
|
|
54
|
+
*/
|
|
55
|
+
export declare const collectLazyDefaults: (columns: any[]) => LazyColumnDefault[];
|
|
56
|
+
/**
|
|
57
|
+
* 给还没处理过的新增行补默认值:值为空(null/undefined)才写,每行只补一次——
|
|
58
|
+
* 用户之后把格子清空是有意的,不能再被填回去。已落库的行(带 id)不动。@author nokecy
|
|
59
|
+
*/
|
|
60
|
+
export declare const applyLazyDefaults: (arrayField: any, defaults: LazyColumnDefault[], handled: WeakSet<object>) => void;
|