Commit fc33f3ce authored by 刘殿昕's avatar 刘殿昕

Merge branch 'ldx' into dev

parents 70d4e623 4a15a472
<!--
* User: CHT
* Date: 2020/6/28
* Time: 17:48
-->
<template>
<div>
<div class="super-flow-demo1">
<div class="node-container">
<span
class="node-item"
v-for="(item, index) in nodeItemList"
:key="index"
@mousedown="evt => nodeItemMouseDown(evt, item.value)"
@click="clickItem">
{{item.label}}
</span>
</div>
<div
class="flow-container"
ref="flowContainer">
<super-flow
ref="superFlow"
:graph-menu="graphMenu"
:node-menu="nodeMenu"
:link-menu="linkMenu"
:link-base-style="linkBaseStyle"
:link-style="linkStyle"
:link-desc="linkDesc">
<template v-slot:node="{meta}">
<div
class="flow-node">
{{meta.name}}
</div>
</template>
</super-flow>
</div>
</div>
<el-dialog
:title="drawerConf.title"
:visible.sync="drawerConf.visible"
:close-on-click-modal="false"
width="500px">
<el-form
v-show="drawerConf.type === drawerType.node"
ref="nodeSetting"
:model="nodeSetting">
<el-form-item
label="节点名称"
prop="name">
<el-input
v-model="nodeSetting.name"
placeholder="请输入节点名称"
maxlength="30">
</el-input>
</el-form-item>
<el-form-item
label="节点描述"
prop="desc">
<el-input
v-model="nodeSetting.desc"
placeholder="请输入节点描述"
maxlength="30">
</el-input>
</el-form-item>
</el-form>
<el-form
v-show="drawerConf.type === drawerType.link"
ref="linkSetting"
:model="linkSetting">
<el-form-item
label="连线描述"
prop="desc">
<el-input
v-model="linkSetting.desc"
placeholder="请输入连线描述">
</el-input>
</el-form-item>
</el-form>
<span
slot="footer"
class="dialog-footer">
<el-button
@click="drawerConf.cancel">
取 消
</el-button>
<el-button
type="primary"
@click="settingSubmit">
确 定
</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
const drawerType = {
node: 0,
link: 1
}
export default {
data() {
return {
drawerType,
drawerConf: {
title: '',
visible: false,
type: null,
info: null,
open: (type, info) => {
const conf = this.drawerConf
conf.visible = true
conf.type = type
conf.info = info
if (conf.type === drawerType.node) {
conf.title = '节点'
if (this.$refs.nodeSetting) this.$refs.nodeSetting.resetFields()
this.$set(this.nodeSetting, 'name', info.meta.name)
this.$set(this.nodeSetting, 'desc', info.meta.desc)
} else {
conf.title = '连线'
if (this.$refs.linkSetting) this.$refs.linkSetting.resetFields()
this.$set(this.linkSetting, 'desc', info.meta ? info.meta.desc : '')
}
},
cancel: () => {
this.drawerConf.visible = false
if (this.drawerConf.type === drawerType.node) {
this.$refs.nodeSetting.clearValidate()
} else {
this.$refs.linkSetting.clearValidate()
}
}
},
linkSetting: {
desc: ''
},
nodeSetting: {
name: '',
desc: ''
},
dragConf: {
isDown: false,
isMove: false,
offsetTop: 0,
offsetLeft: 0,
clientX: 0,
clientY: 0,
ele: null,
info: null
},
nodeItemList: [
{
label: '节点1',
value: {
width: 120,
height: 40,
meta: {
label: '1',
name: '1'
}
}
},
{
label: '节点2',
value: {
width: 120,
height: 40,
meta: {
label: '2',
name: '2'
}
}
},
{
label: '节点3',
value: {
width: 120,
height: 40,
meta: {
label: '3',
name: '3'
}
}
},
{
label: '节点4',
value: {
width: 120,
height: 40,
meta: {
label: '4',
name: '4'
}
}
}
],
graphMenu: [
[
{
// 选项 label
label: '节点1',
// 选项是否禁用
disable(graph) {
return !!graph.nodeList.find(node => node.meta.label === '1')
},
// 选项选中后回调函数
selected(graph, coordinate) {
graph.addNode({
width: 120,
height: 40,
coordinate,
meta: {
label: '1',
name: '1'
}
})
}
},
{
label: '节点2',
selected(graph, coordinate) {
graph.addNode({
width: 120,
height: 40,
coordinate,
meta: {
label: '2',
name: '2'
}
})
}
},
{
label: '节点3',
selected(graph, coordinate) {
graph.addNode({
width: 120,
height: 40,
coordinate,
meta: {
label: '3',
name: '3'
}
})
}
}
],
[
{
label: '节点4',
selected(graph, coordinate) {
graph.addNode({
width: 120,
height: 40,
coordinate,
meta: {
label: '4',
name: '4'
}
})
}
}
],
[
{
label: '全选',
selected: graph => {
graph.selectAll()
}
}
]
],
nodeMenu: [
[
{
label: '删除',
selected: node => {
node.remove()
}
},
{
label: '编辑',
selected: node => {
this.drawerConf.open(drawerType.node, node)
}
}
]
],
linkMenu: [
[
{
label: '删除',
selected: link => {
link.remove()
}
},
{
label: '编辑',
selected: link => {
this.drawerConf.open(drawerType.link, link)
}
}
]
],
linkBaseStyle: {
color: '#666666', // line 颜色
hover: '#FF0000', // line hover 的颜色
textColor: '#666666', // line 描述文字颜色
textHover: '#FF0000', // line 描述文字 hover 颜色
font: '14px Arial', // line 描述文字 字体设置 参考 canvas font
dotted: false, // 是否是虚线
lineDash: [4, 4], // 虚线时生效
background: 'rgba(255,255,255,0.6)' // 描述文字背景色
},
fontList: [
'14px Arial',
'italic small-caps bold 12px arial'
]
}
},
mounted() {
document.addEventListener('mousemove', this.docMousemove)
document.addEventListener('mouseup', this.docMouseup)
this.$once('hook:beforeDestroy', () => {
document.removeEventListener('mousemove', this.docMousemove)
document.removeEventListener('mouseup', this.docMouseup)
})
},
methods: {
flowNodeClick(meta) {
console.log(this.$refs.superFlow.graph)
},
linkStyle(link) {
return {
// hover: '#FF00FF'
}
},
linkDesc(link) {
return link.meta ? link.meta.desc : ''
},
settingSubmit() {
const conf = this.drawerConf
if (this.drawerConf.type === drawerType.node) {
if (!conf.info.meta) conf.info.meta = {}
Object.keys(this.nodeSetting).forEach(key => {
this.$set(conf.info.meta, key, this.nodeSetting[key])
})
this.$refs.nodeSetting.resetFields()
} else {
if (!conf.info.meta) conf.info.meta = {}
Object.keys(this.linkSetting).forEach(key => {
this.$set(conf.info.meta, key, this.linkSetting[key])
})
this.$refs.linkSetting.resetFields()
}
conf.visible = false
},
docMousemove({clientX, clientY}) {
const conf = this.dragConf
if (conf.isMove) {
conf.ele.style.top = clientY - conf.offsetTop + 'px'
conf.ele.style.left = clientX - conf.offsetLeft + 'px'
} else if (conf.isDown) {
// 鼠标移动量大于 5 时 移动状态生效
conf.isMove =
Math.abs(clientX - conf.clientX) > 5
|| Math.abs(clientY - conf.clientY) > 5
}
},
docMouseup({clientX, clientY}) {
const conf = this.dragConf
conf.isDown = false
if (conf.isMove) {
const {
top,
right,
bottom,
left
} = this.$refs.flowContainer.getBoundingClientRect()
// 判断鼠标是否进入 flow container
if (
clientX > left
&& clientX < right
&& clientY > top
&& clientY < bottom
) {
// 获取拖动元素左上角相对 super flow 区域原点坐标
const coordinate = this.$refs.superFlow.getMouseCoordinate(
clientX - conf.offsetLeft,
clientY - conf.offsetTop
)
// 添加节点
this.$refs.superFlow.addNode({
coordinate,
...conf.info
})
}
conf.isMove = false
}
if (conf.ele) {
conf.ele.remove()
conf.ele = null
}
},
nodeItemMouseDown(evt, info) {
const {
clientX,
clientY,
currentTarget
} = evt
const {
top,
left
} = evt.currentTarget.getBoundingClientRect()
const conf = this.dragConf
const ele = currentTarget.cloneNode(true)
Object.assign(this.dragConf, {
offsetLeft: clientX - left,
offsetTop: clientY - top,
clientX: clientX,
clientY: clientY,
info,
ele,
isDown: true
})
ele.id = Math.random()
ele.style.position = 'fixed'
ele.style.margin = '0'
ele.style.top = clientY - conf.offsetTop + 'px'
ele.style.left = clientX - conf.offsetLeft + 'px'
this.$el.appendChild(this.dragConf.ele)
},
clickItem(item) {
console.log(item)
}
}
}
</script>
<style lang="less">
.link-base-style-form {
.el-form-item {
margin-bottom : 12px;
}
padding-bottom : 20px;
border-bottom : 1px solid #DCDCDC;
}
.super-flow-demo1 {
margin-top : 20px ;
width : 100%;
height : 800px;
background-color : #f5f5f5;
@list-width : 200px;
> .node-container {
width : @list-width;
float : left;
height : 100%;
text-align : center;
background-color : #FFFFFF;
}
> .flow-container {
width : calc(100% - @list-width);
float : left;
height : 100%;
overflow : hidden;
}
.super-flow__node {
.flow-node {
width : 100%;
height : 100%;
line-height : 40px;
padding : 0 6px;
font-size : 12px;
}
}
}
.node-item {
@node-item-height : 30px;
font-size : 14px;
display : inline-block;
height : @node-item-height;
width : 120px;
margin-top : 20px;
background-color : #FFFFFF;
line-height : @node-item-height;
box-shadow : 1px 1px 4px rgba(0, 0, 0, 0.3);
cursor : pointer;
user-select : none;
text-align : center;
z-index : 6;
&:hover {
box-shadow : 1px 1px 8px rgba(0, 0, 0, 0.4);
}
}
</style>
\ No newline at end of file
<!--
* User: CHT
* Date: 2020/6/28
* Time: 17:48
-->
<template>
<div>
<div>
<el-button @click="getData">获取参数</el-button>
</div>
<div class="super-flow-demo1">
<div class="node-container">
<p class="label_head">节点类型</p>
<p class="label_explanation">请拖拽添加到流程中</p>
<el-input-number
v-model="scale_num"
@change="handleChange"
:step="10"
:step-strictly="true"
:min="50"
:max="150"
label="描述文字"
></el-input-number>
<span
class="node-item"
v-for="(item, index) in nodeItemList"
:key="index"
@mousedown="evt => nodeItemMouseDown(evt, item.value)"
>{{item.label}}</span>
</div>
<div class="flow-container" :class="`scale${scale_num}`" ref="flowContainer">
<super-flow
ref="superFlow"
:node-list="nodeList"
:link-list="linkList"
:link-menu="linkMenu"
:link-base-style="linkBaseStyle"
:link-style="linkStyle"
:link-desc="linkDesc"
:origin="origin"
>
<template v-slot:node="{meta}">
<div
:class="{'flow-node-begin': meta.type == 'begin', 'flow-node-end': meta.type == 'end', 'flow-node-default': meta.type == 'default'}"
:id="meta.id"
@click="clickItem(meta)"
>{{meta.name}}</div>
</template>
</super-flow>
</div>
</div>
</div>
</template>
<script>
const drawerType = {
node: 0,
link: 1,
};
export default {
data() {
return {
scale_num: 100,
origin: [0, 0],
nodeList: [],
linkList: [],
drawerType,
drawerConf: {
title: "",
visible: false,
type: null,
info: null,
open: (type, info) => {
const conf = this.drawerConf;
conf.visible = true;
conf.type = type;
conf.info = info;
if (conf.type === drawerType.node) {
conf.title = "节点";
if (this.$refs.nodeSetting) this.$refs.nodeSetting.resetFields();
this.$set(this.nodeSetting, "name", info.meta.name);
this.$set(this.nodeSetting, "desc", info.meta.desc);
} else {
conf.title = "连线";
if (this.$refs.linkSetting) this.$refs.linkSetting.resetFields();
this.$set(
this.linkSetting,
"desc",
info.meta ? info.meta.desc : ""
);
}
},
cancel: () => {
this.drawerConf.visible = false;
if (this.drawerConf.type === drawerType.node) {
this.$refs.nodeSetting.clearValidate();
} else {
this.$refs.linkSetting.clearValidate();
}
},
},
linkSetting: {
desc: "",
},
nodeSetting: {
name: "",
desc: "",
},
dragConf: {
isDown: false,
isMove: false,
offsetTop: 0,
offsetLeft: 0,
clientX: 0,
clientY: 0,
ele: null,
info: null,
},
nodeItemList: [
{
label: "开始",
value: {
width: 120,
height: 40,
meta: {
label: "开始开始开始开始开始",
name: "开始开始开始开始开始",
type: "begin",
},
},
},
{
label: "结束",
value: {
width: 120,
height: 40,
meta: {
label: "结束",
name: "结束",
type: "end",
},
},
},
{
label: "普通节点",
value: {
width: 120,
height: 40,
meta: {
label: "普通节点",
name: "普通节点",
type: "default",
},
},
},
],
linkMenu: [
[
{
label: "删除",
selected: (link) => {
console.log(link);
link.remove();
},
},
{
label: "编辑",
selected: (link) => {
this.drawerConf.open(drawerType.link, link);
},
},
],
],
linkBaseStyle: {
color: "#666666", // line 颜色
hover: "#FF0000", // line hover 的颜色
textColor: "#666666", // line 描述文字颜色
textHover: "#FF0000", // line 描述文字 hover 颜色
font: "14px Arial", // line 描述文字 字体设置 参考 canvas font
dotted: false, // 是否是虚线
lineDash: [4, 4], // 虚线时生效
background: "rgba(255,255,255,0.6)", // 描述文字背景色
},
};
},
mounted() {
document.addEventListener("mousemove", this.docMousemove);
document.addEventListener("mouseup", this.docMouseup);
this.$once("hook:beforeDestroy", () => {
document.removeEventListener("mousemove", this.docMousemove);
document.removeEventListener("mouseup", this.docMouseup);
});
},
methods: {
linkStyle(link) {
return {
// hover: '#FF00FF'
};
},
linkDesc(link) {
return link.meta ? link.meta.desc : "";
},
docMousemove({ clientX, clientY }) {
const conf = this.dragConf;
if (conf.isMove) {
conf.ele.style.top = clientY - conf.offsetTop + "px";
conf.ele.style.left = clientX - conf.offsetLeft + "px";
} else if (conf.isDown) {
// 鼠标移动量大于 5 时 移动状态生效
conf.isMove =
Math.abs(clientX - conf.clientX) > 5 ||
Math.abs(clientY - conf.clientY) > 5;
}
},
docMouseup({ clientX, clientY }) {
const conf = this.dragConf;
conf.isDown = false;
if (conf.isMove) {
const {
top,
right,
bottom,
left,
} = this.$refs.flowContainer.getBoundingClientRect();
// 判断鼠标是否进入 flow container
if (
clientX > left &&
clientX < right &&
clientY > top &&
clientY < bottom
) {
} else if (clientX <= left) {
clientX = left;
} else if (clientX >= right) {
clientX = right;
} else if (clientY <= top) {
clientY = top;
} else if (clientY >= bottom) {
clientY = bottom;
}
// 获取拖动元素左上角相对 super flow 区域原点坐标
console.log(top, right, bottom, left, clientX, clientY);
const coordinate = this.$refs.superFlow.getMouseCoordinate(
clientX - conf.offsetLeft,
clientY - conf.offsetTop
);
// 添加节点
this.$refs.superFlow.addNode({
coordinate,
...conf.info,
});
conf.isMove = false;
}
if (conf.ele) {
conf.ele.remove();
conf.ele = null;
}
},
nodeItemMouseDown(evt, info) {
info.meta.id = parseInt(Math.random() * 1000 * 1000);
console.log(evt, info);
const { clientX, clientY, currentTarget } = evt;
const { top, left } = evt.currentTarget.getBoundingClientRect();
const conf = this.dragConf;
const ele = currentTarget.cloneNode(true);
Object.assign(this.dragConf, {
offsetLeft: clientX - left,
offsetTop: clientY - top,
clientX: clientX,
clientY: clientY,
info,
ele,
isDown: true,
});
ele.style.position = "fixed";
ele.style.margin = "0";
ele.style.top = clientY - conf.offsetTop + "px";
ele.style.left = clientX - conf.offsetLeft + "px";
this.$el.appendChild(this.dragConf.ele);
},
clickItem(item) {
console.log(item);
},
getData() {
console.log(this.$refs.superFlow.toJSON());
},
handleChange() {},
},
};
</script>
<style lang="less">
.link-base-style-form {
.el-form-item {
margin-bottom: 12px;
}
padding-bottom: 20px;
border-bottom: 1px solid #dcdcdc;
}
.super-flow-demo1 {
margin-top: 20px;
width: 100%;
height: 800px;
background-color: #f5f5f5;
@list-width: 200px;
> .node-container {
width: @list-width;
position: absolute;
z-index: 2;
left: 0;
height: 400px;
text-align: center;
background-color: #ffffff;
.label_head {
font-weight: bold;
font-size: 18px;
text-align: center;
padding: 20px 0;
}
.label_explanation {
font-size: 16px;
text-align: center;
padding-bottom: 5px;
}
}
> .flow-container {
width: 100%;
float: left;
height: 100%;
overflow: hidden;
}
.super-flow__node {
box-shadow: none;
border: none;
background-color: transparent;
.flow-node-begin {
width: 100%;
height: 100%;
line-height: 36px;
padding: 0 6px;
font-size: 12px;
text-align: center;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
border-radius: 8px;
border: 2px solid #444;
&:focus {
border: 2px solid #0f0;
}
}
.flow-node-end {
width: 100%;
line-height: 36px;
padding: 0 6px;
font-size: 12px;
text-align: center;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
border-radius: 8px;
border: 2px solid #f80;
&:focus {
border: 2px solid #0f0;
}
}
.flow-node-default {
width: 100%;
line-height: 36px;
padding: 0 6px;
font-size: 12px;
text-align: center;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
border-radius: 8px;
border: 2px solid #3a9;
&:focus {
border: 2px solid #0f0;
}
}
}
}
.node-item {
@node-item-height: 30px;
font-size: 14px;
display: inline-block;
height: @node-item-height;
width: 120px;
margin-top: 20px;
background-color: #ffffff;
line-height: @node-item-height;
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.3);
cursor: pointer;
user-select: none;
text-align: center;
z-index: 6;
&:hover {
box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.4);
}
&:focus {
background-color: chocolate;
}
}
</style>
<style scoped>
.scale70 {
transform: scale(0.7, 0.7);
}
.scale80 {
transform: scale(0.8, 0.8);
}
.scale90 {
transform: scale(0.9, 0.9);
}
.scale100 {
transform: scale(1, 1);
}
</style>
\ No newline at end of file
<template>
<div class="topo_inner">
<div id="container" ref="conCav" class="canvas"></div>
</div>
</template>
<script>
import G6 from "@antv/g6";
export default {
props: {
datas: {
type: Object,
default: () => {
return {
nodes: [],
edges: [],
};
},
},
namespace: String,
},
data: () => {
return {
options: [
{
value: "default",
label: "default",
},
{
value: "addNode",
label: "addNode",
},
{
value: "addEdge",
label: "addEdge",
},
],
value: "",
graph: null,
};
},
mounted() {
this.getCav();
},
watch: {
datas(val) {},
},
methods: {
getCav() {
/**
* 该案例演示切换交互模式,在不同模式下实现拖动节点、增加节点、增加边的交互行为。
*/
let addedCount = 0;
// Register a custom behavior: add a node when user click the blank part of canvas
G6.registerBehavior("click-add-node", {
// Set the events and the corresponding responsing function for this behavior
getEvents() {
// The event is canvas:click, the responsing function is onClick
return {
"canvas:click": "onClick",
};
},
// Click event
onClick(ev) {
console.log(ev.canvasX, ev.canvasY);
const self = this;
const graph = self.graph;
// Add a new node
graph.addItem("node", {
x: ev.canvasX,
y: ev.canvasY,
id: `node-${addedCount}`, // Generate the unique id
});
addedCount++;
},
});
// Register a custom behavior: click two end nodes to add an edge
G6.registerBehavior("click-add-edge", {
// Set the events and the corresponding responsing function for this behavior
getEvents() {
return {
"node:click": "onClick", // The event is canvas:click, the responsing function is onClick
mousemove: "onMousemove", // The event is mousemove, the responsing function is onMousemove
"edge:click": "onEdgeClick", // The event is edge:click, the responsing function is onEdgeClick
};
},
// The responsing function for node:click defined in getEvents
onClick(ev) {
const self = this;
const node = ev.item;
const graph = self.graph;
// The position where the mouse clicks
const point = { x: ev.x, y: ev.y };
const model = node.getModel();
if (self.addingEdge && self.edge) {
graph.updateItem(self.edge, {
target: model.id,
});
self.edge = null;
self.addingEdge = false;
} else {
// Add anew edge, the end node is the current node user clicks
self.edge = graph.addItem("edge", {
source: model.id,
target: model.id,
});
self.addingEdge = true;
}
},
// The responsing function for mousemove defined in getEvents
onMousemove(ev) {
const self = this;
// The current position the mouse clicks
const point = { x: ev.x, y: ev.y };
if (self.addingEdge && self.edge) {
// Update the end node to the current node the mouse clicks
self.graph.updateItem(self.edge, {
target: point,
});
}
},
// The responsing function for edge:click defined in getEvents
onEdgeClick(ev) {
const self = this;
const currentEdge = ev.item;
if (self.addingEdge && self.edge === currentEdge) {
self.graph.removeItem(self.edge);
self.edge = null;
self.addingEdge = false;
}
},
});
// Initial data
const data = {
nodes: [
{
id: "node1",
label: "123",
x: 100,
y: 200,
},
{
id: "node2",
label: "123",
x: 300,
y: 200,
},
{
id: "node3",
label: "123",
x: 300,
y: 300,
},
],
edges: [
{
id: "edge1",
target: "node2",
source: "node1",
},
],
};
const graphContainer = document.getElementById("container");
const width = document.getElementById("container").scrollWidth;
const height = document.getElementById("container").scrollHeight || 500;
const graph = new G6.Graph({
container: "container",
width,
height,
// The sets of behavior modes
modes: {
// Defualt mode
default: [
"drag-node",
"click-select",
"click-add-node",
"click-add-edge",
"zoom-canvas"
],
},
defaultNode: {
type: "rect",
style: {
radius: 4,
},
anchorPoints: [
[0.5, 0],
[1, 0.5],
[0.5, 1],
[0, 0.5],
],
},
// The node styles in different states
nodeStateStyles: {
// The node styles in selected state
selected: {
stroke: "#666",
lineWidth: 2,
fill: "steelblue",
},
},
defaultEdge: {
type: "line",
style: {
stroke: "#F6BD16",
endArrow: {
path: "M 0,0 L 20,10 L 20,-10 Z",
fill: "#F6BD16",
},
},
},
});
graph.data(data);
graph.render();
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.canvas {
height: 800px;
width: 100%;
margin: 0 auto;
position: relative;
}
.topo_inner {
position: relative;
}
</style>
<template>
<div class="com_ex">
<SuperFlow />
<WorkFlow />
</div>
</template>
<script>
// @ is an alias to /src
import SuperFlow from "@/components/super-flow.vue";
import WorkFlow from "@/components/work-flow/work-flow";
export default {
components: {
SuperFlow,
WorkFlow,
},
data: () => ({}),
mounted() {},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment