@nokecy/qc-ui 1.1.47 → 1.1.49
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/RuleBuilder/RuleBuilderContainer.js +2 -1
- package/dist/cjs/RuleBuilder/RuleCard.d.ts +2 -0
- package/dist/cjs/RuleBuilder/RuleCard.js +27 -3
- package/dist/cjs/RuleBuilder/RuleGroupEditor.d.ts +2 -0
- package/dist/cjs/RuleBuilder/RuleGroupEditor.js +5 -1
- package/dist/cjs/RuleBuilder/constants/operators.d.ts +5 -0
- package/dist/cjs/RuleBuilder/constants/operators.js +9 -1
- package/dist/cjs/RuleBuilder/index.d.ts +1 -1
- package/dist/cjs/RuleBuilder/index.js +6 -0
- package/dist/cjs/RuleBuilder/inputs/ValueInput.d.ts +10 -2
- package/dist/cjs/RuleBuilder/inputs/ValueInput.js +56 -5
- package/dist/cjs/RuleBuilder/types/index.d.ts +13 -1
- package/dist/cjs/RuleBuilder/types/index.js +1 -1
- package/dist/cjs/RuleBuilder/utils/validation.js +38 -0
- package/dist/cjs/array-table/utils.js +36 -0
- package/dist/esm/RuleBuilder/RuleBuilderContainer.js +2 -1
- package/dist/esm/RuleBuilder/RuleCard.d.ts +2 -0
- package/dist/esm/RuleBuilder/RuleCard.js +28 -4
- package/dist/esm/RuleBuilder/RuleGroupEditor.d.ts +2 -0
- package/dist/esm/RuleBuilder/RuleGroupEditor.js +5 -1
- package/dist/esm/RuleBuilder/constants/operators.d.ts +5 -0
- package/dist/esm/RuleBuilder/constants/operators.js +8 -0
- package/dist/esm/RuleBuilder/index.d.ts +1 -1
- package/dist/esm/RuleBuilder/index.js +1 -1
- package/dist/esm/RuleBuilder/inputs/ValueInput.d.ts +10 -2
- package/dist/esm/RuleBuilder/inputs/ValueInput.js +57 -6
- package/dist/esm/RuleBuilder/types/index.d.ts +13 -1
- package/dist/esm/RuleBuilder/types/index.js +1 -1
- package/dist/esm/RuleBuilder/utils/validation.js +39 -1
- package/dist/esm/array-table/utils.js +36 -0
- package/dist/umd/qc-ui.min.js +1 -1
- package/package.json +1 -1
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* - IsNull/IsNotNull: 不渲染任何输入
|
|
6
6
|
* - Between: 渲染 BetweenValueInput
|
|
7
7
|
* - In/NotIn: 渲染 MultiValueInput
|
|
8
|
-
* - 其他: 渲染 SingleValueInput
|
|
8
|
+
* - 其他: 渲染 SingleValueInput;允许比较字段时前置「固定值 / 字段」切换
|
|
9
9
|
*/
|
|
10
10
|
import React from 'react';
|
|
11
|
-
import type { MatchOperator, FieldDataType } from '../types';
|
|
11
|
+
import type { MatchOperator, FieldDataType, FieldDefinition } from '../types';
|
|
12
12
|
export interface ValueInputProps {
|
|
13
13
|
/** 操作符 */
|
|
14
14
|
operator: MatchOperator;
|
|
@@ -24,6 +24,14 @@ export interface ValueInputProps {
|
|
|
24
24
|
disabled?: boolean;
|
|
25
25
|
/** 尺寸 */
|
|
26
26
|
size?: 'small' | 'middle' | 'large';
|
|
27
|
+
/** 比较字段(undefined 为固定值模式) @author nokecy */
|
|
28
|
+
valueField?: string;
|
|
29
|
+
/** 比较字段变更回调;不传则不提供「字段」模式 @author nokecy */
|
|
30
|
+
onValueFieldChange?: (valueField: string | undefined) => void;
|
|
31
|
+
/** 可供比较的字段列表 @author nokecy */
|
|
32
|
+
fields?: FieldDefinition[];
|
|
33
|
+
/** 当前规则的字段名(比较字段中排除自身) @author nokecy */
|
|
34
|
+
fieldName?: string;
|
|
27
35
|
}
|
|
28
36
|
export declare const ValueInput: React.FC<ValueInputProps>;
|
|
29
37
|
export default ValueInput;
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
* - IsNull/IsNotNull: 不渲染任何输入
|
|
6
6
|
* - Between: 渲染 BetweenValueInput
|
|
7
7
|
* - In/NotIn: 渲染 MultiValueInput
|
|
8
|
-
* - 其他: 渲染 SingleValueInput
|
|
8
|
+
* - 其他: 渲染 SingleValueInput;允许比较字段时前置「固定值 / 字段」切换
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import React from 'react';
|
|
12
|
-
import {
|
|
12
|
+
import { Segmented, Select, Space } from 'antd';
|
|
13
|
+
import { operatorRequiresValue, operatorRequiresValue2, operatorRequiresMultiValue, operatorSupportsValueField } from "../constants/operators";
|
|
13
14
|
import SingleValueInput from "./SingleValueInput";
|
|
14
15
|
import BetweenValueInput from "./BetweenValueInput";
|
|
15
16
|
import MultiValueInput from "./MultiValueInput";
|
|
@@ -22,7 +23,12 @@ export var ValueInput = function ValueInput(_ref) {
|
|
|
22
23
|
_ref$disabled = _ref.disabled,
|
|
23
24
|
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
|
|
24
25
|
_ref$size = _ref.size,
|
|
25
|
-
size = _ref$size === void 0 ? 'middle' : _ref$size
|
|
26
|
+
size = _ref$size === void 0 ? 'middle' : _ref$size,
|
|
27
|
+
valueField = _ref.valueField,
|
|
28
|
+
onValueFieldChange = _ref.onValueFieldChange,
|
|
29
|
+
_ref$fields = _ref.fields,
|
|
30
|
+
fields = _ref$fields === void 0 ? [] : _ref$fields,
|
|
31
|
+
fieldName = _ref.fieldName;
|
|
26
32
|
// 不需要值输入的操作符(IsNull/IsNotNull)
|
|
27
33
|
if (!operatorRequiresValue(operator) && !operatorRequiresValue2(operator) && !operatorRequiresMultiValue(operator)) {
|
|
28
34
|
return null;
|
|
@@ -58,9 +64,7 @@ export var ValueInput = function ValueInput(_ref) {
|
|
|
58
64
|
size: size
|
|
59
65
|
});
|
|
60
66
|
}
|
|
61
|
-
|
|
62
|
-
// 其他操作符:渲染单值输入
|
|
63
|
-
return /*#__PURE__*/React.createElement(SingleValueInput, {
|
|
67
|
+
var singleValueInput = /*#__PURE__*/React.createElement(SingleValueInput, {
|
|
64
68
|
value: value,
|
|
65
69
|
onChange: function onChange(val) {
|
|
66
70
|
return _onChange(val);
|
|
@@ -69,5 +73,52 @@ export var ValueInput = function ValueInput(_ref) {
|
|
|
69
73
|
disabled: disabled,
|
|
70
74
|
size: size
|
|
71
75
|
});
|
|
76
|
+
|
|
77
|
+
// 其他操作符:渲染单值输入
|
|
78
|
+
if (!onValueFieldChange || !operatorSupportsValueField(operator)) {
|
|
79
|
+
return singleValueInput;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 比较类操作符:可切换为与同类型的另一个字段比较。@author nokecy
|
|
83
|
+
var isFieldMode = valueField !== undefined;
|
|
84
|
+
return /*#__PURE__*/React.createElement(Space, {
|
|
85
|
+
size: 4
|
|
86
|
+
}, /*#__PURE__*/React.createElement(Segmented, {
|
|
87
|
+
size: size,
|
|
88
|
+
value: isFieldMode ? 'field' : 'value',
|
|
89
|
+
disabled: disabled,
|
|
90
|
+
options: [{
|
|
91
|
+
label: '固定值',
|
|
92
|
+
value: 'value'
|
|
93
|
+
}, {
|
|
94
|
+
label: '字段',
|
|
95
|
+
value: 'field'
|
|
96
|
+
}],
|
|
97
|
+
onChange: function onChange(mode) {
|
|
98
|
+
return onValueFieldChange(mode === 'field' ? '' : undefined);
|
|
99
|
+
}
|
|
100
|
+
}), isFieldMode ? /*#__PURE__*/React.createElement(Select, {
|
|
101
|
+
value: valueField || undefined,
|
|
102
|
+
onChange: function onChange(name) {
|
|
103
|
+
return onValueFieldChange(name);
|
|
104
|
+
},
|
|
105
|
+
placeholder: "\u8BF7\u9009\u62E9\u6BD4\u8F83\u5B57\u6BB5",
|
|
106
|
+
disabled: disabled,
|
|
107
|
+
size: size,
|
|
108
|
+
showSearch: true,
|
|
109
|
+
optionFilterProp: "label",
|
|
110
|
+
style: {
|
|
111
|
+
width: 200
|
|
112
|
+
},
|
|
113
|
+
options: fields.filter(function (field) {
|
|
114
|
+
return field.dataType === dataType && field.name !== fieldName;
|
|
115
|
+
}).map(function (field) {
|
|
116
|
+
return {
|
|
117
|
+
value: field.name,
|
|
118
|
+
label: field.displayName,
|
|
119
|
+
title: field.description
|
|
120
|
+
};
|
|
121
|
+
})
|
|
122
|
+
}) : singleValueInput);
|
|
72
123
|
};
|
|
73
124
|
export default ValueInput;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* JSON 序列化属性名:
|
|
9
9
|
* - fieldName (不是 FieldName)
|
|
10
10
|
* - operator (不是 Operator)
|
|
11
|
-
* - value, value2
|
|
11
|
+
* - value, value2, valueField
|
|
12
12
|
* - logic, rules, groups
|
|
13
13
|
*/
|
|
14
14
|
/**
|
|
@@ -78,6 +78,12 @@ export interface RuleDto {
|
|
|
78
78
|
value?: any;
|
|
79
79
|
/** 第二个值(用于 Between 操作符) */
|
|
80
80
|
value2?: any;
|
|
81
|
+
/**
|
|
82
|
+
* 比较字段:与另一个字段的值比较,与 value 互斥,仅 6 个比较操作符可用。
|
|
83
|
+
* undefined 为固定值模式;空字符串表示已切到字段模式但尚未选择。
|
|
84
|
+
* @author nokecy
|
|
85
|
+
*/
|
|
86
|
+
valueField?: string;
|
|
81
87
|
}
|
|
82
88
|
/**
|
|
83
89
|
* 规则组 DTO(与后端保持一致)
|
|
@@ -143,6 +149,12 @@ export interface RuleBuilderConfig {
|
|
|
143
149
|
maxNestingLevel?: number;
|
|
144
150
|
/** 是否显示 JSON 预览 */
|
|
145
151
|
showJsonPreview?: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* 是否允许规则与另一个字段比较(valueField)。
|
|
154
|
+
* 需要后端规则引擎与调用方的格式转换都支持 valueField 才能开启,默认关闭。
|
|
155
|
+
* @author nokecy
|
|
156
|
+
*/
|
|
157
|
+
allowFieldComparison?: boolean;
|
|
146
158
|
/** 自定义验证器 */
|
|
147
159
|
validator?: (rule: RuleGroupDto) => ValidationResult;
|
|
148
160
|
}
|
|
@@ -14,7 +14,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
|
|
|
14
14
|
* 规则验证逻辑
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { operatorRequiresValue, operatorRequiresValue2, operatorRequiresMultiValue, getOperatorsByDataType } from "../constants/operators";
|
|
17
|
+
import { operatorRequiresValue, operatorRequiresValue2, operatorRequiresMultiValue, operatorSupportsValueField, getOperatorsByDataType } from "../constants/operators";
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* 验证规则组
|
|
@@ -107,6 +107,12 @@ export function validateRule(rule, fields) {
|
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
// 比较字段模式:值来自另一个字段,不再校验固定值。@author nokecy
|
|
111
|
+
if (rule.valueField !== undefined) {
|
|
112
|
+
errors.push.apply(errors, _toConsumableArray(validateValueField(rule, fields)));
|
|
113
|
+
return errors;
|
|
114
|
+
}
|
|
115
|
+
|
|
110
116
|
// 4. 检查值是否为空(对于需要值的操作符)
|
|
111
117
|
if (operatorRequiresValue(rule.operator)) {
|
|
112
118
|
if (rule.value === undefined || rule.value === null || rule.value === '') {
|
|
@@ -189,6 +195,38 @@ export function validateRule(rule, fields) {
|
|
|
189
195
|
return errors;
|
|
190
196
|
}
|
|
191
197
|
|
|
198
|
+
/**
|
|
199
|
+
* 验证比较字段模式的规则
|
|
200
|
+
* @param rule 规则(valueField 已设置)
|
|
201
|
+
* @param fields 字段定义列表
|
|
202
|
+
* @returns 错误列表
|
|
203
|
+
* @author nokecy
|
|
204
|
+
*/
|
|
205
|
+
function validateValueField(rule, fields) {
|
|
206
|
+
var errors = [];
|
|
207
|
+
var addError = function addError(message) {
|
|
208
|
+
return errors.push({
|
|
209
|
+
path: [],
|
|
210
|
+
message: message,
|
|
211
|
+
field: rule.fieldName
|
|
212
|
+
});
|
|
213
|
+
};
|
|
214
|
+
if (!operatorSupportsValueField(rule.operator)) {
|
|
215
|
+
addError('当前操作符不支持比较字段');
|
|
216
|
+
}
|
|
217
|
+
if (rule.value !== undefined && rule.value !== null && rule.value !== '') {
|
|
218
|
+
addError('固定值和比较字段只能设置一个');
|
|
219
|
+
}
|
|
220
|
+
if (!rule.valueField) {
|
|
221
|
+
addError('请选择比较字段');
|
|
222
|
+
} else if (!fields.some(function (f) {
|
|
223
|
+
return f.name === rule.valueField;
|
|
224
|
+
})) {
|
|
225
|
+
addError("\u6BD4\u8F83\u5B57\u6BB5 \"".concat(rule.valueField, "\" \u4E0D\u5B58\u5728"));
|
|
226
|
+
}
|
|
227
|
+
return errors;
|
|
228
|
+
}
|
|
229
|
+
|
|
192
230
|
/**
|
|
193
231
|
* 验证值的类型是否匹配
|
|
194
232
|
* @param value 值
|
|
@@ -8,6 +8,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
8
8
|
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
9
9
|
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
10
10
|
import React from 'react';
|
|
11
|
+
import { theme } from 'antd';
|
|
11
12
|
import { useField, useFieldSchema, RecursionField, Observer } from '@formily/react';
|
|
12
13
|
import { isArr } from '@formily/shared';
|
|
13
14
|
import ArrayBase from "./arrayBase";
|
|
@@ -162,6 +163,26 @@ var readByFieldPath = function readByFieldPath(record, path) {
|
|
|
162
163
|
}, record);
|
|
163
164
|
};
|
|
164
165
|
|
|
166
|
+
/** 「选一个」型组件:空值占位说「请选择」,其余说「请输入」 */
|
|
167
|
+
var SELECT_LIKE = new Set(['Select', 'TreeSelect', 'Cascader', 'DatePicker', 'TimePicker', 'Radio.Group', 'Checkbox.Group', 'Transfer']);
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* 懒挂载空值格显示什么。
|
|
171
|
+
*
|
|
172
|
+
* 懒挂载把未激活的可编辑格降成纯文本,值为空时整格一片空白——连输入框边框都没有,
|
|
173
|
+
* 用户看不出这里能填,以为功能坏了。故空值时按真控件的 placeholder 出淡灰占位,
|
|
174
|
+
* 点开前后看到同一句话,观感连续。
|
|
175
|
+
*
|
|
176
|
+
* 同样的理由 Switch/Checkbox 早就强制 eager 了(见 buildArrayTableColumns 的
|
|
177
|
+
* isInlineToggle),这里是把那条理由推广到其余可编辑列。@author nokecy
|
|
178
|
+
*/
|
|
179
|
+
var resolveEmptyPlaceholder = function resolveEmptyPlaceholder(fieldSchema) {
|
|
180
|
+
var _fieldSchema$xCompon;
|
|
181
|
+
var configured = fieldSchema === null || fieldSchema === void 0 || (_fieldSchema$xCompon = fieldSchema['x-component-props']) === null || _fieldSchema$xCompon === void 0 ? void 0 : _fieldSchema$xCompon.placeholder;
|
|
182
|
+
if (typeof configured === 'string' && configured) return configured;
|
|
183
|
+
return SELECT_LIKE.has(fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema['x-component']) ? '请选择' : '请输入';
|
|
184
|
+
};
|
|
185
|
+
|
|
165
186
|
/**
|
|
166
187
|
* 懒挂载单元格渲染器(可编辑列)。
|
|
167
188
|
*
|
|
@@ -188,6 +209,9 @@ var LazyAgField = function LazyAgField(params) {
|
|
|
188
209
|
formatter = params.formatter,
|
|
189
210
|
columnProps = params.columnProps,
|
|
190
211
|
fieldSchema = params.fieldSchema;
|
|
212
|
+
// hook 必须在下面的条件 return 之前调用
|
|
213
|
+
var _theme$useToken = theme.useToken(),
|
|
214
|
+
token = _theme$useToken.token;
|
|
191
215
|
var key = "".concat(node === null || node === void 0 ? void 0 : node.id, ":").concat(colDef === null || colDef === void 0 ? void 0 : colDef.field);
|
|
192
216
|
var activated = (record === null || record === void 0 ? void 0 : record._isNew) === true || (context === null || context === void 0 || (_context$activeCells = context.activeCells) === null || _context$activeCells === void 0 || (_context$activeCells$ = _context$activeCells.has) === null || _context$activeCells$ === void 0 ? void 0 : _context$activeCells$.call(_context$activeCells, key)) === true;
|
|
193
217
|
if (activated) {
|
|
@@ -214,6 +238,18 @@ var LazyAgField = function LazyAgField(params) {
|
|
|
214
238
|
fieldSchema: fieldSchema
|
|
215
239
|
}) : liveValue == null ? '' : String(liveValue);
|
|
216
240
|
// 纯文本占满单元格,点击交给 AG-Grid onCellClicked 激活;样式尽量贴近 Editable 只读态避免点开跳动
|
|
241
|
+
if (text === '') {
|
|
242
|
+
// 空值:出淡灰 placeholder,让用户看得出这格能填(颜色取 antd 输入框 placeholder 的 token,自动跟随暗色主题)
|
|
243
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
244
|
+
className: "ag-array-table-lazy-placeholder",
|
|
245
|
+
style: {
|
|
246
|
+
display: 'inline-block',
|
|
247
|
+
width: '100%',
|
|
248
|
+
cursor: 'text',
|
|
249
|
+
color: token.colorTextPlaceholder
|
|
250
|
+
}
|
|
251
|
+
}, resolveEmptyPlaceholder(fieldSchema));
|
|
252
|
+
}
|
|
217
253
|
return /*#__PURE__*/React.createElement("span", {
|
|
218
254
|
className: "ag-array-table-lazy-text",
|
|
219
255
|
style: {
|