You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
org-chart-frant/src/pages/user.jsx

538 lines
18 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import styles from './index.less';
import React, { useEffect, useState } from 'react';
import { OrgChartComponent } from '@/components/orgChart';
import * as d3 from 'd3';
import { TopBar } from '../components/topBar';
import ToolBar from '../components/toolBar';
import moment from 'moment';
import qs from 'qs';
import { message } from 'antd';
import jsPDF from 'jspdf';
let active = 'top';
export default function userPage() {
const [data, setData] = useState(null);
const [topBarSearchRequest, setTpBarSearchRequest] = useState(null);
const [requestRes, setRequestRes] = useState({
date: moment(new Date()).format('YYYY-MM-DD'),
fclass: '0',
root: '0',
level: '3',
fisvitual: '0',
});
const [progressTop, setProgressTop] = useState(50);
let addNodeChildFunc = null;
let orgChart = null;
let progressBtnRef = null;
const [hasRight, setHasRight] = useState('');
// 点击节点
function onNodeClick(nodeId) {
// alert('clicked ' + nodeId);
}
function onButtonClick(event, d) {
if (d.children) {
let idsList = [];
d.children.forEach((item) => {
if (item.data.hasChildren && !item._children) {
idsList.push(item.data.id);
}
});
if (idsList.length == 0) {
return;
}
let idsStr = idsList.join(',');
let api = '';
if (topBarSearchRequest) {
let request = { ...topBarSearchRequest, ids: idsStr };
api =
'/api/bs/hrmorganization/orgchart/asyncUserData' +
qs.stringify(request, { addQueryPrefix: true });
} else {
api =
'/api/bs/hrmorganization/orgchart/asyncUserData?fclass=0&root=0&date=' +
moment(new Date()).format('YYYY-MM-DD') +
'&ids=' +
idsStr;
}
fetch(api)
.then((res) => res.json())
.then((data) => {
if (data.data) {
data.data.forEach((item) => {
window.chart.addNode(item);
});
}
});
}
}
// 获取部门图片
function getDepartmentImage() {
let index = Math.floor(Math.random() * 8) + 1;
return `./img/department/${index}.png`;
}
// 获取部门图片
function getSubcompanyImage() {
let index = Math.floor(Math.random() * 3) + 1;
return `./img/subcompany/${index}.png`;
}
// 获取数据
useEffect(() => {
document.cookie =
'Webstorm-3d4d3ad4=b8ca5bef-a131-4c2b-81da-6f8595481dc2; ecology_JSessionid=aaadYmKjyxMd8_cZAZkuy; JSESSIONID=aaadYmKjyxMd8_cZAZkuy; loginidweaver=1; languageidweaver=7; loginuuids=1; __randcode__=092aa42b-2879-41a3-81e9-7e50b58aa689';
d3.json(
// "/user/data"
'/api/bs/hrmorganization/orgchart/userData?fclass=0&root=0&date=' +
moment(new Date()).format('YYYY-MM-DD'),
).then((data) => {
setData(data.data);
setHasRight(data?.hasRight);
});
}, [true]);
// ButtonContent渲染
const buttonContentRender = ({ node, state }) => {
return `
<div style="margin-left: 16px; margin-top: 10px;">
<img src="./img/button_content.png" />
</div>
`;
};
// 节点宽度渲染
const nodeWidthRender = (d) => {
return 280;
};
const nodeHeightRender = (d) => {
return 160;
};
// tool bar start
const handleTopLayoutClick = (progressBtn) => {
progressBtn.current.style.top = 50 + 'px';
orgChart &&
orgChart
.setCentered(orgChart.getChartState().root.id)
.layout('top')
.render();
active = 'top';
};
const handleLeftLayoutClick = (progressBtn) => {
progressBtn.current.style.top = 50 + 'px';
orgChart &&
orgChart
.layout('left')
.setCentered(orgChart.getChartState().root.id)
.render();
active = 'left';
};
const handleZoomIn = (progressBtn) => {
if (progressBtn) {
let top = parseInt(progressBtn.current.style.top) - 10;
if (top >= 0) {
progressBtn.current.style.top = top + 'px';
} else {
return;
}
}
orgChart && orgChart.zoomIn();
};
const handleZoomOut = (progressBtn) => {
if (progressBtn) {
let top = parseInt(progressBtn.current.style.top) + 10;
if (top <= 100) {
progressBtn.current.style.top = top + 'px';
} else {
return;
}
}
orgChart && orgChart.zoomOut();
};
// tool bar end
// top bar start
function downloadPdf(chart) {
chart.exportImg({
save: false,
full: true,
onLoad: (base64) => {
var pdf = new jsPDF();
var img = new Image();
img.src = base64;
img.onload = function () {
pdf.addImage(
img,
'JPEG',
5,
5,
595 / 3,
((img.height / img.width) * 595) / 3,
);
pdf.save('chart.pdf');
};
},
});
}
const handleExport = (type) => {
if (type == 'png') {
orgChart && orgChart.exportImg({ full: true });
} else {
orgChart && downloadPdf(orgChart);
}
};
const handleSearch = (requestData) => {
setTpBarSearchRequest(requestData);
let api =
'/api/bs/hrmorganization/orgchart/userData' +
qs.stringify(requestData, { addQueryPrefix: true });
fetch(api)
.then((res) => res.json())
.then((data) => {
if (data.data) {
if (!data.data.length) {
setData([{}]);
message.warning('暂无数据');
} else {
setData(data?.data);
}
}
});
};
const handleSynchronous = (requestData) => {
let api = '/api/bs/hrmorganization/orgchart/synchronousData';
fetch(api)
.then((res) => res.json())
.then((data) => {
message.success('同步成功');
this.handleSearch(requestData);
});
};
useEffect(() => {
if (active == 'left') {
orgChart &&
orgChart
.setCentered(orgChart.getChartState().root.id)
.layout('left')
.render();
} else {
orgChart &&
orgChart
.setCentered(orgChart.getChartState().root.id)
.layout('top')
.render();
}
}, [data]);
// top bar end
const nodeContentRender = (d, i, arr, state) => {
// 集团地址
let companyUrl =
'/spa/organization/static/index.html#/main/organization/group';
// 分部地址
let subcompanyUrl = `/spa/organization/static/index.html#/main/organization/companyExtend/${d.data.fobjid}`;
// 部门地址
let departmentUrl = `/spa/organization/static/index.html#/main/organization/departmentExtend/${d.data.fobjid}`;
// 岗位地址
let jobtitleUrl = `/spa/organization/static/index.html#/main/organization/jobExtend/${d.data.fobjid}`;
// 人员地址
let userUrl = `/spa/organization/static/index.html#/main/organization/resourceCard/${d.data.fleader}`;
// 岗位人员地址
let postUserUrl = `/spa/organization/static/index.html#/main/organization/resourceCard/${d.data.fobjid}`;
//集团通讯录
let addressBookGroupUrl = `/spa/organization/static/index.html#/main/organization/resource/?virtualtype=0`;
// 分部通讯录
let addressBookUrl = `/spa/organization/static/index.html#/main/organization/resource/?companyId=${d.data.fobjid}`;
// 部门通讯录
let addressBookDepartmentUrl = `/spa/organization/static/index.html#/main/organization/resource/?departmentId=${d.data.fobjid}`;
// 岗位通讯录
let addressBookPostUrl = `/spa/organization/static/index.html#/main/organization/resource/?jobTitle=${d.data.fobjid}`;
if (d.data.ftype == 0 || d.data.ftype == 1 || d.data.ftype == 2) {
return `<div>
<div style="position: relative;">
<img src="./img/user-card/card-label-start.png" />
<span style="display: inline-block;
position: absolute;
left: 5px;
top: -8px;
background: #F7F9FD;
z-index: 100;
padding: 0px 10px;
font-size: 16px;
font-family: Microsoft YaHei-Bold, Microsoft YaHei;
font-weight: bold;
color: #000000;
" onclick="if(${d.data.fisvitual}==1) return;window.open('${
d.data.ftype == 0
? companyUrl
: d.data.ftype == 1
? subcompanyUrl
: d.data.ftype == 2
? departmentUrl
: ''
}', '_blank')">${d.data.fname}</span>
<span style="margin-left: 70px;">
<img src="./img/user-card/line1.png" />
<img src="./img/user-card/line2.png" />
</span>
<div style=" height: 152px;background-size: 100% 100%;box-sizing: border-box;padding-top: 30px;position:relative;z-index:2">
<div style='position:absolute;z-index:-1;top:0'>
<img src='./img/user-card/user-card.png'></div>
<div style="display: inline-block; background-size: 100% 100%; width: 35%; height: 90px; text-align:center; vertical-align: top; margin-left: 11px;box-sizing: border;">
<img src='./img/user-card/avatar-outer.png' style='position:absolute;width:90px;height:90px;left:11px'/>
<img src="${
d.data.fleaderimg
? d.data.fleaderimg
: d.data.ftype == 0 || d.data.ftype == 1
? './img/company.png'
: './img/default_avator.png'
}" style="width: 58px; height: 58px;position:absolute;left:29px; border-radius: 50%; margin-top: 16px;position:absolute;left:29px;z-index:999"/>
</div>
<div style="display: inline-block; margin-left: 6px;width: 55%" >
<div onclick="if(${d.data.fisvitual}==1) return;${
d.data.fleadername ? `window.open('${userUrl}', '_blank')` : ''
}">
<div style="
font-size: 13px;
font-family: Microsoft YaHei-Bold, Microsoft YaHei;
font-weight: bold;
color: #333333;
margin-bottom: 9px;"
>${d.data.fleadername}</div>
<div style="
font-size: 13px;
font-family: Microsoft YaHei-Regular, Microsoft YaHei;
font-weight: 400;
color: #333333;
margin-bottom: 19px;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;"
title="${d.data.fname}${
d.data.fleaderjob ? `/${d.data.fleaderjob}` : ''
}">${d.data.fname}${
d.data.fleaderjob ? `/${d.data.fleaderjob}` : ''
}</div>
</div>
<div style="display: ${
d.data.fisvitual == 0 ? 'flex' : 'none'
};" >
<div style="height: 28px;border: 1px solid #00C2FF; border-radius: 10px; line-height: 24px; padding: 0px 5px; min-width: 60px;">编制: ${
d.data.fplan
}</div>
<div style="height: 28px;border: 1px solid #00C2FF; border-radius: 10px; line-height: 24px; padding: 0px 5px; min-width: 60px; margin-left: 10px;" onclick="if(${
d.data.fisvitual
}==1) return;event.stopPropagation();window.open('${
d.data.ftype == 0
? addressBookGroupUrl
: d.data.ftype == 1
? addressBookUrl
: d.data.ftype == 2
? addressBookDepartmentUrl
: ''
}', '_blank')">在岗: ${d.data.fonjob}</div>
</div>
</div>
</div>
</div>
</div>`;
} else if (d.data.ftype == 3) {
return `<div>
<div style="position: relative;">
<img src="./img/user-card/card-label-start.png" />
<span style="display: inline-block;
position: absolute;
left: 5px;
top: -8px;
background: #F7F9FD;
z-index: 100;
padding: 0px 10px;
font-size: 16px;
font-family: Microsoft YaHei-Bold, Microsoft YaHei;
font-weight: bold;
color: #000000;
" onclick="if(${
d.data.fisvitual
}==1) return;window.open('${jobtitleUrl}', '_blank')">${
d.data.fname
}</span>
<span style="margin-left: 70px;">
<img src="./img/user-card/line1.png" />
<img src="./img/user-card/line2.png" />
</span>
<div style=" height: 152px;background-size: 100% 100%;box-sizing: border-box;padding-top: 40px;">
<div style='position:absolute;z-index:-1;top:16px'>
<img src='./img/user-card/user-card.png'>
</div>
<img src="./img/user-card/jobicon.png" style="margin-left: 20px; vertical-align: top;"/>
<div style="display: inline-block; margin-left: 15px;">
<div style="
font-size: 13px;
font-family: Microsoft YaHei-Bold, Microsoft YaHei;
font-weight: bold;
color: #333333;
margin-bottom: 23px;
" onclick="if(${
d.data.fisvitual
}==1) return;window.open('${jobtitleUrl}', '_blank')">${
d.data.fname
}</div>
<div style="
font-size: 13px;
font-family: Microsoft YaHei-Regular, Microsoft YaHei;
font-weight: 400;
color: #333333;
display: ${d.data.fisvitual == 0 ? 'flex' : 'none'};
">
<span>编制:${d.data.fplan}</span>
<span style="margin-left: 10px;" onclick="if(${
d.data.fisvitual
}==1) return;window.open('${addressBookPostUrl}', '_blank')">在岗:${
d.data.fonjob
}</span>
</div>
</div>
</div>
</div>
</div>`;
} else if (d.data.ftype == 4) {
return `<div>
<div style="position: relative;" >
<img src="./img/user-card/card-label-start.png" />
<span >
<img src="./img/user-card/line1.png" />
<img src="./img/user-card/line2.png" />
</span>
<div style="height: 152px;background-size: 100% 100%;box-sizing: border-box;padding-top: 30px;">
<div style='position:absolute;z-index:-1;top:16px'>
<img src='./img/user-card/user-card.png'>
</div>
<div style="display: inline-block; background-size: 100% 100%; width: 35%; height: 90px; text-align:center; vertical-align: top; margin-left: 11px;box-sizing: border;">
<img src='./img/user-card/avatar-outer.png' style='position:absolute;width:90px;height:90px;left:11px;z-index:-1'/>
<img src="${
d.data.fleaderimg
? d.data.fleaderimg
: './img/default_avator.png'
}" style="width: 58px; height: 58px; border-radius: 50%; margin-top: 16px;z-index:999"/>
</div>
<div style="display: inline-block; margin-left: 6px;width: 55%;height:100%" onclick="if(${
d.data.fisvitual
}==1) return;window.open('${postUserUrl}', '_blank')">
<div style='display:flex;align-items:center;margin-bottom:19px;margin-top:15px'>
<div style="
font-size: 13px;
font-family: Microsoft YaHei-Bold, Microsoft YaHei;
color: #333333;"
>${d.data.fname}</div>
<div style="
font-size: 13px;
font-family: Microsoft YaHei-Regular, Microsoft YaHei;
font-weight: 400;
color: #999;
white-space:nowrap;
overflow:hidden;
flex:1;
font-size:12px;
transform:scale(0.8);
margin-left:-5px;
text-overflow:ellipsis;"
title="${
d.data.fleaderst
? d.data.fleaderlv
? `(${d.data.fleaderst}/`
: `(${d.data.fleaderst})`
: ''
}${d.data.fleaderlv ? `${d.data.fleaderlv})` : ''}">${
d.data.fleaderst
? d.data.fleaderlv
? `(${d.data.fleaderst}/`
: `(${d.data.fleaderst})`
: ''
}${d.data.fleaderlv ? `${d.data.fleaderlv})` : ''}</div>
</div>
<div style="
font-size: 13px;
font-family: Microsoft YaHei-Regular, Microsoft YaHei;
font-weight: 400;
color: #333333;
">${d.data.department ? d.data.department + ' / ' : ''}${
d.data.fleaderjob
}</div>
</div>
</div>
</div>
</div>`;
}
};
if (hasRight === false) {
return (
<div style={{ width: '100%', top: '40%', position: 'absolute' }}>
<img
style={{ display: 'block', margin: '0 auto' }}
src="./img/permission.png"
/>
<p style={{ textAlign: 'center' }}>对不起您暂时没有权限!</p>
</div>
);
}
return (
hasRight && (
<div className={styles.contentWrapper}>
<TopBar
onExport={(type) => {
handleExport(type);
}}
onSearch={(requestData) => {
setRequestRes(requestData);
handleSearch(requestData);
}}
onSynchronous={(requestData) => {
handleSynchronous(requestData);
}}
type="user"
url="/api/bs/hrmorganization/orgchart/getCondition?type=user"
/>
<ToolBar
onTopLayoutClick={handleTopLayoutClick}
onLeftLayoutClick={handleLeftLayoutClick}
onZoomOut={(progressBtn) => handleZoomOut(progressBtn)}
onZoomIn={(progressBtn) => handleZoomIn(progressBtn)}
/>
<OrgChartComponent
setChart={(chart) => (orgChart = chart)}
setClick={(click) => (addNodeChildFunc = click)}
onNodeClick={onNodeClick}
onButtonClick={onButtonClick}
data={data}
buttonContent={buttonContentRender}
nodeWidth={nodeWidthRender}
nodeHeight={nodeHeightRender}
nodeContent={nodeContentRender}
requestRes={requestRes}
/>
</div>
)
);
}