react引入ggEditor流程图

遇到的问题

1.propsAPI获取不到内容:withPropsAPI包裹的组件必须是GGEditor的子组件。

2.自定义组件如何使用:正确的办法是通过config配置,参照上面的代码(之前我在在内部RegisterCommand以后,在onAfterExecuteCommand中截获命令,通过函数控制图例操作。这中间需要下钻到内部组件调用propsAPI,我就通过setState去设置状态传递到子组件。)

3.如何设置拖拽组件:太羞耻了,居然不晓得在Item双标签内放名称。

4.操作流程图后获取数据延迟:如果获取数据有延迟,尝试使用setTimeout,时间间隔设为0后再调propsAPI属性的方法操作。

 

1. 两种不同颜色的线

用onAfterChange监听,然后用先的更新设置不同的颜色即可。

2. 节点和线的更新

import React, { Fragment } from 'react';
import { Card, Form, Input, Select } from 'antd';
import { withPropsAPI } from 'gg-editor';
import upperFirst from 'lodash/upperFirst';

const { Item } = Form;
const { Option } = Select;

const inlineFormItemLayout = {
  labelCol: {
    sm: { span: 8 },
  },
  wrapperCol: {
    sm: { span: 16 },
  },
};

class DetailForm extends React.Component {
  get item() {
    const { propsAPI } = this.props;

    return propsAPI.getSelected()[0];
  }

  handleSubmit = (e) => {
    if (e && e.preventDefault) {
      e.preventDefault();
    }

    const { form, propsAPI } = this.props;
    const { getSelected, executeCommand, update } = propsAPI;

    setTimeout(() => {
      form.validateFieldsAndScroll((err, values) => {
        if (err) {
          return;
        }

        const item = getSelected()[0];

        if (!item) {
          return;
        }
        console.log(item,values,'values')
        executeCommand(() => {
          update(item, {
            ...values,
          });
        });
      });
    }, 0);
  };

  renderEdgeShapeSelect = () => {
    return (
      <Select onChange={this.handleSubmit}>
        <Option value="flow-smooth">Smooth</Option>
        <Option value="flow-polyline">Polyline</Option>
        <Option value="flow-polyline-round">Polyline Round</Option>
      </Select>
    );
  };

  renderNodeDetail = () => {
    const { form } = this.props;
    const { label } = this.item.getModel();
    return (
      <Item label="Label" {...inlineFormItemLayout}>
        {form.getFieldDecorator('label', {
          initialValue: label.text ? label.text : label,
        })(<Input onBlur={this.handleSubmit} />)}
      </Item>
    );
  };

  renderEdgeDetail = () => {
    const { form } = this.props;
    const { label = '', shape = 'flow-smooth' } = this.item.getModel();

    return (
      <Fragment>
        <Item label="Label" {...inlineFormItemLayout}>
          {form.getFieldDecorator('label', {
            initialValue: label,
          })(<Input onBlur={this.handleSubmit} />)}
        </Item>
        <Item label="Shape" {...inlineFormItemLayout}>
          {form.getFieldDecorator('shape', {
            initialValue: shape,
          })(this.renderEdgeShapeSelect())}
        </Item>
      </Fragment>
    );
  };

  renderGroupDetail = () => {
    const { form } = this.props;
    const { label = '新建分组' } = this.item.getModel();

    return (
      <Item label="Label" {...inlineFormItemLayout}>
        {form.getFieldDecorator('label', {
          initialValue: label,
        })(<Input onBlur={this.handleSubmit} />)}
      </Item>
    );
  };

  render() {
    const { type } = this.props;

    if (!this.item) {
      return null;
    }

    return (
      <Card type="inner" size="small" title={upperFirst(type)} bordered={false}>
        <Form onSubmit={this.handleSubmit}>
          {type === 'node' && this.renderNodeDetail()}
          {type === 'edge' && this.renderEdgeDetail()}
          {type === 'group' && this.renderGroupDetail()}
        </Form>
      </Card>
    );
  }
}

