diff --git a/web/src/components/avatar-upload.tsx b/web/src/components/avatar-upload.tsx new file mode 100644 index 000000000..8df544068 --- /dev/null +++ b/web/src/components/avatar-upload.tsx @@ -0,0 +1,71 @@ +import { transformFile2Base64 } from '@/utils/file-util'; +import { Pencil, Upload } from 'lucide-react'; +import { ChangeEventHandler, useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar'; +import { Input } from './ui/input'; + +type AvatarUploadProps = { value?: string; onChange?: (value: string) => void }; + +export function AvatarUpload({ value, onChange }: AvatarUploadProps) { + const { t } = useTranslation(); + const [avatarBase64Str, setAvatarBase64Str] = useState(''); // Avatar Image base64 + + const handleChange: ChangeEventHandler = useCallback( + async (ev) => { + const file = ev.target?.files?.[0]; + if (/\.(jpg|jpeg|png|webp|bmp)$/i.test(file?.name ?? '')) { + const str = await transformFile2Base64(file!); + setAvatarBase64Str(str); + onChange?.(str); + } + ev.target.value = ''; + }, + [onChange], + ); + + useEffect(() => { + if (value) { + setAvatarBase64Str(value); + } + }, [value]); + + return ( +
+
+ {!avatarBase64Str ? ( +
+
+ +

{t('common.upload')}

+
+
+ ) : ( +
+ + + + +
+ +
+
+ )} + +
+
+ {t('knowledgeConfiguration.photoTip')} +
+
+ ); +} diff --git a/web/src/pages/next-chats/chat/app-settings/chat-basic-settings.tsx b/web/src/pages/next-chats/chat/app-settings/chat-basic-settings.tsx index d5b50d8bc..b9746db7d 100644 --- a/web/src/pages/next-chats/chat/app-settings/chat-basic-settings.tsx +++ b/web/src/pages/next-chats/chat/app-settings/chat-basic-settings.tsx @@ -1,6 +1,6 @@ 'use client'; -import { FileUploader } from '@/components/file-uploader'; +import { AvatarUpload } from '@/components/avatar-upload'; import { KnowledgeBaseFormField } from '@/components/knowledge-base-item'; import { MetadataFilter } from '@/components/metadata-filter'; import { SwitchFormField } from '@/components/switch-fom-field'; @@ -49,14 +49,7 @@ export default function ChatBasicSetting() { {t('assistantAvatar')} - + diff --git a/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx b/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx index a33805bd1..27a47c6c8 100644 --- a/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx +++ b/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx @@ -3,7 +3,6 @@ import { Form } from '@/components/ui/form'; import { Separator } from '@/components/ui/separator'; import { DatasetMetadata } from '@/constants/chat'; import { useFetchDialog, useSetDialog } from '@/hooks/use-chat-request'; -import { transformBase64ToFile, transformFile2Base64 } from '@/utils/file-util'; import { removeUselessFieldsFromValues, setLLMSettingEnabledValues, @@ -36,7 +35,7 @@ export function ChatSettings({ switchSettingVisible }: ChatSettingsProps) { shouldUnregister: true, defaultValues: { name: '', - icon: [], + icon: '', language: 'English', description: '', kb_ids: [], @@ -64,15 +63,10 @@ export function ChatSettings({ switchSettingVisible }: ChatSettingsProps) { values, 'llm_setting.', ); - const icon = nextValues.icon; - const avatar = - Array.isArray(icon) && icon.length > 0 - ? await transformFile2Base64(icon[0]) - : ''; + setDialog({ ...omit(data, 'operator_permission'), ...nextValues, - icon: avatar, dialog_id: id, }); } @@ -88,7 +82,6 @@ export function ChatSettings({ switchSettingVisible }: ChatSettingsProps) { const nextData = { ...data, - icon: data.icon ? [transformBase64ToFile(data.icon)] : [], ...llmSettingEnabledValues, }; form.reset(nextData as FormSchemaType); diff --git a/web/src/pages/next-chats/chat/app-settings/use-chat-setting-schema.tsx b/web/src/pages/next-chats/chat/app-settings/use-chat-setting-schema.tsx index d92f013ad..c051619ff 100644 --- a/web/src/pages/next-chats/chat/app-settings/use-chat-setting-schema.tsx +++ b/web/src/pages/next-chats/chat/app-settings/use-chat-setting-schema.tsx @@ -32,7 +32,7 @@ export function useChatSettingSchema() { const formSchema = z.object({ name: z.string().min(1, { message: t('assistantNameMessage') }), - icon: z.array(z.instanceof(File)), + icon: z.string(), language: z.string().min(1, { message: t('languageMessage'), }),