Ben Lin
2024-06-21 0990f596791ebc4518e293a2d60407ff1165b53c
src/components/FlowChart/src/FlowChart.vue
@@ -16,19 +16,19 @@
    </BasicModal>
  </div>
</template>
<script lang="ts">
<script lang="ts" setup>
  import type { Ref } from 'vue';
  import type { Definition } from '@logicflow/core';
  import { defineComponent, ref, onMounted, unref, nextTick, computed, watch } from 'vue';
  import { ref, onMounted, unref, nextTick, computed, watch } from 'vue';
  import FlowChartToolbar from './FlowChartToolbar.vue';
  import LogicFlow from '@logicflow/core';
  import { Snapshot, BpmnElement, Menu, DndPanel, SelectionSelect } from '@logicflow/extension';
  import { useDesign } from '/@/hooks/web/useDesign';
  import { useAppStore } from '/@/store/modules/app';
  import { useDesign } from '@/hooks/web/useDesign';
  import { useAppStore } from '@/store/modules/app';
  import { createFlowChartContext } from './useFlowContext';
  // import { toLogicFlowData } from './adpterForTurbo';
  import { useModal, BasicModal } from '/@/components/Modal';
  import { JsonPreview } from '/@/components/CodeEditor';
  import { toLogicFlowData } from './adpterForTurbo';
  import { useModal, BasicModal } from '@/components/Modal';
  import { JsonPreview } from '@/components/CodeEditor';
  import { configDefaultDndPanel } from './config';
  import '@logicflow/core/dist/style/index.css';
  import '@logicflow/extension/lib/style/index.css';