export default Form.create()(withPropsAPI(DetailForm));

 

3. 提交数据

4. 自定义节点,注册节点

EditorCustomFlowMap组件

import React from 'react';
import { Col } from 'antd';
import { Flow } from 'gg-editor';
import { withPropsAPI } from 'gg-editor';
import CustomNode from '../EditorCustomNode';

const FlowMap = (props) => {return (
        <Col span={21} className='editorContent'>
              <Flow 
                className='flow' 
                data={props.data} // 已有节点那数据结构
                noEndEdge={false}/>
              <CustomNode />
        </Col>
      );
};

export default withPropsAPI(FlowMap);
CustomNode 组件,注册节点
import React from "react";
import { RegisterNode } from "gg-editor";

class CustomNode extends React.Component {
  render() {
    const config = {
      draw(item) {
        const keyShape = this.drawKeyShape(item);

        // 绘制图标
        const group = item.getGraphicGroup();
        const model = item.getModel();

        group.addShape("image", {
          attrs: {
            x: -35,
            y: -10,
            width: 20,
            height: 20,
            img: model.icon
          }
        });

        // 绘制标签
        this.drawLabel(item);

        return keyShape;
      },

      anchor: [
        [0.5, 0], // 上边中点
        [1, 0.5], // 右边中点
        [0.5, 1], // 底边中点
        [0, 0.5] // 左边中点
      ]
    };

    return (
      <RegisterNode name="custom-node" config={config} extend={"flow-circle"} />
    );
  }
}

export default CustomNode;

 

5.已有节点的数据结构

