修改top图

This commit is contained in:
20932067@zju.edu.cn 2021-05-14 22:53:21 +08:00
parent 57f72190c5
commit baf0d2948d
55 changed files with 1654 additions and 1294 deletions

View File

@ -3,9 +3,9 @@ ENV = 'development'
# 宏驰云管理系统/开发环境
#VUE_APP_BASE_API = '/dev-api'
#VUE_APP_BASE_API = 'http://localhost:8085/dev-api'
VUE_APP_BASE_API = 'http://localhost:8085/dev-api'
#VUE_APP_BASE_API = 'http://apibase.hchyun.com/dev-api'
VUE_APP_BASE_API = 'http://apig.odliken.top/dev-api'
#VUE_APP_BASE_API = 'http://apig.odliken.top/dev-api'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true

View File

@ -48,6 +48,7 @@
"file-saver": "2.0.1",
"fuse.js": "3.4.4",
"highlight.js": "9.18.5",
"jquery": "^3.6.0",
"js-beautify": "1.10.2",
"js-cookie": "2.2.0",
"jsencrypt": "3.0.0-rc.1",

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
<template>
<div class="checkbox" :class="{ 'checkbox-checked': checkVal }">
<div class="cc-checkbox" :class="{ 'checkbox-checked': checkVal }">
<input
id="checkbox"
type="checkbox"
@ -28,7 +28,7 @@ export default {
</script>
<style lang="scss" scoped>
.checkbox {
.cc-checkbox {
display: inline-block;
color: #606266;
font-size: 14px;

View File

@ -1,184 +1,228 @@
<template>
<div class="cc-dropdown" @mouseover="onMouseOver" @mouseout="onMouseOut">
<span><a href="javascript:void(0);">{{ dropdownItems[activeIndex].label }}</a></span>
<div class="cc-dropdown-menu" ref="dropdownMenu" @mouseover="onMouseOver">
<ul>
<li
v-for="(dropdownItem, index) in dropdownItems"
:key="index"
@click="onItemClick(index, $event)"
>
<a href="javascript:void(0);">{{ dropdownItem.label }}</a>
</li>
</ul>
<div class="graph-op">
<i v-for="edgeItem in dropdownItems " :class="edgeItem.class" v-on:title="edgeItem.label" style="width: 120px;"
@click="onItemClick(edgeItem.guid, $event)">&nbsp;&nbsp;{{edgeItem.label}}</i>
</div>
</div>
</template>
<script>
export default {
name: 'CCDropdownList',
props: {
dropdownItems: {
type: Array,
default() {
return [
{ value: 0, label: '未选择' },
{ value: 1, label: '选项一' },
{ value: 2, label: '选项二' },
{ value: 3, label: '选项三' }
]
}
},
defaultIndex: {
type: Number,
default() {
return 0
}
import $ from 'jquery'
export default {
name: 'CCDropdownList',
props: {
dropdownItems: {
type: Array,
default() {
return [
]
}
},
defaultIndex: {
type: Number,
default() {
return 0
}
}
},
data() {
return {
activeIndex: this.defaultIndex,
timeout: null
}
},
watch: {
activeIndex() {
this.$emit('change', this.activeIndex)
}
},
mounted() {
$('.iconfonts')[0].style.backgroundColor = '#ebeef2'
},
methods: {
onItemClick(index,e) {
let lineList = $('.iconfonts')
for (let i=0;i<lineList.length;i++){
lineList[i].style.backgroundColor = '#ffffff'
}
if (e.path[0].style.backgroundColor=='rgb(255, 255, 255)'){
e.path[0].style.backgroundColor = '#ebeef2'
}
if (index !== this.activeIndex) {
this.activeIndex = index
}
}
}
}
},
data() {
return {
activeIndex: this.defaultIndex,
timeout: null
}
},
watch: {
activeIndex() {
this.$emit('change', this.dropdownItems[this.activeIndex])
}
},
methods: {
onMouseOver() {
if (this.timeout) {
clearTimeout(this.timeout)
}
this.$refs.dropdownMenu.style.display = 'block'
},
onMouseOut() {
this.timeout = setTimeout(() => {
this.$refs.dropdownMenu.style.display = 'none'
}, 300)
},
onItemClick(index) {
this.$refs.dropdownMenu.style.display = 'none'
if (index !== this.activeIndex) {
this.activeIndex = index
}
}
}
}
</script>
<style lang="scss" scoped>
.cc-dropdown {
position: relative;
display: inline-block;
min-width: 100px;
text-align: center;
a {
color: #000;
text-decoration: none;
}
ul,
li {
list-style: none;
}
span {
display: block;
z-index: 2;
height: 30px;
line-height: 30px;
background-color: transparent;
font-size: 14px;
border-radius: 5px;
-webkit-transition: all .2s ease-in;
transition: all .2s ease-in;
}
span a:after{
content: " ";
display: inline-block;
width: 0;
height: 0;
font-size: 0;
line-height: 0;
border-bottom: solid 6px #000;
border-left: solid 4px transparent;
border-right: solid 4px transparent;
vertical-align: 3px;
margin-left: 10px;
-webkit-transition: all .2s ease-in;
transition: all .2s ease-in;
}
}
.cc-dropdown-menu {
position: absolute;
display: none;
top: 50px;
left: 0;
right: 0;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.2);
border-radius: 5px;
z-index: 1;
.iconfonts {
color: #666666;
/* 一个很重要的三角形*/
li:first-child:before {
display: block; /* 独占一行 */
content: " ";
font-size: 0;
line-height: 0;
margin: 0 auto; /* 居中 */
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.2); /* 配合整体一样的投影 */
background-color: #fff;
width: 10px;
height: 10px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg); /* 一个正方形倾斜四十五度就是三角了但是要把下半部分藏起来 */
position: relative;
top: -5px; /* 露出上半部分*/
z-index: 1; /* 隐藏下半部分 */
-webkit-transition: all .2s ease-in;
transition: all .2s ease-in;
}
li a {
color: #888;
line-height: 46px;
border-bottom: solid 1px #eee;
font-size: 14px;
display: block;
background-color: #fff; /* 要有背景色才能盖住呀*/
position: relative;
z-index: 2; /* 这里很重要 要挡住三角形的下半部分*/
-webkit-transition: all .2s ease-in;
transition: all .2s ease-in;
}
/* 以下两块控制第一个和最后一个li要圆角因为最外边的div没有overflow 也不可以overflow*/
li:first-child a{
border-top-left-radius: 5px;
border-top-right-radius: 5px;
margin-top: -10px;
}
li:last-child a{
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
border-bottom: none;
}
/*hover事件给了li先改变三角 再改变a*/
li:hover:before{
background-color: #ecf5ff;
}
li:hover a {
background-color: #ecf5ff;
color: #66b1ff;
}
}
font-size: 12px;
line-height: 20px;
height: 20px;
padding-bottom: 2px;
.cc-dropdown:hover span{
background-color: transparent;
}
.cc-dropdown:hover span a:after {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
.graph-op {
display: inline-block;
vertical-align: middle;
i {
width: 20px;
height: 20px;
margin: 0 6px;
line-height: 20px;
color: #a8a8a8;
text-align: center;
border-radius: 2px;
display: inline-block;
border: 1px solid rgba(2, 2, 2, 0);
}
i:hover {
cursor: pointer;
border: 1px solid #E9E9E9;
}
.disabled {
color: rgba(0, 0, 0, 0.25);
}
.disabled:hover {
cursor: not-allowed;
border: 1px solid rgba(2, 2, 2, 0);
}
.icon-select {
background-color: #EEEEEE;
}
.separator {
margin: 4px;
border-left: 1px solid #E9E9E9;
}
}
.cc-dropdown {
position: relative;
display: inline-block;
min-width: 100px;
text-align: center;
a {
color: #000;
text-decoration: none;
}
ul,
li {
list-style: none;
}
span {
display: block;
z-index: 2;
height: 30px;
line-height: 30px;
background-color: transparent;
font-size: 14px;
border-radius: 5px;
-webkit-transition: all .2s ease-in;
transition: all .2s ease-in;
}
span a:after {
content: " ";
display: inline-block;
width: 0;
height: 0;
font-size: 0;
line-height: 0;
border-bottom: solid 6px #000;
border-left: solid 4px transparent;
border-right: solid 4px transparent;
vertical-align: 3px;
margin-left: 10px;
-webkit-transition: all .2s ease-in;
transition: all .2s ease-in;
}
}
.cc-dropdown-menu {
position: absolute;
display: none;
top: 50px;
left: 0;
right: 0;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.2);
border-radius: 5px;
z-index: 1;
/* 一个很重要的三角形*/
li:first-child:before {
display: block; /* 独占一行 */
content: " ";
font-size: 0;
line-height: 0;
margin: 0 auto; /* 居中 */
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.2); /* 配合整体一样的投影 */
background-color: #fff;
width: 10px;
height: 10px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg); /* 一个正方形倾斜四十五度就是三角了但是要把下半部分藏起来 */
position: relative;
top: -5px; /* 露出上半部分*/
z-index: 1; /* 隐藏下半部分 */
-webkit-transition: all .2s ease-in;
transition: all .2s ease-in;
}
li a {
color: #888;
line-height: 46px;
border-bottom: solid 1px #eee;
font-size: 14px;
display: block;
background-color: #fff; /* 要有背景色才能盖住呀*/
position: relative;
z-index: 2; /* 这里很重要 要挡住三角形的下半部分*/
-webkit-transition: all .2s ease-in;
transition: all .2s ease-in;
}
/* 以下两块控制第一个和最后一个li要圆角因为最外边的div没有overflow 也不可以overflow*/
li:first-child a {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
margin-top: -10px;
}
li:last-child a {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
border-bottom: none;
}
/*hover事件给了li先改变三角 再改变a*/
li:hover:before {
background-color: #ecf5ff;
}
li:hover a {
background-color: #ecf5ff;
color: #66b1ff;
}
}
.cc-dropdown:hover span {
background-color: transparent;
}
.cc-dropdown:hover span a:after {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
</style>

View File

@ -1,7 +1,7 @@
/**
* @author: clay
* @data: 2021/11/14
* @description: cceditor内部的通用组件
* @data: 2019/11/14
* @description: ClayTop内部的通用组件
*/
import Checkbox from './checkbox'

View File

@ -1,6 +1,6 @@
<template>
<div class="model-overlay">
<div class="loading">
<div class="cc-loading">
<svg class="circular" viewBox="0 0 50 50">
<circle cx="25" cy="25" r="20" fill="none" stroke="#409EFF" stroke-width="5%" stroke-linecap="round"/>
</svg>
@ -34,7 +34,7 @@ export default {
background-color: transparent;
}
.loading {
.cc-loading {
position: absolute;
width: 50px;
top: 45%;

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/20
* @description: 整合所有的组件对外导出即一个完整的组件库
*/
@ -16,7 +16,7 @@ const install = function(Vue) {
// 判断是否安装
if (install.installed) return
// 遍历注册全局组件
console.info('install----CCEditor: All----')
console.info('install----ClayTop: All----')
components.map(component => Vue.component(component.name, component))
}

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/20
* @description: 导入组件组件必须声明 name
*/
@ -8,7 +8,7 @@ import Topology from './src/topology'
// 为组件提供 install 安装方法,供按需引入
Topology.install = function(Vue) {
console.info('install----CCEditor: Topology----')
console.info('install----ClayTop: Topology----')
Vue.component(Topology.name, Topology)
}

View File

@ -1,11 +1,9 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/05
* @description: edit mode: 通过先后点击两个节点来添加连线容易和节点点击动作交叉已弃用
*/
import G6 from '@antv/g6'
import theme from '../theme'
export default {
name: 'click-add-edge',

View File

@ -1,124 +1,172 @@
/**
* @author: clay
* @data: 2021/5/10
* @author: winyuan
* @data: 2019/07/16
* @repository: https://github.com/winyuan
* @description: edit mode: 鼠标点击交互
*/
// 用来获取调用此js的vue组件实例this
let vm = null
let vm = null;
const sendThis = (_this) => {
vm = _this
}
vm = _this;
};
export default {
sendThis, // 暴露函数
name: 'click-event-edit',
name: "click-event-edit",
options: {
getEvents() {
return {
'node:click': 'onNodeClick',
'node:contextmenu': 'onNodeRightClick',
'edge:click': 'onEdgeClick',
'edge:contextmenu': 'onEdgeRightClick',
'canvas:click': 'onCanvasClick'
}
"node:click": "onNodeClick",
"node:contextmenu": "onNodeRightClick",
"edge:click": "onEdgeClick",
"edge:contextmenu": "onEdgeRightClick",
"canvas:click": "onCanvasClick",
};
},
onNodeClick(event) {
// todo..."selected"是g6自带的状态在"drag-add-edge"中的"node:mouseup"事件也会触发,故此处不需要设置"selected"状态
// let clickNode = event.item;
// clickNode.setState('selected', !clickNode.hasState('selected'));
vm.currentFocus = 'node'
vm.rightMenuShow = false
this.updateVmData(event)
vm.currentFocus = "node";
vm.rightMenuShow = false;
this.updateVmData(event);
},
onNodeRightClick(event) {
let graph = vm.graph
let clickNode = event.item
let clickNodeModel = clickNode.getModel()
let selectedNodes = graph.findAllByState('node', 'selected')
let selectedNodeIds = selectedNodes.map(item => {return item.getModel().id})
vm.selectedNode = clickNode
let graph = vm.graph;
let clickNode = event.item;
let clickNodeModel = clickNode.getModel();
let selectedNodes = graph.findAllByState("node", "selected");
let selectedNodeIds = selectedNodes.map(item => {
return item.getModel().id;
});
vm.selectedNode = clickNode;
// 如果当前点击节点是之前选中的某个节点,就进行下面的处理
if (selectedNodes.length > 1 && selectedNodeIds.indexOf(clickNodeModel.id) > -1) {
vm.rightMenuShow = true
let rightMenu = vm.$refs.rightMenu
rightMenu.style.left = event.clientX + 'px'
rightMenu.style.top = event.clientY + 'px'
vm.rightMenuShow = true;
let rightMenu = vm.$refs.rightMenu;
rightMenu.style.left = event.clientX + "px";
rightMenu.style.top = event.clientY + "px";
} else {
// 隐藏右键菜单
vm.rightMenuShow = false
vm.rightMenuShow = false;
// 先取消所有节点的选中状态
selectedNodes.forEach(node => {
node.setState('selected', false)
})
node.setState("selected", false);
});
// 再添加该节点的选中状态
clickNode.setState('selected', true)
vm.currentFocus = 'node'
this.updateVmData(event)
clickNode.setState("selected", true);
vm.currentFocus = "node";
this.updateVmData(event);
}
graph.paint()
graph.paint();
},
onEdgeClick(event) {
let clickEdge = event.item
clickEdge.setState('selected', !clickEdge.hasState('selected'))
vm.currentFocus = 'edge'
this.updateVmData(event)
let clickEdge = event.item;
clickEdge.setState("selected", !clickEdge.hasState("selected"));
vm.currentFocus = "edge";
this.updateVmData(event);
},
onEdgeRightClick(event) {
let graph = vm.graph
let clickEdge = event.item
let clickEdgeModel = clickEdge.getModel()
let selectedEdges = graph.findAllByState('edge', 'selected')
let graph = vm.graph;
let clickEdge = event.item;
let clickEdgeModel = clickEdge.getModel();
let selectedEdges = graph.findAllByState("edge", "selected");
// 如果当前点击节点不是之前选中的单个节点,才进行下面的处理
if (!(selectedEdges.length === 1 && clickEdgeModel.id === selectedEdges[0].getModel().id)) {
// 先取消所有节点的选中状态
graph.findAllByState('edge', 'selected').forEach(edge => {
edge.setState('selected', false)
})
graph.findAllByState("edge", "selected").forEach(edge => {
edge.setState("selected", false);
});
// 再添加该节点的选中状态
clickEdge.setState('selected', true)
vm.currentFocus = 'edge'
this.updateVmData(event)
clickEdge.setState("selected", true);
vm.currentFocus = "edge";
this.updateVmData(event);
}
let point = { x: event.x, y: event.y }
let point = { x: event.x, y: event.y };
},
onCanvasClick() {
vm.currentFocus = 'canvas'
vm.rightMenuShow = false
vm.currentFocus = "canvas";
vm.rightMenuShow = false;
},
updateVmData(event) {
if (event.item._cfg.type === 'node') {
let self = this
if (event.item._cfg.type === "node") {
// const item = event.item;
// let group = item.getContainer();
// let children = group.get("children");
// for (let i = 0, len = children.length; i < len; i++) {
// const shape = children[i];
// if (shape.get("name") === "collapses") {
// console.log(shape.get("name"),"dkfjg");
// self.graph.updateItem(item, {
// collapsed: true,
// size: [300, 50]
// });
// setTimeout(() => graph.layout(), 100);
// } else if (shape.get("name") === "expands") {
//
// console.log(shape.get("name"),"expands");
// self.graph.updateItem(item, {
// collapsed: false,
// size: [300, 500]
// });
// setTimeout(() => graph.layout(), 100);
// }
// }
// 更新vm的data: selectedNode 和 selectedNodeParams
let clickNode = event.item
if (clickNode.hasState('selected')) {
let clickNodeModel = clickNode.getModel()
vm.selectedNode = clickNode
let nodeAppConfig = { ...vm.nodeAppConfig }
let clickNode = event.item;
// console.log(clickNode)
if (clickNode.hasState("selected")) {
let clickNodeModel = clickNode.getModel();
vm.selectedNode = clickNode;
let nodeAppConfig = { ...vm.nodeAppConfig };
Object.keys(nodeAppConfig).forEach(function(key) {
nodeAppConfig[key] = ''
})
nodeAppConfig[key] = "";
});
vm.selectedNodeParams = {
label: clickNodeModel.label || '',
label: clickNodeModel.label || "",
appConfig: { ...nodeAppConfig, ...clickNodeModel.appConfig }
}
};
}
} else if (event.item._cfg.type === 'edge') {
} else if (event.item._cfg.type === "edge") {
// 更新vm的data: selectedEdge 和 selectedEdgeParams
let clickEdge = event.item
if (clickEdge.hasState('selected')) {
let clickEdgeModel = clickEdge.getModel()
vm.selectedEdge = clickEdge
let edgeAppConfig = { ...vm.edgeAppConfig }
let clickEdge = event.item;
if (clickEdge.hasState("selected")) {
let clickEdgeModel = clickEdge.getModel();
vm.selectedEdge = clickEdge;
let edgeAppConfig = { ...vm.edgeAppConfig };
Object.keys(edgeAppConfig).forEach(function(key) {
edgeAppConfig[key] = ''
})
edgeAppConfig[key] = "";
});
vm.selectedEdgeParams = {
label: clickEdgeModel.label || '',
label: clickEdgeModel.label || "",
appConfig: { ...edgeAppConfig, ...clickEdgeModel.appConfig }
}
};
}
}
}
}
}
};
const isInBBox = (point, bbox) => {
const {
x,
y
} = point;
const {
minX,
minY,
maxX,
maxY
} = bbox;
return x < maxX && x > minX && y > minY && y < maxY;
};

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/16
* @description: edit mode: 通过拖拽节点上的锚点添加连线
*/
import utils from '../utils'
@ -100,7 +100,7 @@ export default {
x: event.x,
y: event.y
},
type: self.graph.$C.edge.type || 'cc-line',
type: self.graph.$C.edge.type || 'top-line',
style: G6.Util.mix({}, themeStyle.edgeStyle.default, self.graph.$C.edge.style)
})
self.drawEdge.isMoving = true

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/16
* @description: edit mode: 鼠标拖动节点的交互(记录拖拽前后的数据用于撤销重做)
*/

