custom.vue 3.42 KB
<!--
 * @Date: 2025-03-10 16:52:35
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-03-13 18:28:05
 * @FilePath: /logic-flow2/src/views/adv-dnd-panel/custom.vue
 * @Description: 自定义拖拽功能
-->
<template>
  <div class="container">
    <div ref="container" class="flow-container"></div>
    <div style="position: absolute; bottom: 20%; left: 50%; transform: translateX(-50%)">
      <el-popover placement="top" :width="400" :visible="visible">
        <template #reference>
          <el-button style="margin-right: 16px" @mouseover="visible = true"
            >hover</el-button
          >
        </template>
        <div style="padding: 10px 0">
          <div class="node-panel">
            <div
              class="node-item"
              draggable="true"
              @dragstart="handleDragStart($event, { type: 'rect' })"
            >
              矩形节点
            </div>
            <div
              class="node-item"
              draggable="true"
              @dragstart="handleDragStart($event, { type: 'circle' })"
            >
              圆形节点
            </div>
          </div>
        </div>
      </el-popover>
    </div>
  </div>
</template>

<script setup>
import LogicFlow from "@logicflow/core";

const container = ref(null);
let lf = null;

const visible = ref(false);

// 拖拽事件处理函数
const handleDragStart = (e, node) => {
  e.dataTransfer.setData("node", JSON.stringify(node));
};

const handleDragOver = (e) => {
  e.preventDefault();
};

const handleDrop = (e) => {
  e.preventDefault();
  const data = JSON.parse(e.dataTransfer.getData("node"));
  const canvasPoint = lf.getPointByClient(e.clientX, e.clientY);

  lf.addNode({
    type: data.type,
    x: canvasPoint.canvasOverlayPosition.x,
    y: canvasPoint.canvasOverlayPosition.y,
  });
};

// 点击事件处理函数
const handleClickOutside = (e) => {
  const popover = document.querySelector(".el-popover");
  const button = document.querySelector(".el-button");
  if (popover && button && !popover.contains(e.target) && !button.contains(e.target)) {
    visible.value = false;
  }
};

onMounted(() => {
  lf = new LogicFlow({
    container: container.value,
    grid: true,
  });

  // 添加事件监听
  container.value.addEventListener("dragover", handleDragOver);
  container.value.addEventListener("drop", handleDrop);

  // 添加点击事件监听
  document.addEventListener("click", handleClickOutside);

  lf.render({
    nodes: [
      { id: "node1", type: "rect", x: 200, y: 100 },
      { id: "node2", type: "circle", x: 400, y: 100 },
    ],
    edges: [{ id: "edge1", sourceNodeId: "node1", targetNodeId: "node2" }],
  });
});

// 组件卸载时移除事件监听
onUnmounted(() => {
  if (container.value) {
    container.value.removeEventListener("dragover", handleDragOver);
    container.value.removeEventListener("drop", handleDrop);

    document.removeEventListener("click", handleClickOutside);
  }
});
</script>

<style scoped>
.container {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.flow-container {
  flex: 1;
  width: 100%;
  height: 100%;
}

.node-panel {
  display: flex;
  gap: 16px;
}

.node-item {
  padding: 8px 16px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  cursor: grab; /* 修改这里 */
  background: #fff;

  &:hover {
    border-color: #409eff;
    color: #409eff;
  }

  /* 添加拖动时的样式 */
  &:active {
    cursor: grabbing;
  }
}
</style>