lu-lowcode-package-form 0.9.7 → 0.9.16
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/index.cjs.js +408 -172
- package/dist/index.es.js +55162 -25861
- package/dist/style.css +6 -1
- package/package.json +6 -1
- package/src/App.jsx +171 -27
- package/src/components/editor/add-with-param.jsx +13 -0
- package/src/components/editor/index.jsx +2 -0
- package/src/components/editor/quill.jsx +125 -0
- package/src/components/editor/wang.jsx +80 -0
- package/src/components/field/base.jsx +18 -3
- package/src/components/field/date-picker/index.jsx +9 -2
- package/src/components/field/select/index.jsx +1 -1
- package/src/components/field/select/search-select.jsx +110 -0
- package/src/components/field/select/select.jsx +5 -5
- package/src/components/field/table/index.jsx +267 -0
- package/src/components/field/upload/upload-image.jsx +0 -2
- package/src/components/form-container/index.jsx +109 -24
- package/src/components/form-container/layout/form-group-title.jsx +1 -1
- package/src/components/index.jsx +9 -3
- package/src/utils/formula.js +11 -0
|
@@ -3,7 +3,14 @@ import { DatePicker as OriginalDatePicker, Button } from 'antd';
|
|
|
3
3
|
import { BaseWrapper } from "../base.jsx"
|
|
4
4
|
import dayjs from 'dayjs';
|
|
5
5
|
import 'dayjs/locale/zh-cn';
|
|
6
|
-
|
|
6
|
+
import zh from 'antd/es/date-picker/locale/zh_CN';
|
|
7
|
+
|
|
8
|
+
import updateLocale from 'dayjs/plugin/updateLocale';
|
|
9
|
+
|
|
10
|
+
dayjs.extend(updateLocale);
|
|
11
|
+
dayjs.updateLocale('zh-cn', {
|
|
12
|
+
weekStart: 0,
|
|
13
|
+
});
|
|
7
14
|
|
|
8
15
|
const DatePicker = ({ datetype, value, onChange, ...props }) => {
|
|
9
16
|
datetype = datetype || "date"
|
|
@@ -58,7 +65,7 @@ const DatePicker = ({ datetype, value, onChange, ...props }) => {
|
|
|
58
65
|
}, [datetype])
|
|
59
66
|
return (
|
|
60
67
|
<BaseWrapper {...props}>
|
|
61
|
-
<OriginalDatePicker {...props} picker={picker} format={format} style={{ width: '100%' }} onChange={handleChange} value={nValue} showTime={showTime} needConfirm={needConfirm} />
|
|
68
|
+
<OriginalDatePicker locale={zh} {...props} picker={picker} format={format} style={{ width: '100%' }} onChange={handleChange} value={nValue} showTime={showTime} needConfirm={needConfirm} />
|
|
62
69
|
</BaseWrapper>
|
|
63
70
|
);
|
|
64
71
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import { Input, Select as OriginalSelect, Spin } from 'antd';
|
|
4
|
+
import React, { useEffect, useState } from 'react';
|
|
5
|
+
import { BaseWrapper } from "../base"
|
|
6
|
+
import { debounce } from 'lodash';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const SearchSelect = ({ addWrapper = true, value, type, defaultValue, onChange, option_label, option_value, option_search, options, request, requestParams, callError, ...props }) => {
|
|
10
|
+
const [nOptions, setNOptions] = React.useState([])
|
|
11
|
+
const [fetching, setFetching] = useState(false);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
initData(requestParams)
|
|
14
|
+
}, [requestParams])
|
|
15
|
+
|
|
16
|
+
const initData = async (params) => {
|
|
17
|
+
let item = null
|
|
18
|
+
if (request && typeof request === 'function') {
|
|
19
|
+
const list = await fetchOptions(params)
|
|
20
|
+
if (list && Array.isArray(list))
|
|
21
|
+
item = value ? list.find(item => item.value == value) : null
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (options && options.length > 0) {
|
|
25
|
+
item = value ? options.find(item => item.value == value) : null
|
|
26
|
+
setNOptions(options)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (item) {
|
|
30
|
+
onChange(item)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const handleSearch = debounce(async (value) => {
|
|
36
|
+
const params = { ...requestParams }
|
|
37
|
+
params[option_search] = value
|
|
38
|
+
await fetchOptions(params)
|
|
39
|
+
}, 200)
|
|
40
|
+
|
|
41
|
+
const fetchOptions = async (params) => {
|
|
42
|
+
try {
|
|
43
|
+
setFetching(true)
|
|
44
|
+
const response = await request(params);
|
|
45
|
+
if (response.code > 0) {
|
|
46
|
+
callError && typeof callError === 'function' && callError(response.message);
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
let list = response.data?.list || response.data
|
|
50
|
+
if (Array.isArray(list)) {
|
|
51
|
+
list = list.map(item => ({ ...item, label: item[option_label], value: item[option_value] }))
|
|
52
|
+
setNOptions(list)
|
|
53
|
+
}
|
|
54
|
+
else setNOptions([])
|
|
55
|
+
return list
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error("fetchOptions", error)
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
setFetching(false)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const handleChange = (value) => {
|
|
65
|
+
const item = nOptions.find(item => item.value === value)
|
|
66
|
+
onChange(item)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
return addWrapper ? (
|
|
71
|
+
<BaseWrapper {...props}>
|
|
72
|
+
<OriginalSelect
|
|
73
|
+
notFoundContent={fetching ? <Spin size="small" /> : null}
|
|
74
|
+
value={value}
|
|
75
|
+
{...props}
|
|
76
|
+
disabled={false}
|
|
77
|
+
filterOption={false}
|
|
78
|
+
showSearch={request && option_search ? true : false}
|
|
79
|
+
onSearch={request && option_search ? handleSearch : null}
|
|
80
|
+
onChange={handleChange}
|
|
81
|
+
style={{ width: '100%' }}
|
|
82
|
+
mode="single" >
|
|
83
|
+
{nOptions.map((item, index) => (
|
|
84
|
+
<OriginalSelect.Option key={index} value={item.value} disabled={false}>
|
|
85
|
+
{item.label}
|
|
86
|
+
</OriginalSelect.Option>
|
|
87
|
+
))}
|
|
88
|
+
</OriginalSelect>
|
|
89
|
+
</BaseWrapper>
|
|
90
|
+
) : <OriginalSelect
|
|
91
|
+
notFoundContent={fetching ? <Spin size="small" /> : null}
|
|
92
|
+
value={value}
|
|
93
|
+
{...props}
|
|
94
|
+
disabled={false}
|
|
95
|
+
filterOption={false}
|
|
96
|
+
showSearch={request && option_search ? true : false}
|
|
97
|
+
onSearch={request && option_search ? handleSearch : null}
|
|
98
|
+
onChange={handleChange}
|
|
99
|
+
style={{ width: '100%' }}
|
|
100
|
+
mode="single" >
|
|
101
|
+
{nOptions.map((item, index) => (
|
|
102
|
+
<OriginalSelect.Option key={index} value={item.value} disabled={false}>
|
|
103
|
+
{item.label}
|
|
104
|
+
</OriginalSelect.Option>
|
|
105
|
+
))}
|
|
106
|
+
</OriginalSelect>
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export {SearchSelect}
|
|
@@ -3,7 +3,7 @@ import { Select as OriginalSelect } from "antd";
|
|
|
3
3
|
import { BaseWrapper } from "../base"
|
|
4
4
|
import React, { useEffect, useState } from 'react';
|
|
5
5
|
|
|
6
|
-
const Select = ({ request, option_label = "label", option_value = "id", disabledValue, callError, options, ...props }) => {
|
|
6
|
+
const Select = ({ request, option_label = "label", option_value = "id", disabledValue, callError, options, addWrapper = true, ...props }) => {
|
|
7
7
|
// const [firstLoad, setFirstLoad] = React.useState(false)
|
|
8
8
|
const [nOptions, setNOptions] = React.useState([])
|
|
9
9
|
useEffect(() => {
|
|
@@ -29,11 +29,11 @@ const Select = ({ request, option_label = "label", option_value = "id", disabled
|
|
|
29
29
|
|
|
30
30
|
// setFirstLoad(true)
|
|
31
31
|
}
|
|
32
|
-
return (
|
|
32
|
+
return addWrapper ?(
|
|
33
33
|
<BaseWrapper {...props}>
|
|
34
34
|
<OriginalSelect {...props} options={nOptions} style={{ width: '100%' }} />
|
|
35
35
|
</BaseWrapper>
|
|
36
|
-
)
|
|
36
|
+
) : <OriginalSelect {...props} options={nOptions} style={{ width: '100%' }} />
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const SingleSelect = ({ ...props }) => {
|
|
@@ -46,7 +46,7 @@ const MultipleSelect = ({ onChange, value, ...props }) => {
|
|
|
46
46
|
const [nValue, setNValue] = React.useState([])
|
|
47
47
|
|
|
48
48
|
useEffect(()=>{
|
|
49
|
-
if (typeof value === "string") {
|
|
49
|
+
if (value && typeof value === "string") {
|
|
50
50
|
try {
|
|
51
51
|
value = JSON.parse(value)
|
|
52
52
|
onChange(value)
|
|
@@ -55,7 +55,7 @@ const MultipleSelect = ({ onChange, value, ...props }) => {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
setNValue(value)
|
|
58
|
+
if(value) setNValue(value)
|
|
59
59
|
},[value])
|
|
60
60
|
|
|
61
61
|
return (
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import React, { useEffect, useState, useRef, useCallback } from "react";
|
|
2
|
+
import { Button } from "antd";
|
|
3
|
+
import { DeleteOutlined } from "@ant-design/icons";
|
|
4
|
+
import { isEqual, debounce } from 'lodash';
|
|
5
|
+
import { evalFormula } from "../../../utils/formula";
|
|
6
|
+
|
|
7
|
+
const TableCol = ({ children, width, ...props }) => {
|
|
8
|
+
const [sWidth, setSWidth] = useState(0);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
setSWidth(width);
|
|
11
|
+
}, [width]);
|
|
12
|
+
return <div className="fflex-1" style={{ minWidth: `${sWidth}px` }} {...props}>
|
|
13
|
+
{children}
|
|
14
|
+
</div>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const TableAction = ({ label, subTableIndex, children, ...props }) => {
|
|
18
|
+
return <div className="fw-16">
|
|
19
|
+
<div className="frelative fw-full fh-full fflex fflex-col">
|
|
20
|
+
{label && subTableIndex === 0 && <div className='fh-12 ffont-semibold fbg-gray-100 ftext-sm fflex fjustify-between fitems-center fpx-2 fborder-b'>{label}</div>}
|
|
21
|
+
<div className="fw-full fflex-1 fflex fitems-center fjustify-center fp-2 ">
|
|
22
|
+
{children}
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const Table = ({ children, value, onChange, ...props }) => {
|
|
29
|
+
const [rows, setRows] = useState([{}]);
|
|
30
|
+
const prevRowsRef = useRef(rows);
|
|
31
|
+
const dependencyMap = useRef(new Map());
|
|
32
|
+
const [updateField, setUpdateField] = useState({});
|
|
33
|
+
const tableId = props.componentId || props.__id;
|
|
34
|
+
const setPrevRows = (newValue) => {
|
|
35
|
+
setRows(newValue);
|
|
36
|
+
prevRowsRef.current = newValue;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
console.log("value useEffect ", JSON.stringify(value));
|
|
41
|
+
if (value && typeof value === "string") {
|
|
42
|
+
try {
|
|
43
|
+
value = JSON.parse(value);
|
|
44
|
+
onChange(value);
|
|
45
|
+
} catch (error) { }
|
|
46
|
+
}
|
|
47
|
+
if (value && Array.isArray(value) && !isEqual(prevRowsRef.current, value)) {
|
|
48
|
+
console.log("useEffect setRows");
|
|
49
|
+
setPrevRows(value);
|
|
50
|
+
}
|
|
51
|
+
}, [value]);
|
|
52
|
+
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
console.log("children useEffect ",children);
|
|
55
|
+
initializeDependencyMap();
|
|
56
|
+
}, [children]);
|
|
57
|
+
|
|
58
|
+
const initializeDependencyMap = useCallback(() => {
|
|
59
|
+
dependencyMap.current.clear();
|
|
60
|
+
const childrenArray = React.Children.toArray(children);
|
|
61
|
+
childrenArray.forEach(child => {
|
|
62
|
+
const { componentId, __id, ...props } = child.props;
|
|
63
|
+
const identifier = `${tableId}.${(componentId || __id)}`;
|
|
64
|
+
|
|
65
|
+
dependencyMap.current.set(identifier, {
|
|
66
|
+
children: childrenArray.filter(item => item.props.withId === identifier || item.props.withIds?.includes(identifier)),
|
|
67
|
+
show: true,
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
initializeFieldVisibility();
|
|
71
|
+
}, [children, tableId]);
|
|
72
|
+
|
|
73
|
+
const handleRowValues = useCallback((rowValues) => {
|
|
74
|
+
const result = {};
|
|
75
|
+
for (let key in rowValues) {
|
|
76
|
+
result[`${tableId}.${key}`] = rowValues[key] || '';
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}, [tableId]);
|
|
80
|
+
|
|
81
|
+
const initializeFieldVisibility = useCallback(() => {
|
|
82
|
+
rows.forEach((row, rowIndex) => {
|
|
83
|
+
const fieldValues = handleRowValues(row);
|
|
84
|
+
for (let key of dependencyMap.current.keys()) {
|
|
85
|
+
handleFieldsWith(key, fieldValues, rowIndex);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}, [rows, handleRowValues]);
|
|
89
|
+
|
|
90
|
+
const handleFieldsWith = useCallback((identifier, fieldValues, rowIndex) => {
|
|
91
|
+
let needRefresh = false;
|
|
92
|
+
const fullIdentifier = `${tableId}.${identifier}`;
|
|
93
|
+
if (dependencyMap.current.has(fullIdentifier)) {
|
|
94
|
+
const dependentChildren = dependencyMap.current.get(fullIdentifier).children;
|
|
95
|
+
dependentChildren.forEach(child => {
|
|
96
|
+
if (child.props.withFunc && typeof child.props.withFunc === 'function') {
|
|
97
|
+
needRefresh = handleFieldsVisible(fieldValues, child);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (child.props.withFill) {
|
|
101
|
+
handleFieldsWithFill(fieldValues, child, rowIndex);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return needRefresh;
|
|
106
|
+
}, [tableId, rows]);
|
|
107
|
+
|
|
108
|
+
const handleFieldsVisible = useCallback((fieldValues, child) => {
|
|
109
|
+
let needRefresh = false;
|
|
110
|
+
const childShouldBeVisible = child.props.withFunc(fieldValues);
|
|
111
|
+
const childIdentifier = child.props.componentId || child.props.__id;
|
|
112
|
+
if (dependencyMap.current.has(childIdentifier)) {
|
|
113
|
+
const childData = dependencyMap.current.get(childIdentifier);
|
|
114
|
+
if (childData.show !== childShouldBeVisible) {
|
|
115
|
+
childData.show = childShouldBeVisible;
|
|
116
|
+
dependencyMap.current.set(childIdentifier, childData);
|
|
117
|
+
needRefresh = true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return needRefresh;
|
|
121
|
+
}, []);
|
|
122
|
+
|
|
123
|
+
const handleFieldsWithFill = useCallback(async (fieldValues, child, rowIndex) => {
|
|
124
|
+
const withFill = child.props.withFill;
|
|
125
|
+
const withDataFetch = child.props.withDataFetch;
|
|
126
|
+
|
|
127
|
+
let withDatas = [];
|
|
128
|
+
if (withFill?.withData && withFill?.withData.length > 0 && withDataFetch && typeof withDataFetch === 'function') {
|
|
129
|
+
for (let index = 0; index < withFill?.withData.length; index++) {
|
|
130
|
+
const element = withFill?.withData[index];
|
|
131
|
+
let params = {}
|
|
132
|
+
params.tableName = element.withTable.table_name;
|
|
133
|
+
params.filter = {};
|
|
134
|
+
for (let index = 0; index < element.withCondition.length; index++) {
|
|
135
|
+
const { value: condition_value, column: condition_column } = element.withCondition[index];
|
|
136
|
+
params.filter[condition_column.column_name] = getParamValue(condition_value.group_key, condition_value.field_key, fieldValues, withDatas);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const response = await withDataFetch(params);
|
|
140
|
+
if (response.code === 0 && response.data.list) {
|
|
141
|
+
withDatas.push({
|
|
142
|
+
id: element.id,
|
|
143
|
+
data: response.data.list
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let formula;
|
|
150
|
+
if (withFill.value && withFill.value.length > 0) {
|
|
151
|
+
formula = withFill.value.map(item => {
|
|
152
|
+
let result = "";
|
|
153
|
+
const { insert, attributes } = item;
|
|
154
|
+
if (typeof insert !== "string") {
|
|
155
|
+
if (insert?.span && attributes && attributes.tagKey && attributes.id) {
|
|
156
|
+
result = getParamValue(attributes.tagKey, attributes.id, fieldValues, withDatas);
|
|
157
|
+
if(result) result = `"${result}"`
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
result = insert;
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
console.log("formula", formula);
|
|
166
|
+
if (formula && formula.length > 0) {
|
|
167
|
+
const childIdentifier = child.props.componentId || child.props.__id;
|
|
168
|
+
const formulaResult = evalFormula(formula);
|
|
169
|
+
console.log("formulaResult", formulaResult);
|
|
170
|
+
console.log("handleFieldsWithFill setRows");
|
|
171
|
+
const newRows = [...rows]
|
|
172
|
+
newRows[rowIndex][childIdentifier] = formulaResult;
|
|
173
|
+
setPrevRows(newRows)
|
|
174
|
+
}
|
|
175
|
+
}, [rows])
|
|
176
|
+
|
|
177
|
+
const getParamValue = useCallback((tagKey, id, fieldValues, withDatas) => {
|
|
178
|
+
let result = "";
|
|
179
|
+
if (tagKey === "fieldsValue") result = fieldValues?.[id] || "";
|
|
180
|
+
else {
|
|
181
|
+
let withData = withDatas.find(item => item.id === tagKey);
|
|
182
|
+
if (withData && withData.data && withData.data.length > 0) {
|
|
183
|
+
result = withData.data[0]?.[id] || "";
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return result;
|
|
187
|
+
}, []);
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
const handleInputChange = useCallback((rowIndex, childIndex, e) => {
|
|
192
|
+
|
|
193
|
+
const newRows = [...rows];
|
|
194
|
+
newRows[rowIndex] = {
|
|
195
|
+
...newRows[rowIndex],
|
|
196
|
+
[childIndex]: e?.target?.value || '',
|
|
197
|
+
};
|
|
198
|
+
console.log("handleInputChange setRows")
|
|
199
|
+
setPrevRows(newRows);
|
|
200
|
+
|
|
201
|
+
setUpdateField({
|
|
202
|
+
rowIndex: rowIndex,
|
|
203
|
+
identifier: childIndex,
|
|
204
|
+
value: handleRowValues(newRows[rowIndex]),
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
}, [rows, handleFieldsWith, handleRowValues, onChange]);
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
const handleDeleteRow = (rowIndex) => {
|
|
211
|
+
const newRows = [...rows];
|
|
212
|
+
newRows.splice(rowIndex, 1);
|
|
213
|
+
console.log("handleDeleteRow setRows")
|
|
214
|
+
setPrevRows(newRows);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const addRow = () => {
|
|
218
|
+
console.log("addRow setRows")
|
|
219
|
+
setPrevRows([...rows, {}]);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
useEffect(() => {
|
|
223
|
+
console.log("rows changed rows", JSON.stringify(prevRowsRef.current));
|
|
224
|
+
console.log("rows changed value", JSON.stringify(value));
|
|
225
|
+
if (isEqual(prevRowsRef.current, value)) return;
|
|
226
|
+
console.log("noreq")
|
|
227
|
+
typeof onChange === "function" && onChange(prevRowsRef.current);
|
|
228
|
+
}, [rows]);
|
|
229
|
+
|
|
230
|
+
useEffect(() => {
|
|
231
|
+
if (updateField && updateField.identifier) {
|
|
232
|
+
handleFieldsWith(updateField.identifier, updateField.value, updateField.rowIndex);
|
|
233
|
+
}
|
|
234
|
+
}, [updateField])
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
return (
|
|
238
|
+
<>
|
|
239
|
+
<div className="fw-full fmin-h-20 foverflow-x-auto">
|
|
240
|
+
{rows.map((row, rowIndex) => (
|
|
241
|
+
<div className="fborder-b finline-flex fflex-wrap fmin-w-full" style={{ width: "max-content" }} key={rowIndex}>
|
|
242
|
+
{React.Children.map(children, (child, childIndex) => {
|
|
243
|
+
const col_id = child?.props?.__id || childIndex;
|
|
244
|
+
if (row?.[col_id] === undefined) row[col_id] = "";
|
|
245
|
+
return <TableCol width={200} key={`row_${rowIndex}_col_${childIndex}`}>
|
|
246
|
+
{React.cloneElement(child, {
|
|
247
|
+
key: `row_${rowIndex}_child_${childIndex}`,
|
|
248
|
+
subTable: true,
|
|
249
|
+
subTableIndex: rowIndex,
|
|
250
|
+
value: row[col_id] || '',
|
|
251
|
+
onChange: (e) => handleInputChange(rowIndex, col_id, e),
|
|
252
|
+
})}
|
|
253
|
+
</TableCol>
|
|
254
|
+
})}
|
|
255
|
+
<TableAction key={`row_${rowIndex}_action`} subTable={true} subTableIndex={rowIndex} label={"操作"}>
|
|
256
|
+
<DeleteOutlined className="fcursor-pointer" onClick={() => handleDeleteRow(rowIndex)} />
|
|
257
|
+
</TableAction>
|
|
258
|
+
</div>
|
|
259
|
+
))}
|
|
260
|
+
</div>
|
|
261
|
+
<Button onClick={addRow}>新增行</Button>
|
|
262
|
+
</>
|
|
263
|
+
);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
export default Table;
|
|
267
|
+
export { TableCol, TableAction };
|
|
@@ -22,8 +22,6 @@ const UploadImage = ({ maxCount, value, onChange, ...props }) => {
|
|
|
22
22
|
for (let i = 0; i < value.length; i++) {
|
|
23
23
|
let file = value[i]
|
|
24
24
|
var oldfile = fileMap.current.find((item) => item.uid === file.uid)
|
|
25
|
-
console.log("set file", file)
|
|
26
|
-
console.log("set oldfile", oldfile)
|
|
27
25
|
if (!oldfile ||( (oldfile.version||0) < (file.version||0 )))
|
|
28
26
|
_fileList.push(file)
|
|
29
27
|
else _fileList.push(oldfile)
|
|
@@ -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) {
|
|
@@ -16,7 +17,7 @@ function batchElements(elements, groupSize) {
|
|
|
16
17
|
for (const element of elements) {
|
|
17
18
|
const { _componentName } = element?.props || {};
|
|
18
19
|
|
|
19
|
-
if (_componentName && _componentName.startsWith('Layout')) {
|
|
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,151 @@ const FormContainer = forwardRef(({ cols = 1, children }, ref) => {
|
|
|
57
58
|
}, [children, cols]);
|
|
58
59
|
|
|
59
60
|
const initializeDependencyMap = () => {
|
|
61
|
+
console.log("initializeDependencyMap**********")
|
|
60
62
|
dependencyMap.current = new Map();
|
|
61
63
|
const childrenArray = React.Children.toArray(children);
|
|
62
64
|
|
|
63
65
|
childrenArray.forEach(child => {
|
|
64
66
|
const { componentId, __id, ...props } = child.props;
|
|
67
|
+
console.log("child.props**********", child.props)
|
|
65
68
|
const identifier = componentId || __id;
|
|
66
69
|
dependencyMap.current.set(identifier, {
|
|
67
|
-
children: childrenArray.filter(item => item.props.
|
|
70
|
+
children: childrenArray.filter(item => item.props.withId === identifier || item.props.withIds?.includes(identifier)),
|
|
68
71
|
show: true,
|
|
69
72
|
});
|
|
70
73
|
});
|
|
71
|
-
|
|
74
|
+
console.log("dependencyMap", dependencyMap.current)
|
|
72
75
|
initializeFieldVisibility();
|
|
73
76
|
};
|
|
74
77
|
|
|
75
|
-
//
|
|
78
|
+
// 初始化字段的级联关系
|
|
76
79
|
const initializeFieldVisibility = (reloadFields = false) => {
|
|
80
|
+
console.log("initializeFieldVisibility**********")
|
|
77
81
|
const fieldValues = form.getFieldsValue();
|
|
78
82
|
for (let key of dependencyMap.current.keys()) {
|
|
79
|
-
|
|
83
|
+
handleFieldsWith(key, fieldValues);
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
if (reloadFields) setFormContent(renderChildren());
|
|
83
87
|
};
|
|
84
88
|
|
|
85
|
-
//
|
|
86
|
-
const
|
|
89
|
+
// 计算字段级联关系
|
|
90
|
+
const handleFieldsWith = (identifier, fieldValues) => {
|
|
87
91
|
let needRefresh = false;
|
|
88
92
|
if (dependencyMap.current.has(identifier)) {
|
|
89
93
|
const dependentChildren = dependencyMap.current.get(identifier).children;
|
|
90
94
|
dependentChildren.forEach(child => {
|
|
91
|
-
if (child.props.
|
|
92
|
-
|
|
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
|
-
}
|
|
95
|
+
if (child.props.withFunc && typeof child.props.withFunc === 'function') {
|
|
96
|
+
needRefresh = handleFieldsVisible(fieldValues, child)
|
|
102
97
|
}
|
|
98
|
+
|
|
99
|
+
if (child.props.withFill)
|
|
100
|
+
handleFieldsWithFill(fieldValues, child)
|
|
101
|
+
|
|
103
102
|
});
|
|
104
103
|
}
|
|
105
104
|
return needRefresh;
|
|
106
105
|
};
|
|
107
106
|
|
|
107
|
+
// 处理级联显示隐藏 @return {boolean} 是否需要重新渲染表单的字段
|
|
108
|
+
const handleFieldsVisible = (fieldValues, child) => {
|
|
109
|
+
let needRefresh = false;
|
|
110
|
+
const childShouldBeVisible = child.props.withFunc(fieldValues);
|
|
111
|
+
const childIdentifier = child.props.componentId || child.props.__id;
|
|
112
|
+
if (dependencyMap.current.has(childIdentifier)) {
|
|
113
|
+
const childData = dependencyMap.current.get(childIdentifier);
|
|
114
|
+
if (childData.show !== childShouldBeVisible) {
|
|
115
|
+
childData.show = childShouldBeVisible;
|
|
116
|
+
dependencyMap.current.set(childIdentifier, childData);
|
|
117
|
+
needRefresh = true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return needRefresh
|
|
121
|
+
}
|
|
122
|
+
// 处理级联数据源
|
|
123
|
+
// 处理级联填充
|
|
124
|
+
const handleFieldsWithFill = async (fieldValues, child) => {
|
|
125
|
+
const withFill = child.props.withFill;
|
|
126
|
+
const withDataFetch = child.props.withDataFetch;
|
|
127
|
+
console.log("withFill", withFill)
|
|
128
|
+
console.log("fieldValues", fieldValues)
|
|
129
|
+
console.log("child", child)
|
|
130
|
+
|
|
131
|
+
let withDatas = [];
|
|
132
|
+
// 先处理依赖数据
|
|
133
|
+
if (withFill?.withData && withFill?.withData.length > 0 && withDataFetch && typeof withDataFetch === 'function') {
|
|
134
|
+
for (let index = 0; index < withFill?.withData.length; index++) {
|
|
135
|
+
const element = withFill?.withData[index];
|
|
136
|
+
let params = {}
|
|
137
|
+
params.tableName = element.withTable.table_name
|
|
138
|
+
params.filter = {}
|
|
139
|
+
for (let index = 0; index < element.withCondition.length; index++) {
|
|
140
|
+
const { value: condition_value, column: condition_column } = element.withCondition[index];
|
|
141
|
+
params.filter[condition_column.column_name] = getParamValue(condition_value.group_key, condition_value.field_key, fieldValues, withDatas)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 访问接口获取数据
|
|
145
|
+
const response = await withDataFetch(params)
|
|
146
|
+
if (response.code === 0 && response.data.list) {
|
|
147
|
+
withDatas.push({
|
|
148
|
+
id: element.id,
|
|
149
|
+
data: response.data.list
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 构造计算公式
|
|
156
|
+
let formula;
|
|
157
|
+
if (withFill.value && withFill.value.length > 0) {
|
|
158
|
+
formula = withFill.value.map(item => {
|
|
159
|
+
let result = "";
|
|
160
|
+
const { insert, attributes } = item
|
|
161
|
+
if (typeof insert !== "string") {
|
|
162
|
+
if (insert?.span && attributes && attributes.tagKey && attributes.id) {
|
|
163
|
+
result = getParamValue(attributes.tagKey, attributes.id, fieldValues, withDatas)
|
|
164
|
+
if (result) result = `"${result}"`
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else result = insert
|
|
168
|
+
return result
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (formula && formula.length > 0) {
|
|
173
|
+
const childIdentifier = child.props.componentId || child.props.__id;
|
|
174
|
+
form.setFieldValue(childIdentifier, evalFormula(formula))
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const getParamValue = (tagKey, id, fieldValues, withDatas) => {
|
|
179
|
+
let result = "";
|
|
180
|
+
// 从当前表单字段取值
|
|
181
|
+
if (tagKey == "fieldsValue") result = fieldValues?.[id] || ""
|
|
182
|
+
// 从依赖数据取值
|
|
183
|
+
else {
|
|
184
|
+
let withData = withDatas.find(item => item.id === tagKey)
|
|
185
|
+
if (withData && withData.data && withData.data.length > 0) {
|
|
186
|
+
// 暂时只取一条数据,后续再想 sum 函数等问题
|
|
187
|
+
result = withData.data[0]?.[id] || ""
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return result
|
|
191
|
+
}
|
|
192
|
+
|
|
108
193
|
const handleFieldsChange = debounce((changedFields, allFields) => {
|
|
109
194
|
const fieldValues = form.getFieldsValue();
|
|
110
195
|
let needRefresh = false;
|
|
111
196
|
changedFields.forEach(field => {
|
|
112
197
|
if (field.name && field.name.length > 0) {
|
|
113
|
-
needRefresh =
|
|
198
|
+
needRefresh = handleFieldsWith(field.name[0], fieldValues);
|
|
114
199
|
}
|
|
115
200
|
});
|
|
116
201
|
|
|
117
202
|
if (needRefresh) {
|
|
118
203
|
setFormContent(renderChildren());
|
|
119
204
|
}
|
|
120
|
-
},
|
|
205
|
+
}, 200);
|
|
121
206
|
|
|
122
207
|
const renderChildren = () => {
|
|
123
208
|
const childrenArray = React.Children.toArray(children);
|
|
@@ -129,12 +214,12 @@ const FormContainer = forwardRef(({ cols = 1, children }, ref) => {
|
|
|
129
214
|
cols
|
|
130
215
|
);
|
|
131
216
|
|
|
132
|
-
return groupedChildren.map((group,index) => (
|
|
217
|
+
return groupedChildren.map((group, index) => (
|
|
133
218
|
<Row key={`row-${index}`} gutter={[24, 24]}>
|
|
134
219
|
{group.map((child, index) => {
|
|
135
220
|
const { componentId, __id, _componentName, ...props } = child.props;
|
|
136
221
|
const identifier = componentId || __id;
|
|
137
|
-
const isLayoutComponent = _componentName && _componentName.startsWith('Layout');
|
|
222
|
+
const isLayoutComponent = _componentName && _componentName.startsWith('Layout.');
|
|
138
223
|
|
|
139
224
|
return (
|
|
140
225
|
<Col key={identifier || `col-${index}`} span={isLayoutComponent ? 24 : 24 / group.length} style={{ marginBottom: 0 }}>
|
|
@@ -168,7 +253,7 @@ export function withWrap(Component) {
|
|
|
168
253
|
return forwardRef((props, ref) => <Component {...props} ref={ref} forwardedRef={ref} />);
|
|
169
254
|
}
|
|
170
255
|
|
|
171
|
-
export class FormContainerClass extends React.PureComponent{
|
|
256
|
+
export class FormContainerClass extends React.PureComponent {
|
|
172
257
|
render() {
|
|
173
258
|
const { forwardedRef, ...otherProps } = this.props;
|
|
174
259
|
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
|
|
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;
|