{
    "nodes": [
    {
      "id": "1",
      "flowType":"flow-circle", // 节点使用的形状
      "label":"开始",
      "x": 100, // 节点X轴坐标位置
      "y": 50,// 节点Y轴坐标位置
      "color":"blue", // 节点的颜色
      "size ": "80*48", // 节点的宽度和高度
      "shape ": "flow-rect"
    }
  ],
  "edges": [
    {
      "source":"1",
      "sourceAnchor": 1, 
      "target":"2",
      "targetAnchor": 3,
      "id": "d1",
    "color":"red" // 连线的颜色 } ] }

6.左侧待拖动的节点

这里的节点和flow图里面的节点样式控制不一样,这里的节点样式是靠css来控制。

flow图里面的节点样式,1,已有节点,靠的是已有节点的数据来控制,2,即将拖拽到flow区域的节点,是靠这里的Item属性来控制样式。

 1 import React from 'react';
 2 import { Card } from 'antd';
 3 import { ItemPanel, Item } from 'gg-editor';
 4 import './index.less'; 6 
 7 const FlowItemPanel = () => {
 8   return (
10     <ItemPanel className='itemPanel'>
11       <Card bordered={false}>        
12         <Item
13           type="node"
14           size="72*72"15           shape="custom-node" // 自定义注册节点名称
16           model={{
17             icon:'//img.alicdn.com/tfs/TB1OzAmyyLaK1RjSZFxXXamPFXa-200-200.svg',
18             color: '#FA8C16',
19             label:{
20               text:'流程',
21               fill: 'green'
22             },
23           }}
24         >
25           <div className="flow-node">流程</div>
26         </Item>
27         
28         <Item
29           type="node"
30           size="80*48"31           shape="flow-rect"
32           model={{
33             color: '#1890FF',
34             label:{
35               text:'文档',
36               fill: '#000'
37             },
38           }}
39         >
40           <div className="document-node">文档</div>
41         </Item>
42       </Card>
43     </ItemPanel>
44   );
45 };
46 
47 export default FlowItemPanel;
 1 .flow-node{
 2   border: 1px solid #fed49a;
 3   background-color: #fef6e7;
 4   border-radius: 50%;
 5   padding: 20px;
 6   color: green;
 7   -webkit-user-select: none; 
 8   -ms-user-select: none; /* Internet Explorer/Edge */
 9 }
10 
11 .document-node{
12   border-radius: 10%;
13   border: 1px solid #a7dafe;
14   background-color: #e7f6fe;
15   padding: 15px 20px;
16   -webkit-user-select: none; 
17   -ms-user-select: none; /* Internet Explorer/Edge */
18 }

7.操作栏的设置

import React from 'react';
import { Divider } from 'antd';
import { Toolbar } from 'gg-editor';
import ToolbarButton from './ToolbarButton';
import './index.less';

const FlowToolbar = () => {
  return (
    <Toolbar className='toolbar'>
      <ToolbarButton command="undo" text="回退一步" />
      <ToolbarButton command="redo" text="前进一步" />
      <Divider type="vertical" />
      <ToolbarButton command="copy" text="复制" />
      <ToolbarButton command="paste" text="粘贴" />
      <ToolbarButton command="delete" text="删除" />
      <Divider type="vertical" />
      <ToolbarButton command="zoomIn" icon="zoom-in" text="Zoom In" />
      <ToolbarButton command="zoomOut" icon="zoom-out" text="Zoom Out" />
      <ToolbarButton command="autoZoom" icon="fit-map" text="Fit Map" />
      <ToolbarButton command="resetZoom" icon="actual-size" text="Actual Size" />
      <Divider type="vertical" />
      <ToolbarButton command="toBack" icon="to-back" text="To Back" />
      <ToolbarButton command="toFront" icon="to-front" text="To Front" />
      <Divider type="vertical" />
      <ToolbarButton command="multiSelect" icon="multi-select" text="Multi Select" />
      <ToolbarButton command="addGroup" icon="group" text="Add Group" />
      <ToolbarButton command="unGroup" icon="ungroup" text="Ungroup" />
    </Toolbar>
  );
};

export default FlowToolbar;

 

8. 总

import React from 'react';
import { Row, Col } from 'antd';
import GGEditor from 'gg-editor';
import EditorMinimap from '../components/EditorMinimap';
import { FlowContextMenu } from '../components/EditorContextMenu';
import { FlowToolbar } from '../components/EditorToolbar';
import { FlowItemPanel } from '../components/EditorItemPanel';
import { FlowDetailPanel } from '../components/EditorDetailPanel';
import './index.less';
import EditorCustomDetailPanel from '../components/EditorCustomDetailPanel';
import EditorCustomFlowMap from '../components/EditorCustomFlowMap';
const flowData = {nodes:[],edges:[]};

const FlowPage = (props) => {return (
        <GGEditor  className='editor' style={{height:props.height}}>
          <Row type="flex" className='editorHd'>
            <Col span={24}>
              <FlowToolbar />
            </Col>
          </Row>
          <Row type="flex" className='editorBd'>
            <Col span={3} className='editorSidebar'>
              <FlowItemPanel />
            </Col>
            <EditorCustomFlowMap 
              data={flowData} 
              onNodeClick={props.handleNodeClick}
              onNodeDragEnd    ={props.handleNodeDragEnd}
              handleAfterChange={props.handleAfterChange}
            />
            <Col span={4} className='editorSidebar'>
              <FlowDetailPanel />
              <EditorMinimap />
            </Col></Row>
          <FlowContextMenu />
          <EditorCustomDetailPanel
            visibleDetailPanel={props.visibleDetailPanel}
            hideVisibleDetailPanel={props.hideVisibleDetailPanel}
            detailPanel={props.detailPanel}
            currentNode={props.currentNode}
            changeDetailPanel={props.changeDetailPanel}
            submitCurrentNode={props.submitCurrentNode}
          /> 
        </GGEditor>
      );
};

export default FlowPage;

 

posted @ 2020-02-25 10:35  芙蓉0504  阅读(3587)  评论(2编辑  收藏  举报