@cloudbase/weda-ui 3.22.3 → 3.23.0
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/configs/components/wd-tabbar.d.ts +16 -0
- package/dist/configs/components/wd-tabbar.js +6 -0
- package/dist/configs/components/wd-table.d.ts +1 -0
- package/dist/configs/components/wd-table.js +14 -1
- package/dist/configs/components/wd-upload-image.js +1 -1
- package/dist/configs/index.d.ts +34 -0
- package/dist/style/index.css +27 -0
- package/dist/style/index.scss +1 -1
- package/dist/style/weda-ui.min.css +2 -2
- package/dist/web/components/form-input-hooks/index.d.ts +0 -1
- package/dist/web/components/form-input-hooks/index.js +8 -14
- package/dist/web/components/wd-form/contexts/form-field-context.d.ts +6 -2
- package/dist/web/components/wd-form/contexts/form-field-context.js +18 -2
- package/dist/web/components/wd-form/contexts/form-field-obj-context.d.ts +2 -2
- package/dist/web/components/wd-form/contexts/form-field-obj-context.js +2 -2
- package/dist/web/components/wd-form/hoc/form-container-decorator.d.ts +11 -0
- package/dist/web/components/wd-form/hoc/form-container-decorator.js +61 -0
- package/dist/web/components/wd-form/index.d.ts +4 -49
- package/dist/web/components/wd-form/index.js +53 -70
- package/dist/web/components/wd-form-obj/base-form-obj.d.ts +5 -1
- package/dist/web/components/wd-form-obj/base-form-obj.js +19 -38
- package/dist/web/components/wd-input/wd-input.d.ts +2 -0
- package/dist/web/components/wd-input/wd-input.js +70 -18
- package/dist/web/components/wd-input-number/wd-input-number.js +15 -15
- package/dist/web/components/wd-tabbar/wd-tabbar.js +4 -6
- package/dist/web/components/wd-table/components/FieldRender/index.d.ts +9 -1
- package/dist/web/components/wd-table/components/FieldRender/index.js +33 -4
- package/dist/web/components/wd-table/components/FilterFieldsPanel/Fields.d.ts +3 -1
- package/dist/web/components/wd-table/components/FilterFieldsPanel/Fields.js +7 -3
- package/dist/web/components/wd-table/components/FilterFieldsPanel/FilterFieldItem.js +4 -1
- package/dist/web/components/wd-table/components/FilterFieldsPanel/filterFieldsGenerate.d.ts +6 -15
- package/dist/web/components/wd-table/components/FilterFieldsPanel/filterFieldsGenerate.js +47 -16
- package/dist/web/components/wd-table/components/FilterFieldsPanel/index.js +15 -5
- package/dist/web/components/wd-table/utils/index.d.ts +5 -2
- package/dist/web/components/wd-table/utils/index.js +12 -1
- package/dist/web/components/wd-table/wd-table.d.ts +5 -19
- package/dist/web/components/wd-table/wd-table.js +22 -2
- package/dist/web/components/wd-tree/utils.js +1 -1
- package/dist/web/utils/hooks/useFormLegacy.js +5 -12
- package/package.json +5 -5
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useState, useCallback } from 'react';
|
|
3
|
+
import lodashSet from 'lodash.set';
|
|
4
|
+
import lodashGet from 'lodash.get';
|
|
5
|
+
import { deepClone } from '../../../utils/tool';
|
|
6
|
+
import isObjectEqual from '../../../utils/isObjectEqual';
|
|
7
|
+
import { emptyObject, emptyArray, NOT_EXISTED_VALUE } from '../../../utils/constant';
|
|
8
|
+
import { FormFieldProvider, useFormField } from '../contexts/form-field-context';
|
|
9
|
+
/**
|
|
10
|
+
* 表单容器装饰器高阶组件
|
|
11
|
+
* 用于包装组件,提供表单容器上下文
|
|
12
|
+
* @param Component 需要包装的组件
|
|
13
|
+
* @returns 包装后的组件,支持透传ref
|
|
14
|
+
*/
|
|
15
|
+
export function withFormContainer(Component) {
|
|
16
|
+
const WithFormContainer = React.forwardRef((props, ref) => {
|
|
17
|
+
var _a;
|
|
18
|
+
const { ...componentProps } = props;
|
|
19
|
+
const formField = useFormField();
|
|
20
|
+
const _formFieldValues = (_a = props.initialValues) !== null && _a !== void 0 ? _a : props.value;
|
|
21
|
+
const [formFieldsValue, setFormFieldsValue] = useState(_formFieldValues !== null && _formFieldValues !== void 0 ? _formFieldValues : ((props === null || props === void 0 ? void 0 : props.objType) === 'arr' ? emptyArray : emptyObject));
|
|
22
|
+
const [isReadyToCalculate, setIsReadyToCalculate] = useState(true);
|
|
23
|
+
const getFieldValue = useCallback(({ namePath, initialValue }) => {
|
|
24
|
+
const value = lodashGet(formFieldsValue, namePath, NOT_EXISTED_VALUE);
|
|
25
|
+
if (value !== NOT_EXISTED_VALUE) {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// 设置初始值,兼容表单项变量绑定场景
|
|
30
|
+
// form的初始值>formArr/formObj/formDetail>field
|
|
31
|
+
if (initialValue !== undefined) {
|
|
32
|
+
return initialValue;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}, [formFieldsValue]);
|
|
37
|
+
const setFieldValue = useCallback(({ namePath, value }) => {
|
|
38
|
+
setFormFieldsValue((formData) => {
|
|
39
|
+
if (typeof formData !== 'object' || formData === null) {
|
|
40
|
+
console.warn('setValue data need expect a object but got null', formData);
|
|
41
|
+
return formData;
|
|
42
|
+
}
|
|
43
|
+
// 获取当前值并比较
|
|
44
|
+
const _value = lodashGet(formData, namePath, NOT_EXISTED_VALUE);
|
|
45
|
+
if (isObjectEqual(_value, value))
|
|
46
|
+
return formData;
|
|
47
|
+
const _formData = deepClone(formData);
|
|
48
|
+
lodashSet(_formData, namePath, value);
|
|
49
|
+
return _formData;
|
|
50
|
+
});
|
|
51
|
+
}, []);
|
|
52
|
+
// 在表单容器内直接渲染原始组件
|
|
53
|
+
if (formField) {
|
|
54
|
+
return _jsx(Component, { ...props, ref: ref, isInformContainer: true });
|
|
55
|
+
}
|
|
56
|
+
return (_jsx(FormFieldProvider, { setFieldValue: setFieldValue, getFieldValue: getFieldValue, isInformContainer: true, formFieldsValue: formFieldsValue, setFormFieldsValue: setFormFieldsValue, isReadyToCalculate: isReadyToCalculate, setIsReadyToCalculate: setIsReadyToCalculate, children: _jsx(Component, { ...componentProps, formFieldsValue: formFieldsValue, ref: ref }) }));
|
|
57
|
+
});
|
|
58
|
+
// 设置显示名称,方便调试
|
|
59
|
+
WithFormContainer.displayName = `withFormContainer(${Component.displayName || Component.name || 'Component'})`;
|
|
60
|
+
return WithFormContainer;
|
|
61
|
+
}
|
|
@@ -6,53 +6,8 @@ import '../style';
|
|
|
6
6
|
export type WdFromProps = CommonPropsType & DataType & EventsType & {
|
|
7
7
|
appCloud: typeof tcbAppCloud;
|
|
8
8
|
};
|
|
9
|
-
declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
contentSlot: React.ReactNode;
|
|
14
|
-
layout: "vertical" | "horizontal";
|
|
15
|
-
dataSourceName: string;
|
|
16
|
-
labelAlign: "left" | "right";
|
|
17
|
-
datasourceType: "connector" | "custom-connector" | "model" | "expression";
|
|
18
|
-
methodGetItem: string;
|
|
19
|
-
paramGetItem: Record<string, unknown>;
|
|
20
|
-
methodCreate: string;
|
|
21
|
-
methodUpdate: string;
|
|
22
|
-
isDisabledSubmit: boolean;
|
|
23
|
-
formType_bind: boolean;
|
|
24
|
-
fields: {
|
|
25
|
-
name: string;
|
|
26
|
-
componentType: string;
|
|
27
|
-
}[];
|
|
28
|
-
colNum: never;
|
|
29
|
-
lgWidth: "lg" | "sm" | "md" | "hundred";
|
|
30
|
-
initialValues: Record<string, unknown>;
|
|
31
|
-
} & {
|
|
32
|
-
events: {
|
|
33
|
-
submit: (eventDetail: unknown, ...args: unknown[]) => unknown;
|
|
34
|
-
validateSuccess: (eventDetail: {
|
|
35
|
-
errors: Record<string, string>;
|
|
36
|
-
}, ...args: unknown[]) => unknown;
|
|
37
|
-
validateFail: (eventDetail: {
|
|
38
|
-
errors: Record<string, string>;
|
|
39
|
-
}, ...args: unknown[]) => unknown;
|
|
40
|
-
queryEmpty: (eventDetail: {
|
|
41
|
-
data: Record<string, any>;
|
|
42
|
-
}, ...args: unknown[]) => unknown;
|
|
43
|
-
querySuccess: (eventDetail: {
|
|
44
|
-
data: Record<string, any>;
|
|
45
|
-
}, ...args: unknown[]) => unknown;
|
|
46
|
-
queryFail: (eventDetail: {
|
|
47
|
-
error: {
|
|
48
|
-
requestid?: string;
|
|
49
|
-
code: string;
|
|
50
|
-
message: string;
|
|
51
|
-
original: any;
|
|
52
|
-
};
|
|
53
|
-
}, ...args: unknown[]) => unknown;
|
|
54
|
-
};
|
|
55
|
-
} & {
|
|
56
|
-
appCloud: typeof tcbAppCloud;
|
|
57
|
-
} & React.RefAttributes<unknown>>>;
|
|
9
|
+
declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Pick<{
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
initialValues?: any;
|
|
12
|
+
}, string | number> & React.RefAttributes<unknown>>>;
|
|
58
13
|
export default _default;
|
|
@@ -19,7 +19,6 @@ import { useDataSource } from '../../utils/hooks/useDataSource';
|
|
|
19
19
|
import { WdForm as FormUi } from './wd-form';
|
|
20
20
|
import StatusContent from '../statusContent';
|
|
21
21
|
import { deepClone } from '../../utils/tool';
|
|
22
|
-
import isObjectEqual from '../../utils/isObjectEqual';
|
|
23
22
|
import { convertMethodParam } from '../../utils/hooks/useFormLegacy';
|
|
24
23
|
import '../style';
|
|
25
24
|
import { getErrorObjectFromValidateResult, convertFormData } from './form-utils';
|
|
@@ -27,13 +26,15 @@ import { isNil } from '../../utils/lodash';
|
|
|
27
26
|
import { FormTypeProvider } from './contexts/form-type-context';
|
|
28
27
|
import { FormLayoutProvider } from './contexts/form-layout-context';
|
|
29
28
|
import { FormWidgetProvider } from './contexts/form-widget-context';
|
|
30
|
-
import {
|
|
29
|
+
import { useFormField } from './contexts/form-field-context';
|
|
30
|
+
// eslint-disable-next-line tree-shaking/no-side-effects-in-initialization
|
|
31
|
+
import { withFormContainer } from './hoc/form-container-decorator';
|
|
31
32
|
import { useSyncValue } from '../../utils/hooks/useSyncValue';
|
|
32
33
|
import useDebouncedCallback from '../../utils/hooks/use-debounced-callback';
|
|
33
34
|
const SET_VALUE_DEBOUNCE_TIMEOUT = 250;
|
|
34
35
|
const logger = debug('wd-form');
|
|
35
|
-
const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
36
|
-
var _a, _b
|
|
36
|
+
const WdForm = withFormContainer(React.forwardRef(function WdForm(props, ref) {
|
|
37
|
+
var _a, _b;
|
|
37
38
|
const { className, id, style, contentSlot: contentSlotEl, layout = 'horizontal', formType = 'create', _id, datasourceType = 'model', dataSourceName, methodGetItem, methodCreate, methodUpdate, paramGetItem, appCloud = tcbAppCloud, lgWidth, labelAlign = 'left', initialValues: _initialValues,
|
|
38
39
|
// 兼容流程setValue调用,其他地方别用
|
|
39
40
|
$node, $widget, } = props;
|
|
@@ -74,16 +75,32 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
|
74
75
|
const [initialValues, setInitialValues] = useState((_b = deepClone(_initialValues)) !== null && _b !== void 0 ? _b : emptyObject);
|
|
75
76
|
const [propsValue] = useSyncValue(props.value);
|
|
76
77
|
// 表单值
|
|
77
|
-
const [formData, setFormData] = useState(
|
|
78
|
+
// const [formData, setFormData] = useState<Record<string, unknown>>(deepClone(_initialValues) ?? emptyObject);
|
|
79
|
+
const formField = useFormField();
|
|
80
|
+
const { setFormFieldsValue, formFieldsValue, setIsReadyToCalculate } = formField || {};
|
|
78
81
|
// 转换后表单值,仅保留已挂载表单项的值
|
|
79
|
-
const
|
|
80
|
-
return convertFormData(
|
|
81
|
-
}, [
|
|
82
|
+
const formFieldConvertValues = useMemo(() => {
|
|
83
|
+
return convertFormData(formFieldsValue, formItemMapList, fieldInitValueCache);
|
|
84
|
+
}, [formFieldsValue, formItemMapList, fieldInitValueCache]);
|
|
82
85
|
useDebouncedEffect(() => {
|
|
83
86
|
var _a, _b;
|
|
84
87
|
// 表单容器上挂载的表单项的值
|
|
85
|
-
(_b = (_a = eventsRef === null || eventsRef === void 0 ? void 0 : eventsRef.current) === null || _a === void 0 ? void 0 : _a.onDataChange) === null || _b === void 0 ? void 0 : _b.call(_a, { data:
|
|
86
|
-
}, [
|
|
88
|
+
(_b = (_a = eventsRef === null || eventsRef === void 0 ? void 0 : eventsRef.current) === null || _a === void 0 ? void 0 : _a.onDataChange) === null || _b === void 0 ? void 0 : _b.call(_a, { data: formFieldConvertValues });
|
|
89
|
+
}, [formFieldConvertValues],
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
91
|
+
SET_VALUE_DEBOUNCE_TIMEOUT);
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (['edit', 'read'].includes(formType) && !hasSetInitValueRef.current) {
|
|
94
|
+
// 表单容器编辑和只读状态下,接口返回数据后具备相应数据计算条件
|
|
95
|
+
setIsReadyToCalculate(false);
|
|
96
|
+
}
|
|
97
|
+
}, [formType, setIsReadyToCalculate]);
|
|
98
|
+
useDebouncedEffect(() => {
|
|
99
|
+
// 在编辑/只读场景下,当所有依赖表单数据全部完成时,允许触发计算逻辑
|
|
100
|
+
if (['edit', 'read'].includes(formType) && hasSetInitValueRef.current) {
|
|
101
|
+
setIsReadyToCalculate(true);
|
|
102
|
+
}
|
|
103
|
+
}, [hasSetInitValueRef.current, formType],
|
|
87
104
|
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
88
105
|
SET_VALUE_DEBOUNCE_TIMEOUT);
|
|
89
106
|
const eventsRef = useSyncedRef(props.events);
|
|
@@ -182,9 +199,9 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
|
182
199
|
if (Object.keys(errorObj !== null && errorObj !== void 0 ? errorObj : {}).length === 0) {
|
|
183
200
|
validateSuccess({ errors: {} });
|
|
184
201
|
const extra = ['read', 'edit'].includes(formType) && _id ? { _id } : {};
|
|
185
|
-
submit && submit(deepClone({ ...extra, ...
|
|
202
|
+
submit && submit(deepClone({ ...extra, ...formFieldConvertValues }));
|
|
186
203
|
// 流程用了;
|
|
187
|
-
return
|
|
204
|
+
return formFieldConvertValues;
|
|
188
205
|
}
|
|
189
206
|
else {
|
|
190
207
|
setErrors(errorObj);
|
|
@@ -199,19 +216,30 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
|
199
216
|
const r = await submitPromiseCache.current;
|
|
200
217
|
submitPromiseCache.current = null;
|
|
201
218
|
return r;
|
|
202
|
-
}, [_id, eventsRef,
|
|
219
|
+
}, [_id, eventsRef, formFieldConvertValues, formType, isDisabledSubmit, validate]);
|
|
203
220
|
const submit = useDebouncedCallback(submitHandler, SET_VALUE_DEBOUNCE_TIMEOUT, {
|
|
204
221
|
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
205
222
|
maxWait: SET_VALUE_DEBOUNCE_TIMEOUT,
|
|
206
223
|
trailing: true,
|
|
207
224
|
});
|
|
208
|
-
const setValue = useCallback((data) => {
|
|
225
|
+
const setValue = useCallback((data, notMerge = false) => {
|
|
226
|
+
// notMerge 默认false,表示与之前的表单值合并
|
|
209
227
|
if (typeof data !== 'object' || data === null) {
|
|
210
228
|
console.warn('setValue data need expect a object but got null', data);
|
|
211
229
|
return;
|
|
212
230
|
}
|
|
213
|
-
|
|
214
|
-
|
|
231
|
+
if (notMerge) {
|
|
232
|
+
setFormFieldsValue(data);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
setFormFieldsValue((formFieldsValue) => ({ ...formFieldsValue, ...data }));
|
|
236
|
+
}
|
|
237
|
+
}, [setFormFieldsValue]);
|
|
238
|
+
const setValueDebounce = useDebouncedCallback(setValue, SET_VALUE_DEBOUNCE_TIMEOUT, {
|
|
239
|
+
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
240
|
+
maxWait: SET_VALUE_DEBOUNCE_TIMEOUT * 2,
|
|
241
|
+
trailing: true,
|
|
242
|
+
});
|
|
215
243
|
const clearValidate = useCallback(() => {
|
|
216
244
|
formsItemMap.forEach((items) => {
|
|
217
245
|
items.forEach((item) => {
|
|
@@ -223,10 +251,6 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
|
223
251
|
});
|
|
224
252
|
});
|
|
225
253
|
}, [formsItemMap]);
|
|
226
|
-
const [isInformContainer, setIsInformContainer] = React.useState(false);
|
|
227
|
-
React.useEffect(() => {
|
|
228
|
-
setIsInformContainer(true);
|
|
229
|
-
}, []);
|
|
230
254
|
useMountEffect(() => {
|
|
231
255
|
logger.debug('formItemMap', formsItemMap);
|
|
232
256
|
});
|
|
@@ -291,19 +315,14 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
|
291
315
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
292
316
|
[formsItemMap]);
|
|
293
317
|
const { data: formInitValueToSet } = useInitValueFromRemote(datasourceType, dataSourceProfile, fetchedInitialValues);
|
|
294
|
-
const setValueDebounce = useDebouncedCallback(setValue, SET_VALUE_DEBOUNCE_TIMEOUT, {
|
|
295
|
-
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
296
|
-
maxWait: SET_VALUE_DEBOUNCE_TIMEOUT * 2,
|
|
297
|
-
trailing: true,
|
|
298
|
-
});
|
|
299
318
|
useEffect(() => {
|
|
300
319
|
if (initValueLoadingStatus !== 'done' || !fetchedInitialValues)
|
|
301
320
|
return;
|
|
302
321
|
if (!initValueFetchError && formInitValueToSet) {
|
|
303
322
|
/*
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
323
|
+
错误处理放在了 @link {onInitialValuesError}
|
|
324
|
+
下面是可以拿到data了
|
|
325
|
+
*/
|
|
307
326
|
// TODO: 有哪些key可以暴露
|
|
308
327
|
setInitialValues((original) => {
|
|
309
328
|
if (hasSetInitValueRef.current) {
|
|
@@ -326,7 +345,7 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
|
326
345
|
}, [authValue, isDataModel, initDataSourceFieldsWithAuth, formItemMapKey]);
|
|
327
346
|
const submitParams = useRemoteParamsFromValue({
|
|
328
347
|
dataSourceProfile,
|
|
329
|
-
formData:
|
|
348
|
+
formData: formFieldConvertValues,
|
|
330
349
|
formType,
|
|
331
350
|
_id,
|
|
332
351
|
});
|
|
@@ -378,13 +397,7 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
|
378
397
|
setValue(val, opts = { notMerge: false }) {
|
|
379
398
|
const value = convertMethodParam(val);
|
|
380
399
|
// notMerge 默认false,表示与之前的表单值合并
|
|
381
|
-
|
|
382
|
-
setValueDebounce(value);
|
|
383
|
-
}
|
|
384
|
-
else {
|
|
385
|
-
const _formData = deepClone(formData);
|
|
386
|
-
setValueDebounce({ ..._formData, ...value });
|
|
387
|
-
}
|
|
400
|
+
setValueDebounce(value, opts.notMerge);
|
|
388
401
|
},
|
|
389
402
|
reset() {
|
|
390
403
|
setValueDebounce(initialValues);
|
|
@@ -427,7 +440,7 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
|
427
440
|
authValue,
|
|
428
441
|
layout,
|
|
429
442
|
dataSourceName,
|
|
430
|
-
value:
|
|
443
|
+
value: formFieldConvertValues,
|
|
431
444
|
remoteValue: fetchedInitialValues,
|
|
432
445
|
dataSourceProfile,
|
|
433
446
|
errors,
|
|
@@ -449,7 +462,7 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
|
449
462
|
authValue,
|
|
450
463
|
layout,
|
|
451
464
|
dataSourceName,
|
|
452
|
-
|
|
465
|
+
formFieldConvertValues,
|
|
453
466
|
fetchedInitialValues,
|
|
454
467
|
dataSourceProfile,
|
|
455
468
|
errors,
|
|
@@ -464,7 +477,6 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
|
464
477
|
fieldInitValueCache,
|
|
465
478
|
formsItemMap,
|
|
466
479
|
setValueDebounce,
|
|
467
|
-
formData,
|
|
468
480
|
formItemMapList,
|
|
469
481
|
setValue,
|
|
470
482
|
validate,
|
|
@@ -495,38 +507,9 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
|
|
|
495
507
|
const labelPosition = useMemo(() => {
|
|
496
508
|
return `${layout}-${labelAlign}`;
|
|
497
509
|
}, [layout, labelAlign]);
|
|
498
|
-
const getFieldValue = useCallback(({ namePath, initialValue }) => {
|
|
499
|
-
const value = lodashGet(formData, namePath, NOT_EXISTED_VALUE);
|
|
500
|
-
if (value !== NOT_EXISTED_VALUE) {
|
|
501
|
-
return value;
|
|
502
|
-
}
|
|
503
|
-
else {
|
|
504
|
-
// 设置初始值,兼容表单项变量绑定场景
|
|
505
|
-
// form的初始值>formArr/formObj/formDetail>field
|
|
506
|
-
if (initialValue !== undefined) {
|
|
507
|
-
return initialValue;
|
|
508
|
-
}
|
|
509
|
-
return undefined;
|
|
510
|
-
}
|
|
511
|
-
}, [formData]);
|
|
512
|
-
const setFieldValue = useCallback(({ namePath, value }) => {
|
|
513
|
-
setFormData((formData) => {
|
|
514
|
-
const _formData = deepClone(formData);
|
|
515
|
-
const _value = lodashGet(_formData, namePath, NOT_EXISTED_VALUE);
|
|
516
|
-
if (isObjectEqual(_value, value)) {
|
|
517
|
-
return _formData;
|
|
518
|
-
}
|
|
519
|
-
lodashSet(_formData, namePath, value);
|
|
520
|
-
if (typeof _formData !== 'object' || _formData === null) {
|
|
521
|
-
console.warn('setValue data need expect a object but got null', _formData);
|
|
522
|
-
return formData;
|
|
523
|
-
}
|
|
524
|
-
return _formData;
|
|
525
|
-
});
|
|
526
|
-
}, []);
|
|
527
510
|
if (initValueLoadingStatus === 'loading' && !fetchedInitialValues) {
|
|
528
511
|
return _jsx(StatusContent, { emptyText: '数据加载中,请稍候...', component: "table", icon: "loading" });
|
|
529
512
|
}
|
|
530
|
-
return (_jsx(FormWidgetProvider, { "$widget": $widget, children: _jsx(FormLayoutProvider, { layout: layout, children: _jsx(FormTypeProvider, { formType: formType, children: _jsx(
|
|
531
|
-
});
|
|
513
|
+
return (_jsx(FormWidgetProvider, { "$widget": $widget, children: _jsx(FormLayoutProvider, { layout: layout, children: _jsx(FormTypeProvider, { formType: formType, children: _jsx(FormUi, { layout: layout, className: cls, style: style, id: id, lgWidth: lgWidth, labelPosition: labelPosition, children: initValueFetchError ? (_jsx(StatusContent, { emptyText: '数据加载失败', errorObj: initValueFetchError, icon: 'error', isH5: isH5 })) : (contentSlot) }) }) }) }));
|
|
514
|
+
}));
|
|
532
515
|
export default React.memo(WdForm);
|
|
@@ -3,12 +3,16 @@ import type { CommonPropsType } from '../../types';
|
|
|
3
3
|
import type { DataType as ObjDataType } from '../../../configs/components/wd-form-obj';
|
|
4
4
|
import type { DataType as ArrDataType } from '../../../configs/components/wd-form-arr';
|
|
5
5
|
import '../style';
|
|
6
|
-
export declare const BaseFormObj: React.ForwardRefExoticComponent<
|
|
6
|
+
export declare const BaseFormObj: React.ForwardRefExoticComponent<Pick<{
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
initialValues?: any;
|
|
9
|
+
}, string | number> & React.RefAttributes<unknown>>;
|
|
7
10
|
type DataType = ObjDataType & ArrDataType;
|
|
8
11
|
export interface BaseFormObjProps extends CommonPropsType, DataType {
|
|
9
12
|
disabled: boolean;
|
|
10
13
|
readOnly: boolean;
|
|
11
14
|
objType: 'arr' | 'obj';
|
|
12
15
|
isRoot?: boolean;
|
|
16
|
+
isInformContainer?: boolean;
|
|
13
17
|
}
|
|
14
18
|
export {};
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-magic-numbers */
|
|
3
|
-
import { forwardRef, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
3
|
+
import { forwardRef, useCallback, useEffect, useLayoutEffect, useRef, useState, useMemo } from 'react';
|
|
4
4
|
import { useDeepCompareEffect } from '@react-hookz/web';
|
|
5
5
|
import { useConfig } from '../../utils/config-context';
|
|
6
6
|
import { WdFormItem } from '../wd-form-item';
|
|
7
7
|
import { usePlatform } from '../../utils/platform';
|
|
8
8
|
import classNames from '../../utils/classnames';
|
|
9
9
|
import { FormFieldObjProvider } from '../wd-form/contexts/form-field-obj-context';
|
|
10
|
-
import {
|
|
11
|
-
import { noop
|
|
10
|
+
import { useFormField } from '../wd-form/contexts/form-field-context';
|
|
11
|
+
import { noop } from '../../utils/constant';
|
|
12
12
|
import lodashSet from 'lodash.set';
|
|
13
|
-
import lodashGet from 'lodash.get';
|
|
14
13
|
import { useFormInputTrait } from '../form-input-hooks';
|
|
15
14
|
import { deepClone } from '../../utils/tool';
|
|
16
15
|
import isObjectEqual from '../../utils/isObjectEqual';
|
|
16
|
+
// eslint-disable-next-line tree-shaking/no-side-effects-in-initialization
|
|
17
|
+
import { withFormContainer } from '../wd-form/hoc/form-container-decorator';
|
|
17
18
|
import '../style';
|
|
18
19
|
import useDebouncedCallback from '../../utils/hooks/use-debounced-callback';
|
|
19
20
|
const classRoot = 'form-obj';
|
|
20
|
-
export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
|
|
21
|
+
export const BaseFormObj = withFormContainer(forwardRef(function BaseFormObj(props, ref) {
|
|
21
22
|
const { classPrefix } = useConfig();
|
|
22
23
|
const platform = usePlatform();
|
|
23
24
|
const cls = classNames({
|
|
@@ -34,8 +35,9 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
|
|
|
34
35
|
const [status, updateStatus] = useState('edit');
|
|
35
36
|
const [innerHandle, setInnerHandle] = useState({});
|
|
36
37
|
const inputRef = useRef({});
|
|
37
|
-
const
|
|
38
|
-
const {
|
|
38
|
+
const formField = useFormField();
|
|
39
|
+
const { setFormFieldsValue, formFieldsValue } = formField || {};
|
|
40
|
+
const { name, value: _objValue, readOnly, disabled, visible, onChange: _onChange, namePath, } = useFormInputTrait({
|
|
39
41
|
label: props.label,
|
|
40
42
|
value: props.value,
|
|
41
43
|
name: props.name,
|
|
@@ -47,9 +49,10 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
|
|
|
47
49
|
requiredMsg: '',
|
|
48
50
|
$widget: props.$widget,
|
|
49
51
|
setInnerHandle,
|
|
50
|
-
onChange: noop,
|
|
52
|
+
onChange: props.isInformContainer ? noop : setFormFieldsValue,
|
|
51
53
|
$node: props.$node,
|
|
52
54
|
});
|
|
55
|
+
const objValue = useMemo(() => (props.isInformContainer ? _objValue : formFieldsValue), [_objValue, formFieldsValue, props.isInformContainer]);
|
|
53
56
|
const valueRef = useRef(props.value);
|
|
54
57
|
useDeepCompareEffect(() => {
|
|
55
58
|
if (isObjectEqual(valueRef.current, objValue)) {
|
|
@@ -57,9 +60,6 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
|
|
|
57
60
|
}
|
|
58
61
|
triggerOnDataChange(objValue);
|
|
59
62
|
}, [objValue]);
|
|
60
|
-
useEffect(() => {
|
|
61
|
-
setIsInformObjContainer(true);
|
|
62
|
-
}, []);
|
|
63
63
|
useEffect(() => {
|
|
64
64
|
if (readOnly) {
|
|
65
65
|
updateStatus('readOnly');
|
|
@@ -78,7 +78,7 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
|
|
|
78
78
|
var _a, _b;
|
|
79
79
|
valueRef.current = value;
|
|
80
80
|
(_b = (_a = props.events) === null || _a === void 0 ? void 0 : _a.onDataChange) === null || _b === void 0 ? void 0 : _b.call(_a, { data: value });
|
|
81
|
-
}, [props.events]),
|
|
81
|
+
}, [props.events]), 250);
|
|
82
82
|
const dealArrChange = useCallback((params, objValue) => {
|
|
83
83
|
let value;
|
|
84
84
|
// 顶层为数组类型
|
|
@@ -138,12 +138,13 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
|
|
|
138
138
|
if (isObjectEqual(value, objValue) || (value === null && isObjectEqual(initValue, objValue))) {
|
|
139
139
|
return;
|
|
140
140
|
}
|
|
141
|
-
_onChange
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
if (_onChange) {
|
|
142
|
+
_onChange(value || initValue);
|
|
143
|
+
}
|
|
144
|
+
}, [disabled, readOnly, props.objType, objValue, _onChange, dealArrChange]);
|
|
144
145
|
const changeDebounce = useDebouncedCallback(useCallback((value) => {
|
|
145
146
|
change(value);
|
|
146
|
-
}, [change]),
|
|
147
|
+
}, [change]), 250);
|
|
147
148
|
useLayoutEffect(() => {
|
|
148
149
|
if (!ref)
|
|
149
150
|
return;
|
|
@@ -187,25 +188,5 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
|
|
|
187
188
|
readOnly,
|
|
188
189
|
};
|
|
189
190
|
}, [innerHandle, props.label, name, objValue, visible, disabled, readOnly, props.objType, change, ref, changeDebounce]);
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}, [change]);
|
|
193
|
-
const getFieldValue = useCallback(({ namePath, initialValue }) => {
|
|
194
|
-
const value = lodashGet(objValue, namePath, NOT_EXISTED_VALUE);
|
|
195
|
-
if (value !== NOT_EXISTED_VALUE) {
|
|
196
|
-
return value;
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
// 设置初始值,兼容表单项变量绑定场景
|
|
200
|
-
// form的初始值>formArr/formObj/formDetail>field
|
|
201
|
-
if (initialValue !== undefined) {
|
|
202
|
-
return initialValue;
|
|
203
|
-
}
|
|
204
|
-
return null;
|
|
205
|
-
}
|
|
206
|
-
}, [objValue]);
|
|
207
|
-
if (_isInformContainer) {
|
|
208
|
-
return (_jsx(FormFieldObjProvider, { namePath: namePath, status: status, objType: props.objType, children: _jsx(WdFormItem, { ...formItemProps, children: _jsx("fieldset", { className: cls, id: props.id, style: props.style, role: "container", "data-testid": "formObj", children: props.children }) }) }));
|
|
209
|
-
}
|
|
210
|
-
return (_jsx(FormFieldProvider, { setFieldValue: setFieldValue, isInformContainer: isInformObjContainer, getFieldValue: getFieldValue, children: _jsx(FormFieldObjProvider, { namePath: namePath, status: status, children: _jsx(WdFormItem, { ...formItemProps, children: _jsx("fieldset", { className: cls, id: props.id, style: props.style, role: "container", "data-testid": "formObj", children: props.children }) }) }) }));
|
|
211
|
-
});
|
|
191
|
+
return (_jsx(FormFieldObjProvider, { namePath: namePath, status: status, isChildField: props.isInformContainer, children: _jsx(WdFormItem, { ...formItemProps, children: _jsx("fieldset", { className: cls, id: props.id, style: props.style, role: "container", "data-testid": "formObj", children: props.children }) }) }));
|
|
192
|
+
}));
|
|
@@ -67,9 +67,11 @@ export declare const WdInput: React.ForwardRefExoticComponent<CommonPropsType &
|
|
|
67
67
|
wrapClassName?: string;
|
|
68
68
|
classRoot?: string;
|
|
69
69
|
inputPattern?: RegExp;
|
|
70
|
+
isTagInput?: boolean;
|
|
70
71
|
} & React.RefAttributes<any>>;
|
|
71
72
|
export type WdInputProps = CommonPropsType & DataType & EventsType & {
|
|
72
73
|
wrapClassName?: string;
|
|
73
74
|
classRoot?: string;
|
|
74
75
|
inputPattern?: RegExp;
|
|
76
|
+
isTagInput?: boolean;
|
|
75
77
|
};
|