king
2022-11-18 f05ce61d55d421926229e50136c3b18c0dd9c262
2022-11-18
10个文件已修改
8个文件已添加
1685 ■■■■■ 已修改文件
src/assets/mobimg/indent.jfif 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/kapmap.jfif 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/mindmap.png 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-G6/chartcompile/index.jsx 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-G6/chartcompile/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-G6/index.jsx 1163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-G6/index.scss 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tree/antd-tree/options.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modulesource/option.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/tablenodes/index.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/tablenodes/index.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkColor/index.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/tablenodes/index.jsx 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/tablenodes/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/updatetable/index.jsx 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/indent.jfif
Binary files differ
src/assets/mobimg/kapmap.jfif
Binary files differ
src/assets/mobimg/mindmap.png
src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx
New file
@@ -0,0 +1,240 @@
/**
 * @description 获取图表视图配置表单
 * @param {object} card       // 图表对象
 */
export function getBaseForm (card) {
  let appType = sessionStorage.getItem('appType')
  let roleList = sessionStorage.getItem('sysRoles')
  if (roleList) {
    try {
      roleList = JSON.parse(roleList)
    } catch (e) {
      roleList = []
    }
  } else {
    roleList = []
  }
  return [
    {
      type: 'text',
      field: 'title',
      label: '标题',
      initval: card.title,
      required: false
    },
    {
      type: 'text',
      field: 'name',
      label: '组件名称',
      initval: card.name,
      tooltip: '用于组件间的区分。',
      required: true
    },
    {
      type: 'number',
      field: 'width',
      label: '宽度',
      initval: card.width,
      tooltip: '栅格布局,每行等分为24列。',
      min: 1,
      max: 24,
      decimal: 0,
      required: true
    },
    {
      type: 'styleInput',
      field: 'height',
      label: '图表高度',
      initval: card.height,
      tooltip: '图表绘图区域的高度,不包括标题及内外边距。',
      required: true,
      options: ['px', 'vh', 'vw']
    },
    {
      type: 'radio',
      field: 'permission',
      label: '权限验证',
      initval: card.permission || 'false',
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      forbid: !appType
    },
    {
      type: 'select',
      field: 'blacklist',
      label: '黑名单',
      initval: card.blacklist || [],
      multi: true,
      required: false,
      options: roleList,
      forbid: !!appType
    }
  ]
}
/**
 * @description 获取图表视图配置表单
 * @param {object} card       // 图表对象
 * @param {Array}  columns    // 显示列
 */
