组织结构图v1.0
@ -0,0 +1,16 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
@ -0,0 +1,20 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/npm-debug.log*
|
||||
/yarn-error.log
|
||||
/yarn.lock
|
||||
/package-lock.json
|
||||
|
||||
# production
|
||||
/dist
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
|
||||
# umi
|
||||
/src/.umi
|
||||
/src/.umi-production
|
||||
/src/.umi-test
|
||||
/.env.local
|
@ -0,0 +1,8 @@
|
||||
**/*.md
|
||||
**/*.svg
|
||||
**/*.ejs
|
||||
**/*.html
|
||||
package.json
|
||||
.umi
|
||||
.umi-production
|
||||
.umi-test
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 80,
|
||||
"overrides": [
|
||||
{
|
||||
"files": ".prettierrc",
|
||||
"options": { "parser": "json" }
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { defineConfig } from 'umi';
|
||||
|
||||
export default defineConfig({
|
||||
hash: true,
|
||||
history: { type: 'hash'},
|
||||
base: "/spa/orgChart/",
|
||||
// exportStatic: {},
|
||||
publicPath: './',
|
||||
nodeModulesTransform: {
|
||||
type: 'none',
|
||||
},
|
||||
routes: [
|
||||
{ path: '/user', component: '@/pages/user' },
|
||||
{ path: '/company', component: '@/pages/company' }
|
||||
],
|
||||
fastRefresh: {},
|
||||
antd: {},
|
||||
proxy: {
|
||||
"/api": { // 标识需要进行转换的请求的url
|
||||
"target": "http://localhost:18089/api", // 服务端域名
|
||||
"changeOrigin": true, // 允许域名进行转换
|
||||
"pathRewrite": { "^/api": ''} // 将请求url里的ci去掉
|
||||
}
|
||||
}
|
||||
});
|
@ -0,0 +1,15 @@
|
||||
# umi project
|
||||
|
||||
## Getting Started
|
||||
|
||||
Install dependencies,
|
||||
|
||||
```bash
|
||||
$ yarn
|
||||
```
|
||||
|
||||
Start the dev server,
|
||||
|
||||
```bash
|
||||
$ yarn start
|
||||
```
|
@ -0,0 +1,158 @@
|
||||
export default {
|
||||
'GET /company/data': [
|
||||
{
|
||||
"id": 1,
|
||||
"fname": "集团公司",
|
||||
"ftype": 0,
|
||||
"parentId": null
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"fname": "HRSSC共享服务中心",
|
||||
"ftype": 1,
|
||||
"parentId": 1
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"fname": "事业部A",
|
||||
"ftype": 1,
|
||||
"parentId": 1
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"fname": "苏州分公司",
|
||||
"ftype": 1,
|
||||
"parentId": 1
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"fname": "人力资源部经理",
|
||||
"ftype": 2,
|
||||
"parentId": 2
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"fname": "招聘组",
|
||||
"ftype": 2,
|
||||
"parentId": 3
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"fname": "薪酬核算组",
|
||||
"ftype": 2,
|
||||
"parentId": 4
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"fname": "人事服务组",
|
||||
"ftype": 2,
|
||||
"parentId": 2
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"fname": "培训组",
|
||||
"ftype": 2,
|
||||
"parentId": 2
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"fname": "员工关系组",
|
||||
"ftype": 2,
|
||||
"parentId": 2
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"fname": "服务管理组",
|
||||
"ftype": 2,
|
||||
"parentId": 2
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"fname": "信息与数据组",
|
||||
"ftype": 2,
|
||||
"parentId": 2
|
||||
}
|
||||
],
|
||||
'GET /user/data': [
|
||||
{
|
||||
"id": 1,
|
||||
"parentId": null,
|
||||
"ftype": 0,
|
||||
"fname": "维森集团",
|
||||
"fleadername": "杨文元",
|
||||
"fleaderimg": "./img/avator.png",
|
||||
"fleaderjob": "董事长",
|
||||
"fplan": 1000,
|
||||
"fonjob": 987
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"parentId": 1,
|
||||
"ftype": 1,
|
||||
"fname": "南京分公司",
|
||||
"fleadername": "杨文元",
|
||||
"fleaderimg": "./img/avator.png",
|
||||
"fleaderjob": "总经理",
|
||||
"fplan": 300,
|
||||
"fonjob": 287
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"parentId": 1,
|
||||
"ftype": 1,
|
||||
"fname": "南京分公司",
|
||||
"fleadername": "杨文元",
|
||||
"fleaderimg": "./img/avator.png",
|
||||
"fleaderjob": "总经理",
|
||||
"fplan": 300,
|
||||
"fonjob": 287
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"parentId": 1,
|
||||
"ftype": 1,
|
||||
"fname": "南京分公司",
|
||||
"fleadername": "杨文元",
|
||||
"fleaderimg": "./img/avator.png",
|
||||
"fleaderjob": "总经理",
|
||||
"fplan": 300,
|
||||
"fonjob": 287
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"parentId": 2,
|
||||
"ftype": 2,
|
||||
"fname": "销售部",
|
||||
"fleadername": "杨文元",
|
||||
"fleaderimg": "./img/avator.png",
|
||||
"fleaderjob": "部长",
|
||||
"fplan": 200,
|
||||
"fonjob": 200
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"parentId": 5,
|
||||
"ftype": 3,
|
||||
"fname": "销售",
|
||||
"fleadername": null,
|
||||
"fleaderimg": null,
|
||||
"fleaderjob": null,
|
||||
"fplan": 200,
|
||||
"fonjob": 200
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"parentId": 6,
|
||||
"ftype": 4,
|
||||
"fname": "杨文元",
|
||||
"fleadername": "杨文元",
|
||||
"department": "销售部",
|
||||
"fleaderimg": "./img/avator.png",
|
||||
"fleaderjob": "销售",
|
||||
"mobile": "13989058743",
|
||||
"address": "秦淮区新街口12-201",
|
||||
"fplan": 200,
|
||||
"fonjob": 200
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "umi dev",
|
||||
"build": "umi build",
|
||||
"postinstall": "umi generate tmp",
|
||||
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
|
||||
"test": "umi-test",
|
||||
"test:coverage": "umi-test --coverage"
|
||||
},
|
||||
"gitHooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,less,md,json}": [
|
||||
"prettier --write"
|
||||
],
|
||||
"*.ts?(x)": [
|
||||
"prettier --parser=typescript --write"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/pro-layout": "^6.5.0",
|
||||
"@types/d3": "^7.4.0",
|
||||
"d3": "7.4.4",
|
||||
"d3-org-chart": "2.6.0",
|
||||
"jspdf": "^2.5.1",
|
||||
"moment": "^2.29.3",
|
||||
"qs": "^6.11.0",
|
||||
"react": "17.x",
|
||||
"react-dom": "17.x",
|
||||
"umi": "^3.5.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"@umijs/preset-react": "1.x",
|
||||
"@umijs/test": "^3.5.26",
|
||||
"lint-staged": "^10.0.7",
|
||||
"prettier": "^2.2.0",
|
||||
"typescript": "^4.1.2",
|
||||
"yorkie": "^2.0.0"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 238 B |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 737 B |
After Width: | Height: | Size: 978 B |
After Width: | Height: | Size: 981 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 997 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 945 B |
After Width: | Height: | Size: 978 B |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 232 B |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 5.5 KiB |
@ -0,0 +1,58 @@
|
||||
import React, { useLayoutEffect, useRef, useEffect } from 'react';
|
||||
import { OrgChart } from 'd3-org-chart';
|
||||
import * as d3 from 'd3';
|
||||
|
||||
export const OrgChartComponent = (props, ref) => {
|
||||
const d3Container = useRef(null);
|
||||
let chart = null;
|
||||
|
||||
function addNode(node) {
|
||||
chart.addNode(node);
|
||||
}
|
||||
|
||||
props.setClick(addNode);
|
||||
|
||||
|
||||
// We need to manipulate DOM
|
||||
useLayoutEffect(() => {
|
||||
if (props.data && d3Container.current) {
|
||||
if (!chart) {
|
||||
chart = new OrgChart();
|
||||
}
|
||||
props.setChart(chart)
|
||||
try {
|
||||
chart
|
||||
.container(d3Container.current)
|
||||
.data(props.data)
|
||||
.nodeWidth(props.nodeWidth)
|
||||
.nodeHeight(props.nodeHeight)
|
||||
.layout("left")
|
||||
|
||||
.linkUpdate(function(d, i, arr) {
|
||||
d3.select(this)
|
||||
.attr("stroke", "#66BAF5")
|
||||
.attr("stroke-width", 1)
|
||||
.style("stroke-dasharray", ("3, 3"))
|
||||
})
|
||||
.onNodeClick((d, i, arr) => {
|
||||
console.log(d, 'Id of clicked node ');
|
||||
props.onNodeClick(d);
|
||||
})
|
||||
.buttonContent(props.buttonContent)
|
||||
.nodeContent(props.nodeContent)
|
||||
.render();
|
||||
|
||||
chart.expandAll()
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
}, [props.data, d3Container.current]);
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div ref={d3Container} />
|
||||
</div>
|
||||
);
|
||||
};
|
After Width: | Height: | Size: 798 B |
After Width: | Height: | Size: 744 B |
After Width: | Height: | Size: 643 B |
After Width: | Height: | Size: 438 B |
After Width: | Height: | Size: 372 B |
After Width: | Height: | Size: 515 B |
@ -0,0 +1,38 @@
|
||||
.toolbarWrapper {
|
||||
width: 68px;
|
||||
position: fixed;
|
||||
right: 10px;
|
||||
z-index: 100;
|
||||
background: #fff;
|
||||
border-radius: 20px;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
.progressWrapper {
|
||||
position: relative;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
margin-left: 20px;
|
||||
.progressLine {
|
||||
height: 100px;
|
||||
width: 0px;
|
||||
border-left: 2px solid #C9C9C9;
|
||||
margin-left: 12px;
|
||||
}
|
||||
.progressBtn {
|
||||
width: 16px;
|
||||
height: 9px;
|
||||
background-color: #C9C9C9;
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
.toolBarItem {
|
||||
display: block;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
margin-left: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
.topbarWrapper {
|
||||
margin: 20px;
|
||||
background: #FFFFFF;
|
||||
// background: red;
|
||||
padding: 20px 26px 20px 26px;
|
||||
box-shadow: 0px 5px 5px #e2e2e2;
|
||||
border-radius: 0px 0px 0px 0px;
|
||||
vertical-align: middle;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import React from 'react'
|
||||
|
||||
export default () => {
|
||||
return <div>Hello</div>
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
.title {
|
||||
background: rgb(121, 242, 157);
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
background: #F7F9FD;
|
||||
}
|
||||
|
||||
.contentWrapper {
|
||||
background-color: #F7F9FD;
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import styles from './index.less';
|
||||
|
||||
export default function IndexPage() {
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<h1 className={styles.title}>Page index</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"importHelpers": true,
|
||||
"jsx": "react-jsx",
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": "./",
|
||||
"strict": true,
|
||||
"paths": {
|
||||
"@/*": ["src/*"],
|
||||
"@@/*": ["src/.umi/*"]
|
||||
},
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": [
|
||||
"mock/**/*",
|
||||
"src/**/*",
|
||||
"config/**/*",
|
||||
".umirc.ts",
|
||||
"typings.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"lib",
|
||||
"es",
|
||||
"dist",
|
||||
"typings",
|
||||
"**/__test__",
|
||||
"test",
|
||||
"docs",
|
||||
"tests"
|
||||
]
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
declare module '*.css';
|
||||
declare module '*.less';
|
||||
declare module '*.png';
|
||||
declare module '*.svg' {
|
||||
export function ReactComponent(
|
||||
props: React.SVGProps<SVGSVGElement>,
|
||||
): React.ReactElement;
|
||||
const url: string;
|
||||
export default url;
|
||||
}
|