GraphLayout.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <script lang="ts" setup>
  2. import { onMounted, ref } from 'vue';
  3. import { useRouter } from 'vue-router';
  4. import { ConnectionLineType, useVueFlow, VueFlow } from '@vue-flow/core';
  5. import { MiniMap } from '@vue-flow/minimap';
  6. import { Background } from '@vue-flow/background';
  7. import '@vue-flow/core/dist/style.css';
  8. import '@vue-flow/core/dist/theme-default.css';
  9. import '@vue-flow/minimap/dist/style.css';
  10. import CustomEdge from '@/views/flow/custom/CustomEdge.vue';
  11. import CustomZoom from '@/views/flow/custom/CustomZoom.vue';
  12. import { useFlowStore } from '@/views/flow/store';
  13. import { nodeTypes } from '@/views/flow/store/get';
  14. import CardLayout from '@/views/flow/layout/CardLayout.vue';
  15. const router = useRouter();
  16. const flowStore = useFlowStore();
  17. const loading = ref(false);
  18. const nodeMenuRef = ref();
  19. const list = ref();
  20. const { addNodes, onConnect, addEdges, project, vueFlowRef, onNodeContextMenu } = useVueFlow({
  21. connectionLineOptions: {
  22. type: ConnectionLineType.SmoothStep,
  23. class: 'animated',
  24. },
  25. });
  26. onMounted(async () => {
  27. loading.value = true;
  28. const data = flowStore.data;
  29. if (data == undefined) {
  30. return;
  31. }
  32. if (data.flow == undefined) {
  33. loading.value = true;
  34. return;
  35. }
  36. list.value = JSON.parse(data.flow);
  37. loading.value = false;
  38. });
  39. onConnect((params) => {
  40. addEdges({ ...params, type: 'custom', animated: true });
  41. });
  42. onNodeContextMenu((e) => {
  43. e.node.selected = true;
  44. console.log(e);
  45. nodeMenuRef.value.show(e.node, e.event);
  46. });
  47. function onDragOver(event: any) {
  48. event.preventDefault();
  49. if (event.dataTransfer) {
  50. event.dataTransfer.dropEffect = 'move';
  51. }
  52. }
  53. function onDrop(event: any) {
  54. if (event.clientX < 340) {
  55. // 拖拽区域没有超过面板宽度时 忽略拖拽
  56. return;
  57. }
  58. const isNode = event.dataTransfer?.getData('isNode');
  59. if (isNode !== 'true') {
  60. return;
  61. }
  62. const { type, data } = JSON.parse(event.dataTransfer?.getData('data'));
  63. const { left, top } = vueFlowRef.value!.getBoundingClientRect();
  64. const position = project({
  65. x: event.clientX - left,
  66. y: event.clientY - top,
  67. });
  68. const newNode = {
  69. id: new Date().getTime().toString(),
  70. type: type,
  71. position,
  72. label: type,
  73. data: data,
  74. };
  75. console.log('添加节点', newNode);
  76. addNodes([newNode]);
  77. }
  78. </script>
  79. <template>
  80. <div @drop="onDrop" class="h-full w-full relative" id="graph-layout">
  81. <CardLayout />
  82. <CustomZoom />
  83. <VueFlow @dragover="onDragOver" v-model="list" :node-types="nodeTypes">
  84. <Background />
  85. <MiniMap />
  86. <template #edge-custom="props">
  87. <CustomEdge v-bind="props" />
  88. </template>
  89. </VueFlow>
  90. </div>
  91. </template>
  92. <style scoped></style>