| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- <script setup lang="ts">
- import { computed } from 'vue'
- import { Position } from '@vue-flow/core'
- import type { NodeProps } from '@vue-flow/core'
- import type {
- IWorkflowNode,
- CanvasConnectionPort,
- CanvasElementPortWithRenderData
- } from '../../Interface'
- import { Icon } from '@repo/ui'
- import CanvasHandle from './handles/CanvasHandle.vue'
- type Props = NodeProps<IWorkflowNode['data']> & {
- readOnly?: boolean
- hovered?: boolean
- }
- const props = defineProps<Props>()
- /**
- * 处理节点
- */
- const createEndpoint = (data: {
- port: CanvasConnectionPort
- index: number
- count: number
- offsetAxis: 'top' | 'left'
- position: Position
- }): CanvasElementPortWithRenderData => {
- const { port, index, count, offsetAxis, position } = data
- return {
- ...port,
- handleId: `${port.type}-${index}`,
- position,
- connectionsCount: count,
- isConnecting: false,
- offset: {
- [offsetAxis]: `${(100 / (count + 1)) * (index + 1)}%`
- }
- }
- }
- /**
- * Inputs
- */
- const inputs = computed(() =>
- (props.data.inputs || []).map((target, index) =>
- createEndpoint({
- port: target,
- index,
- count: props.data.inputs.length,
- offsetAxis: 'top',
- position: Position.Left
- })
- )
- )
- /**
- * Outputs
- */
- const outputs = computed(() =>
- (props.data.outputs || []).map((source, index) =>
- createEndpoint({
- port: source,
- index,
- count: props.data.outputs.length,
- offsetAxis: 'top',
- position: Position.Right
- })
- )
- )
- const nodeClass = computed(() => {
- let classes: string[] = []
- if (props.selected) {
- classes.push('ring-6px', 'ring-#e0e2e7')
- }
- if (inputs.value.length === 0) {
- classes.push('rounded-l-36px')
- }
- return classes
- })
- </script>
- <template>
- <div
- class="w-full h-full bg-#fff box-border border-2 border-solid border-#dcdcdc rounded-8px relative"
- :class="nodeClass"
- >
- <div className="w-full h-full relative flex items-center justify-center">
- <Icon :icon="data?.icon" height="40" width="40" :color="data?.iconColor" />
- </div>
- <div className="absolute w-full bottom--24px text-12px text-center text-#222">
- {{ data?.displayName }}
- </div>
- <div className="absolute w-full bottom--40px text-12px text-center text-#999 truncate">
- {{ data.subtitle }}
- </div>
- <template v-for="target in inputs" :key="'handle-inputs-port' + target.index">
- <CanvasHandle v-bind="target" type="target" />
- </template>
- <template v-for="source in outputs" :key="'handle-outputs-port' + source.index">
- <CanvasHandle v-bind="source" type="source" />
- </template>
- </div>
- </template>
|