wwf
3 天以前 a430284aa21e3ae1f0d5654e55b2ad2852519cc2
app/components/workflow/nodes/_base/components/variable/var-reference-picker.tsx
@@ -6,14 +6,13 @@
  RiArrowDownSLine,
  RiCloseLine,
  RiErrorWarningFill,
  RiMoreLine,
} from '@remixicon/react'
import produce from 'immer'
import { useStoreApi } from 'reactflow'
import RemoveButton from '../remove-button'
import useAvailableVarList from '../../hooks/use-available-var-list'
import VarReferencePopup from './var-reference-popup'
import { getNodeInfoById, isConversationVar, isENV, isSystemVar, varTypeToStructType } from './utils'
import { getNodeInfoById, isConversationVar, isENV, isSystemVar } from './utils'
import ConstantField from './constant-field'
import cn from '@/utils/classnames'
import type { Node, NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types'
@@ -38,8 +37,6 @@
import Badge from '@/app/components/base/badge'
import Tooltip from '@/app/components/base/tooltip'
import { isExceptionVariable } from '@/app/components/workflow/utils'
import VarFullPathPanel from './var-full-path-panel'
import { noop } from 'lodash-es'
const TRIGGER_DEFAULT_WIDTH = 227
@@ -67,18 +64,15 @@
  placeholder?: string
  minWidth?: number
  popupFor?: 'assigned' | 'toAssigned'
  zIndex?: number
}
const DEFAULT_VALUE_SELECTOR: Props['value'] = []
const VarReferencePicker: FC<Props> = ({
  nodeId,
  readonly,
  className,
  isShowNodeName = true,
  value = DEFAULT_VALUE_SELECTOR,
  onOpen = noop,
  value = [],
  onOpen = () => { },
  onChange,
  isSupportConstantValue,
  defaultVarKindType = VarKindType.constant,
@@ -96,7 +90,6 @@
  placeholder,
  minWidth,
  popupFor,
  zIndex,
}) => {
  const { t } = useTranslation()
  const store = useStoreApi()
@@ -106,7 +99,7 @@
  const isChatMode = useIsChatMode()
  const { getCurrentVariableType } = useWorkflowVariables()
  const { availableVars, availableNodesWithParent: availableNodes } = useAvailableVarList(nodeId, {
  const { availableNodes, availableVars } = useAvailableVarList(nodeId, {
    onlyLeafNodeVar,
    passedInAvailableNodes,
    filterVar,
@@ -118,9 +111,6 @@
  const node = getNodes().find(n => n.id === nodeId)
  const isInIteration = !!node?.data.isInIteration
  const iterationNode = isInIteration ? getNodes().find(n => n.id === node.parentId) : null
  const isInLoop = !!node?.data.isInLoop
  const loopNode = isInLoop ? getNodes().find(n => n.id === node.parentId) : null
  const triggerRef = useRef<HTMLDivElement>(null)
  const [triggerWidth, setTriggerWidth] = useState(TRIGGER_DEFAULT_WIDTH)
@@ -150,14 +140,6 @@
    return false
  }, [isInIteration, value, node])
  const isLoopVar = useMemo(() => {
    if (!isInLoop)
      return false
    if (value[0] === node?.parentId && ['item', 'index'].includes(value[1]))
      return true
    return false
  }, [isInLoop, value, node])
  const outputVarNodeId = hasValue ? value[0] : ''
  const outputVarNode = useMemo(() => {
    if (!hasValue || isConstant)
@@ -166,24 +148,22 @@
    if (isIterationVar)
      return iterationNode?.data
    if (isLoopVar)
      return loopNode?.data
    if (isSystemVar(value as ValueSelector))
      return startNode?.data
    return getNodeInfoById(availableNodes, outputVarNodeId)?.data
  }, [value, hasValue, isConstant, isIterationVar, iterationNode, availableNodes, outputVarNodeId, startNode, isLoopVar, loopNode])
  const isShowAPart = (value as ValueSelector).length > 2
  }, [value, hasValue, isConstant, isIterationVar, iterationNode, availableNodes, outputVarNodeId, startNode])
  const varName = useMemo(() => {
    if (!hasValue)
      return ''
    if (hasValue) {
      const isSystem = isSystemVar(value as ValueSelector)
      let varName = ''
      if (Array.isArray(value))
        varName = value.length >= 3 ? (value as ValueSelector).slice(-2).join('.') : value[value.length - 1]
    const isSystem = isSystemVar(value as ValueSelector)
    const varName = Array.isArray(value) ? value[(value as ValueSelector).length - 1] : ''
    return `${isSystem ? 'sys.' : ''}${varName}`
      return `${isSystem ? 'sys.' : ''}${varName}`
    }
    return ''
  }, [hasValue, value])
  const varKindTypes = [
@@ -238,7 +218,7 @@
  }, [onChange, varKindType])
  const type = getCurrentVariableType({
    parentNode: isInIteration ? iterationNode : loopNode,
    parentNode: iterationNode,
    valueSelector: value as ValueSelector,
    availableNodes,
    isChatMode,
@@ -271,22 +251,6 @@
  const WrapElem = isSupportConstantValue ? 'div' : PortalToFollowElemTrigger
  const VarPickerWrap = !isSupportConstantValue ? 'div' : PortalToFollowElemTrigger
  const tooltipPopup = useMemo(() => {
    if (isValidVar && isShowAPart) {
      return (
        <VarFullPathPanel
          nodeName={outputVarNode?.title}
          path={(value as ValueSelector).slice(1)}
          varType={varTypeToStructType(type)}
          nodeType={outputVarNode?.type}
        />)
    }
    if (!isValidVar && hasValue)
      return t('workflow.errorMsg.invalidVariable')
    return null
  }, [isValidVar, isShowAPart, hasValue, t, outputVarNode?.title, outputVarNode?.type, value, type])
  return (
    <div className={cn(className, !readonly && 'cursor-pointer')}>
      <PortalToFollowElem
@@ -298,27 +262,27 @@
          if (readonly)
            return
          !isConstant ? setOpen(!open) : setControlFocus(Date.now())
        }} className='group/picker-trigger-wrap relative !flex'>
        }} className='!flex group/picker-trigger-wrap relative'>
          <>
            {isAddBtnTrigger
              ? (
                <div>
                  <AddButton onClick={noop}></AddButton>
                  <AddButton onClick={() => { }}></AddButton>
                </div>
              )
              : (<div ref={!isSupportConstantValue ? triggerRef : null} className={cn((open || isFocus) ? 'border-gray-300' : 'border-gray-100', 'group/wrap relative flex h-8 w-full items-center', !isSupportConstantValue && 'rounded-lg bg-components-input-bg-normal p-1', isInTable && 'border-none bg-transparent', readonly && 'bg-components-input-bg-disabled')}>
              : (<div ref={!isSupportConstantValue ? triggerRef : null} className={cn((open || isFocus) ? 'border-gray-300' : 'border-gray-100', 'relative group/wrap flex items-center w-full h-8', !isSupportConstantValue && 'p-1 rounded-lg bg-components-input-bg-normal', isInTable && 'bg-transparent border-none', readonly && 'bg-components-input-bg-disabled')}>
                {isSupportConstantValue
                  ? <div onClick={(e) => {
                    e.stopPropagation()
                    setOpen(false)
                    setControlFocus(Date.now())
                  }} className='mr-1 flex h-full items-center space-x-1'>
                  }} className='h-full mr-1 flex items-center space-x-1'>
                    <TypeSelector
                      noLeft
                      trigger={
                        <div className='radius-md flex h-8 items-center bg-components-input-bg-normal px-2'>
                          <div className='system-sm-regular mr-1 text-components-input-text-filled'>{varKindTypes.find(item => item.value === varKindType)?.label}</div>
                          <RiArrowDownSLine className='h-4 w-4 text-text-quaternary' />
                        <div className='flex items-center h-8 px-2 radius-md bg-components-input-bg-normal'>
                          <div className='mr-1 system-sm-regular text-components-input-text-filled'>{varKindTypes.find(item => item.value === varKindType)?.label}</div>
                          <RiArrowDownSLine className='w-4 h-4 text-text-quaternary' />
                        </div>
                      }
                      popupClassName='top-8'
@@ -330,7 +294,7 @@
                    />
                  </div>
                  : (!hasValue && <div className='ml-1.5 mr-1'>
                    <Variable02 className={`h-4 w-4 ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'}`} />
                    <Variable02 className={`w-4 h-4 ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'}`} />
                  </div>)}
                {isConstant
                  ? (
@@ -348,49 +312,43 @@
                          return
                        !isConstant ? setOpen(!open) : setControlFocus(Date.now())
                      }}
                      className='h-full grow'
                      className='grow h-full'
                    >
                      <div ref={isSupportConstantValue ? triggerRef : null} className={cn('h-full', isSupportConstantValue && 'flex items-center rounded-lg bg-components-panel-bg py-1 pl-1')}>
                        <Tooltip noDecoration={isShowAPart} popupContent={tooltipPopup}>
                          <div className={cn('h-full items-center rounded-[5px] px-1.5', hasValue ? 'inline-flex bg-components-badge-white-to-dark' : 'flex')}>
                      <div ref={isSupportConstantValue ? triggerRef : null} className={cn('h-full', isSupportConstantValue && 'flex items-center pl-1 py-1 rounded-lg bg-gray-100')}>
                        <Tooltip popupContent={!isValidVar && hasValue && t('workflow.errorMsg.invalidVariable')}>
                          <div className={cn('h-full items-center px-1.5 rounded-[5px]', hasValue ? 'bg-white inline-flex' : 'flex')}>
                            {hasValue
                              ? (
                                <>
                                  {isShowNodeName && !isEnv && !isChatVar && (
                                    <div className='flex items-center'>
                                      <div className='h-3 px-[1px]'>
                                      <div className='px-[1px] h-3'>
                                        {outputVarNode?.type && <VarBlockIcon
                                          className='!text-text-primary'
                                          className='!text-gray-900'
                                          type={outputVarNode.type}
                                        />}
                                      </div>
                                      <div className='mx-0.5 truncate text-xs font-medium text-text-secondary' title={outputVarNode?.title} style={{
                                      <div className='mx-0.5 text-xs font-medium text-gray-700 truncate' title={outputVarNode?.title} style={{
                                        maxWidth: maxNodeNameWidth,
                                      }}>{outputVarNode?.title}</div>
                                      <Line3 className='mr-0.5'></Line3>
                                    </div>
                                  )}
                                  {isShowAPart && (
                                    <div className='flex items-center'>
                                      <RiMoreLine className='h-3 w-3 text-text-secondary' />
                                      <Line3 className='mr-0.5 text-divider-deep'></Line3>
                                    </div>
                                  )}
                                  <div className='flex items-center text-text-accent'>
                                    {!hasValue && <Variable02 className='h-3.5 w-3.5' />}
                                    {isEnv && <Env className='h-3.5 w-3.5 text-util-colors-violet-violet-600' />}
                                    {isChatVar && <BubbleX className='h-3.5 w-3.5 text-util-colors-teal-teal-700' />}
                                    <div className={cn('ml-0.5 truncate text-xs font-medium', isEnv && '!text-text-secondary', isChatVar && 'text-util-colors-teal-teal-700', isException && 'text-text-warning')} title={varName} style={{
                                  <div className='flex items-center text-primary-600'>
                                    {!hasValue && <Variable02 className='w-3.5 h-3.5' />}
                                    {isEnv && <Env className='w-3.5 h-3.5 text-util-colors-violet-violet-600' />}
                                    {isChatVar && <BubbleX className='w-3.5 h-3.5 text-util-colors-teal-teal-700' />}
                                    <div className={cn('ml-0.5 text-xs font-medium truncate', isEnv && '!text-text-secondary', isChatVar && 'text-util-colors-teal-teal-700', isException && 'text-text-warning')} title={varName} style={{
                                      maxWidth: maxVarNameWidth,
                                    }}>{varName}</div>
                                  </div>
                                  <div className='system-xs-regular ml-0.5 truncate text-center capitalize text-text-tertiary' title={type} style={{
                                  <div className='ml-0.5 capitalize truncate text-text-tertiary text-center system-xs-regular' title={type} style={{
                                    maxWidth: maxTypeWidth,
                                  }}>{type}</div>
                                  {!isValidVar && <RiErrorWarningFill className='ml-0.5 h-3 w-3 text-text-destructive' />}
                                  {!isValidVar && <RiErrorWarningFill className='ml-0.5 w-3 h-3 text-[#D92D20]' />}
                                </>
                              )
                              : <div className={`overflow-hidden ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'} system-sm-regular text-ellipsis`}>{placeholder ?? t('workflow.common.setVarValuePlaceholder')}</div>}
                              : <div className={`overflow-hidden ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'} text-ellipsis system-sm-regular`}>{placeholder ?? t('workflow.common.setVarValuePlaceholder')}</div>}
                          </div>
                        </Tooltip>
                      </div>
@@ -398,10 +356,10 @@
                    </VarPickerWrap>
                  )}
                {(hasValue && !readonly && !isInTable) && (<div
                  className='group invisible absolute right-1 top-[50%] h-5 translate-y-[-50%] cursor-pointer rounded-md p-1 hover:bg-state-base-hover group-hover/wrap:visible'
                  className='invisible group-hover/wrap:visible absolute h-5 right-1 top-[50%] translate-y-[-50%] group p-1 rounded-md hover:bg-black/5 cursor-pointer'
                  onClick={handleClearVar}
                >
                  <RiCloseLine className='h-3.5 w-3.5 text-text-tertiary group-hover:text-text-secondary' />
                  <RiCloseLine className='w-3.5 h-3.5 text-gray-500 group-hover:text-gray-800' />
                </div>)}
                {!hasValue && valueTypePlaceHolder && (
                  <Badge
@@ -413,7 +371,7 @@
              </div>)}
            {!readonly && isInTable && (
              <RemoveButton
                className='absolute right-1 top-0.5 hidden group-hover/picker-trigger-wrap:block'
                className='group-hover/picker-trigger-wrap:block hidden absolute right-1 top-0.5'
                onClick={() => onRemove?.()}
              />
            )}
@@ -428,7 +386,7 @@
          </>
        </WrapElem>
        <PortalToFollowElemContent style={{
          zIndex: zIndex || 100,
          zIndex: 100,
        }} className='mt-1'>
          {!isConstant && (
            <VarReferencePopup