This commit is contained in:
lzp
2026-03-03 15:39:54 +08:00
parent 76afe1022f
commit b3b7ce2f2a
15 changed files with 141 additions and 46 deletions

View File

@@ -55,7 +55,8 @@
const id = props.node.id
if (!id) return
stateManager.deleteNode(id)
nodeManager.createCardNode({ data: { type: v.type } })
const superiorID = props.node.data.superiorID
nodeManager.createCardNode({ data: { type: v.type, superiorID } })
}
defineExpose({})

View File

@@ -110,6 +110,7 @@
if (attrs.node.data) attrs.node.data.data = data
nodeManager.createResultNode({
data: {
superiorID: attrs.node.id,
tier: currentComponent.value.tier,
data: {
url: 'https://s3-alpha-sig.figma.com/img/ea2f/590e/9638f62a2fc91e31f33db0022db1642c?Expires=1773014400&Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ&Signature=M0B8oJJOk~dGG0aZAqOIocAp7T0LFdJ9FYmCrEZVTCRzYxM6SJRNtYMTX-rTO3Z~s14QINh~o-S41XiZnBv-0zcKjuWot~VVaNHfd0~1LesfNe2KwvCinT~72btFut1pheLnKE-wWCX5ewtonxU77bnw386YPMTqv7DBZzksf2udsJA7NmOYD6~TUG3Q2dWSt~zPH~lkaidscPqpCnCbqzljCEi4RiHY4U3A45l5XypcX2umqn1UaYUFCTqV9471J4qdB6Dg2pcKocdp-7-3s1De6Q~2SmBOrSgDQ~KEADCB2lhKfhxgWmy0lwMvhTd4l90ygVZDWZRABgjHNrGUvg__'

View File

@@ -44,18 +44,19 @@
}
})
const nodes = computed(() => props.stateManager.nodes.value)
const firstNode = computed(() => nodes.value[0])
const lastNode = computed(() => nodes.value[nodes.value.length - 1])
const isSubord = computed(() => nodes.value.some((v) => v.data.superiorID === props.node.id))
const tier = computed(() => Number(props.node?.data?.tier || 0))
const isAdd = computed(
() =>
props.node.id === lastNode.value.id &&
!isSubord.value &&
NODE_DATATYPE.RESULT_IMAGE === props.node.data.type &&
!(tier.value === NODE_DATATIER.TO_3VIEW)
)
const onAdd = () => {
const tier_ = tier.value + 1
props.stateManager.nodeManager.createCardsSelect({ data: { tier: tier_ } })
props.stateManager.nodeManager.createCardsSelect({
data: { tier: tier_, superiorID: props.node.id }
})
}
const posCenter = computed(() => {
const arr = [NODE_DATATYPE.RESULT_IMAGE]

View File

@@ -37,13 +37,14 @@
</template>
<script setup lang="ts">
import { reactive, ref, onBeforeUnmount, useAttrs } from 'vue'
import { reactive, ref, onBeforeUnmount, useAttrs, inject } from 'vue'
const props = defineProps({
data: {
type: Object,
default: () => ({})
}
})
const nodeManager = inject('nodeManager') as any
const attrs = useAttrs()
const showHeader = ref(!!attrs.node?.data?.isHeader)
const showMenu = ref(false)
@@ -55,7 +56,7 @@
{ label: 'Copy', tip: 'Ctrl+C', on: () => {} },
{ label: 'Paste', tip: 'Ctrl+V', on: () => {} },
{ label: 'Duplicate', tip: 'Ctrl+D', on: () => {} },
{ label: 'Delete', tip: 'Del', on: () => {} },
{ label: 'Delete', tip: 'Del', on: () => nodeManager.deleteNode(attrs.node.id) },
{ isDivide: true },
{ label: 'Bring to font', tip: 'Del', on: () => {} },
{ label: 'Send to back', tip: 'Del', on: () => {} },

View File

@@ -27,8 +27,10 @@
<zoom
:zoom="stateManager.zoom.value"
:step="0.1"
is-home
@add="(e) => flowManager.setZoom(e)"
@sub="(e) => flowManager.setZoom(e)"
@home="() => fitView({ maxZoom: 1 })"
/>
</template>
@@ -87,7 +89,6 @@
provide('nodeManager', nodeManager)
provide('nodeManager', nodeManager)
const { fitView } = useVueFlow()
const { layout } = useLayout()
const index = ref(0)

View File

@@ -9,6 +9,9 @@ export class FlowManager {
this.stateManager.zoom.value = zoom
this.vueFlow.value.zoomTo(zoom)
}
getNodeById(id: string) {
return this.vueFlow.value.getNode(id)
}
getLastNode() {
const lastNode = this.stateManager.getLastNode()
if (lastNode?.id) {

View File

@@ -28,13 +28,17 @@ export class NodeManager {
/** 创建节点 */
createNode(options: NodeOptions) {
const lastNode = this.stateManager.flowManager.getLastNode();
const superiorID = options?.data?.superiorID
const snode = superiorID ? this.stateManager.flowManager.getNodeById(superiorID) : this.stateManager.flowManager.getLastNode();
const id = options.id || createId()
const positionX = options.positionX || 0
const positionY = options.positionY || 0
const position = options.position ||
!lastNode ? { x: positionX, y: positionY } :
{ x: lastNode.position.x + lastNode.dimensions.width + 50 + positionX, y: lastNode.position.y + positionY }
!snode ? { x: positionX, y: positionY } :
{
x: snode.position.x + snode.dimensions.width + 50 + positionX,
y: snode.position.y + positionY
}
const data = options?.data || {}
data['component'] = options.component
const options_ = {

View File

@@ -6,7 +6,7 @@ export interface NodesItem {
type: string
class: string
position: { x: number, y: number }
data: { component: any, type: string }
data: { component: any, type: string, superiorID?: string }
}
export class StateManager {
vueFlow: any
@@ -30,15 +30,25 @@ export class StateManager {
this.nodes = ref<NodesItem[]>([]);
this.nodes_ = computed(() => {
return this.nodes.value.map((node, index) => {
const obj = {
...node,
}
if (index === 0) {
const obj = node;
// if (index === 0) {
// obj.type = NODE_TYPE.INPUT;
// } else if (index === this.nodes.value.length - 1) {
// obj.type = NODE_TYPE.OUTPUT;
// } else {
// obj.type = NODE_TYPE.SECONDARY;
// }
const superiorID = node.data.superiorID;
const isSuperior = this.nodes.value.some((v) => v.id === superiorID)
const isSubord = this.nodes.value.some((v) => v.data.superiorID === node.id)
if (!superiorID) {// 没有上级ID
obj.type = NODE_TYPE.INPUT;
} else if (index === this.nodes.value.length - 1) {
obj.type = NODE_TYPE.OUTPUT;
} else {
} else if (isSuperior && isSubord) {// 有上级ID并找到下级
obj.type = NODE_TYPE.SECONDARY;
} else if (isSuperior && !isSubord) {// 有上级ID但未找到下级
obj.type = NODE_TYPE.OUTPUT;
} else {// 其他情况-有上级ID未找到上级
obj.type = NODE_TYPE.INPUT;
}
return obj
})
@@ -47,12 +57,25 @@ export class StateManager {
this.edges = computed(() => {
const arr = []
this.nodes.value.forEach((node, index) => {
if (index < this.nodes.value.length - 1) {
const id = node.id
const target = this.nodes.value[index + 1].id
// if (index < this.nodes.value.length - 1) {
// const source = node.id
// const target = this.nodes.value[index + 1].id
// arr.push({
// id: `el-${source}-${target}`,
// source: source,
// target: target,
// selectable: false,
// type: 'default'
// })
// }
const superiorID = node.data.superiorID;
const isSuperior = this.nodes.value.some((v) => v.id === superiorID)
if (superiorID && isSuperior) {
const source = node.data.superiorID
const target = node.id
arr.push({
id: `el-${id}-${target}`,
source: id,
id: `el-${source}-${target}`,
source: source,
target: target,
selectable: false,
type: 'default'

View File

@@ -1,5 +1,6 @@
<template>
<div class="zoom">
<span class="icon" @click="onHome" v-if="isHome"><svg-icon name="home" size="14" /></span>
<span class="icon" @click="zoomIn"><svg-icon name="add" size="14" /></span>
<span class="value">{{ Math.round(zoom * 100) }}%</span>
<span class="icon" @click="zoomOut"><svg-icon name="sub" size="14" /></span>
@@ -10,9 +11,13 @@
import { ref, watch } from 'vue'
const props = defineProps({
zoom: { default: 1, type: Number },
step: { default: 0.1, type: Number }
step: { default: 0.1, type: Number },
isHome: { default: false, type: Boolean }
})
const emit = defineEmits(['add', 'sub'])
const emit = defineEmits(['home', 'add', 'sub'])
const onHome = () => {
emit('home')
}
const zoomIn = () => {
emit('add', Number(props.zoom) + props.step)
}
@@ -27,7 +32,6 @@
bottom: 4rem;
right: 3rem;
padding: 0.7rem 1rem;
min-width: 12.8rem;
height: 4.2rem;
border-radius: 0.8rem;
border: 0.1rem solid #ffcf90;
@@ -48,7 +52,7 @@
--svg-icon-color: #0d0d0d;
}
> .value {
flex: 1;
min-width: 5rem;
text-align: center;
font-family: Medium;
font-size: 1.6rem;