Commit 80b23796 by 莫晓莉

Merge branch 'master' of http://139.159.239.83:9093/mxl/ETL-admin

parents 43442828 be023217
......@@ -4,8 +4,8 @@ VUE_APP_BASE_API = 'http://192.168.0.2:9888/'
VUE_APP_WS_API = 'ws://192.168.0.2:9888/'
# VUE_APP_BASE_API = 'http://192.168.0.44:9888/'
# VUE_APP_WS_API = 'ws://192.168.0.44:9888/'
#VUE_APP_BASE_API = 'http://192.168.0.44:9888/'
#VUE_APP_WS_API = 'ws://192.168.0.44:9888/'
......
......@@ -51,6 +51,7 @@
"jszip": "3.1.5",
"mavon-editor": "^2.9.0",
"moment": "^2.29.1",
"mxgraph": "^4.2.2",
"node-sass": "^5.0.0",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
......
......@@ -116,6 +116,45 @@ export function drop(data){
//etl工具列表
export function steps(data){
return request({
url: 'etlweb/system/steps',
data,
method: 'post'
})
}
//表格类型
export function excelSheetType(data){
return request({
url: 'etlweb/system/excelSheetType',
data,
method: 'post'
})
}
//从哪个步骤读文件名
export function previousSteps(data){
return request({
url: 'etlweb/trans/previousSteps',
data,
method: 'post'
})
}
//保存文件名的字段
export function inputOutputFields(data){
return request({
url: 'etlweb/trans/inputOutputFields',
data,
method: 'post'
})
}
......
......@@ -5,7 +5,9 @@
<!--顶部工具菜单-->
<el-col :span="24">
<div class="ef-tooltar">
<el-link type="primary" :underline="false">{{flowData.name}}</el-link>
<el-link type="primary" :underline="false">{{
flowData.name
}}</el-link>
<el-divider direction="vertical"></el-divider>
<!--顶部工具菜单放大功能-->
<!--<el-tooltip class="item" effect="dark" :open-delay="300" :hide-after="3000" content="点击放大" placement="bottom">-->
......@@ -15,28 +17,68 @@
<!--<el-tooltip class="item" effect="dark" content="点击缩小" placement="bottom">-->
<!--<el-button type="text" icon="el-icon-minus" size="large" @click="zoomSub"></el-button>-->
<!--</el-tooltip>-->
<el-tooltip class="item" effect="dark" :open-delay="300" content="保存流程图" placement="bottom">
<el-button type="text" icon="el-icon-receiving" size="large" @click="saveFlow"></el-button>
<el-tooltip
class="item"
effect="dark"
:open-delay="300"
content="保存流程图"
placement="bottom"
>
<el-button
type="text"
icon="el-icon-receiving"
size="large"
@click="saveFlow"
></el-button>
</el-tooltip>
<!--<el-divider direction="vertical"></el-divider>-->
<!--<el-tooltip class="item" effect="dark" :open-delay="300" content="生产流程图片" placement="bottom">-->
<!--<el-button type="text" icon="el-icon-picture" size="large" @click="downloadData"></el-button>-->
<!--</el-tooltip>-->
<el-divider direction="vertical"></el-divider>
<el-tooltip class="item" effect="dark" content="重新绘制" placement="bottom">
<el-button type="text" icon="el-icon-refresh" size="large" @click="clearFlow"></el-button>
<el-tooltip
class="item"
effect="dark"
content="重新绘制"
placement="bottom"
>
<el-button
type="text"
icon="el-icon-refresh"
size="large"
@click="clearFlow"
></el-button>
</el-tooltip>
<el-divider direction="vertical"></el-divider>
<el-tooltip class="item" effect="dark" content="点击删除" placement="bottom">
<el-button type="text" icon="el-icon-delete" size="large" @click="deleteFlow"
:disabled="!this.activeElement.type"></el-button>
<el-tooltip
class="item"
effect="dark"
content="点击删除"
placement="bottom"
>
<el-button
type="text"
icon="el-icon-delete"
size="large"
@click="deleteFlow"
:disabled="!this.activeElement.type"
></el-button>
</el-tooltip>
<el-divider direction="vertical"></el-divider>
<el-tooltip class="item" effect="dark" content="设置" placement="bottom">
<el-button type="text" icon="el-icon-setting" size="large"
@click="settingFlow"></el-button>
<el-tooltip
class="item"
effect="dark"
content="设置"
placement="bottom"
>
<el-button
type="text"
icon="el-icon-setting"
size="large"
@click="settingFlow"
></el-button>
</el-tooltip>
</div>
</el-col>
......@@ -44,7 +86,7 @@
</div>
<div class="ef-flow-main">
<!-- 左侧节点start -->
<!-- 左侧节点start -->
<!-- <transition name="moveL">
<div class="ef-left-box" v-show="isLeftMenu">
......@@ -59,7 +101,12 @@
<!--左侧节点end -->
<!-- 画布start -->
<div class="ef-flow-content" ref="efContainer" v-flowDrag @click.stop="containerHandler">
<div
class="ef-flow-content"
ref="efContainer"
v-flowDrag
@click.stop="containerHandler"
>
<template v-for="node in flowData.nodeList">
<flow-node
:id="node.id"
......@@ -81,7 +128,6 @@
<!-- 画布end -->
<!-- 右侧表单 -->
<!-- <transition name="moveR">
<div class="ef-right-box" v-show="isShowR">
......@@ -90,99 +136,464 @@
</div>
</transition> -->
</div>
</div>
<!-- 输入工具弹框 -->
<el-dialog
title="Excelt输入"
:visible.sync="excelLnput"
width="800px"
:before-close="handleClose"
>
<div id="ExcelInputDialog"></div>
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="步骤名称">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-form>
<el-tabs v-model="activeName" type="border-card" @tab-click="tapClick">
<el-tab-pane label="文件" name="file">
<el-form ref="form" :model="form" label-width="120px">
<el-form-item label="表格类(引擎):">
<el-select v-model="form.engine" style="width: 100%">
<el-option
v-for="item in engine"
:key="item.code"
:label="item.desc"
:value="item.code"
/>
</el-select>
</el-form-item>
<el-form-item label="选中的文件:">
<!-- <input type="file" placeholder="上传" @change="fileChnageInput" /> -->
<el-upload
class="upload-demo"
action="https://jsonplaceholder.typicode.com/posts/"
:on-change="handleChange"
:show-file-list="false"
:auto-upload="false"
>
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
<el-card class="box-card">
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="name" label="文件/目录" width="120">
</el-table-column>
<el-table-column prop="filemask" label="通配符">
</el-table-column>
<el-table-column
prop="exclude_filemask"
label="通配符号(排除)"
width="120"
>
</el-table-column>
<el-table-column prop="file_required" label="要求">
</el-table-column>
<el-table-column prop="include_subfolders" label="包含子目录">
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
@click="handleClick(scope.row)"
type="text"
size="small"
>编辑</el-button
>
<el-button
type="text"
size="small"
@click="deleteRow(scope.$index, tableData)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</el-card>
</el-form-item>
</el-form>
<el-card class="box-card">
<el-form ref="form" :model="form" label-width="200px">
<el-form-item label="从前面的步骤获取文件名:">
<el-checkbox v-model="form.checked"></el-checkbox>
</el-form-item>
<el-form-item label="从哪个步骤读文化名:">
<el-select
v-model="form.region"
style="width: 100%"
:disabled="form.checked"
>
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="保存文件的字段:">
<el-select
v-model="form.region"
style="width: 100%"
:disabled="form.checked"
>
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
</el-form>
</el-card>
</el-tab-pane>
<el-tab-pane label="工作表" name="worksheet">
<el-button type="primary" @click="addSheet">添加工作表</el-button>
<el-form ref="form" :model="form" label-width="160px">
<el-form-item label="要读取的工作表列表:">
<el-card class="box-card">
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="name" label="工作表名称" width="120">
</el-table-column>
<el-table-column prop="filemask" label="起始行">
</el-table-column>
<el-table-column
prop="exclude_filemask"
label="起始列"
>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
@click="handleClick(scope.row)"
type="text"
size="small"
>编辑</el-button
>
<el-button
type="text"
size="small"
@click="deleteRow(scope.$index, tableData)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</el-card>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="内容" name="content">
<el-form ref="form" :model="form" label-width="200px">
<el-form-item label="头部:">
<el-checkbox v-model="form.checked"></el-checkbox>
</el-form-item>
<el-form-item label="没有空行:">
<el-checkbox v-model="form.checked"></el-checkbox>
</el-form-item>
<el-form-item label="停在空白记录:">
<el-checkbox v-model="form.checked"></el-checkbox>
</el-form-item>
<el-form-item label="限制:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="编码:">
<el-select v-model="form.region" style="width: 100%">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="添加文件名">
<el-checkbox v-model="form.checked"></el-checkbox>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="错误处理" name="handling">
<el-form ref="form" :model="form" label-width="130px">
<el-form-item label="严格类型:">
<el-checkbox v-model="form.checked"></el-checkbox>
</el-form-item>
<el-form-item label="忽略错误:">
<el-checkbox v-model="form.checked"></el-checkbox>
</el-form-item>
<el-form-item label="跳过错误行:">
<el-checkbox v-model="form.checked"></el-checkbox>
</el-form-item>
<el-form-item label="警文件目录:">
<el-row :gutter="10">
<el-col :span="8">
<el-input v-model="form.name"></el-input>
</el-col>
<el-col class="line" :span="2.5">扩展名</el-col>
<el-col :span="8">
<el-input v-model="form.name"></el-input>
</el-col>
<el-col class="line" :span="2.5">
<el-button size="mini">变量</el-button></el-col
>
<el-col class="line" :span="2.5">
<el-button size="mini">浏览</el-button></el-col
>
</el-row>
</el-form-item>
<el-form-item label="错误件目录:">
<el-row :gutter="10">
<el-col :span="8">
<el-input v-model="form.name"></el-input>
</el-col>
<el-col class="line" :span="2.5">扩展名</el-col>
<el-col :span="8">
<el-input v-model="form.name"></el-input>
</el-col>
<el-col class="line" :span="2.5">
<el-button size="mini">变量</el-button></el-col
>
<el-col class="line" :span="2.5">
<el-button size="mini">浏览</el-button></el-col
>
</el-row>
</el-form-item>
<el-form-item label="失败行数文件目录:">
<el-row :gutter="10">
<el-col :span="8">
<el-input v-model="form.name"></el-input>
</el-col>
<el-col class="line" :span="2.5">扩展名</el-col>
<el-col :span="8">
<el-input v-model="form.name"></el-input>
</el-col>
<el-col class="line" :span="2.5">
<el-button size="mini">变量</el-button></el-col
>
<el-col class="line" :span="2.5">
<el-button size="mini">浏览</el-button></el-col
>
</el-row>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="字段" name="field">
<el-card class="box-card"> </el-card>
</el-tab-pane>
<el-tab-pane label="其他输出字段" name="oher ">
<el-form ref="form" :model="form" label-width="150px">
<el-form-item label="文件名称字段:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="Sheet名称字段:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="Sheet的行号列:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="行号列:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="文件名字段:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="扩展名字段:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="路径字段:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="文件大小字段:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="是否为隐藏文件字段:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="最后修改时间字段:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="Uri字段:">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="Root uri字段:">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
<span slot="footer" class="dialog-footer">
<el-button @click="excelLnput = false">取 消</el-button>
<el-button type="primary" @click="excelLnput = false">确 定</el-button>
</span>
</el-dialog>
<!-- 修改-->
<el-dialog
title="编辑"
:visible.sync="edit"
width="500px"
:before-close="handleClose"
>
<el-form ref="form" :model="form" label-width="150px">
<el-form-item label="文件/目录:">
<el-input v-model="form.name" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="通配符:">
<el-input v-model="form.filemask"></el-input>
</el-form-item>
<el-form-item label="通配符号(排除):">
<el-input v-model="form.exclude_filemask"></el-input>
</el-form-item>
<el-form-item label="要求:">
<el-select v-model="form.file_required" style="width: 100%">
<el-option label="是" value="1"></el-option>
<el-option label="否" value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item label="包含子目录:">
<el-select v-model="form.include_subfolders" style="width: 100%">
<el-option label="是" value="1"></el-option>
<el-option label="否" value="0"></el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="edit = false">取 消</el-button>
<el-button type="primary" @click="edit = false">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import draggable from 'vuedraggable'
import {jsPlumb} from 'jsplumb'
import './style/index.css'
// 使用修改后的jsplumb
import {easyFlowMixin} from './config/mixins'//设置流程图参数
import flowNode from './modules/node'//流程图内节点框的编辑
import nodeMenu from './modules/node_menu'//左边tab
// import FlowNodeForm from './modules/node_form'//右边tab
import lodash from 'lodash'//JavaScript 实用工具库
export default {
data() {
return {
isShowIcon:false,
isLeftMenu: true,
isShowR: false,
// jsPlumb 实例
jsPlumb: null,
// 控制画布销毁
easyFlowVisible: true,
// 是否加载完毕标志位
loadEasyFlowFinish: false,
// 数据
flowData: {},
// 激活的元素、可能是节点、可能是连线
activeElement: {
// 可选值 node 、line
type: undefined,
// 节点ID
nodeId: undefined,
// 连线ID
sourceId: undefined,
targetId: undefined
import draggable from "vuedraggable";
import { jsPlumb } from "jsplumb";
import "./style/index.css";
// 使用修改后的jsplumb
import { easyFlowMixin } from "./config/mixins"; //设置流程图参数
import flowNode from "./modules/node"; //流程图内节点框的编辑
import nodeMenu from "./modules/node_menu"; //左边tab
// import FlowNodeForm from './modules/node_form'//右边tab
import lodash from "lodash"; //JavaScript 实用工具库
import {
excelSheetType,
previousSteps,
inputOutputFields,
} from "@/api/kettle/link";
export default {
data() {
return {
tableData: [
{
filemask: "",
name: "王小虎",
exclude_filemask: "",
file_required: "0",
include_subfolders: "1",
},
zoom: 0.5
}
},
// 一些基础配置移动该文件中
mixins: [easyFlowMixin],
components: {
draggable,
flowNode,
nodeMenu,
// FlowNodeForm
},
//自定义指令 https://www.jb51.net/article/108047.htm
directives: {
'flowDrag': {
bind(el, binding, vnode, oldNode) {
if (!binding) {
return
}
el.onmousedown = (e) => {
if (e.button == 2) {
// 右键不管
return
}
// 鼠标按下,计算当前原始距离可视区的高度
let disX = e.clientX
let disY = e.clientY
el.style.cursor = 'move'
document.onmousemove = function (e) {
// 移动时禁止默认事件
e.preventDefault()
const left = e.clientX - disX
disX = e.clientX
el.scrollLeft += -left
const top = e.clientY - disY
disY = e.clientY
el.scrollTop += -top
}
],
engine: [],
isShowIcon: false,
isLeftMenu: true,
isShowR: false,
// jsPlumb 实例
jsPlumb: null,
// 控制画布销毁
easyFlowVisible: true,
// 是否加载完毕标志位
loadEasyFlowFinish: false,
// 数据
flowData: {},
// 激活的元素、可能是节点、可能是连线
activeElement: {
// 可选值 node 、line
type: undefined,
// 节点ID
nodeId: undefined,
// 连线ID
sourceId: undefined,
targetId: undefined,
},
document.onmouseup = function (e) {
el.style.cursor = 'auto'
document.onmousemove = null
document.onmouseup = null
}
}
zoom: 0.5,
excelLnput: false,
edit: false,
form: {
checked: true,
},
activeName: "file",
};
},
// 一些基础配置移动该文件中
mixins: [easyFlowMixin],
components: {
draggable,
flowNode,
nodeMenu,
// FlowNodeForm
},
//自定义指令 https://www.jb51.net/article/108047.htm
directives: {
flowDrag: {
bind(el, binding, vnode, oldNode) {
if (!binding) {
return;
}
}
el.onmousedown = (e) => {
if (e.button == 2) {
// 右键不管
return;
}
// 鼠标按下,计算当前原始距离可视区的高度
let disX = e.clientX;
let disY = e.clientY;
el.style.cursor = "move";
document.onmousemove = function (e) {
// 移动时禁止默认事件
e.preventDefault();
const left = e.clientX - disX;
disX = e.clientX;
el.scrollLeft += -left;
const top = e.clientY - disY;
disY = e.clientY;
el.scrollTop += -top;
};
document.onmouseup = function (e) {
el.style.cursor = "auto";
document.onmousemove = null;
document.onmouseup = null;
};
};
},
},
mounted() {
this.jsPlumb = jsPlumb.getInstance()
this.$nextTick(() => {
// 默认加载流程A的数据、在这里可以根据具体的业务返回符合流程数据格式的数据即可
const data_test = `{
},
mounted() {
this.jsPlumb = jsPlumb.getInstance();
this.$nextTick(() => {
// 默认加载流程A的数据、在这里可以根据具体的业务返回符合流程数据格式的数据即可
const data_test = `{
name: '流程B',
nodeList: [
{
......@@ -238,535 +649,612 @@
to: 'nodeD'
}
]
}`
// console.log(localStorage.getItem('data_test'),'---');
// const data_test = localStorage.getItem('data_test')
console.log('初始化流程数据', (new Function("return " + data_test))());
this.dataReload((new Function("return " + data_test))())
})
}`;
// console.log(localStorage.getItem('data_test'),'---');
// const data_test = localStorage.getItem('data_test')
console.log("初始化流程数据", new Function("return " + data_test)());
this.dataReload(new Function("return " + data_test)());
});
},
methods: {
fileChnageInput(e) {
console.log(e);
},
methods: {
containerHandler(event) {
if(event.currentTarget===event.target){
console.log('containerHandler')
this.isShowR = false
}
},
// 返回唯一标识
getUUID() {
return new Date().getTime() +Math.random().toString(36).substr(3, 10)
},
jsPlumbInit() {
this.jsPlumb.ready(() => {
// 导入默认配置
this.jsPlumb.importDefaults(this.jsplumbSetting)
// 会使整个jsPlumb立即重绘。
this.jsPlumb.setSuspendDrawing(false, true);
// 初始化节点
this.loadEasyFlow()
// 单点击了连接线, https://www.cnblogs.com/ysx215/p/7615677.html
this.jsPlumb.bind('click', (conn, originalEvent) => {
console.log('单点击了连接线',conn)
this.activeElement.type = 'line'
this.activeElement.sourceId = conn.sourceId
this.activeElement.targetId = conn.targetId
// this.$refs.nodeForm.lineInit({
// from: conn.sourceId,
// to: conn.targetId,
// label: conn.getLabel()
// })
})
// 连线
this.jsPlumb.bind("connection", (evt) => {
let from = evt.source.id
let to = evt.target.id
if (this.loadEasyFlowFinish) {
this.flowData.lineList.push({from: from, to: to})
}
})
// 上传
handleChange(file, fileList) {
// console.log(file);
// 删除连线回调
this.jsPlumb.bind("connectionDetached", (evt) => {
this.deleteLine(evt.sourceId, evt.targetId)
})
this.fileList = fileList.slice(-3);
this.tableData.push({ name: file.name });
// console.log(this.tableData);
// this.getObjectURL(file.raw)
// console.log(this.getObjectURL(file.raw));
},
// 改变线的连接节点
this.jsPlumb.bind("connectionMoved", (evt) => {
this.changeLine(evt.originalSourceId, evt.originalTargetId)
})
getObjectURL(file) {
let url = null;
if (window.createObjcectURL != undefined) {
url = window.createOjcectURL(file);
} else if (window.URL != undefined) {
url = window.URL.createObjectURL(file);
} else if (window.webkitURL != undefined) {
url = window.webkitURL.createObjectURL(file);
}
return url;
},
deleteRow(index, rows) {
rows.splice(index, 1);
},
tapClick() {},
handleClick(val) {
this.edit = !this.edit;
this.form = val;
},
// 关闭弹框
handleClose(done) {
this.$confirm("确认关闭?")
.then((_) => {
done();
})
.catch((_) => {});
},
// 连线右击
this.jsPlumb.bind("contextmenu", (evt) => {
console.log('连线右击', evt)
})
containerHandler(event) {
if (event.currentTarget === event.target) {
console.log("containerHandler");
this.isShowR = false;
}
},
// 返回唯一标识
getUUID() {
return new Date().getTime() + Math.random().toString(36).substr(3, 10);
},
jsPlumbInit() {
this.jsPlumb.ready(() => {
// 导入默认配置
this.jsPlumb.importDefaults(this.jsplumbSetting);
// 会使整个jsPlumb立即重绘。
this.jsPlumb.setSuspendDrawing(false, true);
// 初始化节点
this.loadEasyFlow();
// 单点击了连接线, https://www.cnblogs.com/ysx215/p/7615677.html
this.jsPlumb.bind("click", (conn, originalEvent) => {
console.log("单点击了连接线", conn);
this.activeElement.type = "line";
this.activeElement.sourceId = conn.sourceId;
this.activeElement.targetId = conn.targetId;
// this.$refs.nodeForm.lineInit({
// from: conn.sourceId,
// to: conn.targetId,
// label: conn.getLabel()
// })
});
// 连线
this.jsPlumb.bind("connection", (evt) => {
let from = evt.source.id;
let to = evt.target.id;
if (this.loadEasyFlowFinish) {
this.flowData.lineList.push({ from: from, to: to });
}
});
// 连线
this.jsPlumb.bind("beforeDrop", (evt) => {
console.log('连接开始',evt)
let from = evt.sourceId
let to = evt.targetId
if (from === to) {
this.$message.error('节点不支持连接自己')
return false
}
if (this.hasLine(from, to)) {
this.$message.error('该关系已存在,不允许重复创建')
return false
}
if (this.hashOppositeLine(from, to)) {
this.$message.error('不支持两个节点之间连线回环');
return false
}
this.$message.success('连接成功')
return true
})
// 删除连线回调
this.jsPlumb.bind("connectionDetached", (evt) => {
this.deleteLine(evt.sourceId, evt.targetId);
});
// beforeDetach
this.jsPlumb.bind("beforeDetach", (evt) => {
console.log('beforeDetach', evt)
})
this.jsPlumb.setContainer(this.$refs.efContainer)
})
},
// 加载流程图
loadEasyFlow() {
// 初始化节点
for (var i = 0; i < this.flowData.nodeList.length; i++) {
let node = this.flowData.nodeList[i]
// 设置源点,可以拖出线连接其他节点
this.jsPlumb.makeSource(node.id, lodash.merge(this.jsplumbSourceOptions, {}))
// // 设置目标点,其他源点拖出的线可以连接该节点
this.jsPlumb.makeTarget(node.id, this.jsplumbTargetOptions)
if (!node.viewOnly) {
this.jsPlumb.draggable(node.id, {
containment: 'parent',
stop: function (el) {
// 拖拽节点结束后的对调
console.log('拖拽结束001: ', el)
}
})
// 改变线的连接节点
this.jsPlumb.bind("connectionMoved", (evt) => {
this.changeLine(evt.originalSourceId, evt.originalTargetId);
});
// 连线右击
this.jsPlumb.bind("contextmenu", (evt) => {
console.log("连线右击", evt);
});
// 连线
this.jsPlumb.bind("beforeDrop", (evt) => {
console.log("连接开始", evt);
let from = evt.sourceId;
let to = evt.targetId;
if (from === to) {
this.$message.error("节点不支持连接自己");
return false;
}
}
// 初始化连线
for (var i = 0; i < this.flowData.lineList.length; i++) {
let line = this.flowData.lineList[i]
var connParam = {
source: line.from,
target: line.to,
label: line.label ? line.label : '',
connector: line.connector ? line.connector : '',
anchors: line.anchors ? line.anchors : undefined,
paintStyle: line.paintStyle ? line.paintStyle : undefined,
if (this.hasLine(from, to)) {
this.$message.error("该关系已存在,不允许重复创建");
return false;
}
if (this.hashOppositeLine(from, to)) {
this.$message.error("不支持两个节点之间连线回环");
return false;
}
this.jsPlumb.connect(connParam, this.jsplumbConnectOptions)
this.$message.success("连接成功");
return true;
});
// beforeDetach
this.jsPlumb.bind("beforeDetach", (evt) => {
console.log("beforeDetach", evt);
});
this.jsPlumb.setContainer(this.$refs.efContainer);
});
},
// 加载流程图
loadEasyFlow() {
// 初始化节点
for (var i = 0; i < this.flowData.nodeList.length; i++) {
let node = this.flowData.nodeList[i];
// 设置源点,可以拖出线连接其他节点
this.jsPlumb.makeSource(
node.id,
lodash.merge(this.jsplumbSourceOptions, {})
);
// // 设置目标点,其他源点拖出的线可以连接该节点
this.jsPlumb.makeTarget(node.id, this.jsplumbTargetOptions);
if (!node.viewOnly) {
this.jsPlumb.draggable(node.id, {
containment: "parent",
stop: function (el) {
// 拖拽节点结束后的对调
console.log("拖拽结束001: ", el);
},
});
}
this.$nextTick(function () {
this.loadEasyFlowFinish = true
})
},
// 设置连线条件
setLineLabel(from, to, label) {
var conn = this.jsPlumb.getConnections({
source: from,
target: to
})[0]
if (!label || label === '') {
conn.removeClass('flowLabel')
conn.addClass('emptyFlowLabel')
} else {
conn.addClass('flowLabel')
}
// 初始化连线
for (var i = 0; i < this.flowData.lineList.length; i++) {
let line = this.flowData.lineList[i];
var connParam = {
source: line.from,
target: line.to,
label: line.label ? line.label : "",
connector: line.connector ? line.connector : "",
anchors: line.anchors ? line.anchors : undefined,
paintStyle: line.paintStyle ? line.paintStyle : undefined,
};
this.jsPlumb.connect(connParam, this.jsplumbConnectOptions);
}
this.$nextTick(function () {
this.loadEasyFlowFinish = true;
});
},
// 设置连线条件
setLineLabel(from, to, label) {
var conn = this.jsPlumb.getConnections({
source: from,
target: to,
})[0];
if (!label || label === "") {
conn.removeClass("flowLabel");
conn.addClass("emptyFlowLabel");
} else {
conn.addClass("flowLabel");
}
conn.setLabel({
label: label,
});
this.flowData.lineList.forEach(function (line) {
if (line.from == from && line.to == to) {
line.label = label;
}
conn.setLabel({
label: label,
})
this.flowData.lineList.forEach(function (line) {
if (line.from == from && line.to == to) {
line.label = label
}
});
},
isLeftBox() {
let that = this;
that.isLeftMenu = !that.isLeftMenu;
setTimeout(function () {
that.isShowIcon = true;
}, 300);
},
isFlowCtl() {
console.log(999);
this.isLeftMenu = !this.isLeftMenu;
this.isShowIcon = false;
},
//设置
settingFlow() {
console.log("按钮给我测试其他的功能--1", this.isLeftMenu);
},
// 删除激活的元素
deleteFlow() {
if (this.activeElement.type === "node") {
this.deleteNode(this.activeElement.nodeId);
} else if (this.activeElement.type === "line") {
this.$confirm("确定删除所点击的线吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
},
isLeftBox() {
let that = this
that.isLeftMenu = !that.isLeftMenu
setTimeout(function () {
that.isShowIcon=true
}, 300);
},
isFlowCtl(){
console.log(999);
this.isLeftMenu = !this.isLeftMenu
this.isShowIcon=false
},
//设置
settingFlow() {
console.log('按钮给我测试其他的功能--1', this.isLeftMenu);
},
// 删除激活的元素
deleteFlow() {
if (this.activeElement.type === 'node') {
this.deleteNode(this.activeElement.nodeId)
} else if (this.activeElement.type === 'line') {
this.$confirm('确定删除所点击的线吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
.then(() => {
var conn = this.jsPlumb.getConnections({
source: this.activeElement.sourceId,
target: this.activeElement.targetId
})[0]
this.jsPlumb.deleteConnection(conn)
}).catch(() => {
target: this.activeElement.targetId,
})[0];
this.jsPlumb.deleteConnection(conn);
})
.catch(() => {});
}
},
// 删除线
deleteLine(from, to) {
this.flowData.lineList = this.flowData.lineList.filter(function (line) {
if (line.from == from && line.to == to) {
return false;
}
},
// 删除线
deleteLine(from, to) {
this.flowData.lineList = this.flowData.lineList.filter(function (line) {
if (line.from == from && line.to == to) {
return false
}
return true
})
},
// 改变连线
changeLine(oldFrom, oldTo) {
this.deleteLine(oldFrom, oldTo)
},
// 改变节点的位置
changeNodeSite(flowData) {
console.log(666)
return true;
});
},
// 改变连线
changeLine(oldFrom, oldTo) {
this.deleteLine(oldFrom, oldTo);
},
// 改变节点的位置
changeNodeSite(flowData) {
console.log(666);
for (var i = 0; i < this.flowData.nodeList.length; i++) {
let node = this.flowData.nodeList[i];
if (node.id === flowData.nodeId) {
node.left = flowData.left;
node.top = flowData.top;
}
}
},
/**
* 拖拽结束后添加新的节点
* @param evt
* @param nodeMenu 被添加的节点对象
* @param mousePosition 鼠标拖拽结束的坐标
*/
addNode(evt, nodeMenu, mousePosition) {
var screenX = evt.originalEvent.clientX,
screenY = evt.originalEvent.clientY;
let efContainer = this.$refs.efContainer;
var containerRect = efContainer.getBoundingClientRect();
var left = screenX,
top = screenY;
// 计算是否拖入到容器中
if (
left < containerRect.x ||
left > containerRect.width + containerRect.x ||
top < containerRect.y ||
containerRect.y > containerRect.y + containerRect.height
) {
this.$message.error("请把节点拖入到画布中");
return;
}
left = left - containerRect.x + efContainer.scrollLeft;
top = top - containerRect.y + efContainer.scrollTop;
// 居中
left -= 85;
top -= 16;
var nodeId = this.getUUID();
// 动态生成名字
var origName = nodeMenu.name;
var nodeName = origName;
var index = 1;
while (index < 10000) {
var repeat = false;
for (var i = 0; i < this.flowData.nodeList.length; i++) {
let node = this.flowData.nodeList[i]
if (node.id === flowData.nodeId) {
node.left = flowData.left
node.top = flowData.top
let node = this.flowData.nodeList[i];
if (node.name === nodeName) {
nodeName = origName + index;
repeat = true;
}
}
},
/**
* 拖拽结束后添加新的节点
* @param evt
* @param nodeMenu 被添加的节点对象
* @param mousePosition 鼠标拖拽结束的坐标
*/
addNode(evt, nodeMenu, mousePosition) {
var screenX = evt.originalEvent.clientX, screenY = evt.originalEvent.clientY
let efContainer = this.$refs.efContainer
var containerRect = efContainer.getBoundingClientRect()
var left = screenX, top = screenY
// 计算是否拖入到容器中
if (left < containerRect.x || left > containerRect.width + containerRect.x || top < containerRect.y || containerRect.y > containerRect.y + containerRect.height) {
this.$message.error("请把节点拖入到画布中")
return
}
left = left - containerRect.x + efContainer.scrollLeft
top = top - containerRect.y + efContainer.scrollTop
// 居中
left -= 85
top -= 16
var nodeId = this.getUUID()
// 动态生成名字
var origName = nodeMenu.name
var nodeName = origName
var index = 1
while (index < 10000) {
var repeat = false
for (var i = 0; i < this.flowData.nodeList.length; i++) {
let node = this.flowData.nodeList[i]
if (node.name === nodeName) {
nodeName = origName + index
repeat = true
}
}
if (repeat) {
index++
continue
}
break
if (repeat) {
index++;
continue;
}
console.log('-------003',nodeMenu.type);
var node = {
break;
}
console.log("-------003", nodeMenu.type);
var node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
type: nodeMenu.type, //节点类型
left: left + "px", //坐标
top: top + "px", //坐标
ico: nodeMenu.ico, //图标
};
if (nodeMenu.type === "channel") {
node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
type: nodeMenu.type, //节点类型
left: left + 'px', //坐标
top: top + 'px', //坐标
left: left + "px", //坐标
top: top + "px", //坐标
ico: nodeMenu.ico, //图标
}
if(nodeMenu.type === 'channel'){
node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
type: nodeMenu.type, //节点类型
left: left + 'px', //坐标
top: top + 'px', //坐标
ico: nodeMenu.ico, //图标
channel: 'channel01', //渠道名称
clientAccounted: '', //渠道 客户占比
clientDistribution: true, //渠道 客户是否随机分配
strategyOrCustom : ' ', //渠道 选择分组策略 or 自定义 ***弹窗回显
}
}else if(nodeMenu.type === 'customerFission'){
node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
type: nodeMenu.type, //节点类型
left: left + 'px', //坐标
top: top + 'px', //坐标
ico: nodeMenu.ico, //图标
groupingCustomer : '' , //客群 分组客群标识
customerDistribution : true , //客群 客户是否随机分配
customerAccounted : '' , //客群 客户占比
customerOrCustom : '' , //客群 ***弹窗回显
}
}else if(nodeMenu.type === 'intelligentRecommend'){
node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
type: nodeMenu.type, //节点类型
left: left + 'px', //坐标
top: top + 'px', //坐标
ico: nodeMenu.ico, //图标
marketingProduct : '' , //智能推荐 营销产品 ***弹窗回显
testProduct : '' , //智能推荐 测试产品 ***弹窗回显
productDistribution: true , //智能推荐 客户是否随机分配
productAccounted : '' , //智能推荐 客户占比
productOrIntelligent : '智能推荐测试一下' , //智能推荐 ***弹窗回显
}
}else if(nodeMenu.type === 'handmadeRecommend'){
node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
type: nodeMenu.type, //节点类型
left: left + 'px', //坐标
top: top + 'px', //坐标
ico: nodeMenu.ico, //图标
handmadeMarketingProduct : '' , //手工推荐 营销产品 ***弹窗回显
handmadeTestProduct : '' , //手工推荐 测试产品 ***弹窗回显
handmadeProductDistribution: true , //手工推荐 客户是否随机分配
handmadeProductAccounted : '' , //手工推荐 客户占比
productOrHandmade : '手工推荐测试一下' , //手工推荐 ***弹窗回显
}
}else if(nodeMenu.type === 'timeQuantum'){
node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
type: nodeMenu.type, //节点类型
left: left + 'px', //坐标
top: top + 'px', //坐标
ico: nodeMenu.ico, //图标
startTime: '' , //时间段- 开始时间段
endTime : '' , //时间段- 结束时间段
timeDistribution: true , //时间段- 客户是否随机分配
timeAccounted : '' , //时间段- 客户占比
timeOrHandmade : '时间段-测试一下' , //时间段- ***弹窗回显
}
}
/**
* 这里可以进行业务判断、是否能够添加该节点
*/
this.flowData.nodeList.push(node)
this.$nextTick(function () {
this.jsPlumb.makeSource(nodeId, this.jsplumbSourceOptions)
this.jsPlumb.makeTarget(nodeId, this.jsplumbTargetOptions)
this.jsPlumb.draggable(nodeId, {
containment: 'parent',
stop: function (el) {
// 拖拽节点结束后的对调
console.log('拖拽结束002: ', el)
}
})
})
},
channel: "channel01", //渠道名称
clientAccounted: "", //渠道 客户占比
clientDistribution: true, //渠道 客户是否随机分配
strategyOrCustom: " ", //渠道 选择分组策略 or 自定义 ***弹窗回显
};
} else if (nodeMenu.type === "customerFission") {
node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
type: nodeMenu.type, //节点类型
left: left + "px", //坐标
top: top + "px", //坐标
ico: nodeMenu.ico, //图标
groupingCustomer: "", //客群 分组客群标识
customerDistribution: true, //客群 客户是否随机分配
customerAccounted: "", //客群 客户占比
customerOrCustom: "", //客群 ***弹窗回显
};
} else if (nodeMenu.type === "intelligentRecommend") {
node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
type: nodeMenu.type, //节点类型
left: left + "px", //坐标
top: top + "px", //坐标
ico: nodeMenu.ico, //图标
marketingProduct: "", //智能推荐 营销产品 ***弹窗回显
testProduct: "", //智能推荐 测试产品 ***弹窗回显
productDistribution: true, //智能推荐 客户是否随机分配
productAccounted: "", //智能推荐 客户占比
productOrIntelligent: "智能推荐测试一下", //智能推荐 ***弹窗回显
};
} else if (nodeMenu.type === "handmadeRecommend") {
node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
type: nodeMenu.type, //节点类型
left: left + "px", //坐标
top: top + "px", //坐标
ico: nodeMenu.ico, //图标
handmadeMarketingProduct: "", //手工推荐 营销产品 ***弹窗回显
handmadeTestProduct: "", //手工推荐 测试产品 ***弹窗回显
handmadeProductDistribution: true, //手工推荐 客户是否随机分配
handmadeProductAccounted: "", //手工推荐 客户占比
productOrHandmade: "手工推荐测试一下", //手工推荐 ***弹窗回显
};
} else if (nodeMenu.type === "timeQuantum") {
node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
type: nodeMenu.type, //节点类型
left: left + "px", //坐标
top: top + "px", //坐标
ico: nodeMenu.ico, //图标
startTime: "", //时间段- 开始时间段
endTime: "", //时间段- 结束时间段
timeDistribution: true, //时间段- 客户是否随机分配
timeAccounted: "", //时间段- 客户占比
timeOrHandmade: "时间段-测试一下", //时间段- ***弹窗回显
};
}
/**
* 删除节点
* @param nodeId 被删除节点的ID
* 这里可以进行业务判断、是否能够添加该节点
*/
deleteNode(nodeId) {
this.$confirm('确定要删除节点' + nodeId + '?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false
}).then(() => {
this.flowData.nodeList.push(node);
this.$nextTick(function () {
this.jsPlumb.makeSource(nodeId, this.jsplumbSourceOptions);
this.jsPlumb.makeTarget(nodeId, this.jsplumbTargetOptions);
this.jsPlumb.draggable(nodeId, {
containment: "parent",
stop: function (el) {
// 拖拽节点结束后的对调
console.log("拖拽结束002: ", el);
},
});
});
},
/**
* 删除节点
* @param nodeId 被删除节点的ID
*/
deleteNode(nodeId) {
this.$confirm("确定要删除节点" + nodeId + "?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
closeOnClickModal: false,
})
.then(() => {
/**
* 这里需要进行业务判断,是否可以删除
*/
this.flowData.nodeList = this.flowData.nodeList.filter(function (node) {
this.flowData.nodeList = this.flowData.nodeList.filter(function (
node
) {
if (node.id === nodeId) {
// 伪删除,将节点隐藏,否则会导致位置错位
// node.show = false
return false
return false;
}
return true
})
return true;
});
this.$nextTick(function () {
this.jsPlumb.removeAllEndpoints(nodeId);
})
}).catch(() => {
});
})
return true
},
clickNode(nodeId) {
console.log('点击节点操作',nodeId)
this.isShowR = true
this.activeElement.type = 'node'
this.activeElement.nodeId = nodeId
// this.$refs.nodeForm.nodeInit(this.flowData, nodeId)
},
// 是否具有该线
hasLine(from, to) {
for (var i = 0; i < this.flowData.lineList.length; i++) {
var line = this.flowData.lineList[i]
if (line.from === from && line.to === to) {
return true
}
.catch(() => {});
return true;
},
clickNode(nodeId) {
console.log("点击节点操作", nodeId);
this.excelLnput = !this.excelLnput;
this.isShowR = true;
this.activeElement.type = "node";
this.activeElement.nodeId = nodeId;
// this.$refs.nodeForm.nodeInit(this.flowData, nodeId)
let pamer = new FormData(); // 创建form对象
pamer.append("query", "");
excelSheetType(pamer).then((res) => {
this.engine = res;
});
previousSteps().then(res=>{
})
inputOutputFields().then(res=>{
})
},
// 是否具有该线
hasLine(from, to) {
for (var i = 0; i < this.flowData.lineList.length; i++) {
var line = this.flowData.lineList[i];
if (line.from === from && line.to === to) {
return true;
}
return false
},
// 是否含有相反的线
hashOppositeLine(from, to) {
return this.hasLine(to, from)
},
nodeRightMenu(nodeId, evt) {
console.log(88)
this.menu.show = true
this.menu.curNodeId = nodeId
this.menu.left = evt.x + 'px'
this.menu.top = evt.y + 'px'
},
repaintEverything() {
this.jsPlumb.repaint()
},
// 加载流程图-不能删
dataReload(flowData) {
this.easyFlowVisible = false
this.flowData.nodeList = []
this.flowData.lineList = []
}
return false;
},
// 是否含有相反的线
hashOppositeLine(from, to) {
return this.hasLine(to, from);
},
nodeRightMenu(nodeId, evt) {
console.log(88);
this.menu.show = true;
this.menu.curNodeId = nodeId;
this.menu.left = evt.x + "px";
this.menu.top = evt.y + "px";
},
repaintEverything() {
this.jsPlumb.repaint();
},
// 加载流程图-不能删
dataReload(flowData) {
this.easyFlowVisible = false;
this.flowData.nodeList = [];
this.flowData.lineList = [];
this.$nextTick(() => {
flowData = lodash.cloneDeep(flowData);
this.easyFlowVisible = true;
this.flowData = flowData;
// console.log(flowData, '渲染数据');
this.$nextTick(() => {
flowData = lodash.cloneDeep(flowData)
this.easyFlowVisible = true
this.flowData = flowData
// console.log(flowData, '渲染数据');
this.jsPlumb = jsPlumb.getInstance();
this.$nextTick(() => {
this.jsPlumb = jsPlumb.getInstance()
this.$nextTick(() => {
this.jsPlumbInit()
})
})
this.jsPlumbInit();
});
});
});
},
// 保存流程图
saveFlow() {
const that = this;
let flowObj = Object.assign({}, that.flowData);
// localStorage.setItem("data_test", JSON.stringify(flowObj))
console.log("保存流程图", flowObj);
// if (!that.checkFlow()) return;
that.$message.success("保存流程成功!暂时请查先看控制台。");
},
//重绘流程图
clearFlow() {
let that = this;
console.log("重绘流程图--1", that.flowData);
that
.$confirm("确定要重新绘制流程图吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
closeOnClickModal: false,
})
},
// 保存流程图
saveFlow() {
const that = this;
let flowObj = Object.assign({}, that.flowData)
// localStorage.setItem("data_test", JSON.stringify(flowObj))
console.log('保存流程图',flowObj)
// if (!that.checkFlow()) return;
that.$message.success('保存流程成功!暂时请查先看控制台。')
},
//重绘流程图
clearFlow() {
let that = this;
console.log('重绘流程图--1', that.flowData)
that.$confirm('确定要重新绘制流程图吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false
}).then(() => {
.then(() => {
if (that.flowData.nodeList.length !== 0) {
that.flowData.nodeList.forEach(function (node, index) {
that.jsPlumb.remove(node.id);
});
that.flowData.nodeList = [];
that.flowData.linkList = [];
that.$message.success('设置成功');
console.log('重绘流程图--002', that.flowData)
that.$message.success("设置成功");
console.log("重绘流程图--002", that.flowData);
}
}).catch(() => {
console.log('取消重绘流程图--1')
that.$message.error('取消重制');
})
.catch(() => {
console.log("取消重绘流程图--1");
that.$message.error("取消重制");
});
},
//放小
zoomSub() {
let that = this;
if (that.zoom <= 0) {
return;
}
// setInterval(() => {
that.zoom = that.zoom - 0.1;
that.$refs.efContainer.style.transform = `scale(${that.zoom})`;
that.jsPlumb.setZoom(that.zoom);
// }, 1000)
},
//放大
zoomAdd() {
let that = this;
if (that.zoom >= 1) {
return;
}
// setInterval(() => {
that.zoom = that.zoom + 0.1;
},
//放小
zoomSub() {
let that = this;
if (that.zoom <= 0) {
return
}
// setInterval(() => {
that.zoom = that.zoom - 0.1
that.$refs.efContainer.style.transform = `scale(${that.zoom})`
that.jsPlumb.setZoom(that.zoom)
// }, 1000)
},
//放大
zoomAdd() {
let that = this;
if (that.zoom >= 1) {
return
}
// setInterval(() => {
that.zoom = that.zoom + 0.1
// that.$refs.efContainer.style.transform = `scale(${that.zoom})`
console.log(that.zoom);
that.$refs.efContainer.style.transform = `scale(${that.zoom})`
that.jsPlumb.setZoom(that.zoom)
// }, 1000)
},
// 下载数据
downloadData() {
this.$confirm('确定要下载该流程数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false
}).then(() => {
var datastr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(this.flowData, null, '\t'));
var downloadAnchorNode = document.createElement('a')
// that.$refs.efContainer.style.transform = `scale(${that.zoom})`
console.log(that.zoom);
that.$refs.efContainer.style.transform = `scale(${that.zoom})`;
that.jsPlumb.setZoom(that.zoom);
// }, 1000)
},
// 下载数据
downloadData() {
this.$confirm("确定要下载该流程数据吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
closeOnClickModal: false,
})
.then(() => {
var datastr =
"data:text/json;charset=utf-8," +
encodeURIComponent(JSON.stringify(this.flowData, null, "\t"));
var downloadAnchorNode = document.createElement("a");
downloadAnchorNode.setAttribute("href", datastr);
downloadAnchorNode.setAttribute("download", 'flowData.json')
downloadAnchorNode.setAttribute("download", "flowData.json");
downloadAnchorNode.click();
downloadAnchorNode.remove();
this.$message.success("正在下载中,请稍后...")
}).catch(() => {
this.$message.success("正在下载中,请稍后...");
})
},
}
}
.catch(() => {});
},
},
};
</script>
<style lang="scss" type="text/scss">
.moveR-enter-active, .moveR-leave-active {
transition: all 0.3s linear;
transform: translateX(0);
}
.moveR-enter, .moveR-leave {
transform: translateX(100%);
}
.moveR-leave-to {
transform: translateX(100%);
}
.moveL-enter-active, .moveL-leave-active {
transition: all 0.3s linear;
transform: translateX(0%);
}
.moveL-enter,
.moveL-leave {
transform: translateX(-100%);
}
.moveL-leave-to {
transform: translateX(-100%);
}
.moveR-enter-active,
.moveR-leave-active {
transition: all 0.3s linear;
transform: translateX(0);
}
.moveR-enter,
.moveR-leave {
transform: translateX(100%);
}
.moveR-leave-to {
transform: translateX(100%);
}
.moveL-enter-active,
.moveL-leave-active {
transition: all 0.3s linear;
transform: translateX(0%);
}
.moveL-enter,
.moveL-leave {
transform: translateX(-100%);
}
.moveL-leave-to {
transform: translateX(-100%);
}
</style>
import mx from 'mxgraph';
const mxgraph = mx({
mximagebasepath: './src/images',
mxbasepath: './src'
});
// decode bug https://github.com/jgraph/mxgraph/issues/49
window.mxgraph = mxgraph.mxgraph;
window.mxgraphmodel = mxgraph.mxgraphmodel;
window.mxeditor = mxgraph.mxeditor;
window.mxgeometry = mxgraph.mxgeometry;
window.mxdefaultkeyhandler = mxgraph.mxdefaultkeyhandler;
window.mxdefaultpopupmenu = mxgraph.mxdefaultpopupmenu;
window.mxstylesheet = mxgraph.mxstylesheet;
window.mxdefaulttoolbar = mxgraph.mxdefaulttoolbar;
export default mxgraph;
\ No newline at end of file
......@@ -10,7 +10,8 @@
<!-- <div class="ef-node-left"></div> -->
<!-- 节点类型的图标 -->
<div class="el-node-icon ef-node-left-ico flow-node-drag">
<i :class="nodeIcoClass"></i>
<img :src="node.ico" alt="" class=" flow-node-drag">
<!-- <i :class="nodeIcoClass"></i> -->
</div>
<!-- 节点名称 -->
<div class="ef-node-text" :show-overflow-tooltip="true">
......
<template>
<div class="flow-menu" ref="tool">
<div v-for="menu in menuList" :key="menu.id">
<!-- <span class="ef-node-pmenu" @click="menu.open = !menu.open">
<div class="flow-menu" ref="tool">
<!-- <div v-for="menu in menuList" :key="menu.id"> -->
<!-- <span class="ef-node-pmenu" @click="menu.open = !menu.open">
<i :class="{'el-icon-caret-bottom': menu.open,'el-icon-caret-right': !menu.open}"></i>&nbsp;
{{menu.name}}
</span> -->
<ul v-show="menu.open" class="ef-node-menu-ul">
<draggable @end="end" @start="move" v-model="menu.children" :options="draggableOptions">
<li v-for="subMenu in menu.children" class="ef-node-menu-li" :key="subMenu.id" :type="subMenu.type">
<i :class="subMenu.ico"></i> {{subMenu.name}}
</li>
</draggable>
</ul>
</div>
<!-- 文件夹存放区域start-->
<el-tree
:data="jobTreeList"
:auto-expand-parent="true"
:check-strictly="true"
:default-expand-all="false"
node-key="id"
ref="tree"
:props="defaultProps"
:highlight-current="true"
draggable
@allowDrop="allowDrop"
@node-drag-start="handleDragStart"
@node-drag-end="handleDragend"
>
<!-- el-icon-folder -->
<!-- <span class="custom-tree-node" slot-scope="{node,data}">
<!--
<ul v-show="menu.open" class="ef-node-menu-ul">
<draggable
@end="end"
@start="move"
v-model="menu.children"
:options="draggableOptions"
>
<li
v-for="subMenu in menu.children"
class="ef-node-menu-li"
:key="subMenu.id"
:type="type"
>
<i :class="subMenu.ico"></i>
{{ subMenu.name }}
</li>
</draggable>
</ul> -->
<!-- </div> -->
<!-- 文件夹存放区域start-->
<el-tree
:data="jobTreeList"
:auto-expand-parent="true"
:check-strictly="true"
:default-expand-all="false"
node-key="id"
ref="tree"
:props="defaultProps"
:highlight-current="true"
draggable
@allowDrop="allowDrop"
@node-drag-start="handleDragStart"
@node-drag-end="handleDragend"
>
<!-- el-icon-folder -->
<!-- <span class="custom-tree-node" slot-scope="{node,data}">
<span>
<i :class="data.icon"></i>{{ node.label }}
</span>
</span> -->
<span class="custom-tree-node" slot-scope="{node,data}">
<span>
<i class="el-icon-folder"></i>{{ node.label }}
</span>
</span>
</el-tree>
<!-- 文件夹存放区域end -->
</div>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>
<img :src="prefix+data.icon" style="width:20px" width="" alt="">
{{ node.label }}
</span>
</span>
</el-tree>
<!-- 文件夹存放区域end -->
</div>
</template>
<script>
import draggable from 'vuedraggable'
import draggable from "vuedraggable";
import { steps } from "@/api/kettle/link";
var mousePosition = {
left: -1,
top: -1
}
import mxgraph from "./index.js";
// const {mxgraph, mxclient, mxcodec, mxutils, mxconstants, mxperimeter} = mxgraph;
var mousePosition = {
left: -1,
top: -1,
};
export default {
data() {
return {
// 测试数据开始=====
jobTreeList:[
{
path: 'f0',
id: '1',
parent: '0',
lasted: false,
type: 'timeQuantum',
ico: 'el-icon-upload',
},
{
path: 'f01',
id: '2',
parent: '1',
lasted: true,
type: 'timeQuantum',
ico: 'el-icon-upload',
},
{
path: 'f02',
id: '3',
parent: '1',
lasted: true,
type: 'timeQuantum',
ico: 'el-icon-upload',
},
{
path: 'f021',
id: '6',
parent: '3',
lasted: false,
type: 'timeQuantum',
},
{
path: 'f021',
id: '7',
parent: '6',
lasted: false,
type: 'timeQuantum',
ico: 'el-icon-upload',
},
{
path: 'f40',
id: '4',
parent: '0',
lasted: false,
type: 'timeQuantum',
ico: 'el-icon-upload',
},
{
path: 'f41',
id: '5',
parent: '4',
lasted: true,
type: 'timeQuantum',
ico: 'el-icon-upload',
}
],
defaultProps: {
label: 'path',
children: 'children',
},
// 测试数据结束=====
activeNames: '1',
// draggable配置参数参考 https://www.cnblogs.com/weixin186/p/10108679.html
draggableOptions: {
preventOnFilter: false,
sort: false,
disabled: false,
ghostClass: 'tt',
// 不使用H5原生的配置
forceFallback: true,
// 拖拽的时候样式
// fallbackClass: 'flow-node-draggable'
},
// 默认打开的左侧菜单的id
defaultOpeneds: ['1'],
menuList: [
{
id: '1',
type: 'group',
name: '基础节点',
ico: 'el-icon-video-play',
open: true,
children: [
{
id: '01',
type: 'start',
name: '开始',
ico: 'el-icon-caret-right',
// 自定义覆盖样式
style: {}
}, {
id: '02',
type: 'channel',
name: '渠道',
ico: 'el-icon-s-ticket',
// 自定义覆盖样式
style: {}
}, {
id: '03',
type: 'customerFission',
name: '客群',
ico: 'el-icon-s-grid',
// 自定义覆盖样式
style: {}
}, {
id: '04',
type: 'intelligentRecommend',
name: '智能推荐',
ico: 'el-icon-upload',
// 自定义覆盖样式
style: {}
}, {
id: '05',
type: 'handmadeRecommend',
name: '手工推荐',
ico: 'el-icon-s-custom',
// 自定义覆盖样式
style: {}
}, {
id: '06',
type: 'timeQuantum',
name: '时间段',
ico: 'el-icon-time',
// 自定义覆盖样式
style: {}
},{
id: '07',
type: 'end',
name: '结束',
ico: 'el-icon-switch-button',
// 自定义覆盖样式
style: {}
}
]
}
],
nodeMenu: {}
}
export default {
data() {
return {
prefix:'http://192.168.0.44:9700/etlweb/',
// 测试数据开始=====
jobTreeList: [
{
path: "f0",
id: "1",
parent: "0",
lasted: false,
type: "timeQuantum",
ico: "el-icon-upload",
},
components: {
draggable
{
path: "f01",
id: "2",
parent: "1",
lasted: true,
type: "timeQuantum",
ico: "el-icon-upload",
},
created() {
/**
* 以下是为了解决在火狐浏览器上推拽时弹出tab页到搜索问题
* @param event
*/
if (this.isFirefox()) {
document.body.ondrop = function (event) {
// 解决火狐浏览器无法获取鼠标拖拽结束的坐标问题
mousePosition.left = event.layerX
mousePosition.top = event.clientY - 50
event.preventDefault();
event.stopPropagation();
}
}
{
path: "f02",
id: "3",
parent: "1",
lasted: true,
type: "timeQuantum",
ico: "el-icon-upload",
},
mounted(){
this.treeRevert(this.jobTreeList);
{
path: "f021",
id: "6",
parent: "3",
lasted: false,
type: "timeQuantum",
},
methods: {
// 根据类型获取左侧菜单对象
// getMenuByType(type) {
// for (let i = 0; i < this.menuList.length; i++) {
// let children = this.menuList[i].children;
// for (let j = 0; j < children.length; j++) {
// if (children[j].type === type) {
// return children[j]
// }
// }
// }
// },
getMenuByType(type) {
for (let i = 0; i < this.jobTreeList.length; i++) {
let children = this.jobTreeList;
for (let j = 0; j < children.length; j++) {
if (children[j].type === type) {
return children[j]
}
}
}
{
path: "f021",
id: "7",
parent: "6",
lasted: false,
type: "timeQuantum",
ico: "el-icon-upload",
},
{
path: "f40",
id: "4",
parent: "0",
lasted: false,
type: "timeQuantum",
ico: "el-icon-upload",
},
{
path: "f41",
id: "5",
parent: "4",
lasted: true,
type: "timeQuantum",
ico: "el-icon-upload",
},
],
defaultProps: {
label: "text",
children: "children",
},
// 测试数据结束=====
activeNames: "1",
// draggable配置参数参考 https://www.cnblogs.com/weixin186/p/10108679.html
draggableOptions: {
preventOnFilter: false,
sort: false,
disabled: false,
ghostClass: "tt",
// 不使用H5原生的配置
forceFallback: true,
// 拖拽的时候样式
// fallbackClass: 'flow-node-draggable'
},
// 默认打开的左侧菜单的id
defaultOpeneds: ["1"],
menuList: [
{
id: "1",
type: "group",
name: "基础节点",
ico: "el-icon-video-play",
open: true,
children: [
{
id: "01",
type: "start",
name: "没了",
ico: "el-icon-caret-right",
// 自定义覆盖样式
style: {},
},
// 拖拽开始时触发
move(evt, a, b, c) {
var type = evt.item.attributes.type.nodeValue
this.nodeMenu = this.getMenuByType(type)
{
id: "02",
type: "channel",
name: "渠道",
ico: "el-icon-s-ticket",
// 自定义覆盖样式
style: {},
},
// 拖拽结束时触发
end(evt, e) {
this.$emit('addNode', evt, this.nodeMenu, mousePosition)
{
id: "03",
type: "customerFission",
name: "客群",
ico: "el-icon-s-grid",
// 自定义覆盖样式
style: {},
},
// 是否是火狐浏览器
isFirefox() {
var userAgent = navigator.userAgent
if (userAgent.indexOf("Firefox") > -1) {
return true
}
return false
{
id: "04",
type: "intelligentRecommend",
name: "智能推荐",
ico: "el-icon-upload",
// 自定义覆盖样式
style: {},
},
//文件夹数据转换
treeRevert(arrayList){
console.log('传入数据=============',arrayList);
let formatObj = arrayList.reduce((pre, cur) => {
return {...pre, [cur['id']]: cur}
}, {});
console.log(formatObj);
let formatArray = arrayList.reduce((arr, cur) => {
// let pid = cur.pid ? cur.pid : 0;
let pid = cur.parent ? cur.parent : 0;
let parent = formatObj[pid];
cur.disabled = !cur.lasted;
if (parent) {
parent.children ? parent.children.push(cur) : parent.children=[cur];
} else {
arr.push(cur)
}
return arr;
}, []);
console.log('树形数据=============',formatArray);
this.jobTreeList=formatArray;
{
id: "05",
type: "h/andmadeRecommend",
name: "手工推荐",
ico: "el-icon-s-custom",
// 自定义覆盖样式
style: {},
},
{
id: "06",
type: "timeQuantum",
name: "时间段",
ico: "el-icon-time",
// 自定义覆盖样式
style: {},
},
{
id: "07",
type: "end",
name: "结束",
ico: "el-icon-switch-button",
// 自定义覆盖样式
style: {},
},
],
},
],
nodeMenu: {},
};
},
components: {
draggable,
},
created() {
/**
* 以下是为了解决在火狐浏览器上推拽时弹出tab页到搜索问题
* @param event
*/
if (this.isFirefox()) {
document.body.ondrop = function (event) {
// 解决火狐浏览器无法获取鼠标拖拽结束的坐标问题
mousePosition.left = event.layerX;
mousePosition.top = event.clientY - 50;
event.preventDefault();
event.stopPropagation();
};
}
this.stepsFun();
},
mounted() {
this.treeRevert(this.jobTreeList);
},
methods: {
mounted() {
if (!mxClient.isBrowserSupported()) {
// 判断是否支持mxgraph
mxUtils.error("Browser is not supported!", 200, false);
} else {
// 再容器中创建图表
let container = document.getElementById("graphContainer");
let MxGraph = mxGraph;
let MxCodec = mxCodec;
var graph = new MxGraph(container);
// 生成 Hello world!
var parent = graph.getDefaultParent();
graph.getModel().beginUpdate();
try {
var v1 = graph.insertVertex(parent, null, "Hello,", 20, 200, 80, 30);
var v2 = graph.insertVertex(parent, null, "World", 200, 150, 80, 30);
var v3 = graph.insertVertex(
parent,
null,
"everyBody!",
300,
350,
60,
60
);
graph.insertEdge(parent, null, "", v1, v2);
graph.insertEdge(parent, null, "", v2, v3);
graph.insertEdge(parent, null, "", v1, v3);
} finally {
// Updates the display
graph.getModel().endUpdate();
}
// 打包XML文件
let encoder = new MxCodec();
let xx = encoder.encode(graph.getModel());
// 保存到getXml参数中
this.getXml = mxUtils.getXml(xx);
}
},
// allowDrag(model, component) {
// console.log('树形拖拽开始:===',model);
// // if (model.name === 'Node 0-1') {
// // // can't be dragged
// // return false;
// // }
// // // can be dragged
// // return true;
// },
// allowDrop(draggingNode, dropNode, type){
// // console.log('树形拖拽1:===',draggingNode);
// // console.log('树形拖拽2:===',dropNode);
// // console.log('树形拖拽3:===',type);
// },
handleDragStart(Node,event) {
console.log('树形拖拽开始:===',Node);
console.log('树形拖拽开始2:===',event);
var type = Node.data.type;
this.nodeMenu = this.getMenuByType(type)
},
stepsFun() {
let pamer = new FormData(); // 创建form对象
pamer.append("node", "xnode-12");
this.$forceUpdate();
steps(pamer).then((res) => {
this.jobTreeList = res
console.log(this.menuList,res[0]);
});
},
handleDragend (draggingNode, endNode, position, event) {
// console.log('树形拖拽结束1:===',draggingNode);
// console.log('树形拖拽结束2:===',endNode);
// console.log('树形拖拽结束3:===',position);
console.log('树形拖拽结束4:===',event);
console.log('树形拖拽结束51:===',draggingNode);
console.log('树形拖拽结束5:===',endNode);
// this.$emit('addNode', event, this.nodeMenu, mousePosition)
this.$emit('addNode', event, draggingNode, mousePosition)
// if (draggingNode.level === endNode.level) {
// console('=========================');
// // this.$emit('addNode', event, this.nodeMenu, mousePosition)
// this.$emit('addNode', event, this.nodeMenu, mousePosition)
// } else {
// // 不同级进行处理
// return false;
// }
},
// 根据类型获取左侧菜单对象
// getMenuByType(type) {
// for (let i = 0; i < this.menuList.length; i++) {
// let children = this.menuList[i].children;
// for (let j = 0; j < children.length; j++) {
// if (children[j].type === type) {
// return children[j]
// }
// }
// }
// },
getMenuByType(type) {
for (let i = 0; i < this.jobTreeList.length; i++) {
let children = this.jobTreeList;
for (let j = 0; j < children.length; j++) {
if (children[j].type === type) {
return children[j];
}
}
}
},
// 拖拽开始时触发
move(evt, a, b, c) {
var type = evt.item.attributes.type.nodeValue;
this.nodeMenu = this.getMenuByType(type);
},
// 拖拽结束时触发
end(evt, e) {
this.$emit("addNode", evt, this.nodeMenu, mousePosition);
},
// 是否是火狐浏览器
isFirefox() {
var userAgent = navigator.userAgent;
if (userAgent.indexOf("Firefox") > -1) {
return true;
}
return false;
},
//文件夹数据转换
treeRevert(arrayList) {
console.log("传入数据=============", arrayList);
let formatObj = arrayList.reduce((pre, cur) => {
return { ...pre, [cur["id"]]: cur };
}, {});
console.log(formatObj);
// // 拖拽开始时触发
// move(evt, a, b, c) {
// var type = evt.item.attributes.type.nodeValue
// this.nodeMenu = this.getMenuByType(type)
// },
// // 拖拽结束时触发
// end(evt, e) {
// this.$emit('addNode', evt, this.nodeMenu, mousePosition)
// },
// allowDrop(draggingNode, dropNode, type){
// if(draggingNode.level === dropNode.level){
// if(draggingNode.parent.id === dropNode.parent.id){
// // return type === 'prev'
// }
// }else{
// // 不同级进行处理
// }
// }
allowDrop(event) {
event.preventDefault()
},
let formatArray = arrayList.reduce((arr, cur) => {
// let pid = cur.pid ? cur.pid : 0;
let pid = cur.parent ? cur.parent : 0;
let parent = formatObj[pid];
cur.disabled = !cur.lasted;
if (parent) {
parent.children
? parent.children.push(cur)
: (parent.children = [cur]);
} else {
arr.push(cur);
}
return arr;
}, []);
console.log("树形数据=============", formatArray);
this.jobTreeList = formatArray;
},
// allowDrag(model, component) {
// console.log('树形拖拽开始:===',model);
// // if (model.name === 'Node 0-1') {
// // // can't be dragged
// // return false;
// // }
// // // can be dragged
// // return true;
// },
// allowDrop(draggingNode, dropNode, type){
// // console.log('树形拖拽1:===',draggingNode);
// // console.log('树形拖拽2:===',dropNode);
// // console.log('树形拖拽3:===',type);
// },
handleDragStart(Node, event) {
console.log("树形拖拽开始:===", Node);
console.log("树形拖拽开始2:===", event);
var type = Node.data.type;
this.nodeMenu = this.getMenuByType(type);
},
// ===============
handleDragend(draggingNode, endNode, position, event) {
// console.log('树形拖拽结束1:===',draggingNode);
// console.log('树形拖拽结束2:===',endNode);
// console.log('树形拖拽结束3:===',position);
}
}
console.log("树形拖拽结束4:===", event);
console.log("树形拖拽结束51:===", draggingNode);
console.log("树形拖拽结束5:===", endNode);
// this.$emit('addNode', event, this.nodeMenu, mousePosition)
this.$emit("addNode", event, draggingNode, mousePosition);
this.stepsFun();
// if (draggingNode.level === endNode.level) {
// console('=========================');
// // this.$emit('addNode', event, this.nodeMenu, mousePosition)
// this.$emit('addNode', event, this.nodeMenu, mousePosition)
// } else {
// // 不同级进行处理
// return false;
// }
},
// // 拖拽开始时触发
// move(evt, a, b, c) {
// var type = evt.item.attributes.type.nodeValue
// this.nodeMenu = this.getMenuByType(type)
// },
// // 拖拽结束时触发
// end(evt, e) {
// this.$emit('addNode', evt, this.nodeMenu, mousePosition)
// },
// allowDrop(draggingNode, dropNode, type){
// if(draggingNode.level === dropNode.level){
// if(draggingNode.parent.id === dropNode.parent.id){
// // return type === 'prev'
// }
// }else{
// // 不同级进行处理
// }
// }
allowDrop(event) {
event.preventDefault();
},
// ===============
},
};
</script>
......@@ -79,6 +79,7 @@
<span class="custom-tree-node" slot-scope="{node,data}">
<span>
<i class="el-icon-folder"></i>{{ node.label }}
</span>
</span>
......@@ -482,6 +483,7 @@
<span class="custom-tree-node" slot-scope="{node,data}">
<span>
<i class="el-icon-folder"></i>{{ node.label }}
</span>
</span>
......@@ -546,6 +548,9 @@ import {
loginRepository,//连接数据库
addRepository,//资源库信息
} from "@/api/kettle/link";
export default {
components: {
FlowDesigner,
......@@ -728,6 +733,14 @@ export default {
// this.test();
},
methods: {
// 左边文件夹和右边画布的宽度可以拖拽调整
dragControllerDiv: function () {
var resize = document.getElementsByClassName('resize');
......@@ -1175,6 +1188,7 @@ export default {
console.log('天加evt==',evt);
console.log('天加nodeMenu==',draggingNode.data);
var nodeMenu=draggingNode.data;
// var screenX = evt.originalEvent.clientX, screenY = evt.originalEvent.clientY
// let efContainer = this.$refs.efContainer
var screenX = evt.clientX, screenY = evt.clientY
......@@ -1203,12 +1217,13 @@ export default {
console.log('-------003',nodeMenu.type);
var node = {
id: nodeId, //节点id--前端唯一的
name: nodeName, //节点名称
name: nodeMenu.text, //节点名称
type: nodeMenu.type, //节点类型
left: left + 'px', //坐标
top: top + 'px', //坐标
ico: nodeMenu.ico, //图标
ico: this.prefix+nodeMenu.icon, //图标
}
console.log(node);
/**
* 这里可以进行业务判断、是否能够添加该节点
......
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