UNPKG

@cainiaofe/cn-ui-lowcode

Version:
592 lines (572 loc) 17.7 kB
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;