@nokecy/qc-ui 1.1.48 → 1.1.50
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/ag-grid-plus/setting/ColumnSetting.js +2 -1
- package/dist/cjs/ag-grid-plus/setting/columnGroupUtils.d.ts +12 -0
- package/dist/cjs/ag-grid-plus/setting/columnGroupUtils.js +50 -7
- package/dist/cjs/array-table/utils.js +53 -1
- 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/ag-grid-plus/setting/ColumnSetting.js +3 -2
- package/dist/esm/ag-grid-plus/setting/columnGroupUtils.d.ts +12 -0
- package/dist/esm/ag-grid-plus/setting/columnGroupUtils.js +46 -5
- package/dist/esm/array-table/utils.js +55 -3
- package/dist/umd/qc-ui.min.js +1 -1
- package/package.json +1 -1
|
@@ -16,7 +16,7 @@ import { FieldSelector } from "./selectors/FieldSelector";
|
|
|
16
16
|
import { OperatorSelector } from "./selectors/OperatorSelector";
|
|
17
17
|
import ValueInput from "./inputs/ValueInput";
|
|
18
18
|
import { useRuleBuilderContext } from "./context/RuleBuilderContext";
|
|
19
|
-
import { getOperatorInfo } from "./constants/operators";
|
|
19
|
+
import { getOperatorInfo, operatorSupportsValueField } from "./constants/operators";
|
|
20
20
|
import styles from "./styles/index.module.less";
|
|
21
21
|
/**
|
|
22
22
|
* 规则卡片组件 - 紧凑版
|
|
@@ -27,7 +27,9 @@ export var RuleCard = function RuleCard(_ref) {
|
|
|
27
27
|
var rule = _ref.rule,
|
|
28
28
|
path = _ref.path,
|
|
29
29
|
_ref$readonly = _ref.readonly,
|
|
30
|
-
readonly = _ref$readonly === void 0 ? false : _ref$readonly
|
|
30
|
+
readonly = _ref$readonly === void 0 ? false : _ref$readonly,
|
|
31
|
+
_ref$allowFieldCompar = _ref.allowFieldComparison,
|
|
32
|
+
allowFieldComparison = _ref$allowFieldCompar === void 0 ? false : _ref$allowFieldCompar;
|
|
31
33
|
var _useRuleBuilderContex = useRuleBuilderContext(),
|
|
32
34
|
state = _useRuleBuilderContex.state,
|
|
33
35
|
dispatch = _useRuleBuilderContex.dispatch;
|
|
@@ -57,7 +59,9 @@ export var RuleCard = function RuleCard(_ref) {
|
|
|
57
59
|
rule: _objectSpread(_objectSpread({}, rule), {}, {
|
|
58
60
|
fieldName: fieldName,
|
|
59
61
|
value: undefined,
|
|
60
|
-
value2: undefined
|
|
62
|
+
value2: undefined,
|
|
63
|
+
// 可比较的字段随数据类型变化,保留字段模式但清空已选字段。@author nokecy
|
|
64
|
+
valueField: rule.valueField !== undefined ? '' : undefined
|
|
61
65
|
})
|
|
62
66
|
}
|
|
63
67
|
});
|
|
@@ -76,7 +80,8 @@ export var RuleCard = function RuleCard(_ref) {
|
|
|
76
80
|
rule: _objectSpread(_objectSpread({}, rule), {}, {
|
|
77
81
|
operator: operator,
|
|
78
82
|
value: needsValue || needsValue2 || needsMultiValue ? rule.value : undefined,
|
|
79
|
-
value2: needsValue2 ? rule.value2 : undefined
|
|
83
|
+
value2: needsValue2 ? rule.value2 : undefined,
|
|
84
|
+
valueField: operatorSupportsValueField(operator) ? rule.valueField : undefined
|
|
80
85
|
})
|
|
81
86
|
}
|
|
82
87
|
});
|
|
@@ -96,6 +101,21 @@ export var RuleCard = function RuleCard(_ref) {
|
|
|
96
101
|
});
|
|
97
102
|
};
|
|
98
103
|
|
|
104
|
+
// 比较字段改变处理:切换模式或选择字段时清空固定值,undefined 表示回到固定值模式。@author nokecy
|
|
105
|
+
var handleValueFieldChange = function handleValueFieldChange(valueField) {
|
|
106
|
+
dispatch({
|
|
107
|
+
type: 'UPDATE_RULE',
|
|
108
|
+
payload: {
|
|
109
|
+
path: path,
|
|
110
|
+
rule: _objectSpread(_objectSpread({}, rule), {}, {
|
|
111
|
+
value: undefined,
|
|
112
|
+
value2: undefined,
|
|
113
|
+
valueField: valueField
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
|
|
99
119
|
// 删除规则处理
|
|
100
120
|
var handleDelete = function handleDelete() {
|
|
101
121
|
dispatch({
|
|
@@ -154,6 +174,10 @@ export var RuleCard = function RuleCard(_ref) {
|
|
|
154
174
|
value: rule.value,
|
|
155
175
|
value2: rule.value2,
|
|
156
176
|
onChange: handleValueChange,
|
|
177
|
+
valueField: rule.valueField,
|
|
178
|
+
onValueFieldChange: allowFieldComparison ? handleValueFieldChange : undefined,
|
|
179
|
+
fields: state.fields,
|
|
180
|
+
fieldName: rule.fieldName,
|
|
157
181
|
disabled: readonly,
|
|
158
182
|
size: "small"
|
|
159
183
|
}), ruleErrors.some(function (e) {
|
|
@@ -35,6 +35,8 @@ export var RuleGroupEditor = function RuleGroupEditor(_ref) {
|
|
|
35
35
|
maxLevel = _ref.maxLevel,
|
|
36
36
|
_ref$readonly = _ref.readonly,
|
|
37
37
|
readonly = _ref$readonly === void 0 ? false : _ref$readonly,
|
|
38
|
+
_ref$allowFieldCompar = _ref.allowFieldComparison,
|
|
39
|
+
allowFieldComparison = _ref$allowFieldCompar === void 0 ? false : _ref$allowFieldCompar,
|
|
38
40
|
onChange = _ref.onChange;
|
|
39
41
|
var _useRuleBuilderContex = useRuleBuilderContext(),
|
|
40
42
|
state = _useRuleBuilderContex.state,
|
|
@@ -147,7 +149,8 @@ export var RuleGroupEditor = function RuleGroupEditor(_ref) {
|
|
|
147
149
|
key: ruleIndex,
|
|
148
150
|
rule: rule,
|
|
149
151
|
path: rulePath,
|
|
150
|
-
readonly: readonly
|
|
152
|
+
readonly: readonly,
|
|
153
|
+
allowFieldComparison: allowFieldComparison
|
|
151
154
|
});
|
|
152
155
|
}), currentGroup.groups.length > 0 && /*#__PURE__*/React.createElement("div", {
|
|
153
156
|
className: styles.nestedGroups
|
|
@@ -159,6 +162,7 @@ export var RuleGroupEditor = function RuleGroupEditor(_ref) {
|
|
|
159
162
|
level: level + 1,
|
|
160
163
|
maxLevel: maxLevel,
|
|
161
164
|
readonly: readonly,
|
|
165
|
+
allowFieldComparison: allowFieldComparison,
|
|
162
166
|
onChange: onChange
|
|
163
167
|
});
|
|
164
168
|
})), currentGroup.rules.length === 0 && currentGroup.groups.length === 0 && /*#__PURE__*/React.createElement("div", {
|
|
@@ -41,6 +41,11 @@ export declare const operatorRequiresValue2: (operator: MatchOperator) => boolea
|
|
|
41
41
|
* 检查操作符是否需要多个值(In/NotIn)
|
|
42
42
|
*/
|
|
43
43
|
export declare const operatorRequiresMultiValue: (operator: MatchOperator) => boolean;
|
|
44
|
+
/**
|
|
45
|
+
* 检查操作符是否支持与另一个字段比较(与后端 RuleGroupValidator 一致:等于、不等于及 4 个大小比较)
|
|
46
|
+
* @author nokecy
|
|
47
|
+
*/
|
|
48
|
+
export declare const operatorSupportsValueField: (operator: MatchOperator) => boolean;
|
|
44
49
|
/**
|
|
45
50
|
* 最大嵌套层级
|
|
46
51
|
*/
|
|
@@ -163,6 +163,14 @@ export var operatorRequiresMultiValue = function operatorRequiresMultiValue(oper
|
|
|
163
163
|
return ((_OPERATOR_INFO_MAP$op3 = OPERATOR_INFO_MAP[operator]) === null || _OPERATOR_INFO_MAP$op3 === void 0 ? void 0 : _OPERATOR_INFO_MAP$op3.requiresMultiValue) || false;
|
|
164
164
|
};
|
|
165
165
|
|
|
166
|
+
/**
|
|
167
|
+
* 检查操作符是否支持与另一个字段比较(与后端 RuleGroupValidator 一致:等于、不等于及 4 个大小比较)
|
|
168
|
+
* @author nokecy
|
|
169
|
+
*/
|
|
170
|
+
export var operatorSupportsValueField = function operatorSupportsValueField(operator) {
|
|
171
|
+
return [MatchOperator.Equals, MatchOperator.NotEquals, MatchOperator.GreaterThan, MatchOperator.GreaterThanOrEqual, MatchOperator.LessThan, MatchOperator.LessThanOrEqual].includes(operator);
|
|
172
|
+
};
|
|
173
|
+
|
|
166
174
|
/**
|
|
167
175
|
* 最大嵌套层级
|
|
168
176
|
*/
|
|
@@ -20,6 +20,6 @@ export { RuleBuilderProvider, useRuleBuilderContext, useRuleBuilderState, useRul
|
|
|
20
20
|
export { createEmptyRule, createEmptyRuleGroup, generateRuleDescription, cloneRuleGroup, isRuleGroupEmpty, countRules, getMaxDepth, } from './utils/ruleHelpers';
|
|
21
21
|
export { getRuleGroupByPath, getRuleByPath, updateRuleAtPath, deleteRuleAtPath, addRuleAtPath, updateRuleGroupAtPath, deleteRuleGroupAtPath, addRuleGroupAtPath, } from './utils/pathHelpers';
|
|
22
22
|
export { validateRuleGroup, validateRule, isRuleGroupValid, } from './utils/validation';
|
|
23
|
-
export { OPERATOR_INFO_MAP, getOperatorInfo, operatorRequiresValue, operatorRequiresValue2, operatorRequiresMultiValue, getOperatorsByDataType, MAX_NESTING_LEVEL, } from './constants/operators';
|
|
23
|
+
export { OPERATOR_INFO_MAP, getOperatorInfo, operatorRequiresValue, operatorRequiresValue2, operatorRequiresMultiValue, operatorSupportsValueField, getOperatorsByDataType, MAX_NESTING_LEVEL, } from './constants/operators';
|
|
24
24
|
export type { MatchOperator, MatchLogic, FieldDataType, RuleDto, RuleGroupDto, FieldDefinition, ValidationResult, ValidationError, RuleBuilderProps, RuleBuilderConfig, RulePath, RuleBuilderState, RuleBuilderAction, OperatorInfo, } from './types';
|
|
25
25
|
export { RuleBuilderContainer as default } from './RuleBuilderContainer';
|
|
@@ -34,7 +34,7 @@ export { getRuleGroupByPath, getRuleByPath, updateRuleAtPath, deleteRuleAtPath,
|
|
|
34
34
|
export { validateRuleGroup, validateRule, isRuleGroupValid } from "./utils/validation";
|
|
35
35
|
|
|
36
36
|
// ============ 常量 ============
|
|
37
|
-
export { OPERATOR_INFO_MAP, getOperatorInfo, operatorRequiresValue, operatorRequiresValue2, operatorRequiresMultiValue, getOperatorsByDataType, MAX_NESTING_LEVEL } from "./constants/operators";
|
|
37
|
+
export { OPERATOR_INFO_MAP, getOperatorInfo, operatorRequiresValue, operatorRequiresValue2, operatorRequiresMultiValue, operatorSupportsValueField, getOperatorsByDataType, MAX_NESTING_LEVEL } from "./constants/operators";
|
|
38
38
|
|
|
39
39
|
// ============ 类型定义 ============
|
|
40
40
|
|
|
@@ -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 值
|
|
@@ -33,7 +33,7 @@ import { AgGridReact } from 'ag-grid-react';
|
|
|
33
33
|
import { agGridTheme } from "../theme";
|
|
34
34
|
import { localeText } from "../locale";
|
|
35
35
|
import { createForm, onFormInit } from '@formily/core';
|
|
36
|
-
import { gridStateToFlatConfig, flatConfigToGridState, flatConfigToColumnState, isOldSchemeData, migrateOldScheme, generateId } from "./columnGroupUtils";
|
|
36
|
+
import { gridStateToFlatConfig, flatConfigToGridState, flatConfigToColumnState, dropQueryOnlyItems, excludeQueryOnlyColumns, isOldSchemeData, migrateOldScheme, generateId } from "./columnGroupUtils";
|
|
37
37
|
import ColumnConfigTable from "./ColumnConfigTable";
|
|
38
38
|
import DraggableModal from "../../draggableModal";
|
|
39
39
|
import { useGridSchemes } from "../context/useSchemeManager";
|
|
@@ -298,7 +298,8 @@ var ColumnSetting = function ColumnSetting(_ref) {
|
|
|
298
298
|
// 【修复】修正 originalHeaderName,确保使用 initialColumnDefs 中的原始值
|
|
299
299
|
var config = fixOriginalHeaderName(currentScheme.columnConfig);
|
|
300
300
|
// 【修复】检测并追加代码中新增的列到配置末尾
|
|
301
|
-
|
|
301
|
+
// 只做查询条件的列不进列配置:方案里存过的剔除,也不当新增列追加 @author nokecy
|
|
302
|
+
config = mergeNewColumns(dropQueryOnlyItems(config, originalColumnDefs), excludeQueryOnlyColumns(originalColumnDefs));
|
|
302
303
|
// 【修复】按 order 字段排序,确保配置弹窗显示的列顺序与保存时一致
|
|
303
304
|
config = _toConsumableArray(config).sort(function (a, b) {
|
|
304
305
|
return a.order - b.order;
|
|
@@ -8,6 +8,18 @@ import type { FlatColumnItem, OldColumnState } from './columnGroupTypes';
|
|
|
8
8
|
* 生成唯一 ID
|
|
9
9
|
*/
|
|
10
10
|
export declare const generateId: () => string;
|
|
11
|
+
/**
|
|
12
|
+
* 去掉只做查询条件的列(hideInTable),含分组内的
|
|
13
|
+
* 这类列只进查询表单,不是表格列:列方案的还原、新增列检测都不能把它带进表格
|
|
14
|
+
* @author nokecy
|
|
15
|
+
*/
|
|
16
|
+
export declare function excludeQueryOnlyColumns<T extends ColDef | ColGroupDef>(defs?: T[]): T[] | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* 从已存的列方案中去掉只做查询条件的列
|
|
19
|
+
* 旧版本方案会把它们当新增列存进去,还原时要按当前列定义剔除
|
|
20
|
+
* @author nokecy
|
|
21
|
+
*/
|
|
22
|
+
export declare function dropQueryOnlyItems(flatConfig: FlatColumnItem[], originalColumnDefs?: (ColDef | ColGroupDef)[]): FlatColumnItem[];
|
|
11
23
|
/**
|
|
12
24
|
* Grid State → 扁平化配置
|
|
13
25
|
* 将 AG-Grid 的树形结构转换为扁平化数组,用于 UI 展示和编辑
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
-
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; }
|
|
3
|
-
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; }
|
|
4
|
-
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
2
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
8
3
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
9
4
|
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
@@ -11,6 +6,11 @@ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToAr
|
|
|
11
6
|
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; } } }; }
|
|
12
7
|
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); }
|
|
13
8
|
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; }
|
|
9
|
+
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; }
|
|
10
|
+
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; }
|
|
11
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
12
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
13
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
14
14
|
/**
|
|
15
15
|
* 表头分组配置工具函数
|
|
16
16
|
* 负责 Grid State 与扁平化配置之间的转换
|
|
@@ -25,6 +25,39 @@ export var generateId = function generateId() {
|
|
|
25
25
|
return uniqueId('col_');
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* 去掉只做查询条件的列(hideInTable),含分组内的
|
|
30
|
+
* 这类列只进查询表单,不是表格列:列方案的还原、新增列检测都不能把它带进表格
|
|
31
|
+
* @author nokecy
|
|
32
|
+
*/
|
|
33
|
+
export function excludeQueryOnlyColumns(defs) {
|
|
34
|
+
return defs === null || defs === void 0 ? void 0 : defs.filter(function (def) {
|
|
35
|
+
return !def.hideInTable;
|
|
36
|
+
}).map(function (def) {
|
|
37
|
+
return 'children' in def && def.children ? _objectSpread(_objectSpread({}, def), {}, {
|
|
38
|
+
children: excludeQueryOnlyColumns(def.children)
|
|
39
|
+
}) : def;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 从已存的列方案中去掉只做查询条件的列
|
|
45
|
+
* 旧版本方案会把它们当新增列存进去,还原时要按当前列定义剔除
|
|
46
|
+
* @author nokecy
|
|
47
|
+
*/
|
|
48
|
+
export function dropQueryOnlyItems(flatConfig, originalColumnDefs) {
|
|
49
|
+
var queryOnlyFields = new Set();
|
|
50
|
+
var collect = function collect(defs) {
|
|
51
|
+
return defs.forEach(function (def) {
|
|
52
|
+
if ('children' in def && def.children) collect(def.children);else if (def.hideInTable && def.field) queryOnlyFields.add(def.field);
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
collect(originalColumnDefs !== null && originalColumnDefs !== void 0 ? originalColumnDefs : []);
|
|
56
|
+
return flatConfig.filter(function (item) {
|
|
57
|
+
return item.type !== 'column' || !item.field || !queryOnlyFields.has(item.field);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
28
61
|
/**
|
|
29
62
|
* Grid State → 扁平化配置
|
|
30
63
|
* 将 AG-Grid 的树形结构转换为扁平化数组,用于 UI 展示和编辑
|
|
@@ -134,6 +167,10 @@ export function gridStateToFlatConfig(columnDefs, originalColumnDefs) {
|
|
|
134
167
|
* @returns AG-Grid 列定义数组
|
|
135
168
|
*/
|
|
136
169
|
export function flatConfigToGridState(flatConfig, originalColumnDefs) {
|
|
170
|
+
// 只做查询条件的列不进表格:方案里存过的剔除,也不当新增列补回 @author nokecy
|
|
171
|
+
flatConfig = dropQueryOnlyItems(flatConfig, originalColumnDefs);
|
|
172
|
+
originalColumnDefs = excludeQueryOnlyColumns(originalColumnDefs);
|
|
173
|
+
|
|
137
174
|
/**
|
|
138
175
|
* 从原始列定义中查找指定字段的列定义(支持递归查找分组内的列)
|
|
139
176
|
*/
|
|
@@ -451,6 +488,10 @@ export function isOldSchemeData(data) {
|
|
|
451
488
|
* @returns AG-Grid columnState 数组
|
|
452
489
|
*/
|
|
453
490
|
export function flatConfigToColumnState(flatConfig, originalColumnDefs) {
|
|
491
|
+
// 只做查询条件的列不进表格:方案里存过的剔除,也不当新增列补回 @author nokecy
|
|
492
|
+
flatConfig = dropQueryOnlyItems(flatConfig, originalColumnDefs);
|
|
493
|
+
originalColumnDefs = excludeQueryOnlyColumns(originalColumnDefs);
|
|
494
|
+
|
|
454
495
|
/**
|
|
455
496
|
* 递归收集所有列定义(包括分组内的列)
|
|
456
497
|
*/
|
|
@@ -9,8 +9,9 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return
|
|
|
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
11
|
import { theme } from 'antd';
|
|
12
|
-
import { useField, useFieldSchema, RecursionField, Observer } from '@formily/react';
|
|
13
|
-
import { isArr } from '@formily/shared';
|
|
12
|
+
import { useField, useFieldSchema, RecursionField, Observer, useExpressionScope } from '@formily/react';
|
|
13
|
+
import { isArr, lazyMerge } from '@formily/shared';
|
|
14
|
+
import { Schema } from '@formily/json-schema';
|
|
14
15
|
import ArrayBase from "./arrayBase";
|
|
15
16
|
import { getReadOnlyFormatter } from "./readOnlyFormatters";
|
|
16
17
|
var isColumnComponent = function isColumnComponent(schema) {
|
|
@@ -183,6 +184,54 @@ var resolveEmptyPlaceholder = function resolveEmptyPlaceholder(fieldSchema) {
|
|
|
183
184
|
return SELECT_LIKE.has(fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema['x-component']) ? '请选择' : '请输入';
|
|
184
185
|
};
|
|
185
186
|
|
|
187
|
+
/** Formily 字段的四种 pattern;x-pattern 求出来不在其中,视为「求不出」 */
|
|
188
|
+
var CELL_PATTERNS = new Set(['editable', 'disabled', 'readOnly', 'readPretty']);
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* 懒挂载格此刻的 pattern。
|
|
192
|
+
*
|
|
193
|
+
* 懒挂载不创建 Formily 字段,拿不到字段实例上求好的 pattern,只能按同一套规则自己求:
|
|
194
|
+
* 字段自己的 x-pattern 优先(表达式按本行本格的作用域求值,$self 只提供 path/index/value/form/parent/query),
|
|
195
|
+
* 没写则继承整表 pattern。表达式用到本格没有的能力、抛错或求出非法值时返回 undefined,
|
|
196
|
+
* 调用方按「可编辑」处理,保持原有提示。@author nokecy
|
|
197
|
+
*/
|
|
198
|
+
var resolveLazyCellPattern = function resolveLazyCellPattern(arrayField, record, dataKey, fieldSchema, scope) {
|
|
199
|
+
var own = fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema['x-pattern'];
|
|
200
|
+
if (own == null) return arrayField === null || arrayField === void 0 ? void 0 : arrayField.pattern;
|
|
201
|
+
if (typeof own !== 'string') return undefined;
|
|
202
|
+
if (CELL_PATTERNS.has(own)) return own;
|
|
203
|
+
var form = arrayField === null || arrayField === void 0 ? void 0 : arrayField.form;
|
|
204
|
+
if (!form || !dataKey) return undefined;
|
|
205
|
+
try {
|
|
206
|
+
var _arrayField$value$ind, _arrayField$value, _arrayField$value$ind2;
|
|
207
|
+
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;
|
|
208
|
+
var path = arrayField.address.concat(index).concat(dataKey);
|
|
209
|
+
var self = {
|
|
210
|
+
path: path,
|
|
211
|
+
address: path,
|
|
212
|
+
index: index,
|
|
213
|
+
form: form,
|
|
214
|
+
parent: arrayField,
|
|
215
|
+
get value() {
|
|
216
|
+
return readByFieldPath(record, dataKey);
|
|
217
|
+
},
|
|
218
|
+
query: function query(pattern) {
|
|
219
|
+
return form.query(pattern);
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
var result = Schema.shallowCompile(own, lazyMerge(scope !== null && scope !== void 0 ? scope : {}, {
|
|
223
|
+
$form: form,
|
|
224
|
+
$values: form.values,
|
|
225
|
+
$self: self,
|
|
226
|
+
$record: record,
|
|
227
|
+
$index: index
|
|
228
|
+
}));
|
|
229
|
+
return CELL_PATTERNS.has(result) ? result : undefined;
|
|
230
|
+
} catch (_unused) {
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
186
235
|
/**
|
|
187
236
|
* 懒挂载单元格渲染器(可编辑列)。
|
|
188
237
|
*
|
|
@@ -212,6 +261,7 @@ var LazyAgField = function LazyAgField(params) {
|
|
|
212
261
|
// hook 必须在下面的条件 return 之前调用
|
|
213
262
|
var _theme$useToken = theme.useToken(),
|
|
214
263
|
token = _theme$useToken.token;
|
|
264
|
+
var scope = useExpressionScope();
|
|
215
265
|
var key = "".concat(node === null || node === void 0 ? void 0 : node.id, ":").concat(colDef === null || colDef === void 0 ? void 0 : colDef.field);
|
|
216
266
|
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;
|
|
217
267
|
if (activated) {
|
|
@@ -238,7 +288,9 @@ var LazyAgField = function LazyAgField(params) {
|
|
|
238
288
|
fieldSchema: fieldSchema
|
|
239
289
|
}) : liveValue == null ? '' : String(liveValue);
|
|
240
290
|
// 纯文本占满单元格,点击交给 AG-Grid onCellClicked 激活;样式尽量贴近 Editable 只读态避免点开跳动
|
|
241
|
-
|
|
291
|
+
// 只读态(readPretty/disabled/readOnly)的空格不出编辑提示,留空与只读快路径一致
|
|
292
|
+
var pattern = text === '' ? resolveLazyCellPattern(field, record, dataKey, fieldSchema, scope) : undefined;
|
|
293
|
+
if (text === '' && (pattern == null || pattern === 'editable')) {
|
|
242
294
|
// 空值:出淡灰 placeholder,让用户看得出这格能填(颜色取 antd 输入框 placeholder 的 token,自动跟随暗色主题)
|
|
243
295
|
return /*#__PURE__*/React.createElement("span", {
|
|
244
296
|
className: "ag-array-table-lazy-placeholder",
|