OrgChat.js 8.0 KB
import React,{PropTypes} from 'react';   
import cx from 'classnames';
import s from './OrgChat.scss';
import {getCompany, getOrganizations, getEmployeeCount}  from '../../utils/orgUtil';

 
class OrgChat extends React.Component {
	constructor (props) {
	    super(props);    
	    this.renderNode=this.renderNode.bind(this);
	    this.toggleNode=this.toggleNode.bind(this);
	    this.showOrganization=this.showOrganization.bind(this);
	    this.state={ 
            company : {},
            nodes:{},
            subNodeLookup:{},
            rootNode:'',
            employeeCount:0
	    }
	} 
	static propTypes = {    
	}  
	static defaultProps = {   
	} 
	toggleNode(uuid){
		const {nodes,subNodeLookup}=this.state,self=this;
		const node=nodes[uuid];
		if(node&&node.expand){
			node.expand=false;
		}else{
			node.expand=true;
		}
		nodes[uuid]=node;
		this.setState({
			nodes
		})
	}
	loadSubNode(pId){
		const {nodes,subNodeLookup}=this.state,self=this;
		const cols=subNodeLookup[pId];
		const node=nodes[pId];
		if(node.expand){
			node.expand=false;
		}else{
			node.expand=true;
		}
		nodes[pId]=node;
		this.setState({
			nodes
		});
		if(cols&&cols.length>0){
			return null;
		}
		getOrganizations({pId}).then((data)=>{ 
            if (data.items&&data.items.length>0) { 
                for (let item of data.items) { 
                    const uuid=item.uuid; 
                    nodes[uuid]=item; 
                    subNodeLookup[uuid]=[];
                    if(subNodeLookup[item.parent_organization_ID]){
                    	subNodeLookup[item.parent_organization_ID].push(item);
                    } 
                }
            } 
            self.setState({
            	nodes,
            	subNodeLookup
            })
            if(data.items&&data.items.length>0){
            	for (let item of data.items) { 
            		const uuid=item.uuid; 
	            	getEmployeeCount({id:uuid}).then((dataCount)=>{
	                	nodes[uuid]['employeeCount']=dataCount.count; 
	                	self.setState({
			            	nodes 
			            });
		            });
	            }
            }
        });
	}
	componentDidMount(){
		const self = this;
		const {nodes,subNodeLookup}=this.state;
        getCompany({}).then((data)=>{ 
            data.items[0]['id'] = data.items[0].uuid;
            data.items[0]['parentId'] = null; 
            data.items[0]['expand'] = true;  
            const uuid=data.items[0].uuid;
            nodes[uuid]=data.items[0]; 
            subNodeLookup[uuid]=[];
            self.setState({ 
                company : data.items[0],
                rootNode:uuid
            }); 
            return {
                companyId : data.items[0]['uuid'] 
            }; 
        }).then((data)=>{ 
            let dataSource = data;
            let companyId=data.companyId; 
            return getOrganizations({pId:companyId}).then((data1)=>{ 
                if (data1.items&&data1.items.length>0) { 
                    for (let item of data1.items) { 
                        const uuid=item.uuid;
                        item['id']=item.uuid;
                        item['parentId'] = companyId; 
                        nodes[uuid]=item; 
                        subNodeLookup[uuid]=[];
                        if(subNodeLookup[item.parent_organization_ID]){
                        	subNodeLookup[item.parent_organization_ID].push(item);
                        }  
                    }
                }
                return dataSource;
            });
        }).then((data)=>{ 
        	self.setState({
            	nodes,
            	subNodeLookup
            })
        	const allItems=Object.keys(nodes);
        	allItems.map((id,i)=>{
        		getEmployeeCount({id}).then((dataCount)=>{
                	nodes[id]['employeeCount']=dataCount.count; 
                	self.setState({
		            	nodes 
		            })
	            });
        	})
            
        });
	} 
	showOrganization(){
		window.location.href='#/user/hrboard/organization';
	}
	componentWillUnmount(){
		 
	}
	componentDidUpdate(prevProps,prevState){

	}
	renderNode(nodeId){
		const {nodes,subNodeLookup}=this.state,self=this;  
		if(!subNodeLookup[nodeId]||!nodes[nodeId])
			return null; 
		const cols=subNodeLookup[nodeId];
		const colspanNum = cols.length*2;
		const node=nodes[nodeId];
		const colLines = Array.from({ length: colspanNum }); 
		let showSubNode=false;
		let isLeaf=false;
		let nodeStyle={'cursor':'s-resize'};
		let trStyle={'visibility':'hidden'};
		if(cols&&cols.length>0){
			showSubNode=true
		}
		if(node.is_leaf=='y'){
			isLeaf=true; 
		}
		if(node.expand){
			nodeStyle={'cursor':'n-resize'};
			trStyle={'visibility':''};
		} 
		const nodeCount="(" + (node.employeeCount||'0') + "/" + (node.headcount||'-') + "人)";
		return (
			<table cellpadding='0' cellspacing='0' border='0' key={nodeId}>
				<tbody>
					<tr className={cx('node-cells','contracted')} > 
						<td key={i} className='node-cell' colSpan={colspanNum}>
							{isLeaf?
							<div className='node' style={{'cursor':'default'}}>
								{node.name}{nodeCount}
								<div  className={cx(s.depleader)}>
									{node.leader?<span>部门负责人:{node.leader}</span>:""}
								</div>
							</div>:
							<div className='node' style={nodeStyle} onClick={self.loadSubNode.bind(self,nodeId)}>
								{node.name}{nodeCount}
								<div className={cx(s.depleader)}>
									{node.leader?<span>部门负责人:{node.leader}</span>:""}
								</div>
								<div className={cx(s.show_action_btn)}>
									{node.expand?<i className={cx('kr_icon')}>&#xe615;</i>:<i className={cx('kr_icon')}>&#xe60d;</i>}
									
								</div>
							</div>}
						</td> 
					</tr>
					{showSubNode&&
						<tr style={trStyle}>
							<td colSpan={colspanNum}>
								<div className='line down'></div>
							</td>
						</tr>
					}
					{showSubNode&&
						<tr style={trStyle}>
							{colLines.map((col,i)=>{
								if(i%2==0){
									let linesLeftClass='line left top';
									if(i==0){
										linesLeftClass='line left';
									}
									return (
										<td key={i+'left'} className={linesLeftClass}>&nbsp;</td>
									) 
								}else{
									let linesRigthClass='line right top'; 
									if(i==colLines.length-1){
										linesRigthClass='line right';
									} 
									return (
										<td key={i+'right'} className={linesRigthClass}>&nbsp;</td>
									)
								} 
							})} 
						</tr>
					}
					{showSubNode&&
						<tr  style={trStyle}>
							{cols.map((col,i)=>{
								return (
									<td key={i} className='node-container' colSpan={2}>
										{self.renderNode(col.uuid)}
									</td>
								)
							})} 
						</tr>
					}
				</tbody>
			</table>
		)  
	}
	render(){ 
		const {width,height}=this.props;
		const {nodes,rootNode,company,employeeCount}=this.state;
		const depths=Object.keys(nodes),self=this;
		let showOrgChat=false;
		if(rootNode&&rootNode.length>0){
			showOrgChat=true;
		} 
		const rootCount=nodes[rootNode]&&nodes[rootNode].employeeCount? nodes[rootNode].employeeCount:0;
		const title = company.name?(company.name || '-') + "(" + rootCount + "/" + (company.headcount||'-') + "人)":"";
		return(  
			<div className={cx(s.organizationChartContainer)}> 
				<div className={cx(s.organization_chart_head)} style={{width:'auto', height:'30px', backgroundColor:'#f4f4f4', paddingLeft:'10px'}}>
	                <div style={{width:'15px', display:'inline-block', lineHeight:'30px'}}>
	                    <i className={cx('kr_icon')} style={{cursor:'pointer', lineHeight:'30px', fontSize:'15px', color:'#7dc8e2'}} onClick={this.showOrganization}>&#xe650;</i>
	                </div>
	                <div style={{width:'15px', display:'inline-block', lineHeight:'30px', textAlign:'center', verticalAlign:'top'}}>|</div>
	                <div style={{width:'auto', display:'inline-block', lineHeight:'30px'}}>{title}</div>
	            </div>
				<div className={cx("jOrgChart",s.org_chart_wrap)}>
					<div className={cx(s.org_chart)}>
						{showOrgChat?self.renderNode(rootNode):''}
					</div> 
				</div>  
			</div>
		)
	}
}
 


export default OrgChat;