组织架构图
This commit is contained in:
parent
f699fe05cd
commit
1512a8ba9f
|
|
@ -24,6 +24,7 @@
|
|||
"@types/d3": "^7.4.0",
|
||||
"d3": "7.4.4",
|
||||
"d3-org-chart": "2.6.0",
|
||||
"js-export-excel": "^1.1.4",
|
||||
"jspdf": "^2.5.1",
|
||||
"moment": "^2.29.3",
|
||||
"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 { Drawer, Space, Button, Dropdown, Menu, Table } from 'antd';
|
||||
import { Drawer, Space, Button, Dropdown, Menu, Table, Spin } from 'antd';
|
||||
import { OrgChartComponent } from '@/components/orgChart';
|
||||
import * as d3 from 'd3';
|
||||
import qs from 'qs';
|
||||
import { message } from 'antd';
|
||||
import jsPDF from 'jspdf';
|
||||
import styles from './index.less';
|
||||
import ExportJsonExcel from 'js-export-excel';
|
||||
|
||||
let addNodeChildFunc = null;
|
||||
let orgChart = null;
|
||||
|
|
@ -18,12 +18,13 @@ export default class DrawerComponents extends React.Component {
|
|||
data: [],
|
||||
detailType: 'chart',
|
||||
rootId: '',
|
||||
dataSource: [],
|
||||
columns: [],
|
||||
spinning: true,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
//this.getDeatilDatas();
|
||||
}
|
||||
componentDidMount() {}
|
||||
|
||||
// 点击节点
|
||||
onNodeClick(node) {}
|
||||
|
|
@ -39,34 +40,29 @@ export default class DrawerComponents extends React.Component {
|
|||
if (idsList.length == 0) {
|
||||
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() {
|
||||
let index = Math.floor(Math.random() * 8) + 1;
|
||||
return `./img/department/${index}.png`;
|
||||
getDepartmentImage(fisvitual) {
|
||||
return fisvitual == '0'
|
||||
? `./img/user-card/user-card.png`
|
||||
: `./img/user-card/user-card-blue.png`;
|
||||
}
|
||||
|
||||
//获取数据
|
||||
getDeatilDatas(rootId) {
|
||||
const { detailType } = this.state;
|
||||
getDeatilDatas(rootId, type = 'chart') {
|
||||
this.setState({ spinning: true });
|
||||
d3.json(
|
||||
'/api/bs/hrmorganization/orgchart/userData?' +
|
||||
qs.stringify({ detauleType: detailType, rootId: rootId }),
|
||||
'/api/bs/hrmorganization/orgchart/getDepartmentDetail?' +
|
||||
qs.stringify({ detauleType: type, rootId: rootId }),
|
||||
).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();
|
||||
};
|
||||
|
||||
downloadPdf(chart) {
|
||||
downloadPdf = (chart) => {
|
||||
chart.exportImg({
|
||||
save: false,
|
||||
full: true,
|
||||
|
|
@ -154,14 +150,64 @@ export default class DrawerComponents extends React.Component {
|
|||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleExport = (e) => {
|
||||
let type = e.key == '1' ? 'png' : 'pdf';
|
||||
let type = e.key == '1' ? 'png' : e.key == '1' ? 'pdf' : 'excel';
|
||||
if (type == 'png') {
|
||||
orgChart && orgChart.exportImg({ full: true });
|
||||
} else if (type == 'pdf') {
|
||||
orgChart && this.downloadPdf(orgChart);
|
||||
} 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;">
|
||||
<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'>
|
||||
<img style='width: 295px;height: 163px;' src="${this.getDepartmentImage(
|
||||
d.data.fisvitual,
|
||||
)}">
|
||||
</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="./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 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;">${
|
||||
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;">
|
||||
${d.data.fname}${
|
||||
d.data.fleaderjob ? `/${d.data.fleaderjob}` : ''
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex" >
|
||||
<div style="height: 28px;border: 1px solid #00C2FF; border-radius: 10px; line-height: 24px; padding: 0px 5px; min-width: 60px;">
|
||||
在岗: ${d.data.fonjob}
|
||||
<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.fname}
|
||||
</div>
|
||||
<div style="font-size: 13px;font-family: Microsoft YaHei-Bold, Microsoft YaHei;color: #333333;height: 25px;line-height: 25px;">
|
||||
负责人:${d.data.fleader}
|
||||
</div>
|
||||
<div style="display:flex" >
|
||||
<div style="height: 25px; line-height: 25px; min-width: 80px;">
|
||||
在岗: ${d.data.fonjob} 人
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>`;
|
||||
} else if (d.data.ftype == 3) {
|
||||
return `<div style="position: relative;">
|
||||
<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 style='position:absolute;z-index:-1;top:0'>
|
||||
<img style='width: 295px;height: 163px;' src='./img/user-card/user-card-orange.png'>
|
||||
</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="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: 13px;font-family: Microsoft YaHei-Regular, Microsoft YaHei;font-weight: 400;color: #333333;display: flex;">
|
||||
<span style="margin-left: 10px;">在岗:${d.data.fonjob}</span>
|
||||
<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;height: 25px;line-height: 25px;">
|
||||
<span>在岗: ${d.data.fonjob} 人</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -214,25 +261,28 @@ export default class DrawerComponents extends React.Component {
|
|||
} else if (d.data.ftype == 4) {
|
||||
return `<div style="position: relative;" >
|
||||
<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 style='position:absolute;z-index:-1;top:0px'>
|
||||
<img style='width: 295px;height: 163px;' src='./img/user-card/user-card-green.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 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-green.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;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 style="display: inline-block; margin-left: 6px;width: 55%;height:100%">
|
||||
<div style='display:flex;align-items:center;margin-bottom:19px;margin-top:15px'>
|
||||
<div style="font-size: 13px;ont-family: Microsoft YaHei-Bold, Microsoft YaHei;color: #333333;">${
|
||||
d.data.fname
|
||||
}</div>
|
||||
</div>
|
||||
<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>司龄: ${d.data.companyWorkYear} 年</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
};
|
||||
|
|
@ -243,72 +293,35 @@ export default class DrawerComponents extends React.Component {
|
|||
};
|
||||
|
||||
onClose = () => {
|
||||
this.setState({ open: false });
|
||||
this.setState({ open: false, detailType: 'chart' });
|
||||
};
|
||||
|
||||
changeDetail = () => {
|
||||
const { detailType, rootId } = this.state;
|
||||
this.getDeatilDatas(rootId);
|
||||
let type = detailType == 'chart' ? 'table' : 'chart';
|
||||
this.setState({
|
||||
detailType: detailType == 'chart' ? 'table' : 'chart',
|
||||
detailType: type,
|
||||
});
|
||||
this.getDeatilDatas(rootId, type);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { open, data, detailType } = this.state;
|
||||
const { open, data, detailType, dataSource, columns, spinning } =
|
||||
this.state;
|
||||
let arr = [];
|
||||
if (detailType == 'chart') {
|
||||
arr.push({ label: '导出图片', key: '1' });
|
||||
arr.push({ label: '导出PDF', key: '2' });
|
||||
} else {
|
||||
arr.push({ label: '导出表格', key: '3' });
|
||||
}
|
||||
|
||||
const menu = (
|
||||
<Menu
|
||||
onClick={this.handleExport.bind(this)}
|
||||
items={[
|
||||
{
|
||||
label: '导出图片',
|
||||
key: '1',
|
||||
},
|
||||
{
|
||||
label: '导出PDF',
|
||||
key: '2',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
const dataSource = [
|
||||
{
|
||||
key: '1',
|
||||
name: '胡彦斌',
|
||||
age: 32,
|
||||
address: '西湖区湖底公园1号',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: '胡彦祖',
|
||||
age: 42,
|
||||
address: '西湖区湖底公园1号',
|
||||
},
|
||||
];
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
},
|
||||
{
|
||||
title: '住址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
},
|
||||
];
|
||||
const menu = <Menu onClick={this.handleExport.bind(this)} items={arr} />;
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
title="详细信息"
|
||||
width={920}
|
||||
width={1000}
|
||||
onClose={this.onClose}
|
||||
open={open}
|
||||
bodyStyle={{
|
||||
|
|
@ -328,17 +341,21 @@ export default class DrawerComponents extends React.Component {
|
|||
}
|
||||
>
|
||||
{detailType == 'chart' ? (
|
||||
<OrgChartComponent
|
||||
setChart={(chart) => (orgChart = chart)}
|
||||
setClick={(click) => (addNodeChildFunc = click)}
|
||||
onNodeClick={this.onNodeClick}
|
||||
onButtonClick={this.onButtonClick}
|
||||
data={data}
|
||||
buttonContent={this.buttonContentRender}
|
||||
nodeWidth={this.nodeWidthRender}
|
||||
nodeHeight={this.nodeHeightRender}
|
||||
nodeContent={this.nodeContentRender}
|
||||
/>
|
||||
data.length > 0 && (
|
||||
<Spin size="large" spinning={spinning}>
|
||||
<OrgChartComponent
|
||||
setChart={(chart) => (orgChart = chart)}
|
||||
setClick={(click) => (addNodeChildFunc = click)}
|
||||
onNodeClick={this.onNodeClick}
|
||||
onButtonClick={this.onButtonClick}
|
||||
data={data}
|
||||
buttonContent={this.buttonContentRender}
|
||||
nodeWidth={this.nodeWidthRender}
|
||||
nodeHeight={this.nodeHeightRender}
|
||||
nodeContent={this.nodeContentRender}
|
||||
/>
|
||||
</Spin>
|
||||
)
|
||||
) : (
|
||||
<Table dataSource={dataSource} columns={columns} />
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -261,18 +261,17 @@ export class TopBar extends React.Component {
|
|||
</Row>
|
||||
<Row style={{ marginTop: '15px' }}>
|
||||
<Col span={8}>
|
||||
{type == 'user' && (
|
||||
<Button
|
||||
type="primary"
|
||||
style={{ marginRight: '10px' }}
|
||||
disabled={disabled}
|
||||
onClick={() => {
|
||||
this.setState({ open: true });
|
||||
}}
|
||||
>
|
||||
版本记录
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="primary"
|
||||
style={{ marginRight: '10px' }}
|
||||
disabled={disabled}
|
||||
onClick={() => {
|
||||
this.setState({ open: true });
|
||||
}}
|
||||
>
|
||||
版本记录
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
style={{ marginRight: '10px' }}
|
||||
|
|
|
|||
|
|
@ -12,14 +12,15 @@ import qs from 'qs';
|
|||
import { message, Spin } from 'antd';
|
||||
|
||||
let active = 'top';
|
||||
let drawerCom = null;
|
||||
let timeLine = null;
|
||||
let orgChart = null;
|
||||
|
||||
export default function companyPage() {
|
||||
let topbar = null;
|
||||
let timeLine = null;
|
||||
let drawerCom = null;
|
||||
const [data, setData] = useState(null);
|
||||
const [sliderProgress, setSliderProgress] = useState(50);
|
||||
let addNodeChildFunc = null;
|
||||
let orgChart = null;
|
||||
|
||||
let topBarSearchRequest = null;
|
||||
const [hasRight, setHasRight] = useState('');
|
||||
|
|
@ -73,14 +74,13 @@ export default function companyPage() {
|
|||
}
|
||||
|
||||
// 获取部门图片
|
||||
function getDepartmentImage() {
|
||||
let index = Math.floor(Math.random() * 8) + 1;
|
||||
return `./img/back/level4.png`;
|
||||
function getDepartmentImage(fisvitual) {
|
||||
return fisvitual == '0' ? `./img/back/level4.png` : `./img/back/level8.png`;
|
||||
}
|
||||
|
||||
// 获取分部图片
|
||||
function getSubcompanyImage() {
|
||||
return `./img/back/level1.png`;
|
||||
function getSubcompanyImage(fisvitual) {
|
||||
return fisvitual == '0' ? `./img/back/level1.png` : `./img/back/level5.png`;
|
||||
}
|
||||
|
||||
// 获取数据
|
||||
|
|
@ -145,7 +145,9 @@ export default function companyPage() {
|
|||
</div>`;
|
||||
} else if (d.data.ftype == 1) {
|
||||
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 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;">
|
||||
|
|
@ -158,7 +160,9 @@ export default function companyPage() {
|
|||
return `
|
||||
<div style="width: 100%; height: 100%; background-size: 100% 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 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;">
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ export default function userPage() {
|
|||
// 获取数据
|
||||
useEffect(() => {
|
||||
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(
|
||||
// "/user/data"
|
||||
'/api/bs/hrmorganization/orgchart/userData?fclass=0&fisvitual=0&root=0&level=3&id=0',
|
||||
|
|
|
|||
Loading…
Reference in New Issue