| | |
| | | } |
| | | } |
| | | .ant-carousel { |
| | | height: 100%; |
| | | .slick-slider { |
| | | height: 100%; |
| | | } |
| | | .slick-dots li button { |
| | | background: #1890ff; |
| | | } |
| | |
| | | forbid: !appType |
| | | }, |
| | | { |
| | | type: 'select', |
| | | type: 'multiselect', |
| | | field: 'blacklist', |
| | | label: '黑名单', |
| | | initval: card.blacklist || [], |
| | | multi: true, |
| | | required: false, |
| | | options: roleList, |
| | | forbid: !!appType |
| | |
| | | controlFields: [ |
| | | {field: 'dirField', values: ['mindmap']}, |
| | | {field: 'nodeColor', values: ['mindmap']}, |
| | | {field: 'collapsed', values: ['indentTree']}, |
| | | {field: 'collapsed', values: ['indentTree', 'kapmap']}, |
| | | ] |
| | | }, |
| | | { |
| | |
| | | label: '固定值' |
| | | }, { |
| | | value: 'supvalue', |
| | | label: '上级' |
| | | label: '上级组件' |
| | | }, { |
| | | value: 'line', |
| | | label: '行' |
| | |
| | | }, |
| | | { |
| | | type: 'text', |
| | | field: 'rootLabel', |
| | | label: '根节点文本', |
| | | initval: card.rootLabel || '', |
| | | field: 'rootValue', |
| | | label: '根节点值', |
| | | initval: card.rootValue || '', |
| | | required: true |
| | | }, |
| | | { |
| | | type: 'text', |
| | | field: 'rootValue', |
| | | label: '根节点值', |
| | | initval: card.rootValue || '', |
| | | field: 'rootLabel', |
| | | label: '根节点文本', |
| | | initval: card.rootLabel || '', |
| | | required: true |
| | | }, |
| | | { |
| | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | import { resetStyle, getTables, getHeight } from '@/utils/utils-custom.js' |
| | | // import Utils from '@/utils/utils.js' |
| | | import './index.scss' |
| | | |
| | | const { Util } = G6 |
| | |
| | | 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; |
| | | const width = Util.getTextSize(cfg.label, 16)[0] + 24 |
| | | |
| | | return ` |
| | | <group> |
| | |
| | | <text style={{ fontSize: 16, marginLeft: 6, marginTop: 12 }}>${cfg.label}</text> |
| | | </rect> |
| | | </group> |
| | | `; |
| | | ` |
| | | }, |
| | | getAnchorPoints() { |
| | | return [ |
| | | [0, 0.5], |
| | | [1, 0.5], |
| | | ]; |
| | | }, |
| | | [1, 0.5] |
| | | ] |
| | | } |
| | | }, |
| | | 'single-node', |
| | | ); |
| | | ) |
| | | G6.registerNode( |
| | | 'dice-mind-map-sub', { |
| | | jsx: (cfg) => { |
| | | const width = Util.getTextSize(cfg.label, 14)[0] + 24; |
| | | const width = Util.getTextSize(cfg.label, 14)[0] + 24 |
| | | |
| | | return ` |
| | | <group> |
| | |
| | | </rect> |
| | | <rect style={{ fill: ${cfg.color}, width: ${width}, height: 2, x: 0, y: 22, cursor: pointer }} /> |
| | | </group> |
| | | `; |
| | | ` |
| | | }, |
| | | getAnchorPoints() { |
| | | return [ |
| | | [0, 0.965], |
| | | [1, 0.965], |
| | | ]; |
| | | }, |
| | | [1, 0.965] |
| | | ] |
| | | } |
| | | }, |
| | | 'single-node', |
| | | ); |
| | | ) |
| | | G6.registerNode( |
| | | 'dice-mind-map-leaf', { |
| | | jsx: (cfg) => { |
| | | const width = Util.getTextSize(cfg.label, 12)[0] + 24; |
| | | const width = Util.getTextSize(cfg.label, 12)[0] + 24 |
| | | |
| | | return ` |
| | | <group> |
| | |
| | | </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], |
| | | ]; |
| | | }, |
| | | [1, 0.965] |
| | | ] |
| | | } |
| | | }, |
| | | 'single-node', |
| | | ); |
| | | ) |
| | | G6.registerBehavior('dice-mindmap', { |
| | | getEvents() { |
| | | return { |
| | | 'node:click': 'editNode', |
| | | 'canvas:click': 'onCanvasClick' |
| | | }; |
| | | } |
| | | }, |
| | | editNode(evt) { |
| | | const item = evt.item |
| | |
| | | G6.registerBehavior('scroll-canvas', { |
| | | getEvents: function getEvents() { |
| | | return { |
| | | wheel: 'onWheel', |
| | | }; |
| | | wheel: 'onWheel' |
| | | } |
| | | }, |
| | | onWheel: function onWheel(ev) { |
| | | const { graph } = this; |
| | | const { graph } = this |
| | | if (!graph) { |
| | | return; |
| | | return |
| | | } |
| | | if (ev.ctrlKey) { |
| | | const canvas = graph.get('canvas'); |
| | | const point = canvas.getPointByClient(ev.clientX, ev.clientY); |
| | | let ratio = graph.getZoom(); |
| | | 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; |
| | | ratio += ratio * 0.05 |
| | | } else { |
| | | ratio *= ratio * 0.05; |
| | | ratio *= ratio * 0.05 |
| | | } |
| | | graph.zoomTo(ratio, { |
| | | x: point.x, |
| | | y: point.y, |
| | | }); |
| | | y: point.y |
| | | }) |
| | | } else { |
| | | const x = ev.deltaX || ev.movementX; |
| | | const y = ev.deltaY || ev.movementY || (-ev.wheelDelta * 125) / 3; |
| | | graph.translate(-x, -y); |
| | | const x = ev.deltaX || ev.movementX |
| | | const y = ev.deltaY || ev.movementY || (-ev.wheelDelta * 125) / 3 |
| | | graph.translate(-x, -y) |
| | | } |
| | | ev.preventDefault(); |
| | | }, |
| | | ev.preventDefault() |
| | | } |
| | | }) |
| | | |
| | | const dataMapTransform = (data) => { |
| | |
| | | |
| | | switch (level) { |
| | | case 0: |
| | | data.type = 'dice-mind-map-root'; |
| | | break; |
| | | data.type = 'dice-mind-map-root' |
| | | break |
| | | case 1: |
| | | data.type = 'dice-mind-map-sub'; |
| | | break; |
| | | data.type = 'dice-mind-map-sub' |
| | | break |
| | | default: |
| | | data.type = 'dice-mind-map-leaf'; |
| | | break; |
| | | data.type = 'dice-mind-map-leaf' |
| | | break |
| | | } |
| | | |
| | | if (color) { |
| | | data.color = color; |
| | | data.color = color |
| | | } |
| | | |
| | | if (level === 1 && !d.direction) { |
| | |
| | | } |
| | | |
| | | if (d.children) { |
| | | data.children = d.children.map((child) => changeData(child, level + 1, data.color)); |
| | | data.children = d.children.map((child) => changeData(child, level + 1, data.color)) |
| | | } |
| | | return data; |
| | | return data |
| | | } |
| | | return changeData(data); |
| | | return changeData(data) |
| | | } |
| | | |
| | | // 缩进文件树 |
| | | G6.registerNode('indentedRoot', { |
| | | draw(model, group) { |
| | | const keyShape = group.addShape('rect', { |
| | |
| | | textBaseline: 'middle' |
| | | }, |
| | | name: 'root-text-shape' |
| | | }); |
| | | const textBBox = text.getBBox(); |
| | | const width = textBBox.width + 24; |
| | | const height = textBBox.height + 12; |
| | | }) |
| | | const textBBox = text.getBBox() |
| | | const width = textBBox.width + 24 |
| | | const height = textBBox.height + 12 |
| | | keyShape.attr({ |
| | | x: -width / 2, |
| | | y: -height / 2, |
| | |
| | | height |
| | | }) |
| | | |
| | | return keyShape; |
| | | return keyShape |
| | | }, |
| | | getAnchorPoints() { |
| | | return [ |
| | | [0.5, 1], |
| | | ]; |
| | | [0.5, 1] |
| | | ] |
| | | }, |
| | | update: undefined |
| | | }); |
| | | }) |
| | | |
| | | G6.registerNode('indentedNode', { |
| | | addChildCount(group, tag, props) { |
| | | const { collapsed, branchColor, count } = props; |
| | | let clickCircleY = 10; |
| | | const { collapsed, branchColor, count } = props |
| | | let clickCircleY = 10 |
| | | // 子类数量 icon,绘制圆点在节点正下方 |
| | | 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; |
| | | const countBackWidth = collapsed ? 26 : 12 |
| | | childCountGroup.addShape('rect', { |
| | | attrs: { |
| | | width: countBackWidth, |
| | |
| | | y: -6, |
| | | cursor: 'pointer', |
| | | }, |
| | | name: 'child-count-rect-shape', |
| | | }); |
| | | name: 'child-count-rect-shape' |
| | | }) |
| | | const childCountText = childCountGroup.addShape('text', { |
| | | attrs: { |
| | | text: count, |
| | |
| | | textBaseline: 'middle', |
| | | cursor: 'pointer', |
| | | }, |
| | | name: 'child-count-text-shape', |
| | | }); |
| | | name: 'child-count-text-shape' |
| | | }) |
| | | const childHoverIcon = childCountGroup.addShape('path', { |
| | | attrs: { |
| | | stroke: '#fff', |
| | |
| | | }, |
| | | name: 'child-count-expand-icon', |
| | | capture: false |
| | | }); |
| | | childHoverIcon.hide(); |
| | | }) |
| | | childHoverIcon.hide() |
| | | |
| | | // 连接 count 的线段 |
| | | const countLink = group.addShape('path', { |
| | |
| | | lineWidth: 2, |
| | | }, |
| | | name: 'count-link' |
| | | }); |
| | | countLink.toBack(); |
| | | }) |
| | | countLink.toBack() |
| | | |
| | | if (collapsed) { |
| | | childCountGroup.show(); |
| | | childCountText.show(); |
| | | countLink.show(); |
| | | childCountGroup.show() |
| | | childCountText.show() |
| | | countLink.show() |
| | | } |
| | | else { |
| | | childCountGroup.hide(); |
| | | childCountText.hide(); |
| | | countLink.hide(); |
| | | childCountGroup.hide() |
| | | childCountText.hide() |
| | | countLink.hide() |
| | | } |
| | | |
| | | clickCircleY += 16; |
| | | clickCircleY += 16 |
| | | } |
| | | }, |
| | | addBottomLine(group, props) { |
| | | const { x, width, stroke, lineWidth } = props; |
| | | const { x, width, stroke, lineWidth } = props |
| | | return group.addShape('path', { |
| | | attrs: { |
| | | path: [ |
| | |
| | | stroke, |
| | | lineWidth, |
| | | }, |
| | | name: 'node-path-shape', |
| | | }); |
| | | name: 'node-path-shape' |
| | | }) |
| | | }, |
| | | addName(group, props) { |
| | | const { label, x = 0, y, fill } = props; |
| | | const { label, x = 0, y, fill } = props |
| | | return group.addShape('text', { |
| | | attrs: { |
| | | text: label, |
| | |
| | | cursor: 'pointer', |
| | | }, |
| | | name: 'not-root-text-shape' |
| | | }); |
| | | }) |
| | | }, |
| | | draw(model, group) { |
| | | const { collapsed, depth, label, children, selected } = model; |
| | | const { collapsed, depth, label, children, selected } = model |
| | | // 是否为根节点 |
| | | const rootNode = depth === 0; |
| | | const rootNode = depth === 0 |
| | | // 子节点数量 |
| | | const childCount = children ? children.length : 0; |
| | | const childCount = children ? children.length : 0 |
| | | |
| | | let width = 0; |
| | | const height = 24; |
| | | const x = 0; |
| | | const y = -height / 2; |
| | | const borderRadius = 4; |
| | | let width = 0 |
| | | const height = 24 |
| | | const x = 0 |
| | | const y = -height / 2 |
| | | const borderRadius = 4 |
| | | // 名称文本 |
| | | const text = this.addName(group, { label, x, y }); |
| | | const text = this.addName(group, { label, x, y }) |
| | | |
| | | let textWidth = text.getBBox().width; |
| | | width = textWidth + 20; |
| | | let textWidth = text.getBBox().width |
| | | width = textWidth + 20 |
| | | |
| | | const keyShapeAttrs = { |
| | | x, |
| | |
| | | radius: borderRadius, |
| | | fill: undefined, |
| | | stroke: undefined, |
| | | }; |
| | | } |
| | | |
| | | const keyShape = group.addShape('rect', { |
| | | attrs: keyShapeAttrs, |
| | | name: 'root-key-shape-rect-shape', |
| | | }); |
| | | name: 'root-key-shape-rect-shape' |
| | | }) |
| | | |
| | | // 底部横线 |
| | | const bottomLine = this.addBottomLine(group, { |
| | |
| | | lineWidth: 3, |
| | | x, |
| | | width |
| | | }); |
| | | }) |
| | | |
| | | let nameColor = 'rgba(0, 0, 0, 0.65)'; |
| | | 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; |
| | | }) |
| | | text.toFront() |
| | | textWidth = text.getBBox().width |
| | | |
| | | if (bottomLine) bottomLine.toFront(); |
| | | if (bottomLine) bottomLine.toFront() |
| | | |
| | | this.addChildCount(group, childCount && !rootNode, { |
| | | collapsed, |
| | | branchColor: model.branchColor, |
| | | count: childCount ? `${childCount}` : undefined, |
| | | }); |
| | | count: childCount ? `${childCount}` : undefined |
| | | }) |
| | | |
| | | const bbox = group.getBBox(); |
| | | const bbox = group.getBBox() |
| | | const backContainer = group.addShape('path', { |
| | | attrs: { |
| | | path: childCount ? [ |
| | |
| | | opacity: 0 |
| | | } |
| | | }) |
| | | backContainer.toBack(); |
| | | return keyShape; |
| | | 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 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]; |
| | | const keyShape = group.get('children')[0] |
| | | keyShape.attr({ |
| | | stroke: color, |
| | | lineWidth: 3 // branchThick |
| | | }); |
| | | group.toBack(); |
| | | }) |
| | | group.toBack() |
| | | }, |
| | | getControlPoints: (cfg) => { |
| | | const startPoint = cfg.startPoint; |
| | | const endPoint = cfg.endPoint; |
| | | const startPoint = cfg.startPoint |
| | | const endPoint = cfg.endPoint |
| | | return [ |
| | | startPoint, |
| | | { |
| | | x: startPoint.x, |
| | | y: endPoint.y, |
| | | }, |
| | | endPoint, |
| | | ]; |
| | | endPoint |
| | | ] |
| | | }, |
| | | update: undefined |
| | | }, 'polyline'); |
| | | }, 'polyline') |
| | | |
| | | G6.registerBehavior('wheel-scroll', { |
| | | getDefaultCfg() { |
| | |
| | | direction: 'y', |
| | | zoomKey: 'ctrl', |
| | | sensitivity: 3, |
| | | scalableRange: -64, |
| | | }; |
| | | scalableRange: -64 |
| | | } |
| | | }, |
| | | getEvents() { |
| | | return { |
| | | wheel: 'onWheel', |
| | | }; |
| | | wheel: 'onWheel' |
| | | } |
| | | }, |
| | | onWheel(ev) { |
| | | const graph = this.graph; |
| | | let keyDown = ev[`${this.zoomKey}Key`]; |
| | | if (this.zoomKey === 'control') keyDown = ev.ctrlKey; |
| | | 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(); |
| | | 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); |
| | | ratio *= (1 + 0.01 * sensitivity) |
| | | } else { |
| | | ratio *= (1 - 0.01 * sensitivity); |
| | | ratio *= (1 - 0.01 * sensitivity) |
| | | } |
| | | graph.zoomTo(ratio, { |
| | | x: point.x, |
| | | y: point.y, |
| | | }); |
| | | graph.emit('wheelzoom', ev); |
| | | y: point.y |
| | | }) |
| | | graph.emit('wheelzoom', ev) |
| | | } else { |
| | | let dx = ev.deltaX || ev.movementX; |
| | | let dy = ev.deltaY || ev.movementY; |
| | | 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(); |
| | | 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; |
| | | let expandWidth = this.scalableRange |
| | | let expandHeight = this.scalableRange |
| | | // 若 scalableRange 是 0~1 的小数,则作为比例考虑 |
| | | if (expandWidth < 1 && expandWidth > -1) { |
| | | expandWidth = width * expandWidth; |
| | | expandHeight = height * expandHeight; |
| | | expandWidth = width * expandWidth |
| | | expandHeight = height * expandHeight |
| | | } |
| | | |
| | | const { minX, maxX, minY, maxY } = graphCanvasBBox; |
| | | const { minX, maxX, minY, maxY } = graphCanvasBBox |
| | | |
| | | if (dx > 0) { |
| | | if (maxX < -expandWidth) { |
| | |
| | | } |
| | | |
| | | if (this.get('direction') === 'x') { |
| | | dy = 0; |
| | | dy = 0 |
| | | } else if (this.get('direction') === 'y') { |
| | | dx = 0; |
| | | dx = 0 |
| | | } |
| | | |
| | | graph.translate(-dx, -dy); |
| | | graph.translate(-dx, -dy) |
| | | } |
| | | ev.preventDefault(); |
| | | }, |
| | | }); |
| | | 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(); |
| | | 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 (rootNode) return |
| | | |
| | | // 控制子节点个数标记 |
| | | if (!collapsed) { |
| | | const childCountGroup = group.find(e => e.get('name') === 'child-count-group'); |
| | | const childCountGroup = group.find(e => e.get('name') === 'child-count-group') |
| | | if (childCountGroup) { |
| | | childCountGroup.show(); |
| | | childCountGroup.show() |
| | | } |
| | | } |
| | | }, |
| | | onNodeMouseOver(ev) { |
| | | const shape = ev.target; |
| | | const shape = ev.target |
| | | |
| | | // tooltip显示、隐藏 |
| | | this.graph.emit('tooltip: show', ev); |
| | | this.graph.emit('tooltip: show', ev) |
| | | |
| | | // expand 状态下,若 hover 到子节点个数标记,填充背景+显示收起 icon |
| | | const { item } = ev; |
| | | const group = item.getContainer(); |
| | | const model = item.getModel(); |
| | | 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'); |
| | | 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; |
| | | 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'); |
| | | back.attr('fill', branchColor || '#fff') |
| | | } |
| | | if (expandIcon) { |
| | | expandIcon.show(); |
| | | expandIcon.show() |
| | | } |
| | | } else { |
| | | if (back) { |
| | | back.attr('fill', '#fff'); |
| | | back.attr('fill', '#fff') |
| | | } |
| | | if (expandIcon) { |
| | | expandIcon.hide(); |
| | | expandIcon.hide() |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | onNodeMouseLeave(ev) { |
| | | const { item } = ev; |
| | | const model = item.getModel(); |
| | | const group = item.getContainer(); |
| | | const { collapsed } = model; |
| | | 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'); |
| | | const childCountGroup = group.find(e => e.get('name') === 'child-count-group') |
| | | if (childCountGroup) { |
| | | childCountGroup.hide(); |
| | | childCountGroup.hide() |
| | | } |
| | | |
| | | const iconsLinkPath = group.find(e => e.get('name') === 'icons-link-path'); |
| | | const iconsLinkPath = group.find(e => e.get('name') === 'icons-link-path') |
| | | if (iconsLinkPath) { |
| | | iconsLinkPath.hide(); |
| | | iconsLinkPath.hide() |
| | | } |
| | | } |
| | | |
| | | this.graph.emit('tooltip: hide', ev); |
| | | }, |
| | | }); |
| | | 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(); |
| | | 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; |
| | | const updatedCollapsed = !model.collapsed |
| | | this.graph.updateItem(item, { collapsed: updatedCollapsed }) |
| | | this.graph.layout() |
| | | return |
| | | } |
| | | |
| | | // 选中节点 |
| | |
| | | model.selected = true |
| | | this.graph.updateItem(item, model, false) |
| | | |
| | | return; |
| | | return |
| | | }, |
| | | onCanvasClick(e) { |
| | | this.graph.getNodes().forEach(node => { |
| | |
| | | }) |
| | | } |
| | | }) |
| | | const COLORS = ['#5B8FF9', '#F6BD16', '#5AD8A6', '#945FB9', '#E86452', '#6DC8EC', '#FF99C3', '#1E9493', '#FF9845', '#5D7092'] |
| | | const dataIndTransform = (data) => { |
| | | const changeData = (d) => { |
| | | let data = { ...d }; |
| | | let data = { ...d } |
| | | |
| | | data.type = data.isRoot ? 'indentedRoot' : 'indentedNode'; |
| | | data.type = data.isRoot ? 'indentedRoot' : 'indentedNode' |
| | | |
| | | if (d.children) { |
| | | data.children = d.children.map((child) => changeData(child)); |
| | | data.children = d.children.map((child) => changeData(child)) |
| | | } |
| | | // 给定 branchColor 和 0-2 层节点 depth |
| | | if (data.children && data.children.length) { |
| | | data.depth = 0; |
| | | data.depth = 0 |
| | | data.children.forEach((subtree, i) => { |
| | | subtree.branchColor = COLORS[i % COLORS.length]; |
| | | subtree.branchColor = COLORS[i % COLORS.length] |
| | | // dfs |
| | | let currentDepth = 1; |
| | | subtree.depth = currentDepth; |
| | | let currentDepth = 1 |
| | | subtree.depth = currentDepth |
| | | Util.traverseTree(subtree, child => { |
| | | child.branchColor = COLORS[i % COLORS.length]; |
| | | child.branchColor = COLORS[i % COLORS.length] |
| | | |
| | | if (!child.depth) { |
| | | child.depth = currentDepth + 1; |
| | | child.depth = currentDepth + 1 |
| | | } |
| | | else currentDepth = subtree.depth; |
| | | else currentDepth = subtree.depth |
| | | if (child.children) { |
| | | child.children.forEach(subChild => { |
| | | subChild.depth = child.depth + 1; |
| | | subChild.depth = child.depth + 1 |
| | | }) |
| | | } |
| | | |
| | | if (!data.isRoot) { |
| | | child.collapsed = data.collapsed || false |
| | | } |
| | | return true; |
| | | return true |
| | | }) |
| | | }); |
| | | }) |
| | | } |
| | | |
| | | return data; |
| | | }; |
| | | return changeData(data); |
| | | 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', |
| | | }, |
| | | cursor: 'pointer', |
| | | name: 'name-text-shape', |
| | | }) |
| | | const textWidth = text.getBBox().width |
| | | width = textWidth + 20 |
| | | |
| | | width = width < 60 ? 60 : width |
| | | |
| | | if (!rootNode && hasChildren) { |
| | | width += 22 |
| | | } |
| | | |
| | | 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, |
| | | }, |
| | | name: 'smooth-path-shape', |
| | | }) |
| | | return shape |
| | | }, |
| | | }) |
| | | |
| | | G6.registerBehavior('click-item', { |
| | | getEvents() { |
| | | return { |
| | | 'node:click': 'onNodeClick', |
| | | 'canvas:click': 'onCanvasClick' |
| | | } |
| | | }, |
| | | onNodeClick(e) { |
| | | const { item } = e |
| | | let model = item.getModel() |
| | | |
| | | 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) |
| | | } |
| | | }) |
| | | |
| | | 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) |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | class antvG6Chart extends Component { |
| | | static propTpyes = { |
| | |
| | | type: card.type, |
| | | format: 'array', // 组件属性 - 数据格式 |
| | | pageable: false, // 组件属性 - 是否可分页 |
| | | switchable: false, // 组件属性 - 数据是否可切换 |
| | | switchable: true, // 组件属性 - 数据是否可切换 |
| | | width: _plot.width, |
| | | name: _plot.name, |
| | | subtype: card.subtype, |
| | |
| | | } |
| | | |
| | | let data = setData(MindData) |
| | | data.isRoot = true |
| | | data.collapsed = false |
| | | |
| | | if (card.plot.subtype === 'mindmap') { |
| | | if (card.plot.dirField) { |
| | |
| | | } |
| | | }) |
| | | } 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 |
| | |
| | | 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 graph = new G6.TreeGraph({ |
| | | container: card.uuid + 'canvas', |
| | | width: this.wrap.scrollWidth - 30, |
| | | height: getHeight(plot.height), |
| | | modes: { |
| | | default: [ |
| | | { |
| | | type: 'collapse-expand', |
| | | }, |
| | | 'drag-canvas', |
| | | 'zoom-canvas', |
| | | 'click-item' |
| | | ], |
| | | }, |
| | | defaultNode: { |
| | | type: 'treeNode', |
| | | anchorPoints: [ |
| | | [0, 0.5], |
| | | [1, 0.5], |
| | | ], |
| | | }, |
| | | defaultEdge: { |
| | | type: 'smooth', |
| | | }, |
| | | layout: { |
| | | type: 'compactBox', |
| | | direction: 'LR', |
| | | getId: function getId(d) { |
| | | return d.id |
| | | }, |
| | | getHeight: function getHeight() { |
| | | return 16 |
| | | }, |
| | | getWidth: function getWidth(d) { |
| | | const labelWidth = G6.Util.getTextSize(d.label, 12)[0] |
| | | const width = 60 + labelWidth |
| | | return width |
| | | }, |
| | | getVGap: function getVGap() { |
| | | return 15 |
| | | }, |
| | | getHGap: function getHGap() { |
| | | return 30 |
| | | } |
| | | } |
| | | }) |
| | | |
| | | graph.data(data) |
| | | graph.render() |
| | | graph.fitView() |
| | | } |
| | | |
| | | indentrender = () => { |
| | |
| | | indent: 40, |
| | | getHeight: (d) => { |
| | | if (d.isRoot) { |
| | | return 30; |
| | | return 30 |
| | | } |
| | | if (d.collapsed && d.children && d.children.length) { |
| | | return 36; |
| | | return 36 |
| | | } |
| | | return 22; |
| | | return 22 |
| | | }, |
| | | getVGap: () => { |
| | | return 10; |
| | | return 10 |
| | | }, |
| | | }, |
| | | defaultEdge: { |
| | | type: 'indentedEdge', |
| | | style: { |
| | | lineWidth: 2, |
| | | radius: 16, |
| | | }, |
| | | radius: 16 |
| | | } |
| | | }, |
| | | minZoom: 0.5, |
| | | modes: { |
| | |
| | | '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 }); |
| | | }); |
| | | const targetNode = edge.getTarget().getModel() |
| | | const color = targetNode.branchColor |
| | | tree.updateItem(edge, { color }) |
| | | }) |
| | | setTimeout(() => { |
| | | tree.moveTo(32, 32); |
| | | tree.moveTo(32, 32) |
| | | tree.zoomTo(0.7) |
| | | }, 16); |
| | | }); |
| | | }, 16) |
| | | }) |
| | | |
| | | tree.data(dataIndTransform(data)); |
| | | tree.data(dataIndTransform(data)) |
| | | |
| | | tree.render() |
| | | } |
| | |
| | | type: 'mindmap', |
| | | direction: 'H', |
| | | getHeight: () => { |
| | | return 16; |
| | | return 16 |
| | | }, |
| | | getWidth: (node) => { |
| | | return node.level === 0 ? |
| | | Util.getTextSize(node.label, 16)[0] + 12 : |
| | | Util.getTextSize(node.label, 12)[0]; |
| | | Util.getTextSize(node.label, 12)[0] |
| | | }, |
| | | getVGap: () => { |
| | | return 10; |
| | | return 10 |
| | | }, |
| | | getHGap: () => { |
| | | return 60; |
| | | return 60 |
| | | }, |
| | | getSide: (node) => { |
| | | return node.data.direction; |
| | | }, |
| | | return node.data.direction |
| | | } |
| | | }, |
| | | defaultEdge: { |
| | | type: 'cubic-horizontal', |
| | | style: { |
| | | lineWidth: 2, |
| | | }, |
| | | lineWidth: 2 |
| | | } |
| | | }, |
| | | minZoom: 0.5, |
| | | modes: { |
| | | default: ['drag-canvas', 'zoom-canvas', 'dice-mindmap'], |
| | | }, |
| | | }); |
| | | default: ['drag-canvas', 'zoom-canvas', 'dice-mindmap'] |
| | | } |
| | | }) |
| | | |
| | | tree.data(dataMapTransform(data)); |
| | | tree.data(dataMapTransform(data)) |
| | | |
| | | tree.render() |
| | | } |
| | |
| | | key: 'click', |
| | | label: '点击事件', |
| | | initVal: card.click || '', |
| | | tooltip: '当绑定点击事件时,柱形图的切换功能将失效。', |
| | | required: false, |
| | | forbid: appType === 'mob' || card.chartType !== 'bar', |
| | | options: [ |
| | | {value: '', label: '无'}, |
| | | {value: '', label: '数据切换'}, |
| | | {value: 'menu', label: '菜单'}, |
| | | {value: 'menus', label: '菜单组'} |
| | | ] |
| | |
| | | required: true |
| | | }, |
| | | { |
| | | type: 'cascader', |
| | | key: 'syncComponent', |
| | | label: '刷新组件', |
| | | initVal: card.syncComponent || [], |
| | | tooltip: '执行成功后(或弹窗标签关闭时),需要同步刷新的组件。注:选择当前组件的上级组件无效,刷新上级组件请选择成功后“刷新上级组件 - 行”。', |
| | | required: false, |
| | | options: modules |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | key: 'pagination', |
| | | label: '分页', |
| | | initVal: card.pagination || 'false', |
| | | tooltip: '导出数据量较大时(1000+),可设置分页请求数据。', |
| | | required: false, |
| | | options: [{ |
| | | value: 'true', |
| | |
| | | text: '非必填' |
| | | }], |
| | | forbid: appType === 'mob' |
| | | }, |
| | | { |
| | | type: 'cascader', |
| | | key: 'syncComponent', |
| | | label: '刷新组件', |
| | | initVal: card.syncComponent || [], |
| | | tooltip: '执行成功后(或弹窗标签关闭时),需要同步刷新的组件。注:选择当前组件的上级组件无效,刷新上级组件请选择成功后“刷新上级组件 - 行”。', |
| | | required: false, |
| | | options: modules |
| | | }, |
| | | { |
| | | type: 'cascader', |
| | |
| | | required: true |
| | | }, |
| | | { |
| | | type: 'cascader', |
| | | key: 'syncComponent', |
| | | label: '刷新组件', |
| | | initVal: card.syncComponent || [], |
| | | tooltip: '执行成功后(或弹窗标签关闭时),需要同步刷新的组件。注:选择当前组件的上级组件无效,刷新上级组件请选择成功后“刷新上级组件 - 行”。', |
| | | required: false, |
| | | options: modules |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | key: 'pagination', |
| | | label: '分页', |
| | | initVal: card.pagination || 'false', |
| | | tooltip: '导出数据量较大时(1000+),可设置分页请求数据。', |
| | | required: false, |
| | | options: [{ |
| | | value: 'true', |
| | |
| | | value: 'false', |
| | | text: '非必填' |
| | | }] |
| | | }, |
| | | { |
| | | type: 'cascader', |
| | | key: 'syncComponent', |
| | | label: '刷新组件', |
| | | initVal: card.syncComponent || [], |
| | | tooltip: '执行成功后(或弹窗标签关闭时),需要同步刷新的组件。注:选择当前组件的上级组件无效,刷新上级组件请选择成功后“刷新上级组件 - 行”。', |
| | | required: false, |
| | | options: modules |
| | | }, |
| | | { |
| | | type: 'cascader', |
| | |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {/* 1、不分页且不存在上级模块 */} |
| | | {!['navbar', 'interface'].includes(config.type) && !['editable', 'basetable'].includes(config.subtype) && (!config.pageable || (config.pageable && setting.laypage === 'false')) && (setting.supModule.length === 0 || setting.supModule[0] === 'empty') ? <Col span={8}> |
| | | {!['navbar', 'interface'].includes(config.type) && !['editable', 'basetable'].includes(config.subtype) && (!config.pageable || (config.pageable && setting.laypage === 'false')) && (setting.supModule.length === 0 || setting.supModule[0] === 'empty') && setting.interType === 'system' ? <Col span={8}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title={'初始化加载时,是否与其他组件一同加载数据,注:仅在使用系统函数,且初始化加载数据时有效,分页请求时无效。'}> |
| | | <QuestionCircleOutlined className="mk-form-tip" /> |
| | |
| | | chart.on('element:click', (ev) => { |
| | | let data = ev.data.data |
| | | |
| | | MKEmitter.emit('resetSelectLine', config.uuid, (data ? data.$$uuid : ''), data) |
| | | |
| | | if (plot.click === 'menus') { |
| | | let menu = null |
| | | |
| | |
| | | } else { |
| | | MKEmitter.emit('modifyTabs', newtab, 'plus', true) |
| | | } |
| | | } else if (plot.click === 'menu' && plot.MenuID) { |
| | | let menu = { |
| | | MenuID: plot.MenuID, |
| | | MenuName: plot.MenuName, |
| | | MenuNo: plot.MenuNo, |
| | | type: plot.tabType |
| | | } else if (plot.click === 'menu') { |
| | | let menuId = plot.menu.slice(-1)[0] |
| | | let newtab = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0] |
| | | |
| | | if (!newtab && plot.MenuID) { |
| | | newtab = { |
| | | MenuID: plot.MenuID, |
| | | MenuName: plot.MenuName, |
| | | MenuNo: plot.MenuNo, |
| | | type: plot.tabType |
| | | } |
| | | } else if (!newtab) { |
| | | return |
| | | } |
| | | |
| | | let newtab = { |
| | | ...menu, |
| | | newtab = { |
| | | ...newtab, |
| | | param: {} |
| | | } |
| | | |
| | |
| | | } else { |
| | | MKEmitter.emit('modifyTabs', newtab, 'plus', true) |
| | | } |
| | | } else { |
| | | MKEmitter.emit('resetSelectLine', config.uuid, (data ? data.$$uuid : ''), data) |
| | | } |
| | | }) |
| | | |