From d32f7d36a6ed6e4bcd13790dc2fe8e9f368aa369 Mon Sep 17 00:00:00 2001
From: CaptainB
Date: Mon, 21 Apr 2025 18:58:46 +0800
Subject: [PATCH] feat: add support for uploading other file types and extend
file upload settings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
--story=1018411 --user=刘瑞斌 【工作流应用】文件上传可以支持其它文件类型 https://www.tapd.cn/57709429/s/1688679
---
.../start_node/impl/base_start_node.py | 5 +-
apps/application/flow/workflow_manage.py | 4 +
.../serializers/chat_message_serializers.py | 5 +-
apps/application/views/chat_views.py | 2 +
.../component/chat-input-operate/index.vue | 71 +++++++++++-
ui/src/locales/lang/en-US/common.ts | 6 +-
ui/src/locales/lang/zh-CN/common.ts | 4 +-
ui/src/locales/lang/zh-Hant/common.ts | 4 +-
.../component/FileUploadSettingDialog.vue | 101 +++++++++++++++---
ui/src/workflow/nodes/base-node/index.vue | 4 +-
ui/src/workflow/nodes/start-node/index.vue | 6 +-
11 files changed, 185 insertions(+), 27 deletions(-)
diff --git a/apps/application/flow/step_node/start_node/impl/base_start_node.py b/apps/application/flow/step_node/start_node/impl/base_start_node.py
index bf5203274..bd5bcbeee 100644
--- a/apps/application/flow/step_node/start_node/impl/base_start_node.py
+++ b/apps/application/flow/step_node/start_node/impl/base_start_node.py
@@ -40,6 +40,7 @@ class BaseStartStepNode(IStarNode):
self.context['document'] = details.get('document_list')
self.context['image'] = details.get('image_list')
self.context['audio'] = details.get('audio_list')
+ self.context['other'] = details.get('other_list')
self.status = details.get('status')
self.err_message = details.get('err_message')
for key, value in workflow_variable.items():
@@ -59,7 +60,8 @@ class BaseStartStepNode(IStarNode):
'question': question,
'image': self.workflow_manage.image_list,
'document': self.workflow_manage.document_list,
- 'audio': self.workflow_manage.audio_list
+ 'audio': self.workflow_manage.audio_list,
+ 'other': self.workflow_manage.other_list,
}
return NodeResult(node_variable, workflow_variable)
@@ -83,5 +85,6 @@ class BaseStartStepNode(IStarNode):
'image_list': self.context.get('image'),
'document_list': self.context.get('document'),
'audio_list': self.context.get('audio'),
+ 'other_list': self.context.get('other'),
'global_fields': global_fields
}
diff --git a/apps/application/flow/workflow_manage.py b/apps/application/flow/workflow_manage.py
index be91f69be..0f7bc9c75 100644
--- a/apps/application/flow/workflow_manage.py
+++ b/apps/application/flow/workflow_manage.py
@@ -238,6 +238,7 @@ class WorkflowManage:
base_to_response: BaseToResponse = SystemToResponse(), form_data=None, image_list=None,
document_list=None,
audio_list=None,
+ other_list=None,
start_node_id=None,
start_node_data=None, chat_record=None, child_node=None):
if form_data is None:
@@ -248,12 +249,15 @@ class WorkflowManage:
document_list = []
if audio_list is None:
audio_list = []
+ if other_list is None:
+ other_list = []
self.start_node_id = start_node_id
self.start_node = None
self.form_data = form_data
self.image_list = image_list
self.document_list = document_list
self.audio_list = audio_list
+ self.other_list = other_list
self.params = params
self.flow = flow
self.context = {}
diff --git a/apps/application/serializers/chat_message_serializers.py b/apps/application/serializers/chat_message_serializers.py
index 2194028e6..3eaf9a1ae 100644
--- a/apps/application/serializers/chat_message_serializers.py
+++ b/apps/application/serializers/chat_message_serializers.py
@@ -245,6 +245,7 @@ class OpenAIChatSerializer(serializers.Serializer):
'image_list': instance.get('image_list', []),
'document_list': instance.get('document_list', []),
'audio_list': instance.get('audio_list', []),
+ 'other_list': instance.get('other_list', []),
}
).chat(base_to_response=OpenaiToResponse())
@@ -274,6 +275,7 @@ class ChatMessageSerializer(serializers.Serializer):
image_list = serializers.ListField(required=False, error_messages=ErrMessage.list(_("picture")))
document_list = serializers.ListField(required=False, error_messages=ErrMessage.list(_("document")))
audio_list = serializers.ListField(required=False, error_messages=ErrMessage.list(_("Audio")))
+ other_list = serializers.ListField(required=False, error_messages=ErrMessage.list(_("Other")))
child_node = serializers.DictField(required=False, allow_null=True,
error_messages=ErrMessage.dict(_("Child Nodes")))
@@ -372,6 +374,7 @@ class ChatMessageSerializer(serializers.Serializer):
image_list = self.data.get('image_list')
document_list = self.data.get('document_list')
audio_list = self.data.get('audio_list')
+ other_list = self.data.get('other_list')
user_id = chat_info.application.user_id
chat_record_id = self.data.get('chat_record_id')
chat_record = None
@@ -388,7 +391,7 @@ class ChatMessageSerializer(serializers.Serializer):
'client_id': client_id,
'client_type': client_type,
'user_id': user_id}, WorkFlowPostHandler(chat_info, client_id, client_type),
- base_to_response, form_data, image_list, document_list, audio_list,
+ base_to_response, form_data, image_list, document_list, audio_list, other_list,
self.data.get('runtime_node_id'),
self.data.get('node_data'), chat_record, self.data.get('child_node'))
r = work_flow_manage.run()
diff --git a/apps/application/views/chat_views.py b/apps/application/views/chat_views.py
index 0415f8208..77a087351 100644
--- a/apps/application/views/chat_views.py
+++ b/apps/application/views/chat_views.py
@@ -144,6 +144,8 @@ class ChatView(APIView):
'document_list') if 'document_list' in request.data else [],
'audio_list': request.data.get(
'audio_list') if 'audio_list' in request.data else [],
+ 'other_list': request.data.get(
+ 'other_list') if 'other_list' in request.data else [],
'client_type': request.auth.client_type,
'node_id': request.data.get('node_id', None),
'runtime_node_id': request.data.get('runtime_node_id', None),
diff --git a/ui/src/components/ai-chat/component/chat-input-operate/index.vue b/ui/src/components/ai-chat/component/chat-input-operate/index.vue
index 2face1708..5babf0904 100644
--- a/ui/src/components/ai-chat/component/chat-input-operate/index.vue
+++ b/ui/src/components/ai-chat/component/chat-input-operate/index.vue
@@ -10,7 +10,8 @@
uploadDocumentList.length ||
uploadImageList.length ||
uploadAudioList.length ||
- uploadVideoList.length
+ uploadVideoList.length ||
+ uploadOtherList.length
"
>
@@ -50,6 +51,42 @@
+
+
+
+
+
+
+
+
+
![]()
+
+ {{ item && item?.name }}
+
+
+
+
{
- const { image, document, audio, video } = props.applicationDetails.file_upload_setting
+ const { image, document, audio, video, other } = props.applicationDetails.file_upload_setting
let accepts: any = []
if (image) {
accepts = [...imageExtensions]
@@ -326,6 +364,11 @@ const getAcceptList = () => {
if (video) {
accepts = [...accepts, ...videoExtensions]
}
+ if (other) {
+ // 其他文件类型
+ otherExtensions = props.applicationDetails.file_upload_setting.otherExtensions
+ accepts = [...accepts, ...otherExtensions]
+ }
if (accepts.length === 0) {
return `.${t('chat.uploadFile.tipMessage')}`
@@ -339,7 +382,8 @@ const checkMaxFilesLimit = () => {
uploadImageList.value.length +
uploadDocumentList.value.length +
uploadAudioList.value.length +
- uploadVideoList.value.length
+ uploadVideoList.value.length +
+ uploadOtherList.value.length
)
}
@@ -350,7 +394,8 @@ const uploadFile = async (file: any, fileList: any) => {
uploadImageList.value.length +
uploadDocumentList.value.length +
uploadAudioList.value.length +
- uploadVideoList.value.length
+ uploadVideoList.value.length +
+ uploadOtherList.value.length
if (file_limit_once >= maxFiles) {
MsgWarning(t('chat.uploadFile.limitMessage1') + maxFiles + t('chat.uploadFile.limitMessage2'))
fileList.splice(0, fileList.length)
@@ -376,6 +421,8 @@ const uploadFile = async (file: any, fileList: any) => {
uploadVideoList.value.push(file)
} else if (audioExtensions.includes(extension)) {
uploadAudioList.value.push(file)
+ } else if (otherExtensions.includes(extension)) {
+ uploadOtherList.value.push(file)
}
if (!chatId_context.value) {
@@ -434,6 +481,15 @@ const uploadFile = async (file: any, fileList: any) => {
file.file_id = f[0].file_id
}
})
+ uploadOtherList.value.forEach((file: any) => {
+ const f = response.data.filter(
+ (f: any) => f.name.replaceAll(' ', '') === file.name.replaceAll(' ', '')
+ )
+ if (f.length > 0) {
+ file.url = f[0].url
+ file.file_id = f[0].file_id
+ }
+ })
if (!inputValue.value && uploadImageList.value.length > 0) {
inputValue.value = t('chat.uploadFile.imageMessage')
}
@@ -499,6 +555,7 @@ const uploadImageList = ref>([])
const uploadDocumentList = ref>([])
const uploadVideoList = ref>([])
const uploadAudioList = ref>([])
+const uploadOtherList = ref>([])
const showDelete = ref('')
@@ -709,13 +766,15 @@ function autoSendMessage() {
image_list: uploadImageList.value,
document_list: uploadDocumentList.value,
audio_list: uploadAudioList.value,
- video_list: uploadVideoList.value
+ video_list: uploadVideoList.value,
+ other_list: uploadOtherList.value,
})
inputValue.value = ''
uploadImageList.value = []
uploadDocumentList.value = []
uploadAudioList.value = []
uploadVideoList.value = []
+ uploadOtherList.value = []
if (quickInputRef.value) {
quickInputRef.value.textareaStyle.height = '45px'
}
@@ -771,6 +830,8 @@ function deleteFile(index: number, val: string) {
uploadVideoList.value.splice(index, 1)
} else if (val === 'audio') {
uploadAudioList.value.splice(index, 1)
+ } else if (val === 'other') {
+ uploadOtherList.value.splice(index, 1)
}
}
diff --git a/ui/src/locales/lang/en-US/common.ts b/ui/src/locales/lang/en-US/common.ts
index 96afd9916..4e96b7069 100644
--- a/ui/src/locales/lang/en-US/common.ts
+++ b/ui/src/locales/lang/en-US/common.ts
@@ -45,7 +45,9 @@ export default {
document: 'Documents',
image: 'Image',
audio: 'Audio',
- video: 'Video'
+ video: 'Video',
+ other: 'Other file',
+ addExtensions: 'Add file extensions',
},
status: {
label: 'Status',
@@ -55,7 +57,7 @@ export default {
param: {
outputParam: 'Output Parameters',
inputParam: 'Input Parameters',
- initParam: 'Startup Parameters',
+ initParam: 'Startup Parameters'
},
inputPlaceholder: 'Please input',
diff --git a/ui/src/locales/lang/zh-CN/common.ts b/ui/src/locales/lang/zh-CN/common.ts
index 97e25b704..a3b3b8409 100644
--- a/ui/src/locales/lang/zh-CN/common.ts
+++ b/ui/src/locales/lang/zh-CN/common.ts
@@ -45,7 +45,9 @@ export default {
document: '文档',
image: '图片',
audio: '音频',
- video: '视频'
+ video: '视频',
+ other: '其他文件',
+ addExtensions: '添加文件扩展名',
},
status: {
label: '状态',
diff --git a/ui/src/locales/lang/zh-Hant/common.ts b/ui/src/locales/lang/zh-Hant/common.ts
index 0ccbb5c11..c1a1f93a0 100644
--- a/ui/src/locales/lang/zh-Hant/common.ts
+++ b/ui/src/locales/lang/zh-Hant/common.ts
@@ -45,7 +45,9 @@ export default {
document: '文檔',
image: '圖片',
audio: '音頻',
- video: '視頻'
+ video: '視頻',
+ other: '其他文件',
+ addExtensions: '添加文件擴展名'
},
status: {
label: '狀態',
diff --git a/ui/src/workflow/nodes/base-node/component/FileUploadSettingDialog.vue b/ui/src/workflow/nodes/base-node/component/FileUploadSettingDialog.vue
index ec4f9bebd..c22043fa3 100644
--- a/ui/src/workflow/nodes/base-node/component/FileUploadSettingDialog.vue
+++ b/ui/src/workflow/nodes/base-node/component/FileUploadSettingDialog.vue
@@ -57,10 +57,11 @@
{{ $t('common.fileUpload.document') }}(TXT、MD、DOCX、HTML、CSV、XLSX、XLS、PDF)
{{
- $t(
- 'views.applicationWorkflow.nodes.baseNode.FileUploadSetting.fileUploadType.documentText'
- )
- }}
+ $t(
+ 'views.applicationWorkflow.nodes.baseNode.FileUploadSetting.fileUploadType.documentText'
+ )
+ }}
+
{{
- $t(
- 'views.applicationWorkflow.nodes.baseNode.FileUploadSetting.fileUploadType.imageText'
- )
- }}
+ $t(
+ 'views.applicationWorkflow.nodes.baseNode.FileUploadSetting.fileUploadType.imageText'
+ )
+ }}
+
@@ -109,15 +111,58 @@
{{ $t('common.fileUpload.audio') }}(MP3、WAV、OGG、ACC、M4A)
{{
- $t(
- 'views.applicationWorkflow.nodes.baseNode.FileUploadSetting.fileUploadType.audioText'
- )
- }}
+ $t(
+ 'views.applicationWorkflow.nodes.baseNode.FileUploadSetting.fileUploadType.audioText'
+ )
+ }}
+
+
+
+
+

+
+
+ {{ $t('common.fileUpload.other') }}
+
+
+
+ {{ tag }}
+
+
+
+ + {{ $t('common.fileUpload.addExtensions') }}
+
+
+
+
+
+
+
@@ -133,20 +178,28 @@