diff --git a/dist.zip b/dist.zip deleted file mode 100644 index 88723e5..0000000 Binary files a/dist.zip and /dev/null differ diff --git a/public/img/change.png b/public/img/change.png new file mode 100644 index 0000000..b08b481 Binary files /dev/null and b/public/img/change.png differ diff --git a/src/components/drawer/index.jsx b/src/components/drawer/index.jsx new file mode 100644 index 0000000..e434c86 --- /dev/null +++ b/src/components/drawer/index.jsx @@ -0,0 +1,348 @@ +import React from 'react'; +import { Drawer, Space, Button, Dropdown, Menu, Table } 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'; + +let addNodeChildFunc = null; +let orgChart = null; +let active = 'top'; +export default class DrawerComponents extends React.Component { + constructor(props) { + super(props); + this.state = { + open: false, + data: [], + detailType: 'chart', + rootId: '', + }; + } + + componentDidMount() { + //this.getDeatilDatas(); + } + + // 点击节点 + onNodeClick(node) {} + + 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 = '/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`; + } + + //获取数据 + getDeatilDatas(rootId) { + const { detailType } = this.state; + d3.json( + '/api/bs/hrmorganization/orgchart/userData?' + + qs.stringify({ detauleType: detailType, rootId: rootId }), + ).then((data) => { + this.setState(data.data); + }); + } + + // ButtonContent渲染 + buttonContentRender = ({ node, state }) => { + return ` +
+ +
+ `; + }; + + // 节点宽度渲染 + nodeWidthRender = (d) => { + return 280; + }; + + nodeHeightRender = (d) => { + return 160; + }; + + // tool bar start + handleTopLayoutClick = (progressBtn) => { + progressBtn.current.style.top = 50 + 'px'; + orgChart && + orgChart + .setCentered(orgChart.getChartState().root.id) + .layout('top') + .render(); + active = 'top'; + }; + + handleLeftLayoutClick = (progressBtn) => { + progressBtn.current.style.top = 50 + 'px'; + orgChart && + orgChart + .layout('left') + .setCentered(orgChart.getChartState().root.id) + .render(); + active = 'left'; + }; + + 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(); + }; + + 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(); + }; + + 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'); + }; + }, + }); + } + + handleExport = (e) => { + let type = e.key == '1' ? 'png' : 'pdf'; + if (type == 'png') { + orgChart && orgChart.exportImg({ full: true }); + } else { + orgChart && downloadPdf(orgChart); + } + }; + + /** + * 节点渲染 + */ + nodeContentRender = (d, i, arr, state) => { + if (d.data.ftype == 2) { + return `
+
+
+ +
+
+ + +
+
+
${ + d.data.fleadername + }
+
+ ${d.data.fname}${ + d.data.fleaderjob ? `/${d.data.fleaderjob}` : '' + } +
+
+
+
+ 在岗: ${d.data.fonjob} +
+
+
+
`; + } else if (d.data.ftype == 3) { + return `
+
+
+ +
+ +
+
${d.data.fname}
+
+ 在岗:${d.data.fonjob} +
+
+
+
`; + } else if (d.data.ftype == 4) { + return `
+
+
+ +
+
+ + +
+
+
+
${ + d.data.fname + }
+
+
+
+
`; + } + }; + + showDrawer = (rootId) => { + this.getDeatilDatas(rootId); + this.setState({ open: true, rootId: rootId }); + }; + + onClose = () => { + this.setState({ open: false }); + }; + + changeDetail = () => { + const { detailType, rootId } = this.state; + this.getDeatilDatas(rootId); + this.setState({ + detailType: detailType == 'chart' ? 'table' : 'chart', + }); + }; + + render() { + const { open, data, detailType } = this.state; + + const menu = ( + + ); + 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', + }, + ]; + + return ( + + + + + + + } + > + {detailType == '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} + /> + ) : ( + + )} + + ); + } +} diff --git a/src/components/drawer/index.less b/src/components/drawer/index.less new file mode 100644 index 0000000..e69de29 diff --git a/src/components/timeline/index.jsx b/src/components/timeline/index.jsx index d33bd0e..49f34e8 100644 --- a/src/components/timeline/index.jsx +++ b/src/components/timeline/index.jsx @@ -2,7 +2,7 @@ * @Author: Chengliang 1546584672@qq.com * @Date: 2023-06-25 16:33:21 * @LastEditors: Chengliang 1546584672@qq.com - * @LastEditTime: 2023-06-28 16:02:39 + * @LastEditTime: 2023-06-29 14:24:04 * @FilePath: /org-chart-frant/src/components/timeline/index.jsx * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ @@ -33,29 +33,17 @@ export default class TimeLine extends React.Component { } componentDidMount() { - // fetch(this.props.url) - // .then((res) => res.json()) - // .then((data) => { - // this.setState({ - // timelineList: data.timelineList, - // }); - // }); - const datas = [ - { key: 0, id: 0, title: '当前版本', color: 'blue', time: '' }, - { key: 1, id: 1, title: '测试', color: 'grey', time: '2022-01-09' }, - { key: 2, id: 2, title: '测试', color: 'grey', time: '2022-01-09' }, - { key: 3, id: 3, title: '测试', color: 'grey', time: '2022-01-09' }, - { key: 4, id: 4, title: '测试', color: 'grey', time: '2022-01-09' }, - { key: 5, id: 5, title: '测试', color: 'grey', time: '2022-01-09' }, - { key: 6, id: 6, title: '测试', color: 'grey', time: '2022-01-09' }, - { key: 7, id: 7, title: '测试', color: 'grey', time: '2022-01-09' }, - { key: 8, id: 8, title: '测试', color: 'grey', time: '2022-01-09' }, - { key: 9, id: 9, title: '测试', color: 'grey', time: '2022-01-09' }, - { key: 10, id: 10, title: '测试', color: 'grey', time: '2022-01-09' }, - ]; - this.setState({ - timelineList: datas, - }); + this.searchTimeLines(this.props.url); + } + + searchTimeLines(url) { + fetch(url) + .then((res) => res.json()) + .then((data) => { + this.setState({ + timelineList: data.timelineList, + }); + }); } render() { diff --git a/src/components/topBar/index.jsx b/src/components/topBar/index.jsx index d295165..f39c473 100644 --- a/src/components/topBar/index.jsx +++ b/src/components/topBar/index.jsx @@ -94,18 +94,17 @@ export class TopBar extends React.Component { * @param {} parentId * @returns */ - getNodeTreeNode = (parentId) => { - const { fclass } = this.state.requestData; - let api = - '/api/bs/hrmorganization/orgchart/getSubCompanyTree?subcompany=' + - parentId + - '&fclass=' + - fclass; - fetch(api) + getNodeTreeNode = (url, merge = true) => { + fetch(url) .then((res) => res.json()) .then((data) => { if (data.api_status) { - let arr = [...this.state.rootTreeData, ...data.companyTree]; + let arr = []; + if (merge) { + arr = [...this.state.rootTreeData, ...data.companyTree]; + } else { + arr = [...data.companyTree]; + } this.setState({ rootTreeData: arr, }); @@ -122,7 +121,13 @@ export class TopBar extends React.Component { new Promise((resolve) => { const { id } = treeNode.props; setTimeout(() => { - this.getNodeTreeNode(id); + const { fclass } = this.state.requestData; + let api = + '/api/bs/hrmorganization/orgchart/getSubCompanyTree?subcompany=' + + id + + '&fclass=' + + fclass; + this.getNodeTreeNode(api); resolve(undefined); }, 500); }); @@ -190,10 +195,11 @@ export class TopBar extends React.Component { fisvitual: '0', }; this.handleFormChange(requestData); - this.getSeatchCondition( - `/api/bs/hrmorganization/orgchart/getCondition?fclass=${value}&type=${this.props.type}`, + this.getNodeTreeNode( + `/api/bs/hrmorganization/orgchart/getSubCompanyTree?fclass=${value}`, + false, ); - this.props.onSearch(requestData); + this.props.changeFclass(requestData); }} > {this.state.fclasslist.map((item) => ( diff --git a/src/d3-org-chart.js b/src/d3-org-chart.js index 62276d0..13ddc87 100644 --- a/src/d3-org-chart.js +++ b/src/d3-org-chart.js @@ -1076,7 +1076,8 @@ export class OrgChart { ) { return; } - attrs.onNodeClick(attrs.nodeId(data)); + //attrs.onNodeClick(attrs.nodeId(data)); + attrs.onNodeClick(data); }); // Add background rectangle for the nodes diff --git a/src/pages/company.jsx b/src/pages/company.jsx index ab93e05..186d41d 100644 --- a/src/pages/company.jsx +++ b/src/pages/company.jsx @@ -5,14 +5,17 @@ import * as d3 from 'd3'; import { TopBar } from '../components/topBar'; import ToolBar from '../components/toolBar'; import TimeLine from '../components/timeline'; +import DrawerComponents from '../components/drawer'; import jsPDF from 'jspdf'; import moment from 'moment'; import qs from 'qs'; -import { message } from 'antd'; +import { message, Spin } from 'antd'; let active = 'top'; 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; @@ -21,10 +24,13 @@ export default function companyPage() { let topBarSearchRequest = null; const [hasRight, setHasRight] = useState(''); const [id, setId] = useState(0); + const [spinning, setSpinning] = useState(false); // 点击节点 - function onNodeClick(nodeId) { - // alert('clicked ' + nodeId); + function onNodeClick(node) { + if (node.ftype == '2') { + drawerCom.showDrawer(node.id); + } } // 扩展按钮点击 @@ -74,8 +80,7 @@ export default function companyPage() { // 获取分部图片 function getSubcompanyImage() { - let index = Math.floor(Math.random() * 3) + 1; - return `./img/subcompany/2.png`; + return `./img/back/level1.png`; } // 获取数据 @@ -113,7 +118,7 @@ export default function companyPage() { if (d.data.ftype == 0) { return 100; } else if (d.data.ftype == 1) { - return 80; + return 106; } else if (d.data.ftype == 2) { return 106; } @@ -121,16 +126,8 @@ export default function companyPage() { }; 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}`; - if (d.data.ftype == 0) { - return `
+ return `
@@ -147,23 +144,19 @@ export default function companyPage() {
`; } else if (d.data.ftype == 1) { - return `
-
- ${d.data.fname} + return `
+
-
`; +
+
${d.data.fname}
+
`; } else if (d.data.ftype == 2) { return ` -
+
@@ -278,6 +271,7 @@ export default function companyPage() { * @param {*} requestData */ const handleSearch = (requestData, cache = true) => { + setSpinning(true); if (cache) { requestData = { ...requestData, id: id }; } @@ -296,9 +290,21 @@ export default function companyPage() { setData(data?.data); } } + setSpinning(false); }); }; + /** + * 切换维度 + * @param {*} requestData + */ + const handleChange = (requestData) => { + timeLine.searchTimeLines( + `/api/bs/hrmorganization/orgchart/timeLines?fclass=${requestData.fclass}`, + ); + handleSearch(requestData); + }; + useEffect(() => { if (active == 'left') { orgChart && @@ -338,6 +344,9 @@ export default function companyPage() { onSearch={(requestData) => { handleSearch(requestData); }} + changeFclass={(requestData) => { + handleChange(requestData); + }} type="company" url="/api/bs/hrmorganization/orgchart/getCondition?fclass=0&type=company" /> @@ -351,22 +360,27 @@ export default function companyPage() { onZoomBehavior={(value) => handleZoomBehavior(value)} /> (timeLine = r)} onClick={(timeline) => { timeLineSearch(timeline); }} - url={'/api/bs/hrmorganization/orgchart/timelines?id=' + id} - /> - (orgChart = chart)} - setClick={(click) => (addNodeChildFunc = click)} - onNodeClick={onNodeClick} - data={data} - onButtonClick={onButtonClick} - buttonContent={buttonContentRender} - nodeWidth={nodeWidthRender} - nodeHeight={nodeHeightRender} - nodeContent={nodeContentRender} + url={'/api/bs/hrmorganization/orgchart/timeLines?fclass=0'} /> + + (orgChart = chart)} + setClick={(click) => (addNodeChildFunc = click)} + onNodeClick={onNodeClick} + data={data} + onButtonClick={onButtonClick} + buttonContent={buttonContentRender} + nodeWidth={nodeWidthRender} + nodeHeight={nodeHeightRender} + nodeContent={nodeContentRender} + /> + + + (drawerCom = r)} />
) ); diff --git a/src/pages/user.jsx b/src/pages/user.jsx index 513b7e9..be699af 100644 --- a/src/pages/user.jsx +++ b/src/pages/user.jsx @@ -5,7 +5,6 @@ import * as d3 from 'd3'; import { TopBar } from '../components/topBar'; import ToolBar from '../components/toolBar'; import TimeLine from '../components/timeline'; - import moment from 'moment'; import qs from 'qs'; import { message } from 'antd'; @@ -14,6 +13,7 @@ let active = 'top'; export default function userPage() { const [data, setData] = useState(null); let topbar = null; + let timeLine = null; const [topBarSearchRequest, setTpBarSearchRequest] = useState(null); const [requestRes, setRequestRes] = useState({ date: moment(new Date()).format('YYYY-MM-DD'), @@ -99,7 +99,7 @@ export default function userPage() { // 获取数据 useEffect(() => { document.cookie = - 'ecology_JSessionid=aaaMxyh0rOLot5nEk86Jy; JSESSIONID=aaaMxyh0rOLot5nEk86Jy; __randcode__=39ee6033-5f6f-4e53-ad53-5a3de97645eb; Systemlanguid=7; languageidweaver=7; loginidweaver=sysadmin; loginuuids=1'; + 'ecology_JSessionid=aaazPUne5WAU1eB9vTfKy; JSESSIONID=aaazPUne5WAU1eB9vTfKy; Systemlanguid=7; languageidweaver=7; loginidweaver=sysadmin; loginuuids=1; __randcode__=0fd53114-a13b-400b-a7bc-bb0ffb7ab567'; d3.json( // "/user/data" '/api/bs/hrmorganization/orgchart/userData?fclass=0&fisvitual=0&root=0&level=3&id=0', @@ -172,10 +172,6 @@ export default function userPage() { orgChart && orgChart.zoomOut(); }; - // tool bar end - - // top bar start - function downloadPdf(chart) { chart.exportImg({ save: false, @@ -229,6 +225,17 @@ export default function userPage() { }); }; + /** + * 切换维度 + * @param {*} requestData + */ + const handleChange = (requestData) => { + timeLine.searchTimeLines( + `/api/bs/hrmorganization/orgchart/timeLines?fclass=${requestData.fclass}`, + ); + handleSearch(requestData); + }; + useEffect(() => { if (active == 'left') { orgChart && @@ -512,6 +519,9 @@ export default function userPage() { setRequestRes(requestData); handleSearch(requestData); }} + changeFclass={(requestData) => { + handleChange(requestData); + }} type="user" url="/api/bs/hrmorganization/orgchart/getCondition?fclass=0&type=user" /> @@ -522,10 +532,11 @@ export default function userPage() { onZoomIn={(progressBtn) => handleZoomIn(progressBtn)} /> (timeLine = r)} onClick={(timeline) => { timeLineSearch(timeline); }} - url={'/api/bs/hrmorganization/orgchart/timelines?id=' + id} + url={'/api/bs/hrmorganization/orgchart/timeLines?fclass=0'} /> (orgChart = chart)}