export function getOptionForm (card, columns) {
  return [
    {
      type: 'select',
      field: 'subtype',
      label: '类型',
      initval: card.subtype || 'mindmap',
      required: true,
      options: [{
        value: 'mindmap',
        label: '思维导图'
      }, {
        value: 'indentTree',
        label: '缩进文件树'
      }, {
        value: 'kapmap',
        label: '知识图谱树'
      }],
      controlFields: [
        {field: 'dirField', values: ['mindmap']},
        {field: 'nodeColor', values: ['mindmap']},
        {field: 'collapsed', values: ['indentTree']},
      ]
    },
    {
      type: 'radio',
      field: 'rootType',
      label: '根节点取值',
      initval: card.rootType || 'fixed',
      tooltip: '选择上级时,请填写根节点的文本和值的字段名',
      required: true,
      options: [{
        value: 'fixed',
        label: '固定值'
      }, {
        value: 'supvalue',
        label: '上级'
      }, {
        value: 'line',
        label: '行'
      }],
      controlFields: [
        {field: 'rootLabel', values: ['fixed', 'supvalue']},
        {field: 'rootValue', values: ['fixed', 'supvalue']},
        {field: 'mark', values: ['line']},
      ]
    },
    {
      type: 'text',
      field: 'rootLabel',
      label: '根节点文本',
      initval: card.rootLabel || '',
      required: true
    },
    {
      type: 'text',
      field: 'rootValue',
      label: '根节点值',
      initval: card.rootValue || '',
      required: true
    },
    {
      type: 'select',
      field: 'valueField',
      label: '值字段',
      initval: card.valueField || '',
      required: true,
      options: columns
    },
    {
      type: 'select',
      field: 'labelField',
      label: '文本字段',
      initval: card.labelField || '',
      required: true,
      options: columns
    },
    {
      type: 'select',
      field: 'parentField',
      label: '上级字段',
      initval: card.parentField || '',
      required: true,
      options: columns
    },
    {
      type: 'text',
      field: 'mark',
      label: '顶级标识',
      initval: card.mark || '',
      tooltip: '上级字段值与顶级标识相同时,视为根节点。',
      required: true
    },
    {
      type: 'select',
      field: 'dirField',
      label: '方向控制',
      initval: card.dirField || '',
      required: false,
      options: columns,
      controlFields: [
        {field: 'dirSign', notNull: true},
        {field: 'leftColor', notNull: true},
      ]
    },
    {
      type: 'text',
      field: 'dirSign',
      label: '左向标记',
      initval: card.dirSign || '',
      tooltip: '当节点值与标记相同时节点信息位于节点左侧,多个值请用逗号分隔。',
      required: false
    },
    {
      type: 'color',
      field: 'nodeColor',
      label: '节点颜色',
      initval: card.nodeColor || '#1890ff',
      tooltip: '右侧节点的标记颜色。',
      isHex: true,
      required: false
    },
    {
      type: 'color',
      field: 'leftColor',
      label: '左节点颜色',
      initval: card.leftColor || '#26C281',
      tooltip: '左侧节点的标记颜色。',
      isHex: true,
      required: false
    },
    {
      type: 'radio',
      field: 'empty',
      label: '空值隐藏',
      initval: card.empty || 'show',
      tooltip: '当查询数据为空时,隐藏该组件。',
      required: false,
      options: [
        {value: 'show', label: '否'},
        {value: 'hidden', label: '是'},
      ],
    },
    {
      type: 'radio',
      field: 'collapsed',
      label: '节点合并',
      initval: card.collapsed || 'false',
      tooltip: '一级节点是否合并。',
      required: false,
      options: [
        {value: 'false', label: '否'},
        {value: 'true', label: '是'},
      ],
    },
  ]
}
src/menu/components/chart/antv-G6/chartcompile/index.jsx
New file
@@ -0,0 +1,121 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Modal, Form, Tabs } from 'antd'
import { EditOutlined } from '@ant-design/icons'
import { getBaseForm, getOptionForm } from './formconfig'
import asyncComponent from '@/utils/asyncComponent'
import './index.scss'
const { TabPane } = Tabs
const NormalForm = asyncComponent(() => import('@/components/normalform/modalform'))
class LineChartDrawerForm extends Component {
  static propTpyes = {
    plot: PropTypes.object,
    config: PropTypes.object,
    plotchange: PropTypes.func
  }
  state = {
    view: 'normal',
    visible: false,
    plot: null,
    formlist: null,
    baseFormlist: null
  }
  showDrawer = () => {
    const { config } = this.props
    this.setState({
      visible: true,
      view: 'normal',
      plot: fromJS(config.plot).toJS(),
      baseFormlist: getBaseForm(config.plot),
      formlist: getOptionForm(config.plot, config.columns)
    })
  }
  onSubmit = () => {
    const { config } = this.props
    const { plot, view } = this.state
    if (view === 'normal') {
      this.norRef.handleConfirm().then(res => {
        let _plot = {...plot, ...res}
        this.setState({
          plot: _plot,
          visible: false
        })
        this.props.plotchange({...config, plot: _plot})
      })
    } else if (view === 'base') {
      this.baseRef.handleConfirm().then(res => {
        let _plot = {...plot, ...res}
        this.setState({
          plot: _plot,
          visible: false
        })
        this.props.plotchange({...config, plot: _plot})
      })
    }
  }
  changeTab = (tab) => {
    const { plot, view } = this.state
    if (view === 'normal') {
      this.norRef.handleConfirm().then(res => {
        this.setState({
          plot: {...plot, ...res},
          view: tab
        })
      })
    } else if (view === 'base') {
      this.baseRef.handleConfirm().then(res => {
        this.setState({
          plot: {...plot, ...res},
          view: tab
        })
      })
    }
  }
  render() {
    const { config } = this.props
    const { view, visible, baseFormlist, formlist } = this.state
    return (
      <div className="line-chart-drawer-form">
        <EditOutlined title="编辑" onClick={this.showDrawer} />
        <Modal
          wrapClassName="mk-pop-modal"
          visible={visible}
          width={850}
          maskClosable={false}
          onOk={this.onSubmit}
          onCancel={() => { this.setState({ visible: false }) }}
          destroyOnClose
        >
          {config.name ? <div className="mk-com-name">{config.name} - 编辑</div> : null}
          <Tabs activeKey={view} onChange={this.changeTab}>
            <TabPane tab="组件设置" key="base">
              <NormalForm formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/>
            </TabPane>
            <TabPane tab="图表设置" key="normal">
              <NormalForm formlist={formlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.norRef = inst}/>
            </TabPane>
          </Tabs>
        </Modal>
      </div>
    );
  }
}
export default Form.create()(LineChartDrawerForm)
src/menu/components/chart/antv-G6/chartcompile/index.scss
New file
@@ -0,0 +1,6 @@
.line-chart-drawer-form {
  display: inline-block;
  > .anticon-edit {
    color: #1890ff;
  }
}
src/menu/components/chart/antv-G6/index.jsx
New file
@@ -0,0 +1,1163 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover } from 'antd'
import { ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import G6 from '@antv/g6'
import MKEmitter from '@/utils/events.js'
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
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
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'
}
let systemColor = '#1890ff'
if (window.GLOB.style) {
  let type = window.GLOB.style.replace(/bg_black_style_|bg_white_style_/, '')
  systemColor = styles[type] || '#1890ff'
}
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-sub', {
    jsx: (cfg) => {
      const width = Util.getTextSize(cfg.label, 14)[0] + 24;
      return `
        <group>
          <rect style={{width: ${width}, height: 22, cursor: pointer}}>
            <text style={{ fontSize: 14, 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: 22, cursor: pointer }} />
        </group>
      `;
    },
    getAnchorPoints() {
      return [
        [0, 0.965],
        [1, 0.965],
      ];
    },
  },
  '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();
  },
})
const dataMapTransform = (data) => {
  const changeData = (d, level = 0, color) => {
    const data = { ...d }
    switch (level) {
      case 0:
        data.type = 'dice-mind-map-root';
        break;
      case 1:
        data.type = 'dice-mind-map-sub';
        break;
      default:
        data.type = 'dice-mind-map-leaf';
        break;
    }
    if (color) {
      data.color = color;
    }
    if (level === 1 && !d.direction) {
      data.direction = 'right'
    }
    if (d.children) {
      data.children = d.children.map((child) => changeData(child, level + 1, data.color));
    }
    return data;
  }
  return changeData(data);
}
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,绘制圆点在节点正下方
    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.65)';
    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']
        ],
        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();
          }
        }
      }
    }
  },
  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();
      }
      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)
      }
    })
    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)
      }
    })
  }
})
const COLORS = ['#5B8FF9', '#F6BD16', '#5AD8A6', '#945FB9', '#E86452', '#6DC8EC', '#FF99C3', '#1E9493', '#FF9845', '#5D7092']
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);
}
class antvG6Chart extends Component {
  static propTpyes = {
    card: PropTypes.object,
    updateConfig: PropTypes.func,
    deletecomponent: PropTypes.func,
  }
  state = {
    card: null,
    eventListener: null
  }
  UNSAFE_componentWillMount () {
    const { card } = this.props
    if (card.isNew) {
      let _plot = {
        width: card.width || 24,
        height: 400,
        subtype: card.subtype,
        name: card.name
      }
      let _card = {
        uuid: card.uuid,
        type: card.type,
        format: 'array',   // 组件属性 - 数据格式
        pageable: false,   // 组件属性 - 是否可分页
        switchable: false, // 组件属性 - 数据是否可切换
        width: _plot.width,
        name: _plot.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        style: {
          borderWidth: '1px', borderColor: 'rgb(217, 217, 217)',
          marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px'
        },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        columns: [],
        scripts: [],
        search: [],
        action: [],
        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) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    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)
    data.isRoot = true
    data.collapsed = false
    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.color = card.plot.nodeColor || '#1890ff'
        }
      })
    } else if (card.plot.subtype === 'indentTree') {
      data.children.forEach(item => {
        item.collapsed = card.plot.collapsed === 'true'
      })
    }
    return data
  }
  viewrender = () => {
    const { card } = this.state
    if (card.plot.subtype === 'mindmap') {
      this.ponitrender()
    } else if (card.plot.subtype === 'indentTree') {
      this.indentrender()
    }
  }
  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()
  }
  /**
   * @description 散点图
   */
  ponitrender = () => {
    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),
      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;
        },
      },
      defaultEdge: {
        type: 'cubic-horizontal',
        style: {
          lineWidth: 2,
        },
      },
      minZoom: 0.5,
      modes: {
        default: ['drag-canvas', 'zoom-canvas', 'dice-mindmap'],
      },
    });
    tree.data(dataMapTransform(data));
    tree.render()
  }
  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
    card.errors = []
    let columns = card.columns.map(c => c.field)
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
    } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
      card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
    } else if (!card.setting.primaryKey) {
      card.errors.push({ level: 0, detail: '未设置主键!'})
    } else if (!columns.includes(card.setting.primaryKey)) {
      card.errors.push({ level: 0, detail: '主键已失效!'})
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    if (card.errors.length === 0) {
      card.$tables = getTables(card)
    }
    if (!card.plot.valueField) {
      card.errors.push({ level: 0, detail: '图表信息尚未设置!'})
    }
    this.setState({
      card: card
    })
    this.props.updateConfig(card)
  }
  changeStyle = () => {
    const { card } = this.state
    MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear'], card.style, this.getStyle)
  }
  getStyle = (style) => {
    let _card = {...this.state.card, style}
    this.updateComponent(_card)
  }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
      e.stopPropagation()
      MKEmitter.emit('clickComponent', this.state.card.uuid, null, (style) => {
        let _card = {...this.state.card}
        _card.style = {..._card.style, ...style}
        this.updateComponent(_card)
      })
    }
  }
  render() {
    const { card } = this.state
    let _style = resetStyle(card.style)
    return (
      <div className="menu-scatter-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>
        } trigger="hover">
          <ToolOutlined/>
        </Popover>
        <NormalHeader config={card} updateComponent={this.updateComponent}/>
        <div className="canvas" id={card.uuid + 'canvas'} ref={ref => this.wrap = ref}></div>
        <div className="component-name">
          <div className="center">
            <div className="title">{card.name}</div>
            <div className="content">
              {card.errors && card.errors.map((err, index) => {
                if (err.level === 0) {
                  return <span key={index} className="error">{err.detail}</span>
                } else {
                  return <span key={index} className="waring">{err.detail};</span>
                }
              })}
            </div>
          </div>
        </div>
      </div>
    )
  }
}
export default antvG6Chart
src/menu/components/chart/antv-G6/index.scss
New file
@@ -0,0 +1,68 @@
.menu-scatter-chart-edit-box {
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  .canvas {
    margin: 0px;
    padding: 15px;
    letter-spacing: 0px;
  }
  .chart-header {
    position: relative;
    height: 45px;
    border-bottom: 1px solid #e8e8e8;
    overflow: hidden;
    padding-right: 35px;
    .chart-title {
      text-decoration: inherit;
      font-weight: inherit;
      font-style: inherit;
      float: left;
      line-height: 45px;
      margin-left: 10px;
      position: relative;
      z-index: 1;
    }
  }
  >.anticon-tool {
    position: absolute;
    right: 1px;
    top: 1px;
    z-index: 3;
    font-size: 16px;
    padding: 5px;
    cursor: pointer;
    color: rgba(0, 0, 0, 0.85);
    background: rgba(255, 255, 255, 0.55);
  }
  .model-menu-action-list {
    position: absolute;
    right: 0px;
    top: 30px;
    z-index: 4;
    font-size: 16px;
    .ant-row .anticon-plus {
      float: right;
    }
    .page-card {
      float: right;
    }
  }
  .normal-header + .canvas + .model-menu-action-list {
    top: 45px;
  }
}
.menu-scatter-chart-edit-box:hover {
  z-index: 1;
  box-shadow: 0px 0px 4px #1890ff;
}
src/menu/components/tree/antd-tree/options.jsx
@@ -34,16 +34,16 @@
    {
      type: 'select',
      field: 'valueField',
      label: 'Value',
      label: '值字段',
      initval: wrap.valueField || '',
      tooltip: '数据值字段。',
      tooltip: '数据值字段,节点ID值,唯一标识。',
      required: true,
      options: columns
    },
    {
      type: 'select',
      field: 'labelField',
      label: 'Label',
      label: '文本字段',
      initval: wrap.labelField || '',
      tooltip: '显示文字字段。',
      required: true,
@@ -52,9 +52,9 @@
    {
      type: 'select',
      field: 'parentField',
      label: 'Parent',
      label: '上级字段',
      initval: wrap.parentField || '',
      tooltip: '父级字段。',
      tooltip: '上级字段,用于组织数据的上下级关系。',
      required: true,
      options: columns
    },
@@ -63,7 +63,7 @@
      field: 'mark',
      label: '顶级标识',
      initval: wrap.mark || '',
      tooltip: '父级字段值与顶级标识相同时,视为顶级节点。',
      tooltip: '上级字段值与顶级标识相同时,视为顶级节点。',
      required: false
    },
    {
src/menu/menushell/card.jsx
@@ -29,6 +29,7 @@
const Timeline = asyncComponent(() => import('@/menu/components/timeline/normal-timeline'))
const Voucher = asyncComponent(() => import('@/menu/components/module/voucher'))
const Iframe = asyncComponent(() => import('@/menu/components/iframe'))
const AntvG6 = asyncComponent(() => import('@/menu/components/chart/antv-G6'))
const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
  const originalIndex = findCard(id).index
@@ -116,6 +117,8 @@
      return (<CustomChart card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'iframe') {
      return (<Iframe card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'antvG6') {
      return (<AntvG6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'module' && card.subtype === 'voucher') {
      return (<Voucher card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    }
src/menu/menushell/index.jsx
@@ -98,6 +98,7 @@
        tree: '树形列表',
        balcony: '浮动卡',
        timeline: '时间轴',
        antvG6: '树图',
        iframe: 'iframe',
        card: '卡片'
      }
src/menu/modulesource/option.jsx
@@ -27,6 +27,9 @@
import tree from '@/assets/mobimg/tree.png'
import timeline from '@/assets/mobimg/timeline.png'
import Iframe from '@/assets/img/newpage.jpg'
import mindmap from '@/assets/mobimg/mindmap.png'
import indent from '@/assets/mobimg/indent.jfif'
import kapmap from '@/assets/mobimg/kapmap.jfif'
// import Voucher from '@/assets/mobimg/voucher.jpg'
// 组件配置信息
@@ -57,6 +60,9 @@
  { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '仪表盘', width: 12 },
  { type: 'menu', url: ratioboard, component: 'dashboard', subtype: 'ratioboard', title: '占比图', width: 12 },
  { type: 'menu', url: scatter, component: 'scatter', subtype: 'scatter', title: '散点图', width: 24 },
  { type: 'menu', url: mindmap, component: 'antvG6', subtype: 'mindmap', title: '思维导图', width: 24 },
  { type: 'menu', url: indent, component: 'antvG6', subtype: 'indentTree', title: '缩进文件树', width: 24 },
  { type: 'menu', url: kapmap, component: 'antvG6', subtype: 'kapmap', title: '知识图谱树', width: 24 },
  { type: 'menu', url: chart, component: 'chart', subtype: 'custom', title: '自定义图表', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '富文本', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '自定义', width: 24 },
src/menu/tablenodes/index.jsx
@@ -334,6 +334,18 @@
      editNode(evt) {
        const item = evt.item;
        const model = item.get('model');
        // 选中节点
        this.graph.getNodes().forEach(node => {
          let _model = node.get('model')
          if (_model.fontcolor === '#1890ff') {
            _model.fontcolor = ''
            this.graph.updateItem(node, _model, false)
          }
        })
        model.fontcolor = '#1890ff'
        this.graph.updateItem(item, model, false)
        
        that.changeMenu(model)
      }
src/menu/tablenodes/index.scss
@@ -1,6 +1,6 @@
.view-table-modal {
  .ant-modal {
    top: 55px;
    top: 30px;
  }
  .ant-modal-body {
    padding: 20px 50px 20px;
@@ -11,7 +11,7 @@
  }
  .wrap {
    position: relative;
    height: calc(100vh - 200px);
    height: calc(100vh - 175px);
    margin: 10px 0px;
    overflow: hidden;
src/tabviews/zshare/mutilform/mkColor/index.jsx
@@ -29,9 +29,17 @@
  handleChange = (color) => {
    let _color = `rgba(${ color.rgb.r }, ${ color.rgb.g }, ${ color.rgb.b }, ${ color.rgb.a })`
    if (!this.props.config.isHex) {
    this.setState({ color: _color }, () => {
      this.props.onChange(_color)
    })
    } else {
      let _hex = color.hex === 'transparent' ? '#ffffff' : color.hex
      this.setState({ color: _hex }, () => {
        this.props.onChange(_hex)
      })
    }
  }
  componentWillUnmount () {
@@ -42,6 +50,7 @@
  render() {
    const { color } = this.state
    return (
      <div className="color-sketch-block">
        <Popover content={
src/tabviews/zshare/tablenodes/index.jsx
@@ -302,13 +302,6 @@
      },
      'single-node',
    );
    G6.registerBehavior('dice-mindmap', {
      getEvents() {
        return {
          'node:dblclick': 'editNode',
        };
      }
    });
    G6.registerBehavior('scroll-canvas', {
      getEvents: function getEvents() {
        return {
@@ -408,7 +401,7 @@
      },
      minZoom: 0.5,
      modes: {
        default: ['drag-canvas', 'zoom-canvas', 'dice-mindmap'],
        default: ['drag-canvas', 'zoom-canvas'],
      },
    });
    
src/tabviews/zshare/tablenodes/index.scss
@@ -11,7 +11,7 @@
.view-table-modal {
  .ant-modal {
    top: 55px;
    top: 30px;
  }
  .ant-modal-body {
    padding: 20px 50px 20px;
@@ -22,7 +22,7 @@
  }
  .wrap {
    position: relative;
    height: calc(100vh - 240px);
    height: calc(100vh - 175px);
    margin: 10px 0px;
    overflow: hidden;
@@ -52,6 +52,7 @@
    white-space: nowrap;
    .ant-typography {
      margin-bottom: 0px;
      color: #1890ff;
      display: inline-block;
      .ant-typography-copy {
src/templates/comtableconfig/updatetable/index.jsx
@@ -984,6 +984,15 @@
      delete _btn.position
      delete _btn.linkTab
      if (_btn.intertype === 'inner' && !_btn.innerFunc) {
        _btn.intertype = 'system'
      }
      if (_btn.funcType === 'print' && _btn.execMode) {
        _btn.OpenType = 'funcbutton'
      } else if (_btn.OpenType === 'blank') {
        _btn.OpenType = 'tab'
      }
      this.delButtons.push(btn.uuid)
      _btn.show = 'button'
@@ -1016,14 +1025,14 @@
        _btn.popClose = 'mainline'
      }
      if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.funcType === 'print' && btn.execMode === 'pop')) {
      if (_btn.OpenType === 'pop' || (_btn.OpenType === 'funcbutton' && _btn.funcType === 'print' && _btn.execMode === 'pop')) {
        formActions.push({origin: btn.uuid, uuid: _btn.uuid, name: newCon.name, label: btn.label})
      } else if (btn.OpenType === 'popview') {
      } else if (_btn.OpenType === 'popview') {
        if (!popActions) return
        popActions.push({origin: btn.uuid, linkTab: btn.linkTab || '', uuid: _btn.uuid, name: newCon.name, label: btn.label})
      } else if (btn.OpenType === 'tab') {
      } else if (_btn.OpenType === 'tab') {
        if (btn.tabTemplate === 'FormTab' || !btn.linkmenu || btn.linkmenu.length !== 3) {
          errors.push(newCon.name + '中按钮《' + btn.label + '》不在支持')
@@ -1074,8 +1083,14 @@
    _card.scripts = config.setting.scripts || []
    sets.forEach(n => {
      if (n === 'interType' && !['system', 'inner', 'outer'].includes(config.setting.interType)) {
      if (n === 'interType') {
        if (!['system', 'inner', 'outer'].includes(config.setting.interType)) {
        _card.setting.interType = 'system'
        } else if (config.setting.interType === 'inner' && !config.setting.innerFunc) {
          _card.setting.interType = 'system'
        } else {
          _card.setting.interType = config.setting.interType
        }
      } else if (typeof(n) === 'string') {
        _card.setting[n] = config.setting[n] || ''
      } else {
@@ -1090,7 +1105,8 @@
      }
    })
    if (config.setting.doubleClick && !uuids[config.setting.doubleClick]) {
    _card.wrap.doubleClick = config.setting.doubleClick || ''
    if (_card.wrap.doubleClick && !uuids[_card.wrap.doubleClick]) {
      _card.wrap.doubleClick = ''
    }