topology-vue@ >= 0.4.5
完整代码(master单机版)
ts源码: https://github.com/le5le-com/topology-vue-ts,https://gitee.com/le5le/topology-vue-ts
js源码: https://github.com/le5le-com/topology-vue-js,https://gitee.com/le5le/topology-vue-js
前后端联合使用(企业安装包试用包):
ts源码的api分支需要调用后端接口,下面部署安装包配套使用:
https://www.yuque.com/alsmile/topology/chm3rg
后端接口列表: https://www.yuque.com/alsmile/topology/pvto3o
定制导航菜单
详细参考API部分configs.menus说明。
[说明]个人免费版不能定制菜单;企业版没有限制。欢迎大家多支持我们,帮助我们发展的更强、更好用,和为国产原创开源发展做出一份贡献。
<template>
<div class="home">
<!-- 使用topology组件 -->
<topology
:configs="topologyConfigs"
:materials="materials"
:user="user"
:data="data"
@event="onEvent"
/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
// 导入topology-vue组件
import topology from 'topology-vue';
// 需要导入topology-vue.css
import 'topology-vue/topology-vue.css';
import {
defalutMaterials,
iconMenus,
userMenus,
} from './data';
Vue.use(topology);
@Component({})
export default class Home extends Vue {
topologyConfigs = {
license: {
key: 'le5le',
value: 'value',
version:'xxx',
},
logo: {
img: 'http://topology.le5le.com/assets/img/favicon.ico',
url: 'http://topology.le5le.com',
target: '_blank',
},
menus: iconMenus,
loginUrl: 'https://account.le5le.com',
signupUrl: 'https://account.le5le.com',
userMenus: userMenus,
dataOptionsFn: (pen: any, key: string, value: string) => {
// pen - 当前画笔对象
// key - 表单输入左侧的属性名
// value - 仅下拉搜索时有效,当前输入文本
console.log('dataOptionsFn', pen, key, value);
// ************
// 根据实际业务场景 + 参数返回数组对象。
// Do sth.
// ************
return [
{
label: '选项1',
value: 1,
},
{
label: '选项2',
value: 2,
},
{
label: '选项3',
value: 3,
},
];
},
};
user: any = {
username: 'le5le',
};
materials = {
system: defalutMaterials,
uploadUrl: '/api/file',
uploadHeaders: {
Authorization: 'your token',
},
uploadParams: {
mydata: 1,
},
};
data: any = {};
created() {
const data = (window as any).topologyData;
// 预览页返回,存在缓存数据
if (data) {
this.data = { data: Object.assign({}, data) };
setTimeout(() => {
(window as any).topologyData = null;
}, 200);
} else {
}
}
onEvent(e: { name: string; params: any }) {
switch (e.name) {
case 'logout':
// 退出登录
this.user = null;
// Do sth.
break;
case 'openMaterialGroup':
// 展开/折叠图标工具栏分组
console.log('openMaterialGroup', e.params);
// Do sth.
break;
case 'addMaterial':
// 添加“我的组件”
// Do sth. For example:
this.$router.push({
path: '/',
query: { component: '1' },
});
break;
case 'editMaterial':
// 编辑“我的组件”
// Do sth. For example:
this.$router.push({
path: '/',
query: { id: e.params.id, component: '1' },
});
break;
case 'open':
// 导航菜单configs.menus里面定义的action
// 比如这里表示打开文件
break;
case 'save':
// 导航菜单configs.menus里面定义的action
// 比如这里表示保存文件
break;
case 'addImageUrl':
// 在“我的图片”里面添加了一张新图片
// this.addImageUrl(e.params);
break;
case 'preview':
// 点击工具栏“预览”
// 保存当前编辑数据,方便预览时直接打开
(window as any).topologyData = (window as any).topology.data;
this.$router.push({
path: '/preview',
query: { id: 'xxx', r: '1' },
});
break;
case 'remove-user-component': // 删除用户组件
case 'remove-topology': // 删除图纸
break;
case 'remove-user-image': // 删除图片
break;
// ...
// ...
}
}
}
</script>
<style lang="scss">
.home {
height: 100vh;
}
</style>
<template>
<div class="home">
<!-- 使用topology组件 -->
<topology :configs="topologyConfigs" :user="user" />
</div>
</template>
<script>
import Vue from 'vue';
// 导入topology-vue组件
import topology from "topology-vue";
Vue.use(topology);
// 需要导入topology-vue.css
import "topology-vue/topology-vue.css";
export default {
name: "Home",
data: function () {
return {
topologyConfigs: {
logo: {
img: "http://topology.le5le.com/assets/img/favicon.ico",
url: "http://topology.le5le.com",
target: "_blank",
},
menus: {
// back: {
// icon: "t-icon t-angle-left",
// },
// login: true,
left: [
{
name: "文件(自定义菜单1)",
children: [
{ name: "新建文件", keyboard: "Ctrl+N", action: "open" },
{ name: "打开文件", keyboard: "Ctrl+O", action: "loadNew" },
{ name: "导入文件", keyboard: "Ctrl+I", action: "load" },
{},
{ name: "保存", keyboard: "Ctrl+S", action: "save" },
{ name: "另存为", keyboard: "Ctrl+Shift+I", action: "saveAs" },
{ name: "下载JSON文件", action: "downloadJson" },
{ name: "下载zip打包文件", action: "downloadZip" },
{},
{ name: "导出为HTML", action: "downloadHtml" },
{},
{ name: "下载为PNG", action: "downloadPng" },
{ name: "下载为SVG", action: "downloadSvg" },
],
},
{
name: "编辑(自定义菜单2)",
children: [
{ name: "撤销", keyboard: "Ctrl+Z", action: "undo" },
{ name: "恢复 ", keyboard: "Ctrl+Shift+Z", action: "redo" },
{},
{ name: "剪切 ", keyboard: "Ctrl+X", action: "cut" },
{ name: "复制 ", keyboard: "Ctrl+C", action: "copy" },
{ name: "粘贴 ", keyboard: "Ctrl+V", action: "paste" },
],
},
{
name: "我的菜单3",
router: "/page",
},
],
// middle: [],
},
loginUrl: "https://account.le5le.com",
signupUrl: "https://account.le5le.com",
userMenus: [
{ name: "个人中心", router: "/user/home" },
{},
{
name: "账号设置",
url: "https://account.le5le.com/user/profile",
target: "_blank",
},
{},
{ name: "退出", action: "logout" },
],
},
};
},
};
</script>
<style lang="scss">
.home {
height: 100vh;
}
</style>
设置用户登录
【前提】先设置congfigs.menus.login=true (默认值)
1. 显示用户已登录
2. 设置用户菜单
3. 退出登录
根据实际情况,配置用户菜单configs.userMenus中的菜单响应方式即可。
A. 可以跳转到vue路由处理;
参考菜单属性router配置:
B. 跳转新页面处理;
参考菜单属性url配置:
C. 通过发消息通知处理
参考菜单属性action配置,同时设置event事件函数:
<template>
<div class="home">
<!-- 使用topology组件 -->
<topology :configs="topologyConfigs" :user="user" @event="onEvent" />
</div>
</template>
<script>
// 导入topology-vue组件
import topology from "topology-vue";
// 需要导入topology-vue.css
import "topology-vue/topology-vue.css";
export default {
name: "Home",
components: {
topology,
},
data: function () {
return {
topologyConfigs: {
logo: {
img: "http://topology.le5le.com/assets/img/favicon.ico",
url: "http://topology.le5le.com",
target: "_blank",
},
menus: {
// back: {
// icon: "t-icon t-angle-left",
// },
// login: true,
left: [
{
name: "文件(自定义菜单1)",
children: [
{ name: "新建文件", keyboard: "Ctrl+N", action: "open1" },
{ name: "打开文件", keyboard: "Ctrl+O", action: "loadNew" },
{ name: "导入文件", keyboard: "Ctrl+I", action: "load" },
{},
{ name: "保存", keyboard: "Ctrl+S", action: "save" },
{ name: "另存为", keyboard: "Ctrl+Shift+I", action: "saveAs" },
{ name: "下载JSON文件", action: "downloadJson" },
{ name: "下载zip打包文件", action: "downloadZip" },
{},
{ name: "导出为HTML", action: "downloadHtml" },
{},
{ name: "下载为PNG", action: "downloadPng" },
{ name: "下载为SVG", action: "downloadSvg" },
],
},
{
name: "编辑(自定义菜单2)",
children: [
{ name: "撤销", keyboard: "Ctrl+Z", action: "undo" },
{ name: "恢复 ", keyboard: "Ctrl+Shift+Z", action: "redo" },
{},
{ name: "剪切 ", keyboard: "Ctrl+X", action: "cut" },
{ name: "复制 ", keyboard: "Ctrl+C", action: "copy" },
{ name: "粘贴 ", keyboard: "Ctrl+V", action: "paste" },
],
},
{
name: "我的菜单3",
router: "/page",
},
],
// middle: [],
},
loginUrl: "https://account.le5le.com",
signupUrl: "https://account.le5le.com",
userMenus: [
{ name: "个人中心", router: "/user/home" },
{},
{
name: "账号设置",
url: "https://account.le5le.com/user/profile",
target: "_blank",
},
{},
{ name: "退出", action: "logout" },
],
},
user: {
username: "le5le",
},
};
},
methods: {
onEvent(e) {
switch (e.name) {
case "logout":
this.user = null;
// Do sth.
break;
// ...
// ...
}
},
},
};
</script>
<style lang="scss">
.home {
height: 100vh;
}
</style>
js源码: https://github.com/le5le-com/topology-vue-js/tree/user
ts源码: https://github.com/le5le-com/topology-vue-ts/tree/user
定制图标库工具栏
0. Tab标签页
可使用用户自定义的动态组件,可完全自定义。【仅企业授权支持定制。】
配置API中的configs.materialTabs
export const defalutMaterialTabs = [
{
name: '图纸',
component: 'MaterialTopology'
},
{
name: '系统组件', // 显示名称
component: 'MaterialSystem', // vue动态组件名称
active: true // 是否是活动标签
},
{
name: '我创建的',
component: 'MaterialUser'
}
];
1. 图纸
通过文件夹形式展示用户绘画的图纸。配置API中的material.topology。
点击图纸触发event事件:
2. 系统组件
“系统组件”指公用组件,所有人都可以访问。
参考API配置materials.system属性即可。
格式:
【注意】当工具栏图标比较多时,可采用异步加载,在onEvent中监听展开分组事件:’openMaterial’。
1.1 添加阿里字体图形库
【仅企业授权】支持把阿里字体作为图形库加载到工具栏。
使用方法:在materials.system中添加iconUrl类型的数据即可。例如:
defalutMaterials = [
{
iconUrl: '//at.alicdn.com/t/font_xxxxx.css', // 替换成真实的地址
show: true,
list: [], // 此处留空数组就好,会自动填充
}
...
]
1.2 加载企业组件js库
1)把企业js组件库放到public
2)index.html中加载
3)加载到左边工具栏
完整代码:https://github.com/le5le-com/topology-vue-js/tree/tools
3. 我创建的(组件)
“我创建的”指用户在线编辑的组件或上传的图片组件,属于用户独有。
参考API配置materials.user属性即可。
2.1 创建组件
可以在onEvent中监听“addMaterial”,用于自己的业务处理。比如,路由变化,以及保存消息时,图文的数据保存和组件的数据保存处理是不一样的。
2.2 编辑“创建的组件”
点击“我的组件”右上角编辑按钮,可进入编辑组件状态。可以在onEvent中监听“editMaterial”,用于自己的业务处理。
2.3 保存“创建的组件”
可以在onEvent中监听“save”保存操作:
- 通过topology.toComponent() 得到节点数据componentData
- 通过topology.toImage 得到预览图
- 调用自己的接口保存数据即可。
2.4. 上传图片
可以配置一个上传接口地址,实现图片上传。具体参数参考:API.materials.uploadXXX相关属性。
url接口方式:
materials: {
system: defalutMaterials,
user: userMaterials,
images,
uploadUrl: '/api/file',
uploadHeaders: {
Authorization: 'your token'
},
uploadParams: {
mydata: 1
}
}
自定义上传函数方式uploadFn:参考antdv的上传组件用法
上传完成后,会触发event事件:addImageUrl , 确保后端返回的一级属性存在 url 。
uploadFn: (file: any) => {
const param = new FormData(); // 创建form对象
param.append('file', file.file); // 将文件存入file下面
param.append('mydata', '1');
axios
.post('/api/file', param, {
headers: {
Authorization: 'your token',
headers: { 'Content-Type': 'multipart/form-data' }
}
})
.then(res => {
// 调用该方法触发 addImageUrl , 确保 res 的一级属性中存在 url。
file.onSuccess(res);
});
}
完整源码
js源码:https://github.com/le5le-com/topology-vue-js/tree/materials
ts源码:https://github.com/le5le-com/topology-vue-ts/tree/materials
响应菜单等事件
导航菜单栏我们期望触发一个自定义的事件(比如保存用自己的接口)、监听画布消息等场景,我们可以通过event函数去监听。
<template>
<div class="home">
<!-- 使用topology组件 -->
<topology
:configs="topologyConfigs"
:materials="materials"
:user="user"
@event="onEvent"
/>
</div>
</template>
methods: {
onEvent(e) {
switch (e.name) {
case 'logout':
// 退出登录
this.user = null;
// Do sth.
break;
case 'openMaterialGroup':
// 展开/折叠图标工具栏分组
console.log('openMaterialGroup', e.params);
// Do sth.
break;
case 'addMaterial':
// 添加“我的组件”
// Do sth. For example:
this.$router.push({
path: '/',
query: { component: '1' }
});
break;
case 'editMaterial':
// 编辑“我的组件”
// Do sth. For example:
this.$router.push({
path: '/',
query: { id: e.params.id, component: '1' },
});
break;
case 'open':
// 导航菜单configs.menus里面定义的action
// 比如这里表示打开文件
break;
case 'save':
// 导航菜单configs.menus里面定义的action
// 比如这里表示保存文件
break;
case 'addImageUrl':
// 在“我的图片”里面添加了一张新图片
// this.addImageUrl(e.params);
break;
case 'preview':
// 点击工具栏“预览”
this.$router.push({
path: '/preview',
query: { id: 'xxx', r: '1' }
});
break;
// ...
// ...
}
}
}
js源码:https://github.com/le5le-com/topology-vue-js/tree/events
ts源码:https://github.com/le5le-com/topology-vue-ts/tree/events
属性面板-数据输入配置
画笔的数据面板,支持多种类型的表单输入。其中包含下拉选项的,需要通过配置选项函数,返回下拉列表
如何使用:
仅select、自动完成等下拉选项输入框需要配置。通过configs.dataOptionsFn函数返回一个符合antdv下拉列表select等组件格式的数组。
export default {
name: 'Home',
components: {
topology
},
data: function() {
return {
topologyConfigs: {
license: {
key: '企业版授权码',
value: '国产原创开源发展做出我们的贡献',
version:'xxx',
},
logo: {
img: 'http://topology.le5le.com/assets/img/favicon.ico',
url: 'http://topology.le5le.com',
target: '_blank'
},
menus: defalutMenus,
loginUrl: 'https://account.le5le.com',
signupUrl: 'https://account.le5le.com',
userMenus: defalutUserMenus,
dataOptionsFn: (pen, key, value) => {
// pen - 当前画笔对象
// key - 表单输入左侧的属性名
// value - 仅下拉搜索时有效,当前输入文本
console.log('dataOptionsFn', pen, key, value);
// ************
// 根据实际业务场景 + 参数返回数组对象。
// Do sth.
// ************
return [{
label: '选项1',
value: 1
}, {
label: '选项2',
value: 2
}, {
label: '选项3',
value: 3
}];
}
},
user: {
username: 'le5le'
},
materials: {
system: defalutMaterials,
user: userMaterials,
images,
uploadUrl: '/api/file',
uploadHeaders: {
Authorization: 'your token'
},
uploadParams: {
mydata: 1
}
}
};
},
// .....
}
何时触发函数
- 新增数据
- 修改属性名(可以根据不同属性名返回不同的下拉选项)
- (自动完成输入框有效)搜索内容变化
js源码: https://github.com/le5le-com/topology-vue-js/tree/data
ts源码: https://github.com/le5le-com/topology-vue-ts/tree/data
预览
设置preview属性和data属性即可。
<template>
<div class="preview">
<topology preview="true" :data="data" />
</div>
</template>
示例代码实现过程:
- 编辑器页面监听preview事件,保存绘画数据
- 新路由页面(预览和编辑器页面都是一样的)created时,先读取缓存数据,再读取接口数据
完整代码参考:
js源码: https://github.com/le5le-com/topology-vue-js
ts源码: https://github.com/le5le-com/topology-vue-ts
其他
1. echarts库加载
需要使用echarts图形库的,可以在html中直接加载想要的版本:
如果画布没有检查到echarts被加载,则采用图形库中默认的cdn版本。
2. 代码编辑器Monaco加载
右侧属性栏数据编辑有使用Monaco编辑器。缺省使用在线cdn:https://cdn.bootcdn.net/ajax/libs/monaco-editor/0.21.2/min 。如果内网或其他环境,可以通过configs.monaco指定cdn路径。
3. 依赖工具js
href=”//at.alicdn.com/t/font_2030495_6swk6vyrz4.css”
rel=”stylesheet”
/>
<!-- 需要用到的工具js --><br /> <script src="http://topology.le5le.com/js/canvas2svg.js"></script><br /> <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script><br /> <script src="https://cdn.bootcss.com/jszip/3.2.2/jszip.min.js"></script><br /> <script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.8.0/echarts.min.js"></script><br /> </body>
API
id
缺省无需配置(默认值 topology),若存在多个 topology 时,需要指定。
<div class="home">
<!-- 使用topology组件 -->
<div style="flex: 1">
<topology
id="topology1"
:configs="topologyConfigs"
:materials="materials"
:user="user"
:data="data"
@event="onEvent"
/>
</div>
<div style="flex: 1">
<topology
id="topology2"
:configs="topologyConfigs2"
:materials="materials2"
:user="user2"
:data="data2"
@event="onEvent2"
/>
</div>
</div>
configs
配置选项。
属性 | 说明 | 类型 | 默认值 |
---|---|---|---|
license | 授权码 主要用于企业版用户解锁全部功能。 免费版 - 不可配置导航菜单。 企业版本 - 配置企业授权码,导航菜单完全可定制,没有限制。 |
{key, value, version} | 空。(免费版) |
logo | 左上角logo。 img - logo 图片url地址 router - vue路由地址。点击logo调整vue路由地址 url - 新页面地址。点击logo,完全打开新页面。 target - 打开新页面地址的方式,配合url使用。 text - logo 下的文字. |
{ img, router, url, target, text, } |
传入 null 不展示 logo,企业版支持 |
loginUrl | 右上角“登录”按钮跳转地址 | string | 乐吾乐官网登录地址 |
signupUrl | 右上角“注册”按钮跳转地址 | string | 乐吾乐官网注册地址 |
menus | 顶部导航菜单内容 | back:左上角显示“返回”菜单,返回到上一个页面。 left:菜单栏左侧部分。[可缺省] middle:菜单栏中间部分。可选设置为空undefined,为默认数组。当设置为[]空数组,不显示中间部分。 right:菜单栏右侧部分。[可缺省] share:菜单栏右侧是否显示分享图标 login:是否显示用户或用户菜单。 left/middle/right数组下的菜单项含义: image:菜单图标,url地址。可选 icon: 菜单图标,字体图标名。可选 name: 菜单名 router: vue页面路由地址 url: 新页面地址 target: url的打开方式 action: 开发者自己处理的事件名称。(router/url/action三选一) children: [menus] 子菜单 name为空表示分割线 |
缺省菜单 |
userMenus | 用户登录后,显示的下拉菜单 |
默认: [ { name: ‘个人中心’, router: ‘/user/home?h=0’ }, {}, { name: ‘账号设置’, url: ‘https://account.le5le.com/user/profile‘, target: ‘_blank’ }, {}, { name: ‘退出’, action: ‘logout’ } ] |
|
materialTabs | 左侧图形库工具栏标签页 |
| [{
name: 显示名称,
component: vue动态组件名称,
active:是否是活动标签页
}] | export const defalutMaterialTabs = [
{
name: ‘图纸’,
component: ‘MaterialTopology’
},
{
name: ‘系统组件’,
component: ‘MaterialSystem’,
active: true
},
{
name: ‘我创建的’,
component: ‘MaterialUser’
}
]; |
| monaco | monaco-editor cdn前缀地址 | string | 空
0.5.28 版本必传或参照一分钟上手。 |
| dataOptionsFn | 属性面板 - “数据” - “我的数据”中用到的下拉列表选项函数。
需要返回一个对象,对象存在三个属性,根据需要返回。
- keys,键列表,属性名的可选下拉列表
- values,值列表,属性值的可选下拉列表
- value,值,若存在属性值默认值,可以使用该参数
| 函数
(pen, key, value) => {
const keys = [
{ value: ‘aaa’, label: ‘1’ }
];
const values = [
{ value: ‘000’, label: ‘1’ }
];
return {
keys,
value: 999,
values,
};
}
参数:
pen: 当前画笔
key: 表单输入的 “属性名”
value: 表单输入的当前“属性值”。比如自动完成输入框的当前输入的值。
返回值:
参考antdv的select组件的下列选项格式。 | 空 |
| locale | 语言 | string | zh
默认是中文,当前支持传入 en 和 zh . |
materials
图形库工具栏。
属性 | 说明 | 类型 | 默认值 |
---|---|---|---|
topology | 图纸 | [{ name:文件夹名称, opened:是否打开文件夹, notLoad: true 无需加载,不会进入加载中, list:[{ image: 图片URL, name:图纸名称, …自定义数据 }] }] |
空 单击图纸时,触发event事件。事件参数:{ name: ‘view’, params: 图纸数据 } |
system | 系统组件 | [{ name:分类名称 list: [{ name: 工具栏提示文字 icon:工具栏显示字体图标 image: 图片URL, data: json对象,符合topology节点的数据结构 }] expand:是否展开 show:是否显示 count:图标个数 iconUrl:企业版功能,阿里字体css地址,支持把阿里字体文件作为组件库 }] |
空 |
user | 我创建的(组件)。一般用于用户在线绘画保存的组件和上传的图片组件 | [{ name: 文件夹名称, opened:文件夹是否打开, notLoad: true 无需加载,不会进入加载中, list:[{ id: 编辑时,获取后台接口数据用。为图片时不需要 name: 组件名称 image:组件预览图url component: true 才会使用 componentData 或 data componentData: json对象,符合topology节点的数据结构。为图片时不需要 data: json对象,符合topology节点的数据结构,和componentData二选一。为图片时不需要 }] ] |
|
images | 上传的图片。一般用于设置画布的背景图片或为节点添加图片。 | [{ folder:图片所在目录, image:组件预览图url, … }] |
|
iconUrls | 图标。一般用于为节点配置图标。 | string[] | |
uploadFn | 文件上传函数。用法参考antdv上传组件a-upload的customRequest参数用法 和下面uploadUrl二选一 |
函数 | |
uploadUrl | 文件上传接口url | url地址 | |
uploadName | 文件上传数据中,文件存储的字段名 | string | file |
uploadHeaders | 文件上传时,指定的headers | json对象 | |
uploadParams | 文件上传时,额外的上传参数。用法参考antdv上传组件a-upload的data参数用法 | json对象 |
classes
图形库分类。数组类型
属性 | 说明 | 类型 | 默认值 |
---|---|---|---|
name | 分类名称 | [{ name:分类名称 }] |
user
用户信息。判断用户是否登录
属性 | 说明 | 类型 | 默认值 |
---|---|---|---|
username | 用户名 | string |
preview
boolean类型。是否时预览模式。
data
属性 | 说明 | 类型 | 默认值 |
---|---|---|---|
pens | 画笔数组 | Pen[] | |
component | 是否是组件。默认为图文 | boolean | false |
id | 数据库id。用于调用后端接口时查询具体图文或组件;同时用于“最近打开的文件”id | string | |
name | 用于“最近打开的文件”中的名称显示 | string | |
image | 缩略图url。用于“最近打开的文件”中缩略图显示 | url地址 | |
… | 可自定义其他任意属性 |
event事件
@event事件用于响应创建/修改/删除文件夹、新建图纸/组件,左侧图形库展开等事件(可打日志监听事件)
function(event: {name, params})
event.name - 事件名
event.params - 事件附带参数数据