Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import {
  2. memo,
  3. useCallback,
  4. useMemo,
  5. useState,
  6. } from 'react'
  7. import { intersection } from 'lodash-es'
  8. import type { EdgeProps } from 'reactflow'
  9. import {
  10. BaseEdge,
  11. EdgeLabelRenderer,
  12. Position,
  13. getBezierPath,
  14. } from 'reactflow'
  15. import {
  16. useAvailableBlocks,
  17. useNodesInteractions,
  18. } from './hooks'
  19. import BlockSelector from './block-selector'
  20. import type {
  21. Edge,
  22. OnSelectBlock,
  23. } from './types'
  24. import { NodeRunningStatus } from './types'
  25. import { getEdgeColor } from './utils'
  26. import { ITERATION_CHILDREN_Z_INDEX, LOOP_CHILDREN_Z_INDEX } from './constants'
  27. import CustomEdgeLinearGradientRender from './custom-edge-linear-gradient-render'
  28. import cn from '@/utils/classnames'
  29. import { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/components/error-handle/types'
  30. const CustomEdge = ({
  31. id,
  32. data,
  33. source,
  34. sourceHandleId,
  35. target,
  36. targetHandleId,
  37. sourceX,
  38. sourceY,
  39. targetX,
  40. targetY,
  41. selected,
  42. }: EdgeProps) => {
  43. const [
  44. edgePath,
  45. labelX,
  46. labelY,
  47. ] = getBezierPath({
  48. sourceX: sourceX - 8,
  49. sourceY,
  50. sourcePosition: Position.Right,
  51. targetX: targetX + 8,
  52. targetY,
  53. targetPosition: Position.Left,
  54. curvature: 0.16,
  55. })
  56. const [open, setOpen] = useState(false)
  57. const { handleNodeAdd } = useNodesInteractions()
  58. const { availablePrevBlocks } = useAvailableBlocks((data as Edge['data'])!.targetType, (data as Edge['data'])?.isInIteration, (data as Edge['data'])?.isInLoop)
  59. const { availableNextBlocks } = useAvailableBlocks((data as Edge['data'])!.sourceType, (data as Edge['data'])?.isInIteration, (data as Edge['data'])?.isInLoop)
  60. const {
  61. _sourceRunningStatus,
  62. _targetRunningStatus,
  63. } = data
  64. const linearGradientId = useMemo(() => {
  65. if (
  66. (
  67. _sourceRunningStatus === NodeRunningStatus.Succeeded
  68. || _sourceRunningStatus === NodeRunningStatus.Failed
  69. || _sourceRunningStatus === NodeRunningStatus.Exception
  70. ) && (
  71. _targetRunningStatus === NodeRunningStatus.Succeeded
  72. || _targetRunningStatus === NodeRunningStatus.Failed
  73. || _targetRunningStatus === NodeRunningStatus.Exception
  74. || _targetRunningStatus === NodeRunningStatus.Running
  75. )
  76. )
  77. return id
  78. }, [_sourceRunningStatus, _targetRunningStatus, id])
  79. const handleOpenChange = useCallback((v: boolean) => {
  80. setOpen(v)
  81. }, [])
  82. const handleInsert = useCallback<OnSelectBlock>((nodeType, toolDefaultValue) => {
  83. handleNodeAdd(
  84. {
  85. nodeType,
  86. toolDefaultValue,
  87. },
  88. {
  89. prevNodeId: source,
  90. prevNodeSourceHandle: sourceHandleId || 'source',
  91. nextNodeId: target,
  92. nextNodeTargetHandle: targetHandleId || 'target',
  93. },
  94. )
  95. }, [handleNodeAdd, source, sourceHandleId, target, targetHandleId])
  96. const stroke = useMemo(() => {
  97. if (selected)
  98. return getEdgeColor(NodeRunningStatus.Running)
  99. if (linearGradientId)
  100. return `url(#${linearGradientId})`
  101. if (data?._connectedNodeIsHovering)
  102. return getEdgeColor(NodeRunningStatus.Running, sourceHandleId === ErrorHandleTypeEnum.failBranch)
  103. return getEdgeColor()
  104. }, [data._connectedNodeIsHovering, linearGradientId, selected, sourceHandleId])
  105. return (
  106. <>
  107. {
  108. linearGradientId && (
  109. <CustomEdgeLinearGradientRender
  110. id={linearGradientId}
  111. startColor={getEdgeColor(_sourceRunningStatus)}
  112. stopColor={getEdgeColor(_targetRunningStatus)}
  113. position={{
  114. x1: sourceX,
  115. y1: sourceY,
  116. x2: targetX,
  117. y2: targetY,
  118. }}
  119. />
  120. )
  121. }
  122. <BaseEdge
  123. id={id}
  124. path={edgePath}
  125. style={{
  126. stroke,
  127. strokeWidth: 2,
  128. opacity: data._waitingRun ? 0.7 : 1,
  129. }}
  130. />
  131. <EdgeLabelRenderer>
  132. <div
  133. className={cn(
  134. 'nopan nodrag hover:scale-125',
  135. data?._hovering ? 'block' : 'hidden',
  136. open && '!block',
  137. data.isInIteration && `z-[${ITERATION_CHILDREN_Z_INDEX}]`,
  138. data.isInLoop && `z-[${LOOP_CHILDREN_Z_INDEX}]`,
  139. )}
  140. style={{
  141. position: 'absolute',
  142. transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
  143. pointerEvents: 'all',
  144. opacity: data._waitingRun ? 0.7 : 1,
  145. }}
  146. >
  147. <BlockSelector
  148. open={open}
  149. onOpenChange={handleOpenChange}
  150. asChild
  151. onSelect={handleInsert}
  152. availableBlocksTypes={intersection(availablePrevBlocks, availableNextBlocks)}
  153. triggerClassName={() => 'hover:scale-150 transition-all'}
  154. />
  155. </div>
  156. </EdgeLabelRenderer>
  157. </>
  158. )
  159. }
  160. export default memo(CustomEdge)