hc-components-test
Version:
基于react的通用组件库
326 lines (311 loc) • 11.2 kB
JSX
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import Collapse from 'antd/lib/collapse';
import Input from 'antd/lib/input';
import Tooltip from 'antd/lib/tooltip';
import Icon from 'antd/lib/icon';
import Alert from 'antd/lib/alert';
import {DragItem} from '../dnd/dragItem';
import './index.less';
export class TagSearcher extends Component {
static propTypes = {
entityCode: PropTypes.string.isRequired,
tagCode: PropTypes.string.isRequired,
keyword: PropTypes.string.isRequired,
objectList: PropTypes.array.isRequired,
doFetchTagList: PropTypes.func.isRequired
}
static defaultProps = {
entityCode: '',
tagCode: '',
keyword: '',
objectList: []
}
constructor(props) {
super(props);
this.state = {
keyword: '',
entityCode: '',
tagCode: '',
objectList: [],
tagsMap: {},
dimsMap: {}
};
this.handleChange(props.entityCode, props.tagCode, props.objectList);
}
componentWillReceiveProps(nextProps) {
// #! objectList发生变化时因为请求单个entity的tagList #! 只有可能改变entityCode和tagCode, 用来定位
const mergeProps = {
entityCode: this.state.entityCode,
tagCode: this.state.tagCode,
objectList: this.state.objectList,
keyword: this.state.keyword
};
let keyword = this.state.keyword;
let hasReceive = true;
switch(true){
case this.props.entityCode !== nextProps.entityCode:
mergeProps.entityCode = nextProps.entityCode;
break;
case this.props.tagCode !== nextProps.tagCode:
mergeProps.tagCode = nextProps.tagCode;
break;
case nextProps.objectList !== this.props.objectList:
mergeProps.objectList = nextProps.objectList;
break;
case this.props.keyword !== nextProps.keyword:
keyword = '';
// #! 因为setState是异步的
this.setState({keyword: ''});
mergeProps.keyword = nextProps.keyword;
break;
default:
hasReceive = false;
break;
}
if (hasReceive) {
// #! 搜索时,请求tagList会导致objectList更新
if (keyword) {
const [entityCodeOrName] = this
.state
.keyword
.split('.');
const objectList = nextProps
.objectList
.filter(item => item.entityCode.indexOf(entityCodeOrName) > -1 || item.entityName.indexOf(entityCodeOrName) > -1);
this.handleChange(mergeProps.entityCode, mergeProps.tagCode, objectList);
} else if (mergeProps.keyword) {
this.handleSearch(mergeProps.keyword);
} else {
this.handleChange(mergeProps.entityCode, mergeProps.tagCode, mergeProps.objectList);
}
}
}
shouldComponentUpdate(nextProps, nextState) {
return this.props !== nextProps || this.state !== nextState;
}
getDims(object) {
// #! entity
if (object.dims) {
return object
.dims
.map(dim => ({name: dim.dimCode, code: dim.dimId, entityCode: object.entityCode}));
// #! link
} else if (object.objects) {
return object
.objects
.map(obj => ({
name: obj.entityCode + '.' + obj.dims[0].dimCode,
code: obj.relationshipId,
entityCode: object.entityCode
}));
}
}
// #! 展开object或者定位object和tag
handleChange(entityCode, tagCode, objectList) {
const tagsMap = {};
const dimsMap = {};
const object = entityCode ?
objectList.find(item => item.entityCode === entityCode) :
objectList[0];
let focusItem;
if (object) {
// #! 需要定位的元素, 定位到entity
if (entityCode) {
focusItem = object;
}
if (object.tagList) {
tagsMap[entityCode] = {
list: object.tagList
};
if (tagCode) {
// #! 如果有tagCode则是定位到tag
focusItem = object
.tagList
.find(tag => tag.tagCode === tagCode);
tagsMap[entityCode].tagCode = focusItem ? focusItem.tagCode : '';
}
} else if (entityCode) {
tagsMap[entityCode] = {
loading: true,
list: []
};
// #! 请求
this
.props
.doFetchTagList(entityCode);
}
dimsMap[entityCode] = this.getDims(object);
}
if (focusItem) { // undefined表示collaspse的点击
// 延迟200毫秒后定位
}
this.setState({
tagCode,
entityCode,
objectList,
tagsMap,
dimsMap
});
}
handleSearch(keyword) {
const [entityCodeOrName,
tagCodeOrName] = keyword.split('.');
const tagsMap = {};
const dimsMap = {};
let objectList = this.props.objectList;
if (entityCodeOrName) {
objectList = objectList.filter(item => {
// #! 匹配name或者code
if (item.entityCode.indexOf(entityCodeOrName) > -1 || item.entityName.indexOf(entityCodeOrName) > -1) {
if (tagCodeOrName) {
if (item.tagList) {
// #! 匹配name或者code
tagsMap[item.entityCode] = {
list: item
.tagList
.filter(tag => tag.tagCode.indexOf(tagCodeOrName) > -1 || tag.tagName.indexOf(tagCodeOrName) > -1)
};
} else {
tagsMap[item.entityCode] = {
loading: true,
list: []
};
this
.props
.doFetchTagList(item.entityCode);
}
} else {
if (item.tagList) {
tagsMap[item.entityCode] = {
list: item.tagList
};
} else {
tagsMap[item.entityCode] = {
loading: true,
list: []
};
this
.props
.doFetchTagList(item.entityCode);
}
dimsMap[item.entityCode] = this.getDims(item);
}
return true;
} else {
return false;
}
});
}
const entityCode = objectList[0] && objectList[0].entityCode;
const tagCode = tagsMap[entityCode] && tagsMap[entityCode].list.length && tagsMap[entityCode].list[0].tagCode;
this.setState({entityCode: entityCode, tagCode: tagCode, objectList, tagsMap, dimsMap});
}
clearSearch() {
this.setState({keyword: ''});
this.handleSearch('');
}
render() {
const {keyword, entityCode, objectList, tagsMap, dimsMap} = this.state;
// #! 判断是否需要拖拽
const doDrag = this.props.doDrag;
let ItemDom = DragItem;
if (!doDrag) {
ItemDom = React.createClass({
render() {
return (
<div>{this.props.children}</div>
)
}
});
}
// #! 遍历输出所有object,
// 展开的object必然有dims,不展开则没有;展开的object必然有tagList(分为空和有列表数据,!!完全找不到则需要发请求去拿),不展开则没有
// 。 #! handleChange,展开object;handleSearch,搜索object或tag
return (
<div className="j-com-tagSearcher">
<Input.Search
placeholder={this.props.searchPlaceholder || '使用 实体.标签 进行模糊搜索'}
value={keyword}
suffix={keyword ? (<Icon type="close-circle" onClick={() => this.clearSearch()} />) : null}
onChange={(e) => {
this.setState({keyword: e.target.value});
}}
onSearch={() => this.handleSearch(this.state.keyword)} />
<div className="j-com-elem-oltList">
{this.props.keyword ? (<Alert message="通过判定式定位" type="info" closable onClose={() => this.clearSearch()} />) : null}
<Collapse
accordion
activeKey={entityCode}
onChange={(key) => this.handleChange(key, '', objectList)}>
{objectList.map(entity => {
return (
<Collapse.Panel
key={entity.entityCode}
header={(
<ItemDom key={entity.entityCode} doAction={doDrag} type="entity" data={entity}>
<div className="j-com-elem-icon-entity"></div>
<span title={`${entity.entityCode}(${entity.entityName})`}>
{`${entity.entityCode}(${entity.entityName})`}
</span>
</ItemDom>
)}>
<ul>
{dimsMap[entity.entityCode] && dimsMap[entity.entityCode].map((dim, index) => {
return (
<li key={index}>
<ItemDom key={dim.code} doAction={doDrag} type="dim" data={dim}>
<div className="j-com-elem-icon-dim"></div>
<Tooltip
placement="right"
title={`${entity.entityType === 'object' && '实体' || '关系'}(${entity.entityName})下可用的标签`}>
<Icon type="pushpin-o" className="j-com-elem-icon-pushpin-o" />
</Tooltip>
<span title={dim.name}>
{dim.name}
</span>
</ItemDom>
</li>
);
})}
</ul>
<ul>
{tagsMap[entity.entityCode] && (tagsMap[entity.entityCode].loading ?
(
<li>
<span>正在拉取...</span>
</li>
) :
tagsMap[entity.entityCode].list.length ?
tagsMap[entity.entityCode].list.map((tag, index) => {
return (
<li key={index}>
<ItemDom key={tag.tagCode} doAction={doDrag} type="tag" data={tag}>
<div className="j-com-elem-icon-tag"></div>
<Tooltip
placement="right"
title={`${entity.entityType === 'object' && '实体' || '关系'}(${entity.entityName})下可用的标签`}>
<Icon type="tag-o" className="j-com-elem-icon-tag-o" />
</Tooltip>
<span title={`${tag.tagCode}(${tag.tagName})`}>
{`${tag.tagCode}(${tag.tagName})`}
</span>
</ItemDom>
</li>
);
}) :
(
<li>
<span>无标签</span>
</li>
))}
</ul>
</Collapse.Panel>
);
})}
</Collapse>
</div>
</div>
);
}
}