组织架构图

feature/v3
Chengliang 2 years ago
parent f699fe05cd
commit 1512a8ba9f

Binary file not shown.

@ -24,6 +24,7 @@
"@types/d3": "^7.4.0", "@types/d3": "^7.4.0",
"d3": "7.4.4", "d3": "7.4.4",
"d3-org-chart": "2.6.0", "d3-org-chart": "2.6.0",
"js-export-excel": "^1.1.4",
"jspdf": "^2.5.1", "jspdf": "^2.5.1",
"moment": "^2.29.3", "moment": "^2.29.3",
"qs": "^6.11.0", "qs": "^6.11.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

@ -1,11 +1,11 @@
import React from 'react'; import React from 'react';
import { Drawer, Space, Button, Dropdown, Menu, Table } from 'antd'; import { Drawer, Space, Button, Dropdown, Menu, Table, Spin } from 'antd';
import { OrgChartComponent } from '@/components/orgChart'; import { OrgChartComponent } from '@/components/orgChart';
import * as d3 from 'd3'; import * as d3 from 'd3';
import qs from 'qs'; import qs from 'qs';
import { message } from 'antd'; import { message } from 'antd';
import jsPDF from 'jspdf'; import jsPDF from 'jspdf';
import styles from './index.less'; import ExportJsonExcel from 'js-export-excel';
let addNodeChildFunc = null; let addNodeChildFunc = null;
let orgChart = null; let orgChart = null;
@ -18,12 +18,13 @@ export default class DrawerComponents extends React.Component {
data: [], data: [],
detailType: 'chart', detailType: 'chart',
rootId: '', rootId: '',
dataSource: [],
columns: [],
spinning: true,
}; };
} }
componentDidMount() { componentDidMount() {}
//this.getDeatilDatas();
}
// //
onNodeClick(node) {} onNodeClick(node) {}
@ -39,34 +40,29 @@ export default class DrawerComponents extends React.Component {
if (idsList.length == 0) { if (idsList.length == 0) {
return; return;
} }
let idsStr = idsList.join(',');
let api = '/api/bs/hrmorganization/orgchart/asyncUserData?ids=' + idsStr;
fetch(api)
.then((res) => res.json())
.then((data) => {
if (data.data) {
data.data.forEach((item) => {
window.chart.addNode(item);
});
}
});
} }
} }
// //
getDepartmentImage() { getDepartmentImage(fisvitual) {
let index = Math.floor(Math.random() * 8) + 1; return fisvitual == '0'
return `./img/department/${index}.png`; ? `./img/user-card/user-card.png`
: `./img/user-card/user-card-blue.png`;
} }
// //
getDeatilDatas(rootId) { getDeatilDatas(rootId, type = 'chart') {
const { detailType } = this.state; this.setState({ spinning: true });
d3.json( d3.json(
'/api/bs/hrmorganization/orgchart/userData?' + '/api/bs/hrmorganization/orgchart/getDepartmentDetail?' +
qs.stringify({ detauleType: detailType, rootId: rootId }), qs.stringify({ detauleType: type, rootId: rootId }),
).then((data) => { ).then((data) => {
this.setState(data.data); //
if (type == 'chart') {
this.setState({ data: data.data, spinning: false });
} else {
this.setState({ dataSource: data.dataSource, columns: data.columns });
}
}); });
} }
@ -133,7 +129,7 @@ export default class DrawerComponents extends React.Component {
orgChart && orgChart.zoomOut(); orgChart && orgChart.zoomOut();
}; };
downloadPdf(chart) { downloadPdf = (chart) => {
chart.exportImg({ chart.exportImg({
save: false, save: false,
full: true, full: true,
@ -154,14 +150,64 @@ export default class DrawerComponents extends React.Component {
}; };
}, },
}); });
} };
handleExport = (e) => { handleExport = (e) => {
let type = e.key == '1' ? 'png' : 'pdf'; let type = e.key == '1' ? 'png' : e.key == '1' ? 'pdf' : 'excel';
if (type == 'png') { if (type == 'png') {
orgChart && orgChart.exportImg({ full: true }); orgChart && orgChart.exportImg({ full: true });
} else if (type == 'pdf') {
orgChart && this.downloadPdf(orgChart);
} else { } else {
orgChart && downloadPdf(orgChart); let { dataSource } = this.state;
var option = {};
let dataTable = [];
if (dataSource) {
for (let i in dataSource) {
if (dataSource) {
let obj = {
序号: dataSource[i].id,
工号: dataSource[i].workCode,
姓名: dataSource[i].lastName,
性别: dataSource[i].sex,
部门: dataSource[i].departmentId,
分部: dataSource[i].subcompanyid1,
岗位: dataSource[i].jobTitle,
手机号: dataSource[i].mobile,
};
dataTable.push(obj);
}
}
}
option.fileName = '组织信息';
option.datas = [
{
sheetData: dataTable,
sheetName: 'sheet',
sheetFilter: [
'序号',
'工号',
'姓名',
'性别',
'部门',
'分部',
'岗位',
'手机号',
],
sheetHeader: [
'序号',
'工号',
'姓名',
'性别',
'部门',
'分部',
'岗位',
'手机号',
],
},
];
var toExcel = new ExportJsonExcel(option);
toExcel.saveExcel();
} }
}; };
@ -173,40 +219,41 @@ export default class DrawerComponents extends React.Component {
return `<div style="position: relative;"> return `<div style="position: relative;">
<div style=" height: 152px;background-size: 100% 100%;box-sizing: border-box;padding-top: 30px;position:relative;z-index:2"> <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'> <div style='position:absolute;z-index:-1;top:0'>
<img src='./img/user-card/user-card.png'> <img style='width: 295px;height: 163px;' src="${this.getDepartmentImage(
d.data.fisvitual,
)}">
</div> </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;"> <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='./img/user-card/avatar-outer.png' style='position:absolute;width:90px;height:90px;left:11px'/>
<img src="./img/department.png" style="width: 58px; height: 58px;position:absolute;left:29px; border-radius: 50%; margin-top: 16px;position:absolute;left:29px;z-index:999"/> <img src="./img/department.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>
<div style="display: inline-block; margin-left: 6px;width: 55%"> <div style="display: inline-block; margin-left: 6px;width: 55%">
<div style="font-size: 13px;font-family: Microsoft YaHei-Bold, Microsoft YaHei;font-weight: bold;color: #333333;margin-bottom: 9px;">${ <div style="font-size: 15px;font-family: Microsoft YaHei-Regular, Microsoft YaHei;font-weight: 900;color: #333333;height: 25px;line-height: 25px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
d.data.fleadername ${d.data.fname}
}</div> </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;"> <div style="font-size: 13px;font-family: Microsoft YaHei-Bold, Microsoft YaHei;color: #333333;height: 25px;line-height: 25px;">
${d.data.fname}${ 负责人:${d.data.fleader}
d.data.fleaderjob ? `/${d.data.fleaderjob}` : ''
}
</div> </div>
</div> <div style="display:flex" >
<div style="display:flex" > <div style="height: 25px; line-height: 25px; min-width: 80px;">
<div style="height: 28px;border: 1px solid #00C2FF; border-radius: 10px; line-height: 24px; padding: 0px 5px; min-width: 60px;"> 在岗: ${d.data.fonjob}
在岗: ${d.data.fonjob} </div>
</div> </div>
</div> </div>
</div> </div>
</div>`; </div>`;
} else if (d.data.ftype == 3) { } else if (d.data.ftype == 3) {
return `<div style="position: relative;"> return `<div style="position: relative;">
<div style=" height: 152px;background-size: 100% 100%;box-sizing: border-box;padding-top: 40px;"> <div style=" height: 152px;background-size: 100% 100%;box-sizing: border-box;padding-top: 40px;">
<div style='position:absolute;z-index:-1;top:16px'> <div style='position:absolute;z-index:-1;top:0'>
<img src='./img/user-card/user-card.png'> <img style='width: 295px;height: 163px;' src='./img/user-card/user-card-orange.png'>
</div> </div>
<img src="./img/user-card/jobicon.png" style="margin-left: 20px; vertical-align: top;"/> <img src="./img/user-card/jobicon-orange.png" style="margin-left: 20px; vertical-align: top;"/>
<div style="display: inline-block; margin-left: 15px;"> <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;">${d.data.fname}</div> <div style="font-size: 15px;height: 25px;line-height: 25px;font-family: Microsoft YaHei-Bold, Microsoft YaHei;font-weight: bold;color: #333333;">${d.data.fname}</div>
<div style="font-size: 13px;font-family: Microsoft YaHei-Regular, Microsoft YaHei;font-weight: 400;color: #333333;display: flex;"> <div style="font-size: 13px;font-family: Microsoft YaHei-Regular, Microsoft YaHei;font-weight: 400;color: #333333;display: flex;height: 25px;line-height: 25px;">
<span style="margin-left: 10px;">在岗${d.data.fonjob}</span> <span>在岗: ${d.data.fonjob} </span>
</div> </div>
</div> </div>
</div> </div>
@ -214,25 +261,28 @@ export default class DrawerComponents extends React.Component {
} else if (d.data.ftype == 4) { } else if (d.data.ftype == 4) {
return `<div style="position: relative;" > return `<div style="position: relative;" >
<div style="height: 152px;background-size: 100% 100%;box-sizing: border-box;padding-top: 30px;"> <div style="height: 152px;background-size: 100% 100%;box-sizing: border-box;padding-top: 30px;">
<div style='position:absolute;z-index:-1;top:16px'> <div style='position:absolute;z-index:-1;top:0px'>
<img src='./img/user-card/user-card.png'> <img style='width: 295px;height: 163px;' src='./img/user-card/user-card-green.png'>
</div> </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;"> <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='./img/user-card/avatar-outer-green.png' style='position:absolute;width:90px;height:90px;left:11px;z-index:-1'/>
<img src="${ <img src="${
d.data.fleaderimg d.data.fleaderimg
? d.data.fleaderimg ? d.data.fleaderimg
: './img/default_avator.png' : './img/default_avator.png'
}" style="width: 58px; height: 58px; border-radius: 50%; margin-top: 16px;z-index:999" /> }" style="width: 58px; height: 58px; border-radius: 50%; margin-top: 16px;margin-left: -6px;z-index:999" />
</div>
<div style="display: inline-block; margin-left: 6px;width: 55%;height:100%">
<div style='display:flex;align-items:center;height: 25px;line-height: 25px;margin-top:15px'>
<div style="font-weight: bold;font-size: 15px;ont-family: Microsoft YaHei-Bold, Microsoft YaHei;color: #333333;">${
d.data.fname
}</div>
</div> </div>
<div style="display: inline-block; margin-left: 6px;width: 55%;height:100%"> <div style="font-size: 13px;font-family: Microsoft YaHei-Regular, Microsoft YaHei;font-weight: 400;color: #333333;display: flex;height: 25px;line-height: 25px;">
<div style='display:flex;align-items:center;margin-bottom:19px;margin-top:15px'> <span>司龄: ${d.data.companyWorkYear} </span>
<div style="font-size: 13px;ont-family: Microsoft YaHei-Bold, Microsoft YaHei;color: #333333;">${
d.data.fname
}</div>
</div>
</div> </div>
</div> </div>
</div>
</div>`; </div>`;
} }
}; };
@ -243,72 +293,35 @@ export default class DrawerComponents extends React.Component {
}; };
onClose = () => { onClose = () => {
this.setState({ open: false }); this.setState({ open: false, detailType: 'chart' });
}; };
changeDetail = () => { changeDetail = () => {
const { detailType, rootId } = this.state; const { detailType, rootId } = this.state;
this.getDeatilDatas(rootId); let type = detailType == 'chart' ? 'table' : 'chart';
this.setState({ this.setState({
detailType: detailType == 'chart' ? 'table' : 'chart', detailType: type,
}); });
this.getDeatilDatas(rootId, type);
}; };
render() { render() {
const { open, data, detailType } = this.state; const { open, data, detailType, dataSource, columns, spinning } =
this.state;
const menu = ( let arr = [];
<Menu if (detailType == 'chart') {
onClick={this.handleExport.bind(this)} arr.push({ label: '导出图片', key: '1' });
items={[ arr.push({ label: '导出PDF', key: '2' });
{ } else {
label: '导出图片', arr.push({ label: '导出表格', key: '3' });
key: '1', }
},
{
label: '导出PDF',
key: '2',
},
]}
/>
);
const dataSource = [
{
key: '1',
name: '胡彦斌',
age: 32,
address: '西湖区湖底公园1号',
},
{
key: '2',
name: '胡彦祖',
age: 42,
address: '西湖区湖底公园1号',
},
];
const columns = [ const menu = <Menu onClick={this.handleExport.bind(this)} items={arr} />;
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
},
];
return ( return (
<Drawer <Drawer
title="详细信息" title="详细信息"
width={920} width={1000}
onClose={this.onClose} onClose={this.onClose}
open={open} open={open}
bodyStyle={{ bodyStyle={{
@ -328,17 +341,21 @@ export default class DrawerComponents extends React.Component {
} }
> >
{detailType == 'chart' ? ( {detailType == 'chart' ? (
<OrgChartComponent data.length > 0 && (
setChart={(chart) => (orgChart = chart)} <Spin size="large" spinning={spinning}>
setClick={(click) => (addNodeChildFunc = click)} <OrgChartComponent
onNodeClick={this.onNodeClick} setChart={(chart) => (orgChart = chart)}
onButtonClick={this.onButtonClick} setClick={(click) => (addNodeChildFunc = click)}
data={data} onNodeClick={this.onNodeClick}
buttonContent={this.buttonContentRender} onButtonClick={this.onButtonClick}
nodeWidth={this.nodeWidthRender} data={data}
nodeHeight={this.nodeHeightRender} buttonContent={this.buttonContentRender}
nodeContent={this.nodeContentRender} nodeWidth={this.nodeWidthRender}
/> nodeHeight={this.nodeHeightRender}
nodeContent={this.nodeContentRender}
/>
</Spin>
)
) : ( ) : (
<Table dataSource={dataSource} columns={columns} /> <Table dataSource={dataSource} columns={columns} />
)} )}

@ -261,18 +261,17 @@ export class TopBar extends React.Component {
</Row> </Row>
<Row style={{ marginTop: '15px' }}> <Row style={{ marginTop: '15px' }}>
<Col span={8}> <Col span={8}>
{type == 'user' && ( <Button
<Button type="primary"
type="primary" style={{ marginRight: '10px' }}
style={{ marginRight: '10px' }} disabled={disabled}
disabled={disabled} onClick={() => {
onClick={() => { this.setState({ open: true });
this.setState({ open: true }); }}
}} >
> 版本记录
版本记录 </Button>
</Button>
)}
<Button <Button
type="primary" type="primary"
style={{ marginRight: '10px' }} style={{ marginRight: '10px' }}

@ -12,14 +12,15 @@ import qs from 'qs';
import { message, Spin } from 'antd'; import { message, Spin } from 'antd';
let active = 'top'; let active = 'top';
let drawerCom = null;
let timeLine = null;
let orgChart = null;
export default function companyPage() { export default function companyPage() {
let topbar = null; let topbar = null;
let timeLine = null;
let drawerCom = null;
const [data, setData] = useState(null); const [data, setData] = useState(null);
const [sliderProgress, setSliderProgress] = useState(50); const [sliderProgress, setSliderProgress] = useState(50);
let addNodeChildFunc = null; let addNodeChildFunc = null;
let orgChart = null;
let topBarSearchRequest = null; let topBarSearchRequest = null;
const [hasRight, setHasRight] = useState(''); const [hasRight, setHasRight] = useState('');
@ -73,14 +74,13 @@ export default function companyPage() {
} }
// //
function getDepartmentImage() { function getDepartmentImage(fisvitual) {
let index = Math.floor(Math.random() * 8) + 1; return fisvitual == '0' ? `./img/back/level4.png` : `./img/back/level8.png`;
return `./img/back/level4.png`;
} }
// //
function getSubcompanyImage() { function getSubcompanyImage(fisvitual) {
return `./img/back/level1.png`; return fisvitual == '0' ? `./img/back/level1.png` : `./img/back/level5.png`;
} }
// //
@ -145,7 +145,9 @@ export default function companyPage() {
</div>`; </div>`;
} else if (d.data.ftype == 1) { } else if (d.data.ftype == 1) {
return `<div style='position:absolute;height:100%'> return `<div style='position:absolute;height:100%'>
<img style='width:144px;height:106px' src="${getSubcompanyImage()}"/> <img style='width:144px;height:106px' src="${getSubcompanyImage(
d.data.fisvitual,
)}"/>
</div> </div>
<div style="width: 144px;height: 80px;top: 35px;position: relative;font-weight: 400;font-size: 14px; <div style="width: 144px;height: 80px;top: 35px;position: relative;font-weight: 400;font-size: 14px;
font-family: Microsoft YaHei-Regular, Microsoft YaHei;color: #333333;text-align: center;"> font-family: Microsoft YaHei-Regular, Microsoft YaHei;color: #333333;text-align: center;">
@ -158,7 +160,9 @@ export default function companyPage() {
return ` return `
<div style="width: 100%; height: 100%; background-size: 100% 100%;"> <div style="width: 100%; height: 100%; background-size: 100% 100%;">
<div style='position:absolute;height:100%'> <div style='position:absolute;height:100%'>
<img style='width:144px;height:106px' src="${getDepartmentImage()}"/> <img style='width:144px;height:106px' src="${getDepartmentImage(
d.data.fisvitual,
)}"/>
</div> </div>
<div style="width: 144px;height: 80px;top: 35px;position: relative;font-weight: 400;font-size: 14px; <div style="width: 144px;height: 80px;top: 35px;position: relative;font-weight: 400;font-size: 14px;
font-family: Microsoft YaHei-Regular, Microsoft YaHei;color: #333333;text-align: center;"> font-family: Microsoft YaHei-Regular, Microsoft YaHei;color: #333333;text-align: center;">

@ -99,7 +99,7 @@ export default function userPage() {
// //
useEffect(() => { useEffect(() => {
document.cookie = document.cookie =
'ecology_JSessionid=aaazPUne5WAU1eB9vTfKy; JSESSIONID=aaazPUne5WAU1eB9vTfKy; Systemlanguid=7; languageidweaver=7; loginidweaver=sysadmin; loginuuids=1; __randcode__=0fd53114-a13b-400b-a7bc-bb0ffb7ab567'; 'ecology_JSessionid=aaazPUne5WAU1eB9vTfKy; JSESSIONID=aaazPUne5WAU1eB9vTfKy; Systemlanguid=7; languageidweaver=7; loginuuids=1; loginidweaver=sysadmin; __randcode__=7f4710ea-50a3-4552-8193-57269840d388';
d3.json( d3.json(
// "/user/data" // "/user/data"
'/api/bs/hrmorganization/orgchart/userData?fclass=0&fisvitual=0&root=0&level=3&id=0', '/api/bs/hrmorganization/orgchart/userData?fclass=0&fisvitual=0&root=0&level=3&id=0',

Loading…
Cancel
Save