Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 20fdc78

Browse files
committed
feat: 实现JSON导出导入功能
1 parent dc4d034 commit 20fdc78

File tree

4 files changed

+295
-15
lines changed

4 files changed

+295
-15
lines changed

‎README.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44

55
## 进度
66

7-
- [ ] 实现流程配置JSON输出
8-
- [ ] 实现流程配置JSON导入渲染出流程
97
- [ ] 实现删除线段功能
108
- [ ] 实现删除节点功能
119
- [ ] 实现SVG中可选连接线段样式
10+
- [ ] 简化连线路径映射source/target数据结构
11+
- [x] 实现流程配置JSON导入渲染出流程
12+
- [x] 实现流程配置JSON输出
1213
- [x] 优化连接点位置
1314
- [x] 优化连接点选中区域
1415
- [x] 实现SVG中任意移动图形

‎src/components/Graph.vue‎

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
</template>
104104

105105
<script lang="ts">
106-
import { Component, Prop, Vue } from "vue-property-decorator";
106+
import { Component, Prop, Watch, Vue } from "vue-property-decorator";
107107
import { Getter, Action } from "vuex-class";
108108
import Node from "./Node.vue";
109109
@@ -115,7 +115,7 @@ const rectHeight = 55;
115115
const svgDx = rectWidth * 2;
116116
const svgDy = rectHeight * 2;
117117
118-
interface NodeClass {
118+
exportinterface NodeClass {
119119
id: string;
120120
title: string;
121121
x: number;
@@ -124,7 +124,7 @@ interface NodeClass {
124124
linkNode: any;
125125
}
126126
127-
interface EdgeClass {
127+
exportinterface EdgeClass {
128128
id: number;
129129
source: NodeClass | null;
130130
target: NodeClass | null;
@@ -135,6 +135,7 @@ interface EdgeClass {
135135
136136
@Component
137137
export default class Graph extends Vue {
138+
@Prop() private exportStatus!: Boolean;
138139
private nodes: NodeClass[] = [];
139140
private edges: EdgeClass[] = [];
140141
private rectWidth: String = "130px";
@@ -151,6 +152,28 @@ export default class Graph extends Vue {
151152
@Action("toggle_toLink") toggleToLink!: Function;
152153
@Action("toggle_isDragging") toggleIsDragging!: Function;
153154
155+
@Watch("exportStatus")
156+
onExportStatusChanged(value: boolean) {
157+
if (value) {
158+
this.exportSvgToJSON();
159+
}
160+
}
161+
162+
/**
163+
* 导出svg json数据
164+
*/
165+
exportSvgToJSON() {
166+
const { nodes, edges } = this;
167+
if (nodes.length === 0 || edges.length === 0) {
168+
alert("流程配置未给出,无法导出数据");
169+
this.$emit("update:exportStatus", false);
170+
return false;
171+
}
172+
const json = { nodes, edges };
173+
this.$emit("update:exportStatus", false);
174+
this.$emit("export-json", json);
175+
}
176+
154177
/**
155178
* 新增节点
156179
* @description 向SVG画布中新增节点

‎src/components/GraphShow.vue‎

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
<template>
2+
<div class="graph-show-container">
3+
<div class="svg-box" v-show="svgReady">
4+
<svg class="zone" width="100%" height="818">
5+
<defs>
6+
<marker
7+
id="mark-arrow"
8+
viewBox="0 0 11 11"
9+
refX="8"
10+
refY="6"
11+
markerWidth="12"
12+
markerHeight="12"
13+
orient="auto"
14+
>
15+
<path d="M2,2 L10,6 L2,10 L6,6 L2,2" />
16+
</marker>
17+
</defs>
18+
19+
<g class="graph">
20+
<g>
21+
<path
22+
v-for="edge in edges"
23+
:key="edge.id"
24+
class="link"
25+
:d="edgeData(edge)"
26+
marker-end="url(#mark-arrow)"
27+
></path>
28+
</g>
29+
30+
<g>
31+
<g
32+
class="node-container"
33+
v-for="(node, index) in nodes"
34+
:key="index"
35+
:transform="'translate(' + node.x + ',' + node.y + ')'"
36+
>
37+
<rect class="node" :width="rectWidth" :height="rectHeight"></rect>
38+
39+
<circle cx="0" cy="27" class="link-dot" />
40+
41+
<circle cx="130" cy="27" class="link-dot" />
42+
43+
<text x="45" y="20">
44+
<tspan>{{ node.title }}</tspan>
45+
</text>
46+
47+
<text x="35" y="40">
48+
<tspan>{{ node.id }}</tspan>
49+
</text>
50+
</g>
51+
</g>
52+
</g>
53+
</svg>
54+
</div>
55+
<div class="nothing-showing" v-show="!svgReady">
56+
没有可展示的输出JSON数据.
57+
</div>
58+
</div>
59+
</template>
60+
61+
<script lang="ts">
62+
import { Component, Prop, Watch, Vue } from "vue-property-decorator";
63+
import { NodeClass, EdgeClass } from "@/components/Graph.vue";
64+
import { SvgJsonClass } from "@/views/FlowChart.vue";
65+
66+
@Component
67+
export default class GraphShow extends Vue {
68+
@Prop() private jsonData!: SvgJsonClass;
69+
private edges: EdgeClass[] = [];
70+
private nodes: NodeClass[] = [];
71+
private rectWidth: String = "130px";
72+
private rectHeight: String = "50px";
73+
74+
@Watch("jsonData")
75+
onJsonDataChanged(value: SvgJsonClass) {
76+
const { nodes, edges } = value;
77+
if (nodes.length > 0 && edges.length > 0) {
78+
this.edges = edges;
79+
this.nodes = nodes;
80+
}
81+
}
82+
83+
private get svgReady() {
84+
if (this.edges.length > 0 && this.nodes.length > 0) {
85+
return true;
86+
}
87+
return false;
88+
}
89+
90+
/**
91+
* 连线数据
92+
* @argument edge - 路径元数据
93+
*/
94+
edgeData(edge: EdgeClass) {
95+
const { dotLink, dotEndLink } = edge;
96+
if (edge.source && edge.target) {
97+
const bezier = 100;
98+
const { linkNode: sourceLinkNode } = edge.source;
99+
const { linkNode: targetLinkNode } = edge.target;
100+
101+
let startX = 0;
102+
let startY = 0;
103+
let midX = 0;
104+
let midY = 0;
105+
let endX = 0;
106+
let endY = 0;
107+
108+
if (dotLink === "left") {
109+
startX = sourceLinkNode.left.x;
110+
startY = sourceLinkNode.left.y;
111+
} else if (dotLink === "right") {
112+
startX = sourceLinkNode.right.x;
113+
startY = sourceLinkNode.right.y;
114+
}
115+
116+
if (dotEndLink === "left") {
117+
endX = targetLinkNode.left.x;
118+
endY = targetLinkNode.left.y;
119+
} else if (dotEndLink === "right") {
120+
endX = targetLinkNode.right.x;
121+
endY = targetLinkNode.right.y;
122+
}
123+
124+
// midX = (startX + endX) / 2;
125+
// midY = (startY + endX) / 2 - bezier;
126+
127+
// return `M ${startX},${startY} Q ${midX},${midY} ${endX},${endY}`;
128+
return `M ${startX},${startY} L ${endX},${endY}`;
129+
} else {
130+
return false;
131+
}
132+
}
133+
}
134+
</script>
135+
136+
<style lang="stylus" scoped>
137+
.graph-show-container{
138+
height: 100%;
139+
border: 1px solid #DCDCDC;
140+
overflow: hidden;
141+
background: #FFFFFF;
142+
box-shadow: 0 2px 4px 0 #B3C0D8;
143+
margin: 20px 0;
144+
145+
.svg-box{
146+
background: #fff;
147+
transition: background 0.2s ease-in-out;
148+
}
149+
150+
.active{
151+
background: #eee;
152+
}
153+
154+
.zone{
155+
.graph{
156+
path.link{
157+
fill: none;
158+
stroke: #000;
159+
stroke-width: 2px;
160+
}
161+
162+
path.dragline{
163+
stroke: #888;
164+
stroke-dasharray: 8px;
165+
}
166+
167+
path.selected{
168+
stroke: #9b78d3;
169+
}
170+
171+
g.node-container{
172+
user-select: none;
173+
174+
.node{
175+
fill: transparent;
176+
stroke-width: 2px;
177+
stroke: #000;
178+
transition: all 0.2s ease-in-out;
179+
}
180+
181+
.link-dot{
182+
r: 0px;
183+
fill: transparent;
184+
stroke: #000;
185+
stroke-width: 2px;
186+
transition: all 0.2s ease-in-out;
187+
}
188+
189+
text{
190+
font-size: 14px;
191+
color: #4a4a4a;
192+
}
193+
}
194+
}
195+
}
196+
}
197+
</style>

‎src/views/FlowChart.vue‎

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,88 @@
11
<template>
22
<div class="flow-chart-container">
3-
<Graph />
4-
<SideBar />
3+
<div class="flow-chart-config">
4+
<Graph
5+
:exportStatus.sync="exportStatus"
6+
@export-json="handleExportJSON"
7+
/>
8+
<SideBar />
9+
</div>
10+
<GraphShow :jsonData="jsonData" />
11+
<div class="control">
12+
<div class="export-btn btn" @click="exportJSON">导出JSON</div>
13+
<div class="import-btn btn">引入JSON</div>
14+
</div>
515
</div>
616
</template>
717

818
<script lang="ts">
919
import { Component, Vue } from "vue-property-decorator";
1020
import SideBar from "@/components/SideBar.vue";
1121
import Graph from "@/components/Graph.vue";
22+
import GraphShow from "@/components/GraphShow.vue";
23+
import { NodeClass, EdgeClass } from "@/components/Graph.vue";
24+
25+
export interface SvgJsonClass {
26+
nodes: NodeClass[];
27+
edges: EdgeClass[];
28+
}
1229
1330
@Component({
1431
components: {
1532
SideBar,
16-
Graph
33+
Graph,
34+
GraphShow
1735
}
1836
})
19-
export default class Home extends Vue {}
37+
export default class FlowChart extends Vue {
38+
private exportStatus: Boolean = false;
39+
private jsonData: SvgJsonClass = {
40+
nodes: [],
41+
edges: []
42+
};
43+
44+
exportJSON() {
45+
this.exportStatus = true;
46+
}
47+
48+
handleExportJSON(data: SvgJsonClass) {
49+
this.jsonData = data;
50+
console.log(data);
51+
alert("导出json数据成功!");
52+
}
53+
}
2054
</script>
2155

2256
<style scoped lang="stylus">
23-
.flow-chart-container
24-
display flex
25-
align-items center
26-
padding 40px 20px 40px
27-
height 60vh
28-
background-color #eee
57+
.flow-chart-container{
58+
padding: 40px 20px 40px;
59+
background-color: #eee;
60+
61+
.flow-chart-config{
62+
display: flex;
63+
align-items: center;
64+
height: 60vh;
65+
}
66+
67+
.control{
68+
display: flex;
69+
justify-content: flex-end;
70+
71+
.btn{
72+
padding: 10px 20px;
73+
margin-right: 10px;
74+
text-align: center;
75+
font-size: 20px;
76+
background-color: #fff;
77+
border-radius: 4px;
78+
transition: all 0.2s ease-in-out;
79+
cursor: pointer;
80+
}
81+
82+
.btn:hover{
83+
color: #fff;
84+
background-color: #888;
85+
}
86+
}
87+
}
2988
</style>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /