@cainiaofe/cn-ui-m
Version:
192 lines (191 loc) • 11.5 kB
JavaScript
import { __assign, __awaiter, __generator, __rest } from "tslib";
import React from 'react';
import { useRequest } from 'ahooks';
import { createForm, onFieldValueChange } from '@formily/core';
import findLastKey from 'lodash/findLastKey';
import isEmpty from 'lodash/isEmpty';
import cloneDeep from 'lodash/cloneDeep';
import { CnForm } from "../../../form/cn-form";
import { CnLoading } from "../../cn-loading";
import { generateSchema, handleRequestService, useStateCallback, } from '../utils';
import { withNativeProps } from '@cainiaofe/cn-ui-common';
var DynamicContainerKey = 'dynamic_container';
var DynamicFormEffectsKey = 'dynamicFormAddEffectsKey';
export var CnDynamicForm = React.forwardRef(function (props, ref) {
var prevFieldRef = React.useRef(null);
var schema = props.schema, cols = props.cols, formProps = props.formProps, _remoteUrl = props.remoteUrl, requestConfig = props.requestConfig, initRequestConfig = props.initRequestConfig, submitRequestConfig = props.submitRequestConfig, initForm = props.form, initOnSubmit = props.onSubmit, restProps = __rest(props, ["schema", "cols", "formProps", "remoteUrl", "requestConfig", "initRequestConfig", "submitRequestConfig", "form", "onSubmit"]);
var realSchema = React.useMemo(function () { return generateSchema(schema, cols); }, [schema, cols]);
var _a = useStateCallback(__assign(__assign({}, requestConfig), { fromProps: true, url: (requestConfig === null || requestConfig === void 0 ? void 0 : requestConfig.url) || _remoteUrl })), realRequestConfig = _a[0], setRequestConfig = _a[1];
var _b = useStateCallback(submitRequestConfig), realSubmitRequestConfig = _b[0], setSubmitRequestConfig = _b[1];
// 只有props内的requestConfig才存在initRequest;通过reLoad一定会执行run函数,因此何时调用reLoad,何时就会触发run;
// 如果配置了url,但是没配置refreshDeps,则认为是初始渲染直接获取动态Schema
var isInitRequest = React.useMemo(function () {
return (realRequestConfig === null || realRequestConfig === void 0 ? void 0 : realRequestConfig.url) &&
(realRequestConfig === null || realRequestConfig === void 0 ? void 0 : realRequestConfig.fromProps) &&
isEmpty(realRequestConfig === null || realRequestConfig === void 0 ? void 0 : realRequestConfig.refreshDeps);
}, [realRequestConfig]);
// 远程Schema
var _c = realRequestConfig || {}, service = _c.service, searchFormat = _c.searchFormat, refreshDeps = _c.refreshDeps, _d = _c.formatResult, formatResult = _d === void 0 ? function (res) {
var _a;
if (Array.isArray(res)) {
return res;
}
else if (Array.isArray(res === null || res === void 0 ? void 0 : res.data)) {
return res.data;
}
else if (Array.isArray((_a = res === null || res === void 0 ? void 0 : res.data) === null || _a === void 0 ? void 0 : _a.schema)) {
return res.data.schema;
}
return [];
} : _d, otherConfig = __rest(_c, ["service", "searchFormat", "refreshDeps", "formatResult"]);
var requestService = React.useCallback(handleRequestService(realRequestConfig), [realRequestConfig]);
var _e = useRequest(requestService, __assign({ ready: !!(realRequestConfig.url || service), manual: true }, otherConfig)), run = _e.run, runAsync = _e.runAsync, _f = _e.data, data = _f === void 0 ? [] : _f, loading = _e.loading;
// 当props中requestConfig含有url && 且refreshDeps为空,则认为是isInitRequest,则调用run获取远程Schema。
React.useEffect(function () {
if (isInitRequest) {
run();
}
}, [isInitRequest]);
// 两种情况,一种是外部注入form,一种是内部createForm;
// 需要判断,外部注入的话,需要获取form后,执行addEffects;内部生成的话需要获取form后,执行addEffects;
var finalForm = React.useMemo(function () {
// 如果涉及到状态的更新,须传入form实例
if (initForm) {
initForm.addEffects(DynamicFormEffectsKey, function (form) {
if (refreshDeps && refreshDeps.length > 0) {
onFieldValueChange("*(".concat(refreshDeps.join(','), ")"), function (field) {
run({
watchValue: field.value,
formValues: form.getFormState().values,
});
});
}
});
return initForm;
}
return createForm(__assign(__assign({}, formProps), { effects: function (form) {
if (refreshDeps && refreshDeps.length > 0) {
onFieldValueChange("*(".concat(refreshDeps.join(','), ")"), function (field) {
run({
watchValue: field.value,
formValues: form.getFormState().values,
});
});
}
(formProps === null || formProps === void 0 ? void 0 : formProps.effects) && formProps.effects(form);
} }));
}, [initForm, realSchema]);
var finalSchema = React.useMemo(function () {
var _a, _b;
// 清除字段模型、删除字段值,确保异步Schema不会值缓存
if (prevFieldRef.current && prevFieldRef.current.length > 0) {
finalForm.clearFormGraph("*.".concat(DynamicContainerKey, ".*"));
finalForm.deleteValuesIn("*.".concat(DynamicContainerKey, ".*"));
}
var cloneRealSchema = cloneDeep(realSchema);
// 如果接口返回为空,则直接返回初始Schema;
if (isEmpty(data))
return cloneRealSchema;
// 如果接口返回不为空,则进行format;并构建最终Schema进行渲染
var initFormatData = formatResult(data);
var formatData = [];
if (Array.isArray(initFormatData)) {
formatData = initFormatData;
}
else if (Array.isArray(initFormatData === null || initFormatData === void 0 ? void 0 : initFormatData.schema)) {
formatData = initFormatData.schema;
}
else if (Array.isArray(initFormatData === null || initFormatData === void 0 ? void 0 : initFormatData.data)) {
formatData = initFormatData.data;
}
else if (Array.isArray((_a = initFormatData === null || initFormatData === void 0 ? void 0 : initFormatData.data) === null || _a === void 0 ? void 0 : _a.schema)) {
formatData = initFormatData.data.schema;
}
prevFieldRef.current = formatData;
var realData = formatData;
// 如果format后的data为空,则直接返回静态Schema
if (isEmpty(realData)) {
return cloneRealSchema;
}
else if (isEmpty(cloneRealSchema)) {
// 不存在静态Schema时,直接使用接口返回进行渲染
return generateSchema(realData, cols);
}
else {
// 存在静态Schema时,查找到静态Schema最后一个Properties对象,将接口返回Schema塞进去
var lastProperties = findLastKey(cloneRealSchema === null || cloneRealSchema === void 0 ? void 0 : cloneRealSchema.properties, function (o) {
return !isEmpty(o === null || o === void 0 ? void 0 : o.properties);
});
// 将异步获取的Schema,添加至最后一个properties中,确保异步Schema在表单最后位置
if (lastProperties) {
var targetProperties = (_b = cloneRealSchema === null || cloneRealSchema === void 0 ? void 0 : cloneRealSchema.properties[lastProperties]) === null || _b === void 0 ? void 0 : _b.properties;
targetProperties[DynamicContainerKey] = {
type: 'void',
'x-component': 'CnFormGrid',
'x-component-props': {
cols: cols,
},
colSpan: 'full',
properties: generateSchema(realData, cols, true),
};
}
}
return cloneRealSchema;
}, [data, realSchema, cols, finalForm]);
// 初始值数据源
var _g = initRequestConfig || {}, initUrl = _g.url, initService = _g.service, _h = _g.formatResult, initFormatResult = _h === void 0 ? function (res) {
return (res === null || res === void 0 ? void 0 : res.data) || res || {};
} : _h, initRestConfig = __rest(_g, ["url", "service", "formatResult"]);
var initRequestService = React.useCallback(handleRequestService(initRequestConfig), [initRequestConfig]);
var _j = useRequest(initRequestService, __assign({ ready: !!(initUrl || initService), manual: true }, initRestConfig)), initRun = _j.run, _k = _j.data, initData = _k === void 0 ? {} : _k;
React.useEffect(function () {
initRun();
}, [initRequestConfig]);
React.useEffect(function () {
var initialValues = initFormatResult(initData);
if (!isEmpty(initialValues)) {
finalForm.setInitialValues(initialValues);
}
}, [initData, finalForm]);
// 提交数据源
var _l = realSubmitRequestConfig || {}, submitUrl = _l.url, submitService = _l.service,
// eslint-disable-next-line
_m = _l.formatResult,
// eslint-disable-next-line
submitFormatResult = _m === void 0 ? function (res) {
return (res === null || res === void 0 ? void 0 : res.data) || res || {};
} : _m, submitRestConfig = __rest(_l, ["url", "service", "formatResult"]);
var submitRequestService = React.useCallback(handleRequestService(realSubmitRequestConfig), [realSubmitRequestConfig]);
var submitRun = useRequest(submitRequestService, __assign({ ready: !!(submitUrl || submitService), manual: true }, submitRestConfig)).run;
// 根据onSubmit、submitRequestConfig重写onSubmit函数
var onSubmit = React.useCallback(function (values) {
initOnSubmit && (initOnSubmit === null || initOnSubmit === void 0 ? void 0 : initOnSubmit(values));
submitRun({ formValues: values });
}, [initOnSubmit, realSubmitRequestConfig]);
React.useImperativeHandle(ref, function () { return ({
reLoad: function (_requestConfig) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, new Promise(function (resolve) {
setRequestConfig(__assign(__assign({}, _requestConfig), { fromProps: false }), resolve);
})];
case 1:
_a.sent();
return [4 /*yield*/, runAsync()];
case 2:
_a.sent();
return [2 /*return*/];
}
});
}); },
submit: function (_requestConfig) {
setSubmitRequestConfig(_requestConfig, function () {
var formValues = finalForm.getFormState().values;
onSubmit(formValues);
});
},
}); });
return withNativeProps(props, React.createElement(CnLoading, { visible: loading, style: { width: '100%' } },
React.createElement(CnForm, __assign({}, restProps, { form: finalForm, schema: finalSchema, onSubmit: onSubmit }))));
});
CnDynamicForm.displayName = 'CnDynamicForm';