lu-lowcode-package-form 0.9.8 → 0.9.18

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.
@@ -1,7 +1,8 @@
1
1
  import React, { forwardRef, useEffect } from "react";
2
2
  import { Form, Row, Col } from "antd";
3
3
 
4
- import {debounce } from 'lodash';
4
+ import { debounce } from 'lodash';
5
+ import { evalFormula } from '../../utils/formula'
5
6
 
6
7
 
7
8
  function batchElements(elements, groupSize) {
@@ -15,8 +16,8 @@ function batchElements(elements, groupSize) {
15
16
 
16
17
  for (const element of elements) {
17
18
  const { _componentName } = element?.props || {};
18
-
19
- if (_componentName && _componentName.startsWith('Layout.')) {
19
+ const componentName = element.type?.displayName || _componentName;
20
+ if (componentName && componentName.startsWith('Layout.')) {
20
21
  if (tempArray.length > 0) {
21
22
  fillWithReactElement(groupSize, tempArray);
22
23
  groupedElements.push(tempArray);
@@ -57,67 +58,177 @@ const FormContainer = forwardRef(({ cols = 1, children }, ref) => {
57
58
  }, [children, cols]);
58
59
 
59
60
  const initializeDependencyMap = () => {
61
+ const fields = [];
62
+ function traverse(currentNode) {
63
+ var componentName = currentNode.type?.displayName || currentNode.props?._componentName;
64
+ const { props } = currentNode;
65
+ if (componentName && componentName.startsWith('Field.')) {
66
+ fields.push(currentNode);
67
+ }
68
+
69
+ if (props?.children){
70
+ let children = React.Children.toArray(props?.children)
71
+ children.forEach(child => traverse(child));
72
+ }
73
+ }
60
74
  dependencyMap.current = new Map();
61
75
  const childrenArray = React.Children.toArray(children);
62
-
63
- childrenArray.forEach(child => {
64
- const { componentId, __id, ...props } = child.props;
76
+ for (let index = 0; index < childrenArray.length; index++) {
77
+ const element = childrenArray[index];
78
+ traverse(element)
79
+ }
80
+ fields.forEach(child => {
81
+ const { componentId, __id, ...props } = child?.props;
65
82
  const identifier = componentId || __id;
66
83
  dependencyMap.current.set(identifier, {
67
- children: childrenArray.filter(item => item.props.__withId === identifier || item.props.__withIds?.includes(identifier)),
84
+ children: childrenArray.filter(item => item.props.withId === identifier || item.props.withIds?.some(item=>{
85
+ return identifier == item || item.startsWith(identifier + '.')
86
+ })),
68
87
  show: true,
69
88
  });
70
89
  });
71
-
90
+ console.log("dependencyMap", dependencyMap.current)
72
91
  initializeFieldVisibility();
73
92
  };
74
93
 
75
- // 初始化字段的显示状态
94
+ // 初始化字段的级联关系
76
95
  const initializeFieldVisibility = (reloadFields = false) => {
77
96
  const fieldValues = form.getFieldsValue();
78
97
  for (let key of dependencyMap.current.keys()) {
79
- updateFieldVisibility(key, fieldValues);
98
+ handleFieldsWith(key, fieldValues);
80
99
  }
81
-
82
100
  if (reloadFields) setFormContent(renderChildren());
83
101
  };
84
102
 
85
- // 计算是否显示
86
- const updateFieldVisibility = (identifier, fieldValues) => {
103
+ // 计算字段级联关系
104
+ const handleFieldsWith = (identifier, fieldValues) => {
87
105
  let needRefresh = false;
88
106
  if (dependencyMap.current.has(identifier)) {
89
107
  const dependentChildren = dependencyMap.current.get(identifier).children;
90
108
  dependentChildren.forEach(child => {
91
- if (child.props.__withFunc && typeof child.props.__withFunc === 'function') {
92
- const childShouldBeVisible = child.props.__withFunc(fieldValues);
93
- const childIdentifier = child.props.componentId || child.props.__id;
94
- if (dependencyMap.current.has(childIdentifier)) {
95
- const childData = dependencyMap.current.get(childIdentifier);
96
- if (childData.show !== childShouldBeVisible) {
97
- childData.show = childShouldBeVisible;
98
- dependencyMap.current.set(childIdentifier, childData);
99
- needRefresh = true;
100
- }
101
- }
109
+ if (child.props.withFunc && typeof child.props.withFunc === 'function') {
110
+ needRefresh = handleFieldsVisible(fieldValues, child)
102
111
  }
112
+
113
+ if (child.props.withFill)
114
+ handleFieldsWithFill(fieldValues, child)
115
+
103
116
  });
104
117
  }
105
118
  return needRefresh;
106
119
  };
107
120
 
121
+ // 处理级联显示隐藏 @return {boolean} 是否需要重新渲染表单的字段
122
+ const handleFieldsVisible = (fieldValues, child) => {
123
+ let needRefresh = false;
124
+ const childShouldBeVisible = child.props.withFunc(fieldValues);
125
+ const childIdentifier = child.props.componentId || child.props.__id;
126
+ if (dependencyMap.current.has(childIdentifier)) {
127
+ const childData = dependencyMap.current.get(childIdentifier);
128
+ if (childData.show !== childShouldBeVisible) {
129
+ childData.show = childShouldBeVisible;
130
+ dependencyMap.current.set(childIdentifier, childData);
131
+ needRefresh = true;
132
+ }
133
+ }
134
+ return needRefresh
135
+ }
136
+ // 处理级联数据源
137
+ // 处理级联填充
138
+ const handleFieldsWithFill = async (fieldValues, child) => {
139
+ const withFill = child.props.withFill;
140
+ const withDataFetch = child.props.withDataFetch;
141
+ console.log("withFill", withFill)
142
+ console.log("fieldValues", fieldValues)
143
+ console.log("child", child)
144
+
145
+ let withDatas = [];
146
+ // 先处理依赖数据
147
+ if (withFill?.withData && withFill?.withData.length > 0 && withDataFetch && typeof withDataFetch === 'function') {
148
+ for (let index = 0; index < withFill?.withData.length; index++) {
149
+ const element = withFill?.withData[index];
150
+ let params = {}
151
+ params.tableName = element.withTable.table_name
152
+ params.filter = {}
153
+ for (let index = 0; index < element.withCondition.length; index++) {
154
+ const { value: condition_value, column: condition_column } = element.withCondition[index];
155
+ params.filter[condition_column.column_name] = getParamValue(condition_value.group_key, condition_value.field_key, fieldValues, withDatas)
156
+ }
157
+
158
+ // 访问接口获取数据
159
+ const response = await withDataFetch(params)
160
+ if (response.code === 0 && response.data.list) {
161
+ withDatas.push({
162
+ id: element.id,
163
+ data: response.data.list
164
+ })
165
+ }
166
+ }
167
+ }
168
+
169
+ // 构造计算公式
170
+ let formula;
171
+ if (withFill.value && withFill.value.length > 0) {
172
+ formula = withFill.value.map(item => {
173
+ let result = "";
174
+ const { insert, attributes } = item
175
+ if (typeof insert !== "string") {
176
+ if (insert?.span && attributes && attributes.tagKey && attributes.id) {
177
+ result = getParamValue(attributes.tagKey, attributes.id, fieldValues, withDatas)
178
+ if (Array.isArray(result)) result = JSON.stringify(result)
179
+ else if (result) result = `"${result}"`
180
+ }
181
+ }
182
+ else result = insert
183
+ return result
184
+ })
185
+ }
186
+ console.log("formula",formula)
187
+ if (formula && formula.length > 0) {
188
+ const childIdentifier = child.props.componentId || child.props.__id;
189
+ form.setFieldValue(childIdentifier, evalFormula(formula))
190
+ }
191
+ }
192
+
193
+ const getParamValue = (tagKey, id, fieldValues, withDatas) => {
194
+ let result = "";
195
+ // 从当前表单字段取值
196
+ if (tagKey == "fieldsValue") {
197
+ if (id.indexOf(".") >= 0) {
198
+ const [parentKey, childKey] = id.split(".");
199
+ const parentValue = fieldValues?.[parentKey] || [];
200
+ if (Array.isArray(parentValue))
201
+ result = parentValue.map(item => {
202
+ return item?.[childKey] || ""
203
+ })
204
+ else result = parentValue?.[childKey] || ""
205
+ }
206
+ else result = fieldValues?.[id] || ""
207
+ }
208
+ // 从依赖数据取值
209
+ else {
210
+ let withData = withDatas.find(item => item.id === tagKey)
211
+ if (withData && withData.data && withData.data.length > 0) {
212
+ // 暂时只取一条数据,后续再想 sum 函数等问题
213
+ result = withData.data[0]?.[id] || ""
214
+ }
215
+ }
216
+ return result
217
+ }
218
+
108
219
  const handleFieldsChange = debounce((changedFields, allFields) => {
109
220
  const fieldValues = form.getFieldsValue();
110
221
  let needRefresh = false;
111
222
  changedFields.forEach(field => {
112
223
  if (field.name && field.name.length > 0) {
113
- needRefresh = updateFieldVisibility(field.name[0], fieldValues);
224
+ needRefresh = handleFieldsWith(field.name[0], fieldValues);
114
225
  }
115
226
  });
116
227
 
117
228
  if (needRefresh) {
118
229
  setFormContent(renderChildren());
119
230
  }
120
- }, 100);
231
+ }, 200);
121
232
 
122
233
  const renderChildren = () => {
123
234
  const childrenArray = React.Children.toArray(children);
@@ -129,12 +240,13 @@ const FormContainer = forwardRef(({ cols = 1, children }, ref) => {
129
240
  cols
130
241
  );
131
242
 
132
- return groupedChildren.map((group,index) => (
243
+ return groupedChildren.map((group, index) => (
133
244
  <Row key={`row-${index}`} gutter={[24, 24]}>
134
245
  {group.map((child, index) => {
135
246
  const { componentId, __id, _componentName, ...props } = child.props;
247
+ const componentName = child.type?.displayName || _componentName;
136
248
  const identifier = componentId || __id;
137
- const isLayoutComponent = _componentName && _componentName.startsWith('Layout.');
249
+ const isLayoutComponent = componentName && componentName.startsWith('Layout.');
138
250
 
139
251
  return (
140
252
  <Col key={identifier || `col-${index}`} span={isLayoutComponent ? 24 : 24 / group.length} style={{ marginBottom: 0 }}>
@@ -168,7 +280,7 @@ export function withWrap(Component) {
168
280
  return forwardRef((props, ref) => <Component {...props} ref={ref} forwardedRef={ref} />);
169
281
  }
170
282
 
171
- export class FormContainerClass extends React.PureComponent{
283
+ export class FormContainerClass extends React.PureComponent {
172
284
  render() {
173
285
  const { forwardedRef, ...otherProps } = this.props;
174
286
  return <FormContainer {...otherProps} ref={forwardedRef} />
@@ -1,5 +1,5 @@
1
1
  const FormGroupTitle = ({ title }) => {
2
- return (title? <div className="fh-11 fflex fitems-center ftext-lg ffont-medium fmb-5 "><span className="fborder-l-4 fborder-slate-300 fpl-2 ">{title}</span></div>: null )
2
+ return (title? <div className="fh-11 fflex fitems-center ftext-lg ffont-medium "><span className="fborder-l-4 fborder-slate-300 fpl-2 ">{title}</span></div>: null )
3
3
  };
4
4
 
5
5
  export default FormGroupTitle;
@@ -1,6 +1,6 @@
1
- import { Input, TextArea, Password, Search ,CodeMachine} from './field/input/index.jsx'
1
+ import { Input, TextArea, Password, Search ,CodeMachine, Number} from './field/input/index.jsx'
2
2
  import '../App.css';
3
- import { TreeSelect, Select, WithSingleSelect,WithMultipleSelect, SingleSelect, MultipleSelect } from './field/select/index.jsx'
3
+ import { TreeSelect, Select, WithSingleSelect,WithMultipleSelect, SingleSelect, MultipleSelect, SearchSelect } from './field/select/index.jsx'
4
4
  import Custom from './field/custom/index.jsx'
5
5
  import { FormContainer, FormContainerWrapper,LayoutFormRow,LayoutFormGroupTitle } from './form-container/index.jsx'
6
6
  import { Checkbox ,CheckboxTree, CheckboxGroup } from './field/checkbox/index.jsx'
@@ -14,8 +14,10 @@ const Field = {
14
14
  TextArea,
15
15
  Password,
16
16
  Search,
17
+ Number,
17
18
  TreeSelect,
18
19
  Select,
20
+ SearchSelect,
19
21
  WithSingleSelect,
20
22
  WithMultipleSelect,
21
23
  SingleSelect,
@@ -29,17 +31,26 @@ const Field = {
29
31
  UploadImage,
30
32
  Switch,
31
33
  DatePicker,
34
+ Table,
32
35
  Custom,
33
36
  }
37
+ Object.keys(Field).forEach(key => {
38
+ Field[key].displayName = `Field.${key}`;
39
+ });
40
+
34
41
  const Layout = {
35
42
  FormRow: LayoutFormRow,
36
43
  FormGroupTitle: LayoutFormGroupTitle,
37
- Table,
38
44
  TableCol
39
45
  }
46
+ Object.keys(Layout).forEach(key => {
47
+ Layout[key].displayName = `Layout.${key}`;
48
+ });
40
49
  export { FormContainer, Field ,FormContainerWrapper,Layout }
41
50
  import { default as OptionSetter} from './setter/optionsetter'
42
51
  const Setter = {
43
52
  OptionSetter
44
53
  }
45
- export { Setter }
54
+ export { Setter }
55
+
56
+ export { EditorQuill , EditorWang} from './editor'
@@ -0,0 +1,12 @@
1
+ // 不安全的eval函数,有时间的话需要重新编写公式编译器
2
+ const evalFormula =(formula) => {
3
+ let result = "";
4
+ try {
5
+ result = eval(formula.join(""));
6
+ } catch (error) {
7
+ console.error("formula error", error);
8
+ }
9
+ return result.toString();
10
+ };
11
+
12
+ export {evalFormula};