View File

@ -1,25 +1,45 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/16
* @description: edit mode: 悬浮交互
*/
// 用来获取调用此js的vue组件实例this
let vm = null;
const sendThis = (_this) => {
vm = _this;
};
export default {
name: 'hover-event-edit',
sendThis, // 暴露函数
name: "hover-event-edit",
options: {
getEvents() {
return {
'node:mouseover': 'onNodeHover',
'node:mouseout': 'onNodeOut'
}
"node:mouseover": "onNodeHover",
"node:mouseout": "onNodeOut",
};
},
onNodeHover(event) {
let hoverNode = event.item
hoverNode.setState('hover', true)
let graph = vm.graph;
let hoverNode = event.item;
const name = event.shape.get("name");
const item = event.item;
if (name && name.startsWith("item")) {
graph.updateItem(item, {
selectedIndex: Number(name.split("-")[1])
});
} else {
graph.updateItem(item, {
selectedIndex: NaN
});
}
// console.log(item);
hoverNode.setState("hover", true);
},
onNodeOut(event) {
let hoverNode = event.item
hoverNode.setState('hover', false)
let hoverNode = event.item;
hoverNode.setState("hover", false);
}
}
}
};

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/16
* @description: register behaviors
*/

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/16
* @description: edit mode: 键盘事件的交互主要是删除节点和连线(记录删除前后的数据用于撤销重做)
*/

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/16
* @description: 线条的后期设置
*/

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/16
* @description: 配置
*/

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/18
* @description: 线公共方法
*/

