From 79e4981aa6cc9354276fc54cdf6d14eb08ab7fee Mon Sep 17 00:00:00 2001 From: king <18310653075@163.com> Date: 星期四, 22 六月 2023 15:59:04 +0800 Subject: [PATCH] Merge branch 'develop' of ssh://121.36.20.145:29418/~jinfei/pc-plat into develop --- src/menu/components/chart/antv-X6/index.jsx | 1813 ++++++++++++++++++--------------------------------------- 1 files changed, 576 insertions(+), 1,237 deletions(-) diff --git a/src/menu/components/chart/antv-X6/index.jsx b/src/menu/components/chart/antv-X6/index.jsx index 985a6f5..6d20b17 100644 --- a/src/menu/components/chart/antv-X6/index.jsx +++ b/src/menu/components/chart/antv-X6/index.jsx @@ -1,947 +1,246 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' -import { Popover, message } from 'antd' -import { ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons' -import G6 from '@antv/g6' +import { Popover, Tooltip, message } from 'antd' +import { ToolOutlined, DeleteOutlined, FontColorsOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined, SaveOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined, DoubleLeftOutlined } from '@ant-design/icons' +import { Graph, Shape } from '@antv/x6' +import { Stencil } from '@antv/x6-plugin-stencil' +import { Transform } from '@antv/x6-plugin-transform' +import { Selection } from '@antv/x6-plugin-selection' +import { Snapline } from '@antv/x6-plugin-snapline' +import { Keyboard } from '@antv/x6-plugin-keyboard' +import { Clipboard } from '@antv/x6-plugin-clipboard' +import { History } from '@antv/x6-plugin-history' import MKEmitter from '@/utils/events.js' import asyncComponent from '@/utils/asyncComponent' import asyncIconComponent from '@/utils/asyncIconComponent' -import { resetStyle, getTables, getHeight, checkComponent } from '@/utils/utils-custom.js' +import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js' import './index.scss' - -const { Util } = G6 const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) const ChartCompileForm = asyncIconComponent(() => import('./chartcompile')) +const NodeUpdate = asyncIconComponent(() => import('./nodeupdate')) const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) -const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) -const MindData = [ - 'Modeling Methods', - [ - 'Classification', - ['Logistic regression', 'Linear discriminant analysis', 'Rules', 'Decision trees', 'Naive Bayes', 'K nearest neighbor', 'Probabilistic neural network', 'Support vector machine'] - ], - [ - 'Consensus', - [ - 'Models diversity', - ['Different initializations', 'Different parameter choices', 'Different architectures', 'Different modeling methods', 'Different training sets', 'Different feature sets'] - ], - [ - 'Methods', - ['Classifier selection', 'Classifier fusion'] - ], - [ - 'Common', - ['Bagging', 'Boosting', 'AdaBoost'] - ] - ], - [ - 'Regression', - ['Multiple linear regression', 'Partial least squares', 'Multi-layer feedforward neural network', 'General regression neural network', 'Support vector regression'] - ] -] - -const styles = { - blue: '#1890ff', - red: '#f5222d', - orange_red: '#fa541c', - orange: '#fa8c16', - orange_yellow: '#faad14', - yellow: '#fadb14', - yellow_green: '#a0d911', - green: '#52c41a', - cyan: '#13c2c2', - blue_purple: '#2f54eb', - purple: '#722ed1', - magenta: '#eb2f96', - grass_green: '#aeb303', - deep_red: '#c32539', - deep_blue: '#1d3661' -} - -let systemColor = '#1890ff' -if (window.GLOB.style) { - let type = window.GLOB.style.replace(/bg_black_style_|bg_white_style_/, '') - systemColor = styles[type] || '#1890ff' -} -const COLORS = ['#5B8FF9', '#F6BD16', '#5AD8A6', '#945FB9', '#E86452', '#6DC8EC', '#FF99C3', '#1E9493', '#FF9845', '#5D7092'] - -// 鎬濈淮瀵煎浘 -G6.registerNode( - 'dice-mind-map-root', { - jsx: (cfg) => { - const width = Util.getTextSize(cfg.label, 16)[0] + 24 - - return ` - <group> - <rect style={{width: ${width}, height: 42, stroke: ${systemColor}, radius: 4}} keyshape> - <text style={{ fontSize: 16, marginLeft: 6, marginTop: 12 }}>${cfg.label}</text> - </rect> - </group> - ` - }, - getAnchorPoints() { - return [ - [0, 0.5], - [1, 0.5] - ] - } - }, - 'single-node', -) - -G6.registerNode( - 'dice-mind-map-leaf', { - jsx: (cfg) => { - const width = Util.getTextSize(cfg.label, 12)[0] + 24 - - return ` - <group> - <rect style={{width: ${width}, height: 26, fill: 'transparent', cursor: pointer }}> - <text style={{ fontSize: 12, fill: ${cfg.selected ? systemColor : '#000000'}, marginLeft: 12, marginTop: 6, cursor: pointer }}>${cfg.label}</text> - </rect> - <rect style={{ fill: ${cfg.color}, width: ${width}, height: 2, x: 0, y: 32, cursor: pointer }} /> - </group> - ` - }, - getAnchorPoints() { - return [ - [0, 0.965], - [1, 0.965] - ] - } - }, - 'single-node', -) -G6.registerBehavior('dice-mindmap', { - getEvents() { - return { - 'node:click': 'editNode', - 'canvas:click': 'onCanvasClick' - } - }, - editNode(evt) { - const item = evt.item - const model = item.get('model') - - this.graph.getNodes().forEach(node => { - let _model = node.get('model') - if (_model.selected) { - _model.selected = false - this.graph.updateItem(node, _model, false) - } - }) - - model.selected = true - this.graph.updateItem(item, model, false) - }, - onCanvasClick(e) { - this.graph.getNodes().forEach(node => { - let _model = node.get('model') - if (_model.selected) { - _model.selected = false - this.graph.updateItem(node, _model, false) - } - }) - } -}) -G6.registerBehavior('scroll-canvas', { - getEvents: function getEvents() { - return { - wheel: 'onWheel' - } - }, - onWheel: function onWheel(ev) { - const { graph } = this - if (!graph) { - return - } - if (ev.ctrlKey) { - const canvas = graph.get('canvas') - const point = canvas.getPointByClient(ev.clientX, ev.clientY) - let ratio = graph.getZoom() - if (ev.wheelDelta > 0) { - ratio += ratio * 0.05 - } else { - ratio *= ratio * 0.05 - } - graph.zoomTo(ratio, { - x: point.x, - y: point.y - }) - } else { - const x = ev.deltaX || ev.movementX - const y = ev.deltaY || ev.movementY || (-ev.wheelDelta * 125) / 3 - graph.translate(-x, -y) - } - ev.preventDefault() - } -}) - -// 缂╄繘鏂囦欢鏍� -G6.registerNode('indentedRoot', { - draw(model, group) { - const keyShape = group.addShape('rect', { - attrs: { - x: -46, - y: -16, - width: 92, - height: 32, - fill: systemColor, - radius: 2, - stroke: '#5B8FF9', - lineWidth: 0 - }, - name: 'key-shape' - }) - - const text = group.addShape('text', { - attrs: { - text: model.label || 'root', - fill: "#fff", - fontSize: 12, - x: 0, - y: 0, - textAlign: 'center', - textBaseline: 'middle' - }, - name: 'root-text-shape' - }) - const textBBox = text.getBBox() - const width = textBBox.width + 24 - const height = textBBox.height + 12 - keyShape.attr({ - x: -width / 2, - y: -height / 2, - width, - height - }) - - return keyShape - }, - getAnchorPoints() { - return [ - [0.5, 1] - ] - }, - update: undefined -}) - -G6.registerNode('indentedNode', { - addChildCount(group, tag, props) { - const { collapsed, branchColor, count } = props - let clickCircleY = 10 - // 瀛愮被鏁伴噺 icon锛岀粯鍒跺渾鐐瑰湪鑺傜偣姝d笅鏂� - if (tag) { - const childCountGroup = group.addGroup({ - name: 'child-count-group' - }) - childCountGroup.setMatrix([1, 0, 0, 0, 1, 0, 0, clickCircleY, 1]) - const countBackWidth = collapsed ? 26 : 12 - childCountGroup.addShape('rect', { - attrs: { - width: countBackWidth, - height: 12, - radius: 6, - stroke: branchColor, - lineWidth: 2, - fill: collapsed ? branchColor : '#fff', - x: -countBackWidth / 2, - y: -6, - cursor: 'pointer', - }, - name: 'child-count-rect-shape' - }) - const childCountText = childCountGroup.addShape('text', { - attrs: { - text: count, - fill: '#fff', - x: 0, - y: 0, - fontSize: 10, - textAlign: 'center', - textBaseline: 'middle', - cursor: 'pointer', - }, - name: 'child-count-text-shape' - }) - const childHoverIcon = childCountGroup.addShape('path', { - attrs: { - stroke: '#fff', - lineWidth: 1, - cursor: 'pointer', - path: [['M', -3, 2], ['L', 0, -2], ['L', 3, 2]] - }, - name: 'child-count-expand-icon', - capture: false - }) - childHoverIcon.hide() - - // 杩炴帴 count 鐨勭嚎娈� - const countLink = group.addShape('path', { - attrs: { - path: [['M', 0, 0], ['L', 0, 11]], - stroke: branchColor, - lineWidth: 2, - }, - name: 'count-link' - }) - countLink.toBack() - - if (collapsed) { - childCountGroup.show() - childCountText.show() - countLink.show() - } - else { - childCountGroup.hide() - childCountText.hide() - countLink.hide() - } - - clickCircleY += 16 - } - }, - addBottomLine(group, props) { - const { x, width, stroke, lineWidth } = props - return group.addShape('path', { - attrs: { - path: [ - ['M', x - 1, 0], - ['L', width, 0], - ], - stroke, - lineWidth, - }, - name: 'node-path-shape' - }) - }, - addName(group, props) { - const { label, x = 0, y, fill } = props - return group.addShape('text', { - attrs: { - text: label, - x, - y, - textAlign: 'start', - textBaseline: 'top', - fill, - fontSize: 14, - fontFamily: 'PingFangSC-Regular', - cursor: 'pointer', - }, - name: 'not-root-text-shape' - }) - }, - draw(model, group) { - const { collapsed, depth, label, children, selected } = model - // 鏄惁涓烘牴鑺傜偣 - const rootNode = depth === 0 - // 瀛愯妭鐐规暟閲� - const childCount = children ? children.length : 0 - - let width = 0 - const height = 24 - const x = 0 - const y = -height / 2 - const borderRadius = 4 - // 鍚嶇О鏂囨湰 - const text = this.addName(group, { label, x, y }) - - let textWidth = text.getBBox().width - width = textWidth + 20 - - const keyShapeAttrs = { - x, - y, - width, - height, - radius: borderRadius, - fill: undefined, - stroke: undefined, - } - - const keyShape = group.addShape('rect', { - attrs: keyShapeAttrs, - name: 'root-key-shape-rect-shape' - }) - - // 搴曢儴妯嚎 - const bottomLine = this.addBottomLine(group, { - stroke: model.branchColor || '#AAB7C4', - lineWidth: 3, - x, - width - }) - - let nameColor = 'rgba(0, 0, 0, 0.85)' - - if (selected) { - nameColor = systemColor - } - - // 鍚嶇О - text.attr({ - y: y - 12, - fill: nameColor - }) - text.toFront() - textWidth = text.getBBox().width - - if (bottomLine) bottomLine.toFront() - - this.addChildCount(group, childCount && !rootNode, { - collapsed, - branchColor: model.branchColor, - count: childCount ? `${childCount}` : undefined - }) - - const bbox = group.getBBox() - const backContainer = group.addShape('path', { - attrs: { - path: childCount ? [ - ['M', bbox.minX, bbox.minY], - ['L', bbox.maxX, bbox.minY], - ['L', bbox.maxX, bbox.maxY], - ['L', bbox.minX + 20, bbox.maxY], - ['L', bbox.minX + 20, bbox.maxY + 20], - ['L', bbox.minX, bbox.maxY + 20], - ['Z'] - ] : [ - ['M', bbox.minX, bbox.minY], - ['L', bbox.maxX, bbox.minY], - ['L', bbox.maxX, bbox.maxY], - ['L', bbox.minX, bbox.maxY], - ['Z'] - ], +// #region 鍒濆鍖栧浘褰� +const groups = { + top: { + position: 'top', + attrs: { + circle: { + r: 4, + magnet: true, + stroke: 'var(--mk-sys-color)', + strokeWidth: 1, fill: '#fff', - opacity: 0 - } - }) - backContainer.toBack() - return keyShape - } -}) - -G6.registerEdge('indentedEdge', { - afterDraw: (cfg, group) => { - const sourceNode = cfg.sourceNode && cfg.sourceNode.getModel() - const targetNode = cfg.targetNode && cfg.targetNode.getModel() - const color = sourceNode.branchColor || targetNode.branchColor || cfg.color || '#000' - - const keyShape = group.get('children')[0] - keyShape.attr({ - stroke: color, - lineWidth: 3 // branchThick - }) - group.toBack() - }, - getControlPoints: (cfg) => { - const startPoint = cfg.startPoint - const endPoint = cfg.endPoint - return [ - startPoint, - { - x: startPoint.x, - y: endPoint.y, - }, - endPoint - ] - }, - update: undefined -}, 'polyline') - -G6.registerBehavior('wheel-scroll', { - getDefaultCfg() { - return { - direction: 'y', - zoomKey: 'ctrl', - sensitivity: 3, - scalableRange: -64 - } - }, - getEvents() { - return { - wheel: 'onWheel' - } - }, - onWheel(ev) { - const graph = this.graph - let keyDown = ev[`${this.zoomKey}Key`] - if (this.zoomKey === 'control') keyDown = ev.ctrlKey - if (keyDown) { - const sensitivity = this.get('sensitivity') - const canvas = graph.get('canvas') - const point = canvas.getPointByClient(ev.clientX, ev.clientY) - let ratio = graph.getZoom() - if (ev.wheelDelta > 0) { - ratio *= (1 + 0.01 * sensitivity) - } else { - ratio *= (1 - 0.01 * sensitivity) - } - graph.zoomTo(ratio, { - x: point.x, - y: point.y - }) - graph.emit('wheelzoom', ev) - } else { - let dx = ev.deltaX || ev.movementX - let dy = ev.deltaY || ev.movementY - if (!dy && navigator.userAgent.indexOf('Firefox') > -1) dy = (-ev.wheelDelta * 125) / 3 - - const width = this.graph.get('width') - const height = this.graph.get('height') - const graphCanvasBBox = this.graph.get('group').getCanvasBBox() - - let expandWidth = this.scalableRange - let expandHeight = this.scalableRange - // 鑻� scalableRange 鏄� 0~1 鐨勫皬鏁帮紝鍒欎綔涓烘瘮渚嬭�冭檻 - if (expandWidth < 1 && expandWidth > -1) { - expandWidth = width * expandWidth - expandHeight = height * expandHeight - } - - const { minX, maxX, minY, maxY } = graphCanvasBBox - - if (dx > 0) { - if (maxX < -expandWidth) { - dx = 0 - } else if (maxX - dx < -expandWidth) { - dx = maxX + expandWidth - } - } else if (dx < 0) { - if (minX > width + expandWidth) { - dx = 0 - } else if (minX - dx > width + expandWidth) { - dx = minX - (width + expandWidth) - } - } - - if (dy > 0) { - if (maxY < -expandHeight) { - dy = 0 - } else if (maxY - dy < -expandHeight) { - dy = maxY + expandHeight - } - } else if (dy < 0) { - if (minY > height + expandHeight) { - dy = 0 - } else if (minY - dy > height + expandHeight) { - dy = minY - (height + expandHeight) - } - } - - if (this.get('direction') === 'x') { - dy = 0 - } else if (this.get('direction') === 'y') { - dx = 0 - } - - graph.translate(-dx, -dy) - } - ev.preventDefault() - } -}) -G6.registerBehavior('hover-node', { - getEvents() { - return { - 'node:mouseover': 'onNodeMouseOver', - 'node:mouseleave': 'onNodeMouseLeave', - 'node:mouseenter': 'onNodeMouseEnter' - } - }, - onNodeMouseEnter(ev) { - const { item } = ev - if (!item || item.get('destroyed')) return - item.toFront() - const model = item.getModel() - const { collapsed, depth } = model - const rootNode = depth === 0 || model.isRoot - const group = item.getContainer() - - if (rootNode) return - - // 鎺у埗瀛愯妭鐐逛釜鏁版爣璁� - if (!collapsed) { - const childCountGroup = group.find(e => e.get('name') === 'child-count-group') - if (childCountGroup) { - childCountGroup.show() - } - } - }, - onNodeMouseOver(ev) { - const shape = ev.target - - // tooltip鏄剧ず銆侀殣钘� - this.graph.emit('tooltip: show', ev) - - // expand 鐘舵�佷笅锛岃嫢 hover 鍒板瓙鑺傜偣涓暟鏍囪锛屽~鍏呰儗鏅�+鏄剧ず鏀惰捣 icon - const { item } = ev - const group = item.getContainer() - const model = item.getModel() - if (!model.collapsed) { - const childCountGroup = group.find(e => e.get('name') === 'child-count-group') - if (childCountGroup) { - childCountGroup.show() - const back = childCountGroup.find(e => e.get('name') === 'child-count-rect-shape') - const expandIcon = childCountGroup.find(e => e.get('name') === 'child-count-expand-icon') - const rootNode = model.depth === 0 || model.isRoot - const branchColor = rootNode ? '#576286' : model.branchColor - if (shape.get('parent').get('name') === 'child-count-group') { - if (back) { - back.attr('fill', branchColor || '#fff') - } - if (expandIcon) { - expandIcon.show() - } - } else { - if (back) { - back.attr('fill', '#fff') - } - if (expandIcon) { - expandIcon.hide() - } + style: { + visibility: 'hidden' } } } }, - onNodeMouseLeave(ev) { - const { item } = ev - const model = item.getModel() - const group = item.getContainer() - const { collapsed } = model - - if (!collapsed) { - const childCountGroup = group.find(e => e.get('name') === 'child-count-group') - if (childCountGroup) { - childCountGroup.hide() + right: { + position: 'right', + attrs: { + circle: { + r: 4, + magnet: true, + stroke: 'var(--mk-sys-color)', + strokeWidth: 1, + fill: '#fff', + style: { + visibility: 'hidden' + } } - - const iconsLinkPath = group.find(e => e.get('name') === 'icons-link-path') - if (iconsLinkPath) { - iconsLinkPath.hide() - } - } - - this.graph.emit('tooltip: hide', ev) - } -}) -G6.registerBehavior('click-node', { - getEvents() { - return { - 'node:click': 'onNodeClick', - 'canvas:click': 'onCanvasClick' } }, - onNodeClick(e) { - const { item, target } = e - const shape = target - const shapeName = shape.cfg.name - let model = item.getModel() - - // 鐐瑰嚮鏀惰捣/灞曞紑 icon - if (shapeName === 'child-count-rect-shape' || shapeName === 'child-count-text-shape') { - const updatedCollapsed = !model.collapsed - this.graph.updateItem(item, { collapsed: updatedCollapsed }) - this.graph.layout() - return - } - - // 閫変腑鑺傜偣 - this.graph.getNodes().forEach(node => { - let _model = node.get('model') - if (_model.selected) { - _model.selected = false - this.graph.updateItem(node, _model, false) + bottom: { + position: 'bottom', + attrs: { + circle: { + r: 4, + magnet: true, + stroke: 'var(--mk-sys-color)', + strokeWidth: 1, + fill: '#fff', + style: { + visibility: 'hidden' + } } - }) - - model.selected = true - this.graph.updateItem(item, model, false) - - return + } }, - onCanvasClick(e) { - this.graph.getNodes().forEach(node => { - let _model = node.get('model') - if (_model.selected) { - _model.selected = false - this.graph.updateItem(node, _model, false) + left: { + position: 'left', + attrs: { + circle: { + r: 4, + magnet: true, + stroke: 'var(--mk-sys-color)', + strokeWidth: 1, + fill: '#fff', + style: { + visibility: 'hidden' + } } - }) - } -}) -const dataIndTransform = (data) => { - const changeData = (d) => { - let data = { ...d } - - data.type = data.isRoot ? 'indentedRoot' : 'indentedNode' - - if (d.children) { - data.children = d.children.map((child) => changeData(child)) } - // 缁欏畾 branchColor 鍜� 0-2 灞傝妭鐐� depth - if (data.children && data.children.length) { - data.depth = 0 - data.children.forEach((subtree, i) => { - subtree.branchColor = COLORS[i % COLORS.length] - // dfs - let currentDepth = 1 - subtree.depth = currentDepth - Util.traverseTree(subtree, child => { - child.branchColor = COLORS[i % COLORS.length] - - if (!child.depth) { - child.depth = currentDepth + 1 - } - else currentDepth = subtree.depth - if (child.children) { - child.children.forEach(subChild => { - subChild.depth = child.depth + 1 - }) - } - - if (!data.isRoot) { - child.collapsed = data.collapsed || false - } - return true - }) - }) - } - - return data } - return changeData(data) } -// 鐭ヨ瘑鍥捐氨鏍� -G6.registerNode('treeNode', { - draw: (cfg, group) => { - const { label, selected, children, isRoot } = cfg - const rootNode = !!isRoot - const hasChildren = children && children.length !== 0 - - let width = 0 - const height = 28 - const x = 0 - const y = -height / 2 - - // 鍚嶇О鏂囨湰 - const text = group.addShape('text', { - attrs: { - text: label, - x: x * 2, - y, - textAlign: 'left', - textBaseline: 'top', - fontFamily: 'PingFangSC-Regular', +Graph.registerNode( + 'mk-rect', + { + inherit: 'rect', + width: 66, + height: 36, + attrs: { + body: { + strokeWidth: 1, + stroke: '#5F95FF', + fill: '#EFF4FF' }, - cursor: 'pointer', - name: 'name-text-shape', - }) - const textWidth = text.getBBox().width - width = textWidth + 20 - - width = width < 60 ? 60 : width - - if (!rootNode && hasChildren) { - width += 22 + text: { + fontSize: 12, + fill: '#262626' + } + }, + ports: { + groups, + items: [ + { group: 'top' }, + { group: 'right' }, + { group: 'bottom' }, + { group: 'left' } + ] } + }, + true +) - const keyShapeAttrs = { - x, - y, - width, - height, - radius: 4 - } - - const keyShape = group.addShape('rect', { - attrs: keyShapeAttrs, - name: 'root-key-shape-rect-shape' - }) - - if (!rootNode) { - // 搴曢儴妯嚎 - group.addShape('path', { - attrs: { - path: [ - ['M', x - 1, 0], - ['L', width, 0], - ], - stroke: '#AAB7C4', - lineWidth: 1, - }, - name: 'node-path-shape' - }) - } - - const mainX = x - 10 - const mainY = -height + 15 - - if (rootNode) { - group.addShape('rect', { - attrs: { - x: mainX, - y: mainY, - width: width + 12, - height, - radius: 14, - fill: systemColor, - cursor: 'pointer', - }, - name: 'main-shape' - }) - } - - let nameColor = 'rgba(0, 0, 0, 0.85)' - if (selected) { - nameColor = systemColor - } - - // 鍚嶇О - if (rootNode) { - group.addShape('text', { - attrs: { - text: label, - x: mainX + 18, - y: 1, - textAlign: 'left', - textBaseline: 'middle', - fill: '#ffffff', - fontSize: 12, - fontFamily: 'PingFangSC-Regular', - cursor: 'pointer', - }, - name: 'root-text-shape' - }) - } else { - group.addShape('text', { - attrs: { - text: label, - x: mainX + 6, - y: y - 5, - textAlign: 'start', - textBaseline: 'top', - fill: nameColor, - fontSize: 12, - fontFamily: 'PingFangSC-Regular', - cursor: 'pointer', - }, - name: 'not-root-text-shape' - }) - } - - // 瀛愮被鏁伴噺 - if (hasChildren && !rootNode) { - const childCountHeight = 12 - const childCountX = width - 22 - const childCountY = -childCountHeight / 2 - - group.addShape('rect', { - attrs: { - width: 22, - height: 12, - stroke: systemColor, - fill: '#fff', - x: childCountX, - y: childCountY, - radius: 6, - cursor: 'pointer', - }, - name: 'child-count-rect-shape', - }) - group.addShape('text', { - attrs: { - text: `${children.length}`, - fill: 'rgba(0, 0, 0, .65)', - x: childCountX + 11, - y: childCountY + 12, - fontSize: 10, - width: 22, - textAlign: 'center', - cursor: 'pointer', - }, - name: 'child-count-text-shape' - }) - } - - return keyShape - } -}) - -G6.registerEdge('smooth', { - draw(cfg, group) { - const { startPoint, endPoint } = cfg - const hgap = Math.abs(endPoint.x - startPoint.x) - - const path = [ - ['M', startPoint.x, startPoint.y], - [ - 'C', - startPoint.x + hgap / 4, - startPoint.y, - endPoint.x - hgap / 2, - endPoint.y, - endPoint.x, - endPoint.y, - ], - ] - - const shape = group.addShape('path', { - attrs: { - stroke: '#AAB7C4', - path, +Graph.registerNode( + 'mk-polygon', + { + inherit: 'polygon', + width: 66, + height: 36, + attrs: { + body: { + strokeWidth: 1, + stroke: '#5F95FF', + fill: '#EFF4FF' }, - name: 'smooth-path-shape', - }) - return shape - }, -}) - -G6.registerBehavior('click-item', { - getEvents() { - return { - 'node:click': 'onNodeClick', - 'canvas:click': 'onCanvasClick' + text: { + fontSize: 12, + fill: '#262626' + } + }, + ports: { + groups, + items: [ + { group: 'top' }, + { group: 'right' }, + { group: 'bottom' }, + { group: 'left' } + ] } }, - onNodeClick(e) { - const { item } = e - let model = item.getModel() + true +) - if (model.children) return - // 閫変腑鑺傜偣 - this.graph.getNodes().forEach(node => { - let _model = node.get('model') - if (_model.selected) { - _model.selected = false - this.graph.updateItem(node, _model, false) +Graph.registerNode( + 'mk-circle', + { + inherit: 'circle', + width: 36, + height: 36, + attrs: { + body: { + strokeWidth: 1, + stroke: '#5F95FF', + fill: '#EFF4FF' + }, + text: { + fontSize: 12, + fill: '#262626' } - }) - - model.selected = true - this.graph.updateItem(item, model, false) - - return + }, + ports: { + groups, + items: [ + { group: 'top' }, + { group: 'right' }, + { group: 'bottom' }, + { group: 'left' } + ] + } }, - onCanvasClick(e) { - this.graph.getNodes().forEach(node => { - let _model = node.get('model') - if (_model.selected) { - _model.selected = false - this.graph.updateItem(node, _model, false) - } - }) - } -}) + true +) -class antvG6Chart extends Component { +Graph.registerNode( + 'mk-ellipse', + { + inherit: 'ellipse', + width: 66, + height: 36, + attrs: { + body: { + strokeWidth: 1, + stroke: '#5F95FF', + fill: '#EFF4FF' + }, + text: { + fontSize: 12, + fill: '#262626' + } + }, + ports: { + groups, + items: [ + { group: 'top' }, + { group: 'right' }, + { group: 'bottom' }, + { group: 'left' } + ] + } + }, + true +) + +Graph.registerNode( + 'mk-star', + { + inherit: 'polygon', + width: 36, + height: 36, + points: '100,10 40,198 190,78 10,78 160,198', + attrs: { + body: { + fill: '#EFF4FF', + stroke: '#5F95FF', + strokeWidth: 1, + fillRule: 'nonzero' + }, + text: { + fontSize: 12, + fill: '#262626' + } + }, + ports: { + groups, + items: [ + { group: 'top' }, + { group: 'right' }, + { group: 'bottom' }, + { group: 'left' } + ] + } + }, + true +) + +class antvX6Chart extends Component { static propTpyes = { card: PropTypes.object, updateConfig: PropTypes.func, @@ -950,8 +249,14 @@ state = { card: null, - eventListener: null + eventListener: null, + toolunfold: true, + nodeunfold: true, + node: null } + + selectNode = null + mkGraph = null UNSAFE_componentWillMount () { const { card } = this.props @@ -986,32 +291,12 @@ plot: _plot, } - if (card.config) { - let config = fromJS(card.config).toJS() - - _card.plot = config.plot - _card.plot.name = card.name - _card.style = config.style - _card.headerStyle = config.headerStyle - - _card.setting = config.setting - _card.columns = config.columns - _card.scripts = config.scripts - } - this.updateComponent(_card) } else { this.setState({ card: fromJS(card).toJS() }) } - } - - componentDidMount () { - MKEmitter.addListener('tabsChange', this.handleTabsChange) - setTimeout(() => { - this.viewrender() - }, 1000) } shouldComponentUpdate (nextProps, nextState) { @@ -1025,326 +310,364 @@ this.setState = () => { return } - MKEmitter.removeListener('tabsChange', this.handleTabsChange) } - handleTabsChange = (parentId) => { - const { card } = this.state - - if (parentId.indexOf(card.uuid) > -1 || parentId === 'all') { - let _element = document.getElementById(card.uuid + 'canvas') - if (_element) { - _element.innerHTML = '' - } - - this.$timer && clearTimeout(this.$timer) - this.$timer = setTimeout(this.viewrender, 100) - } - } - - getdata = () => { - const { card } = this.state - - const setData = (list) => { - let item = { - label: list[0], - id: list[0], - children: [] - } - if (!list[1]) { - delete item.children - - return item - } else if (!Array.isArray(list[1])) { - return list.map(m => ({label: m, id: m})) - } - - for (let i = 1; i < list.length; i++) { - let cell = setData(list[i]) - - if (Array.isArray(cell)) { - item.children.push(...cell) - } else { - item.children.push(cell) - } - } - - return item - } - - let data = setData(MindData) - - if (card.plot.subtype === 'mindmap') { - if (card.plot.dirField) { - data.children[0].direction = 'left' - data.children[2].direction = 'left' - } - - data.children.forEach(item => { - if (item.direction === 'left') { - item.color = card.plot.leftColor || '#26C281' - } else { - item.direction = 'right' - item.color = card.plot.nodeColor || '#1890ff' - } - }) - - data.collapsed = false - data.type = 'dice-mind-map-root' - - const collapse = (item) => { - if (!item.children) return - - item.children.forEach(cell => { - cell.collapsed = card.plot.collapsed === 'true' - cell.direction = cell.direction || 'right' - cell.type = 'dice-mind-map-leaf' - cell.color = cell.color || item.color - collapse(cell) - }) - } - - collapse(data) - } else if (card.plot.subtype === 'indentTree') { - data.isRoot = true - data.collapsed = false - - data.children.forEach(item => { - item.collapsed = card.plot.collapsed === 'true' - }) - } else if (card.plot.subtype === 'kapmap') { - data.isRoot = true - data.collapsed = false - - if (card.plot.collapsed === 'true') { - const collapse = (item) => { - if (!item.children) return - - item.children.forEach(cell => { - cell.collapsed = true - collapse(cell) - }) - } - - collapse(data) - } - } - - return data + componentDidMount () { + setTimeout(() => { + this.viewrender() + }, 1000) } viewrender = () => { - const { card } = this.state + // const { card } = this.state - if (card.plot.subtype === 'mindmap') { - this.ponitrender() - } else if (card.plot.subtype === 'indentTree') { - this.indentrender() - } else if (card.plot.subtype === 'kapmap') { + // if (card.plot.subtype === 'mindmap') { + // this.ponitrender() + // } else if (card.plot.subtype === 'indentTree') { + // this.indentrender() + // } else if (card.plot.subtype === 'kapmap') { this.kapmaprender() - } + // } } kapmaprender = () => { const { card } = this.state - const plot = card.plot - const data = this.getdata() - const height = getHeight(plot.height) - const graph = new G6.TreeGraph({ - container: card.uuid + 'canvas', - width: this.wrap.scrollWidth - 30, - height: height, - modes: { - default: [ - { - type: 'collapse-expand', - }, - 'drag-canvas', - 'zoom-canvas', - 'click-item' - ], + // #region 鍒濆鍖栫敾甯� + const graph = new Graph({ + container: document.getElementById(card.uuid + 'container'), + // grid: { + // visible: true, + // type: 'doubleMesh', + // args: [ + // { + // color: '#eee', // 涓荤綉鏍肩嚎棰滆壊 + // thickness: 1 // 涓荤綉鏍肩嚎瀹藉害 + // }, + // { + // color: '#ddd', // 娆$綉鏍肩嚎棰滆壊 + // thickness: 1, // 娆$綉鏍肩嚎瀹藉害 + // factor: 4 // 涓绘缃戞牸绾块棿闅� + // } + // ] + // }, + scaling: { + min: 0.5, + max: 2 }, - defaultNode: { - type: 'treeNode', - anchorPoints: [ - [0, 0.5], - [1, 0.5], - ], + autoResize: true, + panning: true, + background: { + color: '#ffffff' }, - defaultEdge: { - type: 'smooth', + mousewheel: { + enabled: true, + zoomAtMousePosition: true, + modifiers: 'ctrl' }, - layout: { - type: 'compactBox', - direction: 'LR', - getId: function getId(d) { - return d.id + connecting: { + router: 'manhattan', + connector: { + name: 'rounded', + args: { + radius: 8 + } }, - getHeight: function getHeight() { - return 16 + anchor: 'center', + connectionPoint: 'anchor', + allowBlank: false, + snap: { + radius: 20 }, - getWidth: function getWidth(d) { - const labelWidth = G6.Util.getTextSize(d.label, 12)[0] - const width = 60 + labelWidth - return width + createEdge() { + return new Shape.Edge({ + attrs: { + line: { + stroke: '#A2B1C3', + strokeWidth: 2, + targetMarker: { + name: 'block', + width: 12, + height: 8 + } + } + }, + zIndex: 0 + }) }, - getVGap: function getVGap() { - return 15 - }, - getHGap: function getHGap() { - return 30 + validateConnection({ targetMagnet }) { + return !!targetMagnet + } + }, + highlighting: { + magnetAdsorbed: { + name: 'stroke', + args: { + attrs: { + fill: '#5F95FF', + stroke: '#5F95FF' + } + } } } }) - graph.data(data) - graph.render() - graph.fitView() + // #region 浣跨敤鎻掍欢 + graph + .use(new Transform({ + resizing: true, + rotating: true + })) + .use(new Selection()) + .use(new Snapline()) + .use(new Keyboard()) + .use(new Clipboard()) + .use(new History()) - if (plot.collapsed === 'true') { - graph.zoomTo(1, { x: 0, y: height / 2 }) + // #region 鍒濆鍖� stencil + const stencil = new Stencil({ + title: '娴佺▼鍥�', + target: graph, + stencilGraphWidth: 180, + stencilGraphHeight: 180, + groups: [ + { + title: '閫氱敤鑺傜偣', + name: 'group1' + }, + { + title: '鑷畾涔�', + name: 'group2', + graphHeight: 120, + layoutOptions: { + rowHeight: 70 + } + } + ], + layoutOptions: { + columns: 2, + columnWidth: 80, + rowHeight: 55 + } + }) + + document.getElementById(card.uuid + 'stencil').appendChild(stencil.container) + + // #region 蹇嵎閿笌浜嬩欢 + graph.bindKey(['meta+c', 'ctrl+c'], () => { + const cells = graph.getSelectedCells() + if (cells.length) { + graph.copy(cells) + } + return false + }) + graph.bindKey(['meta+x', 'ctrl+x'], () => { + const cells = graph.getSelectedCells() + if (cells.length) { + graph.cut(cells) + } + return false + }) + graph.bindKey(['meta+v', 'ctrl+v'], () => { + if (!graph.isClipboardEmpty()) { + graph.paste({ offset: 32 }) + } + return false + }) + + // undo redo + graph.bindKey(['meta+z', 'ctrl+z'], () => { + if (graph.canUndo()) { + graph.undo() + } + return false + }) + graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => { + if (graph.canRedo()) { + graph.redo() + } + return false + }) + + // 鍒犻櫎鍏冪礌 + graph.bindKey(['backspace', 'delete'], () => { + const cells = graph.getSelectedCells() + if (cells.length) { + graph.removeCells(cells) + this.selectNode = null + this.setState({node: null}) + } + }) + + // 鎺у埗杩炴帴妗╂樉绀�/闅愯棌 + const showPorts = (ports, show) => { + for (let i = 0, len = ports.length; i < len; i += 1) { + ports[i].style.visibility = show ? 'visible' : 'hidden' + } } + graph.on('node:mouseenter', () => { + const container = document.getElementById(card.uuid + 'container') + const ports = container.querySelectorAll('.x6-port-body') + showPorts(ports, true) + }) + graph.on('node:mouseleave', () => { + const container = document.getElementById(card.uuid + 'container') + const ports = container.querySelectorAll('.x6-port-body') + showPorts(ports, false) + }) + + graph.on('node:click', ({ e, x, y, node, view }) => { + this.selectNode = node + + this.setState({node: node.store.data}) + }) + graph.on('edge:click', ({ e, x, y, edge, view }) => { + this.selectNode = edge + + this.setState({node: edge.store.data}) + + graph.clearTransformWidgets() + }) + graph.on('blank:click', ({ e, x, y }) => { + this.selectNode = null + + this.setState({node: null}) + }) + + const r1 = graph.createNode({ + shape: 'mk-rect', + label: '寮�濮�', + attrs: { + body: { + rx: 20, + ry: 26 + } + } + }) + const r2 = graph.createNode({ + shape: 'mk-rect', + label: '杩囩▼' + }) + const r3 = graph.createNode({ + shape: 'mk-rect', + attrs: { + body: { + rx: 6, + ry: 6 + } + }, + label: '鍙�夎繃绋�' + }) + const r4 = graph.createNode({ + shape: 'mk-polygon', + attrs: { + body: { + refPoints: '0,10 10,0 20,10 10,20' + } + }, + label: '鍐崇瓥' + }) + const r5 = graph.createNode({ + shape: 'mk-polygon', + attrs: { + body: { + refPoints: '10,0 40,0 30,20 0,20' + } + }, + label: '鏁版嵁' + }) + const r6 = graph.createNode({ + shape: 'mk-circle', + label: '杩炴帴' + }) + + stencil.load([r1, r2, r3, r4, r5, r6], 'group1') + + const p1 = graph.createNode({ + shape: 'mk-ellipse', + label: 'ellipse' + }) + const p2 = graph.createNode({ + shape: 'mk-star', + label: '' + }) + + stencil.load([p1, p2], 'group2') + + this.mkGraph = graph + } + + setTop = () => { + if (!this.selectNode) { + message.warning('璇烽�夋嫨鑺傜偣锛�') + return + } + this.selectNode.toFront() } - indentrender = () => { - const { card } = this.state - const plot = card.plot - const data = this.getdata() - - const tree = new G6.TreeGraph({ - container: card.uuid + 'canvas', - width: this.wrap.scrollWidth - 30, - height: getHeight(plot.height), - layout: { - type: 'indented', - direction: 'LR', - isHorizontal: true, - indent: 40, - getHeight: (d) => { - if (d.isRoot) { - return 30 - } - if (d.collapsed && d.children && d.children.length) { - return 36 - } - return 22 - }, - getVGap: () => { - return 10 - }, - }, - defaultEdge: { - type: 'indentedEdge', - style: { - lineWidth: 2, - radius: 16 - } - }, - minZoom: 0.5, - modes: { - default: [ - 'drag-canvas', - 'wheel-scroll', - 'hover-node', - 'click-node' - ] - } - }) - - tree.on('afterrender', e => { - tree.getEdges().forEach(edge => { - const targetNode = edge.getTarget().getModel() - const color = targetNode.branchColor - tree.updateItem(edge, { color }) - }) - setTimeout(() => { - tree.moveTo(32, 32) - tree.zoomTo(0.7) - }, 16) - }) - - tree.data(dataIndTransform(data)) - - tree.render() + setBottom = () => { + if (!this.selectNode) { + message.warning('璇烽�夋嫨鑺傜偣锛�') + return + } + // let cells = this.mkGraph.getCells() + this.selectNode.toBack() } - /** - * @description 鏁g偣鍥� - */ - ponitrender = () => { - const { card } = this.state - const plot = card.plot - const data = this.getdata() - const width = this.wrap.scrollWidth - 30 - const height = getHeight(plot.height) - let modes = ['drag-canvas', 'zoom-canvas', 'dice-mindmap'] + // zoom() 鍙幏鍙栨垨鑰呰缃缉鏀炬瘮渚� + setZoomIn = () => { + this.mkGraph.zoom(0.1) + } - if (plot.collapsed === 'true') { - modes = [{ type: 'collapse-expand' },'drag-canvas', 'zoom-canvas', 'dice-mindmap'] - } + setZoomOut = () => { + this.mkGraph.zoom(-0.1) + } - const tree = new G6.TreeGraph({ - container: card.uuid + 'canvas', - width: width, - height: height, - fitView: true, - layout: { - type: 'mindmap', - direction: 'H', - getHeight: () => { - return 16 - }, - getWidth: (node) => { - return node.level === 0 ? - Util.getTextSize(node.label, 16)[0] + 12 : - Util.getTextSize(node.label, 12)[0] - }, - getVGap: () => { - return 10 - }, - getHGap: () => { - return 60 - }, - getSide: (node) => { - return node.data.direction + setZoomInt = () => { + this.mkGraph.zoomTo(1) + } + + save = () => { + // let nodes = this.mkGraph.toJSON() + } + + changeProps = (value, key) => { + const { node } = this.state + + if (node.shape === 'edge') { + if (key === 'title') { + this.selectNode.setLabels(value) + } else if (key === 'stroke') { + this.selectNode.attr('line/stroke', value) + } else if (key === 'strokeWidth') { + this.selectNode.attr('line/strokeWidth', value) + } else if (key === 'lineType') { + if (value === 'dash') { + this.selectNode.attr('line/strokeDasharray', 5) + } else { + this.selectNode.attr('line/strokeDasharray', 0) } - }, - defaultEdge: { - type: 'cubic-horizontal', - style: { - lineWidth: 2 - } - }, - minZoom: 0.5, - modes: { - default: modes + } else if (key === 'fontSize') { + this.selectNode.attr('text/fontSize', value) + } else if (key === 'fontFill') { + this.selectNode.attr('text/fill', value) } - }) - - tree.data(data) - - tree.render() - - if (plot.collapsed === 'true' && plot.dirField) { - tree.zoomTo(1, { x: width / 2, y: height / 2 }) - } else if (plot.collapsed === 'true') { - tree.zoomTo(1, { x: 0, y: height / 2 }) + } else { + if (key === 'title') { + this.selectNode.attr('text/text', value) + } else if (key === 'fill') { + this.selectNode.attr('body/fill', value) + } else if (key === 'stroke') { + this.selectNode.attr('body/stroke', value) + } else if (key === 'fontSize') { + this.selectNode.attr('text/fontSize', value) + } else if (key === 'fontFill') { + this.selectNode.attr('text/fill', value) + } } } updateComponent = (card) => { - if (this.state.card && (!is(fromJS(card.plot), fromJS(this.state.card.plot)) || !is(fromJS(card.style), fromJS(this.state.card.style)))) { - let _element = document.getElementById(card.uuid + 'canvas') - if (_element) { - _element.innerHTML = '' - } - this.$timer && clearTimeout(this.$timer) - this.$timer = setTimeout(() => { - this.viewrender() - }, 150) - } - card.width = card.plot.width card.name = card.plot.name card.subtype = card.plot.subtype @@ -1354,19 +677,6 @@ if (card.errors.length === 0) { card.$tables = getTables(card) - } - - if (!card.plot.valueField) { - card.errors.push({ level: 0, detail: '鍥捐〃淇℃伅灏氭湭璁剧疆锛�'}) - } else { - let columns = card.columns.map(c => c.field) - if (!columns.includes(card.plot.valueField)) { - card.errors.push({ level: 0, detail: '鍊煎瓧娈靛湪瀛楁闆嗕腑涓嶅瓨鍦�'}) - } else if (!columns.includes(card.plot.labelField)) { - card.errors.push({ level: 0, detail: '鏂囨湰瀛楁鍦ㄥ瓧娈甸泦涓笉瀛樺湪'}) - } else if (!columns.includes(card.plot.parentField)) { - card.errors.push({ level: 0, detail: '涓婄骇瀛楁鍦ㄥ瓧娈甸泦涓笉瀛樺湪'}) - } } this.setState({ @@ -1400,17 +710,16 @@ } render() { - const { card } = this.state + const { card, toolunfold, nodeunfold, node } = this.state let _style = resetStyle(card.style) return ( - <div className="menu-scatter-chart-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> + <div className="menu-x6-chart-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <ChartCompileForm config={card} plotchange={this.updateComponent}/> <CopyComponent type="antvG6" card={card}/> <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/> - <UserComponent config={card}/> <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)}/> <SettingComponent config={card} updateConfig={this.updateComponent}/> </div> @@ -1418,18 +727,48 @@ <ToolOutlined/> </Popover> <NormalHeader config={card} updateComponent={this.updateComponent}/> - <div className="canvas" style={{minHeight: card.plot.height}} id={card.uuid + 'canvas'} ref={ref => this.wrap = ref}></div> + <div className="mk-toolbar"> + <div className="left-tool"> + <Tooltip title="缃墠"> + <VerticalAlignTopOutlined onClick={this.setTop}/> + </Tooltip> + <Tooltip title="缃悗"> + <VerticalAlignBottomOutlined onClick={this.setBottom}/> + </Tooltip> + <Tooltip title="淇濆瓨"> + <SaveOutlined onClick={this.save}/> + </Tooltip> + </div> + <div className="right-tool"> + <Tooltip title="鏀惧ぇ"> + <ZoomInOutlined onClick={this.setZoomIn}/> + </Tooltip> + <Tooltip title="缂╁皬"> + <ZoomOutOutlined onClick={this.setZoomOut}/> + </Tooltip> + <Tooltip title="1:1"> + <OneToOneOutlined onClick={this.setZoomInt}/> + </Tooltip> + </div> + </div> + <div className="canvas" style={{width: '100%', minHeight: card.plot.height, height: card.plot.height}} id={card.uuid + 'canvas'}> + <div id={card.uuid + 'stencil'} className={'mk-stencil ' + (toolunfold ? '' : 'merge')}> + <div className="tool-control" onClick={() => this.setState({toolunfold: !toolunfold})}> + <DoubleLeftOutlined /> + </div> + </div> + <div id={card.uuid + 'container'} className="mk-container"></div> + <div className={'mk-node-edit ' + (nodeunfold ? '' : 'merge')}> + <div className="tool-control" onClick={() => this.setState({nodeunfold: !nodeunfold})}> + <DoubleLeftOutlined /> + </div> + <div className="header">璁剧疆</div> + {!node ? <div className="empty">鏈�変腑</div> : <NodeUpdate node={node} onChange={this.changeProps}/>} + </div> + </div> <div className="component-name"> <div className="center"> - <div className="title" onDoubleClick={() => { - let oInput = document.createElement('input') - oInput.value = 'anchor' + card.uuid - document.body.appendChild(oInput) - oInput.select() - document.execCommand('Copy') - document.body.removeChild(oInput) - message.success('澶嶅埗鎴愬姛銆�') - }}>{card.name}</div> + <div className="title">{card.name}</div> <div className="content"> {card.errors && card.errors.map((err, index) => { if (err.level === 0) { @@ -1446,4 +785,4 @@ } } -export default antvG6Chart \ No newline at end of file +export default antvX6Chart \ No newline at end of file -- Gitblit v1.8.0