@rasir/x6-arch
TypeScript icon, indicating that this package has built-in type declarations

1.2.10 • Public • Published

AUTH

作者:rasir 源码地址 文档地址

前言

这是一款基于antv/x6的用于系统架构设计可视化的一款工具。

效果图

效果图

快速上手

说明

本组件是在react框架下的前端组件,推荐react@16.8以上版本。推荐使用umijs@3.x脚手架。其他必要依赖见下文。

目前,作品还有很多需要完善的地方,有些兼容没有处理,推荐使用 mac + 谷歌最新浏览器。这样能体验到更好的滚动效果。

安装方式

通过 npm 安装 npm i @rasir/x6-arch -S

必要依赖

  "dependencies": {
    "@antv/x6": "^1.33.1",
    "ahooks": "^3.7.0"
  },
  "peerDependencies": {
    "antd": ">=4.x",
    "react": ">=16.14.0",
    "react-dom": ">=16.14.0"
  },

使用方式

import React from 'react';
import ReactDOM from 'react-dom';
// 自定义的节点配置组件
import AppModule from './AppModule';
import moduleConfig from './moduleConfig';
import Arch from '../src';
import registerList from './register';
import 'antd/dist/antd.css';
import './index.less';

import appIcon from './icon/app.png';
....
import bmsIcon from './icon/bms.png';

const data = {
  "lanes": [
    { "id": "user", "name": "用户层", "height": 120 },
    { "id": "access", "name": "接入层", "height": 150 },
    { "id": "app", "name": "应用逻辑层", "height": 200 },
    { "id": "store", "name": "存储层", "height": 150 }
  ],
  "nodes": [
    {
      "id": "1",
      "x": 100,
      "y": 180,
      "name": "ARCH-VIEW-DUBBO-K8S-SIT",
      "moduleType": "bmr",
      "preId": "access"
    },
    {
      "id": "2",
      "x": 100,
      "y": 380,
      "name": "ARCH-VIEW-DUBBO-K8S-SIT",
      "moduleType": "tidb",
      "preId": "app"
    },
    {
      "id": "3",
      "x": 300,
      "y": 380,
      "name": "ARCH-VIEW-DUBBO-K8S-SIT",
      "moduleType": "browser",
      "preId": "app"
    },
    {
      "id": "4",
      "x": 300,
      "y": 30,
      "name": "ARCH-VIEW-DUBBO-K8S-SIT",
      "moduleType": "app",
      "preId": "user"
    },
    {
      "moduleType": "jetty",
      "name": "ceshi2222",
      "x": 450,
      "y": 380,
      "preId": "app",
      "id": "1flj7sg14",
      "label": "Jetty",
      "icon": "jetty",
      "value": "jetty",
      "type": "node",
      "image": "jettyModule",
      "bgImage": "innerSystem"
    },
    {
      "moduleType": "jetty",
      "name": "ceshi11111",
      "x": 600,
      "y": 380,
      "preId": "app",
      "id": "1flj7sg1422",
      "label": "Jetty",
      "icon": "jetty",
      "value": "jetty",
      "type": "node",
      "image": "jettyModule",
      "bgImage": "innerSystem"
    },
  ],
  "links": [{ "source": "1", "target": "2" }]
}
const config: ModuleConfig = {
  search: {
    placeholder: '请输入组件名称',
  },
  options: [
    {
      label: '用户层组件',
      value: 'userLayer',
      children: [
        {
          label: 'USER',
          icon: 'user',
          moduleType: 'user',
          moduleImage: 'user',
          value: 'user',
          target: ['user'],
          moduleProp: () =>
            [
              {
                type: 'INPUT',
                label: '用户名称',
                name: 'name',
                inputProps: {
                  allowClear: true,
                  placeholder: '请输入用户名称',
                  className: 'search-input',
                },
                rules: [
                  {
                    required: true,
                    message: '请选择使用时长',
                  },
                ],
              },
            ] as ModuleFormItem[],
        },
        {
          label: 'APP',
          icon: 'app',
          value: 'app',
          moduleProp: (data, form) =>
          (<AppModule form={form} data={data} />),
        },
      ],
    },
    {
      label: '云主机',
      value: 'clound',
      children: [
        {
          label: 'Jetty',
          icon: 'jetty',
          value: 'jetty',
          moduleProp: [],
        },
        {
          label: 'Nginx',
          icon: 'nginx',
          value: 'nginx',
          moduleProp: [],
        },
        {
          label: 'Other',
          icon: 'other',
          value: 'other',
          moduleProp: [],
        },
      ],
    },
    {
      label: '裸金属',
      value: 'mate',
      children: [
        {
          label: 'BMS',
          icon: 'bms',
          value: 'bms',
          moduleProp: [],
        },
      ],
    },
    {
      label: 'K8S容器',
      value: 'k8s',
      children: [
        {
          label: 'Dubbo',
          icon: 'dubbo',
          value: 'dubbo',
          moduleProp: [],
        },
        {
          label: 'SpringBoot',
          icon: 'springboot',
          value: 'springboot',
          moduleProp: [],
        },
        {
          label: 'NODEJS',
          icon: 'nodejs',
          value: 'nodejs',
          moduleProp: [],
        },
        {
          label: 'PYTHON',
          icon: 'python',
          value: 'python',
          moduleProp: [],
        },
        {
          label: 'Jetty',
          icon: 'jetty',
          value: 'jetty',
          moduleProp: [],
        },
        {
          label: 'Nginx',
          icon: 'nginx',
          value: 'nginx',
          moduleProp: [],
        },
      ],
    },
    {
      label: '中间件',
      value: 'middelwear',
      children: [
        {
          label: 'Redis',
          icon: 'redis',
          value: 'redis',
          moduleProp: [],
        },
        {
          label: 'Kafka',
          icon: 'kafka',
          value: 'kafka',
          moduleProp: [],
        },
        {
          label: 'Zookeeper',
          icon: 'zookeeper',
          value: 'zookeeper',
          moduleProp: [],
        },
      ],
    },
    {
      label: '数据库',
      value: 'database',
      children: [
        {
          label: 'MySQL',
          icon: 'mysql',
          value: 'mysql',
          moduleProp: [],
        },
      ],
    },
  ],
};
const assets = {
    appIcon,
    bmsIcon,
    ....
}

