diff --git a/src/api/index.ts b/src/api/index.ts index b9dcae1..ea40a39 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -86,5 +86,9 @@ export default { set_openPrice(body: object) { return $axios.post('/admin/updOpenPrice', body) }, + user_relation(data: object) { + return $axios.post('/admin/inviti', data) + } + } diff --git a/src/pages/chart/data.ts b/src/pages/chart/data.ts new file mode 100644 index 0000000..12a4ff8 --- /dev/null +++ b/src/pages/chart/data.ts @@ -0,0 +1,53 @@ +import dagre from 'dagre'; +const edgeType = 'smoothstep'; + +export const flattenTree = (tree) => { + let stack = [tree]; + let nodes = []; + let edges = []; + while (stack.length > 0) { + let node = stack.pop(); + nodes.push({ id: node.id, data: { ...node, label: `${node.name}` }, position: node.position }); + if (node.children && node.children.length > 0) { + node.children.map(item => { + edges.push({ source: node.id, target: item.id, id: item.id, type: edgeType, animated: true }); + stack.unshift(item); + }); + }; + }; + return { nodes, edges }; +}; + +export const getLayoutedElements = (nodes, edges, direction = 'TB') => { + const dagreGraph = new dagre.graphlib.Graph(); + dagreGraph.setDefaultEdgeLabel(() => ({})); + + const nodeWidth = 172; + const nodeHeight = 36; + const isHorizontal = direction === 'LR'; + dagreGraph.setGraph({ rankdir: direction }); + + nodes.forEach((node: any) => { + dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight }); + }); + + edges.forEach((edge: any) => { + dagreGraph.setEdge(edge.source, edge.target); + }); + + dagre.layout(dagreGraph); + + nodes.forEach((node: any) => { + const nodeWithPosition = dagreGraph.node(node.id); + node.targetPosition = isHorizontal ? 'left' : 'top'; + node.sourcePosition = isHorizontal ? 'right' : 'bottom'; + node.position = { + x: nodeWithPosition.x - nodeWidth / 2, + y: nodeWithPosition.y - nodeHeight / 2, + }; + + return node; + }); + + return { nodes, edges }; +}; \ No newline at end of file diff --git a/src/pages/chart/index.tsx b/src/pages/chart/index.tsx new file mode 100644 index 0000000..9b3ab69 --- /dev/null +++ b/src/pages/chart/index.tsx @@ -0,0 +1,84 @@ +import React, { useCallback, FC, useEffect, useState, useRef } from 'react'; +import ReactFlow, { + addEdge, + ConnectionLineType, + useNodesState, + useEdgesState, + Controls +} from 'react-flow-renderer'; +import { getLayoutedElements, flattenTree } from './data'; +import { Button, Form, Input, Modal, notification } from 'antd'; +import api from '@/api'; + +const InviteChart: FC = () => { + const [nodes, setNodes, onNodesChange] = useNodesState([]); + const [edges, setEdges, onEdgesChange] = useEdgesState([]); + const [form] = Form.useForm() + const buttonRef = useRef(null) + + // 获取节点 + const getNodes = async (email?: string) => { + const res: any = await api.user_relation({ email: email || '' }); + if (res.code === 0) { + let { nodes, edges } = flattenTree(res.data) // 处理节点及连接线 + let { nodes: layoutedNodes, edges: layoutedEdges } = getLayoutedElements(nodes, edges)//计算节点位置 + setNodes([...layoutedNodes]) + setEdges([...layoutedEdges]) + buttonRef.current.click() + }; + }; + + const onFinish = (values) => { + form.resetFields() + getNodes(values.email) + } + + const onLayout = useCallback( + (direction: any) => { + const { nodes: layoutedNodes, edges: layoutedEdges } = getLayoutedElements( + nodes, + edges, + direction + ); + + setNodes([...layoutedNodes]); + setEdges([...layoutedEdges]); + }, + [nodes, edges] + ); + + + useEffect(() => { + getNodes(); + }, []); + + return ( +
+ +
+ + + + + + +
+ +
+ + + +
+ +
+ ); +}; + +export default InviteChart; \ No newline at end of file diff --git a/src/route/routes.ts b/src/route/routes.ts index 88f4378..145b690 100644 --- a/src/route/routes.ts +++ b/src/route/routes.ts @@ -12,6 +12,7 @@ import SystemWithdraw from "@/pages/system/withdraw" import SystemNotify from "@/pages/system/notify" import SystemReceive from "@/pages/system/receive" import AccountReview from "@/pages/account-review" +import InviteChart from "@/pages/chart" const routes = [ { @@ -170,7 +171,15 @@ const routes = [ }, ] }, - + { + path: '/chart', + name: '仪表盘', + exact: true, + key: 'chart', + icon: HomeOutlined, + component: InviteChart, + routes: [] + }, ]