|
|
@@ -1,9 +1,10 @@
|
|
|
<template>
|
|
|
<div>
|
|
|
<!-- <el-button type="primary" @click="saveFlow">测试</el-button> -->
|
|
|
- <div style="display: flex;margin-left: 1%;padding-top: 1%;position: absolute;z-index: 1000;cursor: pointer;justify-content: space-between;width: 98%;">
|
|
|
- <el-icon size="large" @click="back"><Back /></el-icon>
|
|
|
- <el-button style="margin-left: auto;" type="danger" size="mini">删除</el-button>
|
|
|
+ <div style="display: flex;margin-left: 1%;padding-top: 0.5%;position: absolute;z-index: 1000;justify-content: space-between;width: 98%;align-items: center;">
|
|
|
+ <el-icon size="large" style="cursor: pointer" @click="back"><Back /></el-icon>
|
|
|
+ <el-button @click="delWholeFlow" style="margin-left: auto;" type="danger" size="mini">删除</el-button>
|
|
|
+ <el-button style="margin-left: 1%;" type="info" size="mini" plain @click="toImage">导出为图片</el-button>
|
|
|
<el-button style="margin-left: 1%;" type="primary" size="mini" @click="saveFlow">保存</el-button>
|
|
|
</div>
|
|
|
<div v-if="nodeDeSer" style="height: 85vh;width: 20vw;position: absolute;float: right;z-index: 1000;right: 1%;top: 1%;border: 0.1px solid #dedfe0;border-radius: 6px;background-color: white;">
|
|
|
@@ -61,12 +62,15 @@
|
|
|
<el-form-item label="失败重连次数">
|
|
|
<el-input-number v-model="form.retryCount" :min="1" style="width: 50%" :max="30"/>
|
|
|
</el-form-item>
|
|
|
+ <el-form-item label="输出">
|
|
|
+ <el-input v-model="form.output" style="width: 100%" type="textarea" />
|
|
|
+ </el-form-item>
|
|
|
</el-form>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div style="display: flex;height: 85vh;width: 100%;padding-top:2%;">
|
|
|
- <div style="width: 20%;margin-left: 1%;overflow-y: auto;">
|
|
|
+ <div style="display: flex;height: 87vh;width: 100%;padding-top:2%;justify-items: center;">
|
|
|
+ <div style="width: 20%;margin-left: 1%;overflow-y: auto;margin-top: 0.5%;">
|
|
|
<el-input
|
|
|
v-model="inputNode"
|
|
|
style="width:90%;margin-left: 5%;background-color: #ebeef5;margin-top: 1%;"
|
|
|
@@ -74,7 +78,7 @@
|
|
|
:prefix-icon="Search"
|
|
|
/>
|
|
|
<el-tree :expand-on-click-node="false" ref="treeRef" :filter-node-method="filterNode" :current-node-key="currentNodeKey" class="treeLeft" :data="dataTree"
|
|
|
- @node-click="handleNodeClick" node-key="id" style="margin-left: 5%;margin-top: 2%;width: 90%;background-color: transparent;" default-expand-all :key="valueKet">
|
|
|
+ @node-click="handleNodeClick" node-key="id" style="margin-left: 5%;margin-top: 3%;width: 90%;background-color: transparent;" default-expand-all :key="valueKet">
|
|
|
<template #default="{ node, data }">
|
|
|
<span style="justify-content: space-between;display: flex;width: 100%;align-items: center;">
|
|
|
<div class="custom-tree-node":draggable="true"
|
|
|
@@ -92,72 +96,80 @@
|
|
|
</template>
|
|
|
</el-tree>
|
|
|
</div>
|
|
|
- <VueFlow :nodes="nodes" :viewport="zoom" :edges="edges" @drop="onDrop" @dragover="onDragOver" @dragleave="onDragLeave"
|
|
|
- @node-click="onNodeClick" @connect="onConnect" fit-view-on-init>
|
|
|
- <template #node-special="specialNodeProps">
|
|
|
- <div v-if="specialNodeProps.data.label=='开始'" class="vue-flow__node-default" style="border: 0.2px solid #c8c9cc;border-radius: 6px;min-height: 6vh;min-width: 11vw">
|
|
|
- <div style='width:100%;font-size:10px;display:flex;align-items:flex-end;height: 10px;margin-top: 2%;'>
|
|
|
- <img style="width: 15px;height:15px;border-radius: 12px;" src="@/assets/images/icon-Start-v2.jpg" alt="">
|
|
|
- <div style="margin-left: 3%;font-weight: 500;">
|
|
|
- 开始
|
|
|
+ <div ref="flowContainer" style="width: 80%;">
|
|
|
+ <VueFlow style="background-color: #EFEFF4;margin-top: 0.5%;" :nodes="nodes" :viewport="zoom" :edges="edges" @drop="onDrop" @dragover="onDragOver" @dragleave="onDragLeave"
|
|
|
+ @node-click="onNodeClick" @connect="onConnect" fit-view-on-init>
|
|
|
+ <Controls :showInteractive="false" :showFitView="false"/>
|
|
|
+ <template #node-special="specialNodeProps">
|
|
|
+ <div v-if="specialNodeProps.data.label=='开始'" class="vue-flow__node-default" style="border: 0.2px solid #c8c9cc;border-radius: 6px;min-height: 6vh;min-width: 11vw">
|
|
|
+ <div style='width:100%;font-size:10px;display:flex;align-items:flex-end;height: 10px;margin-top: 2%;'>
|
|
|
+ <img style="width: 15px;height:15px;border-radius: 12px;" src="@/assets/images/icon-Start-v2.jpg" alt="">
|
|
|
+ <div style="margin-left: 3%;font-weight: 500;">
|
|
|
+ 开始
|
|
|
+ </div>
|
|
|
+ <el-tag class="ml-2" style="width: 30px;height: 15px;font-size: 7px;margin-left: 6%;" type="info">触发器</el-tag>
|
|
|
</div>
|
|
|
- <el-tag class="ml-2" style="width: 30px;height: 15px;font-size: 7px;margin-left: 6%;" type="info">触发器</el-tag>
|
|
|
+ <Handle type="source" :position="Position.Right"/>
|
|
|
</div>
|
|
|
- <Handle type="source" :position="Position.Right"/>
|
|
|
- </div>
|
|
|
- <div v-if="specialNodeProps.data.label=='结束'" class="vue-flow__node-default" style="border: 0.2px solid #c8c9cc;border-radius: 6px;min-height: 6vh;min-width: 11vw">
|
|
|
- <div style='width:100%;font-size:10px;display:flex;align-items:flex-end;height: 10px;margin-top: 2%;'>
|
|
|
- <img style="width: 15px;height:15px;border-radius: 12px;" src="@/assets/images/icon-Start-v2.jpg" alt="">
|
|
|
- <div style="margin-left: 3%;font-weight: 500;">
|
|
|
- 结束
|
|
|
- </div>
|
|
|
- <div>
|
|
|
+ <div v-if="specialNodeProps.data.label=='结束'" class="vue-flow__node-default" style="border: 0.2px solid #c8c9cc;border-radius: 6px;min-height: 6vh;min-width: 11vw">
|
|
|
+ <div style='width:100%;font-size:10px;display:flex;align-items:flex-end;height: 10px;margin-top: 2%;'>
|
|
|
+ <img style="width: 15px;height:15px;border-radius: 12px;" src="@/assets/images/icon-Start-v2.jpg" alt="">
|
|
|
+ <div style="margin-left: 3%;font-weight: 500;">
|
|
|
+ 结束
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ <Handle type="target" :position="Position.Left"/>
|
|
|
</div>
|
|
|
- <Handle type="target" :position="Position.Left"/>
|
|
|
- </div>
|
|
|
- <div v-if="specialNodeProps.data.label!=='结束'&&specialNodeProps.data.label!=='开始'" class="vue-flow__node-default"
|
|
|
- style="border: 0.5px solid #c8c9cc;border-radius: 6px;border-radius: 6px;min-height: 8vh;min-width: 13vw">
|
|
|
- <div style='width:100%;font-size:10px;display:flex;align-items:flex-end;height: 10px;margin-top: 2%;justify-content: space-between;'>
|
|
|
- <img style="width: 15px;height:15px;border-radius: 12px;" src="@/assets/images/icon-HTTP.png" alt="">
|
|
|
- <div style="margin-left:3%;font-weight: 500;">
|
|
|
- {{ specialNodeProps.data.label }}
|
|
|
+ <div v-if="specialNodeProps.data.label!=='结束'&&specialNodeProps.data.label!=='开始'" class="vue-flow__node-default"
|
|
|
+ style="border: 0.5px solid #c8c9cc;border-radius: 6px;border-radius: 6px;min-height: 8vh;min-width: 13vw">
|
|
|
+ <div style='width:100%;font-size:10px;display:flex;align-items:flex-end;height: 10px;margin-top: 2%;justify-content: space-between;'>
|
|
|
+ <img style="width: 15px;height:15px;border-radius: 12px;" src="@/assets/images/icon-HTTP.png" alt="">
|
|
|
+ <div style="margin-left:3%;font-weight: 500;">
|
|
|
+ {{ specialNodeProps.data.label }}
|
|
|
+ </div>
|
|
|
+ <el-icon style="cursor: pointer;margin-left: auto;"><CaretRight /></el-icon>
|
|
|
+ <el-icon @click.stop="delNode(specialNodeProps.data)" style="cursor: pointer;color: #F56C6C;margin-left: 2%;"><Delete /></el-icon>
|
|
|
</div>
|
|
|
- <el-icon style="cursor: pointer;margin-left: auto;"><CaretRight /></el-icon>
|
|
|
- <el-icon @click.stop="delNode(specialNodeProps.data)" style="cursor: pointer;color: #F56C6C;margin-left: 2%;"><Delete /></el-icon>
|
|
|
- </div>
|
|
|
- <div style="display: flex;margin-top: 3%;">
|
|
|
- <el-tag class="ml-2" style="width: 35px;height: 20px;font-size: 10px;" type="warning">服务</el-tag>
|
|
|
- </div>
|
|
|
- <div style="display: flex;margin-top: 3%;font-size: 9px;color: #b1b3b8;flex-wrap: wrap;align-items: flex-start;">
|
|
|
- <div style="word-break: break-all;min-width: 0;width: 100%;text-align: left;">
|
|
|
- {{ specialNodeProps.data.service.rqtype+ ':' }}{{ specialNodeProps.data.service.url }}
|
|
|
+ <div style="display: flex;margin-top: 3%;">
|
|
|
+ <el-tag class="ml-2" style="width: 35px;height: 20px;font-size: 10px;" type="warning">服务</el-tag>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div style="display: flex;margin-top: 3%;font-size: 9px;color: #b1b3b8;align-items: center;">
|
|
|
- <div>
|
|
|
- 说明:
|
|
|
+ <div style="display: flex;margin-top: 3%;font-size: 9px;color: #b1b3b8;flex-wrap: wrap;align-items: flex-start;">
|
|
|
+ <div style="word-break: break-all;min-width: 0;width: 100%;text-align: left;">
|
|
|
+ {{ specialNodeProps.data.service.rqtype+ ':' }}{{ specialNodeProps.data.service.url }}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div>
|
|
|
- {{ specialNodeProps.data.service.intro }}
|
|
|
+ <div style="display: flex;margin-top: 3%;font-size: 9px;color: #b1b3b8;align-items: center;">
|
|
|
+ <div>
|
|
|
+ 说明:
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {{ specialNodeProps.data.service.intro }}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ <Handle type="source" :position="Position.Right"/>
|
|
|
+ <Handle type="target" :position="Position.Left"/>
|
|
|
</div>
|
|
|
- <Handle type="source" :position="Position.Right"/>
|
|
|
- <Handle type="target" :position="Position.Left"/>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- <template #edge-custom="specialEdgeProps">
|
|
|
- <div style="height: 1px;color: red;">
|
|
|
+ </template>
|
|
|
+ <template #edge-custom="specialEdgeProps">
|
|
|
+ <div style="height: 1px;color: red;">
|
|
|
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </VueFlow>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </VueFlow>
|
|
|
+ </div>
|
|
|
+
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
</template>
|
|
|
<script setup>
|
|
|
+import html2canvas from 'html2canvas';
|
|
|
+import { Controls } from '@vue-flow/controls'
|
|
|
+import '@vue-flow/controls/dist/style.css'
|
|
|
+import '@vue-flow/core/dist/theme-default.css';
|
|
|
import { Plus,Search } from '@element-plus/icons-vue'
|
|
|
import DynamicMap from '@/components/DynamicMap/index.vue'
|
|
|
import {Promotion} from '@element-plus/icons-vue'
|
|
|
@@ -168,7 +180,7 @@ import SpecialEdge from './components/SpecialEdge.vue'
|
|
|
import {getPtServiceList,getSerDe} from "@/api/service/info.js";
|
|
|
import {getModelList2} from "@/api/register/regCom.js";
|
|
|
import {copyObject} from "@/utils/index.js";
|
|
|
-import {getModelingDe,addModelingFlow,editModelingFlow} from "@/api/standardization/modeling.js";
|
|
|
+import {getModelingDe,addModelingFlow,editModelingFlow,delFlow} from "@/api/standardization/modeling.js";
|
|
|
import { useStore } from 'vuex';
|
|
|
import {Handle, Position} from '@vue-flow/core'
|
|
|
import { computed } from 'vue';
|
|
|
@@ -188,6 +200,8 @@ const {
|
|
|
getEdges,
|
|
|
} = useVueFlow()
|
|
|
snapToGrid.value = true
|
|
|
+const flowContainer = ref(null);
|
|
|
+const status = ref('就绪');
|
|
|
const zoom = ref();
|
|
|
const inputNode = ref('');
|
|
|
const treeRef = ref(null);
|
|
|
@@ -246,9 +260,54 @@ const store = useStore();
|
|
|
watch(inputNode, (val) => {
|
|
|
treeRef.value?.filter(val); // 调用树的过滤方法
|
|
|
});
|
|
|
+function delWholeFlow(){
|
|
|
+ proxy.$confirm('是否删除该模型流程?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ delFlow(parFlowId.value).then(res => {
|
|
|
+ if(res.code === 200){
|
|
|
+ proxy.$message({
|
|
|
+ message: '删除成功',
|
|
|
+ type: 'success'
|
|
|
+ });
|
|
|
+ getList();
|
|
|
+ } else {
|
|
|
+ proxy.$message.error('删除失败');
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+const toImage = async () => {
|
|
|
+ console.log(flowContainer.value)
|
|
|
+ await nextTick();
|
|
|
+ status.value = '生成图片中...';
|
|
|
+ try {
|
|
|
+ const canvas = await html2canvas(flowContainer.value, {
|
|
|
+ backgroundColor: '#fff', // 白底背景
|
|
|
+ scale: 2, // 提高导出清晰度
|
|
|
+ useCORS: true, // 支持跨域图片
|
|
|
+ });
|
|
|
+
|
|
|
+ // 生成下载链接
|
|
|
+ const dataUrl = canvas.toDataURL('image/png');
|
|
|
+ const link = document.createElement('a');
|
|
|
+ link.href = dataUrl;
|
|
|
+ link.download = 'vueflow-diagram.png'; // 文件名
|
|
|
+ link.click();
|
|
|
+
|
|
|
+ status.value = '导出成功!';
|
|
|
+ setTimeout(() => status.value = '就绪', 3000); // 重置状态
|
|
|
+ } catch (error) {
|
|
|
+ status.value = `导出失败: ${error.message}`;
|
|
|
+ console.error('导出错误:', error);
|
|
|
+ }
|
|
|
+};
|
|
|
function delNode(node){
|
|
|
console.log(node)
|
|
|
- nodes.value = nodes.value.filter(item => item.id !== node.id)
|
|
|
+ console.log(nodes.value)
|
|
|
+ nodes.value = nodes.value.filter(item => item.data.label !== node.label)
|
|
|
}
|
|
|
onEdgeClick(({ edge }) => {
|
|
|
console.log(edges.value,edge)
|
|
|
@@ -275,6 +334,7 @@ function saveFlow(){
|
|
|
type: 'success'
|
|
|
});
|
|
|
}
|
|
|
+ getList()
|
|
|
})
|
|
|
}
|
|
|
else{
|
|
|
@@ -292,6 +352,7 @@ function saveFlow(){
|
|
|
message: '保存成功',
|
|
|
type: 'success'
|
|
|
});
|
|
|
+ getList()
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
@@ -304,9 +365,9 @@ onNodeClick(({event, node}) => {
|
|
|
servieName.value = res.data.ptService.name
|
|
|
tableDataCan.value = res.data.list
|
|
|
serviceUrl.value = res.data.ptService.url
|
|
|
- dataReturn.value = res.data.returnList
|
|
|
+ nodeDeSer.value = true
|
|
|
})
|
|
|
- nodeDeSer.value = true
|
|
|
+
|
|
|
}
|
|
|
|
|
|
});
|
|
|
@@ -431,10 +492,15 @@ function getList() {
|
|
|
getModelingDe(par).then(res => {
|
|
|
if(res.data.length===0){
|
|
|
isAdd.value = true
|
|
|
+ nodes.value = [
|
|
|
+ { id: '1', position: { x: -600, y: -300 }, data: { label: '开始' }, type: 'special' },
|
|
|
+ { id: '2', position: { x: 150, y: 100 }, data: { label: '结束' }, type: 'special' },
|
|
|
+ ]
|
|
|
}
|
|
|
else{
|
|
|
isAdd.value = false
|
|
|
var a = JSON.parse(JSON.parse(JSON.stringify(res.data[0].flowGraph)))
|
|
|
+ console.log(a)
|
|
|
nodes.value = a.nodes
|
|
|
edges.value = a.edges
|
|
|
zoom.value = a.zoom
|