const App = () => {
  const onCreateNode = (nodeData) => {
    const { name } = nodeData;
    return Promise.resolve({
      id: '100',
      name,
      moduleType: 'user',
      systemType: 'inner',
      preId: 'user',
      shape: 'arch-node',
    });
  };
  return (
    <Arch
      data={data}
      moduleConfig={moduleConfig}
      assets={assets}
      appendActions={<div>hello</div>}
      registerList={registerList}
      defaultNodeShape="arch-node"
      onCreateNode={onCreateNode}
      cache={false}
    />
  );
};

ReactDOM.render(<App />, document.getElementById('root'));

自定义抽屉中的内容

import { Form, Input } from 'antd';
import { FormInstance } from 'antd/es/form/Form';
import React, { useEffect } from 'react';

interface AppModuleProps {
  data?: any;
  form: FormInstance;
  [key: string]: any;
}

const { Item: FormItem } = Form;

const AppModule: React.FC<AppModuleProps> = function (props) {
  const { form, data } = props;

  useEffect(() => {
    if (data) {
      form?.setFieldsValue(data);
    } else {
      form?.resetFields();
    }
  }, [data]);

  return (
    <Form form={form}>
      <FormItem
        name="name"
        label="APP名称"
        rules={[
          {
            required: true,
            message: '请填写app名称',
          },
        ]}
      >
        <Input placeholder="请填写app名称"></Input>
      </FormItem>
    </Form>
  );
};

export default AppModule;

注意

iconfont 不再需要另外引入

