lu-lowcode-package-form 0.11.51 → 0.11.54
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 +279 -277
- package/dist/index.es.js +25709 -24120
- package/package.json +1 -1
- package/src/components/field/table/drag-head.jsx +121 -0
- package/src/components/field/table/index.jsx +159 -141
- package/src/components/form-container/index.jsx +15 -2
- package/src/components/index.jsx +2 -1
package/package.json
CHANGED
@@ -0,0 +1,121 @@
|
|
1
|
+
import React, { useRef, useState, useEffect } from "react"
|
2
|
+
import { eventEmitter } from "../../../utils/events"
|
3
|
+
import { createPortal } from "react-dom"
|
4
|
+
import { Resizable } from "react-resizable"
|
5
|
+
|
6
|
+
const DragHead = ({ children, changeWidth, ...props }) => {
|
7
|
+
const [headWidths, setHeadWidths] = useState([])
|
8
|
+
const headWidthsRef = useRef([])
|
9
|
+
const [isDragging, setIsDragging] = useState(false)
|
10
|
+
const [resizingColumn, setResizingColumn] = useState(null)
|
11
|
+
const [dragPosition, setDragPosition] = useState(0)
|
12
|
+
const startPositionRef = useRef(0)
|
13
|
+
|
14
|
+
|
15
|
+
const getColumnWidth = (index) => {
|
16
|
+
return headWidths[index] || 150
|
17
|
+
}
|
18
|
+
|
19
|
+
// 处理拖动开始
|
20
|
+
const onResizeStart = (index) => {
|
21
|
+
return (e, data) => {
|
22
|
+
e.stopPropagation()
|
23
|
+
setIsDragging(true)
|
24
|
+
setResizingColumn(index)
|
25
|
+
setDragPosition(e.clientX)
|
26
|
+
startPositionRef.current = e.clientX
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
// 处理拖动中
|
31
|
+
const onResize = (index) => {
|
32
|
+
return (e, { size }) => {
|
33
|
+
e.stopPropagation()
|
34
|
+
// 只在拖动过程中更新虚拟指示线位置
|
35
|
+
setDragPosition(e.clientX)
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
// 处理拖动结束
|
40
|
+
const onResizeStop = (index) => {
|
41
|
+
return (e, { size }) => {
|
42
|
+
// 更新列宽
|
43
|
+
const newHeadWidths = [...headWidthsRef.current]
|
44
|
+
const delta = e.clientX - startPositionRef.current
|
45
|
+
const oldWidth = headWidths[index] || 150
|
46
|
+
const newWidth = Math.max(50, oldWidth + delta)
|
47
|
+
newHeadWidths[index] = newWidth
|
48
|
+
headWidthsRef.current = newHeadWidths
|
49
|
+
setHeadWidths(newHeadWidths)
|
50
|
+
typeof changeWidth === 'function' && changeWidth(newHeadWidths)
|
51
|
+
eventEmitter.emit('changeSubTableColumnWidth', newHeadWidths)
|
52
|
+
// 重置拖动状态
|
53
|
+
setIsDragging(false)
|
54
|
+
setResizingColumn(null)
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
// 虚拟指示线组件
|
59
|
+
const DragIndicator = () => {
|
60
|
+
if (!isDragging) return null
|
61
|
+
|
62
|
+
const style = {
|
63
|
+
position: 'fixed',
|
64
|
+
top: 0,
|
65
|
+
left: `${dragPosition}px`,
|
66
|
+
width: '2px',
|
67
|
+
height: '100vh',
|
68
|
+
backgroundColor: '#1890ff',
|
69
|
+
pointerEvents: 'none',
|
70
|
+
zIndex: 9999
|
71
|
+
}
|
72
|
+
|
73
|
+
return createPortal(
|
74
|
+
<div style={style}></div>,
|
75
|
+
document.body
|
76
|
+
)
|
77
|
+
}
|
78
|
+
|
79
|
+
return <><div className="fflex flex-nowrap fmin-w-full fabsolute">
|
80
|
+
{React.Children.map(children, (child, childIndex) => {
|
81
|
+
const width = getColumnWidth(childIndex)
|
82
|
+
|
83
|
+
return (
|
84
|
+
<Resizable
|
85
|
+
key={childIndex}
|
86
|
+
width={width}
|
87
|
+
height={0} // 高度不用调整,设为0
|
88
|
+
onResizeStart={onResizeStart(childIndex)}
|
89
|
+
onResize={onResize(childIndex)}
|
90
|
+
onResizeStop={onResizeStop(childIndex)}
|
91
|
+
handle={
|
92
|
+
<div
|
93
|
+
className="react-resizable-handle react-resizable-handle-e"
|
94
|
+
style={{
|
95
|
+
position: 'absolute',
|
96
|
+
right: 0,
|
97
|
+
top: 0,
|
98
|
+
height: '100%',
|
99
|
+
width: '8px',
|
100
|
+
cursor: 'col-resize',
|
101
|
+
zIndex: 1
|
102
|
+
}}
|
103
|
+
/>
|
104
|
+
}
|
105
|
+
resizeHandles={['e']} // 只允许从右侧拖动调整宽度
|
106
|
+
>
|
107
|
+
<div
|
108
|
+
className="fflex-1 fh-12 fflex fitems-center fpx-1 frelative"
|
109
|
+
style={{minWidth: width}}
|
110
|
+
>
|
111
|
+
|
112
|
+
</div>
|
113
|
+
</Resizable>
|
114
|
+
)
|
115
|
+
})}
|
116
|
+
<div className="fsticky fright-0 fborder-b" style={{ boxShadow: "rgba(50, 50, 50, 0.15) -6px 0px 6px -6px", flex: "0 0 50px", width: "50px" }}></div>
|
117
|
+
</div>
|
118
|
+
<DragIndicator /></>
|
119
|
+
}
|
120
|
+
|
121
|
+
export default DragHead
|
@@ -1,16 +1,17 @@
|
|
1
1
|
import React, { useEffect, useRef, useState } from "react";
|
2
|
-
import { Button, Form, Input,Popconfirm } from "antd";
|
2
|
+
import { Button, Form, Input, Popconfirm } from "antd";
|
3
3
|
import { CopyOutlined, DeleteOutlined } from "@ant-design/icons";
|
4
4
|
import { BaseWrapper } from "../base.jsx"
|
5
5
|
import { nanoid } from "nanoid";
|
6
6
|
import { eventEmitter } from '../../../utils/events'
|
7
7
|
import { useMemoizedFn } from 'ahooks';
|
8
|
+
import DragHead from "./drag-head"
|
8
9
|
|
9
10
|
const TableAction = ({ label, subTableIndex, children, subTableHead = false, ...props }) => {
|
10
11
|
//fsticky fright-0
|
11
12
|
return <div className="fsticky fright-0 fbg-white fborder-b " style={{
|
12
13
|
boxShadow: '-6px 0 6px -6px rgba(50,50,50,0.15)',
|
13
|
-
flex: '0 0 50px',
|
14
|
+
flex: '0 0 50px',
|
14
15
|
width: '50px'
|
15
16
|
}}>
|
16
17
|
<div className="frelative fw-full fh-full fflex fflex-col foverflow-hidden">
|
@@ -22,7 +23,7 @@ const TableAction = ({ label, subTableIndex, children, subTableHead = false, ...
|
|
22
23
|
</div>
|
23
24
|
}
|
24
25
|
|
25
|
-
const RowID = ({value,onChange
|
26
|
+
const RowID = ({ value, onChange, ...props }) => {
|
26
27
|
useEffect(() => {
|
27
28
|
if (!value) onChange(nanoid())
|
28
29
|
}, [value])
|
@@ -42,10 +43,16 @@ const TableCol = ({ children, width, hidden, ...props }) => {
|
|
42
43
|
</div>
|
43
44
|
}
|
44
45
|
|
45
|
-
const Table = ({ children, onTableAddRow, disabled, readonly, onTableRemoveRow, form, fieldName, initializeFormRender, recordFieldsChange, getTableWithIds,removeLastFieldsValues, mode, isAllowCopy=false, isAllowAdd=true,getDependencyMapItem, ...props }) => {
|
46
|
+
const Table = ({ children, onTableAddRow, disabled, readonly, onTableRemoveRow, form, fieldName, initializeFormRender, recordFieldsChange, getTableWithIds, removeLastFieldsValues, mode, isAllowCopy = false, isAllowAdd = true, getDependencyMapItem, ...props }) => {
|
46
47
|
useEffect(() => {
|
47
48
|
// console.log("Table form reload", form)
|
48
49
|
}, [form])
|
50
|
+
|
51
|
+
useEffect(() => {
|
52
|
+
console.log("Table props", props)
|
53
|
+
}, [props])
|
54
|
+
|
55
|
+
const [headWidths, setHeadWidths] = useState([])
|
49
56
|
const tableComponentId = props.componentId || props.__id
|
50
57
|
const newidRefs = useRef(React.Children.map(children, () => nanoid()));
|
51
58
|
const [init, setInit] = useState(false);
|
@@ -68,8 +75,15 @@ const Table = ({ children, onTableAddRow, disabled, readonly, onTableRemoveRow,
|
|
68
75
|
return () => {
|
69
76
|
eventEmitter.off('reloadTable', handleReloadTable);
|
70
77
|
}
|
71
|
-
|
72
78
|
}, [])
|
79
|
+
|
80
|
+
|
81
|
+
const getColumnWidth = (index) => {
|
82
|
+
return headWidths[index] || 150
|
83
|
+
}
|
84
|
+
const handleChangeWidth = (newHeadWidths) => {
|
85
|
+
setHeadWidths(newHeadWidths)
|
86
|
+
}
|
73
87
|
const getAllWithIds = () => {
|
74
88
|
if (typeof getTableWithIds === 'function') {
|
75
89
|
return getTableWithIds(childrenIds)
|
@@ -84,9 +98,9 @@ const Table = ({ children, onTableAddRow, disabled, readonly, onTableRemoveRow,
|
|
84
98
|
}
|
85
99
|
return true
|
86
100
|
}
|
87
|
-
const handleCopy = useMemoizedFn((index)=>{
|
101
|
+
const handleCopy = useMemoizedFn((index) => {
|
88
102
|
let tableValues = form.getFieldValue(fieldName)
|
89
|
-
const copyRow = {...tableValues[index],__id:nanoid()}
|
103
|
+
const copyRow = { ...tableValues[index], __id: nanoid() }
|
90
104
|
tableValues.splice(index + 1, 0, copyRow)
|
91
105
|
form?.setFieldValue(fieldName, tableValues)
|
92
106
|
|
@@ -95,159 +109,163 @@ const Table = ({ children, onTableAddRow, disabled, readonly, onTableRemoveRow,
|
|
95
109
|
for (let i = index + 1; i < tableValues.length; i++) {
|
96
110
|
let value = tableValues[i]
|
97
111
|
for (let key in value) {
|
98
|
-
let changedFieldName = [tableName,i,key]
|
99
|
-
changedFields[changedFieldName] =
|
112
|
+
let changedFieldName = [tableName, i, key]
|
113
|
+
changedFields[changedFieldName] = { name: changedFieldName, value: value[key] }
|
100
114
|
}
|
101
115
|
}
|
102
|
-
typeof recordFieldsChange == "function" && recordFieldsChange(changedFields,true)
|
116
|
+
typeof recordFieldsChange == "function" && recordFieldsChange(changedFields, true)
|
103
117
|
})
|
104
118
|
|
105
|
-
const handleRemove = useMemoizedFn((index)=>{
|
119
|
+
const handleRemove = useMemoizedFn((index) => {
|
106
120
|
let tableValues = form.getFieldValue(fieldName)
|
107
121
|
tableValues.splice(index, 1)
|
108
|
-
form?.setFieldValue(fieldName, tableValues)
|
122
|
+
form?.setFieldValue(fieldName, tableValues)
|
109
123
|
typeof onTableRemoveRow === "function" && onTableRemoveRow(childrenIds);
|
110
|
-
typeof removeLastFieldsValues === "function" && removeLastFieldsValues(`${name},${index}`,true)
|
124
|
+
typeof removeLastFieldsValues === "function" && removeLastFieldsValues(`${name},${index}`, true)
|
111
125
|
})
|
112
126
|
if (props.isRequired)
|
113
127
|
rules.push({ required: true, message: `子表[${props.label}]必须填写` });
|
114
|
-
return <
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
<div className="fw-full
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
{hidden ? null : React.cloneElement(child, {
|
124
|
-
key: `row_${0}_child_${childIndex}`,
|
125
|
-
subTable: true,
|
126
|
-
subTableHead: true,
|
127
|
-
subTableContent: false,
|
128
|
-
})}
|
129
|
-
</TableCol>
|
130
|
-
})}
|
131
|
-
{disabled != true && readonly != true && <TableAction subTableHead={true} key={`row_${0}_action`} subTable={true} subTableIndex={0} label={"操作"}>
|
132
|
-
</TableAction>}
|
133
|
-
</div>}
|
134
|
-
{fields.map((field, index) => (
|
135
|
-
<div key={`${tableId}.${field.key}`} className=" fflex flex-nowrap fmin-w-full ">
|
136
|
-
<Form.Item hidden={true} name={[field.name, "__id"]}>
|
137
|
-
<RowID />
|
138
|
-
</Form.Item>
|
128
|
+
return <div className="fw-full fflex fflex-col fgap-2">
|
129
|
+
<Form.List name={name} rules={rules}>
|
130
|
+
{(fields, { add, remove }) => {
|
131
|
+
if (fields.length === 0 && !init) handleAdd();
|
132
|
+
return <div className="fw-full ">
|
133
|
+
|
134
|
+
<div className="fw-full frelative fmin-h-20 foverflow-x-auto" style={{ position: 'relative' }}>
|
135
|
+
<DragHead changeWidth={handleChangeWidth}>{children}</DragHead>
|
136
|
+
{fields.length === 0 && <div key={`tableHead`} className="fborder-b fflex flex-nowrap fmin-w-full ">
|
139
137
|
{React.Children.map(children, (child, childIndex) => {
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
138
|
+
const hidden = (child?.props?.calcHidden || !getDependencyMapShow(child?.props?.componentId || child?.props?.__id)) && mode != "desgin";
|
139
|
+
return <TableCol width={getColumnWidth(childIndex)} key={`row_${0}_col_${childIndex}`} hidden={hidden}>
|
140
|
+
{hidden ? null : React.cloneElement(child, {
|
141
|
+
key: `row_${0}_child_${childIndex}`,
|
142
|
+
subTable: true,
|
143
|
+
subTableHead: true,
|
144
|
+
subTableContent: false,
|
145
|
+
})}
|
146
|
+
</TableCol>
|
147
|
+
})}
|
148
|
+
{disabled != true && readonly != true && <TableAction subTableHead={true} key={`row_${0}_action`} subTable={true} subTableIndex={0} label={"操作"}>
|
149
|
+
</TableAction>}
|
150
|
+
</div>}
|
151
|
+
{fields.map((field, index) => (
|
152
|
+
<div key={`${tableId}.${field.key}`} className=" fflex flex-nowrap fmin-w-full ">
|
153
|
+
<Form.Item hidden={true} name={[field.name, "__id"]}>
|
154
|
+
<RowID />
|
155
|
+
</Form.Item>
|
156
|
+
{React.Children.map(children, (child, childIndex) => {
|
157
|
+
let { props } = child;
|
158
|
+
const col_id = child?.props?.componentId || child?.props?.__id || childIndex;
|
159
|
+
// if (field?.[col_id] === undefined) field[col_id] = "";
|
160
|
+
const rules = []
|
161
|
+
if (props.isRequired)
|
162
|
+
rules.push({ required: true, message: `${props.label}必须填写` });
|
163
|
+
if (props.rules)
|
164
|
+
if (Array.isArray(props.rules)) {
|
165
|
+
const pattern = props.rules.join("|")
|
166
|
+
rules.push({ pattern: new RegExp(pattern), message: props.rulesFailMessage ? props.rulesFailMessage : `${props.label}格式错误` })
|
167
|
+
}
|
168
|
+
else {
|
169
|
+
rules.push({ pattern: new RegExp(props.rules), message: props.rulesFailMessage ? props.rulesFailMessage : `${props.label}格式错误` })
|
170
|
+
}
|
154
171
|
|
155
|
-
|
156
|
-
|
157
|
-
|
172
|
+
const { componentId, __id, _componentName, ...otherProps } = child.props;
|
173
|
+
const componentName = child.type?.displayName || _componentName;
|
174
|
+
const identifier = componentId || __id;
|
158
175
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
176
|
+
const hidden = (props.calcHidden || !getDependencyMapShow(identifier)) && mode != "desgin";
|
177
|
+
return <TableCol width={getColumnWidth(childIndex)} key={`row_${field.key}_col_${childIndex}`} hidden={hidden}>
|
178
|
+
<Form.Item
|
179
|
+
style={{ margin: 0 }}
|
180
|
+
hidden={hidden}
|
181
|
+
shouldUpdate={(prevValues, curValues) => {
|
182
|
+
let result = false;
|
183
|
+
if (
|
184
|
+
(componentName === "Field.WithSingleSelect" || componentName === "Field.WithMultipleSelect") &&
|
185
|
+
Array.isArray(otherProps.filterRules) &&
|
186
|
+
otherProps.filterRules.length > 0
|
187
|
+
) {
|
188
|
+
// 验证关联表字段是否需要重新渲染
|
189
|
+
for (let rule of otherProps.filterRules) {
|
190
|
+
let prevFieldValue, curFieldValue;
|
191
|
+
if (rule.valueType != "variable") continue
|
192
|
+
if ("parent" in rule?.value && rule.value.parent != "") {
|
193
|
+
prevFieldValue = prevValues?.[rule?.value?.parent]?.[field.name]?.[rule?.value?.field_key];
|
194
|
+
curFieldValue = curValues?.[rule?.value?.parent]?.[field.name]?.[rule?.value?.field_key];
|
195
|
+
} else {
|
196
|
+
prevFieldValue = prevValues?.[rule.value.field_key];
|
197
|
+
curFieldValue = curValues?.[rule.value.field_key];
|
198
|
+
}
|
182
199
|
|
183
|
-
|
184
|
-
|
185
|
-
|
200
|
+
if (prevFieldValue !== curFieldValue) {
|
201
|
+
result = true;
|
202
|
+
break;
|
203
|
+
}
|
186
204
|
}
|
187
205
|
}
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
206
|
+
if (result) {
|
207
|
+
newidRefs.current[childIndex] = nanoid();
|
208
|
+
console.log("newidRefs.current[childIndex]", newidRefs.current[childIndex])
|
209
|
+
}
|
210
|
+
return result;
|
211
|
+
}}
|
212
|
+
>
|
213
|
+
{({ getFieldsValue }) => {
|
214
|
+
const fieldsValue = getFieldsValue();
|
215
|
+
// const newid = nanoid()
|
216
|
+
// console.log(`[${child.props.label}] key`,`row_${field.key}_child_${childIndex}_${newidRefs.current[childIndex]}` )
|
217
|
+
return <Form.Item
|
218
|
+
label=""
|
219
|
+
style={{ marginBottom: 0 }}
|
220
|
+
name={[field.name, col_id]}
|
221
|
+
rules={rules}
|
222
|
+
>
|
223
|
+
{React.cloneElement(child, {
|
224
|
+
// key: `row_${field.key}_child_${childIndex}_${newidRefs.current[childIndex]}`,
|
225
|
+
key: `row_${field.key}_child_${childIndex}`,
|
226
|
+
subTable: true,
|
227
|
+
subTableIndex: index,
|
228
|
+
subTableHead: index === 0,
|
229
|
+
form,
|
230
|
+
shouldUpdateKey: newidRefs.current[childIndex],
|
231
|
+
fieldName: [fieldName, field.name, col_id],
|
232
|
+
fieldsValue: fieldsValue,
|
233
|
+
initializeFormRender,
|
234
|
+
recordFieldsChange,
|
235
|
+
getAllWithIds: getAllWithIds,
|
236
|
+
removeLastFieldsValues
|
237
|
+
})}
|
238
|
+
</Form.Item>
|
239
|
+
}}
|
240
|
+
</Form.Item>
|
241
|
+
|
242
|
+
</TableCol>
|
243
|
+
})}
|
244
|
+
{disabled != true && readonly != true && <TableAction subTableHead={index == 0} key={`row_${index}_action`} subTable={true} subTableIndex={index} label={"操作"}>
|
245
|
+
{isAllowCopy && <CopyOutlined className="fcursor-pointer" onClick={() => handleCopy(index)} />}
|
246
|
+
<Popconfirm
|
247
|
+
title="删除确认"
|
248
|
+
description="确定要删除这一行吗?"
|
249
|
+
onConfirm={() => {
|
250
|
+
handleRemove(index)
|
194
251
|
}}
|
252
|
+
okText="确定"
|
253
|
+
cancelText="取消"
|
195
254
|
>
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
{React.cloneElement(child, {
|
207
|
-
// key: `row_${field.key}_child_${childIndex}_${newidRefs.current[childIndex]}`,
|
208
|
-
key: `row_${field.key}_child_${childIndex}`,
|
209
|
-
subTable: true,
|
210
|
-
subTableIndex: index,
|
211
|
-
subTableHead: index === 0,
|
212
|
-
form,
|
213
|
-
shouldUpdateKey: newidRefs.current[childIndex],
|
214
|
-
fieldName: [fieldName, field.name, col_id],
|
215
|
-
fieldsValue: fieldsValue,
|
216
|
-
initializeFormRender,
|
217
|
-
recordFieldsChange,
|
218
|
-
getAllWithIds: getAllWithIds,
|
219
|
-
removeLastFieldsValues
|
220
|
-
})}
|
221
|
-
</Form.Item>
|
222
|
-
}}
|
223
|
-
</Form.Item>
|
224
|
-
|
225
|
-
</TableCol>
|
226
|
-
})}
|
227
|
-
{disabled != true && readonly != true && <TableAction subTableHead={index == 0} key={`row_${index}_action`} subTable={true} subTableIndex={index} label={"操作"}>
|
228
|
-
{isAllowCopy && <CopyOutlined className="fcursor-pointer" onClick={()=>handleCopy(index)} />}
|
229
|
-
<Popconfirm
|
230
|
-
title="删除确认"
|
231
|
-
description="确定要删除这一行吗?"
|
232
|
-
onConfirm={() => {
|
233
|
-
handleRemove(index)
|
234
|
-
}}
|
235
|
-
okText="确定"
|
236
|
-
cancelText="取消"
|
237
|
-
>
|
238
|
-
<DeleteOutlined className="fcursor-pointer ftext-red-500" />
|
239
|
-
</Popconfirm>
|
240
|
-
</TableAction>}
|
241
|
-
</div>
|
242
|
-
))}
|
255
|
+
<DeleteOutlined className="fcursor-pointer ftext-red-500" />
|
256
|
+
</Popconfirm>
|
257
|
+
</TableAction>}
|
258
|
+
</div>
|
259
|
+
))}
|
260
|
+
</div>
|
261
|
+
{disabled != true && readonly != true && isAllowAdd && <Button onClick={() => {
|
262
|
+
add({ key: nanoid(), })
|
263
|
+
typeof onTableAddRow === "function" && onTableAddRow(childrenIds);
|
264
|
+
}} className="fmy-2">新增一行</Button>}
|
243
265
|
</div>
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
}} className="fmy-2">新增一行</Button>}
|
248
|
-
</div>
|
249
|
-
}}
|
250
|
-
</Form.List>
|
266
|
+
}}
|
267
|
+
</Form.List>
|
268
|
+
</div>
|
251
269
|
}
|
252
270
|
|
253
271
|
Table.displayName = "Table"
|
@@ -73,6 +73,8 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
73
73
|
currentCycleId: 0,
|
74
74
|
// 当前更新周期的依赖路径
|
75
75
|
updatePath: [],
|
76
|
+
// 最大更新深度限制,避免过深的嵌套引起栈溢出
|
77
|
+
MAX_DEPTH: 30,
|
76
78
|
// 开始新的更新周期
|
77
79
|
startNewCycle: function () {
|
78
80
|
this.currentCycleId++;
|
@@ -81,10 +83,18 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
81
83
|
},
|
82
84
|
// 添加依赖路径
|
83
85
|
addToPath: function (fieldId) {
|
84
|
-
|
86
|
+
// 限制依赖路径深度,防止栈溢出
|
87
|
+
if (this.updatePath.length >= this.MAX_DEPTH) {
|
88
|
+
console.warn(`依赖路径深度超过限制(${this.MAX_DEPTH}),可能存在过深嵌套`);
|
89
|
+
return;
|
90
|
+
}
|
91
|
+
if (fieldId) {
|
92
|
+
this.updatePath.push(fieldId);
|
93
|
+
}
|
85
94
|
},
|
86
95
|
// 检查是否形成循环
|
87
96
|
hasCircularDependency: function (targetFieldId) {
|
97
|
+
if (!targetFieldId) return false;
|
88
98
|
return this.updatePath.includes(targetFieldId);
|
89
99
|
},
|
90
100
|
// 获取当前依赖路径
|
@@ -232,6 +242,10 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
232
242
|
|
233
243
|
// 计算字段级联关系
|
234
244
|
const handleFieldsWith = async (identifier, fieldValues, init = false, fieldId = null) => {
|
245
|
+
if (mode == "desgin") {
|
246
|
+
console.log("设计模式下不进行字段级联计算")
|
247
|
+
return false
|
248
|
+
}
|
235
249
|
// console.log("handleFieldsWith identifier", identifier)
|
236
250
|
let needRefresh = false;
|
237
251
|
let parentIdentifier = [];
|
@@ -734,7 +748,6 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
734
748
|
}
|
735
749
|
lastFormValues.current[field.name] = field.value;
|
736
750
|
}
|
737
|
-
else console.log(`重复的field`, field.name)
|
738
751
|
}
|
739
752
|
if (needRefresh) {
|
740
753
|
console.log("needRefresh", needRefresh)
|
package/src/components/index.jsx
CHANGED
@@ -73,4 +73,5 @@ export * from './editor'
|
|
73
73
|
export * from "./wangEditor"
|
74
74
|
export * from "./wangEditorNext"
|
75
75
|
export * from "./sortList"
|
76
|
-
export * from "./TinyMCEEditor"
|
76
|
+
export * from "./TinyMCEEditor"
|
77
|
+
export {eventEmitter as packageFormEventEmitter} from "../utils/events"
|