您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import React, { useState } from 'react'
  2. import type { FC } from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import { RiBookOpenLine } from '@remixicon/react'
  5. import type { CreateExternalAPIReq, FormSchema } from '../declarations'
  6. import Input from '@/app/components/base/input'
  7. import cn from '@/utils/classnames'
  8. import { useDocLink } from '@/context/i18n'
  9. type FormProps = {
  10. className?: string
  11. itemClassName?: string
  12. fieldLabelClassName?: string
  13. value: CreateExternalAPIReq
  14. onChange: (val: CreateExternalAPIReq) => void
  15. formSchemas: FormSchema[]
  16. inputClassName?: string
  17. }
  18. const Form: FC<FormProps> = React.memo(({
  19. className,
  20. itemClassName,
  21. fieldLabelClassName,
  22. value,
  23. onChange,
  24. formSchemas,
  25. inputClassName,
  26. }) => {
  27. const { t, i18n } = useTranslation()
  28. const docLink = useDocLink()
  29. const [changeKey, setChangeKey] = useState('')
  30. const handleFormChange = (key: string, val: string) => {
  31. setChangeKey(key)
  32. if (key === 'name') {
  33. onChange({ ...value, [key]: val })
  34. }
  35. else {
  36. onChange({
  37. ...value,
  38. settings: {
  39. ...value.settings,
  40. [key]: val,
  41. },
  42. })
  43. }
  44. }
  45. const renderField = (formSchema: FormSchema) => {
  46. const { variable, type, label, required } = formSchema
  47. const fieldValue = variable === 'name' ? value[variable] : (value.settings[variable as keyof typeof value.settings] || '')
  48. return (
  49. <div key={variable} className={cn(itemClassName, 'flex flex-col items-start gap-1 self-stretch')}>
  50. <div className="flex w-full items-center justify-between">
  51. <label className={cn(fieldLabelClassName, 'system-sm-semibold text-text-secondary')} htmlFor={variable}>
  52. {label[i18n.language] || label.en_US}
  53. {required && <span className='ml-1 text-red-500'>*</span>}
  54. </label>
  55. {variable === 'endpoint' && (
  56. <a
  57. href={docLink('/guides/knowledge-base/external-knowledge-api-documentation') || '/'}
  58. target='_blank'
  59. rel='noopener noreferrer'
  60. className='body-xs-regular flex items-center text-text-accent'
  61. >
  62. <RiBookOpenLine className='mr-1 h-3 w-3 text-text-accent' />
  63. {t('dataset.externalAPIPanelDocumentation')}
  64. </a>
  65. )}
  66. </div>
  67. <Input
  68. type={type === 'secret' ? 'password' : 'text'}
  69. id={variable}
  70. name={variable}
  71. value={fieldValue}
  72. onChange={val => handleFormChange(variable, val.target.value)}
  73. required={required}
  74. className={cn(inputClassName)}
  75. />
  76. </div>
  77. )
  78. }
  79. return (
  80. <form className={cn('flex flex-col items-start justify-center gap-4 self-stretch', className)}>
  81. {formSchemas.map(formSchema => renderField(formSchema))}
  82. </form>
  83. )
  84. })
  85. Form.displayName = 'Form'
  86. export default Form