@cainiaofe/cn-ui-lowcode
Version:
592 lines (572 loc) • 17.7 kB
JavaScript
import React, {
useCallback,
useMemo,
useEffect,
useRef,
useState,
forwardRef,
useImperativeHandle,
} from 'react';
import {
CnFilter as UICnFilter,
CnFilterItem as UICnFilterItem,
} from '@cainiaofe/cn-ui';
import {
executeObjectExpr,
filterUndefined,
getFormDefaultValue,
getRealizeValue,
handleEvents,
isDesignMode,
transProxyToObject,
needRequestRemote,
executeEventWithoutJS,
makeFilterItem,
} from '@/common/util/util';
import {
getRunTimeItem,
transRulesToValidator,
} from '@/common/manager/filter-item';
import { getButtonAction } from '@/common/manager/button';
import { ButtonPosition } from '@/common/manager/position/button-position';
import isPlainObject from 'lodash/isPlainObject';
import cloneDeep from 'lodash/cloneDeep';
import {
dataOriginRequest,
dataOriginStatic,
onFieldValueChange,
} from '@/common/util/const';
import {
__dataSource__,
__filterValue__,
__formValue__,
} from '@/common/util/expr-const';
import {
CnFilterOnChange,
CnFilterOnSearch,
CnPageRequestFinish,
emitEvent,
onEvent,
} from '@/common/util/event-name';
import { ValidatorPosition } from '@/common/manager/position/validator-position';
const CnFilter = forwardRef((props, ref) => {
const {
// className,
config = [],
onSearch: originOnSearch,
_dataSource,
_dataSourceName,
_context,
forwardedRef,
_bindTable,
defaultParams,
filterStyle,
title,
events: filterEvents,
...otherProps
} = props;
const isDesign = isDesignMode(props);
const urlParams = _context?.state?.urlParams || {};
const willMount = useRef(true);
const eventMap = handleEvents(config);
const { deferRender } = defaultParams || {};
const [forceUpdate, setForceUpdate] = useState();
// 缓存默认值,用于重置还原
const cacheDefaultValue = useRef(null);
// 记录默认值请求需要等待哪些组件请求完成
const waitComponentList = useRef([]);
let defaultDeferRender;
if (
!isDesign &&
defaultParams?.dataOrigin === dataOriginRequest &&
!!deferRender
) {
defaultDeferRender = !!deferRender;
}
const [defer, setDefer] = useState(defaultDeferRender);
const { afterResetNeedQuery } = filterStyle || {};
const filterRef = useRef(null);
const formValue = useMemo(() => {
if (typeof _dataSource === 'object') {
return transProxyToObject(_dataSource);
}
return null;
}, [_dataSource]);
useImperativeHandle(ref, () => ({
reset() {
const ref = filterRef?.current;
if (ref) {
const field = ref?.getField?.();
field?.filterReset?.();
}
},
search() {
const ref = filterRef?.current;
if (ref) {
const field = ref?.getField?.();
field?.filterSearch?.();
}
},
}));
// const field = Field.useField({
// values: {},
// onChange: (name,value)=>{
// // this.props._context.setState({
// // "dp2":this.field.getValues()
// // })
// }
// });
//
const onReset = useCallback((field) => {
if (field) {
let newDefaultValue;
if (isPlainObject(cacheDefaultValue.current)) {
newDefaultValue = cloneDeep(cacheDefaultValue.current);
}
field?.setValues(newDefaultValue);
onChange?.(newDefaultValue);
if (afterResetNeedQuery !== false) {
setTimeout(() => {
field.filterSearch?.();
});
}
}
}, []);
const componentRequestFinish = useCallback((tempConfig) => {
const { name, dataSource } = tempConfig || {};
const defaultValues = cacheDefaultValue.current;
const oldLength = waitComponentList.current.length;
if (
isPlainObject(defaultValues) &&
name &&
waitComponentList.current.includes(name)
) {
waitComponentList.current = waitComponentList.current.filter(
(item) => item !== name,
);
const current = defaultValues[name];
if (
typeof current?.value === 'number' &&
current?.valueType === 'DefaultSelect'
) {
const temp = dataSource?.[current.value];
defaultValues[name] = temp?.value;
}
const newLength = waitComponentList.current.length;
if (newLength === 0 && oldLength > 0) {
setDefaultValue(defaultValues);
const table = _context.$(_bindTable);
if (table?.props?.manual === true) {
} else {
setTimeout(() => {
onSearch();
});
}
}
}
}, []);
const executeEvent = useCallback((values, name, value, field) => {
if (name) {
const toExecuteEvents = eventMap?.[name];
if (Array.isArray(toExecuteEvents) && toExecuteEvents.length > 0) {
for (const item of toExecuteEvents) {
const { name: eventName, optType, jsFunction } = item;
if (eventName === onFieldValueChange) {
if (optType === 'jsAction' && typeof jsFunction === 'function') {
const mockField = {
value,
query(fieldName) {
return {
value() {
return values?.[fieldName];
},
};
},
};
const mockForm = {
setFieldState(fieldName, callback) {
let temp = {};
if (typeof callback === 'function') {
try {
callback(temp);
} catch (e) {}
}
if (fieldName && temp?.value !== undefined) {
field.setValue(fieldName, temp?.value);
if (Date.now() - startTime > 10) {
field.filterChange(field.values);
}
}
},
};
const startTime = Date.now();
jsFunction.call(null, mockField, mockForm);
} else {
const action = getButtonAction({
...item,
position: ButtonPosition.filterItemEvent,
});
if (typeof action === 'function') {
action({
buttonConfig: {
...item,
position: ButtonPosition.filterItemEvent,
options: {
...item,
},
},
position: ButtonPosition.filterItemEvent,
componentProps: props,
state: _context?.state,
urlParamsDataSource: urlParams,
recordDataSource: values,
_context,
});
}
}
}
}
}
}
}, []);
// const generateChildren = () => {
// if (config.length > 0) {
// const result = [];
// let recordDataSource = formValue;
// if (willMount.current) {
// const p = getFormDefaultValue(defaultParams, {
// urlParamsDataSource: urlParams,
// state:_context?.state,
// isDesign,
// formConfig: config,
// })
// if(isPlainObject(p)){
// recordDataSource = p;
// }
// willMount.current = false;
// }
// config.forEach((item, index) => {
// const { label = '', name, componentName, span, required, requiredMessage, options = {}, placeholder, hidden, disabled, rules = [], hasClear, events = [], tip, mobileProps } = item;
// const componentDefine = getRunTimeItem(componentName);
// if (componentName && componentDefine) {
// const isDisabled = executeObjectExpr(disabled, {
// [__formValue__]: formValue,
// [__filterValue__]: formValue,
// [__dataSource__]: _context?.state,
// },formValue, _context?.state);
// let { component, filterItemBeforeHandler } = componentDefine;
// const filterItemProps = {
// label,
// name,
// componentName,
// span,
// required,
// requiredMessage,
// disabled: isDisabled,
// mobileProps,
// };
// if(tip) {
// filterItemProps.tip = tip;
// }
// // 协议更改兼容
// delete options.placeholder;
// let componentProps = cloneDeep({ hasClear, placeholder, ...options });
// component = getRealizeValue(component);
// const filterBeforeHandler = component?.filterBeforeHandler;
// if (filterBeforeHandler) {
// componentProps = filterBeforeHandler(componentProps, {
// isDesign,
// urlParamsDataSource: urlParams,
// recordDataSource,
// state: _context?.state,
// componentRequestFinish,
// filterItemConfig: item,
// });
// }
// const isHidden = executeObjectExpr(hidden,{
// [__formValue__]: formValue,
// [__filterValue__]: formValue,
// [__dataSource__]: _context?.state,
// }, formValue, _context?.state)
// if (isHidden) {
// // filterItemProps.display = 'none';
// return
// }
// // 处理校验
// if (rules.length > 0) {
// filterItemProps.rules = handleRulesToValidator(rules, {
// formValue,
// state: _context?.state,
// position: ValidatorPosition.filter
// });
// }
// // 处理事件
// // const eventMap = handleEvents(events, {
// // position: ButtonPosition.filterItemEvent,
// // _context,
// // extraParams: {
// // formValue,
// // fieldName: name,
// // }
// // });
// filterItemBeforeHandler && filterItemBeforeHandler(filterItemProps, {componentProps,isDesign,urlParamsDataSource:urlParams, recordDataSource, state:_context?.state})
// result.push(<UICnFilterItem key={index} {...filterUndefined(filterItemProps)}>
// {React.createElement(
// component,
// {
// ...componentProps,
// _context,
// // ...eventMap,
// },
// )}
// </UICnFilterItem>);
// }
// });
// return result;
// }
// return null;
// }
const generateChildren = () => {
if (config.length > 0) {
const result = [];
let recordDataSource = formValue;
if (willMount.current) {
const p = getFormDefaultValue(defaultParams, {
urlParamsDataSource: urlParams,
state: _context?.state,
isDesign,
formConfig: config,
});
if (isPlainObject(p)) {
recordDataSource = p;
}
willMount.current = false;
}
config.forEach((item, index) => {
const filterItemResult = makeFilterItem({
filterItemConfig: item,
formValue,
_context,
isDesign,
urlParams,
recordDataSource,
componentRequestFinish,
});
if (isPlainObject(filterItemResult)) {
const { filterItemProps, component, componentProps, dom } =
filterItemResult;
let realDom;
if (dom) {
realDom = dom;
} else if (component) {
realDom = React.createElement(component, {
...componentProps,
_context,
});
}
if (realDom) {
result.push(
<UICnFilterItem key={index} {...filterItemProps}>
{realDom}
</UICnFilterItem>,
);
}
}
});
return result;
}
return null;
};
const children = defer ? null : generateChildren();
const onSearch = useCallback(
(value) => {
emitEvent(CnFilterOnSearch, {
componentProps: props,
payload: value,
});
if (typeof originOnSearch === 'function') {
originOnSearch(value);
}
executeEventWithoutJS({
eventType: 'onSearch',
events: filterEvents,
_context,
position: ButtonPosition.filterEvent,
urlParamsDataSource: urlParams,
recordDataSource: value,
});
const { _bindTable } = props;
if (_bindTable && _context) {
const table = _context.$(_bindTable);
table?.load?.();
}
},
[originOnSearch],
);
const onChange = useCallback((values, temp) => {
const { name, value, field } = temp || {};
if (_dataSourceName) {
_context?.setState({
[_dataSourceName]: values,
});
}
executeEvent(values, name, value, field);
emitEvent(CnFilterOnChange, {
componentProps: props,
payload: values,
});
if (_bindTable && _context) {
const table = _context?.$?.(_bindTable);
table?.forceUpdate?.();
}
}, []);
const setDefaultValue = useCallback((v) => {
cacheDefaultValue.current = v;
if (isPlainObject(v)) {
for (const key in v) {
const tempV = v[key];
if (tempV?.name && tempV?.valueType === 'DefaultSelect') {
return;
}
}
}
if (waitComponentList.current?.length > 0) {
return;
}
onChange?.(v);
}, []);
useEffect(() => {
const {
dataOrigin,
requestConfig = {},
afterRequest = {},
} = defaultParams || {};
if (config.length > 0) {
config.forEach((item, index) => {
const { name } = item || {};
const need = needRequestRemote(item, defaultParams);
if (need) {
waitComponentList.current.push(name);
}
});
}
const p = getFormDefaultValue(defaultParams, {
urlParamsDataSource: urlParams,
state: _context?.state,
isDesign,
formConfig: config,
});
let newFormValue;
if (isPlainObject(p)) {
newFormValue = { ...(formValue || {}), ...(p || {}) };
setDefaultValue(newFormValue);
} else if (p?.then) {
p.then((result) => {
if (result) {
newFormValue = { ...(formValue || {}), ...(result || {}) };
setDefaultValue(newFormValue);
}
}).then((res) => {
setDefer(false);
if (dataOrigin === 'request' && requestConfig?.url) {
if (afterRequest?.optType) {
const action = getButtonAction({
...afterRequest,
position: ButtonPosition.filterDefaultValueAfterRequestSuccess,
});
action?.({
position: ButtonPosition.filterDefaultValueAfterRequestSuccess,
urlParamsDataSource: urlParams,
recordDataSource: newFormValue,
state: _context?.state,
buttonConfig: afterRequest,
_context,
});
}
}
});
}
// const { dataOrigin, defaultValue = {}, requestConfig = {}, afterRequest = {} } = defaultParams || {};
// if (dataOrigin === 'static') {
// if (defaultValue && is.plainObject(defaultValue) && Object.keys(defaultValue).length > 0) {
// setTimeout(() => {
// onChange?.({ ...(formValue || {}), ...(defaultValue || {}) });
// }, 100);
// }
// } else if (dataOrigin === 'request' && requestConfig?.url) {
// makeRequest({
// buttonConfig: {
// options: {
// requestConfig,
// },
// },
// urlParamsDataSource: urlParams,
// recordDataSource: {},
// state: _context?.state,
// needSuccessToast: false,
// }).then((res) => {
// const res2 = getRealResponse(res);
// const { success, data } = res2;
// if (success && is.plainObject(data) && Object.keys(data).length > 0) {
// onChange?.({ ...(formValue || {}), ...(data || {}) });
// if (afterRequest?.optType) {
// const action = getButtonAction({ ...afterRequest, position: ButtonPosition.filterDefaultValueAfterRequestSuccess });
// action?.({
// position: ButtonPosition.filterDefaultValueAfterRequestSuccess,
// urlParamsDataSource: urlParams,
// recordDataSource: formValue,
// state: _context?.state,
// buttonConfig: afterRequest,
// _context,
// });
// }
// }
// });
// }
onEvent(CnPageRequestFinish, () => {
setForceUpdate(Date.now());
});
}, []);
let extraProps = {
onReset,
};
if (filterStyle) {
extraProps = {
...extraProps,
...filterStyle,
};
}
extraProps.showBottomLine = true;
if (defer) {
return null;
}
let realFormValue = formValue || {};
if (isDesign === true) {
if (defaultParams?.dataOrigin === dataOriginStatic) {
const p = getFormDefaultValue(defaultParams, {
urlParamsDataSource: urlParams,
state: _context?.state,
isDesign,
formConfig: config,
});
if (isPlainObject(p)) {
realFormValue = p;
}
}
}
return (
<UICnFilter
ref={filterRef}
{...extraProps}
// field={field}
value={realFormValue}
onChange={onChange}
{...otherProps}
onSearch={onSearch}
>
{children}
</UICnFilter>
);
});
CnFilter.displayName = 'CnFilter';
export default CnFilter;