功能说明

  • 生成节点,拖拽左侧组件到右侧,会有弹窗让用户填写相关信息然后生成节点。
  • 调整节点尺寸,单击节点,出现工具端口,拖动端口调整节点尺寸。
  • 右键删除节点 右键点击节点,在右键菜单中点击删除。触发 onRemoveNode
  • 右键编辑节点 右键单击节点,在右键菜单中点击编辑,在弹窗中对数据进行编辑。但是节点层级和组件类型不能编辑,触发 onUpdateNode
  • 调整层级高度,鼠标移入层级下侧拖拽线,点击鼠标左键进行拖动对层级高度进行调整。
  • 生成连线,在画布中从源端节点的端口拖拽连线到目标节点的端口。相同两个节点不能有重复的连线,生成节点前会调用 onAddLink
  • 删除连线,鼠标移入链接出现删除按钮。点击按钮会触发 onRemoveLink
  • 组件过滤,在左侧搜索框中输入内容,对下面的组件模版进行过滤
  • 撤销重做,画布上的操作都可以通过撤销重做来操作。会触发 onUndoOrRedo 回调
  • 放大 最多放大到当前画布的 1.5
  • 缩小 最小缩小到当前画布的 0.5
  • 全屏 展开整个编辑器到全屏操作
  • 取消全屏
  • 本地导入数据 在弹窗中拖入 ArchData 结构的 .json 文件
  • 本地导出数据 生成 ArchData 结果的.json 文件
  • 本地导出图片 将画布区域生成 png 图片
  • 上传数据 触发 onSave
  • 复制节点 左键单击节点,再点击复制节点按钮,节点信息将放入剪贴板中
  • 粘贴节点 点击粘贴节点按钮,将触发 onCreateNode
  • 删除节点 左键单击节点,再点击删除节点按钮。触发 onRemoveNode
  • 清理缓存 点击清理缓存,将清除缓存数据,并触发 reload ,而使用 data 传入的数据

快捷键

  • 复制节点到剪贴板 ctrl+c/commond+c
  • 粘贴节点 ctrl+v/commond+v
  • 撤销 ctrl+z/commond+z
  • 重做 ctrl+shift+z/commond+shift+z
  • 删除节点 backspace/backspace
  • 放大 ctrl+1/commond+1
  • 缩小 ctrl+2/commond+2
  • 清理缓存 ctrl+e/commond+e

API

参数 说明 类型 默认值
assets 图片资源键值对 Object {}
data 需要加载的数据,如果要更新数据,需要获取数据后,清理掉缓存 ArchData undefined
moduleConfig 画布左侧的组件模版,包含申请组件需要填写的数据 ModuleConfig undefined
cache 是否使用 indexdb 缓存数据,autoSaveInterval > 0时生效 boolean undefined
autoSaveInterval 数据自动保存的间隔时间 默认为 0,为 0 时不自动保存。单位为 ms number 0
showActions 是否显示功能按钮 boolean true
actions 显示功能键分类 ActionTypes[] undefined
appendActions 功能键右侧添加额外的组件 React.ReactNode undefined
registerList 需要注册的节点和线条的样式 Register[] undefined
defaultEdgeShape 默认生成线条的样式名称 string laneEdge
defaultNodeShape 默认生成节点的样式名称 string undefined
moduleNodeShape 左侧模型节点样式名称 string moduleNode
drawerRootNode 节点编辑弹窗根节点 false | string | HTMLElement | (() => HTMLElement); undefined
onAddLink 在画布中添加链接的回调,返回 promise<boolaen>。如果 resolve(true) 则建立链接,如果 resolve(false)则不会产生链接。 (link: Edge) => Promise<boolean> undefined
onRemoveLink 在画布中移除链接的回调,返回 promise<boolaen>。如果 resolve(true) 则移除链接,如果 resolve(false)则不会移除链接。 (links: Edge[]) => Promise<boolean> undefined
onRemoveNode 在画布中移除节点的回调,返回 promise<boolaen>。如果 resolve(true) 则移除节点,如果 resolve(false)则不会移除节点。 (nodes: Node[]) => Promise<boolean> undefined
onCreateNode 在画布中新建节点的回调,返回 promise<NodeData>。如果 resolve(data) 则创建新节点,如果 resolve(false)则不会创建节点。 (nodeData: NodeData) => Promise<NodeData> undefined
onUpdateNode 在画布中编辑节点的回调,返回 promise<NodeData>。如果 resolve(data) 则更新节点数据,如果 resolve(false)则不会更新节点数据。 (nodeData: NodeData) => Promise<NodeData> undefined
onUndoOrRedo 在画布中撤销和重做的回调。因为数据是之前已经产生过的,不需要用户再次确认,但可能存在与后端的交互,所以开放给开发者进行处理。节点数据更新不会放入撤销和重做队列中 (type: 'undo' | 'redo',graph: Graph,args: { cmds: any[]; options: any }) => Promise<boolean> undefined
onSave 将画布中数据保存至后端,返回 promise<boolean>。如果 resolve(true) 则保存成功,如果 resolve(false)则保存失败。 (data: ArchData) => Promise<boolean> undefined
onAutoSave 每隔一段时间自动将数据同步出来 (data: ArchData) => any undefined
onChange 节点和连线发生变化时的回调 (data: ArchData) => any undefined