View File

@ -1,13 +1,13 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/18
* @description: register edges
*/
import ccLine from './cc-line'
import ccBrokenline from './cc-brokenline'
import ccPolyline from './cc-polyline'
import ccCubic from './cc-cubic'
import ccLine from './top-line'
import ccBrokenline from './top-brokenline'
import ccPolyline from './top-polyline'
import ccCubic from './top-cubic'
const obj = {
ccLine,

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/10/22
* @description: 折线
*/
@ -12,7 +12,7 @@ import theme from '../theme'
* 现实现方法参考 https://g6.antv.vision/zh/examples/shape/customEdge#customPolyline
*/
export default {
name: 'cc-brokenline',
name: 'top-brokenline',
extendName: 'line',
options: {
...base,

View File

@ -1,13 +1,13 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/18
* @description: 曲线
*/
import base from './base'
export default {
name: 'cc-cubic',
name: 'top-cubic',
extendName: 'cubic',
options: {
...base

View File

@ -1,13 +1,13 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/18
* @description: 直线
*/
import base from './base'
export default {
name: 'cc-line',
name: 'top-line',
extendName: 'line',
options: {
...base

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/18
* @description: 多段线
*/
@ -8,7 +8,7 @@ import base from './base'
import { polylineFinding } from './polyline-finding'
export default {
name: 'cc-polyline',
name: 'top-polyline',
extendName: 'single-edge',
options: {
...base,

View File

@ -0,0 +1,128 @@
/**
* @author: clay
* @data: 2021/5/12 0:05
* @email: clay@hchyun.com
* @description: node
*/
export default {
name: 'top-table',
extendName: 'table',
options:{
draw(cfg, group) {
//todo 画线
const edge = group.cfg.item;
const sourceNode = edge.getSource().getModel();
const targetNode = edge.getTarget().getModel();
const sourceIndex = sourceNode.attrs.findIndex(
(e) => e.key === cfg.sourceKey
);
const sourceStartIndex = sourceNode.startIndex || 0;
let sourceY = 15;
if (!sourceNode.collapsed && sourceIndex > sourceStartIndex - 1) {
sourceY = 30 + (sourceIndex - sourceStartIndex + 0.5) * 30;
sourceY = Math.min(sourceY, 300);
}
const targetIndex = targetNode.attrs.findIndex(
(e) => e.key === cfg.targetKey
);
const targetStartIndex = targetNode.startIndex || 0;
let targetY = 15;
if (!targetNode.collapsed && targetIndex > targetStartIndex - 1) {
targetY = (targetIndex - targetStartIndex + 0.5) * 30 + 30;
targetY = Math.min(targetY, 300);
}
const startPoint = {
...cfg.startPoint
};
const endPoint = {
...cfg.endPoint
};
startPoint.y = startPoint.y + sourceY;
endPoint.y = endPoint.y + targetY;
let shape;
if (sourceNode.id !== targetNode.id) {
shape = group.addShape("path", {
attrs: {
stroke: "#5B8FF9",
path: [
["M", startPoint.x, startPoint.y],
[
"C",
endPoint.x / 3 + (2 / 3) * startPoint.x,
startPoint.y,
endPoint.x / 3 + (2 / 3) * startPoint.x,
endPoint.y,
endPoint.x,
endPoint.y,
],
],
endArrow: true,
},
name: "path-shape",
});
} else if (!sourceNode.collapsed) {
let gap = Math.abs((startPoint.y - endPoint.y) / 3);
if (startPoint["index"] === 1) {
gap = -gap;
}
shape = group.addShape("path", {
attrs: {
stroke: "#5B8FF9",
path: [
["M", startPoint.x, startPoint.y],
[
"C",
startPoint.x - gap,
startPoint.y,
startPoint.x - gap,
endPoint.y,
startPoint.x,
endPoint.y,
],
],
endArrow: true,
},
name: "path-shape",
});
}
return shape;
},
afterDraw(cfg, group) {
const labelCfg = cfg.labelCfg || {};
const edge = group.cfg.item;
const sourceNode = edge.getSource().getModel();
const targetNode = edge.getTarget().getModel();
if (sourceNode.collapsed && targetNode.collapsed) {
return;
}
const path = group.find(
(element) => element.get("name") === "path-shape"
);
const labelStyle = Util.getLabelPosition(path, 0.5, 0, 0, true);
const label = group.addShape("text", {
attrs: {
...labelStyle,
text: cfg.label || '',
fill: "#000",
textAlign: "center",
stroke: "#fff",
lineWidth: 1,
},
});
label.rotateAtStart(labelStyle.rotate);
},
}
}

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/05
* @description: 图的布局方式/图的初始化
*/
@ -33,7 +33,7 @@ const initGraph = {
// height: options.height
// },
defaultNode: {
type: 'top-rect',
type: 'cc-rect',
labelCfg: {
position: 'bottom'
}

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/05
* @description: 节点基础方法
*/

View File

@ -1,21 +0,0 @@
/**
* @author: clay
* @data: 2021/5/10
* @description: 节点基础方法
*/
import utils from '../utils'
export default {
setState(name, value, item) {
// 设置节点状态
utils.node.setState(name, value, item)
// 设置锚点状态
utils.anchor.setState(name, value, item)
},
// 绘制后附加锚点
afterDraw(cfg, group) {
// 绘制锚点
utils.anchor.draw(cfg, group)
}
}

View File

@ -1,15 +1,17 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/05
* @description: register nodes
*/
import ccRect from './top-rect'
import ccImage from './top-image'
import Rect from './top-rect'
import Image from './top-image'
import ErTable from './top-ertable'
const obj = {
ccRect,
ccImage
Rect,
Image,
ErTable
}
export default {

View File

@ -0,0 +1,243 @@
/**
* @author: clay
* @data: 2019/07/05
* @description: er数据库表基本图像
*/
import utils from '../utils'
export default {
name: "top-ertable",
extendName: "ertable",
options: {
setState(name, value, item,group) {
// 设置节点状态
utils.node.setState(name, value, item,group);
// 设置锚点状态
utils.anchor.setState(name, value, item);
//设置收缩状态
utils.collapse.setState(item)
},
draw(cfg, group) {
const width = 250;
const height = 316;
const itemCount = 10;
const itemHeight = 30;
const boxStyle = {
stroke: "#096DD9",
radius: 4
};
const {
attrs = [],
startIndex = 0,
selectedIndex,
collapsed,
icon
} = cfg;
const list = attrs;
const afterList = list.slice(
Math.floor(startIndex),
Math.floor(startIndex + itemCount - 1)
);
const offsetY = (0.5 - (startIndex % 1)) * itemHeight + 30;
group.addShape("rect", {
attrs: {
fill: boxStyle.stroke,
height: 30,
width,
radius: [boxStyle.radius, boxStyle.radius, 0, 0]
},
draggable: true
});
let fontLeft = 12;
if (icon && icon.show !== false) {
group.addShape("image", {
attrs: {
x: 8,
y: 8,
height: 16,
width: 16,
...icon
}
});
fontLeft += 18;
}
group.addShape("text", {
attrs: {
y: 22,
x: fontLeft,
fill: "#fff",
text: cfg.name,
fontSize: 12,
fontWeight: 500
}
});
group.addShape("rect", {
attrs: {
x: 0,
y: collapsed ? 30 : 300,
height: 15,
width,
fill: "#eee",
radius: [0, 0, boxStyle.radius, boxStyle.radius],
cursor: "pointer"
},
name: collapsed ? "expand" : "collapse"
});
group.addShape("text", {
attrs: {
x: width / 2 - 6,
y: (collapsed ? 30 : 300) + 12,
text: collapsed ? "+" : "-",
width,
fill: "#000",
radius: [0, 0, boxStyle.radius, boxStyle.radius],
cursor: "pointer"
},
name: collapsed ? "expands" : "collapses"
});
const keyshape = group.addShape("rect", {
attrs: {
x: 0,
y: 0,
width,
height: collapsed ? 45 : height,
...boxStyle
},
draggable: true
});
if (collapsed) {
return keyshape;
}
const listContainer = group.addGroup({});
listContainer.setClip({
type: "rect",
attrs: {
x: -8,
y: 30,
width: width + 16,
height: 300 - 30
}
});
listContainer.addShape({
type: "rect",
attrs: {
x: 1,
y: 30,
width: width - 2,
height: 300 - 30,
fill: "#fff"
},
draggable: true
});
if (list.length > itemCount) {
const barStyle = {
width: 4,
padding: 0,
boxStyle: {
stroke: "#00000022"
},
innerStyle: {
fill: "#00000022"
}
};
listContainer.addShape("rect", {
attrs: {
y: 30,
x: width - barStyle.padding - barStyle.width,
width: barStyle.width,
height: height - 30,
...barStyle.boxStyle
}
});
const indexHeight =
afterList.length > itemCount ?
(afterList.length / list.length) * height :
10;
listContainer.addShape("rect", {
attrs: {
y: 30 +
barStyle.padding +
(startIndex / list.length) * (height - 30),
x: width - barStyle.padding - barStyle.width,
width: barStyle.width,
height: Math.min(height, indexHeight),
...barStyle.innerStyle
}
});
}
if (afterList) {
afterList.forEach((e, i) => {
const isSelected =
Math.floor(startIndex) + i === Number(selectedIndex);
let {
key = "", type
} = e;
if (type) {
key += " - " + type;
}
const label = key.length > 26 ? key.slice(0, 24) + "..." : key;
listContainer.addShape("rect", {
attrs: {
x: 1,
y: i * itemHeight - itemHeight / 2 + offsetY,
width: width - 4,
height: itemHeight,
radius: 2,
lineWidth: 1
// cursor: "pointer"
},
name: `item-${Math.floor(startIndex) + i}-content`,
draggable: true
});
if (!cfg.hideDot) {
// todo 左侧锚点
utils.anchor.erDraw(group, label, 0, i * itemHeight + offsetY, i, itemHeight, offsetY);
//todo 右侧锚点
utils.anchor.erDraw(group, label, width, i * itemHeight + offsetY, i, itemHeight, offsetY);
}
listContainer.addShape("text", {
attrs: {
name:'label',
x: 12,
y: i * itemHeight + offsetY + 6,
text: label,
fontSize: 12,
fill: "#000",
fontFamily: "Avenir,-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Helvetica Neue,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol",
full: e,
fontWeight: isSelected ? 500 : 100,
cursor: "pointer"
},
name: `item-${Math.floor(startIndex) + i}`
});
});
}
return keyshape;
},
getAnchorPoints() {
return [
[0, 0],
[1, 0]
];
}
}
};

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/05
* @description: 图片节点
*/

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/05
* @description: 矩形节点
*/

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/07/05
* @description: install 3rd plugins
*/

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/11/20
* @description: dark style
*/

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/15
* @description: default style
*/
@ -10,8 +10,8 @@ export default {
default: {
stroke: '#CED4D9',
fill: 'transparent',
shadowOffsetX: 0,
shadowOffsetY: 4,
// shadowOffsetX: 0,
// shadowOffsetY: 4,
shadowBlur: 10,
shadowColor: 'rgba(13, 26, 38, 0.08)',
lineWidth: 1,
@ -20,9 +20,10 @@ export default {
},
selected: {
shadowColor: '#ff240b',
shadowBlur: 4,
shadowOffsetX: 0,
shadowOffsetY: 0
shadowBlur: 2,
// shadowOffsetX: 0,
// shadowOffsetY: 0,
// fontSize:'50'
// shadowColor: '#626262',
// shadowBlur: 8,
// shadowOffsetX: -1,

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/15
* @description: 编辑器主题样式 - 节点连线的预设样式
*/

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/11/21
* @description: office style
*/

View File

@ -2,12 +2,12 @@
<div class="toolbar">
<div class="left">
<!--<el-checkbox class="edge-enabled" title="连线模式" @change="$parent.enableEdgeHandler"></el-checkbox>-->
<cc-dropdown
class="edge-shape"
:dropdown-items="$parent.edgeShapeList"
@change="$parent.changeEdgeShapeHandler"
>
</cc-dropdown>
<!-- <cc-dropdown-->
<!-- class="edge-shape"-->
<!-- :dropdown-items="$parent.edgeShapeList"-->
<!-- @change="$parent.changeEdgeShapeHandler"-->
<!-- >-->
<!-- </cc-dropdown>-->
</div>
<div class="center">
<div class="graph-ops">
@ -29,6 +29,14 @@
<i class="iconfont icon-actualsize" title="实际尺寸" @click="$parent.resetZoomHandler"></i>
<span class="separator"></span>
<i class="iconfont icon-roi-select" id="multi-select" title="框选" @click="$parent.multiSelectHandler"></i>
<div v-if="$parent.$data.graphMode === 'edit'" class="iconfont zx"><cc-dropdown
class="edge-shape"
:dropdown-items="$parent.edgeShapeList"
@change="$parent.changeEdgeShapeHandler"
>
</cc-dropdown></div>
</div>
</div>
<div class="right">
@ -58,6 +66,9 @@ export default {
</script>
<style lang="scss" scoped>
.zx{
float: right;
}
.toolbar {
/*z-index: 3;*/
/*width: 100%;*/

View File

@ -16,7 +16,7 @@
<i class="iconfont icon-fit" title="适应画布" @click="$parent.autoZoomHandler"></i>
<i class="iconfont icon-actualsize" title="实际尺寸" @click="$parent.resetZoomHandler"></i>
<span class="separator"></span>
<checkbox @change="$parent.enableMinimapHandler">导航器</checkbox>
<cc-checkbox @change="$parent.enableMinimapHandler">导航器</cc-checkbox>
<cc-dropdown :dropdown-items="refreshOptions" @change="toggleAutoRefresh"></cc-dropdown>
</div>
</div>
@ -33,7 +33,7 @@ import { Checkbox, Button, Dropdown } from '../../elements'
export default {
name: 'ToolbarEdit',
components: {
'checkbox': Checkbox,
'cc-checkbox': Checkbox,
'cc-button': Button,
'cc-dropdown': Dropdown
},
@ -159,7 +159,7 @@ export default {
margin: 0 8px 0 12px;
}
.checkbox {
.cc-checkbox {
margin: 0 6px;
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/15
* @description: draw anchor
*/
@ -31,6 +31,7 @@ export default function(cfg, group) {
name: 'markerBg-shape'
})
// 添加锚点Marker形状
// eslint-disable-next-line no-unused-vars
let anchorShape = group.addShape('marker', {
id: id + '_anchor_' + i,
attrs: {

View File

@ -0,0 +1,48 @@
import theme from '../../theme'
export default function(group,label,x,y,i,itemHeight,offsetY) {
const themeStyle = theme.defaultStyle // todo...先使用默认主题,后期可能增加其它风格的主体
let anchorBgShape = group.addShape('marker', {
id: label+ '_anchor_bg_lift_' + i,
attrs: {
name: 'anchorBg',
x: x,
y: y,
...themeStyle.anchorBgStyle.default
},
draggable: false,
name: 'markerBg-shape'
})
let anchorShape = group.addShape('marker', {
id: label+ '_anchor_bg_lift_' + i,
attrs: {
name: 'anchor',
x: x,
y: y,
...themeStyle.anchorStyle.default
},
draggable: false,
name: 'markerBg-shape'
})
anchorShape.on('mouseenter', function() {
anchorBgShape.attr({
...themeStyle.anchorBgStyle.active
})
})
anchorShape.on('mouseleave', function() {
anchorBgShape.attr({
...themeStyle.anchorBgStyle.inactive
})
})
}

View File

@ -1,15 +1,17 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/15
* @description: anchor
*/
import draw from './draw'
import erDrawLeft from './er-draw'
import setState from './set-state'
import update from './update'
export default {
draw,
setState,
update
update,
erDraw: erDrawLeft,
}

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/15
* @description: set anchor state
*/
@ -8,6 +8,7 @@ import theme from '../../theme'
export default function(name, value, item) {
const themeStyle = theme.defaultStyle // todo...先使用默认主题,后期可能增加其它风格的主体
// console.log(item)
if (name === 'hover') {
let group = item.getContainer()
let children = group.get('children')

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/15
* @description: update anchor
*/

View File

@ -0,0 +1,11 @@
/**
* @author: clay
* @data: 2021/5/11 17:28
* @email: clay@hchyun.com
* @description: node
*/
import setState from './set-state'
export default {
setState
}

View File

@ -0,0 +1,57 @@
/**
* @author: clay
* @data: 2021/5/11 17:33
* @email: clay@hchyun.com
* @description: node
*/
export default function(e){
e.preventDefault();
const {
graph
} = this;
const nodes = graph.getNodes().filter((n) => {
const bbox = n.getBBox();
return isInBBox(graph.getPointByClient(e.clientX, e.clientY), bbox);
});
if (nodes) {
nodes.forEach((node) => {
const model = node.getModel();
if (model.attrs.length < 9) {
return;
}
const idx = model.startIndex || 0;
let startX = model.startX || 0.5;
let startIndex = idx + e.deltaY * 0.02;
startX -= e.deltaX;
if (startIndex < 0) {
startIndex = 0;
}
if (startX > 0) {
startX = 0;
}
if (startIndex > model.attrs.length - 1) {
startIndex = model.attrs.length - 1;
}
graph.update(node, {
startIndex,
startX,
});
});
}
}
const isInBBox = (point, bbox) => {
const {
x,
y
} = point;
const {
minX,
minY,
maxX,
maxY
} = bbox;
return x < maxX && x > minX && y > minY && y < maxY;
};

View File

@ -0,0 +1,33 @@
/**
* @author: clay
* @data: 2021/5/11 17:28
* @email: clay@hchyun.com
* @description: node
*/
export default function(e){
const {
graph
} = this;
const {
y
} = e;
const item = e.item;
const shape = e.shape;
if (!item) {
return;
}
if (shape.get("name") === "collapse") {
graph.updateItem(item, {
collapsed: true,
size: [300, 50],
});
setTimeout(() => graph.layout(), 100);
} else if (shape.get("name") === "expand") {
graph.updateItem(item, {
collapsed: false,
size: [300, 500],
});
setTimeout(() => graph.layout(), 100);
}
}

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/15
* @description: edge
*/

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/15
* @description: set edge state
*/

View File

@ -1,12 +1,13 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/15
* @description: graph utils
*/
import node from './node'
import anchor from './anchor'
import edge from './edge'
import collapse from './collapse'
/**
* 比较两个对象的内容是否相同两个对象的键值都相同
@ -58,6 +59,7 @@ export default {
node,
anchor,
edge,
collapse,
// 通用工具类函数
isObjectValueEqual,
generateUUID

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/15
* @description: node
*/

View File

@ -1,6 +1,6 @@
/**
* @author: clay
* @data: 2021/5/10
* @data: 2019/08/15
* @description: set node state
*/
@ -18,9 +18,10 @@ export default function(name, value, item) {
}
} else if (name === 'selected') {
if (value) {
shape.attr(themeStyle.nodeStyle.selected)
group.attr(themeStyle.nodeStyle.selected)
} else {
shape.attr(themeStyle.nodeStyle.default)
group.attr(themeStyle.nodeStyle.default)
}
}
}

View File

@ -1,5 +1,5 @@
/**
* Created by clay on 2021/10/14
* Created by clay on 2019/10/14
* Description: common utils
*/