@@ -43,249 +43,228 @@
  import PackingNode from './PackingNode';
  import RepairNode from './RepairNode';
  const { notification } = useMessage();
  const { t } = useI18n();
  defineOptions({ name: 'FlowChart' });
  export default defineComponent({
    name: 'FlowChart',
    components: { BasicModal, FlowChartToolbar, JsonPreview },
    props: {
      flowOptions: {
        type: Object as PropType<Definition>,
        default: () => ({}),
      },
      data: {
        type: Object as PropType<any>,
        default: () => ({}),
      },
      toolbar: {
        type: Boolean,
        default: true,
      },
      patternItems: {
        type: Array,
      },
  const props = defineProps({
    flowOptions: {
      type: Object as PropType<Definition>,
      default: () => ({}),
    },
    emits: [
      'view-data',
      'save-data',
      'add-lf',
      'select-node',
      'click-blank',
      'init',
      'undo',
      'redo',
    ],
    setup(props, { emit }) {
      const globSetting = useGlobSetting();
      const lfElRef = ref(null);
      const graphData = ref({});
      const lfInstance = ref(null) as Ref<LogicFlow | null>;
    data: {
      type: Object as PropType<any>,
      default: () => ({}),
    },
      const { prefixCls } = useDesign('flow-chart');
      const appStore = useAppStore();
      const [register, { openModal }] = useModal();
      createFlowChartContext({
        logicFlow: lfInstance as unknown as LogicFlow,
      });
      const getFlowOptions = computed(() => {
        const { flowOptions } = props;
        const defaultOptions: Partial<Definition> = {
          grid: true,
          background: {
            color: appStore.getDarkMode === 'light' ? '#f7f9ff' : '#151515',
          },
          keyboard: {
            enabled: true,
          },
          edgeType: 'bezier',
          ...flowOptions,
        };
        return defaultOptions as Definition;
      });
      watch(
        () => props.data,
        () => {
          onRender();
        },
      );
      // TODO
      // watch(
      //   () => appStore.getDarkMode,
      //   () => {
      //     init();
      //   }
      // );
      watch(
        () => unref(getFlowOptions),
        (options) => {
          unref(lfInstance)?.updateEditConfig(options);
        },
      );
      // init logicFlow
      async function init() {
        await nextTick();
        const lfEl = unref(lfElRef);
        if (!lfEl) {
          return;
        }
        LogicFlow.use(DndPanel);
        // Canvas configuration
        LogicFlow.use(Snapshot);
        // Use the bpmn plug-in to introduce bpmn elements, which can be used after conversion in turbo
        LogicFlow.use(BpmnElement);
        // Start the right-click menu
        LogicFlow.use(Menu);
        LogicFlow.use(SelectionSelect);
        lfInstance.value = new LogicFlow({
          ...unref(getFlowOptions),
          container: lfEl,
          edgeGenerator: (sourceNode) => {
            // console.log('a');
            // 起始节点类型 rect 时使用 自定义的边 custom-edge
            if (sourceNode.properties.isReturn) return 'custom-edge';
            // if (sourceNode.type === 'rect') return 'custom-edge';
            // return 'custom-edge';
          },
        });
        const lf = unref(lfInstance)!;
        // lf?.setDefaultEdgeType('line');
        lf.register(actionRect);
        lf.register(TestNode);
        lf.register(CollectNode);
        lf.register(AssemblyNode);
        lf.register(PackingNode);
        lf.register(RepairNode);
        onRender();
        lf?.setPatternItems(props.patternItems || configDefaultDndPanel(lf));
      }
      async function onRender() {
        await nextTick();
        const lf = unref(lfInstance);
        if (!lf) {
          return;
        }
        lf.register(customEdge);
        // const lFData = toLogicFlowData(props.data);
        lf.render(props.data);
        lf.on('anchor:drop', (data) => {
          const nodeData = data.nodeModel.getData();
          if (nodeData.properties.isReturn === true) {
            console.log(11, nodeData.properties.isReturn);
            data.nodeModel.graphModel.edges.forEach((element) => {
              if (element.sourceNodeId === data.nodeModel.id) {
                lf.changeEdgeType(element.id, 'custom-edge');
              }
            });
          }
        });
        lf.on('node:click,edge:click', (data) => {
          if (data.isSelected) {
            console.log(data.data.text.value, data.isSelected);
            // notification.success({
            //   message: t('点击了节点'),
            //   description: `${data.data.text.value}: ${data.isSelected}`,
            //   duration: 3,
            // });
            emit('select-node', data, lf);
          } else {
            console.log(data.data.type);
          }
        });
        lf.on('blank:mousedown', (e) => {
          emit('click-blank');
        });
        lf.on('node:dnd-add', (data, e) => {
          console.log('node:dnd-add', data);
          emit('select-node', data, lf);
        });
        emit('init', lf);
      }
      function handlePreview() {
        const lf = unref(lfInstance);
        if (!lf) {
          return;
        }
        graphData.value = unref(lf).getGraphData();
        openModal();
      }
      function handleSave() {
        // console.log('handleSave');
        const lf = unref(lfInstance);
        if (!lf) {
          return;
        }
        emit('save-data', lf);
      }
      function handleAdd() {
        const lf = unref(lfInstance);
        console.log('handleAdd');
        if (!lf) {
          return;
        }
        // lf.clearData();
        lf.render({});
      }
      function handleAddlf() {
        const lf = unref(lfInstance);
        if (!lf) {
          return;
        }
        emit('add-lf', lf);
      }
      function handleUndo() {
        const lf = unref(lfInstance);
        if (!lf) {
          return;
        }
        emit('undo', lf);
      }
      function handleRedo() {
        const lf = unref(lfInstance);
        if (!lf) {
          return;
        }
        emit('redo', lf);
      }
      onMounted(init);
      return {
        register,
        prefixCls,
        lfElRef,
        handlePreview,
        graphData,
        handleSave,
        handleAdd,
        handleAddlf,
        handleUndo,
        handleRedo,
      };
    toolbar: {
      type: Boolean,
      default: true,
    },
    patternItems: {
      type: Array,
    },
  });
  const emit = defineEmits([
    'view-data',
    'save-data',
    'add-lf',
    'select-node',
    'click-blank',
    'init',
    'undo',
    'redo',
  ]);
  const lfElRef = ref(null);
  const graphData = ref({});
  const lfInstance = ref(null) as Ref<LogicFlow | null>;
  const { prefixCls } = useDesign('flow-chart');
  const appStore = useAppStore();
  const [register, { openModal }] = useModal();
  createFlowChartContext({
    logicFlow: lfInstance as unknown as LogicFlow,
  });
  const getFlowOptions = computed(() => {
    const { flowOptions } = props;
    const defaultOptions: Partial<Definition> = {
      grid: true,
      background: {
        color: appStore.getDarkMode === 'light' ? '#f7f9ff' : '#151515',
      },
      keyboard: {
        enabled: true,
      },
      edgeType: 'polyline',
      ...flowOptions,
    };
    return defaultOptions as Definition;
  });
  watch(
    () => props.data,
    () => {
      onRender();
    },
  );
  // TODO
  // watch(
  //   () => appStore.getDarkMode,
  //   () => {
  //     init();
  //   }
  // );
  watch(
    () => unref(getFlowOptions),
    (options) => {
      unref(lfInstance)?.updateEditConfig(options);
    },
  );
  // init logicFlow
  async function init() {
    await nextTick();
    const lfEl = unref(lfElRef);
    if (!lfEl) {
      return;
    }
    LogicFlow.use(DndPanel);
    // Canvas configuration
    LogicFlow.use(Snapshot);
    // Use the bpmn plug-in to introduce bpmn elements, which can be used after conversion in turbo
    LogicFlow.use(BpmnElement);
    // Start the right-click menu
    LogicFlow.use(Menu);
    LogicFlow.use(SelectionSelect);
    lfInstance.value = new LogicFlow({
      ...unref(getFlowOptions),
      container: lfEl,
      edgeGenerator: (sourceNode) => {
        // console.log('a');
        // 起始节点类型 rect 时使用 自定义的边 custom-edge
        if (sourceNode.properties.isReturn) return 'custom-edge';
        // if (sourceNode.type === 'rect') return 'custom-edge';
        // return 'custom-edge';
      },
    });
    const lf = unref(lfInstance)!;
    lf?.setDefaultEdgeType('polyline');
    lf.register(actionRect);
    lf.register(TestNode);
    lf.register(CollectNode);
    lf.register(AssemblyNode);
    lf.register(PackingNode);
    lf.register(RepairNode);
    lf.register(customEdge);
    onRender();
    lf?.setPatternItems(props.patternItems || configDefaultDndPanel(lf));
  }
  async function onRender() {
    await nextTick();
    const lf = unref(lfInstance);
    if (!lf) {
      return;
    }
    const lFData = toLogicFlowData(props.data);
    lf.render(lFData);
    lf.on('anchor:drop', (data) => {
      const nodeData = data.nodeModel.getData();
      if (nodeData.properties.isReturn === true) {
        console.log(11, nodeData.properties.isReturn);
        data.nodeModel.graphModel.edges.forEach((element) => {
          if (element.sourceNodeId === data.nodeModel.id) {
            lf.changeEdgeType(element.id, 'custom-edge');
          }
        });
      }
    });
    lf.on('node:click,edge:click', (data) => {
      if (data.isSelected) {
        console.log(data.data.text.value, data.isSelected);
        // notification.success({
        //   message: t('点击了节点'),
        //   description: `${data.data.text.value}: ${data.isSelected}`,
        //   duration: 3,
        // });
        emit('select-node', data, lf);
      } else {
        console.log(data.data.type);
      }
    });
    lf.on('blank:mousedown', (e) => {
      emit('click-blank');
    });
    lf.on('node:dnd-add', (data, e) => {
      console.log('node:dnd-add', data);
      emit('select-node', data, lf);
    });
    emit('init', lf);
  }
  function handlePreview() {
    const lf = unref(lfInstance);
    if (!lf) {
      return;
    }
    graphData.value = unref(lf).getGraphData();
    openModal();
  }
function handleSave() {
  // console.log('handleSave');
  const lf = unref(lfInstance);
  if (!lf) {
    return;
  }
  emit('save-data', lf);
}
function handleAdd() {
  const lf = unref(lfInstance);
  console.log('handleAdd');
  if (!lf) {
    return;
  }
  // lf.clearData();
  lf.render({});
}
function handleAddlf() {
  const lf = unref(lfInstance);
  if (!lf) {
    return;
  }
  emit('add-lf', lf);
}
function handleUndo() {
  const lf = unref(lfInstance);
  if (!lf) {
    return;
  }
  emit('undo', lf);
}
function handleRedo() {
  const lf = unref(lfInstance);
  if (!lf) {
    return;
  }
  emit('redo', lf);
}
  onMounted(init);
</script>
./TestNode