@cainiaofe/cn-ui-lowcode
Version:
305 lines (291 loc) • 7.87 kB
JavaScript
import React from 'react';
import { Box, CnAsyncTree } from '@cainiaofe/cn-ui';
import {
handleSelectRequestConfig,
isArrayNotEmpty,
isDesignMode,
makeButtons,
mergeHandleProps,
setDataToDs,
} from '@/common/util/util';
import { getButtonAction } from '@/common/manager/button';
import { ButtonPosition } from '@/common/manager/position/button-position';
import {
__left_tree_currentItem__,
__left_tree_currentValue__,
__stateValueOfSplit__,
} from '@/common/util/expr-const';
import cloneDeep from 'lodash/cloneDeep';
import get from 'lodash/get';
import isPlainObject from 'lodash/isPlainObject';
class CnLeftTree extends React.Component {
constructor(props) {
super(props);
this.remoteInstance = CnAsyncTree?.createRemoteInstance?.();
this.treeRef = null;
}
getUrlParams = () => {
const { _context } = this.props;
return _context?.state?.urlParams || {};
};
load = () => {
const p = this.remoteInstance?.load?.();
if (typeof p?.then === 'function') {
p.then((res) => {
this.refreshCurrentItem();
});
}
};
refreshCurrentItem = () => {
const { _context, _dataSourceName } = this.props;
const currentItem =
_context?.state?.[_dataSourceName]?.[__left_tree_currentItem__];
if (currentItem && isArrayNotEmpty(this.treeRef?.dataSource)) {
const { pos } = currentItem;
if (typeof pos === 'string') {
const path = pos?.slice(2)?.replaceAll('-', '-children-')?.split('-');
const newCurrent = get(this.treeRef?.dataSource, path);
if (newCurrent && newCurrent?.value === currentItem?.value) {
this.setDataSource({
[__left_tree_currentItem__]: newCurrent,
});
}
}
}
};
makeButtons = () => {
const { treeNodeButtons, _context } = this.props;
if (isArrayNotEmpty(treeNodeButtons)) {
return makeButtons({
buttons: treeNodeButtons.map((item) => {
return {
...item,
position: ButtonPosition.treeNode,
text: true,
type: 'primary',
style: {
marginLeft: '5px',
},
};
}),
_context,
state: _context?.state,
urlParamsDataSource: this.getUrlParams(),
recordDataSource: {},
});
}
};
setDataSource = (data) => {
if (data) {
const { _context, _dataSource, _dataSourceName } = this.props;
setDataToDs({
_context,
_dataSource,
_dataSourceName,
data,
});
}
};
executeEvent = (config) => {
const { eventType, afterDropDataSource } = config;
const { events, _context } = this.props;
if (isArrayNotEmpty(events)) {
for (const item of events) {
const { name: eventName } = item;
if (eventName === eventType) {
const action = getButtonAction({
...item,
position: ButtonPosition.treeEvent,
});
if (typeof action === 'function') {
action({
buttonConfig: {
...item,
position: ButtonPosition.treeEvent,
options: {
...item,
},
},
position: ButtonPosition.treeEvent,
state: _context?.state,
urlParamsDataSource: this.getUrlParams(),
_context,
recordDataSource: {},
getExtraParam: () => {
return {
afterDropDataSource,
};
},
});
}
}
}
}
};
onDrop = (info) => {
const { dragNode } = info || {};
if (!dragNode) {
return;
}
if (isArrayNotEmpty(this.treeRef?.dataSource)) {
const dragKey = info.dragNode?.props?.eventKey;
const dropKey = info.node?.props?.eventKey;
const { dropPosition } = info;
const loop = (data, key, callback) => {
data.forEach((item, index, arr) => {
if (item.key === key) {
return callback(item, index, arr);
}
if (item.children) {
return loop(item.children, key, callback);
}
});
};
const data = cloneDeep(this.treeRef?.dataSource);
let dragObj;
loop(data, dragKey, (item, index, arr) => {
arr.splice(index, 1);
dragObj = item;
});
if (info.dropPosition === 0) {
loop(data, dropKey, (item) => {
item.children = item.children || [];
item.children.push(dragObj);
});
} else {
let ar;
let i;
loop(data, dropKey, (item, index, arr) => {
ar = arr;
i = index;
});
if (dropPosition === -1) {
ar.splice(i, 0, dragObj);
} else {
ar.splice(i + 1, 0, dragObj);
}
}
if (isArrayNotEmpty(data)) {
this.executeEvent({
eventType: 'onDrop',
afterDropDataSource: data,
});
}
}
};
render() {
const extraProps = {};
const isDesign = isDesignMode(this.props);
const urlParamsDataSource = this.getUrlParams();
const {
children,
_context,
title,
_dataSource,
_dataSourceName,
dataOrigin,
requestConfig,
treeStyle,
handleProps,
defaultParams,
...rest
} = this.props;
const { draggable } = treeStyle || {};
if (draggable === true) {
extraProps.onDrop = this.onDrop;
}
const tempConfig = {
componentProps: {
requestConfig,
dataOrigin,
},
urlParamsDataSource,
recordDataSource: {},
state: _context?.state,
handleDynamicUrl: true,
};
handleSelectRequestConfig(tempConfig, { dynamicParams: true });
if (isDesign) {
extraProps.defaultExpandAll = true;
extraProps.dataSource = [
{
label: '树节点示例',
value: 'tree1',
children: [
{
label: '子节点示例',
value: 'sub1',
},
],
},
];
} else {
extraProps.instance = this.remoteInstance;
extraProps.requestConfig = tempConfig?.componentProps?.requestConfig;
}
let realComponentProps = {
...treeStyle,
selectable: true,
...rest,
...(defaultParams || {}),
};
const temp = mergeHandleProps({
handleProps,
componentProps: realComponentProps,
_context,
});
if (isPlainObject(temp)) {
realComponentProps = temp;
}
let rightDom = (
<div
style={{
flex: 3,
height: '100%',
overflow: 'auto',
borderLeft: '1px solid #e5e5e5',
}}
className=''
>
{children}
</div>
);
if (!isDesign && !children) {
rightDom = null;
}
return (
<div className=''>
<Box spacing={12} direction='row'>
<div
style={{
flex: 1,
maxWidth: '288px',
}}
>
<CnAsyncTree
ref={(c) => (this.treeRef = c)}
{...extraProps}
treeArea={() => {
return this.makeButtons();
}}
onChange={(key, item) => {
this.setDataSource({
[__left_tree_currentValue__]: key,
[__left_tree_currentItem__]: item,
});
this.executeEvent({
eventType: 'onChange',
});
}}
{...realComponentProps}
/>
</div>
{rightDom}
</Box>
</div>
);
}
}
CnLeftTree.displayName = 'CnLeftTree';
export default CnLeftTree;
export { CnLeftTree };