@rasir/x6-arch
v1.2.10
Published
基于antv/x6的架构设计工具
Downloads
4
Readme
AUTH
前言
这是一款基于antv/x6
的用于系统架构设计可视化的一款工具。
效果图
快速上手
说明
本组件是在react
框架下的前端组件,推荐[email protected]
以上版本。推荐使用[email protected]
脚手架。其他必要依赖见下文。
目前,作品还有很多需要完善的地方,有些兼容没有处理,推荐使用 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 修改
- 修改了 iconfont 引入方式,不再需要手动引入。
- 增加了功能键的可选,可以只使用部分功能键。
- 删除预置的内部系统和外部系统图标。
- 去除内置节点样式,让用户自定义节点样式,保留默认边。
- 可自定义泳道样式
V1.2.0 新增功能
- 新增 onChange 事件,节点和连线发生变化时都将出发 onChange。
- 可以通过鼠标滚动或拖拽画布空白处调整当前视窗。不兼容 IE