wwf
3 天以前 a430284aa21e3ae1f0d5654e55b2ad2852519cc2
app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx
@@ -1,25 +1,10 @@
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
import {
  RiFileTextLine,
  RiFilmAiLine,
  RiImageCircleAiLine,
  RiVoiceAiFill,
} from '@remixicon/react'
import type {
  DefaultModel,
  Model,
  ModelItem,
} from '../declarations'
import {
  ModelFeatureEnum,
  ModelFeatureTextEnum,
  ModelTypeEnum,
} from '../declarations'
import {
  modelTypeFormat,
  sizeFormat,
} from '../utils'
import {
  useLanguage,
  useUpdateModelList,
@@ -27,16 +12,15 @@
} from '../hooks'
import ModelIcon from '../model-icon'
import ModelName from '../model-name'
import ModelBadge from '../model-badge'
import {
  ConfigurationMethodEnum,
  MODEL_STATUS_TEXT,
  ModelStatusEnum,
} from '../declarations'
import { Check } from '@/app/components/base/icons/src/vender/line/general'
import { useModalContext } from '@/context/modal-context'
import { useProviderContext } from '@/context/provider-context'
import Tooltip from '@/app/components/base/tooltip'
import cn from '@/utils/classnames'
type PopupItemProps = {
  defaultModel?: DefaultModel
@@ -80,104 +64,50 @@
  return (
    <div className='mb-1'>
      <div className='flex h-[22px] items-center px-3 text-xs font-medium text-text-tertiary'>
      <div className='flex items-center px-3 h-[22px] text-xs font-medium text-gray-500'>
        {model.label[language] || model.label.en_US}
      </div>
      {
        model.models.map(modelItem => (
          <Tooltip
            key={modelItem.model}
            popupContent={modelItem.status !== ModelStatusEnum.active ? MODEL_STATUS_TEXT[modelItem.status][language] : undefined}
            position='right'
            popupClassName='p-3 !w-[206px] bg-components-panel-bg-blur backdrop-blur-sm border-[0.5px] border-components-panel-border rounded-xl'
            popupContent={
              <div className='flex flex-col gap-1'>
                <div className='flex flex-col items-start gap-2'>
                  <ModelIcon
                    className={cn('h-5 w-5 shrink-0')}
                    provider={model}
                    modelName={modelItem.model}
                  />
                  <div className='system-md-medium text-wrap break-words text-text-primary'>{modelItem.label[language] || modelItem.label.en_US}</div>
                </div>
                {/* {currentProvider?.description && (
                  <div className='text-text-tertiary system-xs-regular'>{currentProvider?.description?.[language] || currentProvider?.description?.en_US}</div>
                )} */}
                <div className='flex flex-wrap gap-1'>
                  {modelItem.model_type && (
                    <ModelBadge>
                      {modelTypeFormat(modelItem.model_type)}
                    </ModelBadge>
                  )}
                  {modelItem.model_properties.mode && (
                    <ModelBadge>
                      {(modelItem.model_properties.mode as string).toLocaleUpperCase()}
                    </ModelBadge>
                  )}
                  {modelItem.model_properties.context_size && (
                    <ModelBadge>
                      {sizeFormat(modelItem.model_properties.context_size as number)}
                    </ModelBadge>
                  )}
                </div>
                {modelItem.model_type === ModelTypeEnum.textGeneration && modelItem.features?.some(feature => [ModelFeatureEnum.vision, ModelFeatureEnum.audio, ModelFeatureEnum.video, ModelFeatureEnum.document].includes(feature)) && (
                  <div className='pt-2'>
                    <div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t('common.model.capabilities')}</div>
                    <div className='flex flex-wrap gap-1'>
                      {modelItem.features?.includes(ModelFeatureEnum.vision) && (
                        <ModelBadge>
                          <RiImageCircleAiLine className='mr-0.5 h-3.5 w-3.5' />
                          <span>{ModelFeatureTextEnum.vision}</span>
                        </ModelBadge>
                      )}
                      {modelItem.features?.includes(ModelFeatureEnum.audio) && (
                        <ModelBadge>
                          <RiVoiceAiFill className='mr-0.5 h-3.5 w-3.5' />
                          <span>{ModelFeatureTextEnum.audio}</span>
                        </ModelBadge>
                      )}
                      {modelItem.features?.includes(ModelFeatureEnum.video) && (
                        <ModelBadge>
                          <RiFilmAiLine className='mr-0.5 h-3.5 w-3.5' />
                          <span>{ModelFeatureTextEnum.video}</span>
                        </ModelBadge>
                      )}
                      {modelItem.features?.includes(ModelFeatureEnum.document) && (
                        <ModelBadge>
                          <RiFileTextLine className='mr-0.5 h-3.5 w-3.5' />
                          <span>{ModelFeatureTextEnum.document}</span>
                        </ModelBadge>
                      )}
                    </div>
                  </div>
                )}
              </div>
            }
          >
            <div
              key={modelItem.model}
              className={cn('group relative flex h-8 items-center gap-1 rounded-lg px-3 py-1.5', modelItem.status === ModelStatusEnum.active ? 'cursor-pointer hover:bg-state-base-hover' : 'cursor-not-allowed hover:bg-state-base-hover-alt')}
              className={`
                group relative flex items-center px-3 py-1.5 h-8 rounded-lg
                ${modelItem.status === ModelStatusEnum.active ? 'cursor-pointer hover:bg-gray-50' : 'cursor-not-allowed hover:bg-gray-50/60'}
              `}
              onClick={() => handleSelect(model.provider, modelItem)}
            >
              <div className='flex items-center gap-2'>
                <ModelIcon
                  className={cn('h-5 w-5 shrink-0')}
                className={`
                  shrink-0 mr-2 w-4 h-4
                  ${modelItem.status !== ModelStatusEnum.active && 'opacity-60'}
                `}
                  provider={model}
                  modelName={modelItem.model}
                />
                <ModelName
                  className={cn('system-sm-medium text-text-secondary', modelItem.status !== ModelStatusEnum.active && 'opacity-60')}
                className={`
                  grow text-sm font-normal text-gray-900
                  ${modelItem.status !== ModelStatusEnum.active && 'opacity-60'}
                `}
                  modelItem={modelItem}
                showMode
                showFeatures
                />
              </div>
              {
                defaultModel?.model === modelItem.model && defaultModel.provider === currentProvider.provider && (
                  <Check className='h-4 w-4 shrink-0 text-text-accent' />
                  <Check className='shrink-0 w-4 h-4 text-primary-600' />
                )
              }
              {
                modelItem.status === ModelStatusEnum.noConfigure && (
                  <div
                    className='hidden cursor-pointer text-xs font-medium text-text-accent group-hover:block'
                    className='hidden group-hover:block text-xs font-medium text-primary-600 cursor-pointer'
                    onClick={handleOpenModelModal}
                  >
                    {t('common.operation.add').toLocaleUpperCase()}