|
@@ -1,158 +0,0 @@
|
|
|
-<template>
|
|
|
- <div
|
|
|
- class="flow-node"
|
|
|
- :style="nodeStyle"
|
|
|
- ref="nodeElement"
|
|
|
- @mousedown="startDrag"
|
|
|
- >
|
|
|
- <div class="node-header" :style="headerStyle">
|
|
|
- {{ nodeData.name }}
|
|
|
- </div>
|
|
|
- <div class="node-content">
|
|
|
- <slot></slot>
|
|
|
- </div>
|
|
|
- <div class="node-footer">
|
|
|
- <button
|
|
|
- v-for="type in availableChildTypes"
|
|
|
- :key="type"
|
|
|
- @click.stop="addChild(type)"
|
|
|
- class="add-child-btn"
|
|
|
- >
|
|
|
- 添加{{ nodeTypes[type].name }}节点
|
|
|
- </button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup>
|
|
|
-import { computed, ref } from 'vue'
|
|
|
-
|
|
|
-const props = defineProps({
|
|
|
- node: {
|
|
|
- type: Object,
|
|
|
- required: true
|
|
|
- }
|
|
|
-})
|
|
|
-
|
|
|
-const emit = defineEmits(['add-child', 'node-drag'])
|
|
|
-
|
|
|
-const nodeTypes = {
|
|
|
- start: { name: '开始', color: '#4CAF50' },
|
|
|
- process: { name: '处理', color: '#2196F3' },
|
|
|
- decision: { name: '判断', color: '#FFC107' },
|
|
|
- end: { name: '结束', color: '#F44336' }
|
|
|
-}
|
|
|
-
|
|
|
-const nodeElement = ref(null)
|
|
|
-const isDragging = ref(false)
|
|
|
-const dragStartPos = ref({ x: 0, y: 0 })
|
|
|
-const nodeStartPos = ref({ x: 0, y: 0 })
|
|
|
-
|
|
|
-const nodeData = computed(() => ({
|
|
|
- ...props.node,
|
|
|
- ...nodeTypes[props.node.type]
|
|
|
-}))
|
|
|
-
|
|
|
-const nodeStyle = computed(() => ({
|
|
|
- left: `${props.node.x}px`,
|
|
|
- top: `${props.node.y}px`,
|
|
|
- borderColor: nodeData.value.color
|
|
|
-}))
|
|
|
-
|
|
|
-const headerStyle = computed(() => ({
|
|
|
- backgroundColor: nodeData.value.color
|
|
|
-}))
|
|
|
-
|
|
|
-const availableChildTypes = computed(() => {
|
|
|
- if (props.node.type === 'start') return ['process', 'decision']
|
|
|
- if (props.node.type === 'process') return ['process', 'decision', 'end']
|
|
|
- if (props.node.type === 'decision') return ['process', 'end']
|
|
|
- return []
|
|
|
-})
|
|
|
-
|
|
|
-function addChild(type) {
|
|
|
- emit('add-child', props.node.id, type)
|
|
|
-}
|
|
|
-
|
|
|
-function startDrag(e) {
|
|
|
- if (e.target.closest('.add-child-btn')) return
|
|
|
-
|
|
|
- isDragging.value = true
|
|
|
- dragStartPos.value = {
|
|
|
- x: e.clientX,
|
|
|
- y: e.clientY
|
|
|
- }
|
|
|
- nodeStartPos.value = {
|
|
|
- x: props.node.x,
|
|
|
- y: props.node.y
|
|
|
- }
|
|
|
-
|
|
|
- document.addEventListener('mousemove', handleDrag)
|
|
|
- document.addEventListener('mouseup', stopDrag)
|
|
|
- e.preventDefault()
|
|
|
-}
|
|
|
-
|
|
|
-function handleDrag(e) {
|
|
|
- if (!isDragging.value) return
|
|
|
-
|
|
|
- const dx = e.clientX - dragStartPos.value.x
|
|
|
- const dy = e.clientY - dragStartPos.value.y
|
|
|
-
|
|
|
- const newX = nodeStartPos.value.x + dx
|
|
|
- const newY = nodeStartPos.value.y + dy
|
|
|
-
|
|
|
- emit('node-drag', props.node.id, newX, newY)
|
|
|
-}
|
|
|
-
|
|
|
-function stopDrag() {
|
|
|
- isDragging.value = false
|
|
|
- document.removeEventListener('mousemove', handleDrag)
|
|
|
- document.removeEventListener('mouseup', stopDrag)
|
|
|
-}
|
|
|
-</script>
|
|
|
-
|
|
|
-<style>
|
|
|
-.flow-node {
|
|
|
- position: absolute;
|
|
|
- width: 200px;
|
|
|
- background: white;
|
|
|
- border: 2px solid;
|
|
|
- border-radius: 4px;
|
|
|
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
|
- z-index: 1;
|
|
|
- cursor: move;
|
|
|
- user-select: none;
|
|
|
-}
|
|
|
-
|
|
|
-.node-header {
|
|
|
- padding: 8px 12px;
|
|
|
- color: white;
|
|
|
- font-weight: bold;
|
|
|
- border-top-left-radius: 2px;
|
|
|
- border-top-right-radius: 2px;
|
|
|
-}
|
|
|
-
|
|
|
-.node-content {
|
|
|
- padding: 12px;
|
|
|
-}
|
|
|
-
|
|
|
-.node-footer {
|
|
|
- padding: 8px;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- gap: 4px;
|
|
|
-}
|
|
|
-
|
|
|
-.add-child-btn {
|
|
|
- padding: 4px 8px;
|
|
|
- background: #f5f5f5;
|
|
|
- border: 1px solid #ddd;
|
|
|
- border-radius: 3px;
|
|
|
- cursor: pointer;
|
|
|
- font-size: 12px;
|
|
|
-}
|
|
|
-
|
|
|
-.add-child-btn:hover {
|
|
|
- background: #e0e0e0;
|
|
|
-}
|
|
|
-</style>
|