diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..03d9549
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/public/avatar.jpg b/public/avatar.jpg
new file mode 100644
index 0000000..13ad0f5
Binary files /dev/null and b/public/avatar.jpg differ
diff --git a/public/logo.png b/public/logo.png
new file mode 100644
index 0000000..7a23e05
Binary files /dev/null and b/public/logo.png differ
diff --git a/src/App.css b/src/App.css
index 74b5e05..f56cfd3 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,38 +1,38 @@
-.App {
- text-align: center;
-}
+/*.App {*/
+/* !*text-align: center;*!*/
+/*}*/
-.App-logo {
- height: 40vmin;
- pointer-events: none;
-}
+/*.App-logo {*/
+/* height: 40vmin;*/
+/* pointer-events: none;*/
+/*}*/
-@media (prefers-reduced-motion: no-preference) {
- .App-logo {
- animation: App-logo-spin infinite 20s linear;
- }
-}
+/*@media (prefers-reduced-motion: no-preference) {*/
+/* .App-logo {*/
+/* animation: App-logo-spin infinite 20s linear;*/
+/* }*/
+/*}*/
-.App-header {
- background-color: #282c34;
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: calc(10px + 2vmin);
- color: white;
-}
+/*.App-header {*/
+/* background-color: #282c34;*/
+/* min-height: 100vh;*/
+/* display: flex;*/
+/* flex-direction: column;*/
+/* align-items: center;*/
+/* justify-content: center;*/
+/* font-size: calc(10px + 2vmin);*/
+/* color: white;*/
+/*}*/
-.App-link {
- color: #61dafb;
-}
+/*.App-link {*/
+/* color: #61dafb;*/
+/*}*/
-@keyframes App-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
+/*@keyframes App-logo-spin {*/
+/* from {*/
+/* transform: rotate(0deg);*/
+/* }*/
+/* to {*/
+/* transform: rotate(360deg);*/
+/* }*/
+/*}*/
diff --git a/src/App.js b/src/App.js
index 3784575..c18ff67 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,25 +1,528 @@
-import logo from './logo.svg';
import './App.css';
+import {OrgChart} from "./components/OrgChart";
+import {Component, Fragment} from "react";
+import {OrgChartNode} from "./components/OrgChartNode";
+import "./iconfont/iconfont.css"
-function App() {
- return (
-
+
+ );
+ }
}
export default App;
diff --git a/src/components/OrgChart.jsx b/src/components/OrgChart.jsx
new file mode 100644
index 0000000..b04079a
--- /dev/null
+++ b/src/components/OrgChart.jsx
@@ -0,0 +1,182 @@
+import {Component, Fragment} from 'react'
+// import {OrgChartNode} from "./OrgChartNode";
+import "../css/index.css"
+
+export class OrgChart extends Component {
+
+ state = {
+ marginTop: 0,
+ orgChildren: ""
+ }
+
+ constructor(props) {
+ super(props);
+ this.state = {...this.state, ...props}
+ }
+
+ showOrHidden = (node) => {
+ if (node.showChildren === 0) {
+ this.showChildren(node)
+ } else {
+ this.hiddenChildren((node))
+ }
+ }
+
+ showChildren = (node) => {
+ node.showChildren = 1
+ this.setState({
+ data: {...this.state.data}
+ })
+ }
+
+
+ hiddenChildren = (node) => {
+ this.setState({
+ orgChildren: "hidden-org-children"
+ })
+ setTimeout(() => {
+ node.showChildren = 0
+ this.hiddenChildrenStack(node)
+ this.setState({
+ data: {...this.state.data},
+ orgChildren: "",
+ })
+ }, 300)
+ }
+
+ hiddenChildrenStack = (node)=>{
+ if(!node.children || node.children.length === 0){
+ return
+ }
+ node.children.forEach(item=>{
+ item.showChildren = 0
+ this.hiddenChildrenStack(item)
+ })
+ }
+
+ getOrgChartNode = (node) => {
+ return
+
+ {
+ node.isRoot ? "" : (this.props.parent && this.props.parent.show && this.props.parent.show === 1 ?
+ this.props.hiddenParent(this.props.parent)}>
+ :
+ this.props.showParent(this.props.parent)}>)
+ }
+ {this.state.getChartNode(node)}
+ {/*{*/}
+ {/* node.children && node.children.length > 0 ? (node.showChildren === 0 ?*/}
+ {/* this.showChildren(node)}>*/}
+ {/* */}
+ {/* :*/}
+ {/* this.hiddenChildren(node)}>*/}
+ {/* ) : ""*/}
+ {/*}*/}
+ {
+ node.children && node.children.length > 0 ? {
+ this.showOrHidden(node)
+ }}
+ > : ""
+ }
+
+
+ // return this.props.getChartNode(node)
+ }
+
+ getOrgItem = (parent) => {
+ let getChartNode = this.state.getChartNode
+ let node = this.state.data
+ if (node.children && node.children.length > 0) {
+ return (
+
+
this.setState({marginTop: 2})}
+ onMouseOut={() => this.setState({marginTop: 0})}
+ >
+ {
+ this.getOrgChartNode(node)
+ }
+
+ {
+ node.showChildren === 1 ?
+
+
+
+ {
+ node.children.length === 1 ?
+
+
+ : node.children.map((item, index) => {
+ if (index === 0) {
+ return
+ }
+ if (index === node.children.length - 1) {
+ return
+ }
+ return
+ })
+ }
+
+ : ""
+ }
+
+
+ )
+ } else {
+ return this.getOrgChartNode(node)
+ }
+ }
+
+ render() {
+ return (
+
+ {
+ this.state.lineClass ?
+
+
+
+ {
+ this.getOrgItem(this.props.parent)
+ }
+
+ : {this.getOrgItem(this.props.parent)}
+ }
+
+ )
+ }
+
+}
\ No newline at end of file
diff --git a/src/components/OrgChartItem.jsx b/src/components/OrgChartItem.jsx
new file mode 100644
index 0000000..9011f4d
--- /dev/null
+++ b/src/components/OrgChartItem.jsx
@@ -0,0 +1,45 @@
+import {Component, Fragment} from 'react'
+import {OrgChart} from "./OrgChart";
+
+export class OrgChartItem extends Component {
+
+ getHasChildrenItem = (node) => {
+ return (
+
+
+ {
+ node.children.map(item=>{
+ return
+ })
+ }
+
+
+ )
+ }
+
+ getRenderItem = (node) => {
+ if (node.children || node.children.length > 0) {
+ // 存在下一等级
+ return this.getHasChildrenItem(node)
+ }else {
+ return (
+
+ {
+ this.props.getOrgChartNode(node)
+ }
+
+ )
+ }
+ }
+
+ render() {
+ console.log(this.props)
+ return (
+
+ {
+ this.getRenderItem(this.props.node)
+ }
+
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/components/OrgChartNode.jsx b/src/components/OrgChartNode.jsx
new file mode 100644
index 0000000..e0a400e
--- /dev/null
+++ b/src/components/OrgChartNode.jsx
@@ -0,0 +1,77 @@
+import {Component, Fragment} from 'react'
+import '../css/node.css'
+
+export class OrgChartNode extends Component {
+
+
+ render() {
+ let node = this.props.node
+ return (
+
+
+
+
+
+
+
+
+ {
+ node.type === 1 ?
:
+
+ }
+
+
+
+
{node.downLevel}
+
+
+
+
+ {node.name}
+
+
+
+ DEPARTMENT
+
+
+ {node.department}
+
+
+
+
+ JOB
+
+
+ {node.department}
+
+
+
+
+
+
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/css/index.css b/src/css/index.css
new file mode 100644
index 0000000..c33f584
--- /dev/null
+++ b/src/css/index.css
@@ -0,0 +1,218 @@
+
+body{
+ -moz-user-select:none; /*火狐*/
+ -webkit-user-select:none; /*webkit浏览器*/
+ -ms-user-select:none; /*IE10*/
+ -khtml-user-select:none; /*早期浏览器*/
+ user-select:none;
+ /*cursor: move;*/
+}
+
+#org-chart-container{
+ text-align: center;
+ padding: 20px;
+ position: relative;
+ transform-origin: left center;
+}
+#org-chart-container .org-root{
+ transition: height 0.3s;
+}
+.functional-container{
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ font-size: 14px;
+ display: flex;
+ align-items: center;
+ z-index: 99;
+ background-color:rgba(255,255,255,0.8);
+ padding: 10px;
+ border-radius: 5px;
+ box-shadow: 1px 1px 5px 1px #f1f1f1;
+}
+.functional-container .cus_iconfont{
+ font-size: 25px;
+ margin: 0 5px;
+ cursor: pointer;
+ color: #333;
+ line-height: 0 !important;
+}
+
+.functional-container>span{
+ margin: 0 5px;
+ color: #666;
+}
+.functional-container .cus_iconfont:hover{
+ color: #C32929;
+}
+
+
+#org-chart-container .org-children-chart{
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: flex-start;
+ animation: 0.3s children-show;
+ opacity: 1;
+ transition: 0.3s all;
+ /*margin-top: -20px;*/
+}
+
+#org-chart-container .org-children-chart.hidden-org-children{
+ animation: 0.4s children-hidden;
+}
+
+
+@keyframes children-hidden {
+ 0%{
+ overflow: hidden;
+ }
+ 70%{
+ opacity: 0;
+ overflow: hidden;
+ }
+
+ to{
+ margin-top: -50px;
+ z-index: -1;
+ height: 0;
+ opacity: 0;
+ overflow: hidden;
+ }
+}
+
+@keyframes children-show {
+ from{
+ opacity: 0;
+ margin-top: -50px;
+ }
+ to{
+ margin-top: 0px;
+ opacity: 1;
+ }
+}
+
+#org-chart-container .line{
+ line-height: 0 !important;
+}
+
+
+#org-chart-container .org-chart-node {
+ display: inline-block;
+ /*line-height: 0;*/
+ /*position: relative;*/
+ /*left: 50%;*/
+ /*transform: translateX(-50%);*/
+}
+#org-chart-container .org-chart-root{
+ display: inline-block;
+}
+
+#org-chart-container .bottom-down-line{
+ width: 2px;
+ height: 20px;
+ background-color: #C32929;
+ position: relative;
+ left: 50%;
+ transform: translateX(-50%);
+ transition: all 0.3s;
+}
+
+#org-chart-container .right-row-line{
+ height: 2px;
+ width: 50%;
+ position: relative;
+ left: 50%;
+ background-color: #C32929;
+ transition: all 0.3s;
+}
+#org-chart-container .left-row-line{
+ height: 2px;
+ width: 50%;
+ position: relative;
+ left: 0;
+ background-color: #C32929;
+ transition: all 0.3s;
+}
+#org-chart-container .row-line{
+ height: 2px;
+ position: relative;
+ left: 0;
+ background-color: #C32929;
+ transition: all 0.3s;
+}
+#org-chart-container .top-down-line{
+ height: 20px;
+ width: 2px;
+ background-color: #C32929;
+ position: relative;
+ top: -2px;
+ left: 50%;
+ transform: translateX(-50%);
+ transition: all 0.3s;
+}
+
+
+#org-chart-container .org-chart-item{
+ position: relative;
+ margin-top: -3px;
+}
+
+#org-chart-container .org-chart-item:hover{
+ transition: all 0.3s;
+ /*transform: scale(0.975);*/
+}
+
+
+
+
+#org-chart-container .org-chart-item .hidden-icon{
+ transform: translateX(-50%) rotateZ(180deg) !important;
+ display: inline-block;
+}
+#org-chart-container .org-chart-item .show-parent-icon{
+ transform: rotateZ(180deg);
+ display: inline-block;
+}
+
+#org-chart-container .org-chart-item .expansion-icon{
+ position: absolute;
+ bottom: -16px;
+ font-size: 25px;
+ left: 50%;
+ transform: translateX(-50%);
+ z-index: 999;
+ display: none;
+ color: #C32929;
+ cursor: pointer !important;
+}
+#org-chart-container .org-chart-item:hover .expansion-icon{
+ display: inline-block;
+}
+#org-chart-container .org-chart-item .expansion-icon:hover{
+ color: #C32929;
+ transform: translateX(-50%);
+ font-size: 30px;
+ transition: all 0.3s;
+}
+
+#org-chart-container .org-chart-item .show-or-hidden{
+ color: #C32929;
+ font-size: 31px;
+ position: absolute;
+ bottom: -15px;
+ transform: translateX(-50%);
+ transition: all 0.3s;
+ opacity: 0;
+}
+#org-chart-container .org-chart-item:hover .show-or-hidden{
+ display: inline-block;
+ opacity: 1;
+ bottom: -17px;
+ cursor: pointer;
+}
+
+
+#org-chart-container .org-chart-item .show-or-hidden:hover{
+ transform: translateX(-50%) scale(1.125);
+ transform-origin: center;
+}
\ No newline at end of file
diff --git a/src/css/node.css b/src/css/node.css
new file mode 100644
index 0000000..eaa1192
--- /dev/null
+++ b/src/css/node.css
@@ -0,0 +1,150 @@
+
+.node-container{
+ width: 160px;
+ border: 1px #C32929 solid;
+ border-radius: 10px;
+ position: relative;
+ margin: 50px 15px 0px 15px;
+ font-size: 10px;
+ padding: 10px 10px 20px 10px;
+ height: 100%;
+ animation: 0.6s show;
+}
+
+.org-chart-node-item{
+ overflow: hidden;
+ margin: 0 0 -3px 0;
+}
+.node-container .content-container{
+ animation: 0.5s show-content;
+}
+
+@keyframes show-content {
+ from{
+ height: 0;
+ opacity: 0;
+ overflow: hidden;
+ }
+ 90%{
+ overflow: hidden;
+ }
+ to{
+ height: auto;
+ opacity: 1;
+ }
+}
+
+.hidden-org-children .node-container{
+ animation: 0.6s hidden;
+}
+
+.hidden-org-children .node-container .content-container{
+ animation: 0.6s hidden-content;
+}
+
+@keyframes hidden-content {
+ 0%{
+ overflow: hidden;
+ }
+ to{
+ overflow: hidden;
+ width: 0;
+ opacity: 0;
+ height: 0;
+ }
+}
+@keyframes hidden {
+ to{
+ width: 0;
+ opacity: 0;
+ height: 0;
+ }
+}
+
+@keyframes show {
+ from{
+ width: 0;
+ opacity: 0;
+ height: 0;
+ }
+ to{
+ width: 160px;
+ opacity: 1;
+ }
+}
+
+
+.node-container .avatar-container{
+ border-radius: 50%;
+ width: 100px;
+ height: 100px;
+ overflow: hidden;
+ position: absolute;
+ left: 50%;
+ top: -50px;
+ transform: translateX(-50%);
+ border: 1px #C32929 solid;
+ background-color: #f2f2f2;
+}
+.node-container .logo{
+ position: absolute;
+ left: calc(50% + 2px);
+ transform: translateX(-50%);
+ z-index: 10;
+ top: 42px;
+}
+
+.node-container .down-level-type{
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ color: #666666;
+}
+
+.node-container .down-level-type .down-level{
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ font-size: 10px;
+}
+
+.node-container .name{
+ margin-top: 35px;
+ font-size: 14px;
+ font-weight: 600;
+}
+
+.node-container .department-job-container{
+ margin-top: 10px;
+ text-align: left;
+}
+
+.node-container .department-job-container .title{
+ font-weight: 600;
+ font-size: 12px;
+ text-align: left;
+ padding: 5px 0;
+ display: flex;
+ align-items: center;
+}
+
+.node-container .department-job-container .title::before{
+ content: "";
+ display: inline-block;
+ width: 4px;
+ height: 13px;
+ background-color: #C32929;
+ margin-right: 5px;
+}
+
+.node-container .department-job-container .content{
+ font-size: 12px;
+ margin-left: 8px;
+ color: #666;
+ transform: scale(0.8);
+ width: 125%;
+ transform-origin:center left;
+}
+
+
diff --git a/src/iconfont/iconfont.css b/src/iconfont/iconfont.css
new file mode 100644
index 0000000..7efdc7b
--- /dev/null
+++ b/src/iconfont/iconfont.css
@@ -0,0 +1,63 @@
+@font-face {
+ font-family: "cus_iconfont"; /* Project id 3778032 */
+ src: url('iconfont.woff2?t=1669465666296') format('woff2'),
+ url('iconfont.woff?t=1669465666296') format('woff'),
+ url('iconfont.ttf?t=1669465666296') format('truetype');
+}
+
+.cus_iconfont {
+ font-family: "cus_iconfont" !important;
+ font-size: 16px;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-fangda1:before {
+ content: "\e614";
+}
+
+.icon-zhongzhi:before {
+ content: "\e613";
+}
+
+.icon-fangda:before {
+ content: "\e60f";
+}
+
+.icon-24gf-shrinkVertical2:before {
+ content: "\eb78";
+}
+
+.icon-24gf-shrinkHorizontal2:before {
+ content: "\eb79";
+}
+
+.icon-suoxiao:before {
+ content: "\e612";
+}
+
+.icon-zhankai_mian:before {
+ content: "\e639";
+}
+
+.icon-zhankai-mian:before {
+ content: "\e60e";
+}
+
+.icon-yuandian:before {
+ content: "\e683";
+}
+
+.icon-zhankai:before {
+ content: "\e65d";
+}
+
+.icon-bjxxjr:before {
+ content: "\e606";
+}
+
+.icon-qunzu:before {
+ content: "\e6da";
+}
+
diff --git a/src/iconfont/iconfont.ttf b/src/iconfont/iconfont.ttf
new file mode 100644
index 0000000..6d77cf5
Binary files /dev/null and b/src/iconfont/iconfont.ttf differ
diff --git a/src/iconfont/iconfont.woff b/src/iconfont/iconfont.woff
new file mode 100644
index 0000000..1db0f27
Binary files /dev/null and b/src/iconfont/iconfont.woff differ
diff --git a/src/iconfont/iconfont.woff2 b/src/iconfont/iconfont.woff2
new file mode 100644
index 0000000..63a84fd
Binary files /dev/null and b/src/iconfont/iconfont.woff2 differ