@cainiaofe/cn-ui-lowcode
Version:
438 lines (416 loc) • 11.8 kB
JavaScript
import React, {
useCallback,
useEffect,
useState,
forwardRef,
useImperativeHandle,
} from 'react';
import {
CnStep as UICnStep,
CnStepItem,
Box,
CnButton,
} from '@cainiaofe/cn-ui';
import {
calculateTextExprValue,
executeFunction,
executeObjectExpr,
isArrayNotEmpty,
isDesignMode,
isEmptyButNotZero,
isRequestConfig,
setDataToDs,
} from '@/common/util/util';
import {
getButtonAction,
getItem as getButtonItem,
} from '@/common/manager/button';
import { ButtonPosition } from '@/common/manager/position/button-position';
import isPlainObject from 'lodash/isPlainObject';
import {
__dataSource__,
__step_activeKey__,
__step_current__,
__step_currentItem__,
__step_list__,
} from '@/common/util/expr-const';
import { dataOriginRequest } from '@/common/util/const';
import { getRealResponse, makeRequest } from '@/common/util/request';
const CnStep = forwardRef((props, ref) => {
if (!UICnStep) {
return null;
}
useImperativeHandle(ref, () => ({
changeStep(...arg) {
changeStep(...arg);
},
load(...arg) {
load(arg);
},
}));
const {
steps: propSteps,
stepStyle,
current: propsCurrent,
leftButtons,
rightButtons,
_dataSource,
_dataSourceName,
_context,
dataOrigin,
requestConfig,
events,
} = props;
const isDesign = isDesignMode(props);
const findCurrent = (list, tempCurrent) => {
let result = tempCurrent;
if (typeof tempCurrent === 'number') {
} else {
const tempActiveKey = calculateTextExprValue(tempCurrent, {
state: _context?.state,
recordDataSource: {},
});
if (typeof tempActiveKey === 'number') {
result = tempActiveKey;
} else {
if (typeof result === 'function') {
result = undefined;
}
for (const index in list) {
const item = list[index];
const { key } = item || {};
if (key === tempActiveKey) {
result = +index;
break;
}
}
}
}
return result;
};
const filterHiddenStep = (list) => {
const result = [];
if (Array.isArray(list)) {
list.forEach((item) => {
const { hidden } = item || {};
const isHidden = executeObjectExpr(hidden, {}, {}, _context?.state);
if (isHidden !== true) {
result.push(item);
}
});
}
return result;
};
let initialSteps = filterHiddenStep(propSteps);
if (dataOrigin === dataOriginRequest) {
initialSteps = [];
}
const [steps, setSteps] = useState(initialSteps);
const [current, setCurrent] = useState(findCurrent(steps, propsCurrent));
useEffect(() => {
if (dataOrigin !== dataOriginRequest) {
setSteps(filterHiddenStep(propSteps));
}
}, [propSteps]);
useEffect(() => {
if (dataOrigin !== dataOriginRequest) {
setCurrent(findCurrent(steps, propsCurrent));
}
}, [propsCurrent]);
const executeEvent = (config) => {
const { eventType } = config || {};
const { events } = props;
if (isArrayNotEmpty(events)) {
for (const item of events) {
const { name: eventName } = item || {};
if (eventName === eventType) {
const action = getButtonAction({
...item,
position: ButtonPosition.stepEvent,
});
if (typeof action === 'function') {
action({
buttonConfig: {
...item,
position: ButtonPosition.stepEvent,
options: {
...item,
},
},
position: ButtonPosition.stepEvent,
state: _context?.state,
urlParamsDataSource: _context?.state?.urlParams || {},
_context,
recordDataSource: {},
});
}
}
}
}
};
const getActiveKeyByIndex = (list, index) => {
if (typeof index === 'number' && isArrayNotEmpty(list)) {
const temp = list[index];
if (temp?.key) {
return temp.key;
}
}
};
const changeStep = (newIndex, config) => {
const { needSetState } = config || {};
let realIndex;
if (typeof newIndex === 'number') {
realIndex = newIndex;
} else {
realIndex = findCurrent(steps, newIndex);
}
if (typeof realIndex === 'number') {
if (needSetState) {
setCurrent(realIndex);
}
setDataToDs({
_context,
_dataSource,
_dataSourceName,
data: {
[__step_current__]: realIndex,
[__step_activeKey__]: getActiveKeyByIndex(steps, newIndex),
[__step_currentItem__]: steps[newIndex] || {},
},
});
setTimeout(() => {
executeEvent({
eventType: 'onStepItemClick',
});
});
}
};
const handleStep = (steps) => {
if (isDesign && dataOrigin === dataOriginRequest) {
return [
<CnStepItem key={'unique'} title={'动态Step,请到预览页面查看'} />,
];
}
const result = [];
if (Array.isArray(steps) && steps.length > 0) {
steps.forEach((item, index) => {
const { title, content, key, ...rest } = item;
if (key) {
result.push(
<CnStepItem
{...rest}
key={index}
title={title}
content={content}
onClick={changeStep}
/>,
);
}
});
}
return result;
};
const handleButtons = useCallback((leftButtons, rightButtons) => {
function handle(buttons) {
if (Array.isArray(buttons) && buttons.length > 0) {
const result = [];
buttons.forEach((item) => {
const { children, disabled, hidden, optType, type } = item || {};
const action = getButtonAction({
...item,
position: ButtonPosition.step,
});
const getRenderDom = getButtonItem(
ButtonPosition.step,
optType,
'getRenderDom',
);
const isDisabled = executeObjectExpr(
disabled,
{
[__step_current__]: current,
[__dataSource__]: _context?.state,
},
current,
_context?.state,
);
const isHidden = executeObjectExpr(
hidden,
{
[__step_current__]: current,
[__dataSource__]: _context?.state,
},
current,
_context?.state,
);
if (isHidden !== true) {
if (typeof getRenderDom === 'function') {
result.push(
executeFunction(getRenderDom, {
_context,
buttonConfig: item,
state: _context?.state,
urlParamsDataSource: _context?.state?.urlParams || {},
}),
);
} else {
result.push(
<CnButton
type={type}
disabled={isDisabled}
onClick={() => {
if (typeof action === 'function') {
action({
buttonConfig: item,
state: _context?.state,
urlParamsDataSource: _context?.state?.urlParams || {},
_context,
position: ButtonPosition.step,
});
}
}}
size={'large'}
>
{children}
</CnButton>,
);
}
}
});
if (result.length > 0) {
return (
<Box
// className="cn-ui-form-footer-footer"
style={{ alignItems: 'center' }}
spacing={8}
direction='row'
>
{result}
</Box>
);
}
}
}
const leftSlot = handle(leftButtons);
const rightSlot = handle(rightButtons);
if (leftSlot || rightSlot) {
return {
hasCnPageFooter: true,
cnPageFooterProps: {
leftSlot,
rightSlot,
},
};
}
}, []);
const stepProps = {
...stepStyle,
current,
...handleButtons(leftButtons, rightButtons),
};
const getUrlParams = () => {
return _context?.state?.urlParams || {};
};
const load = () => {
if (dataOrigin === dataOriginRequest) {
let realSteps;
let realCurrent;
if (isRequestConfig(requestConfig)) {
makeRequest({
buttonConfig: {
options: {
requestConfig,
},
},
urlParamsDataSource: getUrlParams(),
recordDataSource: {},
state: _context?.state || {},
needSuccessToast: false,
isDesign,
})
.then((res) => {
const res2 = getRealResponse(res);
const { success, data } = res2;
if (success) {
if (isPlainObject(data)) {
const { list: originList, activeKey: originalActiveKey } = data;
const list = filterHiddenStep(originList);
if (isArrayNotEmpty(list)) {
let tempCurrent;
const newList = [];
if (typeof originalActiveKey === 'number') {
tempCurrent = originalActiveKey;
}
for (const index in list) {
const { label, value, title, key } = list[index];
const realKey = key || value;
if (
typeof originalActiveKey === 'string' &&
originalActiveKey === realKey
) {
tempCurrent = +index;
}
const temp = {
...list[index],
title: label || title,
key: realKey,
};
if (title) {
temp.title = title;
}
newList.push(temp);
}
if (isEmptyButNotZero(tempCurrent)) {
tempCurrent = 0;
}
realSteps = newList;
realCurrent = tempCurrent;
setDataToDs({
_context,
_dataSource,
_dataSourceName,
data: {
[__step_list__]: newList,
[__step_current__]: tempCurrent,
[__step_activeKey__]: getActiveKeyByIndex(
newList,
tempCurrent,
),
[__step_currentItem__]: newList[tempCurrent] || {},
},
});
}
}
}
})
.finally(() => {
setSteps(realSteps);
setCurrent(realCurrent);
});
}
}
};
useEffect(() => {
if (dataOrigin === dataOriginRequest) {
load();
} else {
setDataToDs({
_context,
_dataSource,
_dataSourceName,
data: {
[__step_list__]: steps,
[__step_current__]: current,
[__step_activeKey__]: getActiveKeyByIndex(steps, current),
},
});
}
}, []);
return (
<div className=''>
<UICnStep {...stepProps}>{handleStep(steps)}</UICnStep>
</div>
);
});
CnStep.displayName = 'CnStep';
export default CnStep;