Merge pull request #717 from SuanmoSuanyangTechnology/feature/ui_upgrade_zy
Feature/UI upgrade zy
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-02 15:25:31
|
* @Date: 2026-02-02 15:25:31
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-25 12:32:58
|
* @Last Modified time: 2026-03-27 16:38:57
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* SiderMenu Component
|
* SiderMenu Component
|
||||||
@@ -128,11 +128,35 @@ const Menu: FC<{
|
|||||||
|
|
||||||
/** Filter menus based on user role and source */
|
/** Filter menus based on user role and source */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
let menuList: MenuItem[] = []
|
||||||
|
|
||||||
if (user.role === 'member' && source === 'space') {
|
if (user.role === 'member' && source === 'space') {
|
||||||
setMenus((allMenus[source] || []).filter(menu => menu.code !== 'member'))
|
menuList = (allMenus[source] || []).filter(menu => menu.code !== 'member')
|
||||||
} else if (user) {
|
} else if (user) {
|
||||||
setMenus(allMenus[source] || [])
|
menuList = allMenus[source] || []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const noAuthList = ['user', 'pricing'].filter(vo => !user.permissions.includes(vo) && !user.permissions?.includes('all'))
|
||||||
|
|
||||||
|
if (noAuthList && !noAuthList?.includes('all')) {
|
||||||
|
const filterMenus = (list: MenuItem[]): MenuItem[] =>{
|
||||||
|
const filterList = list?.filter(menu => !noAuthList?.includes(menu.code as string))
|
||||||
|
|
||||||
|
const showList: MenuItem[] = []
|
||||||
|
filterList?.forEach(menu => {
|
||||||
|
const filteredSubs = filterMenus(menu.subs || [])
|
||||||
|
const hadSubs = menu.subs && menu.subs.length > 0
|
||||||
|
if (hadSubs && filteredSubs.length === 0) return
|
||||||
|
if (menu.type === 'group' && (!menu.subs || menu.subs?.length < 1)) return
|
||||||
|
showList.push({ ...menu, subs: filteredSubs })
|
||||||
|
})
|
||||||
|
|
||||||
|
return showList
|
||||||
|
}
|
||||||
|
menuList = filterMenus(menuList)
|
||||||
|
}
|
||||||
|
|
||||||
|
setMenus(menuList)
|
||||||
}, [source, allMenus, user])
|
}, [source, allMenus, user])
|
||||||
|
|
||||||
/** Handle menu item click and navigate to path */
|
/** Handle menu item click and navigate to path */
|
||||||
@@ -153,7 +177,7 @@ const Menu: FC<{
|
|||||||
const iconKey = selectedKeys.includes(menu.path || '') ? `${menu.code}Active` : menu.code;
|
const iconKey = selectedKeys.includes(menu.path || '') ? `${menu.code}Active` : menu.code;
|
||||||
const iconSrc = iconPathMap[iconKey as keyof typeof iconPathMap];
|
const iconSrc = iconPathMap[iconKey as keyof typeof iconPathMap];
|
||||||
const subs = (menu.subs || []).filter(sub => sub.display);
|
const subs = (menu.subs || []).filter(sub => sub.display);
|
||||||
|
|
||||||
/** Leaf node - menu item without children */
|
/** Leaf node - menu item without children */
|
||||||
if (!subs || subs.length === 0) {
|
if (!subs || subs.length === 0) {
|
||||||
if (menu.path) {
|
if (menu.path) {
|
||||||
|
|||||||
@@ -143,7 +143,7 @@
|
|||||||
"code": "systemSettings",
|
"code": "systemSettings",
|
||||||
"label": "systemSettings",
|
"label": "systemSettings",
|
||||||
"i18nKey": "menu.systemSettings",
|
"i18nKey": "menu.systemSettings",
|
||||||
"path": "/",
|
"path": null,
|
||||||
"enable": true,
|
"enable": true,
|
||||||
"display": true,
|
"display": true,
|
||||||
"level": 1,
|
"level": 1,
|
||||||
|
|||||||
@@ -396,3 +396,7 @@ body {
|
|||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
background-color: #171719;
|
background-color: #171719;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.spin.ant-spin-nested-loading .ant-spin-container::after {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 16:29:21
|
* @Date: 2026-02-03 16:29:21
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-27 13:46:18
|
* @Last Modified time: 2026-03-27 18:13:51
|
||||||
*/
|
*/
|
||||||
import { useEffect, useRef, useState, forwardRef, useImperativeHandle, useMemo } from 'react';
|
import { useEffect, useRef, useState, forwardRef, useImperativeHandle, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@@ -255,7 +255,7 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
|||||||
saveAgentConfig(data.app_id, params)
|
saveAgentConfig(data.app_id, params)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (flag) {
|
if (flag) {
|
||||||
message.success(t('common.saveSuccess'))
|
message.success({ content: t('common.saveSuccess'), duration: 1 })
|
||||||
}
|
}
|
||||||
setIsSave(false)
|
setIsSave(false)
|
||||||
resolve(res)
|
resolve(res)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 16:29:33
|
* @Date: 2026-02-03 16:29:33
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-27 11:51:34
|
* @Last Modified time: 2026-03-27 18:14:25
|
||||||
*/
|
*/
|
||||||
import { useEffect, useState, useRef, forwardRef, useImperativeHandle } from 'react'
|
import { useEffect, useState, useRef, forwardRef, useImperativeHandle } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@@ -79,7 +79,7 @@ const Cluster = forwardRef<ClusterRef, { onFeaturesLoad?: (features: FeaturesCon
|
|||||||
saveMultiAgentConfig(id as string, params)
|
saveMultiAgentConfig(id as string, params)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (flag) {
|
if (flag) {
|
||||||
message.success(t('common.saveSuccess'))
|
message.success({ content: t('common.saveSuccess'), duration: 1 })
|
||||||
}
|
}
|
||||||
resolve(res)
|
resolve(res)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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([])
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 16:49:45
|
* @Date: 2026-02-03 16:49:45
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-25 12:28:07
|
* @Last Modified time: 2026-03-27 18:06:23
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Model List Detail Drawer
|
* Model List Detail Drawer
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
import { useState, useImperativeHandle, forwardRef, useRef, useMemo } from 'react';
|
import { useState, useImperativeHandle, forwardRef, useRef, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Switch, Row, Col, Space, Tooltip } from 'antd'
|
import { Button, Switch, Row, Col, Space, Tooltip, Popover } from 'antd'
|
||||||
|
|
||||||
import type { ProviderModelItem, ModelListItem, ModelListDetailRef, MultiKeyConfigModalRef } from '../types';
|
import type { ProviderModelItem, ModelListItem, ModelListDetailRef, MultiKeyConfigModalRef } from '../types';
|
||||||
import RbDrawer from '@/components/RbDrawer';
|
import RbDrawer from '@/components/RbDrawer';
|
||||||
@@ -136,11 +136,19 @@ const ModelListDetail = forwardRef<ModelListDetailRef, ModelListDetailProps>(({
|
|||||||
<RbCard
|
<RbCard
|
||||||
key={item.id}
|
key={item.id}
|
||||||
title={item.name}
|
title={item.name}
|
||||||
subTitle={<Space size={8} className="rb:mt-1!">
|
subTitle={
|
||||||
<Tag>{t(`modelNew.${item.type}`)}</Tag>
|
<Popover content={
|
||||||
<Tag color="warning">{item.api_keys.length}{t('modelNew.apiKeyNum')}</Tag>
|
<Space size={8} className="rb:mt-1!">
|
||||||
{item.capability?.filter(item => item !=='video').map(vo => <Tag key={vo}>{t(`modelNew.${vo}`)}</Tag>)}
|
<Tag>{t(`modelNew.${item.type}`)}</Tag>
|
||||||
</Space>}
|
<Tag color="warning">{item.api_keys.length}{t('modelNew.apiKeyNum')}</Tag>
|
||||||
|
{item.capability?.map(vo => <Tag key={vo}>{t(`modelNew.${vo}`)}</Tag>)}
|
||||||
|
</Space>}>
|
||||||
|
<Space size={8} className="rb:mt-1!">
|
||||||
|
<Tag>{t(`modelNew.${item.type}`)}</Tag>
|
||||||
|
<Tag color="warning">{item.api_keys.length}{t('modelNew.apiKeyNum')}</Tag>
|
||||||
|
{item.capability?.map(vo => <Tag key={vo}>{t(`modelNew.${vo}`)}</Tag>)}
|
||||||
|
</Space>
|
||||||
|
</Popover>}
|
||||||
avatarUrl={getLogoUrl(item.logo)}
|
avatarUrl={getLogoUrl(item.logo)}
|
||||||
avatar={
|
avatar={
|
||||||
<div className="rb:w-12 rb:h-12 rb:rounded-lg rb:mr-3.25 rb:bg-[#155eef] rb:flex rb:items-center rb:justify-center rb:text-[28px] rb:text-[#ffffff]">
|
<div className="rb:w-12 rb:h-12 rb:rounded-lg rb:mr-3.25 rb:bg-[#155eef] rb:flex rb:items-center rb:justify-center rb:text-[28px] rb:text-[#ffffff]">
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 17:50:56
|
* @Date: 2026-02-03 17:50:56
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-02-25 11:44:02
|
* @Last Modified time: 2026-03-27 16:03:32
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* User data type
|
* User data type
|
||||||
@@ -18,6 +18,7 @@ export interface User {
|
|||||||
current_workspace_id?: string;
|
current_workspace_id?: string;
|
||||||
current_workspace_name?: string;
|
current_workspace_name?: string;
|
||||||
role: 'member' | 'manager' | null;
|
role: 'member' | 'manager' | null;
|
||||||
|
permissions: string[];
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ const CommunityNetwork: FC<{ onSelectCommunity?: (node: RawCommunityNode) => voi
|
|||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <Flex align="center" justify="center" className="rb:w-full rb:h-full">
|
return <Flex align="center" justify="center" className="rb:w-full rb:h-full">
|
||||||
<Spin tip={t('userMemory.communityLoadingTip')} size="large" className="rb:text-[#5B6167]!">
|
<Spin tip={t('userMemory.communityLoadingTip')} size="large" className="rb:text-[#5B6167]! spin">
|
||||||
<div className="rb:w-64 rb:h-64" />
|
<div className="rb:w-64 rb:h-64" />
|
||||||
</Spin>
|
</Spin>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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 18:14:38
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1176,7 +1177,7 @@ export const useWorkflowGraph = ({
|
|||||||
saveWorkflowConfig(config.app_id, params as WorkflowConfig)
|
saveWorkflowConfig(config.app_id, params as WorkflowConfig)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (flag) {
|
if (flag) {
|
||||||
message.success(t('common.saveSuccess'))
|
message.success({ content: t('common.saveSuccess'), duration: 1 })
|
||||||
}
|
}
|
||||||
resolve(res)
|
resolve(res)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
@@ -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,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user