ArchData 输入数据结构

参数 说明 类型
width 画布宽度 number
height 画布高度 number
lanes 节点层级配置 NodeData[]
nodes 组件节点 NodeData[]
links 组件连线 LinkData[]

NodeData 数据结构

参数 说明 类型
id 节点 ID (必需) string
name 节点名称 (必需) string
type 节点类型 (必需) "lane"|"node"
width 节点宽度 number
height 节点高度 number
zIndex 节点层级 默认 1 number
x 节点 x 坐标 number
y 节点 y 坐标 number
moduleType 节点组件类型 (必需) string
preId 节点所在层级的 ID (必需) string

ActionTypes

type ActionTypes = 'RE_UN_DO' | 'ZOOM' | 'EXPORT_DATA' | 'IMPORT_DATA' | 'EXPORT_IMG'| 'SUBMIT' | 'COPY' | 'PASTE' | 'DELETE' | 'CLEAR'
参数 说明
RE_UN_DO 撤销/重做
ZOOM 放大/缩小/全屏
EXPORT_DATA 导出数据
IMPORT_DATA 导入数据
EXPORT_IMG 导出图片
SUBMIT 上传数据,保存数据
COPY 复制节点
PASTE 粘贴节点
DELETE 删除节点
CLEAR 清理缓存

Register

NODE 是节点;EDGE是线条
type Register = { name: string; options: any; type: 'NODE' | 'EDGE'; handler: NodeHanlder; };

LinkData 数据结构

参数 说明 类型
source 链接源端节点 ID string | number
target 链接目标端节点 ID string | number
zIndex 链接所在层次(非必需) number

ModuleConfig 左侧组件类型定义

参数 说明 类型
title 左侧组件标题 string
search 是否需要搜索组件,以及搜索功能的配置 undefined|{placeholder?: string;}
options 左侧组件 ModuleGropuItem[]

ModuleGropuItem

参数 说明 类型
label 显示内容 string
value 标记 string
children 组件群 ModuleConfigItem[]

ModuleConfigItem

参数 说明 类型
label 显示内容 string
value 标记 string
moduleImage 图标 可根据assets[moduleImage]|| assets[${moduleType ? moduleType : value}Module||moduleImage 获取图片 ModuleConfigItem[]
target 组件只能放入哪些层级,如果为 undefined 或者[]默认可以放入所有层级 string[]
moduleProp 组件模版参数表单使用 ModulePropItem[]

ModulePropItem

参数 说明 类型
InputProp antd 表单录入组件属性 any
... antd FormItem 属性 any

V1.1.0 修改

  1. 修改了 iconfont 引入方式,不再需要手动引入。
  2. 增加了功能键的可选,可以只使用部分功能键。
  3. 删除预置的内部系统和外部系统图标。
  4. 去除内置节点样式,让用户自定义节点样式,保留默认边。
  5. 可自定义泳道样式

V1.2.0 新增功能

  1. 新增 onChange 事件,节点和连线发生变化时都将出发 onChange。
  2. 可以通过鼠标滚动或拖拽画布空白处调整当前视窗。不兼容 IE

Readme

Keywords

none

Package Sidebar

Install

npm i @rasir/x6-arch

Weekly Downloads

0

Version

1.2.10

License

ISC

Unpacked Size

403 kB

Total Files

73

Last publish

Collaborators

  • rasir