Allow file upload in chat.

This commit is contained in:
Eric-Guo
2025-09-08 16:15:46 +08:00
parent e91a1f6194
commit 17007b2014
2 changed files with 40 additions and 4 deletions

View File

@ -15,6 +15,9 @@ import Toast from '@/app/components/base/toast'
import ChatImageUploader from '@/app/components/base/image-uploader/chat-image-uploader' import ChatImageUploader from '@/app/components/base/image-uploader/chat-image-uploader'
import ImageList from '@/app/components/base/image-uploader/image-list' import ImageList from '@/app/components/base/image-uploader/image-list'
import { useImageFiles } from '@/app/components/base/image-uploader/hooks' import { useImageFiles } from '@/app/components/base/image-uploader/hooks'
import FileUploaderInAttachmentWrapper from '@/app/components/base/file-uploader-in-attachment'
import type { FileEntity, FileUpload } from '@/app/components/base/file-uploader-in-attachment/types'
import { getProcessedFiles } from '@/app/components/base/file-uploader-in-attachment/utils'
export type IChatProps = { export type IChatProps = {
chatList: ChatItem[] chatList: ChatItem[]
@ -33,6 +36,7 @@ export type IChatProps = {
isResponding?: boolean isResponding?: boolean
controlClearQuery?: number controlClearQuery?: number
visionConfig?: VisionSettings visionConfig?: VisionSettings
fileConfig?: FileUpload
} }
const Chat: FC<IChatProps> = ({ const Chat: FC<IChatProps> = ({
@ -46,6 +50,7 @@ const Chat: FC<IChatProps> = ({
isResponding, isResponding,
controlClearQuery, controlClearQuery,
visionConfig, visionConfig,
fileConfig,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { notify } = Toast const { notify } = Toast
@ -89,15 +94,20 @@ const Chat: FC<IChatProps> = ({
onClear, onClear,
} = useImageFiles() } = useImageFiles()
const [attachmentFiles, setAttachmentFiles] = React.useState<FileEntity[]>([])
const handleSend = () => { const handleSend = () => {
if (!valid() || (checkCanSend && !checkCanSend())) if (!valid() || (checkCanSend && !checkCanSend()))
return return
onSend(queryRef.current, files.filter(file => file.progress !== -1).map(fileItem => ({ const imageFiles: VisionFile[] = files.filter(file => file.progress !== -1).map(fileItem => ({
type: 'image', type: 'image',
transfer_method: fileItem.type, transfer_method: fileItem.type,
url: fileItem.url, url: fileItem.url,
upload_file_id: fileItem.fileId, upload_file_id: fileItem.fileId,
}))) }))
const docAndOtherFiles: VisionFile[] = getProcessedFiles(attachmentFiles)
const combinedFiles: VisionFile[] = [...imageFiles, ...docAndOtherFiles]
onSend(queryRef.current, combinedFiles)
if (!files.find(item => item.type === TransferMethod.local_file && !item.fileId)) { if (!files.find(item => item.type === TransferMethod.local_file && !item.fileId)) {
if (files.length) if (files.length)
onClear() onClear()
@ -106,6 +116,8 @@ const Chat: FC<IChatProps> = ({
queryRef.current = '' queryRef.current = ''
} }
} }
if (!attachmentFiles.find(item => item.transferMethod === TransferMethod.local_file && !item.uploadedId))
setAttachmentFiles([])
} }
const handleKeyUp = (e: any) => { const handleKeyUp = (e: any) => {
@ -187,6 +199,17 @@ const Chat: FC<IChatProps> = ({
</> </>
) )
} }
{
fileConfig?.enabled && (
<div className={`${visionConfig?.enabled ? 'pl-[52px]' : ''} mb-1`}>
<FileUploaderInAttachmentWrapper
fileConfig={fileConfig}
value={attachmentFiles}
onChange={setAttachmentFiles}
/>
</div>
)
}
<Textarea <Textarea
className={` className={`
block w-full px-2 pr-[118px] py-[7px] leading-5 max-h-none text-sm text-gray-700 outline-none appearance-none resize-none block w-full px-2 pr-[118px] py-[7px] leading-5 max-h-none text-sm text-gray-700 outline-none appearance-none resize-none

View File

@ -12,6 +12,7 @@ import ConfigSence from '@/app/components/config-scence'
import Header from '@/app/components/header' import Header from '@/app/components/header'
import { fetchAppParams, fetchChatList, fetchConversations, generationConversationName, sendChatMessage, updateFeedback } from '@/service' import { fetchAppParams, fetchChatList, fetchConversations, generationConversationName, sendChatMessage, updateFeedback } from '@/service'
import type { ChatItem, ConversationItem, Feedbacktype, PromptConfig, VisionFile, VisionSettings } from '@/types/app' import type { ChatItem, ConversationItem, Feedbacktype, PromptConfig, VisionFile, VisionSettings } from '@/types/app'
import type { FileUpload } from '@/app/components/base/file-uploader-in-attachment/types'
import { Resolution, TransferMethod, WorkflowRunningStatus } from '@/types/app' import { Resolution, TransferMethod, WorkflowRunningStatus } from '@/types/app'
import Chat from '@/app/components/chat' import Chat from '@/app/components/chat'
import { setLocaleOnClient } from '@/i18n/client' import { setLocaleOnClient } from '@/i18n/client'
@ -48,6 +49,7 @@ const Main: FC<IMainProps> = () => {
detail: Resolution.low, detail: Resolution.low,
transfer_methods: [TransferMethod.local_file], transfer_methods: [TransferMethod.local_file],
}) })
const [fileConfig, setFileConfig] = useState<FileUpload | undefined>()
useEffect(() => { useEffect(() => {
if (APP_INFO?.title) if (APP_INFO?.title)
@ -260,10 +262,20 @@ const Main: FC<IMainProps> = () => {
prompt_template: promptTemplate, prompt_template: promptTemplate,
prompt_variables, prompt_variables,
} as PromptConfig) } as PromptConfig)
const outerFileUploadEnabled = !!file_upload?.enabled
setVisionConfig({ setVisionConfig({
...file_upload?.image, ...file_upload?.image,
enabled: !!(outerFileUploadEnabled && file_upload?.image?.enabled),
image_file_size_limit: system_parameters?.system_parameters || 0, image_file_size_limit: system_parameters?.system_parameters || 0,
}) })
setFileConfig({
enabled: outerFileUploadEnabled,
allowed_file_types: file_upload?.allowed_file_types,
allowed_file_extensions: file_upload?.allowed_file_extensions,
allowed_file_upload_methods: file_upload?.allowed_file_upload_methods,
number_limits: file_upload?.number_limits,
fileUploadConfig: file_upload?.fileUploadConfig,
})
setConversationList(conversations as ConversationItem[]) setConversationList(conversations as ConversationItem[])
if (isNotNewConversation) if (isNotNewConversation)
@ -373,7 +385,7 @@ const Main: FC<IMainProps> = () => {
conversation_id: isNewConversation ? null : currConversationId, conversation_id: isNewConversation ? null : currConversationId,
} }
if (visionConfig?.enabled && files && files?.length > 0) { if (files && files?.length > 0) {
data.files = files.map((item) => { data.files = files.map((item) => {
if (item.transfer_method === TransferMethod.local_file) { if (item.transfer_method === TransferMethod.local_file) {
return { return {
@ -391,7 +403,7 @@ const Main: FC<IMainProps> = () => {
id: questionId, id: questionId,
content: message, content: message,
isAnswer: false, isAnswer: false,
message_files: files, message_files: (files || []).filter((f: any) => f.type === 'image'),
} }
const placeholderAnswerId = `answer-placeholder-${Date.now()}` const placeholderAnswerId = `answer-placeholder-${Date.now()}`
@ -700,6 +712,7 @@ const Main: FC<IMainProps> = () => {
isResponding={isResponding} isResponding={isResponding}
checkCanSend={checkCanSend} checkCanSend={checkCanSend}
visionConfig={visionConfig} visionConfig={visionConfig}
fileConfig={fileConfig}
/> />
</div> </div>
</div>) </div>)