fix(web): app file

This commit is contained in:
zhaoying
2026-03-27 18:03:09 +08:00
parent 7dce63dc0b
commit 57b6b34567
9 changed files with 37 additions and 27 deletions

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-03-17 14:22:25 * @Date: 2026-03-17 14:22:25
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-23 17:42:38 * @Last Modified time: 2026-03-27 17:54:47
*/ */
// Toolbar component for chat input area, supporting file upload, audio recording, and variable configuration // Toolbar component for chat input area, supporting file upload, audio recording, and variable configuration
import { useRef, forwardRef, useImperativeHandle, type ReactNode, useEffect } from 'react' import { useRef, forwardRef, useImperativeHandle, type ReactNode, useEffect } from 'react'
@@ -19,6 +19,7 @@ import type { UploadFileListModalRef } from '@/views/Conversation/types'
import type { VariableConfigModalRef } from '@/views/Workflow/types' import type { VariableConfigModalRef } from '@/views/Workflow/types'
import type { Variable } from '@/views/Workflow/components/Properties/VariableList/types' import type { Variable } from '@/views/Workflow/components/Properties/VariableList/types'
import { getFileInfoByUrl } from '@/api/fileStorage'; import { getFileInfoByUrl } from '@/api/fileStorage';
import { transform_file_type } from '@/views/Conversation/components/FileUpload'
// Exposed methods via ref for parent components to access/set form state // Exposed methods via ref for parent components to access/set form state
export interface ChatToolbarRef { export interface ChatToolbarRef {
@@ -126,7 +127,7 @@ const ChatToolbar = forwardRef<ChatToolbarRef, ChatToolbarProps>(({
status: 'done', status: 'done',
name: file_name, name: file_name,
size: file_size, size: file_size,
type: content_type, type: transform_file_type[content_type] || content_type,
} : f) } : f)
form.setFieldValue('files', updated) form.setFieldValue('files', updated)
onFilesChange?.(updated) onFilesChange?.(updated)

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:27:39 * @Date: 2026-02-03 16:27:39
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-26 13:41:44 * @Last Modified time: 2026-03-27 17:59:07
*/ */
/** /**
* Chat debugging component for application testing * Chat debugging component for application testing
@@ -224,11 +224,11 @@ const Chat: FC<ChatProps> = ({
if (loading || !id) return if (loading || !id) return
setLoading(true) setLoading(true)
setCompareLoading(true) setCompareLoading(true)
const files = (fileList || []).filter(item => !['uploading', 'error'].includes(item.status))
handleSave(false) handleSave(false)
.then(() => { .then(() => {
const message = msg const message = msg
if (!message?.trim()) return if (!message?.trim()) return
const files = (toolbarRef.current?.getFiles() || []).filter(item => !['uploading', 'error'].includes(item.status))
// Validate required variables before sending // Validate required variables before sending
let isCanSend = true let isCanSend = true
const params: Record<string, any> = {} const params: Record<string, any> = {}
@@ -427,11 +427,11 @@ const Chat: FC<ChatProps> = ({
if (loading || !id) return if (loading || !id) return
setLoading(true) setLoading(true)
setCompareLoading(true) setCompareLoading(true)
const files = (fileList || []).filter(item => !['uploading', 'error'].includes(item.status))
handleSave(false) handleSave(false)
.then(() => { .then(() => {
const message = msg const message = msg
if (!message || message.trim() === '') return if (!message || message.trim() === '') return
const files = (toolbarRef.current?.getFiles() || []).filter(item => !['uploading', 'error'].includes(item.status))
addUserMessage(message, files) addUserMessage(message, files)
setMessage(undefined) setMessage(undefined)
toolbarRef.current?.setFiles([]) toolbarRef.current?.setFiles([])

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:27:52 * @Date: 2026-02-03 16:27:52
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-24 15:58:23 * @Last Modified time: 2026-03-27 17:33:44
*/ */
import { type FC, useRef, useMemo, useCallback } from 'react'; import { type FC, useRef, useMemo, useCallback } from 'react';
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
@@ -212,7 +212,12 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
</Flex>} </Flex>}
extra={application?.type === 'workflow' && source !== 'sharing' && activeTab === 'arrangement' extra={application?.type === 'workflow' && source !== 'sharing' && activeTab === 'arrangement'
? <Flex align="center" justify="end" gap={10} className="rb:h-8"> ? <Flex align="center" justify="end" gap={10} className="rb:h-8">
<FeaturesConfig source={application?.type} value={features as FeaturesConfigForm} refresh={handleSaveFeaturesConfig} /> <FeaturesConfig
source={application?.type}
value={features as FeaturesConfigForm}
refresh={handleSaveFeaturesConfig}
chatVariables={(workflowRef.current?.chatVariables || []).map(v => ({ ...v, display_name: v.name }))}
/>
<Button onClick={clear}>{t('workflow.clear')}</Button> <Button onClick={clear}>{t('workflow.clear')}</Button>
<Button onClick={addvariable}>{t('workflow.addvariable')}</Button> <Button onClick={addvariable}>{t('workflow.addvariable')}</Button>
<Button onClick={run}>{t('workflow.run')}</Button> <Button onClick={run}>{t('workflow.run')}</Button>

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:27:56 * @Date: 2026-02-03 16:27:56
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-27 14:24:47 * @Last Modified time: 2026-03-27 17:32:10
*/ */
/** /**
* Copy Application Modal * Copy Application Modal
@@ -75,15 +75,15 @@ const FeaturesConfigModal = forwardRef<FeaturesConfigModalRef, FeaturesConfigMod
const formatFileTypeOptions = (fu: FeaturesConfigForm['file_upload']) => { const formatFileTypeOptions = (fu: FeaturesConfigForm['file_upload']) => {
let options = fu.document_enabled ? [{ type: 'document', enabled: fu.document_enabled, maxSize: fu.document_max_size_mb }] : [] let options = fu.document_enabled ? [{ type: 'document', enabled: fu.document_enabled, maxSize: fu.document_max_size_mb }] : []
if (!capability) return options if (!capability && source !== 'workflow') return options
if ((capability.includes('vision') || source === 'workflow') && fu.image_enabled) { if ((capability?.includes('vision') || source === 'workflow') && fu.image_enabled) {
options.push({ type: 'image', enabled: fu.image_enabled, maxSize: fu.image_max_size_mb }) options.push({ type: 'image', enabled: fu.image_enabled, maxSize: fu.image_max_size_mb })
} }
if ((capability.includes('audio') || source === 'workflow') && fu.audio_enabled) { if ((capability?.includes('audio') || source === 'workflow') && fu.audio_enabled) {
options.push({ type: 'audio', enabled: fu.audio_enabled, maxSize: fu.audio_max_size_mb }) options.push({ type: 'audio', enabled: fu.audio_enabled, maxSize: fu.audio_max_size_mb })
} }
if ((capability.includes('video') || source === 'workflow') && fu.video_enabled) { if ((capability?.includes('video') || source === 'workflow') && fu.video_enabled) {
options.push({ type: 'video', enabled: fu.video_enabled, maxSize: fu.video_max_size_mb }) options.push({ type: 'video', enabled: fu.video_enabled, maxSize: fu.video_max_size_mb })
} }
return options.filter(item => item.enabled) return options.filter(item => item.enabled)

View File

@@ -8,7 +8,7 @@ import type { KnowledgeConfig } from './components/Knowledge/types'
import type { Variable } from './components/VariableList/types' import type { Variable } from './components/VariableList/types'
import type { ToolOption } from './components/ToolList/types' import type { ToolOption } from './components/ToolList/types'
import type { ChatItem } from '@/components/Chat/types' import type { ChatItem } from '@/components/Chat/types'
import type { GraphRef, WorkflowConfig } from '@/views/Workflow/types'; import type { ChatVariable, GraphRef, WorkflowConfig } from '@/views/Workflow/types';
import type { ApiKey } from '@/views/ApiKeyManagement/types' import type { ApiKey } from '@/views/ApiKeyManagement/types'
import type { SkillConfigForm } from './components/Skill/types' import type { SkillConfigForm } from './components/Skill/types'
import type { Capability } from '@/views/ModelManagement/types' import type { Capability } from '@/views/ModelManagement/types'
@@ -164,6 +164,7 @@ export interface WorkflowRef {
graphRef: GraphRef; graphRef: GraphRef;
/** Add variable */ /** Add variable */
addVariable: () => void; addVariable: () => void;
chatVariables: ChatVariable[];
config: WorkflowConfig | null; config: WorkflowConfig | null;
features: WorkflowConfig['features']; features: WorkflowConfig['features'];
handleSaveFeaturesConfig?: (value: FeaturesConfigForm) => void; handleSaveFeaturesConfig?: (value: FeaturesConfigForm) => void;

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-06 21:09:42 * @Date: 2026-02-06 21:09:42
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-23 17:19:58 * @Last Modified time: 2026-03-27 17:55:04
*/ */
/** /**
* File Upload Component * File Upload Component
@@ -59,7 +59,7 @@ interface UploadFilesProps extends Omit<UploadProps, 'onChange'> {
featureConfig: FeaturesConfigForm['file_upload'] featureConfig: FeaturesConfigForm['file_upload']
} }
const transform_file_type = { export const transform_file_type: Record<string, string> = {
'text/plain': 'document/text', 'text/plain': 'document/text',
'text/markdown': 'document/markdown', 'text/markdown': 'document/markdown',
'text/x-markdown': 'document/x-markdown', 'text/x-markdown': 'document/x-markdown',

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-06 21:10:56 * @Date: 2026-02-06 21:10:56
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-25 13:57:40 * @Last Modified time: 2026-03-27 17:30:47
*/ */
/** /**
* Workflow Chat Component * Workflow Chat Component
@@ -41,7 +41,9 @@ import type { ChatToolbarRef } from '@/components/Chat/ChatToolbar'
import Runtime from './Runtime'; import Runtime from './Runtime';
import type { FeaturesConfigForm } from '@/views/ApplicationConfig/types'; import type { FeaturesConfigForm } from '@/views/ApplicationConfig/types';
const Chat = forwardRef<ChatRef, { appId: string; graphRef: GraphRef; data: WorkflowConfig | null }>(({ appId, graphRef, data }, ref) => { const Chat = forwardRef<ChatRef, { appId: string; graphRef: GraphRef; data: WorkflowConfig | null; features?: FeaturesConfigForm }>(({
appId, graphRef, features
}, ref) => {
const { t } = useTranslation() const { t } = useTranslation()
const { message: messageApi } = App.useApp() const { message: messageApi } = App.useApp()
const toolbarRef = useRef<ChatToolbarRef>(null) const toolbarRef = useRef<ChatToolbarRef>(null)
@@ -58,7 +60,6 @@ const Chat = forwardRef<ChatRef, { appId: string; graphRef: GraphRef; data: Work
const [conversationId, setConversationId] = useState<string | null>(null) const [conversationId, setConversationId] = useState<string | null>(null)
const [fileList, setFileList] = useState<any[]>([]) const [fileList, setFileList] = useState<any[]>([])
const [message, setMessage] = useState<string | undefined>(undefined) const [message, setMessage] = useState<string | undefined>(undefined)
const [features, setFeatures] = useState<FeaturesConfigForm>({} as FeaturesConfigForm)
/** /**
* Opens the chat drawer and loads workflow variables from the start node * Opens the chat drawer and loads workflow variables from the start node
@@ -67,10 +68,6 @@ const Chat = forwardRef<ChatRef, { appId: string; graphRef: GraphRef; data: Work
setOpen(true) setOpen(true)
} }
useEffect(() => {
if (data?.features && open) setFeatures(data.features)
}, [open, data?.features])
useEffect(() => { useEffect(() => {
if (open && toolbarReady) { if (open && toolbarReady) {
getVariables() getVariables()
@@ -434,7 +431,7 @@ const Chat = forwardRef<ChatRef, { appId: string; graphRef: GraphRef; data: Work
> >
<ChatToolbar <ChatToolbar
ref={toolbarCallbackRef} ref={toolbarCallbackRef}
features={features} features={features as FeaturesConfigForm}
onFilesChange={setFileList} onFilesChange={setFileList}
onVariablesChange={setVariables} onVariablesChange={setVariables}
/> />

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 15:17:48 * @Date: 2026-02-03 15:17:48
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-24 15:01:52 * @Last Modified time: 2026-03-27 17:11:01
*/ */
import { useRef, useEffect, useState } from 'react'; import { useRef, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
@@ -72,6 +72,7 @@ export interface UseWorkflowGraphReturn {
handleAddNotes: () => void; handleAddNotes: () => void;
handleSaveFeaturesConfig: (value: FeaturesConfigForm) => void; handleSaveFeaturesConfig: (value: FeaturesConfigForm) => void;
features?: FeaturesConfigForm;
} }
/** /**
@@ -1212,6 +1213,7 @@ export const useWorkflowGraph = ({
} }
const handleSaveFeaturesConfig = (value?: FeaturesConfigForm) => { const handleSaveFeaturesConfig = (value?: FeaturesConfigForm) => {
featuresRef.current = value featuresRef.current = value
onFeaturesLoad?.(value)
} }
return { return {
@@ -1233,6 +1235,7 @@ export const useWorkflowGraph = ({
chatVariables, chatVariables,
setChatVariables, setChatVariables,
handleAddNotes, handleAddNotes,
handleSaveFeaturesConfig handleSaveFeaturesConfig,
features: featuresRef.current,
}; };
}; };

View File

@@ -34,7 +34,8 @@ const Workflow = forwardRef<WorkflowRef, { onFeaturesLoad?: (features: FeaturesC
chatVariables, chatVariables,
setChatVariables, setChatVariables,
handleAddNotes, handleAddNotes,
handleSaveFeaturesConfig handleSaveFeaturesConfig,
features
} = useWorkflowGraph({ containerRef, miniMapRef, onFeaturesLoad }); } = useWorkflowGraph({ containerRef, miniMapRef, onFeaturesLoad });
const onDragOver = (event: React.DragEvent) => { const onDragOver = (event: React.DragEvent) => {
@@ -55,8 +56,9 @@ const Workflow = forwardRef<WorkflowRef, { onFeaturesLoad?: (features: FeaturesC
handleRun, handleRun,
graphRef, graphRef,
addVariable, addVariable,
chatVariables,
config, config,
features: config?.features, features: features,
handleSaveFeaturesConfig handleSaveFeaturesConfig
})) }))
return ( return (
@@ -99,6 +101,7 @@ const Workflow = forwardRef<WorkflowRef, { onFeaturesLoad?: (features: FeaturesC
<Chat <Chat
ref={chatRef} ref={chatRef}
data={config} data={config}
features={features}
graphRef={graphRef} graphRef={graphRef}
appId={config?.app_id as string} appId={config?.app_id as string}
/> />