<!-- eslint-disable vue/valid-v-for -->
|
<!-- eslint-disable vue/require-v-for-key -->
|
<template>
|
<vue-flowchart-editor class="vue-flowchart-editor" ref="flowChart">
|
<div class="vfe-chart">
|
<!-- Top Menu -->
|
<div class="vfe-chart-header" v-if="type !== 'detail'">
|
<editor-toolbar :chart-data="flowChartData" />
|
</div>
|
<div class="vfe-chart-container">
|
<!-- Left Items -->
|
<div class="vfe-chart-sidebar" v-if="type !== 'detail'">
|
<editor-item-panel :node-items="flowChartNodeItems" />
|
</div>
|
<!-- Main Chart -->
|
<div class="vfe-chart-main">
|
<flow :data="flowChartData" :onAfterChange="onAfterChange" />
|
<div class="tooltip">
|
<template v-for="item in tooltipData">
|
<p>{{ item.name }}: {{ item.value }}</p>
|
</template>
|
</div>
|
</div>
|
<div class="vfe-chart-panel" v-if="type !== 'detail'">
|
<div class="vfe-chart-panel-detail">
|
<editor-detail-panel :rowData="rowData" ref="EditorDetailPanel" :existNodes="existNodes" :type="type"/>
|
</div>
|
</div>
|
</div>
|
</div>
|
<!-- Mouse Right Button Context Menu -->
|
<editor-context-menu v-if="type !== 'detail'" />
|
<register-edge
|
name="custom-polyline"
|
extend="flow-polyline"
|
:config="customEdgeConfig"
|
/>
|
<custom-command :download="downloadImage" />
|
</vue-flowchart-editor>
|
</template>
|
|
<script>
|
import VueFlowchartEditor, { Flow, RegisterEdge } from "vue-flowchart-editor";
|
import EditorToolbar from "./components/Toolbar";
|
import EditorItemPanel from "./components/ItemPanel";
|
import EditorDetailPanel from "./components/DetailPanel";
|
import EditorMinimap from "./components/EditorMinimap";
|
import EditorContextMenu from "./components/ContextMenu";
|
import CustomCommand from "./components/CustomCommand";
|
|
export default {
|
name: "FlowchartEditor",
|
|
components: {
|
VueFlowchartEditor,
|
Flow,
|
EditorToolbar,
|
EditorItemPanel,
|
EditorDetailPanel,
|
EditorMinimap,
|
EditorContextMenu,
|
CustomCommand,
|
RegisterEdge,
|
},
|
|
props: ["chartData", "chartDataNodeItems", "saveData", "rowData", "type"],
|
|
data() {
|
return {
|
flowChartData: this.chartData,
|
flowChartNodeItems: this.chartDataNodeItems,
|
customEdgeConfig: {
|
getActivedStyle(/*item*/) {
|
return {
|
lineWidth: 3,
|
};
|
},
|
getSelectedStyle(/*item*/) {
|
return {
|
lineWidth: 3,
|
};
|
},
|
},
|
tooltipShow: true,
|
tooltipData: [],
|
existNodes: this.chartData.nodes || []
|
};
|
},
|
|
mounted() {
|
if (this.type === "add") {
|
this.$nextTick(() => {
|
this.$refs.flowChart.propsAPI.executeCommand("autoZoom");
|
});
|
}
|
},
|
|
methods: {
|
onAfterChange(e) {
|
try {
|
if (e.action === "add" && e.model.type === "node") {
|
if (!e.model.change) {
|
this.$refs.flowChart.propsAPI.remove(e.item);
|
e.model.id = e.model.label;
|
e.model.change = true;
|
this.$refs.flowChart.propsAPI.add("node", e.model);
|
}
|
}
|
} catch (err) {
|
if (
|
err.message ===
|
`id:${e.model.label} has already been set, please set new one`
|
) {
|
this.$message.error("不能添加已存在的节点!");
|
}
|
}
|
const { nodes } = this.$refs.flowChart.propsAPI.save()
|
this.existNodes = nodes || []
|
console.log(this.$refs.flowChart.propsAPI.save());
|
},
|
_downloadImage(data, filename = "flowchart.png") {
|
const a = document.createElement("a");
|
a.href = data;
|
a.download = filename;
|
document.body.appendChild(a);
|
a.click();
|
},
|
|
downloadImage() {
|
const page = this.$refs["flowChart"].propsAPI.editor.getCurrentPage();
|
this._downloadImage(page.saveImage().toDataURL("image/png"));
|
},
|
getNewRowData() {
|
return this.$refs.EditorDetailPanel.getNewRowDate();
|
},
|
getFlowData() {
|
return this.$refs.flowChart.propsAPI.save();
|
},
|
},
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
.vue-flowchart-editor {
|
display: flex;
|
flex: 1;
|
flex-direction: column;
|
width: 100%;
|
height: 100%;
|
background: #fff;
|
}
|
|
.vfe-chart {
|
position: relative;
|
width: 100%;
|
height: 100%;
|
display: flex;
|
flex-direction: column;
|
|
.vfe-chart-header {
|
border: 1px solid #e6e9ed;
|
padding: 8px;
|
}
|
|
.vfe-chart-container {
|
flex: 1;
|
display: flex;
|
height: 550px;
|
overflow: hidden;
|
.vfe-chart-main {
|
position: relative;
|
flex: 1;
|
max-height: calc(100% - 5px); // fix scroll show
|
|
.tooltip {
|
position: absolute;
|
display: none;
|
top: 0;
|
left: 0;
|
width: 100px;
|
height: auto;
|
padding: 15px;
|
border-radius: 10px;
|
z-index: 999;
|
opacity: 0.8;
|
color: #ffffff;
|
font-size: 12px;
|
background-color: #000;
|
|
p {
|
margin: 0;
|
}
|
}
|
}
|
|
.vfe-chart-sidebar {
|
position: relative;
|
display: flex;
|
justify-content: center;
|
width: 15%;
|
background-color: #fafafa;
|
border-right: 1px solid #e6e9ed;
|
}
|
|
.vfe-chart-panel {
|
position: relative;
|
width: 300px;
|
background-color: #fafafa;
|
border-left: 1px solid #e6e9ed;
|
overflow-y: scroll;
|
|
.vfe-chart-panel-detail {
|
box-sizing: border-box;
|
padding: 10px;
|
}
|
}
|
}
|
}
|
</style>
|