flow.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <template>
  2. <div class="flow">
  3. <div class="content">
  4. <!--左侧工具栏-->
  5. <div id="stencil" />
  6. <!-- 流程图 -->
  7. <div class="panel">
  8. <!--工具栏-->
  9. <div class="toolbar">
  10. <ToolBar v-if="isReady" />
  11. </div>
  12. <!--画板-->
  13. <div id="container" />
  14. </div>
  15. <!--右侧工具栏-->
  16. <div class="config">
  17. <ConfigPanel v-if="isReady" />
  18. </div>
  19. </div>
  20. <SubFlowDialog ref="dialogRef"></SubFlowDialog>
  21. </div>
  22. </template>
  23. <script setup lang="ts">
  24. import { $, getContainerSize } from '@/utils'
  25. import FlowGraph from '../graph'
  26. import ContextMenu from '@imengyu/vue3-context-menu'
  27. import SubFlowDialog from './components/subFlow.vue'
  28. import { Graph } from '@antv/x6'
  29. let isReady = ref(false)
  30. let destroyFn = ref<Function>(() => {})
  31. onMounted(() => {
  32. destroyFn.value = initGraph()
  33. })
  34. onUnmounted(() => {
  35. destroyFn.value()
  36. })
  37. const graph = ref<Graph>()
  38. const initGraph = () => {
  39. graph.value = FlowGraph.init(
  40. $('#container'),
  41. $('#container').getBoundingClientRect().width,
  42. $('#container').getBoundingClientRect().height
  43. )
  44. graph.value?.on('node:contextmenu', ({ e, x, y, cell, view }) => {
  45. const cells = graph.value?.getSelectedCells() || []
  46. if (!cells.length) {
  47. return
  48. }
  49. handleContextmenu(e, cell)
  50. })
  51. isReady.value = true
  52. const resizeFn = () => {
  53. const { width, height } = getContainerSize($('.panel'))
  54. graph.value?.resize(width, height - 38)
  55. }
  56. resizeFn()
  57. window.addEventListener('resize', resizeFn)
  58. return () => {
  59. window.removeEventListener('resize', resizeFn)
  60. graph.value?.dispose()
  61. }
  62. }
  63. // 右键菜单
  64. const handleContextmenu = (e: { pageX: any; pageY: any }, cell) => {
  65. const cells = graph.value?.getSelectedCells() || []
  66. ContextMenu.showContextMenu({
  67. x: e.pageX,
  68. y: e.pageY,
  69. items: [
  70. {
  71. label: '编辑子流程',
  72. onClick: () => {
  73. if (cell) {
  74. openDialog('编辑子流程', null)
  75. }
  76. }
  77. },
  78. {
  79. label: '删除节点',
  80. onClick: () => {
  81. if (cells.length) {
  82. graph.value?.removeCells(cells)
  83. }
  84. }
  85. },
  86. {
  87. label: '置顶',
  88. onClick: () => {
  89. if (cells.length) {
  90. cells.forEach(item => item.toFront({ deep: true }))
  91. }
  92. }
  93. },
  94. {
  95. label: '置底',
  96. onClick: () => {
  97. if (cells.length) {
  98. cells.forEach(item => item.toBack({ deep: true }))
  99. }
  100. }
  101. }
  102. ]
  103. })
  104. }
  105. // 打开 dialog
  106. const dialogRef = ref<InstanceType<typeof SubFlowDialog> | null>(null)
  107. const openDialog = (title: string, row) => {
  108. const params = {
  109. title,
  110. row: { ...row },
  111. isView: title === '查看'
  112. }
  113. dialogRef.value?.acceptParams(params)
  114. }
  115. </script>
  116. <style lang="scss" scoped>
  117. @use './index.scss';
  118. </style>