fix(web): ui upgrade
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-07 16:49:59
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-18 10:12:23
|
||||
* @Last Modified time: 2026-03-25 11:21:59
|
||||
*/
|
||||
import { useEffect, useState, type FC } from 'react';
|
||||
import { Select, Flex, Space } from 'antd';
|
||||
@@ -20,12 +20,16 @@ interface ModelSelectProps extends SelectProps {
|
||||
params?: Query;
|
||||
placeholder?: string;
|
||||
fontClassName?: string;
|
||||
isAutoFetch?: boolean;
|
||||
initialData?: Model[];
|
||||
}
|
||||
|
||||
const ModelSelect: FC<ModelSelectProps> = ({
|
||||
params,
|
||||
placeholder,
|
||||
fontClassName,
|
||||
isAutoFetch = true,
|
||||
initialData = [],
|
||||
...props
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -33,6 +37,7 @@ const ModelSelect: FC<ModelSelectProps> = ({
|
||||
|
||||
// Fetch active models whenever params change; stringify for stable deep comparison
|
||||
useEffect(() => {
|
||||
if (!isAutoFetch) return
|
||||
getModelList({
|
||||
...(params ?? {}),
|
||||
pagesize: 100,
|
||||
@@ -40,7 +45,7 @@ const ModelSelect: FC<ModelSelectProps> = ({
|
||||
}).then((res) => {
|
||||
setOptions((res as { items: Model[] }).items ?? []);
|
||||
});
|
||||
}, [JSON.stringify(params)]);
|
||||
}, [JSON.stringify(params), isAutoFetch]);
|
||||
|
||||
// Render the selected value inside the trigger with logo + truncated name
|
||||
const labelRender: SelectProps['labelRender'] = ({ value }) => {
|
||||
@@ -58,7 +63,7 @@ const ModelSelect: FC<ModelSelectProps> = ({
|
||||
return (
|
||||
<Select
|
||||
placeholder={placeholder ?? t('common.pleaseSelect')}
|
||||
options={options}
|
||||
options={[...options, ...initialData]}
|
||||
fieldNames={{ label: 'name', value: 'id' }}
|
||||
allowClear
|
||||
popupMatchSelectWidth={false}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:24:23
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-23 11:35:33
|
||||
* @Last Modified time: 2026-03-25 11:15:26
|
||||
*/
|
||||
/**
|
||||
* SearchInput Component
|
||||
@@ -51,6 +51,7 @@ const SearchInput: FC<SearchInputProps> = ({
|
||||
throttleDelay,
|
||||
defaultValue = undefined,
|
||||
className = '',
|
||||
variant = 'filled',
|
||||
...props
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -115,7 +116,8 @@ const SearchInput: FC<SearchInputProps> = ({
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
style={{ width: '300px' }}
|
||||
className={`rb:border-none! ${className}`}
|
||||
className={className}
|
||||
variant={variant}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:25:31
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 10:51:29
|
||||
* @Last Modified time: 2026-03-25 12:32:58
|
||||
*/
|
||||
/**
|
||||
* SiderMenu Component
|
||||
@@ -298,7 +298,10 @@ const Menu: FC<{
|
||||
items={menuItems}
|
||||
inlineCollapsed={collapsed}
|
||||
inlineIndent={10}
|
||||
className="rb:max-h-[calc(100vh-136px)] rb:overflow-y-auto"
|
||||
className={clsx("rb:overflow-y-auto", {
|
||||
'rb:max-h-[calc(100vh-136px)]': user?.is_superuser && source === 'space',
|
||||
'rb:max-h-[calc(100vh-76px)]': !(user?.is_superuser && source === 'space')
|
||||
})}
|
||||
/>
|
||||
{/* Return to space button for superusers */}
|
||||
{user?.is_superuser && source === 'space' &&
|
||||
|
||||
@@ -2801,6 +2801,7 @@ export const zh = {
|
||||
},
|
||||
prompt: {
|
||||
promptDesc: '输入您的原始提示词,AI将帮助您优化为更专业的版本',
|
||||
chatTitle: '多轮对话',
|
||||
editor: '提示词生成器',
|
||||
history: '我的历史',
|
||||
historyDesc: '查看和管理您的提示词优化历史',
|
||||
|
||||
@@ -351,6 +351,10 @@ body {
|
||||
color: #212332;
|
||||
background: #F6F6F6;
|
||||
}
|
||||
.ant-input-filled,
|
||||
.ant-select-filled:not(.ant-select-customize-input) .ant-select-selector {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
.ant-checkbox .ant-checkbox-inner {
|
||||
border-radius: 6px !important;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:21
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 15:27:30
|
||||
* @Last Modified time: 2026-03-25 11:34:04
|
||||
*/
|
||||
import { useEffect, useRef, useState, forwardRef, useImperativeHandle } from 'react';
|
||||
import { useEffect, useRef, useState, forwardRef, useImperativeHandle, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Row, Col, Space, Form, Input, Button, App, Spin, Flex } from 'antd'
|
||||
@@ -27,7 +27,7 @@ import type {
|
||||
} from './types'
|
||||
import type { Variable } from './components/VariableList/types'
|
||||
import type { KnowledgeConfig } from './components/Knowledge/types'
|
||||
import type { ModelListItem } from '@/views/ModelManagement/types'
|
||||
import type { Model } from '@/views/ModelManagement/types'
|
||||
import { getModelList } from '@/api/models';
|
||||
import { saveAgentConfig } from '@/api/application'
|
||||
import Knowledge from './components/Knowledge/Knowledge'
|
||||
@@ -43,6 +43,7 @@ import type { Skill } from '@/views/Skills/types'
|
||||
import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
|
||||
import DescWrapper from '@/components/FormItem/DescWrapper'
|
||||
import FeaturesConfig from './components/FeaturesConfig'
|
||||
import { getListLogoUrl } from '@/views/ModelManagement/utils';
|
||||
|
||||
/**
|
||||
* Agent configuration component
|
||||
@@ -56,8 +57,8 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [data, setData] = useState<Config | null>(null);
|
||||
const modelConfigModalRef = useRef<ModelConfigModalRef>(null)
|
||||
const [modelList, setModelList] = useState<ModelListItem[]>([])
|
||||
const [defaultModel, setDefaultModel] = useState<ModelListItem | null>(null)
|
||||
const [modelList, setModelList] = useState<Model[]>([])
|
||||
const [defaultModel, setDefaultModel] = useState<Model | null>(null)
|
||||
const [chatList, setChatList] = useState<ChatData[]>([])
|
||||
const values = Form.useWatch<Config>([], form)
|
||||
const [isSave, setIsSave] = useState(false)
|
||||
@@ -260,7 +261,7 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
const getModels = () => {
|
||||
getModelList({ type: 'llm,chat', pagesize: 100, page: 1, is_active: true })
|
||||
.then(res => {
|
||||
const response = res as { items: ModelListItem[] }
|
||||
const response = res as { items: Model[] }
|
||||
setModelList(response.items)
|
||||
})
|
||||
}
|
||||
@@ -273,7 +274,7 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
useEffect(() => {
|
||||
if (values?.default_model_config_id && modelList.length > 0) {
|
||||
const filterValue = modelList.find(item => item.id === values.default_model_config_id)
|
||||
setDefaultModel(filterValue as ModelListItem | null)
|
||||
setDefaultModel(filterValue as Model | null)
|
||||
setChatList([{
|
||||
label: filterValue?.name || '',
|
||||
model_config_id: filterValue?.id || '',
|
||||
@@ -343,7 +344,10 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
const handleSaveFeaturesConfig = (value: FeaturesConfigForm) => {
|
||||
form.setFieldValue('features', value)
|
||||
}
|
||||
console.log('values', values)
|
||||
const modelLogo = useMemo(() => {
|
||||
return defaultModel?.name && getListLogoUrl(defaultModel.provider, defaultModel.logo as string)
|
||||
}, [defaultModel])
|
||||
console.log('values', values, defaultModel)
|
||||
return (
|
||||
<>
|
||||
{loading && <Spin fullscreen></Spin>}
|
||||
@@ -353,7 +357,10 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
<Flex gap={16} 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">
|
||||
{defaultModel?.name ? <div className="rb:size-4 rb:bg-[url('@/assets/images/application/model.svg')]"></div> : null}
|
||||
{modelLogo
|
||||
? <img src={modelLogo} className="rb:size-4 rb:rounded-md" alt="" />
|
||||
: defaultModel?.name
|
||||
? <div className="rb:size-4 rb:bg-[url('@/assets/images/application/model.svg')]"></div> : null}
|
||||
{defaultModel?.name || t('application.chooseModel')}
|
||||
</Button>
|
||||
<Space size={12}>
|
||||
@@ -475,7 +482,6 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
</Row>
|
||||
|
||||
<ModelConfigModal
|
||||
modelList={modelList}
|
||||
data={values}
|
||||
ref={modelConfigModalRef}
|
||||
refresh={refresh}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:29
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-03 19:05:23
|
||||
* @Last Modified time: 2026-03-25 11:18:09
|
||||
*/
|
||||
import { type FC, useState, useRef, useEffect } from 'react';
|
||||
import clsx from 'clsx';
|
||||
@@ -127,10 +127,10 @@ const Api: FC<{ application: Application | null }> = ({ application }) => {
|
||||
<div className="rb:w-250 rb:mx-auto">
|
||||
<Flex gap={20} vertical>
|
||||
<RbCard
|
||||
title={<Flex align="center">
|
||||
title={() => (<Flex align="center">
|
||||
{t('application.endpointConfiguration')}
|
||||
<span className="rb:text-[#5B6167] rb:text-[12px]">({t('application.endpointConfigurationSubTitle')})</span>
|
||||
</Flex>}
|
||||
</Flex>)}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-13.5!"
|
||||
>
|
||||
@@ -157,10 +157,10 @@ const Api: FC<{ application: Application | null }> = ({ application }) => {
|
||||
</Flex>
|
||||
</RbCard>
|
||||
<RbCard
|
||||
title={<Flex align="center">
|
||||
title={() => (<Flex align="center">
|
||||
{t('application.apiKeys')}
|
||||
<span className="rb:text-[#5B6167] rb:text-[12px]">({t('application.apiKeySubTitle')})</span>
|
||||
</Flex>}
|
||||
</Flex>)}
|
||||
extra={
|
||||
<Button style={{padding: '0 8px', height: '24px'}} onClick={handleAdd}>+ {t('application.addApiKey')}</Button>
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import copy from 'copy-to-clipboard';
|
||||
import { updatePromptMessages, createPromptSessions } from '@/api/prompt'
|
||||
import type { AiPromptModalRef, AiPromptVariableModalRef, AiPromptForm } from '../types'
|
||||
import RbModal from '@/components/RbModal'
|
||||
import type { ModelListItem } from '@/views/ModelManagement/types'
|
||||
import type { Model } from '@/views/ModelManagement/types'
|
||||
import ChatContent from '@/components/Chat/ChatContent'
|
||||
import Empty from '@/components/Empty'
|
||||
import ConversationEmptyIcon from '@/assets/images/conversation/conversationEmpty.svg'
|
||||
@@ -37,7 +37,7 @@ interface AiPromptModalProps {
|
||||
/** Callback to refresh prompt with optimized value */
|
||||
refresh: (value: string) => void;
|
||||
/** Default model to pre-select */
|
||||
defaultModel?: ModelListItem | null;
|
||||
defaultModel?: Model | null;
|
||||
source?: 'application' | 'skills'
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:28:07
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 10:59:20
|
||||
* @Last Modified time: 2026-03-25 11:28:02
|
||||
*/
|
||||
/**
|
||||
* Model Configuration Modal
|
||||
@@ -11,13 +11,14 @@
|
||||
*/
|
||||
|
||||
import { forwardRef, useImperativeHandle, useState, useEffect } from 'react';
|
||||
import { Form, Select } from 'antd';
|
||||
import { Form, type SelectProps } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import type { ModelConfig, ModelConfigModalRef, Config, Source } from '../types'
|
||||
import type { ModelListItem } from '@/views/ModelManagement/types'
|
||||
import type { Model } from '@/views/ModelManagement/types'
|
||||
import RbModal from '@/components/RbModal'
|
||||
import RbSlider from '@/components/RbSlider'
|
||||
import ModelSelect from '@/components/ModelSelect'
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
@@ -25,8 +26,6 @@ const FormItem = Form.Item;
|
||||
* Component props
|
||||
*/
|
||||
interface ModelConfigModalProps {
|
||||
/** List of available models */
|
||||
modelList?: ModelListItem[];
|
||||
/** Callback to update model configuration */
|
||||
refresh: (values: ModelConfig, type: Source) => void;
|
||||
/** Application configuration data */
|
||||
@@ -51,7 +50,6 @@ const configFields = [
|
||||
const ModelConfigModal = forwardRef<ModelConfigModalRef, ModelConfigModalProps>(({
|
||||
refresh,
|
||||
data,
|
||||
modelList = []
|
||||
}, ref) => {
|
||||
const { t } = useTranslation();
|
||||
const [visible, setVisible] = useState(false);
|
||||
@@ -102,11 +100,11 @@ const ModelConfigModal = forwardRef<ModelConfigModalRef, ModelConfigModalProps>(
|
||||
});
|
||||
}
|
||||
/** Handle model selection change */
|
||||
const handleChange = (_value: string, option: ModelListItem | ModelListItem[] | undefined) => {
|
||||
const handleChange: SelectProps['onChange'] = (_value, option) => {
|
||||
if (source === 'chat') {
|
||||
form.setFieldValue('label', (option as ModelListItem).name)
|
||||
form.setFieldValue('label', (option as Model).name)
|
||||
} else {
|
||||
form.setFieldValue('capability', (option as ModelListItem).capability)
|
||||
form.setFieldValue('capability', (option as Model).capability)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,13 +138,8 @@ const ModelConfigModal = forwardRef<ModelConfigModalRef, ModelConfigModalProps>(
|
||||
hidden={source === 'multi_agent'}
|
||||
>
|
||||
{source !== 'multi_agent' &&
|
||||
<Select
|
||||
<ModelSelect
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
fieldNames={{
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
}}
|
||||
options={modelList}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-05 10:45:08
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 16:59:57
|
||||
* @Last Modified time: 2026-03-25 11:09:01
|
||||
*/
|
||||
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
|
||||
import { List, Flex, Tooltip, Form } from 'antd';
|
||||
@@ -169,6 +169,7 @@ const SkillListModal = forwardRef<SkillModalRef, SkillModalProps>(({
|
||||
<SearchInput
|
||||
placeholder={t('skills.searchPlaceholder')}
|
||||
className="rb:w-full!"
|
||||
variant="outlined"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
@@ -181,9 +182,9 @@ const SkillListModal = forwardRef<SkillModalRef, SkillModalProps>(({
|
||||
renderItem={(item: Skill) => (
|
||||
<List.Item>
|
||||
{/* Skill card with selection state styling */}
|
||||
<div key={item.id} className={clsx("rb:border rb:rounded-lg rb:p-[17px_16px] rb:cursor-pointer rb:hover:bg-[#F0F3F8]", {
|
||||
"rb:bg-[rgba(21,94,239,0.06)] rb:border-[#155EEF] rb:text-[#155EEF]": selectedIds.includes(item.id),
|
||||
"rb:border-[#DFE4ED] rb:text-[#212332]": !selectedIds.includes(item.id),
|
||||
<div key={item.id} className={clsx("rb:border rb:rounded-lg rb:p-[17px_16px] rb:cursor-pointer rb:hover:bg-[#F6F6F6]", {
|
||||
"rb:border-[#171719]": selectedIds.includes(item.id),
|
||||
"rb-border": !selectedIds.includes(item.id),
|
||||
})} onClick={() => handleSelect(item)}>
|
||||
{/* Skill name and description */}
|
||||
<div className="rb:flex-1 rb:max-w-[calc(100%-60px)]">
|
||||
@@ -194,7 +195,7 @@ const SkillListModal = forwardRef<SkillModalRef, SkillModalProps>(({
|
||||
</Tooltip>
|
||||
|
||||
{/* Skill description with tooltip */}
|
||||
<Tooltip title={item.description}>
|
||||
<Tooltip title={item.description} placement="topLeft">
|
||||
<div className="rb:h-10 rb:leading-5 rb:wrap-break-word rb:line-clamp-2">{item.description}</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:34:12
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-18 16:15:43
|
||||
* @Last Modified time: 2026-03-25 11:37:51
|
||||
*/
|
||||
import React, { useState, useEffect, useMemo, type MouseEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, App, Flex, Row, Col, Collapse } from 'antd';
|
||||
import { Button, App, Flex, Collapse } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import type { MySharedOutItem } from './types';
|
||||
@@ -112,9 +112,9 @@ const MySharing: React.FC = () => {
|
||||
</Button>
|
||||
),
|
||||
children: (
|
||||
<Row gutter={[12, 12]}>
|
||||
<div className="rb:grid rb:grid-cols-4 rb:gap-3">
|
||||
{items.map(item => (
|
||||
<Col key={item.id} span={6} className="rb:bg-[#F6F6F6] rb:rounded-lg rb:py-3! rb:px-4! rb:relative rb:cursor-pointer" onClick={() => handleEdit(item)}>
|
||||
<div key={item.id} className="rb:bg-[#F6F6F6] rb:rounded-lg rb:py-3! rb:px-4! rb:relative rb:cursor-pointer" onClick={() => handleEdit(item)}>
|
||||
<div
|
||||
className="rb:absolute rb:top-3 rb:right-3 rb:cursor-pointer rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/close.svg')]"
|
||||
onClick={(e) => handleCancelOne(item, e)}
|
||||
@@ -153,15 +153,15 @@ const MySharing: React.FC = () => {
|
||||
<span>{item.source_app_is_active ? t('application.sourceActive') : t('application.sourceInactive')}</span>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Col>
|
||||
</div>
|
||||
))}
|
||||
</Row>
|
||||
</div>
|
||||
),
|
||||
}]}
|
||||
/>
|
||||
))}
|
||||
</BodyWrapper>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:34:12
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-19 21:29:45
|
||||
* @Last Modified time: 2026-03-25 11:16:04
|
||||
*/
|
||||
/**
|
||||
* Application Management Page
|
||||
@@ -148,6 +148,7 @@ const ApplicationManagement: React.FC = () => {
|
||||
label: t(`application.${type}`),
|
||||
}))}
|
||||
allowClear
|
||||
variant="filled"
|
||||
className="rb:w-30!"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:56:54
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-12 16:58:14
|
||||
* @Last Modified time: 2026-03-25 11:42:26
|
||||
*/
|
||||
/**
|
||||
* Emotion Engine Configuration Page
|
||||
@@ -19,13 +19,12 @@ import clsx from 'clsx';
|
||||
import RbCard from '@/components/RbCard/Card';
|
||||
import { getMemoryEmotionConfig, updateMemoryEmotionConfig } from '@/api/memory'
|
||||
import type { ConfigForm } from './types'
|
||||
import CustomSelect from '@/components/CustomSelect';
|
||||
import { getModelListUrl } from '@/api/models'
|
||||
import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
|
||||
import LabelWrapper from '@/components/FormItem/LabelWrapper'
|
||||
import DescWrapper from '@/components/FormItem/DescWrapper'
|
||||
import RbSlider from '@/components/RbSlider';
|
||||
import RbAlert from '@/components/RbAlert';
|
||||
import ModelSelect from '@/components/ModelSelect';
|
||||
|
||||
/**
|
||||
* Configuration field definitions
|
||||
@@ -37,9 +36,8 @@ const configList = [
|
||||
},
|
||||
{
|
||||
key: 'emotion_model_id',
|
||||
type: 'customSelect',
|
||||
url: getModelListUrl,
|
||||
params: { type: 'chat,llm', page: 1, pagesize: 100, is_active: true }, // chat,llm
|
||||
type: 'modelSelect',
|
||||
params: { type: 'chat,llm' }, // chat,llm
|
||||
},
|
||||
{
|
||||
key: 'emotion_min_intensity',
|
||||
@@ -174,7 +172,7 @@ const EmotionEngine: React.FC = () => {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (config.type === 'customSelect') {
|
||||
if (config.type === 'modelSelect') {
|
||||
return (
|
||||
<div key={config.key} className="rb:bg-[#F6F6F6] rb:rounded-xl rb:p-3">
|
||||
<LabelWrapper title={t(`emotionEngine.${config.key}`)} className="rb:mb-3">
|
||||
@@ -184,12 +182,8 @@ const EmotionEngine: React.FC = () => {
|
||||
name={config.key}
|
||||
className="rb:mb-0!"
|
||||
>
|
||||
<CustomSelect
|
||||
url={config.url as string}
|
||||
<ModelSelect
|
||||
params={config.params}
|
||||
valueKey='id'
|
||||
labelKey='name'
|
||||
hasAll={false}
|
||||
disabled={!values?.emotion_enabled && config.key !== 'emotion_enabled'}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
@@ -68,7 +68,7 @@ const TopCardList: FC<{data?: DataResponse}> = ({ data }) => {
|
||||
</Flex>
|
||||
|
||||
<div className="rb:mt-5 rb:font-[MiSans-Bold] rb:font-bold rb:text-[24px] rb:leading-8">
|
||||
{item.key === 'spaces' && String(data?.active_workspaces)}
|
||||
{item.key === 'spaces' && String(data?.active_workspaces || 0)}
|
||||
{item.key === 'running_apps' && String(data?.[`${item.key}` as keyof DataResponse] || item.value || 0)}
|
||||
{item.key !== 'spaces' && item.key !== 'running_apps' && String(data?.[`total_${item.key}` as keyof DataResponse] || item.value || 0)}
|
||||
</div>
|
||||
|
||||
@@ -6,22 +6,24 @@
|
||||
* @LastEditors: yujiangping
|
||||
* @LastEditTime: 2026-01-23 19:07:36
|
||||
*/
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useState, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Flex } from 'antd';
|
||||
|
||||
import { getVersion, type versionResponse } from '@/api/common'
|
||||
import Empty from '@/components/Empty';
|
||||
import { useI18n } from '@/store/locale';
|
||||
|
||||
const VersionCard: React.FC = () => {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
const { language } = useI18n()
|
||||
const [versionInfo, setVersionInfo] = useState<versionResponse | null>(null);
|
||||
|
||||
// 获取当前语言对应的介绍信息
|
||||
const getIntroduction = () => {
|
||||
const introduction = useMemo(() => {
|
||||
if (!versionInfo) return null;
|
||||
const currentLang = i18n.language;
|
||||
return currentLang === 'zh' ? versionInfo.introduction : (versionInfo.introduction_en || versionInfo.introduction);
|
||||
};
|
||||
return language === 'zh' ? versionInfo.introduction : (versionInfo.introduction_en || versionInfo.introduction);
|
||||
}, [versionInfo, language])
|
||||
|
||||
useEffect(() => {
|
||||
const fetchVersion = async () => {
|
||||
@@ -40,13 +42,14 @@ const VersionCard: React.FC = () => {
|
||||
<div className='rb:w-full rb:p-3 rb:bg-white rb:rounded-xl rb:mt-3'>
|
||||
<Flex gap={4} className="rb:mb-3">
|
||||
<span className="rb:font-[MiSans-Bold] rb:font-bold rb:leading-5">{t('index.latestUpdate')}</span>
|
||||
<span className='rb:text-[12px] rb:text-white rb:leading-4.25 rb:pt-px rb:pl-2 rb:pr-1.75 rb:bg-[#171719] rb:rounded-lg rb:rounded-bl-none '>
|
||||
{versionInfo?.version}
|
||||
</span>
|
||||
{versionInfo?.version &&
|
||||
<span className='rb:text-[12px] rb:text-white rb:leading-4.25 rb:pt-px rb:pl-2 rb:pr-1.75 rb:bg-[#171719] rb:rounded-lg rb:rounded-bl-none '>
|
||||
{versionInfo?.version}
|
||||
</span>
|
||||
}
|
||||
</Flex>
|
||||
{versionInfo && (() => {
|
||||
const introduction = getIntroduction();
|
||||
return introduction ? (<>
|
||||
{introduction
|
||||
? (<>
|
||||
<div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4.5 rb:mt-1 rb:mb-2">
|
||||
{t('version.releaseDate')}: {introduction.releaseDate} | {t('version.name')}: {introduction.codeName}
|
||||
</div>
|
||||
@@ -63,8 +66,9 @@ const VersionCard: React.FC = () => {
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</>) : null;
|
||||
})()}
|
||||
</>)
|
||||
: <Empty size={88} />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:30:11
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-19 15:38:38
|
||||
* @Last Modified time: 2026-03-25 11:40:38
|
||||
*/
|
||||
/**
|
||||
* Result Component
|
||||
@@ -382,7 +382,7 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
if (textPreprocessingTab === 'chunking') {
|
||||
if (textPreprocessingTab === 'chunking' && vo.content) {
|
||||
return (
|
||||
<div key={index} className="rb:leading-5">
|
||||
<div className="rb:font-medium">-{t('memoryExtractionEngine.fragment')}{vo.chunk_index}:</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:50:10
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 16:52:48
|
||||
* @Last Modified time: 2026-03-25 12:27:51
|
||||
*/
|
||||
/**
|
||||
* Model List View
|
||||
@@ -26,7 +26,7 @@ import { getListLogoUrl } from './utils'
|
||||
/**
|
||||
* Model list component
|
||||
*/
|
||||
const ModelList = forwardRef<BaseRef, { query: any; handleEdit: (vo?: ModelListItem) => void; }> (({ query, handleEdit }, ref) => {
|
||||
const ModelList = forwardRef<BaseRef, { query: any; handleEdit: (vo?: ModelListItem) => void; handleCloseModel: () => void; }>(({ query, handleEdit, handleCloseModel }, ref) => {
|
||||
const { t } = useTranslation();
|
||||
const keyConfigModalRef = useRef<KeyConfigModalRef>(null)
|
||||
const modelListDetailRef = useRef<ModelListDetailRef>(null)
|
||||
@@ -101,6 +101,7 @@ const ModelList = forwardRef<BaseRef, { query: any; handleEdit: (vo?: ModelListI
|
||||
ref={modelListDetailRef}
|
||||
refresh={getList}
|
||||
handleEdit={handleEdit}
|
||||
handleCloseConfig={handleCloseModel}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:50:14
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-23 11:33:44
|
||||
* @Last Modified time: 2026-03-25 12:19:24
|
||||
*/
|
||||
/**
|
||||
* Model Square View
|
||||
@@ -39,7 +39,9 @@ const ModelSquare = forwardRef <BaseRef, { query: any; }>(({ query }, ref) => {
|
||||
.then(res => {
|
||||
const response = res as ModelPlaza[]
|
||||
setList(response || [])
|
||||
setActiveProvider(response[0]?.provider || null)
|
||||
if (!activeProvider) {
|
||||
setActiveProvider(response[0]?.provider || null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:49:28
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 18:23:31
|
||||
* @Last Modified time: 2026-03-25 12:27:33
|
||||
*/
|
||||
/**
|
||||
* Custom Model Modal
|
||||
@@ -148,6 +148,7 @@ const CustomModelModal = forwardRef<CustomModelModalRef, CustomModelModalProps>(
|
||||
/** Expose methods to parent component */
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOpen,
|
||||
handleClose
|
||||
}));
|
||||
return (
|
||||
<RbModal
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:49:45
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 16:55:30
|
||||
* @Last Modified time: 2026-03-25 12:28:07
|
||||
*/
|
||||
/**
|
||||
* Model List Detail Drawer
|
||||
@@ -31,12 +31,13 @@ interface ModelListDetailProps {
|
||||
/** Callback to refresh parent list */
|
||||
refresh?: () => void;
|
||||
handleEdit: (vo?: ModelListItem) => void;
|
||||
handleCloseConfig?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Model list detail drawer component
|
||||
*/
|
||||
const ModelListDetail = forwardRef<ModelListDetailRef, ModelListDetailProps>(({ refresh, handleEdit }, ref) => {
|
||||
const ModelListDetail = forwardRef<ModelListDetailRef, ModelListDetailProps>(({ refresh, handleEdit, handleCloseConfig }, ref) => {
|
||||
const { t } = useTranslation();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [data, setData] = useState<ProviderModelItem>({} as ProviderModelItem)
|
||||
@@ -84,6 +85,8 @@ const ModelListDetail = forwardRef<ModelListDetailRef, ModelListDetailProps>(({
|
||||
setType(null)
|
||||
setOpen(false)
|
||||
refresh?.()
|
||||
multiKeyConfigModalRef.current?.handleClose()
|
||||
handleCloseConfig?.()
|
||||
}
|
||||
/** Refresh model list */
|
||||
const handleRefresh = () => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:49:55
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-11 15:11:06
|
||||
* @Last Modified time: 2026-03-25 12:24:41
|
||||
*/
|
||||
/**
|
||||
* Multi-Key Configuration Modal
|
||||
@@ -95,6 +95,7 @@ const MultiKeyConfigModal = forwardRef<MultiKeyConfigModalRef, MultiKeyConfigMod
|
||||
/** Expose methods to parent component */
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOpen,
|
||||
handleClose
|
||||
}));
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:50:05
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 19:02:31
|
||||
* @Last Modified time: 2026-03-25 12:28:07
|
||||
*/
|
||||
/**
|
||||
* Model Management Main Page
|
||||
@@ -134,7 +134,7 @@ const tabKeys = ['group', 'list', 'square']
|
||||
|
||||
<div className="rb:w-full rb:h-[calc(100vh-125px)] rb:overflow-y-auto">
|
||||
{activeTab === 'group' && <GroupModel ref={groupRef} query={query} handleEdit={handleEdit} />}
|
||||
{activeTab === 'list' && <ModelList ref={modelListRef} query={query} handleEdit={handleEdit} />}
|
||||
{activeTab === 'list' && <ModelList ref={modelListRef} query={query} handleEdit={handleEdit} handleCloseModel={() => customModelModalRef.current?.handleClose() } />}
|
||||
{activeTab === 'square' && <ModelSquare query={query} />}
|
||||
</div>
|
||||
<GroupModelModal
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:50:18
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 18:23:48
|
||||
* @Last Modified time: 2026-03-25 12:28:10
|
||||
*/
|
||||
/**
|
||||
* Type definitions for Model Management
|
||||
@@ -220,6 +220,7 @@ export interface MultiKeyForm {
|
||||
export interface MultiKeyConfigModalRef {
|
||||
/** Open modal with model data */
|
||||
handleOpen: (vo: ModelListItem, provider?: string) => void;
|
||||
handleClose: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,6 +304,7 @@ export interface CustomModelForm {
|
||||
export interface CustomModelModalRef {
|
||||
/** Open modal with optional model plaza item */
|
||||
handleOpen: (vo?: ModelListItem) => void;
|
||||
handleClose: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 14:10:15
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 16:36:02
|
||||
* @Last Modified time: 2026-03-25 13:38:59
|
||||
*/
|
||||
import { type FC, useState, useRef } from 'react';
|
||||
import type { MenuInfo } from 'rc-menu/lib/interface';
|
||||
@@ -164,7 +164,7 @@ const Ontology: FC = () => {
|
||||
}}
|
||||
placement="bottomRight"
|
||||
>
|
||||
<div className="rb:cursor-pointer rb:size-6 rb:bg-[url('@/assets/images/common/more.svg')] rb:hover:bg-[url('@/assets/images/common/more_hover.svg')]"></div>
|
||||
<div onClick={(e) => e.stopPropagation()} className="rb:cursor-pointer rb:size-6 rb:bg-[url('@/assets/images/common/more.svg')] rb:hover:bg-[url('@/assets/images/common/more_hover.svg')]"></div>
|
||||
</Dropdown>
|
||||
</Flex>
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 14:10:20
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 16:35:14
|
||||
* @Last Modified time: 2026-03-25 12:16:23
|
||||
*/
|
||||
import { type FC, useEffect, useState, useRef } from 'react'
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
@@ -122,7 +122,7 @@ const Detail: FC = () => {
|
||||
</Space>}
|
||||
/>
|
||||
|
||||
<div className="rb:h-[calc(100vh-64px)] rb:overflow-y-auto rb:pb-3 rb:px-3">
|
||||
<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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:46:47
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:54:45
|
||||
* @Last Modified time: 2026-03-25 11:44:16
|
||||
*/
|
||||
/**
|
||||
* Self Reflection Engine Configuration Page
|
||||
@@ -18,13 +18,12 @@ import { useTranslation } from 'react-i18next';
|
||||
import RbCard from '@/components/RbCard/Card';
|
||||
import { getMemoryReflectionConfig, updateMemoryReflectionConfig, pilotRunMemoryReflectionConfig } from '@/api/memory'
|
||||
import type { ConfigForm, Result, ReflexionData, MemoryVerify, QualityAssessment } from './types'
|
||||
import CustomSelect from '@/components/CustomSelect';
|
||||
import { getModelListUrl } from '@/api/models'
|
||||
import Tag from '@/components/Tag'
|
||||
import { useI18n } from '@/store/locale';
|
||||
import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
|
||||
import LabelWrapper from '@/components/FormItem/LabelWrapper'
|
||||
import DescWrapper from '@/components/FormItem/DescWrapper'
|
||||
import ModelSelect from '@/components/ModelSelect';
|
||||
|
||||
/** Configuration list */
|
||||
const configList = [
|
||||
@@ -36,9 +35,8 @@ const configList = [
|
||||
// Reflection model
|
||||
{
|
||||
key: 'reflection_model_id',
|
||||
type: 'customSelect',
|
||||
url: getModelListUrl,
|
||||
params: { type: 'chat,llm', page: 1, pagesize: 100, is_active: true }, // chat,llm
|
||||
type: 'modelSelect',
|
||||
params: { type: 'chat,llm' }, // chat,llm
|
||||
},
|
||||
// Iteration period
|
||||
{
|
||||
@@ -195,7 +193,7 @@ const SelfReflectionEngine: React.FC = () => {
|
||||
>
|
||||
<Flex vertical gap={24}>
|
||||
{configList.map(config => {
|
||||
if (config.type === 'customSelect') {
|
||||
if (config.type === 'modelSelect') {
|
||||
return (
|
||||
<div key={config.key}>
|
||||
<LabelWrapper title={t(`reflectionEngine.${config.key}`)} className="rb:mb-3">
|
||||
@@ -205,12 +203,8 @@ const SelfReflectionEngine: React.FC = () => {
|
||||
name={config.key}
|
||||
className="rb:mb-0!"
|
||||
>
|
||||
<CustomSelect
|
||||
url={config.url as string}
|
||||
<ModelSelect
|
||||
params={config.params}
|
||||
valueKey='id'
|
||||
labelKey='name'
|
||||
hasAll={false}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
disabled={!values?.reflection_enabled && config.key !== 'reflection_enabled'}
|
||||
/>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:49:09
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-03 17:49:09
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:45:54
|
||||
*/
|
||||
/**
|
||||
* Space Modal Component
|
||||
@@ -17,13 +17,12 @@ import type { SpaceModalData, SpaceModalRef, Space, StorageType } from '../types
|
||||
import RbModal from '@/components/RbModal'
|
||||
import { createWorkspace } from '@/api/workspaces'
|
||||
import RadioGroupCard from '@/components/RadioGroupCard'
|
||||
import { getModelListUrl } from '@/api/models'
|
||||
import CustomSelect from '@/components/CustomSelect'
|
||||
import UploadImages from '@/components/Upload/UploadImages'
|
||||
import { getFileLink } from '@/api/fileStorage'
|
||||
import ragIcon from '@/assets/images/space/rag.png'
|
||||
import neo4jIcon from '@/assets/images/space/neo4j.png'
|
||||
import { stringRegExp } from '@/utils/validator';
|
||||
import ModelSelect from '@/components/ModelSelect';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
@@ -206,12 +205,8 @@ const SpaceModal = forwardRef<SpaceModalRef, SpaceModalProps>(({
|
||||
name="llm"
|
||||
rules={[{ required: true, message: t('common.selectPlaceholder', { title: t('space.llmModel') }) }]}
|
||||
>
|
||||
<CustomSelect
|
||||
url={getModelListUrl}
|
||||
params={{ type: 'llm,chat', pagesize: 100, is_active: true }}
|
||||
valueKey="id"
|
||||
labelKey="name"
|
||||
hasAll={false}
|
||||
<ModelSelect
|
||||
params={{ type: 'llm,chat' }}
|
||||
placeholder={t('common.selectPlaceholder', { title: t('space.llmModel') })}
|
||||
className="rb:w-full!"
|
||||
/>
|
||||
@@ -221,12 +216,8 @@ const SpaceModal = forwardRef<SpaceModalRef, SpaceModalProps>(({
|
||||
name="embedding"
|
||||
rules={[{ required: true, message: t('common.selectPlaceholder', { title: t('space.embeddingModel') }) }]}
|
||||
>
|
||||
<CustomSelect
|
||||
url={getModelListUrl}
|
||||
params={{ type: 'embedding', pagesize: 100, is_active: true }}
|
||||
valueKey="id"
|
||||
labelKey="name"
|
||||
hasAll={false}
|
||||
<ModelSelect
|
||||
params={{ type: 'embedding' }}
|
||||
placeholder={t('common.selectPlaceholder', { title: t('space.embeddingModel') })}
|
||||
className="rb:w-full!"
|
||||
/>
|
||||
@@ -236,12 +227,8 @@ const SpaceModal = forwardRef<SpaceModalRef, SpaceModalProps>(({
|
||||
name="rerank"
|
||||
rules={[{ required: true, message: t('common.selectPlaceholder', { title: t('space.rerankModel') }) }]}
|
||||
>
|
||||
<CustomSelect
|
||||
url={getModelListUrl}
|
||||
params={{ type: 'rerank', pagesize: 100, is_active: true }}
|
||||
valueKey="id"
|
||||
labelKey="name"
|
||||
hasAll={false}
|
||||
<ModelSelect
|
||||
params={{ type: 'rerank' }}
|
||||
placeholder={t('common.selectPlaceholder', { title: t('space.rerankModel') })}
|
||||
className="rb:w-full!"
|
||||
/>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:51:08
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-23 12:14:51
|
||||
* @Last Modified time: 2026-03-25 10:41:25
|
||||
*/
|
||||
/**
|
||||
* User Management Page
|
||||
@@ -72,7 +72,7 @@ const UserManagement: React.FC = () => {
|
||||
className: 'rb:text-[#212332]'
|
||||
},
|
||||
{
|
||||
title: <>{t('user.username')}<div className="rb:text-[#5B6167] rb:text-[12px] rb:font-medium">({t(`user.subUsername`)})</div></>,
|
||||
title: <>{t('user.username')}<div>({t(`user.subUsername`)})</div></>,
|
||||
dataIndex: 'email',
|
||||
key: 'email',
|
||||
width: 210,
|
||||
@@ -121,7 +121,7 @@ const UserManagement: React.FC = () => {
|
||||
key: 'action',
|
||||
width: 137,
|
||||
render: (_, record) => (
|
||||
<Flex wrap>
|
||||
<Flex vertical justify="start" align="start">
|
||||
{record.is_active &&
|
||||
<Button
|
||||
type="link"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-16 15:00:07
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:00:07
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 12:09:39
|
||||
*/
|
||||
import { type FC, useRef, useState, useEffect } from 'react'
|
||||
import { Flex, Dropdown, type MenuProps, Slider } from 'antd'
|
||||
@@ -114,7 +114,7 @@ const AudioPlayer: FC<AudioPlayerProps> = ({ src, fileName, fileSize }) => {
|
||||
<Flex align="center" gap={12}>
|
||||
<div className="rb:w-7.5 rb:h-9 rb:bg-cover rb:bg-[url('@/assets/images/userMemory/mp3.svg')]" />
|
||||
<div className="rb:flex-1">
|
||||
<div className="rb:font-medium rb:leading-5 rb:text-[14px]">{fileName}</div>
|
||||
<div className="rb:font-medium rb:leading-5 rb:text-[14px] rb:wrap-break-word rb:line-clamp-1">{fileName}</div>
|
||||
<div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4.5">{fileSize || '-'}</div>
|
||||
</div>
|
||||
</Flex>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:32:23
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 11:36:22
|
||||
* @Last Modified time: 2026-03-25 12:09:53
|
||||
*/
|
||||
import { type FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -130,7 +130,7 @@ const PerceptualLastInfo: FC = () => {
|
||||
'rb:bg-[#F6F6F6]': type !== key
|
||||
})}
|
||||
onClick={() => setType(key)}
|
||||
>{key}</div>))}
|
||||
>{t(`perceptualDetail.${key}`)}</div>))}
|
||||
</Flex>
|
||||
{loading
|
||||
? <Skeleton active />
|
||||
@@ -147,7 +147,7 @@ const PerceptualLastInfo: FC = () => {
|
||||
<Flex gap={12} align="center">
|
||||
<div className="rb:w-7.5 rb:h-9 rb:bg-cover rb:bg-[url('@/assets/images/userMemory/file.svg')]"></div>
|
||||
<div>
|
||||
<div className="rb:leading-5 rb:font-medium rb:mb-1">{data.file_name}</div>
|
||||
<div className="rb:leading-5 rb:font-medium rb:mb-1 rb:wrap-break-word rb:line-clamp-1">{data.file_name}</div>
|
||||
<div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4.5">
|
||||
{fileSize || '-'}
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 18:31:50
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:02:00
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:50:16
|
||||
*/
|
||||
import { useEffect, useState, useRef, forwardRef, useImperativeHandle } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -83,7 +83,8 @@ const Suggestions = forwardRef<{ handleRefresh: () => void; }, { refresh: () =>
|
||||
title={t('statementDetail.suggestions')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[46px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[740px]"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-46px)]! rb:overflow-y-auto!"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
>
|
||||
{suggestions?.suggestions && suggestions?.suggestions.length > 0
|
||||
? <Flex vertical gap={16} className="rb:h-full! rb:overflow-y-auto!">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-01-07 20:37:34
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:07:50
|
||||
* @Last Modified time: 2026-03-25 12:05:26
|
||||
*/
|
||||
import { useEffect, useState, useMemo, forwardRef, useImperativeHandle, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -170,8 +170,8 @@ const ForgetDetail = forwardRef((_props, ref) => {
|
||||
<div className="rb:text-[18px] rb:font-[MiSans-Bold] rb:font-bold rb:leading-6">{data.activation_metrics?.low_activation_nodes ?? 0}</div>
|
||||
<div className="rb:text-[#5B6167] rb:text-[10px] rb:leading-3.5">{t('forgetDetail.low_nodes')}</div>
|
||||
|
||||
<div className="rb:bg-white rb:rounded-lg rb:mt-2">
|
||||
<div className="rb:h-29.5 rb:w-full rb:bg-cover rb:bg-[url('@/assets/images/userMemory/forget.png')]"></div>
|
||||
<div className="rb:bg-white rb:rounded-lg rb:mt-2 rb:h-29.5">
|
||||
<div className="rb:h-29.5 rb:w-full rb:bg-contain rb:bg-no-repeat rb:bg-center rb:bg-[url('@/assets/images/userMemory/forget.png')]"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-01-08 19:46:02
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 14:27:58
|
||||
* @Last Modified time: 2026-03-25 11:56:55
|
||||
*/
|
||||
import { forwardRef, useImperativeHandle, useRef, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -91,7 +91,7 @@ const ImplicitDetail = forwardRef<{ handleRefresh: () => void; }, { refresh: ()
|
||||
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-84px)]!"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
>
|
||||
<RadioGroupButton
|
||||
value={activeTab}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-01-12 14:42:02
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-16 15:10:17
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:55:36
|
||||
*/
|
||||
import { type FC, useEffect, useState, useMemo, useRef } from 'react'
|
||||
import clsx from 'clsx'
|
||||
@@ -157,34 +157,44 @@ const WorkingDetail: FC = () => {
|
||||
:(
|
||||
<Row gutter={16}>
|
||||
<Col span={5}>
|
||||
<div id="conversation-list" className="rb:h-[calc(100vh-76px)]! rb:border-r rb:border-[#EAECEE] rb:py-3 rb:px-4 rb:overflow-y-auto">
|
||||
<InfiniteScroll
|
||||
dataLength={data.length}
|
||||
next={loadMore}
|
||||
hasMore={hasMore}
|
||||
loader={null}
|
||||
scrollableTarget="conversation-list"
|
||||
>
|
||||
{data.map(item => (
|
||||
<Flex
|
||||
key={item.id}
|
||||
gap={12}
|
||||
align="center"
|
||||
className={clsx("rb:cursor-pointer rb:rounded-xl rb:h-12 rb:py-1! rb:px-3! rb:hover:bg-[#F6F6F6]", {
|
||||
'rb:bg-[#171719] rb:hover:bg-[#171719]! rb:text-white': item.id === selected?.id,
|
||||
})}
|
||||
onClick={() => setSelected(item)}
|
||||
>
|
||||
<div className="rb:size-6 rb:bg-cover rb:bg-[url('@/assets/images/userMemory/chat.svg')]"></div>
|
||||
<Tooltip title={item.title}>
|
||||
<div className="rb:leading-5 rb:wrap-break-word rb:line-clamp-2 rb:flex-1">
|
||||
{item.title}
|
||||
</div>
|
||||
</Tooltip>
|
||||
<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)]!"
|
||||
>
|
||||
<div id="conversation-list" className="rb:h-full! rb:overflow-y-auto">
|
||||
<InfiniteScroll
|
||||
dataLength={data.length}
|
||||
next={loadMore}
|
||||
hasMore={hasMore}
|
||||
loader={null}
|
||||
scrollableTarget="conversation-list"
|
||||
>
|
||||
<Flex vertical gap={8}>
|
||||
{data.map(item => (
|
||||
<Flex
|
||||
key={item.id}
|
||||
gap={12}
|
||||
align="center"
|
||||
className={clsx("rb:cursor-pointer rb:rounded-xl rb:h-12 rb:py-1! rb:px-3! rb:hover:bg-[#F6F6F6]", {
|
||||
'rb:bg-[#171719] rb:hover:bg-[#171719]! rb:text-white': item.id === selected?.id,
|
||||
})}
|
||||
onClick={() => setSelected(item)}
|
||||
>
|
||||
<div className="rb:size-6 rb:bg-cover rb:bg-[url('@/assets/images/userMemory/chat.svg')]"></div>
|
||||
<Tooltip title={item.title}>
|
||||
<div className="rb:leading-5 rb:break-all rb:line-clamp-2 rb:flex-1">
|
||||
{item.title}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
))}
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
</RbCard>
|
||||
</Col>
|
||||
{selected && <>
|
||||
<Col flex="auto" className="rb:h-full">
|
||||
@@ -193,7 +203,7 @@ const WorkingDetail: FC = () => {
|
||||
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-full!"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
>
|
||||
<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!">
|
||||
@@ -222,7 +232,7 @@ const WorkingDetail: FC = () => {
|
||||
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-full!"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
>
|
||||
{detailLoading
|
||||
? <Skeleton active />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-01-07 20:37:34
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 11:52:00
|
||||
* @Last Modified time: 2026-03-25 11:47:31
|
||||
*/
|
||||
import { type FC, useState, useMemo, useRef } from 'react'
|
||||
import { useParams, useNavigate } from 'react-router-dom'
|
||||
@@ -114,7 +114,7 @@ const Detail: FC = () => {
|
||||
</Space>
|
||||
}
|
||||
/>
|
||||
<div className="rb:h-[calc(100vh-64px)] rb:overflow-y-auto rb:px-3 rb:pb-3">
|
||||
<div className="rb:h-[calc(100vh-64px)] rb:overflow-y-auto rb:p-3">
|
||||
{type === 'EMOTIONAL_MEMORY' && <StatementDetail ref={statementDetailRef} refresh={handleRefresh} />}
|
||||
{type === 'FORGET_MEMORY' && <ForgetDetail ref={forgetDetailRef} />}
|
||||
{type === 'IMPLICIT_MEMORY' && <ImplicitDetail ref={implicitDetailRef} refresh={handleRefresh} />}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import type { FC } from 'react';
|
||||
import { Select, Divider } from 'antd';
|
||||
// import { Node } from '@antv/x6';
|
||||
import type { GraphRef } from '../types'
|
||||
import { PlusOutlined, MinusOutlined, FileAddOutlined } from '@ant-design/icons'
|
||||
import clsx from 'clsx'
|
||||
import { Node } from '@antv/x6';
|
||||
|
||||
import type { GraphRef } from '../types'
|
||||
|
||||
interface CanvasToolbarProps {
|
||||
/** Currently selected node */
|
||||
selectedNode: Node | null;
|
||||
miniMapRef: React.RefObject<HTMLDivElement>;
|
||||
graphRef: GraphRef;
|
||||
isHandMode: boolean;
|
||||
@@ -14,6 +18,7 @@ interface CanvasToolbarProps {
|
||||
}
|
||||
|
||||
const CanvasToolbar: FC<CanvasToolbarProps> = ({
|
||||
selectedNode,
|
||||
miniMapRef,
|
||||
graphRef,
|
||||
zoomLevel,
|
||||
@@ -26,9 +31,15 @@ const CanvasToolbar: FC<CanvasToolbarProps> = ({
|
||||
return (
|
||||
<>
|
||||
{/* 小地图 */}
|
||||
<div ref={miniMapRef} className="rb:absolute rb:bottom-15 rb:right-8 rb:z-1000 rb:rounded-lg rb:overflow-hidden"></div>
|
||||
<div ref={miniMapRef} className={clsx("rb:absolute rb:bottom-15 rb:z-1000 rb:rounded-lg rb:overflow-hidden", {
|
||||
'rb:right-8': !selectedNode,
|
||||
'rb:right-95.5': selectedNode,
|
||||
})}></div>
|
||||
{/* 缩放控制按钮 */}
|
||||
<div className="rb:h-8.5 rb:bg-[#FFFFFF] rb:border rb:border-[#DFE4ED] rb:rounded-lg rb:shadow-[0px_2px_6px_0px_rgba(33,35,50,0.15)] rb:px-3 rb:py-2 rb:absolute rb:bottom-5 rb:right-8 rb:flex rb:flex-row rb:items-center rb:gap-4 rb:z-1000">
|
||||
<div className={clsx("rb:h-8.5 rb:bg-[#FFFFFF] rb:border rb:border-[#DFE4ED] rb:rounded-lg rb:shadow-[0px_2px_6px_0px_rgba(33,35,50,0.15)] rb:px-3 rb:py-2 rb:absolute rb:bottom-5 rb:flex rb:flex-row rb:items-center rb:gap-4 rb:z-1000", {
|
||||
'rb:right-8': !selectedNode,
|
||||
'rb:right-95.5': selectedNode,
|
||||
})}>
|
||||
<MinusOutlined className="rb:text-[16px] rb:cursor-pointer" onClick={() => graphRef.current?.zoom(-0.1)} />
|
||||
<Select
|
||||
value={Math.round(zoomLevel * 100)}
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
border-color: rgba(91, 97, 103, 0.30);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.default:global(.ant-collapse .ant-collapse-content) {
|
||||
padding-top: 12px;
|
||||
}
|
||||
.collapse-item {
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2025-12-23 16:22:51
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-03 10:11:48
|
||||
* @Last Modified time: 2026-03-25 10:58:47
|
||||
*/
|
||||
import { type FC, useState, useEffect, useMemo } from 'react';
|
||||
import { LexicalComposer } from '@lexical/react/LexicalComposer';
|
||||
@@ -185,7 +185,7 @@ const Editor: FC<LexicalEditorProps> =({
|
||||
|
||||
// Calculate line height based on size prop
|
||||
const lineHeight = useMemo(() => {
|
||||
return `${height ? 16 : size === 'small' && variant === 'borderless' ? 18 : size === 'small' ? 16 : 20}px`
|
||||
return `${height ? height - 10 : size === 'small' && variant === 'borderless' ? 18 : size === 'small' ? 16 : 20}px`
|
||||
}, [size])
|
||||
|
||||
// Calculate placeholder minimum height
|
||||
@@ -228,7 +228,7 @@ const Editor: FC<LexicalEditorProps> =({
|
||||
<ContentEditable
|
||||
style={{
|
||||
minHeight: minheight,
|
||||
padding: height || variant === 'borderless' ? '0' : '6px 8px',
|
||||
padding: height ? '4px 6px' : variant === 'borderless' ? '0' : '6px 8px',
|
||||
border: variant === 'borderless' ? 'none' : '1px solid #EBEBEB',
|
||||
borderRadius: '8px',
|
||||
outline: 'none',
|
||||
|
||||
@@ -79,7 +79,7 @@ const ConditionNode: ReactShapeConfig['component'] = ({ node }) => {
|
||||
{item.expressions.length > 0 && <Flex vertical gap={2}>
|
||||
{item.expressions.map((expression: any, eIndex: number) => (
|
||||
<div key={eIndex} className="rb:relative">
|
||||
{item.expressions.length > 1 && eIndex > 0 && <div className="rb:absolute rb:-top-2 rb:right-2 rb:text-[10px] rb:text-[#155EEF] rb:font-medium rb:leading-3.5 rb:text-right rb:pr-0.5">{item.logical_operator.toLocaleUpperCase()}</div>}
|
||||
{item.expressions.length > 1 && eIndex > 0 && <div className="rb:absolute rb:-top-2 rb:right-2 rb:text-[10px] rb:text-[#155EEF] rb:font-medium rb:leading-3.5 rb:text-right rb:pr-0.5">{item.logical_operator?.toLocaleUpperCase()}</div>}
|
||||
<Flex align="center" className="rb:bg-[#F0F3F8] rb:shadow-[0px_2px_4px_0px_rgba(23,23,25,0.03)] rb:rounded-md rb:py-1! rb:px-1.5! rb:text-[10px] rb:text-[#5B6167] rb:font-medium rb:leading-3.5">
|
||||
{caculateIsSet(expression, 'cases')
|
||||
? <>
|
||||
|
||||
@@ -29,7 +29,7 @@ const ModelConfig: FC = () => {
|
||||
{model_id && (
|
||||
<RbCard
|
||||
title={t('workflow.config.llm.parameterSettings')}
|
||||
headerClassName="rb:min-h-8! rb:mx-2!"
|
||||
headerClassName="rb:min-h-8! rb:mx-2! rb:text-[12px]!"
|
||||
bodyClassName="rb:pt-[14px]! rb:px-2! rb:pb-2!"
|
||||
className="rb-border! rb:mb-4!"
|
||||
variant="outlined"
|
||||
|
||||
@@ -212,10 +212,11 @@ const ToolConfig: FC<{ options: Suggestion[]; }> = ({
|
||||
onChange={(value) => form.setFieldValue(['tool_parameters', parameter.name], value)}
|
||||
/>
|
||||
: <Editor
|
||||
height={32}
|
||||
variant="outlined"
|
||||
options={options}
|
||||
type="input"
|
||||
size="small"
|
||||
height={28}
|
||||
options={options}
|
||||
placeholder={t('common.pleaseEnter')}
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ const Workflow = forwardRef<WorkflowRef, { onFeaturesLoad?: (features: FeaturesC
|
||||
<div ref={containerRef} className="rb:w-full rb:h-full" />
|
||||
{/* 地图工具栏 */}
|
||||
<CanvasToolbar
|
||||
selectedNode={selectedNode}
|
||||
miniMapRef={miniMapRef}
|
||||
graphRef={graphRef}
|
||||
isHandMode={isHandMode}
|
||||
|
||||
Reference in New Issue
Block a user