@cainiaofe/cn-ui-lowcode
Version:
550 lines (517 loc) • 14.3 kB
JavaScript
import React from 'react';
import {
CnTab as UICnTab,
CnTabItem as UICnTabItem,
CnIcon,
} from '@cainiaofe/cn-ui';
import './view.scss';
import isFunction from 'lodash/isFunction';
import {
calculateTextExprValue,
executeFunction,
executeObjectExpr,
isDesignMode,
isEmptyButNotZero,
isRequestConfig,
setDataToDs,
} from '@/common/util/util';
import { componentMap } from '@/common/manager/event';
import { getRealResponse, makeRequest } from '@/common/util/request';
import isPlainObject from 'lodash/isPlainObject';
import {
__dataSource__,
__tab_activeKey__,
__tab_removeKey__,
__tab_addKey__,
} from '@/common/util/expr-const';
import { getButtonAction } from '@/common/manager/button';
import { ButtonPosition } from '@/common/manager/position/button-position';
import {
CnFilterDefaultValueFinished,
CnFilterOnChange,
CnFilterOnSearch,
emitEvent,
onEvent,
} from '@/common/util/event-name';
import {
dataOriginRequest,
dataOriginStatic,
} from '@/common/util/const';
import merge from 'lodash/merge';
class CnTab extends React.Component {
constructor(props) {
super(props);
// const activeKey = props.defaultActiveKey;
//
// const activeItem = this.findItem(activeKey);
// this.state = {
// activeKey: activeItem?.primaryKey,
// };
const defaultActiveKey = this.getDefaultActiveKey();
this.state = {
activeKey: defaultActiveKey,
itemList: [],
};
this.setDataSource({
[__tab_activeKey__]: defaultActiveKey,
});
// this.indexesCache = [];
}
setDataSource = (data) => {
if (data) {
const { _context, _dataSource, _dataSourceName } = this.props;
setDataToDs({
_context,
_dataSource,
_dataSourceName,
data,
});
}
};
getDefaultActiveKey = () => {
const { dataOrigin, items, _context, activeKey } = this.props;
if (dataOrigin !== 'request') {
let first;
if (activeKey) {
first = calculateTextExprValue(activeKey, {
state: _context?.state,
recordDataSource: {},
});
} else {
if (Array.isArray(items)) {
for (const item of items) {
const { primaryKey, hidden } = item;
if (primaryKey) {
const isHidden = executeObjectExpr(
hidden,
{},
{},
_context?.state,
);
if (isHidden !== true) {
first = primaryKey;
break;
}
}
}
}
if (first === undefined) {
first = items[0]?.primaryKey;
}
}
return first;
}
};
getItems = () => {
const { items = [] } = this.props;
const { itemList = [] } = this.state;
const { dataOrigin } = this.props;
if (dataOrigin === 'request') {
return itemList;
}
return items;
};
getUrlParams = () => {
const { _context } = this.props;
return _context?.state?.urlParams || {};
};
getData = () => {
const isDesign = isDesignMode(this.props);
const { dataOrigin, requestConfig, _context } = this.props;
if (dataOrigin === 'request' && isRequestConfig(requestConfig)) {
return makeRequest({
buttonConfig: {
options: {
requestConfig,
},
},
urlParamsDataSource: this.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, activeKey: originalActiveKey } = data;
const state = {
itemList: [],
};
if (Array.isArray(list) && list.length > 0) {
const newList = list.map((item) => {
if (isPlainObject(item)) {
const { label, value, title, primaryKey, key } = item;
if (isEmptyButNotZero(title) && label) {
item.title = label;
}
if (isEmptyButNotZero(primaryKey) && value) {
item.primaryKey = value;
}
if (isEmptyButNotZero(item.primaryKey) && key) {
item.primaryKey = key;
}
}
return { ...item };
});
let activeKey = originalActiveKey;
if (isEmptyButNotZero(activeKey)) {
activeKey = newList[0]?.primaryKey;
}
state.itemList = newList;
if (activeKey !== undefined) {
state.activeKey = activeKey;
this.setDataSource({
[__tab_activeKey__]: activeKey,
});
}
} else if (originalActiveKey !== undefined) {
state.activeKey = originalActiveKey;
this.setDataSource({
[__tab_activeKey__]: originalActiveKey,
});
}
this.setState(state);
this.executeEvent({
eventType: 'onTabRequestFinish',
activeKey: state.activeKey,
});
}
}
});
}
};
componentDidMount() {
const p = this.getData();
const { dataOrigin, requestConfig, _context } = this.props;
if (dataOrigin === dataOriginStatic) {
setTimeout(() => {
emitEvent(CnFilterDefaultValueFinished, {
componentProps: this.props,
formValues: {},
});
});
} else if (dataOrigin === dataOriginRequest) {
if (typeof p?.finally === 'function') {
p.finally((res) => {
emitEvent(CnFilterDefaultValueFinished, {
componentProps: this.props,
formValues: {},
});
});
}
}
onEvent(CnFilterOnChange, (tableInfo) => {
this.forceUpdate();
});
}
renderTitle(title, props) {
const { _customRenderTabItem = () => null, _context } = this.props;
if (isFunction(_customRenderTabItem)) {
const customTitle = executeFunction(
_customRenderTabItem,
props,
_context?.state,
);
if (customTitle) {
return customTitle;
}
}
return title;
}
clickClose(removeKey) {
this.setDataSource({
[__tab_removeKey__]: removeKey,
});
this.executeEvent({
eventType: 'onTabDeleteItemClick',
activeKey: removeKey,
});
}
clickTab = (tabKey) => {
const items = this.getItems();
const current = items.find((item) => {
if (item) {
return item.primaryKey === tabKey;
}
});
if (current) {
const { optType, url, redirectType } = current;
if (optType === 'link' && url && redirectType) {
if (redirectType === 'current') {
location.href = url;
} else if (redirectType === 'open') {
window.open(url);
}
}
}
};
renderTabItems() {
const items = this.getItems();
const { children, _context, dataOrigin, _customRenderTabItem } = this.props;
let tabItems;
if (dataOrigin === 'request') {
if (items.length > 0) {
tabItems = items.map((item) => {
const { title, primaryKey, disabled, closeable } = item;
let realTitle = title;
if (typeof _customRenderTabItem === 'function') {
const tempTitle = executeFunction(
_customRenderTabItem,
item,
_context?.state,
);
if (tempTitle) {
realTitle = tempTitle;
}
}
return (
<UICnTabItem
title={realTitle}
key={primaryKey}
disabled={disabled}
closeable={closeable}
/>
);
});
}
} else {
const isDesign = isDesignMode(this.props);
const safeChildren = Array.isArray(children) ? children : [children];
tabItems = safeChildren.map((child, index) => {
if (!child) {
return null;
}
let childProps;
if (Array.isArray(items) && items[index]) {
childProps = items[index];
} else if (child.props.componentSchema) {
childProps = child.props.componentSchema.props;
} else {
childProps = child.props;
}
const hidden = executeObjectExpr(
childProps?.hidden,
{},
{},
_context?.state,
);
if (hidden === true) {
return null;
}
// const tabContentChildren = child?.props?.children;
const title = this.renderTitle(childProps.title, childProps);
// let paddingClassName = 'cn-tab-page-content';
// if(isDesign) {
// if(tabContentChildren?.[0]?.props?.isCnTab === true) {
// paddingClassName = ''
// }
// }else{
// if(tabContentChildren?.props?.isCnTab === true) {
// paddingClassName = ''
// }
// }
return (
<UICnTabItem
title={title}
key={childProps.primaryKey}
disabled={childProps.disabled}
closeable={childProps.closeable}
>
{child}
</UICnTabItem>
);
});
}
return tabItems;
}
findItem(activeKey) {
const items = this.getItems();
let ret;
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (
activeKey === item.primaryKey ||
(item.customKey && item.customKey === activeKey)
) {
ret = item;
break;
}
}
return ret ? { ...ret, customKey: ret.customKey || ret.primaryKey } : null;
}
setTabActiveKey = (activeKey) => {
this.setDataSource({
[__tab_activeKey__]: activeKey,
});
this.setState({
activeKey,
});
this.executeEvent({
eventType: 'onChange',
activeKey,
});
emitEvent(CnFilterOnSearch, {
componentProps: this.props,
payload: {},
});
// const { onTabChange, onChange, fieldId, traceable } = this.props;
// const activeItem = this.findItem(activeKey);
// const key = activeItem?.customKey;
// const changeHandle = onTabChange || onChange;
// this.setState(
// {
// activeKey: activeItem.primaryKey,
// },
// () => {
// if (isFunction(changeHandle)) {
// const activeIndex = this.indexesCache.indexOf(key) + 1;
// changeHandle(activeIndex, key, activeItem);
// }
// },
// );
};
executeEvent = (config) => {
const { eventType, activeKey } = config;
const { events, _context } = this.props;
if (Array.isArray(events) && events.length > 0) {
for (const item of events) {
const { name: eventName, optType, flowList } = item;
if (eventName === eventType) {
const action = getButtonAction({
...item,
position: ButtonPosition.tabEvent,
});
if (typeof action === 'function') {
action({
buttonConfig: {
...item,
position: ButtonPosition.tabEvent,
options: {
...item,
},
},
position: ButtonPosition.tabEvent,
state: _context?.state,
urlParamsDataSource: this.getUrlParams(),
_context,
recordDataSource: activeKey,
});
}
}
}
}
};
addTab() {
this.executeEvent({
eventType: componentMap?.onTabAddItemClick?.value,
});
}
renderTabAdd() {
const { addTabOpen, dataOrigin, _context } = this.props;
const realIsOpen =
dataOrigin === 'request' &&
(isFunction(addTabOpen)
? executeFunction(addTabOpen, {}, _context?.state)
: addTabOpen);
return (
realIsOpen && (
<CnTabItem
onClick={this.addTab.bind(this)}
key='operation'
icon={<CnIcon type='add' />}
/>
)
);
}
render() {
const {
shape,
size,
excessMode,
tabPosition,
contentPadding,
unmountInactiveTabs,
extraRender,
tabRender,
onClose,
// items,
children,
lazyLoad = true,
dataOrigin,
className,
handleProps,
_context,
} = this.props;
const { activeKey } = this.state;
const isDesign = isDesignMode(this.props);
const tabProps = {
animation: false,
shape,
size,
activeKey,
excessMode,
tabPosition,
unmountInactiveTabs,
onClose,
lazyLoad,
className,
};
// if (contentPadding) {
// tabProps.contentStyle = {
// padding: contentPadding,
// };
// }
if (isFunction(extraRender)) {
tabProps.extra = extraRender();
}
if (isFunction(tabRender)) {
tabProps.tabRender = tabRender;
}
if (isDesign && dataOrigin === 'request') {
return (
<UICnTab {...tabProps} smartPadding>
<UICnTabItem
title={'动态Tab,请到预览页面查看'}
key={'dynamic_tab'}
/>
</UICnTab>
);
}
let realProps = {
smartPadding: true,
};
if (typeof handleProps === 'function') {
const tempProps = executeFunction(
handleProps,
{ ...realProps },
_context?.state,
);
if (isPlainObject(tempProps)) {
realProps = merge(realProps, tempProps);
}
}
return (
<UICnTab
onChange={this.setTabActiveKey}
{...tabProps}
onClick={this.clickTab}
onClose={this.clickClose.bind(this)}
{...realProps}
>
{this.renderTabItems()}
{this.renderTabAdd()}
</UICnTab>
);
}
}
CnTab.displayName = 'CnTab';
class CnTabItem extends React.Component {
static displayName = 'CnTabItem';
render() {
return <>{this.props.children}</>;
}
}
export default [CnTab, CnTabItem];
export { CnTab, CnTabItem };