Merge pull request #711 from SuanmoSuanyangTechnology/feature/ui_upgrade_zy
Feature/UI upgrade zy
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2025-12-10 16:46:17
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 13:32:29
|
||||
* @Last Modified time: 2026-03-27 14:17:38
|
||||
*/
|
||||
import { type FC, useRef, useEffect, useState } from 'react'
|
||||
import clsx from 'clsx'
|
||||
@@ -194,7 +194,10 @@ const ChatContent: FC<ChatContentProps> = ({
|
||||
key={idx}
|
||||
size="small"
|
||||
className="rb:text-[12px]!"
|
||||
onClick={() => window.open(`/knowledge/${citation.knowledge_id}/document/${citation.document_id}`, '_blank')}
|
||||
onClick={() => {
|
||||
const params = new URLSearchParams({ documentId: citation.document_id, parentId: citation.knowledge_id });
|
||||
window.open(`/#/knowledge-base/${citation.knowledge_id}/DocumentDetails?${params}`, '_blank');
|
||||
}}
|
||||
>{citation.file_name}</Button>
|
||||
))}
|
||||
</div>}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:02:47
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-02 15:47:24
|
||||
* @Last Modified time: 2026-03-26 14:58:24
|
||||
*/
|
||||
/**
|
||||
* BodyWrapper Component
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px 24px 16px 20px;
|
||||
height: 64px;
|
||||
color: #212332;
|
||||
z-index: 0;
|
||||
font-size: 14px;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:11:02
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-03 18:43:42
|
||||
* @Last Modified time: 2026-03-26 15:01:02
|
||||
*/
|
||||
/**
|
||||
* AuthLayout Component
|
||||
@@ -54,14 +54,14 @@ const AuthLayout: FC = () => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: '100vh' }}>
|
||||
<Layout className="rb:min-h-screen!">
|
||||
{/* Sidebar navigation */}
|
||||
<Sider />
|
||||
<Layout style={{maxHeight: '100vh', width: '100vh', overflowY: 'auto' }}>
|
||||
<Layout className="rb:max-h-screen! rb:w-screen! rb:overflow-y-auto!">
|
||||
{/* Header with breadcrumbs and user menu */}
|
||||
<AppHeader />
|
||||
{/* Main content area - renders child routes */}
|
||||
<Content style={{ padding: '0 12px 20px 12px', zIndex: 0 }}>
|
||||
<Content className="rb:px-3! rb:pb-3! rb:z-0! rb:flex-1!">
|
||||
<Outlet />
|
||||
</Content>
|
||||
</Layout>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:11:43
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-05 14:57:08
|
||||
* @Last Modified time: 2026-03-26 15:00:54
|
||||
*/
|
||||
/**
|
||||
* AuthSpaceLayout Component
|
||||
@@ -56,14 +56,14 @@ const AuthSpaceLayout: FC = () => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: '100vh' }}>
|
||||
<Layout className="rb:min-h-screen!">
|
||||
{/* Sidebar navigation configured for space mode */}
|
||||
<Sider source="space" />
|
||||
<Layout style={{maxHeight: '100vh', width: '100vh', overflowY: 'auto' }}>
|
||||
<Layout className="rb:max-h-screen! rb:w-screen! rb:overflow-y-auto!">
|
||||
{/* Header with breadcrumbs and user menu configured for space mode */}
|
||||
<AppHeader source="space" />
|
||||
{/* Main content area for knowledge base pages - renders child routes */}
|
||||
<Content style={{ padding: '0 12px 12px 12px', zIndex: 0, height: 'calc(100vh - 64px)', overflowY: 'auto' }}>
|
||||
<Content className="rb:px-3! rb:pb-3! rb:z-0! rb:flex-1! rb:overflow-y-auto!">
|
||||
<Outlet />
|
||||
</Content>
|
||||
</Layout>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:12:42
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-28 17:28:41
|
||||
* @Last Modified time: 2026-03-26 15:36:25
|
||||
*/
|
||||
/**
|
||||
* BasicAuthLayout Component
|
||||
@@ -35,7 +35,7 @@ const BasicAuthLayout: FC = () => {
|
||||
}, [getUserInfo]);
|
||||
|
||||
return (
|
||||
<div className="rb:relative rb:h-full rb:w-full">
|
||||
<div className="rb:relative rb:min-h-screen rb:w-screen">
|
||||
{/* Render child routes without additional UI */}
|
||||
<Outlet />
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-10 11:08:27
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 11:19:48
|
||||
* @Last Modified time: 2026-03-26 15:38:31
|
||||
*/
|
||||
/*
|
||||
* PageHeader Component
|
||||
@@ -43,7 +43,7 @@ const PageHeader: FC<ConfigHeaderProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
// Main header container: full width, 64px height, flex layout with space between
|
||||
<Header className={`rb:w-full rb:h-16 rb:grid rb:grid-cols-${extra && centerContent ? '3' : ((extra && !centerContent) || (!extra && centerContent)) ? '2': 1} rb:gap-6 rb:px-4! rb:bg-white!`}>
|
||||
<Header className={`rb:w-full rb:h-16! rb:grid rb:grid-cols-${extra && centerContent ? '3' : ((extra && !centerContent) || (!extra && centerContent)) ? '2': 1} rb:gap-6 rb:px-4! rb:bg-white!`}>
|
||||
<Flex align="center" gap={8}>
|
||||
{avatarUrl
|
||||
? <img src={avatarUrl} alt={avatarUrl} className="rb:size-8 rb:rounded-lg rb:mr-2" />
|
||||
@@ -58,7 +58,7 @@ const PageHeader: FC<ConfigHeaderProps> = ({
|
||||
{operation}
|
||||
</Flex>
|
||||
|
||||
{centerContent && <Flex align="center">
|
||||
{centerContent && <Flex align="center" justify="center">
|
||||
{centerContent}
|
||||
</Flex>}
|
||||
{/* Right section: Extra content (buttons, filters, etc.) */}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:18:19
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-19 20:47:34
|
||||
* @Last Modified time: 2026-03-26 14:43:33
|
||||
*/
|
||||
/**
|
||||
* PageScrollList Component
|
||||
@@ -56,9 +56,10 @@ interface PageScrollListProps<T, Q = Record<string, unknown>> {
|
||||
/** Additional CSS classes */
|
||||
className?: string;
|
||||
needLoading?: boolean;
|
||||
heightClass?: string;
|
||||
}
|
||||
|
||||
const heightClass = 'rb:h-[calc(100vh-124px)]!';
|
||||
const defaultHeightClass = 'rb:h-[calc(100vh-116px)]!';
|
||||
|
||||
/** Infinite scroll list component with pagination support */
|
||||
const PageScrollList = forwardRef(<T, Q = Record<string, unknown>>({
|
||||
@@ -68,6 +69,7 @@ const PageScrollList = forwardRef(<T, Q = Record<string, unknown>>({
|
||||
column = 4,
|
||||
className = '',
|
||||
needLoading = true,
|
||||
heightClass,
|
||||
}: PageScrollListProps<T, Q>, ref: React.Ref<PageScrollListRef>) => {
|
||||
/** Expose refresh method to parent component */
|
||||
useImperativeHandle(ref, () => ({
|
||||
@@ -140,13 +142,13 @@ const PageScrollList = forwardRef(<T, Q = Record<string, unknown>>({
|
||||
<div
|
||||
ref={scrollRef}
|
||||
id="scrollableDiv"
|
||||
className={`rb:overflow-y-auto rb:overflow-x-hidden ${heightClass} ${className}`}
|
||||
className={`rb:overflow-y-auto rb:overflow-x-hidden ${heightClass || defaultHeightClass} ${className}`}
|
||||
>
|
||||
<InfiniteScroll
|
||||
dataLength={data.length}
|
||||
next={() => loadMoreData()}
|
||||
hasMore={hasMore}
|
||||
loader={loading && needLoading ? <PageLoading className={heightClass} /> : false}
|
||||
loader={loading && needLoading ? <PageLoading className={heightClass || defaultHeightClass} /> : false}
|
||||
// endMessage={<Divider plain>It is all, nothing more 🤐</Divider>}
|
||||
scrollableTarget="scrollableDiv"
|
||||
className='rb:h-full!'
|
||||
@@ -162,7 +164,7 @@ const PageScrollList = forwardRef(<T, Q = Record<string, unknown>>({
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
) : !loading ? <PageEmpty className={heightClass} /> : null}
|
||||
) : !loading ? <PageEmpty className={heightClass || defaultHeightClass} /> : null}
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:29:46
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 17:11:55
|
||||
* @Last Modified time: 2026-03-26 14:52:23
|
||||
*/
|
||||
/**
|
||||
* RbTable Component
|
||||
@@ -199,7 +199,7 @@ const RbTable = forwardRef(<T = Record<string, unknown>, Q = Record<string, unkn
|
||||
if (scrollY !== undefined) {
|
||||
config.y = scrollY;
|
||||
} else if (isScroll) {
|
||||
config.y = 'calc(100vh - 232px)';
|
||||
config.y = 'calc(100vh - 224px)';
|
||||
}
|
||||
|
||||
return Object.keys(config).length > 0 ? config : undefined;
|
||||
|
||||
@@ -32,7 +32,7 @@ export const lightTheme: ThemeConfig = {
|
||||
bodyBg: '#EEEFF4',
|
||||
siderBg: '#FAFCFF',
|
||||
headerPadding: '0 24px 0 20px',
|
||||
headerHeight: 64,
|
||||
headerHeight: 56,
|
||||
headerColor: '#212332',
|
||||
},
|
||||
Menu: {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:21
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 12:13:33
|
||||
* @Last Modified time: 2026-03-27 13:46:18
|
||||
*/
|
||||
import { useEffect, useRef, useState, forwardRef, useImperativeHandle, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -44,6 +44,14 @@ import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
|
||||
import DescWrapper from '@/components/FormItem/DescWrapper'
|
||||
import FeaturesConfig from './components/FeaturesConfig'
|
||||
import { getListLogoUrl } from '@/views/ModelManagement/utils';
|
||||
import type { ChatItem } from '@/components/Chat/types'
|
||||
|
||||
export const replaceVariables = (statement: string, variables: Variable[]) => {
|
||||
return statement.replace(/\{\{([^}]+)\}\}/g, (match, name) => {
|
||||
const v = variables.find(item => item.name === name)
|
||||
return v?.value != null && v.value !== '' ? String(v.value) : match
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Agent configuration component
|
||||
@@ -148,8 +156,9 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
model_parameters: {...rest}
|
||||
})
|
||||
if (default_model_config_id === values?.default_model_config_id) {
|
||||
const label = defaultModel?.id === default_model_config_id && defaultModel?.name ? defaultModel.name : vo.label || ''
|
||||
setChatList([{
|
||||
label: defaultModel?.id === default_model_config_id && defaultModel?.name ? defaultModel.name : vo.label || '',
|
||||
label: label,
|
||||
model_config_id: default_model_config_id || '',
|
||||
model_parameters: {...rest},
|
||||
list: []
|
||||
@@ -331,28 +340,13 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
const handleOpenVariableConfig = () => {
|
||||
chatVariableConfigModalRef.current?.handleOpen(chatVariables)
|
||||
}
|
||||
|
||||
/**
|
||||
* Save chat variable configuration
|
||||
* @param values - Variable values
|
||||
*/
|
||||
const handleSaveChatVariable = (variables: Variable[]) => {
|
||||
setChatVariables(variables)
|
||||
const opening_statement = form.getFieldValue(['features', 'opening_statement'])
|
||||
|
||||
if (opening_statement?.statement && opening_statement?.statement.trim() !== '') {
|
||||
const statement = opening_statement.statement as string
|
||||
const replacedContent = statement.replace(/\{\{([^}]+)\}\}/g, (match, name) => {
|
||||
const v = variables.find(item => item.name === name)
|
||||
return v?.value != null && v.value !== '' ? String(v.value) : match
|
||||
})
|
||||
setChatList(prev => prev.map(item => {
|
||||
const list = [...(item.list || [])]
|
||||
if (list.length > 0 && list[0].role === 'assistant') {
|
||||
list[0] = { ...list[0], content: replacedContent }
|
||||
}
|
||||
return { ...item, list }
|
||||
}))
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
setChatVariables(values?.variables || [])
|
||||
@@ -360,43 +354,55 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
|
||||
const handleSaveFeaturesConfig = (value: FeaturesConfigForm) => {
|
||||
form.setFieldValue('features', value)
|
||||
|
||||
if (value?.opening_statement?.statement && value?.opening_statement?.statement.trim() !== '') {
|
||||
setChatList(prev => (prev.map(item => {
|
||||
const firstMsg = item.list?.[0]
|
||||
|
||||
if (firstMsg?.role === 'assistant') {
|
||||
firstMsg.meta_data = {
|
||||
suggested_questions: value.opening_statement?.suggested_questions || []
|
||||
}
|
||||
return item
|
||||
} else {
|
||||
return {
|
||||
...item,
|
||||
list: [{
|
||||
role: 'assistant',
|
||||
content: value.opening_statement?.statement,
|
||||
meta_data: {
|
||||
suggested_questions: value.opening_statement?.suggested_questions || []
|
||||
}
|
||||
}, ...(item.list || [])]
|
||||
}
|
||||
}
|
||||
})))
|
||||
}
|
||||
}
|
||||
const modelLogo = useMemo(() => {
|
||||
return defaultModel?.name && getListLogoUrl(defaultModel.provider, defaultModel.logo as string)
|
||||
}, [defaultModel])
|
||||
|
||||
useEffect(() => {
|
||||
const opening_statement = form.getFieldValue(['features', 'opening_statement'])
|
||||
console.log('opening_statement', opening_statement, defaultModel, chatList)
|
||||
|
||||
if (opening_statement?.enabled && opening_statement?.statement && opening_statement?.statement.trim() !== '') {
|
||||
const assistantMsg: ChatItem = {
|
||||
role: 'assistant',
|
||||
content: replaceVariables(opening_statement.statement, chatVariables),
|
||||
meta_data: {
|
||||
suggested_questions: opening_statement?.suggested_questions
|
||||
}
|
||||
}
|
||||
setChatList(prev => {
|
||||
if (prev.length === 0 && !defaultModel) return prev
|
||||
if (defaultModel && prev.length === 1) {
|
||||
return [{
|
||||
label: defaultModel.name,
|
||||
model_config_id: defaultModel.id,
|
||||
model_parameters: defaultModel.config as unknown as ModelConfig,
|
||||
list: [assistantMsg]
|
||||
}]
|
||||
}
|
||||
|
||||
return prev.map(vo => {
|
||||
if (vo.list?.length === 0) {
|
||||
return { ...vo, list: [assistantMsg] }
|
||||
} else if (vo.list && vo.list[0].role === 'assistant') {
|
||||
return { ...vo, list: [assistantMsg, ...vo.list.slice(1)] }
|
||||
} else {
|
||||
return { ...vo, list: [assistantMsg, ...(vo.list || [])] }
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}, [defaultModel, chatList.length, form.getFieldValue(['features', 'opening_statement']), chatVariables])
|
||||
|
||||
console.log('agent values', values)
|
||||
return (
|
||||
<>
|
||||
{loading && <Spin fullscreen></Spin>}
|
||||
<Row className="rb:h-[calc(100vh-88px)]" gutter={12}>
|
||||
<Col span={12} className="rb:h-full rb:overflow-y-auto">
|
||||
<Row className="rb:h-full!" gutter={12}>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<Form form={form}>
|
||||
<Flex gap={16} vertical>
|
||||
<Flex gap={12} vertical>
|
||||
<Flex align="center" justify="space-between" className="rb:p-3! rb:bg-white rb:rounded-xl">
|
||||
<Button type="primary" ghost onClick={handleModelConfig} className="rb:group">
|
||||
{modelLogo
|
||||
@@ -417,89 +423,92 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
</Button>
|
||||
</Space>
|
||||
</Flex>
|
||||
<Form.Item name="default_model_config_id" hidden noStyle></Form.Item>
|
||||
<Form.Item name="capability" hidden noStyle></Form.Item>
|
||||
<Form.Item name="model_parameters" hidden noStyle></Form.Item>
|
||||
<Form.Item name="features" hidden noStyle></Form.Item>
|
||||
<Card
|
||||
title={t('application.promptConfiguration')}
|
||||
extra={
|
||||
<Space
|
||||
size={1}
|
||||
className="rb:px-2 rb:h-5.5 rb:rounded-md rb:cursor-pointer rb:border rb:border-[rgba(21,94,239,0.3)] rb:text-[#155EEF]"
|
||||
onClick={handlePrompt}
|
||||
>
|
||||
<div className="rb:size-5 rb:bg-cover rb:bg-[url('@/assets/images/application/aiPrompt.png')]"></div>
|
||||
<span className="rb:font-[PingFangSC, PingFang_SC]!">{t('application.aiPrompt')}</span>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<div className="rb:leading-4.5 rb:text-[12px] rb:mb-2">
|
||||
<span className="rb:font-medium">{t('application.configuration')}</span>
|
||||
<span className="rb:font-regular rb:text-[#5B6167]"> ({t('application.configurationDesc')})</span>
|
||||
</div>
|
||||
|
||||
<Form.Item name="system_prompt" className="rb:mb-0!">
|
||||
<Input.TextArea
|
||||
placeholder={t('application.promptPlaceholder')}
|
||||
styles={{
|
||||
textarea: {
|
||||
minHeight: '200px',
|
||||
borderRadius: '8px',
|
||||
padding: '12px'
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>
|
||||
<Flex gap={12} vertical className="rb:h-[calc(100vh-156px)]! rb:overflow-y-auto!">
|
||||
<Form.Item name="default_model_config_id" hidden noStyle></Form.Item>
|
||||
<Form.Item name="capability" hidden noStyle></Form.Item>
|
||||
<Form.Item name="model_parameters" hidden noStyle></Form.Item>
|
||||
<Form.Item name="features" hidden noStyle></Form.Item>
|
||||
<Card
|
||||
title={t('application.promptConfiguration')}
|
||||
extra={
|
||||
<Space
|
||||
size={1}
|
||||
className="rb:px-2 rb:h-5.5 rb:rounded-md rb:cursor-pointer rb:border rb:border-[rgba(21,94,239,0.3)] rb:text-[#155EEF]"
|
||||
onClick={handlePrompt}
|
||||
>
|
||||
<div className="rb:size-5 rb:bg-cover rb:bg-[url('@/assets/images/application/aiPrompt.png')]"></div>
|
||||
<span className="rb:font-[PingFangSC, PingFang_SC]!">{t('application.aiPrompt')}</span>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<div className="rb:leading-4.5 rb:text-[12px] rb:mb-2">
|
||||
<span className="rb:font-medium">{t('application.configuration')}</span>
|
||||
<span className="rb:font-regular rb:text-[#5B6167]"> ({t('application.configurationDesc')})</span>
|
||||
</div>
|
||||
|
||||
<Form.Item name="system_prompt" className="rb:mb-0!">
|
||||
<Input.TextArea
|
||||
placeholder={t('application.promptPlaceholder')}
|
||||
styles={{
|
||||
textarea: {
|
||||
minHeight: '200px',
|
||||
borderRadius: '8px',
|
||||
padding: '12px'
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>
|
||||
|
||||
<Form.Item name="knowledge_retrieval" noStyle>
|
||||
<Knowledge />
|
||||
</Form.Item>
|
||||
|
||||
{/* Memory Configuration */}
|
||||
<Card title={t('application.memoryConfiguration')}>
|
||||
<Flex gap={16} vertical className="rb:bg-[#FAFAFA] rb:rounded-xl rb:p-3!">
|
||||
<SwitchFormItem
|
||||
title={t('application.dialogueHistoricalMemory')}
|
||||
name={['memory', 'enabled']}
|
||||
desc={t('application.dialogueHistoricalMemoryDesc')}
|
||||
/>
|
||||
<Form.Item
|
||||
name={['memory', 'memory_config_id']}
|
||||
label={t('application.selectMemoryContent')}
|
||||
extra={<DescWrapper desc={t('application.selectMemoryContentDesc')} className="rb:mt-1" />}
|
||||
layout="vertical"
|
||||
className="rb:mb-0!"
|
||||
>
|
||||
<CustomSelect
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
url={memoryConfigListUrl}
|
||||
hasAll={false}
|
||||
valueKey='config_id'
|
||||
labelKey="config_name"
|
||||
disabled={!values?.memory?.enabled}
|
||||
{/* Memory Configuration */}
|
||||
<Card title={t('application.memoryConfiguration')}>
|
||||
<Flex gap={16} vertical className="rb:bg-[#FAFAFA] rb:rounded-xl rb:p-3!">
|
||||
<SwitchFormItem
|
||||
title={t('application.dialogueHistoricalMemory')}
|
||||
name={['memory', 'enabled']}
|
||||
desc={t('application.dialogueHistoricalMemoryDesc')}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Flex>
|
||||
</Card>
|
||||
<Form.Item
|
||||
name={['memory', 'memory_config_id']}
|
||||
label={t('application.selectMemoryContent')}
|
||||
extra={<DescWrapper desc={t('application.selectMemoryContentDesc')} className="rb:mt-1" />}
|
||||
layout="vertical"
|
||||
className="rb:mb-0!"
|
||||
>
|
||||
<CustomSelect
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
url={memoryConfigListUrl}
|
||||
hasAll={false}
|
||||
valueKey='config_id'
|
||||
labelKey="config_name"
|
||||
disabled={!values?.memory?.enabled}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Flex>
|
||||
</Card>
|
||||
|
||||
<Form.Item name="variables" noStyle>
|
||||
<VariableList />
|
||||
</Form.Item>
|
||||
<Form.Item name="variables" noStyle>
|
||||
<VariableList />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="skills" noStyle>
|
||||
<SkillList />
|
||||
</Form.Item>
|
||||
<Form.Item name="skills" noStyle>
|
||||
<SkillList />
|
||||
</Form.Item>
|
||||
|
||||
{/* Tool Configuration */}
|
||||
<Form.Item name="tools" noStyle>
|
||||
<ToolList />
|
||||
</Form.Item>
|
||||
{/* Tool Configuration */}
|
||||
<Form.Item name="tools" noStyle>
|
||||
<ToolList />
|
||||
</Form.Item>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Form>
|
||||
</Col>
|
||||
<Col span={12} className="rb:h-full rb:overflow-y-hidden">
|
||||
<Col span={12} className="rb:h-full! rb:overflow-y-hidden">
|
||||
<RbCard
|
||||
title={t('application.debuggingAndPreview')}
|
||||
extra={
|
||||
@@ -513,7 +522,7 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
headerType="borderless"
|
||||
headerClassName="rb:h-[56px]! rb:leading-[22px]!"
|
||||
titleClassName="rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-4! rb:pt-0!"
|
||||
bodyClassName="rb:p-4! rb:pt-0! rb:h-[calc(100%-56px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<Chat
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:29
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:18:09
|
||||
* @Last Modified time: 2026-03-26 15:31:36
|
||||
*/
|
||||
import { type FC, useState, useRef, useEffect } from 'react';
|
||||
import clsx from 'clsx';
|
||||
@@ -124,7 +124,7 @@ const Api: FC<{ application: Application | null }> = ({ application }) => {
|
||||
// Calculate total requests across all API keys
|
||||
const totalRequests = apiKeyList.reduce((total, item) => total + item.total_requests, 0);
|
||||
return (
|
||||
<div className="rb:w-250 rb:mx-auto">
|
||||
<div className="rb:w-250 rb:mx-auto rb:max-h-[calc(100vh-88px)]! rb:overflow-y-auto">
|
||||
<Flex gap={20} vertical>
|
||||
<RbCard
|
||||
title={() => (<Flex align="center">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:33
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 15:16:25
|
||||
* @Last Modified time: 2026-03-27 11:51:34
|
||||
*/
|
||||
import { useEffect, useState, useRef, forwardRef, useImperativeHandle } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -197,33 +197,34 @@ const Cluster = forwardRef<ClusterRef, { onFeaturesLoad?: (features: FeaturesCon
|
||||
return (
|
||||
<>
|
||||
{loading && <Spin fullscreen></Spin>}
|
||||
<Row className="rb:h-[calc(100vh-89px)]" gutter={12}>
|
||||
<Col span={12} className="rb:h-full rb:overflow-x-auto rb:border-r rb:border-[#DFE4ED]">
|
||||
<Row className="rb:h-full!" gutter={12}>
|
||||
<Col span={12}>
|
||||
<Form form={form} layout="vertical">
|
||||
<Flex gap={16} vertical>
|
||||
<Flex gap={12} vertical>
|
||||
<Flex align="center" justify="end" className="rb:p-3! rb:bg-white rb:rounded-xl">
|
||||
{/* <FeaturesConfig value={values?.features as FeaturesConfigForm} refresh={handleSaveFeaturesConfig} /> */}
|
||||
<Button type="primary" onClick={() => handleSave()}>
|
||||
{t('common.save')}
|
||||
</Button>
|
||||
</Flex>
|
||||
<Form.Item name="features" hidden noStyle></Form.Item>
|
||||
<Card title={t('application.collaboration')}>
|
||||
<Form.Item
|
||||
name="orchestration_mode"
|
||||
noStyle
|
||||
>
|
||||
<RadioGroupCard
|
||||
options={['supervisor', 'collaboration'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
labelDesc: t(`application.${type}Desc`),
|
||||
}))}
|
||||
allowClear={false}
|
||||
block={true}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>
|
||||
<Flex gap={12} vertical className="rb:h-[calc(100vh-158px)]! rb:overflow-y-auto!">
|
||||
<Form.Item name="features" hidden noStyle></Form.Item>
|
||||
<Card title={t('application.collaboration')}>
|
||||
<Form.Item
|
||||
name="orchestration_mode"
|
||||
noStyle
|
||||
>
|
||||
<RadioGroupCard
|
||||
options={['supervisor', 'collaboration'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
labelDesc: t(`application.${type}Desc`),
|
||||
}))}
|
||||
allowClear={false}
|
||||
block={true}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title={<>
|
||||
@@ -289,45 +290,46 @@ const Cluster = forwardRef<ClusterRef, { onFeaturesLoad?: (features: FeaturesCon
|
||||
>{t('application.modelConfig')}</Button>
|
||||
</Form.Item>
|
||||
</Flex>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={['execution_config', "sub_agent_execution_mode"]}
|
||||
label={<span className="rb:text-[#5B6167]">{t('application.orchestrationMode')}</span>}
|
||||
className="rb:mb-4!"
|
||||
>
|
||||
<Select
|
||||
options={['sequential', 'parallel'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
}))}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="aggregation_strategy"
|
||||
label={<span className="rb:text-[#5B6167]">{t('application.aggregationStrategy')}</span>}
|
||||
className="rb:mb-0!"
|
||||
>
|
||||
<Select
|
||||
options={['merge', 'vote', 'priority'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
}))}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={['execution_config', "sub_agent_execution_mode"]}
|
||||
label={<span className="rb:text-[#5B6167]">{t('application.orchestrationMode')}</span>}
|
||||
className="rb:mb-4!"
|
||||
>
|
||||
<Select
|
||||
options={['sequential', 'parallel'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
}))}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="aggregation_strategy"
|
||||
label={<span className="rb:text-[#5B6167]">{t('application.aggregationStrategy')}</span>}
|
||||
className="rb:mb-0!"
|
||||
>
|
||||
<Select
|
||||
options={['merge', 'vote', 'priority'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
}))}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>}
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Form>
|
||||
</Col>
|
||||
<Col span={12} className="rb:h-full rb:overflow-y-hidden">
|
||||
<Col span={12} className="rb:h-full! rb:overflow-y-hidden">
|
||||
<RbCard
|
||||
title={t('application.debuggingAndPreview')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:h-[56px]! rb:leading-[22px]!"
|
||||
titleClassName="rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-4! rb:pt-0!"
|
||||
className="rb:h-full"
|
||||
bodyClassName="rb:p-4! rb:pt-0! rb:h-[calc(100%-56px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<Chat
|
||||
data={data as Config}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:41
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 16:43:10
|
||||
* @Last Modified time: 2026-03-26 15:24:41
|
||||
*/
|
||||
import { type FC, useState, useEffect, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -30,7 +30,7 @@ const tagColors: Record<Release['tagKey'], TagProps['color']> = {
|
||||
history: 'default',
|
||||
}
|
||||
|
||||
const heightClass = 'rb:h-[calc(100vh-88px)]'
|
||||
const heightClass = 'rb:max-h-[calc(100vh-140px)]'
|
||||
/**
|
||||
* Release page component
|
||||
* Manages application version releases, rollbacks, and version history
|
||||
@@ -77,51 +77,55 @@ const ReleasePage: FC<{data: Application; refresh: () => void}> = ({data, refres
|
||||
}
|
||||
return (
|
||||
<Flex gap={12}>
|
||||
<div className={`rb:overflow-y-auto rb:w-101 rb:flex-[0_0_auto] ${heightClass}`}>
|
||||
<div className="rb:w-101 rb:h-full">
|
||||
<Flex gap={12} vertical>
|
||||
<div className="rb:px-1">
|
||||
<div className="rb:text-[16px] rb:leading-5.5 rb:font-medium">{t('application.versionList')}</div>
|
||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">{t('application.versionListDesc')}</div>
|
||||
</div>
|
||||
{releaseList.length === 0
|
||||
? <Empty />
|
||||
: selectedVersion && releaseList.map((version, index) => {
|
||||
const tagKey = version.id === data.current_release_id && index === 0
|
||||
? 'current'
|
||||
: version.id === data.current_release_id
|
||||
? 'rolledBack' : 'history'
|
||||
return (
|
||||
<RbCard
|
||||
key={version.version}
|
||||
title={<>
|
||||
{version.version_name && version.version_name[0].toLocaleLowerCase() === 'v' ? version.version_name : version.version_name ? `v${version.version_name}` : `v${version.version}`}
|
||||
{tagKey && <Tag color={tagColors[tagKey]} className="rb:ml-2">
|
||||
{tagKey}
|
||||
</Tag>}
|
||||
</>}
|
||||
className={clsx("rb:hover:shadow-[0px_2px_8px_0px_rgba(0,0,0,0.2)]! rb:cursor-pointer rb:bg-white", {
|
||||
'rb:border-[#171719]!': version.id === selectedVersion.id,
|
||||
'rb:border-[#DFE4ED] ': version.id !== selectedVersion.id
|
||||
})}
|
||||
headerType="borderless"
|
||||
onClick={() => setSelectedVersion(version)}
|
||||
>
|
||||
<div className="rb:leading-5 rb:line-clamp-2 rb:overflow-hidden rb:text-ellipsis rb:whitespace-nowrap">
|
||||
<Markdown content={version.release_notes} />
|
||||
</div>
|
||||
<div className="rb:mt-4 rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">
|
||||
{t('application.publishedOn')} {formatDateTime(version.published_at, 'YYYY-MM-DD HH:mm:ss')}
|
||||
</div>
|
||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">
|
||||
{t('application.publisher')}: {version.publisher_name}
|
||||
</div>
|
||||
</RbCard>
|
||||
)
|
||||
})
|
||||
}
|
||||
<div className={`${heightClass} rb:overflow-y-auto`}>
|
||||
{releaseList.length === 0
|
||||
? <Empty />
|
||||
: <Flex gap={12} vertical>
|
||||
{selectedVersion && releaseList.map((version, index) => {
|
||||
const tagKey = version.id === data.current_release_id && index === 0
|
||||
? 'current'
|
||||
: version.id === data.current_release_id
|
||||
? 'rolledBack' : 'history'
|
||||
return (
|
||||
<RbCard
|
||||
key={version.version}
|
||||
title={<>
|
||||
{version.version_name && version.version_name[0].toLocaleLowerCase() === 'v' ? version.version_name : version.version_name ? `v${version.version_name}` : `v${version.version}`}
|
||||
{tagKey && <Tag color={tagColors[tagKey]} className="rb:ml-2">
|
||||
{tagKey}
|
||||
</Tag>}
|
||||
</>}
|
||||
className={clsx("rb:hover:shadow-[0px_2px_8px_0px_rgba(0,0,0,0.2)]! rb:cursor-pointer rb:bg-white", {
|
||||
'rb:border-[#171719]!': version.id === selectedVersion.id,
|
||||
'rb:border-[#DFE4ED] ': version.id !== selectedVersion.id
|
||||
})}
|
||||
headerType="borderless"
|
||||
onClick={() => setSelectedVersion(version)}
|
||||
>
|
||||
<div className="rb:leading-5 rb:line-clamp-2 rb:overflow-hidden rb:text-ellipsis rb:whitespace-nowrap">
|
||||
<Markdown content={version.release_notes} />
|
||||
</div>
|
||||
<div className="rb:mt-4 rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">
|
||||
{t('application.publishedOn')} {formatDateTime(version.published_at, 'YYYY-MM-DD HH:mm:ss')}
|
||||
</div>
|
||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">
|
||||
{t('application.publisher')}: {version.publisher_name}
|
||||
</div>
|
||||
</RbCard>
|
||||
)
|
||||
})}
|
||||
</Flex>
|
||||
}
|
||||
</div>
|
||||
</Flex>
|
||||
</div>
|
||||
<div className={`rb:overflow-y-auto rb:flex-[1_1_auto] ${heightClass}`}>
|
||||
<div className="rb:overflow-y-auto rb:flex-1">
|
||||
<Form layout="vertical">
|
||||
<Flex align="center" className={clsx("rb:leading-6.5! rb:text-[18px] rb:font-medium rb:mb-4.75!", {
|
||||
'rb:justify-between': selectedVersion,
|
||||
@@ -140,7 +144,7 @@ const ReleasePage: FC<{data: Application; refresh: () => void}> = ({data, refres
|
||||
</Space>
|
||||
</Flex>
|
||||
{selectedVersion &&
|
||||
<Flex gap={16} vertical>
|
||||
<Flex gap={16} vertical className={`${heightClass} rb:overflow-y-auto`}>
|
||||
<RbCard
|
||||
title={t('application.VersionInformation')}
|
||||
headerType="borderless"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-13 17:27:52
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 13:43:02
|
||||
* @Last Modified time: 2026-03-26 15:35:13
|
||||
*/
|
||||
import { type FC, useState, useRef, useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -531,11 +531,11 @@ const TestChat: FC<TestChatProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rb:w-250 rb:p-3 rb:mx-auto">
|
||||
<div className="rb:w-250 rb:mx-auto rb:h-full">
|
||||
<RbCard
|
||||
title={t('application.test')}
|
||||
headerClassName="rb:min-h-[56px]!"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
bodyClassName="rb:h-[calc(100%-56px)]! rb:overflow-y-auto rb:px-3! rb:py-0!"
|
||||
>
|
||||
<Chat
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:27:56
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 14:03:01
|
||||
* @Last Modified time: 2026-03-27 14:24:47
|
||||
*/
|
||||
/**
|
||||
* Copy Application Modal
|
||||
@@ -74,16 +74,16 @@ const FeaturesConfigModal = forwardRef<FeaturesConfigModalRef, FeaturesConfigMod
|
||||
}
|
||||
|
||||
const formatFileTypeOptions = (fu: FeaturesConfigForm['file_upload']) => {
|
||||
let options = [{ 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.includes('vision')) {
|
||||
if ((capability.includes('vision') || source === 'workflow') && fu.image_enabled) {
|
||||
options.push({ type: 'image', enabled: fu.image_enabled, maxSize: fu.image_max_size_mb })
|
||||
}
|
||||
if (capability.includes('audio')) {
|
||||
if ((capability.includes('audio') || source === 'workflow') && fu.audio_enabled) {
|
||||
options.push({ type: 'audio', enabled: fu.audio_enabled, maxSize: fu.audio_max_size_mb })
|
||||
}
|
||||
if (capability.includes('video')) {
|
||||
if ((capability.includes('video') || source === 'workflow') && fu.video_enabled) {
|
||||
options.push({ type: 'video', enabled: fu.video_enabled, maxSize: fu.video_max_size_mb })
|
||||
}
|
||||
return options.filter(item => item.enabled)
|
||||
@@ -201,6 +201,7 @@ const FeaturesConfigModal = forwardRef<FeaturesConfigModalRef, FeaturesConfigMod
|
||||
ref={fileUploadSettingModalRef}
|
||||
onSave={handleSaveSettings}
|
||||
capability={capability}
|
||||
source={source}
|
||||
/>
|
||||
<OpenStatementSettingModal
|
||||
ref={openStatementSettingModalRef}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-05
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 11:00:14
|
||||
* @Last Modified time: 2026-03-27 14:02:40
|
||||
*/
|
||||
import { forwardRef, useImperativeHandle, useState, useMemo } from 'react';
|
||||
import { Form, InputNumber, Flex, Switch, Row, Col, Radio } from 'antd';
|
||||
@@ -12,6 +12,7 @@ import clsx from 'clsx';
|
||||
import RbModal from '@/components/RbModal';
|
||||
import type { FeaturesConfigForm } from '../../types'
|
||||
import type { Capability } from '@/views/ModelManagement/types'
|
||||
import type { Application } from '@/views/ApplicationManagement/types';
|
||||
|
||||
type FileUpload = Omit<FeaturesConfigForm['file_upload'], 'settings'>
|
||||
|
||||
@@ -23,6 +24,7 @@ interface FileUploadSettingModalRef {
|
||||
interface FileUploadSettingModalProps {
|
||||
onSave: (values: FileUpload) => void;
|
||||
capability?: Capability[];
|
||||
source?: Application['type']
|
||||
}
|
||||
const documentType = {
|
||||
type: 'document',
|
||||
@@ -108,6 +110,7 @@ const defaultValues: FileUpload = {
|
||||
const FileUploadSettingModal = forwardRef<FileUploadSettingModalRef, FileUploadSettingModalProps>(({
|
||||
onSave,
|
||||
capability,
|
||||
source,
|
||||
}, ref) => {
|
||||
const { t } = useTranslation();
|
||||
const [visible, setVisible] = useState(false);
|
||||
@@ -149,6 +152,14 @@ const FileUploadSettingModal = forwardRef<FileUploadSettingModalRef, FileUploadS
|
||||
}));
|
||||
|
||||
const fileTypeOptions = useMemo(() => {
|
||||
if (source === 'workflow') {
|
||||
return [
|
||||
documentType,
|
||||
imageType,
|
||||
audioType,
|
||||
videoType,
|
||||
]
|
||||
}
|
||||
let options = [documentType]
|
||||
if (!capability) return options
|
||||
if (capability.includes('vision')) options = [...options, imageType]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-05
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 14:12:11
|
||||
* @Last Modified time: 2026-03-27 14:38:28
|
||||
*/
|
||||
import { forwardRef, useImperativeHandle, useState } from 'react';
|
||||
import { Button, Form, Input, Flex, App } from 'antd';
|
||||
@@ -44,12 +44,13 @@ const OpenStatementSettingModal = forwardRef<OpenStatementSettingModalRef, OpenS
|
||||
|
||||
const handleSave = async () => {
|
||||
form.validateFields().then(values => {
|
||||
const { suggested_questions, ...rest } = values
|
||||
const filterSuggestedQuestions = suggested_questions.filter(vo => vo && vo.trim() !== '' && vo !== null)
|
||||
if (values?.enabled && values?.statement && values?.statement?.trim() !== '') {
|
||||
const usedVars = [...new Set([...values.statement?.matchAll(/\{\{(\w+)\}\}/g)].map(m => m[1]))]
|
||||
|
||||
const validNames = new Set(chatVariables.map(v => v.name))
|
||||
const invalid = usedVars.filter(v => !validNames.has(v))
|
||||
console.log('invalid', invalid)
|
||||
if (invalid.length > 0) {
|
||||
modal.confirm({
|
||||
title: t('application.invalidVariablesTitle'),
|
||||
@@ -57,14 +58,26 @@ const OpenStatementSettingModal = forwardRef<OpenStatementSettingModalRef, OpenS
|
||||
okText: t('common.confirm'),
|
||||
cancelText: t('common.cancel'),
|
||||
onOk: () => {
|
||||
onSave(values);
|
||||
onSave({
|
||||
...rest,
|
||||
suggested_questions: filterSuggestedQuestions
|
||||
});
|
||||
handleClose();
|
||||
},
|
||||
})
|
||||
} else {
|
||||
onSave(values);
|
||||
onSave({
|
||||
...rest,
|
||||
suggested_questions: filterSuggestedQuestions
|
||||
});
|
||||
handleClose();
|
||||
}
|
||||
} else {
|
||||
onSave({
|
||||
...rest,
|
||||
suggested_questions: filterSuggestedQuestions
|
||||
});
|
||||
handleClose();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -139,6 +139,7 @@ const ModelConfigModal = forwardRef<ModelConfigModalRef, ModelConfigModalProps>(
|
||||
>
|
||||
{source !== 'multi_agent' &&
|
||||
<ModelSelect
|
||||
params={{type: 'llm,chat'}}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:37
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 15:59:47
|
||||
* @Last Modified time: 2026-03-26 15:37:18
|
||||
*/
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Flex } from 'antd'
|
||||
|
||||
import ConfigHeader from './components/ConfigHeader'
|
||||
import type { AgentRef, ClusterRef, WorkflowRef, Config } from './types'
|
||||
@@ -108,7 +109,7 @@ const ApplicationConfig: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex vertical className="rb:h-screen!">
|
||||
<ConfigHeader
|
||||
activeTab={activeTab}
|
||||
handleChangeTab={handleChangeTab}
|
||||
@@ -119,7 +120,7 @@ const ApplicationConfig: React.FC = () => {
|
||||
features={features}
|
||||
onFeaturesChange={setFeatures}
|
||||
/>
|
||||
<div className="rb:p-3 rb:max-h-[calc(100vh-65px)] rb:overflow-auto">
|
||||
<div className="rb:p-3 rb:flex-1 rb:overflow-auto">
|
||||
{activeTab === 'arrangement' && application?.type === 'agent' && <Agent ref={agentRef} onFeaturesLoad={setFeatures} />}
|
||||
{activeTab === 'arrangement' && application?.type === 'multi_agent' && <Cluster ref={clusterRef} onFeaturesLoad={setFeatures} />}
|
||||
{activeTab === 'arrangement' && application?.type === 'workflow' && <Workflow ref={workflowRef} onFeaturesLoad={setFeatures} />}
|
||||
@@ -129,7 +130,7 @@ const ApplicationConfig: React.FC = () => {
|
||||
{activeTab === 'test' && <TestChat application={application} config={config} />}
|
||||
{activeTab === 'log' && <Logs />}
|
||||
</div>
|
||||
</>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:34:12
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:37:51
|
||||
* @Last Modified time: 2026-03-26 14:39:18
|
||||
*/
|
||||
import React, { useState, useEffect, useMemo, type MouseEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -81,7 +81,7 @@ const MySharing: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex vertical gap={12} className="rb:h-[calc(100vh-148px)]! rb:overflow-y-auto!">
|
||||
<Flex vertical gap={12} className="rb:max-h-[calc(100%-48px)]! rb:overflow-y-auto!">
|
||||
<BodyWrapper loading={false} empty={data.length === 0}>
|
||||
{grouped.map(({ workspace, items }) => (
|
||||
<Collapse
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:58:03
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 13:35:42
|
||||
* @Last Modified time: 2026-03-27 14:28:19
|
||||
*/
|
||||
/**
|
||||
* Conversation Page
|
||||
@@ -30,8 +30,10 @@ import { type SSEMessage } from '@/utils/stream'
|
||||
import { shareFileUploadUrlWithoutApiPrefix } from '@/api/fileStorage'
|
||||
import ChatToolbar, { type ChatToolbarRef } from '@/components/Chat/ChatToolbar'
|
||||
import type { Variable } from '@/views/Workflow/components/Properties/VariableList/types'
|
||||
import type { Variable as AppVariable } from '@/views/ApplicationConfig/components/VariableList/types'
|
||||
import type { FeaturesConfigForm } from '@/views/ApplicationConfig/types';
|
||||
import { getFileStatusById } from '@/api/fileStorage';
|
||||
import { replaceVariables } from '@/views/ApplicationConfig/Agent'
|
||||
|
||||
const Conversation: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
@@ -84,11 +86,11 @@ const Conversation: FC = () => {
|
||||
if (shareToken && token) {
|
||||
getExperienceConfig(token)
|
||||
.then(res => {
|
||||
const response = res as { variables: Variable[]; features: FeaturesConfigForm; app_type: string; memory?: boolean; }
|
||||
const response = res as { variables: Variable[]; features: FeaturesConfigForm; app_type: string; memory: boolean; }
|
||||
toolbarRef.current?.setVariables(response.variables || [])
|
||||
setConfig(response)
|
||||
setFeatures(response.features)
|
||||
setIsHasMemory((response.app_type === 'workflow' && response.memory) || (response.app_type !== 'workflow'))
|
||||
setIsHasMemory((response.app_type === 'workflow' && response.memory) || response.memory)
|
||||
})
|
||||
} else {
|
||||
setChatList([])
|
||||
@@ -375,6 +377,17 @@ const Conversation: FC = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleChangeVariables = (variables: Variable[]) => {
|
||||
setChatList(prev => {
|
||||
const firstMsg = prev[0]
|
||||
console.log('firstMsg', firstMsg)
|
||||
if (firstMsg && firstMsg.role === 'assistant' && firstMsg.content && features?.opening_statement.enabled && features?.opening_statement.statement && variables.length > 0) {
|
||||
firstMsg.content = replaceVariables(features?.opening_statement.statement, variables as unknown as AppVariable[])
|
||||
}
|
||||
return [firstMsg, ...prev.slice(1)]
|
||||
})
|
||||
}
|
||||
|
||||
console.log('chatList', chatList)
|
||||
|
||||
return (
|
||||
@@ -460,7 +473,8 @@ const Conversation: FC = () => {
|
||||
}
|
||||
}}
|
||||
rightExtra={
|
||||
<Flex align="center" justify="end" gap={8}>
|
||||
(features?.web_search?.enabled || isHasMemory)
|
||||
? <Flex align="center" justify="end" gap={8}>
|
||||
{features?.web_search?.enabled &&
|
||||
<Tooltip title={t('memoryConversation.web_search')}>
|
||||
<Flex justify="center" align="center"
|
||||
@@ -496,7 +510,9 @@ const Conversation: FC = () => {
|
||||
</Tooltip>
|
||||
}
|
||||
</Flex>
|
||||
: undefined
|
||||
}
|
||||
onVariablesChange={handleChangeVariables}
|
||||
/>
|
||||
</Chat>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:56:54
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 18:28:18
|
||||
* @Last Modified time: 2026-03-26 15:43:29
|
||||
*/
|
||||
/**
|
||||
* Emotion Engine Configuration Page
|
||||
@@ -118,8 +118,8 @@ const EmotionEngine: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={12}>
|
||||
<Row gutter={[16, 16]} className="rb:h-full!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('emotionEngine.emotionEngineConfig')}
|
||||
headerType="borderless"
|
||||
@@ -128,7 +128,7 @@ const EmotionEngine: React.FC = () => {
|
||||
<Button block onClick={handleReset}>{t('common.reset')}</Button>
|
||||
<Button type="primary" loading={loading} block onClick={handleSave}>{t('common.save')}</Button>
|
||||
</Space>}
|
||||
className="rb:h-[calc(100vh-76px)]!"
|
||||
className="rb:h-full!"
|
||||
bodyClassName="rb:h-[calc(100%-54px)] rb:overflow-y-auto! rb:p-3! rb:pt-0!"
|
||||
>
|
||||
<Form
|
||||
@@ -207,12 +207,12 @@ const EmotionEngine: React.FC = () => {
|
||||
</Form>
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('emotionEngine.emotionEngineConfig')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
className="rb:h-[calc(100vh-76px)]!"
|
||||
className="rb:h-full!"
|
||||
bodyClassName="rb:h-[calc(100%-54px)] rb:overflow-y-auto! rb:p-3! rb:pt-0!"
|
||||
>
|
||||
<Flex vertical gap={24} className="rb:text-[#212332]">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:00:12
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 18:29:00
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 15:47:37
|
||||
*/
|
||||
/**
|
||||
* Forgetting Engine Configuration Page
|
||||
@@ -155,8 +155,8 @@ const ForgettingEngine: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Row gutter={12}>
|
||||
<Col span={12}>
|
||||
<Row gutter={12} className="rb:h-full!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('forgettingEngine.forgettingEngineConfigParams')}
|
||||
extra={<Space>
|
||||
@@ -165,7 +165,7 @@ const ForgettingEngine: React.FC = () => {
|
||||
</Space>}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
className="rb:h-[calc(100vh-76px)]!"
|
||||
className="rb:h-full!"
|
||||
bodyClassName="rb:h-[calc(100%-54px)] rb:overflow-y-auto! rb:p-3! rb:pt-0!"
|
||||
>
|
||||
<Form
|
||||
@@ -226,7 +226,7 @@ const ForgettingEngine: React.FC = () => {
|
||||
</Form>
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('forgettingEngine.forgettingCurve')}
|
||||
headerType="borderless"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:16:45
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-10 11:57:35
|
||||
* @Last Modified time: 2026-03-26 14:30:27
|
||||
*/
|
||||
/**
|
||||
* Pie Chart Card Component
|
||||
@@ -33,7 +33,7 @@ const PieCard: FC<PieCardProps> = ({ chartData, loading }) => {
|
||||
>
|
||||
{loading
|
||||
? <Loading size={249} />
|
||||
: <PieChart chartData={chartData} />
|
||||
: <PieChart chartData={chartData} itemGap={24} />
|
||||
}
|
||||
</Card>
|
||||
)
|
||||
|
||||
@@ -75,7 +75,7 @@ const GuideCard: React.FC = () => {
|
||||
<div className="rb:mt-2 rb:pl-3 rb:pr-4">
|
||||
<Button ref={startButtonRef} block className='rb:gap-1 rb:flex rb:items-center' onClick={handleStartGuide}>
|
||||
<span className='rb:text-xs'>{t('index.viewGuide')}</span>
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/common/arrow_right_dark.svg')]"></div>
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/arrow_right_dark.svg')]"></div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @LastEditTime: 2025-12-19 20:19:59
|
||||
*/
|
||||
import { useEffect, useState, useRef, type FC } from 'react';
|
||||
import { useNavigate, useParams, useLocation } from 'react-router-dom';
|
||||
import { useNavigate, useParams, useLocation, useSearchParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useBreadcrumbManager, type BreadcrumbPath } from '@/hooks/useBreadcrumbManager';
|
||||
import { Button, Spin, message, Switch } from 'antd';
|
||||
@@ -29,11 +29,16 @@ const DocumentDetails: FC = () => {
|
||||
const { updateBreadcrumbs } = useBreadcrumbManager({
|
||||
breadcrumbType: 'detail'
|
||||
});
|
||||
const [searchParams] = useSearchParams();
|
||||
const {
|
||||
documentId,
|
||||
parentId: locationParentId,
|
||||
breadcrumbPath
|
||||
} = (location.state || {}) as {
|
||||
} = ({
|
||||
documentId: searchParams.get('documentId') ?? undefined,
|
||||
parentId: searchParams.get('parentId') ?? undefined,
|
||||
...(location.state || {})
|
||||
}) as {
|
||||
documentId?: string;
|
||||
parentId?: string;
|
||||
breadcrumbPath?: BreadcrumbPath;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:42:12
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 16:25:23
|
||||
* @Last Modified time: 2026-03-26 15:48:43
|
||||
*/
|
||||
/**
|
||||
* Member Management Page
|
||||
@@ -105,7 +105,7 @@ const MemberManagement: React.FC = () => {
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="rb:h-[calc(100vh-80px)] rb:overflow-hidden rb:bg-white rb:rounded-lg rb:pt-3 rb:px-3">
|
||||
<div className="rb:h-full rb:overflow-hidden rb:bg-white rb:rounded-lg rb:pt-3 rb:px-3">
|
||||
<Flex justify="end" className="rb:px-1! rb:mb-3!">
|
||||
<Button type="primary" onClick={() => handleEdit()}>
|
||||
{t('member.createMember')}
|
||||
@@ -117,6 +117,7 @@ const MemberManagement: React.FC = () => {
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
scrollY="calc(100vh - 248px)"
|
||||
/>
|
||||
|
||||
<MemberModal
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/**
|
||||
* Card Component
|
||||
* Styled wrapper for conversation and analysis panels
|
||||
* Provides consistent layout and styling
|
||||
*/
|
||||
|
||||
import { Card } from 'antd'
|
||||
import { type FC, type ReactNode } from 'react'
|
||||
|
||||
/**
|
||||
* Component props
|
||||
*/
|
||||
interface RbCardProps {
|
||||
children: ReactNode;
|
||||
title: string;
|
||||
bodyClassName?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
const RbCard: FC<RbCardProps> = ({ children, title, bodyClassName, style, ...props }) => {
|
||||
return (
|
||||
<Card
|
||||
title={title}
|
||||
classNames={{
|
||||
header: "rb:min-h-[40px]! rb:p-[0_16px]! rb:rounded-[12px_12px_0_0]! rb:text-[14px]! rb:leading-[20px]! rb:font-medium! rb:border-b-[#DFE4ED]",
|
||||
body: `rb:h-[calc(100%-40px)] rb:p-[16px]! ${bodyClassName || ''}`,
|
||||
}}
|
||||
style={{
|
||||
borderRadius: '12px',
|
||||
borderColor: '#DFE4ED',
|
||||
background: '#FBFDFF',
|
||||
height: 'calc(100vh - 152px)',
|
||||
...style
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
export default RbCard
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:09:03
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 10:22:08
|
||||
* @Last Modified time: 2026-03-26 15:00:15
|
||||
*/
|
||||
/**
|
||||
* Memory Conversation Page
|
||||
@@ -174,14 +174,14 @@ const MemoryConversation: FC = () => {
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={16}>
|
||||
<Row gutter={16} className="rb:h-[calc(100%-48px)]!">
|
||||
<Col span={12}>
|
||||
<RbCard
|
||||
title={t('memoryConversation.conversationContent')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[52px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:px-3! rb:py-0! rb:h-[calc(100%-52px)]!"
|
||||
className="rb:h-[calc(100vh-124px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<Chat
|
||||
empty={
|
||||
@@ -213,7 +213,7 @@ const MemoryConversation: FC = () => {
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[52px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-52px)]! rb:overflow-y-auto!"
|
||||
className="rb:h-[calc(100vh-124px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
{loading ?
|
||||
<Skeleton active />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:30:11
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:40:38
|
||||
* @Last Modified time: 2026-03-26 15:46:30
|
||||
*/
|
||||
/**
|
||||
* Result Component
|
||||
@@ -267,7 +267,7 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
||||
title={t('memoryExtractionEngine.exampleMemoryExtractionResults')}
|
||||
subTitle={t('memoryExtractionEngine.exampleMemoryExtractionResultsSubTitle')}
|
||||
headerClassName="rb:pb-0! rb:pt-4!"
|
||||
bodyClassName="rb:h-[calc(100vh-163px)]! rb:overflow-y-auto rb:p-[16px_20px]!"
|
||||
bodyClassName="rb:h-[calc(100%-50px)]! rb:overflow-y-auto rb:p-[16px_20px]!"
|
||||
extra={<Space size={8}>
|
||||
<Button
|
||||
icon={<div className="rb:size-3.5 rb:bg-cover rb:bg-[url('@/assets/images/common/save.svg')]"></div>}
|
||||
@@ -281,6 +281,7 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
||||
onClick={handleRun}
|
||||
>{t('memoryExtractionEngine.debug')}</Button>
|
||||
</Space>}
|
||||
className="rb:h-full!"
|
||||
>
|
||||
{/* <RbAlert color="orange" icon={<ExclamationCircleFilled />} className="rb:mb-3!">
|
||||
{t('memoryExtractionEngine.warning')}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:30:02
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 14:07:35
|
||||
* @Last Modified time: 2026-03-26 15:45:42
|
||||
*/
|
||||
/**
|
||||
* Memory Extraction Engine Configuration Page
|
||||
@@ -123,10 +123,10 @@ const MemoryExtractionEngine: FC = () => {
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
|
||||
<Row gutter={12}>
|
||||
<Col span={12}>
|
||||
<Form form={form}>
|
||||
<Flex vertical gap={12} className="rb:h-[calc(100vh-114px)]! rb:overflow-y-auto">
|
||||
<Row gutter={12} className="rb:h-[calc(100%-38px)]!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<Form form={form} className="rb:h-full!">
|
||||
<Flex vertical gap={12} className="rb:h-full! rb:overflow-y-auto">
|
||||
<div className="rb:bg-white rb:rounded-xl rb:py-2.5 rb:px-4">
|
||||
<Flex
|
||||
align="center"
|
||||
@@ -259,7 +259,7 @@ const MemoryExtractionEngine: FC = () => {
|
||||
</Flex>
|
||||
</Form>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<Result
|
||||
loading={loading}
|
||||
handleSave={handleSave}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:33:15
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-12 15:44:32
|
||||
* @Last Modified time: 2026-03-26 14:56:00
|
||||
*/
|
||||
/**
|
||||
* Memory Management Page
|
||||
@@ -100,7 +100,10 @@ const MemoryManagement: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<BodyWrapper loading={loading} empty={data.length === 0}>
|
||||
<Row gutter={[12, 12]}>
|
||||
<Row
|
||||
gutter={[12, 12]}
|
||||
className="rb:max-h-[calc(100%-48px)] rb:overflow-y-auto"
|
||||
>
|
||||
{data.map((item) => (
|
||||
<Col key={item.config_id} span={12}>
|
||||
<RbCard
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:50:05
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 12:28:07
|
||||
* @Last Modified time: 2026-03-26 15:51:08
|
||||
*/
|
||||
/**
|
||||
* Model Management Main Page
|
||||
@@ -84,8 +84,8 @@ const tabKeys = ['group', 'list', 'square']
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex vertical gap={16}>
|
||||
<Flex justify="space-between" align="center">
|
||||
<>
|
||||
<Flex justify="space-between" align="center" className="rb:mb-3!">
|
||||
<PageTabs
|
||||
value={activeTab}
|
||||
options={formatTabItems()}
|
||||
@@ -132,7 +132,7 @@ const tabKeys = ['group', 'list', 'square']
|
||||
</Form>
|
||||
</Flex>
|
||||
|
||||
<div className="rb:w-full rb:h-[calc(100vh-125px)] rb:overflow-y-auto">
|
||||
<div className="rb:w-full rb:h-[calc(100%-44px)] rb:overflow-y-auto">
|
||||
{activeTab === 'group' && <GroupModel ref={groupRef} query={query} handleEdit={handleEdit} />}
|
||||
{activeTab === 'list' && <ModelList ref={modelListRef} query={query} handleEdit={handleEdit} handleCloseModel={() => customModelModalRef.current?.handleClose() } />}
|
||||
{activeTab === 'square' && <ModelSquare query={query} />}
|
||||
@@ -145,7 +145,7 @@ const tabKeys = ['group', 'list', 'square']
|
||||
ref={customModelModalRef}
|
||||
refresh={handleRefresh}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:50:22
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 14:03:13
|
||||
* @Last Modified time: 2026-03-25 18:35:13
|
||||
*/
|
||||
/**
|
||||
* Utility functions for Model Management
|
||||
*/
|
||||
|
||||
import bedrockIcon from '@/assets/images/model/bedrock.svg'
|
||||
import bedrockIcon from '@/assets/images/model/bedrock.png'
|
||||
import dashscopeIcon from '@/assets/images/model/dashscope.png'
|
||||
import gpustackIcon from '@/assets/images/model/gpustack.png'
|
||||
import ollamaIcon from '@/assets/images/model/ollama.svg'
|
||||
import openaiIcon from '@/assets/images/model/openai.svg'
|
||||
import ollamaIcon from '@/assets/images/model/ollama.png'
|
||||
import openaiIcon from '@/assets/images/model/openai.png'
|
||||
import xinferenceIcon from '@/assets/images/model/xinference.svg'
|
||||
import volcanoIcon from '@/assets/images/model/volcano.png'
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 14:10:20
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 12:16:23
|
||||
* @Last Modified time: 2026-03-26 18:55:37
|
||||
*/
|
||||
import { type FC, useEffect, useState, useRef } from 'react'
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
@@ -100,58 +100,60 @@ const Detail: FC = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader
|
||||
title={<Space>
|
||||
{data.scene_name}
|
||||
{data.is_system_default ? <Tag color="warning">{t('common.default')}</Tag> : undefined}
|
||||
<Tooltip title={data.scene_description}>
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/question.svg')]"></div>
|
||||
</Tooltip>
|
||||
</Space>}
|
||||
extra={<Space size={12}>
|
||||
{data.is_system_default ? undefined : (<Space>
|
||||
<Button type="primary" ghost className="rb:h-6! rb:px-2! rb:leading-5.5!" onClick={handleAdd}>+ {t('ontology.addClass')}</Button>
|
||||
<Button className="rb:h-6! rb:px-2! rb:leading-5.5!" type="primary" onClick={handleExtract}>+ {t('ontology.extract')}</Button>
|
||||
</Space>)}
|
||||
<Flex align="center" className="rb:leading-5 rb:text-[14px] rb:text-[#5B6167] rb:font-regular rb:cursor-pointer" onClick={() => navigate(-1)}>
|
||||
<div
|
||||
className="rb:mr-2 rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/logout.svg')]"
|
||||
></div>
|
||||
{t('common.return')}
|
||||
</Flex>
|
||||
</Space>}
|
||||
/>
|
||||
<Flex vertical className="rb:h-screen!">
|
||||
<PageHeader
|
||||
title={<Space>
|
||||
{data.scene_name}
|
||||
{data.is_system_default ? <Tag color="warning">{t('common.default')}</Tag> : undefined}
|
||||
<Tooltip title={data.scene_description}>
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/question.svg')]"></div>
|
||||
</Tooltip>
|
||||
</Space>}
|
||||
extra={<Space size={12}>
|
||||
{data.is_system_default ? undefined : (<Space>
|
||||
<Button type="primary" ghost className="rb:h-6! rb:px-2! rb:leading-5.5!" onClick={handleAdd}>+ {t('ontology.addClass')}</Button>
|
||||
<Button className="rb:h-6! rb:px-2! rb:leading-5.5!" type="primary" onClick={handleExtract}>+ {t('ontology.extract')}</Button>
|
||||
</Space>)}
|
||||
<Flex align="center" className="rb:leading-5 rb:text-[14px] rb:text-[#5B6167] rb:font-regular rb:cursor-pointer" onClick={() => navigate(-1)}>
|
||||
<div
|
||||
className="rb:mr-2 rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/logout.svg')]"
|
||||
></div>
|
||||
{t('common.return')}
|
||||
</Flex>
|
||||
</Space>}
|
||||
/>
|
||||
|
||||
<div className="rb:h-[calc(100vh-64px)] rb:overflow-y-auto rb:p-3">
|
||||
<Row gutter={12} className="rb:mb-4">
|
||||
<Col span={6} offset={18}>
|
||||
<SearchInput
|
||||
placeholder={t('ontology.classSearchPlaceholder')}
|
||||
onSearch={(value) => setQuery({ class_name: value })}
|
||||
className="rb:w-full!"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<BodyWrapper loading={loading} empty={!data.items?.length}>
|
||||
<Row gutter={[16, 16]}>
|
||||
{data.items?.map(item => (
|
||||
<Col key={item.class_id} span={6}>
|
||||
<RbCard
|
||||
title={item.class_name}
|
||||
extra={data.is_system_default ? undefined : (<div
|
||||
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/common/delete.svg')] rb:hover:bg-[url('@/assets/images/common/delete_hover.svg')]"
|
||||
onClick={() => handleDelete(item)}
|
||||
></div>)}
|
||||
>
|
||||
<Tooltip title={item.class_description}>
|
||||
<div className="rb:h-10 rb:text-[#5B6167] rb:leading-5 rb:font-regular rb:wrap-break-word rb:line-clamp-2">{item.class_description}</div>
|
||||
</Tooltip>
|
||||
</RbCard>
|
||||
</Col>
|
||||
))}
|
||||
<div className="rb:flex-1 rb:p-3 rb:overflow-hidden">
|
||||
<Row gutter={12} className="rb:mb-4">
|
||||
<Col span={6} offset={18}>
|
||||
<SearchInput
|
||||
placeholder={t('ontology.classSearchPlaceholder')}
|
||||
onSearch={(value) => setQuery({ class_name: value })}
|
||||
className="rb:w-full!"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</BodyWrapper>
|
||||
</div>
|
||||
<BodyWrapper loading={loading} empty={!data.items?.length}>
|
||||
<Row gutter={[16, 16]} className="rb:max-h-[calc(100%-48px)] rb:overflow-y-auto">
|
||||
{data.items?.map(item => (
|
||||
<Col key={item.class_id} span={6}>
|
||||
<RbCard
|
||||
title={item.class_name}
|
||||
extra={data.is_system_default ? undefined : (<div
|
||||
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/common/delete.svg')] rb:hover:bg-[url('@/assets/images/common/delete_hover.svg')]"
|
||||
onClick={() => handleDelete(item)}
|
||||
></div>)}
|
||||
>
|
||||
<Tooltip title={item.class_description}>
|
||||
<div className="rb:h-10 rb:text-[#5B6167] rb:leading-5 rb:font-regular rb:wrap-break-word rb:line-clamp-2">{item.class_description}</div>
|
||||
</Tooltip>
|
||||
</RbCard>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</BodyWrapper>
|
||||
</div>
|
||||
</Flex>
|
||||
|
||||
<OntologyClassModal
|
||||
ref={ontologyClassModalRef}
|
||||
|
||||
@@ -8,7 +8,7 @@ const Header:FC<{ title: string; desc: string; className?: string; }> = ({
|
||||
return (
|
||||
<div className={`rb:pl-2 ${className}`}>
|
||||
<div className="rb:text-[#212332] rb:font-[MiSans-Bold] rb:font-bold rb:text-[16px] rb:leading-5.5">{title}</div>
|
||||
<div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4 rb:mt-2 rb:pb-1">{desc}</div>
|
||||
<div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4 rb:mt-2">{desc}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:44:15
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 13:52:09
|
||||
* @Last Modified time: 2026-03-26 14:31:50
|
||||
*/
|
||||
/**
|
||||
* Prompt Editor Component
|
||||
@@ -193,7 +193,7 @@ const Prompt: FC = () => {
|
||||
bodyClassName="rb:px-4! rb:pt-0! rb:pb-3!"
|
||||
>
|
||||
<ChatContent
|
||||
classNames="rb:h-[calc(100vh-265px)] rb:mb-[12px]!"
|
||||
classNames="rb:h-[calc(100vh-257px)] rb:mb-[12px]!"
|
||||
contentClassNames="rb:max-w-75!"
|
||||
empty={<Empty url={ConversationEmptyIcon} title={t(`prompt.promptChatEmpty`)} isNeedSubTitle={false} size={[140, 100]} className="rb:h-full" />}
|
||||
data={chatList || []}
|
||||
@@ -275,10 +275,10 @@ const Prompt: FC = () => {
|
||||
{values?.current_prompt
|
||||
? <Editor
|
||||
ref={editorRef}
|
||||
className="rb:h-[calc(100vh-201px)] rb:bg-white! rb:border-none! rb:p-0! rb:text-[#212332] rb:leading-5"
|
||||
className="rb:h-[calc(100vh-193px)] rb:bg-white! rb:border-none! rb:p-0! rb:text-[#212332] rb:leading-5"
|
||||
onChange={(value) => form.setFieldValue('current_prompt', value)}
|
||||
/>
|
||||
: <Empty url={analysisEmptyIcon} title={t(`prompt.promptPlaceholder`)} isNeedSubTitle={false} size={[270, 170]} className="rb:h-[calc(100vh-201px)] rb:w-70 rb:mx-auto! rb:text-center! rb:text-[12px]! rb:leading-4!" />
|
||||
: <Empty url={analysisEmptyIcon} title={t(`prompt.promptPlaceholder`)} isNeedSubTitle={false} size={[270, 170]} className="rb:h-[calc(100vh-193px)] rb:w-70 rb:mx-auto! rb:text-center! rb:text-[12px]! rb:leading-4!" />
|
||||
}
|
||||
</Form.Item>
|
||||
</RbCard>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:44:04
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-09 12:18:09
|
||||
* @Last Modified time: 2026-03-26 14:36:33
|
||||
*/
|
||||
/**
|
||||
* Prompt History Component
|
||||
@@ -126,6 +126,7 @@ const History: React.FC = () => {
|
||||
</div>
|
||||
</RbCard>
|
||||
)}
|
||||
heightClass="rb:h-[calc(100vh-126px)]!"
|
||||
/>
|
||||
|
||||
<PromptDetail
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:46:47
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:44:16
|
||||
* @Last Modified time: 2026-03-26 18:57:08
|
||||
*/
|
||||
/**
|
||||
* Self Reflection Engine Configuration Page
|
||||
@@ -169,8 +169,8 @@ const SelfReflectionEngine: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={12}>
|
||||
<Row gutter={[16, 16]} className="rb:h-full!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('reflectionEngine.reflectionEngineConfig')}
|
||||
extra={<Space>
|
||||
@@ -179,7 +179,7 @@ const SelfReflectionEngine: React.FC = () => {
|
||||
</Space>}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
className="rb:h-[calc(100vh-76px)]!"
|
||||
className="rb:h-full!"
|
||||
bodyClassName="rb:h-[calc(100%-54px)] rb:overflow-y-auto! rb:p-4! rb:pt-0!"
|
||||
>
|
||||
<Form
|
||||
@@ -252,8 +252,8 @@ const SelfReflectionEngine: React.FC = () => {
|
||||
</Form>
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Space size={16} direction="vertical" className="rb:w-full">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<Flex gap={16} vertical className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('memoryExtractionEngine.example')}
|
||||
>
|
||||
@@ -346,7 +346,7 @@ const SelfReflectionEngine: React.FC = () => {
|
||||
</RbCard>
|
||||
)}
|
||||
</>}
|
||||
</Space>
|
||||
</Flex>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:48:59
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 15:33:38
|
||||
* @Last Modified time: 2026-03-26 14:43:20
|
||||
*/
|
||||
/**
|
||||
* Space Management Page
|
||||
@@ -12,7 +12,7 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { List, Button, Flex, Space as AntSpace, Tooltip } from 'antd';
|
||||
import { Button, Flex, Space as AntSpace, Tooltip, Row, Col } from 'antd';
|
||||
|
||||
import type { Space, SpaceModalRef } from './types';
|
||||
import SpaceModal from './components/SpaceModal';
|
||||
@@ -68,11 +68,12 @@ const SpaceManagement: React.FC = () => {
|
||||
{t('space.createSpace')}
|
||||
</Button>
|
||||
<BodyWrapper loading={loading} empty={data.length === 0}>
|
||||
<List
|
||||
grid={{ gutter: 16, column: 4 }}
|
||||
dataSource={data}
|
||||
renderItem={(item) => (
|
||||
<List.Item key={item.id}>
|
||||
<Row
|
||||
gutter={[16, 16]}
|
||||
className="rb:max-h-[calc(100%-48px)] rb:overflow-y-auto"
|
||||
>
|
||||
{data.map(item => (
|
||||
<Col key={item.id} span={6}>
|
||||
<RbCard
|
||||
avatarUrl={item.icon}
|
||||
avatarText={item.name[0]}
|
||||
@@ -91,10 +92,9 @@ const SpaceManagement: React.FC = () => {
|
||||
</Button>}
|
||||
>
|
||||
</RbCard>
|
||||
</List.Item>
|
||||
)}
|
||||
className="rb:h-[calc(100vh-124px)] rb:overflow-y-auto rb:overflow-x-hidden"
|
||||
/>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</BodyWrapper>
|
||||
|
||||
<SpaceModal
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
Row,
|
||||
Col,
|
||||
App,
|
||||
List,
|
||||
Space,
|
||||
Flex,
|
||||
Tooltip,
|
||||
@@ -69,11 +68,12 @@ const Custom = forwardRef<CustomRef, { getStatusTag: (status: string) => ReactNo
|
||||
return (
|
||||
<>
|
||||
<BodyWrapper loading={loading} empty={data.length === 0}>
|
||||
<List
|
||||
grid={{ gutter: 16, column: 3 }}
|
||||
dataSource={data}
|
||||
renderItem={(item) => (
|
||||
<List.Item key={item.id}>
|
||||
<Row
|
||||
gutter={[16, 16]}
|
||||
className="rb:max-h-[calc(100%-48px)] rb:overflow-y-auto"
|
||||
>
|
||||
{data.map((item) => (
|
||||
<Col span={8} key={item.id}>
|
||||
<RbCard
|
||||
title={
|
||||
<Flex justify="space-between" gap={16}>
|
||||
@@ -109,7 +109,6 @@ const Custom = forwardRef<CustomRef, { getStatusTag: (status: string) => ReactNo
|
||||
}
|
||||
isNeedTooltip={false}
|
||||
>
|
||||
|
||||
{item.tags?.length > 0
|
||||
? <Flex gap={8} wrap align="center">
|
||||
<Flex gap={6}>
|
||||
@@ -142,10 +141,9 @@ const Custom = forwardRef<CustomRef, { getStatusTag: (status: string) => ReactNo
|
||||
</Col>
|
||||
</Row>
|
||||
</RbCard>
|
||||
</List.Item>
|
||||
)}
|
||||
className="rb:h-[calc(100vh-178px)] rb:overflow-y-auto rb:overflow-x-hidden"
|
||||
/>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</BodyWrapper>
|
||||
|
||||
{/* 添加服务弹窗组件 */}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { useState, useRef, useEffect, type ReactNode } from 'react';
|
||||
import {
|
||||
List,
|
||||
Flex,
|
||||
Space,
|
||||
Tooltip,
|
||||
@@ -68,13 +67,14 @@ const Inner: React.FC<{ getStatusTag: (status: string) => ReactNode; keyword?: s
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<BodyWrapper loading={loading} empty={data.length === 0}>
|
||||
<List
|
||||
grid={{ gutter: 16, column: 3 }}
|
||||
dataSource={data}
|
||||
renderItem={(item) => (
|
||||
<List.Item key={item.id} className='rb:h-full!'>
|
||||
<Row
|
||||
gutter={[12, 12]}
|
||||
className="rb:max-h-[calc(100%-48px)] rb:overflow-y-auto"
|
||||
>
|
||||
{data.map((item) => (
|
||||
<Col span={8} key={item.id}>
|
||||
<RbCard
|
||||
title={
|
||||
<Flex justify="space-between" gap={16}>
|
||||
@@ -130,21 +130,20 @@ const Inner: React.FC<{ getStatusTag: (status: string) => ReactNode; keyword?: s
|
||||
</Col>
|
||||
</>
|
||||
: item.config_data.tool_class === 'JsonTool'
|
||||
? <Col span={24}>
|
||||
? <Col span={24}>
|
||||
<div className="rb:text-[#5B6167] rb:mb-1">{t('tool.jsonEg')}</div>
|
||||
{InnerConfigData[item.config_data.tool_class].eg}
|
||||
</Col>
|
||||
: <Col span={24}>
|
||||
<div className="rb:text-[#5B6167] rb:mb-1">{t('configStatus')}</div>
|
||||
{t(`tool.${item.status}_desc`)}
|
||||
</Col>
|
||||
: <Col span={24}>
|
||||
<div className="rb:text-[#5B6167] rb:mb-1">{t('configStatus')}</div>
|
||||
{t(`tool.${item.status}_desc`)}
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
</RbCard>
|
||||
</List.Item>
|
||||
)}
|
||||
className="rb:h-[calc(100vh-178px)] rb:overflow-y-auto rb:overflow-x-hidden"
|
||||
/>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</BodyWrapper>
|
||||
|
||||
<TimeToolModal
|
||||
@@ -157,7 +156,7 @@ const Inner: React.FC<{ getStatusTag: (status: string) => ReactNode; keyword?: s
|
||||
ref={innerToolModalRef}
|
||||
refreshTable={getData}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -434,7 +434,7 @@ const Market: React.FC<{ getStatusTag?: (status: string) => ReactNode }> = () =>
|
||||
footer={<Flex justify="space-between" align="center" className="rb:text-[#5B6167] rb:text-[12px] rb:mb-1!">
|
||||
{mcp.publisher && <span>{mcp.publisher.startsWith('@') ? mcp.publisher : `@${mcp.publisher}`}</span>}
|
||||
{mcp.view_count && <Space size={4}>
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/common/global_outline.svg')]"></div>
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/global_outline.svg')]"></div>
|
||||
{mcp.view_count.toLocaleString()}
|
||||
</Space>}
|
||||
</Flex>}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useState, useRef, useEffect, forwardRef, useImperativeHandle, type ReactNode } from 'react';
|
||||
import {
|
||||
App,
|
||||
List,
|
||||
Space,
|
||||
Tooltip,
|
||||
Dropdown,
|
||||
Flex,
|
||||
Row, Col,
|
||||
} from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -84,11 +84,12 @@ const Mcp = forwardRef<McpRef, { getStatusTag: (status: string) => ReactNode; ke
|
||||
return (
|
||||
<>
|
||||
<BodyWrapper loading={loading} empty={data?.length === 0}>
|
||||
<List
|
||||
grid={{ gutter: 16, column: 3 }}
|
||||
dataSource={data}
|
||||
renderItem={(item) => (
|
||||
<List.Item key={item.id}>
|
||||
<Row
|
||||
gutter={[16, 16]}
|
||||
className="rb:max-h-[calc(100%-48px)] rb:overflow-y-auto"
|
||||
>
|
||||
{data.map((item) => (
|
||||
<Col span={8} key={item.id}>
|
||||
<RbCard
|
||||
title={
|
||||
<Flex justify="space-between" gap={16}>
|
||||
@@ -137,12 +138,12 @@ const Mcp = forwardRef<McpRef, { getStatusTag: (status: string) => ReactNode; ke
|
||||
</div>
|
||||
</Flex>
|
||||
<div className="rb:text-[#5B6167] rb:leading-4.5 rb:text-[12px] rb:mt-4">{t('tool.last_health_check')}: {formatDateTime(item.config_data?.last_health_check)}</div>
|
||||
|
||||
|
||||
</RbCard>
|
||||
</List.Item>
|
||||
)}
|
||||
className="rb:h-[calc(100vh-124px)] rb:overflow-y-auto rb:overflow-x-hidden"
|
||||
/>
|
||||
</Col>
|
||||
))}
|
||||
<Col span={8}></Col>
|
||||
</Row>
|
||||
</BodyWrapper>
|
||||
|
||||
{/* 添加服务弹窗组件 */}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:51:08
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 16:45:18
|
||||
* @Last Modified time: 2026-03-26 14:53:41
|
||||
*/
|
||||
/**
|
||||
* User Management Page
|
||||
@@ -142,7 +142,7 @@ const UserManagement: React.FC = () => {
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="rb:h-[calc(100vh-80px)] rb:overflow-hidden rb:bg-white rb:rounded-lg rb:pt-3 rb:px-3">
|
||||
<div className="rb:h-full rb:overflow-hidden rb:bg-white rb:rounded-lg rb:pt-3 rb:px-3">
|
||||
<Flex justify="space-between" align="center" className="rb:px-1! rb:mb-3!">
|
||||
<div className="rb:gont-[MiSans-Bold] rb:font-bold rb:text-[#212332] rb:leading-5">{t('user.userList')}</div>
|
||||
<Button type="primary" onClick={handleCreate}>
|
||||
@@ -159,7 +159,7 @@ const UserManagement: React.FC = () => {
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
isScroll={true}
|
||||
scrollY="calc(100vh - 256px)"
|
||||
scrollY="calc(100vh - 248px)"
|
||||
/>
|
||||
|
||||
<CreateModal
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:53:44
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:23:18
|
||||
* @Last Modified time: 2026-03-26 14:58:48
|
||||
*/
|
||||
/**
|
||||
* User Memory Page
|
||||
@@ -12,15 +12,15 @@
|
||||
import { useEffect, useState, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { Row, Col, Skeleton, Form, Flex, Tooltip } from 'antd';
|
||||
import { Row, Col, Form, Flex, Tooltip } from 'antd';
|
||||
|
||||
import Empty from '@/components/Empty'
|
||||
import type { Data } from './types'
|
||||
import { getUserMemoryList } from '@/api/memory';
|
||||
import { useUser } from '@/store/user'
|
||||
import RbCard from '@/components/RbCard/Card'
|
||||
import SearchInput from '@/components/SearchInput';
|
||||
import RbStatistic from '@/components/RbStatistic';
|
||||
import BodyWrapper from '@/components/Empty/BodyWrapper'
|
||||
|
||||
export default function UserMemory() {
|
||||
const { t } = useTranslation();
|
||||
@@ -91,52 +91,52 @@ export default function UserMemory() {
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
{loading ?
|
||||
<Skeleton active />
|
||||
: filterData.length > 0 ? (
|
||||
<Row gutter={[12, 12]}>
|
||||
{filterData.map((item, index) => {
|
||||
const { end_user, memory_num, memory_config } = item as Data;
|
||||
const name = end_user?.other_name && end_user?.other_name !== '' ? end_user?.other_name : end_user?.id
|
||||
return (
|
||||
<Col key={index} span={8}>
|
||||
<RbCard
|
||||
title={<Flex gap={4}>
|
||||
<div className="rb:size-6 rb:text-center rb:font-semibold rb:leading-6 rb:rounded-md rb:text-white rb:bg-[#155EEF]">{name[0]}</div>
|
||||
|
||||
<Tooltip title={name || '-'}><div className={`rb:flex-1 rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap`}>{name || '-'}</div></Tooltip>
|
||||
</Flex>}
|
||||
headerType="border"
|
||||
headerClassName="rb:h-[48px]! rb:mx-4!"
|
||||
bodyClassName="rb:py-3! rb:px-4!"
|
||||
className="rb:cursor-pointer"
|
||||
onClick={() => handleViewDetail(end_user.id)}
|
||||
>
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<RbStatistic title={t('userMemory.capacity')} value={memory_num?.total || 0} suffix={t('userMemory.memoryNum')} />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<RbStatistic title={t('userMemory.type')} value={t(`userMemory.${item.type || 'person'}`)} />
|
||||
</Col>
|
||||
</Row>
|
||||
<BodyWrapper loading={loading} empty={data.length === 0}>
|
||||
<Row
|
||||
gutter={[12, 12]}
|
||||
className="rb:max-h-[calc(100%-48px)] rb:overflow-y-auto"
|
||||
>
|
||||
{filterData.map((item, index) => {
|
||||
const { end_user, memory_num, memory_config } = item as Data;
|
||||
const name = end_user?.other_name && end_user?.other_name !== '' ? end_user?.other_name : end_user?.id
|
||||
return (
|
||||
<Col key={index} span={8}>
|
||||
<RbCard
|
||||
title={<Flex gap={4}>
|
||||
<div className="rb:size-6 rb:text-center rb:font-semibold rb:leading-6 rb:rounded-md rb:text-white rb:bg-[#155EEF]">{name[0]}</div>
|
||||
|
||||
<div className="rb:relative rb:z-2 rb:mt-3 rb:bg-[#F6F6F6] rb:rounded-lg rb:py-2 rb:px-3 rb:leading-5" onClick={handleViewMemoryConfig}>
|
||||
<Flex align="center" justify="space-between" className="rb:text-[#5B6167]">
|
||||
{t('userMemory.memory_config_name')}
|
||||
<div
|
||||
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/userMemory/arrow_right_dark.svg')]"
|
||||
></div>
|
||||
</Flex>
|
||||
<div className="rb:font-medium rb:text-[#212332] rb:mt-1">{memory_config?.memory_config_name || '-'}</div>
|
||||
</div>
|
||||
</RbCard>
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
</Row>
|
||||
) : <Empty />
|
||||
}
|
||||
<Tooltip title={name || '-'}><div className={`rb:flex-1 rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap`}>{name || '-'}</div></Tooltip>
|
||||
</Flex>}
|
||||
headerType="border"
|
||||
headerClassName="rb:h-[48px]! rb:mx-4!"
|
||||
bodyClassName="rb:py-3! rb:px-4!"
|
||||
className="rb:cursor-pointer"
|
||||
onClick={() => handleViewDetail(end_user.id)}
|
||||
>
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<RbStatistic title={t('userMemory.capacity')} value={memory_num?.total || 0} suffix={t('userMemory.memoryNum')} />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<RbStatistic title={t('userMemory.type')} value={t(`userMemory.${item.type || 'person'}`)} />
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<div className="rb:relative rb:z-2 rb:mt-3 rb:bg-[#F6F6F6] rb:rounded-lg rb:py-2 rb:px-3 rb:leading-5" onClick={handleViewMemoryConfig}>
|
||||
<Flex align="center" justify="space-between" className="rb:text-[#5B6167]">
|
||||
{t('userMemory.memory_config_name')}
|
||||
<div
|
||||
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/userMemory/arrow_right_dark.svg')]"
|
||||
></div>
|
||||
</Flex>
|
||||
<div className="rb:font-medium rb:text-[#212332] rb:mt-1">{memory_config?.memory_config_name || '-'}</div>
|
||||
</div>
|
||||
</RbCard>
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
</Row>
|
||||
</BodyWrapper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:57:26
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-09 14:28:34
|
||||
* @Last Modified time: 2026-03-26 18:59:53
|
||||
*/
|
||||
/**
|
||||
* Neo4j User Memory Detail View
|
||||
@@ -75,7 +75,7 @@ const Neo4j: FC = () => {
|
||||
|
||||
return (
|
||||
<div className="rb:h-screen rb:w-screen rb:p-3 rb:relative" onClick={() => setSelectedKey(null)}>
|
||||
<Flex className="rb:h-[calc(100vh-24px)]" gap={12}>
|
||||
<Flex className="rb:h-full!" gap={12}>
|
||||
<Flex gap={15} vertical justify="space-between" align="center" className="rb:h-full! rb:px-4! rb:pt-6! rb:pb-5! rb:bg-white rb:w-20 rb:rounded-xl">
|
||||
<Flex gap={15} vertical>
|
||||
<Popover
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:57:11
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 11:27:53
|
||||
* @Last Modified time: 2026-03-27 10:26:31
|
||||
*/
|
||||
/**
|
||||
* RAG User Memory Detail View
|
||||
@@ -113,10 +113,11 @@ const Rag: FC = () => {
|
||||
})
|
||||
}
|
||||
return (
|
||||
<Row gutter={[16, 16]}>
|
||||
<Row gutter={[16, 16]} className="rb:h-full!">
|
||||
<Col span={8}>
|
||||
<RbCard
|
||||
bodyClassName="rb:p-3! rb:pt-4! rb:h-[calc(100vh-76px)]"
|
||||
bodyClassName="rb:p-3! rb:pt-4!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<Flex align="center" gap={12} className="rb:mb-6!">
|
||||
<div className="rb:size-12 rb:text-center rb:font-semibold rb:text-[28px] rb:leading-12 rb:rounded-xl rb:text-white rb:bg-[#155EEF]">{name?.[0]}</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:34:23
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-11 15:03:05
|
||||
* @Last Modified time: 2026-03-27 11:09:52
|
||||
*/
|
||||
/**
|
||||
* About Me Component
|
||||
@@ -67,12 +67,12 @@ const AboutMe = forwardRef<AboutMeRef, { className?: string; }>(({ className },
|
||||
title={t('userMemory.aboutMe')}
|
||||
headerClassName="rb:min-h-[46px]!! rb:font-medium!"
|
||||
className={clsx("rb:bg-[#FFFFFF]! rb:shadow-[0px_2px_6px_0px_rgba(33,35,50,0.13)]! rb:absolute! rb:w-100 rb:top-29 rb:left-26", className)}
|
||||
bodyClassName="rb:px-5! rb:pb-5! rb:pt-3.75! rb:max-h-[calc(100vh-176px)] rb:overflow-y-auto!"
|
||||
bodyClassName="rb:px-5! rb:pb-5! rb:pt-3.75! rb:max-h-[calc(100vh-186px)]! rb:overflow-y-auto!"
|
||||
>
|
||||
{loading
|
||||
? <Skeleton className="rb:mt-4" />
|
||||
: Object.keys(data).filter(key => data[key] !== null).length > 0
|
||||
? <>
|
||||
? <div className="rb:overflow-y-auto rb:h-full">
|
||||
{data.user_summary &&
|
||||
<div className="rb:font-regular rb:leading-5 rb:text-[#5B6167]">
|
||||
{data.user_summary}
|
||||
@@ -95,7 +95,7 @@ const AboutMe = forwardRef<AboutMeRef, { className?: string; }>(({ className },
|
||||
{data.one_sentence &&
|
||||
<RbAlert className="rb:mt-4! rb:text-[14px]!">{data.one_sentence}</RbAlert>
|
||||
}
|
||||
</>
|
||||
</div>
|
||||
: <Empty size={88} className="rb:mt-12 rb:mb-20.25" />
|
||||
}
|
||||
</RbCard>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:34:16
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 11:36:02
|
||||
* @Last Modified time: 2026-03-27 11:22:10
|
||||
*/
|
||||
import { type FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -32,7 +32,7 @@ const ActivationMetricsPieCard: FC<ActivationMetricsPieCardProps> = ({ chartData
|
||||
className="rb:h-full!"
|
||||
>
|
||||
{loading
|
||||
? <Loading size={249} />
|
||||
? <Loading size={150} />
|
||||
: <PieChart
|
||||
chartData={chartData as { name: string; value: number }[]}
|
||||
height={214}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:34:04
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 11:04:52
|
||||
* @Last Modified time: 2026-03-27 10:28:53
|
||||
*/
|
||||
import { type FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -20,8 +20,10 @@ const ConversationMemory: FC = () => {
|
||||
return (
|
||||
<RbCard
|
||||
title={t('userMemory.conversationMemory')}
|
||||
headerClassName="rb:text-[18px]! rb:leading-[24px]"
|
||||
bodyClassName="rb:h-[100%]! rb:overflow-hidden rb:py-0!"
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:pt-0! rb:mb-0! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-4! rb:pt-0! rb:h-[calc(100%-54px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<PageScrollList<string>
|
||||
url={getRagContentUrl}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:33:30
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 17:55:02
|
||||
* @Last Modified time: 2026-03-27 11:11:09
|
||||
*/
|
||||
/**
|
||||
* End User Profile Component
|
||||
@@ -85,7 +85,7 @@ const EndUserProfile = forwardRef<EndUserProfileRef, EndUserProfileProps>(({ cla
|
||||
}
|
||||
headerClassName="rb:min-h-[46px]!! rb:font-medium!"
|
||||
className={clsx("rb:bg-[#FFFFFF]! rb:shadow-[0px_2px_6px_0px_rgba(33,35,50,0.13)]! rb:absolute! rb:w-80 rb:top-29 rb:left-26", className)}
|
||||
bodyClassName="rb:px-5! rb:pb-5! rb:pt-3.75! rb:max-h-[calc(100vh-176px)] rb:overflow-auto"
|
||||
bodyClassName="rb:px-5! rb:pb-5! rb:pt-3.75! rb:max-h-[calc(100vh-186px)] rb:overflow-auto"
|
||||
>
|
||||
{loading
|
||||
? <Skeleton />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:33:06
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 14:05:10
|
||||
* @Last Modified time: 2026-03-27 11:18:47
|
||||
*/
|
||||
import { useEffect, useState, forwardRef, useImperativeHandle } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -83,7 +83,7 @@ const Habits = forwardRef<{ handleRefresh: () => void; }>((_props, ref) => {
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-54px)] rb:overflow-y-auto!"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
{loading
|
||||
? <Skeleton active />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:32:47
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-05 18:29:29
|
||||
* @Last Modified time: 2026-03-27 11:11:35
|
||||
*/
|
||||
/**
|
||||
* Interest Distribution Component
|
||||
@@ -77,7 +77,7 @@ const InterestDistribution: FC<{ className?: string; }> = ({ className }) => {
|
||||
title={t('userMemory.interestDistribution')}
|
||||
headerClassName="rb:min-h-[46px]!! rb:font-medium!"
|
||||
className={clsx("rb:bg-[#FFFFFF]! rb:shadow-[0px_2px_6px_0px_rgba(33,35,50,0.13)]! rb:absolute! rb:w-100 rb:top-29 rb:left-26", className)}
|
||||
bodyClassName="rb:px-5! rb:pb-5! rb:pt-3.75! rb:max-h-[calc(100vh-176px)] rb:overflow-auto"
|
||||
bodyClassName="rb:px-5! rb:pb-5! rb:pt-3.75! rb:max-h-[calc(100vh-186px)] rb:overflow-auto"
|
||||
>
|
||||
{loading
|
||||
? <Loading size={249} />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:32:41
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-05 18:35:01
|
||||
* @Last Modified time: 2026-03-27 11:11:46
|
||||
*/
|
||||
/**
|
||||
* Memory Insight Component
|
||||
@@ -66,7 +66,7 @@ const MemoryInsight = forwardRef<MemoryInsightRef, { className?: string; }>(({ c
|
||||
title={t('userMemory.memoryInsight')}
|
||||
headerClassName="rb:min-h-[46px]!! rb:font-medium!"
|
||||
className={clsx("rb:bg-[#FFFFFF]! rb:shadow-[0px_2px_6px_0px_rgba(33,35,50,0.13)]! rb:absolute! rb:w-100 rb:top-29 rb:left-26", className)}
|
||||
bodyClassName="rb:px-5! rb:pb-5! rb:pt-3.75! rb:max-h-[calc(100vh-176px)] rb:overflow-auto"
|
||||
bodyClassName="rb:px-5! rb:pb-5! rb:pt-3.75! rb:max-h-[calc(100vh-186px)] rb:overflow-auto"
|
||||
>
|
||||
{loading
|
||||
? <Skeleton />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:32:23
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 12:09:53
|
||||
* @Last Modified time: 2026-03-27 11:13:27
|
||||
*/
|
||||
import { type FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -119,7 +119,7 @@ const PerceptualLastInfo: FC = () => {
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[50px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-4! rb:pt-0! rb:h-[calc(100%-50px)] rb:overflow-y-auto"
|
||||
className="rb:h-[calc(100vh-88px)]! rb:w-full!"
|
||||
className="rb:h-full! rb:w-full!"
|
||||
>
|
||||
<Flex align="center" gap={8} className="rb:mb-4!">
|
||||
{Object.keys(KEYS).map(key => (
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:32:07
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 11:49:29
|
||||
* @Last Modified time: 2026-03-27 11:23:11
|
||||
*/
|
||||
import { type FC, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -72,7 +72,7 @@ const RecentTrendsLineCard: FC<RecentTrendsLineCardProps> = ({ chartData, series
|
||||
className="rb:h-full!"
|
||||
>
|
||||
{loading
|
||||
? <Loading size={249} />
|
||||
? <Loading size={150} />
|
||||
: !chartData || chartData.length === 0
|
||||
? <Empty size={120} className="rb:mt-12 rb:mb-20.25" />
|
||||
: <ReactEcharts
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:31:50
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:50:16
|
||||
* @Last Modified time: 2026-03-27 11:36:27
|
||||
*/
|
||||
import { useEffect, useState, useRef, forwardRef, useImperativeHandle } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:31:36
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:02:11
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-27 11:13:44
|
||||
*/
|
||||
import { type FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -86,7 +86,7 @@ const Timeline: FC = () => {
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:pl-5! rb:pt-0! rb:pr-3! rb:pb-4! rb:h-[calc(100%-54px)] rb:overflow-y-auto"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
{loading
|
||||
? <Skeleton active />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-01-08 19:46:02
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:03:50
|
||||
* @Last Modified time: 2026-03-27 11:20:40
|
||||
*/
|
||||
import { type FC, useEffect, useState } from 'react'
|
||||
import clsx from 'clsx'
|
||||
@@ -148,15 +148,15 @@ const EpisodicDetail: FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Row gutter={16}>
|
||||
<Col flex="400px">
|
||||
<Row gutter={16} className="rb:h-full!">
|
||||
<Col flex="400px" className="rb:h-full!">
|
||||
<RbCard
|
||||
title={<div className="rb:leading-5.5!">
|
||||
<span className="rb:font-[MiSans-Bold] rb:font-bold">{t('episodicDetail.curResult')}</span>
|
||||
<span className="rb:text-[#5B6167] rb:font-regular!"> ({data.total || 0}{t('episodicDetail.unix')})</span>
|
||||
</div>}
|
||||
headerType="borderless"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
headerClassName="rb:min-h-[38px]! rb:pt-3! rb:mb-0!"
|
||||
bodyClassName="rb:p-3! rb:pb-0! rb:h-[calc(100%-38px)]!"
|
||||
>
|
||||
@@ -231,11 +231,11 @@ const EpisodicDetail: FC = () => {
|
||||
}
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col flex="1">
|
||||
<Col flex="1" className="rb:h-full!">
|
||||
<RbCard
|
||||
title={selected?.title}
|
||||
headerType="borderless"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-54px)]! rb:overflow-y-auto"
|
||||
>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-01-10 17:35:17
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:05:06
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-27 11:19:38
|
||||
*/
|
||||
import { type FC, useEffect, useState, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -132,14 +132,14 @@ const ExplicitDetail: FC = () => {
|
||||
return () => { chartInstance.current?.dispose(); chartInstance.current = null }
|
||||
}, [data.semantic_memories])
|
||||
return (
|
||||
<Row gutter={12} className="rb:h-full">
|
||||
<Col span={12}>
|
||||
<Row gutter={12} className="rb:h-full!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('explicitDetail.episodic_memories')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[50px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-50px)] rb:overflow-y-auto!"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
{loading ?
|
||||
<Skeleton active />
|
||||
@@ -163,13 +163,13 @@ const ExplicitDetail: FC = () => {
|
||||
}
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('explicitDetail.semantic_memories')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-54px)] rb:overflow-y-auto!"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
{loading ?
|
||||
<Skeleton active />
|
||||
|
||||
@@ -113,13 +113,13 @@ const GraphDetail = forwardRef<GraphDetailRef>((_props, ref) => {
|
||||
}
|
||||
/>
|
||||
<Row gutter={12} className="rb:p-3! rb:pr-0! rb:h-[calc(100vh-64px)] rb:w-full! rb:flex-nowrap! rb:overflow-hidden!">
|
||||
<Col flex="480px">
|
||||
<Col flex="480px" className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('userMemory.relationshipEvolution')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[56px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-56px)] rb:overflow-y-auto!"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<Flex vertical gap={16}>
|
||||
<EmotionLine chartData={emotionData} loading={loading} />
|
||||
@@ -127,13 +127,13 @@ const GraphDetail = forwardRef<GraphDetailRef>((_props, ref) => {
|
||||
</Flex>
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col className="rb:w-[calc(100%-480px)]!">
|
||||
<Col flex="1" className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('userMemory.timelineMemories')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[53px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0!"
|
||||
className="rb:w-full!"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-53px)]!"
|
||||
className="rb:w-full! rb:h-full!"
|
||||
>
|
||||
<BtnTabs
|
||||
className="rb:mb-4!"
|
||||
@@ -144,7 +144,7 @@ const GraphDetail = forwardRef<GraphDetailRef>((_props, ref) => {
|
||||
}))}
|
||||
onChange={(key: string) => setActiveTab(key)}
|
||||
/>
|
||||
<div className="rb:h-[calc(100vh-193px)] rb:overflow-y-auto">
|
||||
<div className="rb:h-[calc(100%-42px)] rb:overflow-y-auto">
|
||||
{timelineLoading
|
||||
? <Skeleton active />
|
||||
: !activeContent || activeContent.length === 0
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-01-08 19:46:02
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:56:55
|
||||
* @Last Modified time: 2026-03-27 11:18:50
|
||||
*/
|
||||
import { forwardRef, useImperativeHandle, useRef, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -83,41 +83,39 @@ const ImplicitDetail = forwardRef<{ handleRefresh: () => void; }, { refresh: ()
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rb:h-full">
|
||||
<Row gutter={12}>
|
||||
<Col span={12}>
|
||||
<RbCard
|
||||
title={t('implicitDetail.subconscious')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[50px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-54px)]"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
>
|
||||
<RadioGroupButton
|
||||
value={activeTab}
|
||||
options={[
|
||||
{ value: 'preferences', label: t('implicitDetail.preferences') },
|
||||
{ value: 'portrait', label: t('implicitDetail.portrait') },
|
||||
]}
|
||||
onChange={handleChangeTab}
|
||||
/>
|
||||
<Row gutter={12} className="rb:h-full!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('implicitDetail.subconscious')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[50px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-54px)]"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<RadioGroupButton
|
||||
value={activeTab}
|
||||
options={[
|
||||
{ value: 'preferences', label: t('implicitDetail.preferences') },
|
||||
{ value: 'portrait', label: t('implicitDetail.portrait') },
|
||||
]}
|
||||
onChange={handleChangeTab}
|
||||
/>
|
||||
|
||||
<div className="rb:mt-3 rb:h-[calc(100%-32px)]">
|
||||
{activeTab === 'preferences'
|
||||
? <Preferences ref={preferencesRef} />
|
||||
: <div className="rb:h-full rb:overflow-y-auto">
|
||||
<Portrait ref={portraitRef} />
|
||||
<InterestAreas ref={interestAreasRef} />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Habits ref={habitsRef} />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<div className="rb:mt-3 rb:h-[calc(100%-32px)]">
|
||||
{activeTab === 'preferences'
|
||||
? <Preferences ref={preferencesRef} />
|
||||
: <div className="rb:h-full rb:overflow-y-auto">
|
||||
<Portrait ref={portraitRef} />
|
||||
<InterestAreas ref={interestAreasRef} />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<Habits ref={habitsRef} />
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
})
|
||||
export default ImplicitDetail
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-01-08 19:46:02
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:09:12
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-27 11:13:19
|
||||
*/
|
||||
import { type FC } from 'react'
|
||||
import { Row, Col } from 'antd'
|
||||
@@ -22,11 +22,11 @@ import Timeline from '../components/Timeline'
|
||||
const PerceptualDetail: FC = () => {
|
||||
|
||||
return (
|
||||
<Row gutter={12}>
|
||||
<Col flex="480px">
|
||||
<Row gutter={12} className="rb:h-full!">
|
||||
<Col flex="480px" className="rb:h-full!">
|
||||
<PerceptualLastInfo />
|
||||
</Col>
|
||||
<Col flex="1">
|
||||
<Col flex="1" className="rb:h-full!">
|
||||
<Timeline />
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-01-08 19:46:02
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:09:49
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-27 11:17:22
|
||||
*/
|
||||
import { type FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -87,8 +87,8 @@ const ShortTermDetail: FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Row gutter={12}>
|
||||
<Col span={12}>
|
||||
<Row gutter={12} className="rb:h-full!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<div className="rb:grid rb:grid-cols-3 rb:gap-3 rb:mb-3">
|
||||
{(['retrieval_number', 'entity', 'long_term_number'] as const).map(key => (
|
||||
<Flex key={key} align="center" justify="space-between" className="rb:bg-white rb:rounded-xl rb:py-3! rb:pl-5! rb:pr-4!">
|
||||
@@ -115,10 +115,10 @@ const ShortTermDetail: FC = () => {
|
||||
</Space>)}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-54px)] rb:overflow-y-auto!"
|
||||
className="rb:h-[calc(100vh-183px)]!"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-54px)]"
|
||||
className="rb:h-[calc(100%-94px)]!"
|
||||
>
|
||||
<Flex gap={12} vertical>
|
||||
<Flex gap={12} vertical className="rb:h-full! rb:overflow-y-auto!">
|
||||
{loading
|
||||
? <Skeleton active />
|
||||
: !data.short_term || data.short_term.length === 0
|
||||
@@ -189,7 +189,7 @@ const ShortTermDetail: FC = () => {
|
||||
</Flex>
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={() => (<Space size={4}>
|
||||
{t('shortTermDetail.longTermTitle')}
|
||||
@@ -200,7 +200,7 @@ const ShortTermDetail: FC = () => {
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-54px)] rb:overflow-y-auto!"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<Flex vertical gap={12}>
|
||||
{loading
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2025-12-19 16:54:52
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:06:29
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-27 11:35:37
|
||||
*/
|
||||
import { forwardRef, useImperativeHandle, useRef } from 'react'
|
||||
import { Row, Col } from 'antd';
|
||||
@@ -46,8 +46,8 @@ const StatementDetail = forwardRef<{ handleRefresh: () => void },{ refresh: () =
|
||||
handleRefresh
|
||||
}));
|
||||
return (
|
||||
<Row gutter={[12, 12]}>
|
||||
<Col span={12}>
|
||||
<Row gutter={[12, 12]} className="rb:h-full!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<Row gutter={[12, 12]}>
|
||||
<Col span={24}>
|
||||
<WordCloud />
|
||||
@@ -60,7 +60,7 @@ const StatementDetail = forwardRef<{ handleRefresh: () => void },{ refresh: () =
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<Suggestions ref={suggestionsRef} refresh={refresh} />
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-01-12 14:42:02
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:55:36
|
||||
* @Last Modified time: 2026-03-27 11:15:05
|
||||
*/
|
||||
import { type FC, useEffect, useState, useMemo, useRef } from 'react'
|
||||
import clsx from 'clsx'
|
||||
@@ -155,14 +155,14 @@ const WorkingDetail: FC = () => {
|
||||
: data.length === 0
|
||||
? <Empty />
|
||||
:(
|
||||
<Row gutter={16}>
|
||||
<Col span={5}>
|
||||
<Row gutter={16} className="rb:h-full!">
|
||||
<Col span={5} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('workingDetail.conversation')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[58px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName='rb:p-3! rb:pt-0! rb:h-[calc(100%-58px)]'
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<div id="conversation-list" className="rb:h-full! rb:overflow-y-auto">
|
||||
<InfiniteScroll
|
||||
@@ -197,13 +197,13 @@ const WorkingDetail: FC = () => {
|
||||
</RbCard>
|
||||
</Col>
|
||||
{selected && <>
|
||||
<Col flex="auto" className="rb:h-full">
|
||||
<Col flex="auto" className="rb:h-full!">
|
||||
<RbCard
|
||||
title={selected.title}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[42px]! rb:pt-4! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName='rb:p-4! rb:pt-0! rb:h-[calc(100%-42px)]'
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<div className="rb:text-[#5B6167] rb:leading-4.5 rb:text-[12px]">{timeRange}</div>
|
||||
<Flex justify="space-between" align="center" className="rb:bg-[#F6F6F6] rb:rounded-lg rb:py-2.5! rb:pr-2.5! rb:pl-3.25! rb:mt-3!">
|
||||
@@ -226,13 +226,13 @@ const WorkingDetail: FC = () => {
|
||||
}
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col flex='360px' className="rb:h-full">
|
||||
<Col flex='360px' className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('workingDetail.successfulTitle')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[50px]! rb:font-[MiSans-Bold] rb:font-bold rb:leading-5.5"
|
||||
bodyClassName='rb:p-4! rb:pt-0! rb:h-[calc(100%-50px)] rb:overflow-y-auto!'
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
{detailLoading
|
||||
? <Skeleton active />
|
||||
|
||||
@@ -10,7 +10,7 @@ const NodeLibrary: FC<{ collapsed: boolean; handleToggle: () => void }> = ({ col
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className={clsx("rb:overflow-hidden rb:fixed rb:left-2.5 rb:top-18.5 rb:z-1000", {
|
||||
<div className={clsx("rb:h-[calc(100vh-88px)] rb:overflow-hidden rb:fixed rb:left-2.5 rb:top-18.5 rb:z-1000", {
|
||||
'rb:w-65': !collapsed,
|
||||
'rb:w-14': collapsed
|
||||
})}>
|
||||
@@ -27,9 +27,9 @@ const NodeLibrary: FC<{ collapsed: boolean; handleToggle: () => void }> = ({ col
|
||||
'rb:min-h-[52px]!': collapsed
|
||||
})}
|
||||
className="rb:h-full! rb:hover:shadow-none!"
|
||||
bodyClassName={clsx('rb:overflow-y-auto! rb:h-[calc(100vh-126px)]! rb:pt-0! rb:pb-3!', {
|
||||
'rb:px-0!': collapsed,
|
||||
'rb:px-3!': !collapsed
|
||||
bodyClassName={clsx('rb:overflow-y-auto! rb:pt-0! rb:pb-3!', {
|
||||
'rb:px-0! rb:h-[calc(100%-52px)]!': collapsed,
|
||||
'rb:px-3! rb:h-[calc(100%-42px)]!': !collapsed
|
||||
})}
|
||||
>
|
||||
<Flex vertical align={collapsed ? 'center' : undefined} gap={collapsed ? 8 : 16}>
|
||||
@@ -87,8 +87,6 @@ const NodeLibrary: FC<{ collapsed: boolean; handleToggle: () => void }> = ({ col
|
||||
}
|
||||
</Flex>
|
||||
</RbCard>
|
||||
<Flex gap={12} vertical>
|
||||
</Flex>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 15:39:59
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 15:08:02
|
||||
* @Last Modified time: 2026-03-27 11:30:44
|
||||
*/
|
||||
import { type FC, useEffect, useState, useMemo } from "react";
|
||||
import clsx from 'clsx'
|
||||
@@ -431,7 +431,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={clsx("rb:w-90 rb:fixed rb:right-2.5 rb:top-18.5 rb:bottom-2.5 rb:z-1000", styles.properties)}>
|
||||
<div className={clsx("rb:h-[calc(100vh-88px)] rb:w-90 rb:fixed rb:right-2.5 rb:top-18.5 rb:bottom-2.5 rb:z-1000", styles.properties)}>
|
||||
<RbCard
|
||||
title={t('workflow.nodeProperties')}
|
||||
extra={<Space>
|
||||
@@ -452,7 +452,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
headerType="borderless"
|
||||
headerClassName={clsx("rb:font-[MiSans-Bold] rb:font-bold rb:min-h-[48px]!")}
|
||||
className="rb:h-full! rb:hover:shadow-none!"
|
||||
bodyClassName={clsx('rb:overflow-y-auto! rb:h-[calc(100vh-131px)]! rb:px-3! rb:pt-0! rb:pb-3!')}
|
||||
bodyClassName={clsx('rb:overflow-y-auto! rb:h-[calc(100%-48px)]! rb:px-3! rb:pt-0! rb:pb-3!')}
|
||||
>
|
||||
<Form key={selectedNode?.getData()?.id} form={form} size="small" layout="vertical">
|
||||
<Form.Item name="name" label={t('workflow.nodeName')}>
|
||||
|
||||
@@ -100,6 +100,7 @@ export const useWorkflowGraph = ({
|
||||
const [isHandMode, setIsHandMode] = useState(true);
|
||||
const [config, setConfig] = useState<WorkflowConfig | null>(null);
|
||||
const [chatVariables, setChatVariables] = useState<ChatVariable[]>([])
|
||||
const featuresRef = useRef<FeaturesConfigForm | undefined>(undefined)
|
||||
|
||||
useEffect(() => {
|
||||
getConfig()
|
||||
@@ -121,6 +122,7 @@ export const useWorkflowGraph = ({
|
||||
})
|
||||
setChatVariables(initChatVariables)
|
||||
setConfig({ ...rest, variables: initChatVariables })
|
||||
featuresRef.current = rest.features
|
||||
onFeaturesLoad?.(rest.features)
|
||||
})
|
||||
}
|
||||
@@ -1016,6 +1018,7 @@ export const useWorkflowGraph = ({
|
||||
|
||||
const params = {
|
||||
...config,
|
||||
features: featuresRef.current,
|
||||
variables: chatVariables.map(v => {
|
||||
const { defaultValue, ...cleanV } = v
|
||||
return {
|
||||
@@ -1208,7 +1211,7 @@ export const useWorkflowGraph = ({
|
||||
});
|
||||
}
|
||||
const handleSaveFeaturesConfig = (value?: FeaturesConfigForm) => {
|
||||
setConfig(prev => prev ? { ...prev, features: value } as WorkflowConfig : prev)
|
||||
featuresRef.current = value
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -60,7 +60,7 @@ const Workflow = forwardRef<WorkflowRef, { onFeaturesLoad?: (features: FeaturesC
|
||||
handleSaveFeaturesConfig
|
||||
}))
|
||||
return (
|
||||
<div className="rb:h-[calc(100vh-64px)] rb:relative">
|
||||
<div className="rb:h-full rb:relative">
|
||||
{/* 左侧节点面板 */}
|
||||
<NodeLibrary collapsed={collapsed} handleToggle={handleToggle} />
|
||||
|
||||
|
||||
Reference in New Issue
Block a user