fix(web): ui upgrade

This commit is contained in:
zhaoying
2026-03-25 13:58:25 +08:00
parent 9df41456f6
commit 2b9fd33bc8
42 changed files with 223 additions and 191 deletions

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-03-07 16:49:59 * @Date: 2026-03-07 16:49:59
* @Last Modified by: ZhaoYing * @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 { useEffect, useState, type FC } from 'react';
import { Select, Flex, Space } from 'antd'; import { Select, Flex, Space } from 'antd';
@@ -20,12 +20,16 @@ interface ModelSelectProps extends SelectProps {
params?: Query; params?: Query;
placeholder?: string; placeholder?: string;
fontClassName?: string; fontClassName?: string;
isAutoFetch?: boolean;
initialData?: Model[];
} }
const ModelSelect: FC<ModelSelectProps> = ({ const ModelSelect: FC<ModelSelectProps> = ({
params, params,
placeholder, placeholder,
fontClassName, fontClassName,
isAutoFetch = true,
initialData = [],
...props ...props
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -33,6 +37,7 @@ const ModelSelect: FC<ModelSelectProps> = ({
// Fetch active models whenever params change; stringify for stable deep comparison // Fetch active models whenever params change; stringify for stable deep comparison
useEffect(() => { useEffect(() => {
if (!isAutoFetch) return
getModelList({ getModelList({
...(params ?? {}), ...(params ?? {}),
pagesize: 100, pagesize: 100,
@@ -40,7 +45,7 @@ const ModelSelect: FC<ModelSelectProps> = ({
}).then((res) => { }).then((res) => {
setOptions((res as { items: Model[] }).items ?? []); setOptions((res as { items: Model[] }).items ?? []);
}); });
}, [JSON.stringify(params)]); }, [JSON.stringify(params), isAutoFetch]);
// Render the selected value inside the trigger with logo + truncated name // Render the selected value inside the trigger with logo + truncated name
const labelRender: SelectProps['labelRender'] = ({ value }) => { const labelRender: SelectProps['labelRender'] = ({ value }) => {
@@ -58,7 +63,7 @@ const ModelSelect: FC<ModelSelectProps> = ({
return ( return (
<Select <Select
placeholder={placeholder ?? t('common.pleaseSelect')} placeholder={placeholder ?? t('common.pleaseSelect')}
options={options} options={[...options, ...initialData]}
fieldNames={{ label: 'name', value: 'id' }} fieldNames={{ label: 'name', value: 'id' }}
allowClear allowClear
popupMatchSelectWidth={false} popupMatchSelectWidth={false}

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-02 15:24:23 * @Date: 2026-02-02 15:24:23
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-23 11:35:33 * @Last Modified time: 2026-03-25 11:15:26
*/ */
/** /**
* SearchInput Component * SearchInput Component
@@ -51,6 +51,7 @@ const SearchInput: FC<SearchInputProps> = ({
throttleDelay, throttleDelay,
defaultValue = undefined, defaultValue = undefined,
className = '', className = '',
variant = 'filled',
...props ...props
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -115,7 +116,8 @@ const SearchInput: FC<SearchInputProps> = ({
value={value} value={value}
onChange={handleChange} onChange={handleChange}
style={{ width: '300px' }} style={{ width: '300px' }}
className={`rb:border-none! ${className}`} className={className}
variant={variant}
{...props} {...props}
/> />
); );

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-02 15:25:31 * @Date: 2026-02-02 15:25:31
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-16 10:51:29 * @Last Modified time: 2026-03-25 12:32:58
*/ */
/** /**
* SiderMenu Component * SiderMenu Component
@@ -298,7 +298,10 @@ const Menu: FC<{
items={menuItems} items={menuItems}
inlineCollapsed={collapsed} inlineCollapsed={collapsed}
inlineIndent={10} 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 */} {/* Return to space button for superusers */}
{user?.is_superuser && source === 'space' && {user?.is_superuser && source === 'space' &&

View File

@@ -2801,6 +2801,7 @@ export const zh = {
}, },
prompt: { prompt: {
promptDesc: '输入您的原始提示词AI将帮助您优化为更专业的版本', promptDesc: '输入您的原始提示词AI将帮助您优化为更专业的版本',
chatTitle: '多轮对话',
editor: '提示词生成器', editor: '提示词生成器',
history: '我的历史', history: '我的历史',
historyDesc: '查看和管理您的提示词优化历史', historyDesc: '查看和管理您的提示词优化历史',

View File

@@ -351,6 +351,10 @@ body {
color: #212332; color: #212332;
background: #F6F6F6; background: #F6F6F6;
} }
.ant-input-filled,
.ant-select-filled:not(.ant-select-customize-input) .ant-select-selector {
background-color: #FFFFFF;
}
.ant-checkbox .ant-checkbox-inner { .ant-checkbox .ant-checkbox-inner {
border-radius: 6px !important; border-radius: 6px !important;
} }

View File

@@ -2,9 +2,9 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:29:21 * @Date: 2026-02-03 16:29:21
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-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 { useTranslation } from 'react-i18next'
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { Row, Col, Space, Form, Input, Button, App, Spin, Flex } from 'antd' import { Row, Col, Space, Form, Input, Button, App, Spin, Flex } from 'antd'
@@ -27,7 +27,7 @@ import type {
} from './types' } from './types'
import type { Variable } from './components/VariableList/types' import type { Variable } from './components/VariableList/types'
import type { KnowledgeConfig } from './components/Knowledge/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 { getModelList } from '@/api/models';
import { saveAgentConfig } from '@/api/application' import { saveAgentConfig } from '@/api/application'
import Knowledge from './components/Knowledge/Knowledge' import Knowledge from './components/Knowledge/Knowledge'
@@ -43,6 +43,7 @@ import type { Skill } from '@/views/Skills/types'
import SwitchFormItem from '@/components/FormItem/SwitchFormItem' import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
import DescWrapper from '@/components/FormItem/DescWrapper' import DescWrapper from '@/components/FormItem/DescWrapper'
import FeaturesConfig from './components/FeaturesConfig' import FeaturesConfig from './components/FeaturesConfig'
import { getListLogoUrl } from '@/views/ModelManagement/utils';
/** /**
* Agent configuration component * Agent configuration component
@@ -56,8 +57,8 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [data, setData] = useState<Config | null>(null); const [data, setData] = useState<Config | null>(null);
const modelConfigModalRef = useRef<ModelConfigModalRef>(null) const modelConfigModalRef = useRef<ModelConfigModalRef>(null)
const [modelList, setModelList] = useState<ModelListItem[]>([]) const [modelList, setModelList] = useState<Model[]>([])
const [defaultModel, setDefaultModel] = useState<ModelListItem | null>(null) const [defaultModel, setDefaultModel] = useState<Model | null>(null)
const [chatList, setChatList] = useState<ChatData[]>([]) const [chatList, setChatList] = useState<ChatData[]>([])
const values = Form.useWatch<Config>([], form) const values = Form.useWatch<Config>([], form)
const [isSave, setIsSave] = useState(false) const [isSave, setIsSave] = useState(false)
@@ -260,7 +261,7 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
const getModels = () => { const getModels = () => {
getModelList({ type: 'llm,chat', pagesize: 100, page: 1, is_active: true }) getModelList({ type: 'llm,chat', pagesize: 100, page: 1, is_active: true })
.then(res => { .then(res => {
const response = res as { items: ModelListItem[] } const response = res as { items: Model[] }
setModelList(response.items) setModelList(response.items)
}) })
} }
@@ -273,7 +274,7 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
useEffect(() => { useEffect(() => {
if (values?.default_model_config_id && modelList.length > 0) { if (values?.default_model_config_id && modelList.length > 0) {
const filterValue = modelList.find(item => item.id === values.default_model_config_id) const filterValue = modelList.find(item => item.id === values.default_model_config_id)
setDefaultModel(filterValue as ModelListItem | null) setDefaultModel(filterValue as Model | null)
setChatList([{ setChatList([{
label: filterValue?.name || '', label: filterValue?.name || '',
model_config_id: filterValue?.id || '', model_config_id: filterValue?.id || '',
@@ -343,7 +344,10 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
const handleSaveFeaturesConfig = (value: FeaturesConfigForm) => { const handleSaveFeaturesConfig = (value: FeaturesConfigForm) => {
form.setFieldValue('features', value) 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 ( return (
<> <>
{loading && <Spin fullscreen></Spin>} {loading && <Spin fullscreen></Spin>}
@@ -353,7 +357,10 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
<Flex gap={16} vertical> <Flex gap={16} vertical>
<Flex align="center" justify="space-between" className="rb:p-3! rb:bg-white rb:rounded-xl"> <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"> <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')} {defaultModel?.name || t('application.chooseModel')}
</Button> </Button>
<Space size={12}> <Space size={12}>
@@ -475,7 +482,6 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
</Row> </Row>
<ModelConfigModal <ModelConfigModal
modelList={modelList}
data={values} data={values}
ref={modelConfigModalRef} ref={modelConfigModalRef}
refresh={refresh} refresh={refresh}

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:29:29 * @Date: 2026-02-03 16:29:29
* @Last Modified by: ZhaoYing * @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 { type FC, useState, useRef, useEffect } from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
@@ -127,10 +127,10 @@ const Api: FC<{ application: Application | null }> = ({ application }) => {
<div className="rb:w-250 rb:mx-auto"> <div className="rb:w-250 rb:mx-auto">
<Flex gap={20} vertical> <Flex gap={20} vertical>
<RbCard <RbCard
title={<Flex align="center"> title={() => (<Flex align="center">
{t('application.endpointConfiguration')} {t('application.endpointConfiguration')}
<span className="rb:text-[#5B6167] rb:text-[12px]">({t('application.endpointConfigurationSubTitle')})</span> <span className="rb:text-[#5B6167] rb:text-[12px]">({t('application.endpointConfigurationSubTitle')})</span>
</Flex>} </Flex>)}
headerType="borderless" headerType="borderless"
headerClassName="rb:min-h-13.5!" headerClassName="rb:min-h-13.5!"
> >
@@ -157,10 +157,10 @@ const Api: FC<{ application: Application | null }> = ({ application }) => {
</Flex> </Flex>
</RbCard> </RbCard>
<RbCard <RbCard
title={<Flex align="center"> title={() => (<Flex align="center">
{t('application.apiKeys')} {t('application.apiKeys')}
<span className="rb:text-[#5B6167] rb:text-[12px]">({t('application.apiKeySubTitle')})</span> <span className="rb:text-[#5B6167] rb:text-[12px]">({t('application.apiKeySubTitle')})</span>
</Flex>} </Flex>)}
extra={ extra={
<Button style={{padding: '0 8px', height: '24px'}} onClick={handleAdd}>+ {t('application.addApiKey')}</Button> <Button style={{padding: '0 8px', height: '24px'}} onClick={handleAdd}>+ {t('application.addApiKey')}</Button>
} }

View File

@@ -19,7 +19,7 @@ import copy from 'copy-to-clipboard';
import { updatePromptMessages, createPromptSessions } from '@/api/prompt' import { updatePromptMessages, createPromptSessions } from '@/api/prompt'
import type { AiPromptModalRef, AiPromptVariableModalRef, AiPromptForm } from '../types' import type { AiPromptModalRef, AiPromptVariableModalRef, AiPromptForm } from '../types'
import RbModal from '@/components/RbModal' 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 ChatContent from '@/components/Chat/ChatContent'
import Empty from '@/components/Empty' import Empty from '@/components/Empty'
import ConversationEmptyIcon from '@/assets/images/conversation/conversationEmpty.svg' import ConversationEmptyIcon from '@/assets/images/conversation/conversationEmpty.svg'
@@ -37,7 +37,7 @@ interface AiPromptModalProps {
/** Callback to refresh prompt with optimized value */ /** Callback to refresh prompt with optimized value */
refresh: (value: string) => void; refresh: (value: string) => void;
/** Default model to pre-select */ /** Default model to pre-select */
defaultModel?: ModelListItem | null; defaultModel?: Model | null;
source?: 'application' | 'skills' source?: 'application' | 'skills'
} }

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:28:07 * @Date: 2026-02-03 16:28:07
* @Last Modified by: ZhaoYing * @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 * Model Configuration Modal
@@ -11,13 +11,14 @@
*/ */
import { forwardRef, useImperativeHandle, useState, useEffect } from 'react'; import { forwardRef, useImperativeHandle, useState, useEffect } from 'react';
import { Form, Select } from 'antd'; import { Form, type SelectProps } from 'antd';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import type { ModelConfig, ModelConfigModalRef, Config, Source } from '../types' 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 RbModal from '@/components/RbModal'
import RbSlider from '@/components/RbSlider' import RbSlider from '@/components/RbSlider'
import ModelSelect from '@/components/ModelSelect'
const FormItem = Form.Item; const FormItem = Form.Item;
@@ -25,8 +26,6 @@ const FormItem = Form.Item;
* Component props * Component props
*/ */
interface ModelConfigModalProps { interface ModelConfigModalProps {
/** List of available models */
modelList?: ModelListItem[];
/** Callback to update model configuration */ /** Callback to update model configuration */
refresh: (values: ModelConfig, type: Source) => void; refresh: (values: ModelConfig, type: Source) => void;
/** Application configuration data */ /** Application configuration data */
@@ -51,7 +50,6 @@ const configFields = [
const ModelConfigModal = forwardRef<ModelConfigModalRef, ModelConfigModalProps>(({ const ModelConfigModal = forwardRef<ModelConfigModalRef, ModelConfigModalProps>(({
refresh, refresh,
data, data,
modelList = []
}, ref) => { }, ref) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
@@ -102,11 +100,11 @@ const ModelConfigModal = forwardRef<ModelConfigModalRef, ModelConfigModalProps>(
}); });
} }
/** Handle model selection change */ /** Handle model selection change */
const handleChange = (_value: string, option: ModelListItem | ModelListItem[] | undefined) => { const handleChange: SelectProps['onChange'] = (_value, option) => {
if (source === 'chat') { if (source === 'chat') {
form.setFieldValue('label', (option as ModelListItem).name) form.setFieldValue('label', (option as Model).name)
} else { } 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'} hidden={source === 'multi_agent'}
> >
{source !== 'multi_agent' && {source !== 'multi_agent' &&
<Select <ModelSelect
placeholder={t('common.pleaseSelect')} placeholder={t('common.pleaseSelect')}
fieldNames={{
label: 'name',
value: 'id',
}}
options={modelList}
onChange={handleChange} onChange={handleChange}
/> />
} }

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-05 10:45:08 * @Date: 2026-02-05 10:45:08
* @Last Modified by: ZhaoYing * @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 { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import { List, Flex, Tooltip, Form } from 'antd'; import { List, Flex, Tooltip, Form } from 'antd';
@@ -169,6 +169,7 @@ const SkillListModal = forwardRef<SkillModalRef, SkillModalProps>(({
<SearchInput <SearchInput
placeholder={t('skills.searchPlaceholder')} placeholder={t('skills.searchPlaceholder')}
className="rb:w-full!" className="rb:w-full!"
variant="outlined"
/> />
</Form.Item> </Form.Item>
</Form> </Form>
@@ -181,9 +182,9 @@ const SkillListModal = forwardRef<SkillModalRef, SkillModalProps>(({
renderItem={(item: Skill) => ( renderItem={(item: Skill) => (
<List.Item> <List.Item>
{/* Skill card with selection state styling */} {/* 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]", { <div key={item.id} className={clsx("rb:border rb:rounded-lg rb:p-[17px_16px] rb:cursor-pointer rb:hover:bg-[#F6F6F6]", {
"rb:bg-[rgba(21,94,239,0.06)] rb:border-[#155EEF] rb:text-[#155EEF]": selectedIds.includes(item.id), "rb:border-[#171719]": selectedIds.includes(item.id),
"rb:border-[#DFE4ED] rb:text-[#212332]": !selectedIds.includes(item.id), "rb-border": !selectedIds.includes(item.id),
})} onClick={() => handleSelect(item)}> })} onClick={() => handleSelect(item)}>
{/* Skill name and description */} {/* Skill name and description */}
<div className="rb:flex-1 rb:max-w-[calc(100%-60px)]"> <div className="rb:flex-1 rb:max-w-[calc(100%-60px)]">
@@ -194,7 +195,7 @@ const SkillListModal = forwardRef<SkillModalRef, SkillModalProps>(({
</Tooltip> </Tooltip>
{/* Skill description with 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> <div className="rb:h-10 rb:leading-5 rb:wrap-break-word rb:line-clamp-2">{item.description}</div>
</Tooltip> </Tooltip>
</div> </div>

View File

@@ -2,11 +2,11 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:34:12 * @Date: 2026-02-03 16:34:12
* @Last Modified by: ZhaoYing * @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 React, { useState, useEffect, useMemo, type MouseEvent } from 'react';
import { useTranslation } from 'react-i18next'; 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 clsx from 'clsx';
import type { MySharedOutItem } from './types'; import type { MySharedOutItem } from './types';
@@ -112,9 +112,9 @@ const MySharing: React.FC = () => {
</Button> </Button>
), ),
children: ( children: (
<Row gutter={[12, 12]}> <div className="rb:grid rb:grid-cols-4 rb:gap-3">
{items.map(item => ( {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 <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')]" 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)} 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> <span>{item.source_app_is_active ? t('application.sourceActive') : t('application.sourceInactive')}</span>
</Flex> </Flex>
</Flex> </Flex>
</Col> </div>
))} ))}
</Row> </div>
), ),
}]} }]}
/> />
))} ))}
</BodyWrapper> </BodyWrapper>
</Flex> </Flex>
); );
}; };

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:34:12 * @Date: 2026-02-03 16:34:12
* @Last Modified by: ZhaoYing * @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 * Application Management Page
@@ -148,6 +148,7 @@ const ApplicationManagement: React.FC = () => {
label: t(`application.${type}`), label: t(`application.${type}`),
}))} }))}
allowClear allowClear
variant="filled"
className="rb:w-30!" className="rb:w-30!"
/> />
</Form.Item> </Form.Item>

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:56:54 * @Date: 2026-02-03 16:56:54
* @Last Modified by: ZhaoYing * @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 * Emotion Engine Configuration Page
@@ -19,13 +19,12 @@ import clsx from 'clsx';
import RbCard from '@/components/RbCard/Card'; import RbCard from '@/components/RbCard/Card';
import { getMemoryEmotionConfig, updateMemoryEmotionConfig } from '@/api/memory' import { getMemoryEmotionConfig, updateMemoryEmotionConfig } from '@/api/memory'
import type { ConfigForm } from './types' import type { ConfigForm } from './types'
import CustomSelect from '@/components/CustomSelect';
import { getModelListUrl } from '@/api/models'
import SwitchFormItem from '@/components/FormItem/SwitchFormItem' import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
import LabelWrapper from '@/components/FormItem/LabelWrapper' import LabelWrapper from '@/components/FormItem/LabelWrapper'
import DescWrapper from '@/components/FormItem/DescWrapper' import DescWrapper from '@/components/FormItem/DescWrapper'
import RbSlider from '@/components/RbSlider'; import RbSlider from '@/components/RbSlider';
import RbAlert from '@/components/RbAlert'; import RbAlert from '@/components/RbAlert';
import ModelSelect from '@/components/ModelSelect';
/** /**
* Configuration field definitions * Configuration field definitions
@@ -37,9 +36,8 @@ const configList = [
}, },
{ {
key: 'emotion_model_id', key: 'emotion_model_id',
type: 'customSelect', type: 'modelSelect',
url: getModelListUrl, params: { type: 'chat,llm' }, // chat,llm
params: { type: 'chat,llm', page: 1, pagesize: 100, is_active: true }, // chat,llm
}, },
{ {
key: 'emotion_min_intensity', key: 'emotion_min_intensity',
@@ -174,7 +172,7 @@ const EmotionEngine: React.FC = () => {
</div> </div>
) )
} }
if (config.type === 'customSelect') { if (config.type === 'modelSelect') {
return ( return (
<div key={config.key} className="rb:bg-[#F6F6F6] rb:rounded-xl rb:p-3"> <div key={config.key} className="rb:bg-[#F6F6F6] rb:rounded-xl rb:p-3">
<LabelWrapper title={t(`emotionEngine.${config.key}`)} className="rb:mb-3"> <LabelWrapper title={t(`emotionEngine.${config.key}`)} className="rb:mb-3">
@@ -184,12 +182,8 @@ const EmotionEngine: React.FC = () => {
name={config.key} name={config.key}
className="rb:mb-0!" className="rb:mb-0!"
> >
<CustomSelect <ModelSelect
url={config.url as string}
params={config.params} params={config.params}
valueKey='id'
labelKey='name'
hasAll={false}
disabled={!values?.emotion_enabled && config.key !== 'emotion_enabled'} disabled={!values?.emotion_enabled && config.key !== 'emotion_enabled'}
/> />
</Form.Item> </Form.Item>

View File

@@ -68,7 +68,7 @@ const TopCardList: FC<{data?: DataResponse}> = ({ data }) => {
</Flex> </Flex>
<div className="rb:mt-5 rb:font-[MiSans-Bold] rb:font-bold rb:text-[24px] rb:leading-8"> <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 === '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)} {item.key !== 'spaces' && item.key !== 'running_apps' && String(data?.[`total_${item.key}` as keyof DataResponse] || item.value || 0)}
</div> </div>

View File

@@ -6,22 +6,24 @@
* @LastEditors: yujiangping * @LastEditors: yujiangping
* @LastEditTime: 2026-01-23 19:07:36 * @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 { useTranslation } from 'react-i18next';
import { Flex } from 'antd'; import { Flex } from 'antd';
import { getVersion, type versionResponse } from '@/api/common' import { getVersion, type versionResponse } from '@/api/common'
import Empty from '@/components/Empty';
import { useI18n } from '@/store/locale';
const VersionCard: React.FC = () => { const VersionCard: React.FC = () => {
const { t, i18n } = useTranslation(); const { t } = useTranslation();
const { language } = useI18n()
const [versionInfo, setVersionInfo] = useState<versionResponse | null>(null); const [versionInfo, setVersionInfo] = useState<versionResponse | null>(null);
// 获取当前语言对应的介绍信息 // 获取当前语言对应的介绍信息
const getIntroduction = () => { const introduction = useMemo(() => {
if (!versionInfo) return null; if (!versionInfo) return null;
const currentLang = i18n.language; return language === 'zh' ? versionInfo.introduction : (versionInfo.introduction_en || versionInfo.introduction);
return currentLang === 'zh' ? versionInfo.introduction : (versionInfo.introduction_en || versionInfo.introduction); }, [versionInfo, language])
};
useEffect(() => { useEffect(() => {
const fetchVersion = async () => { 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'> <div className='rb:w-full rb:p-3 rb:bg-white rb:rounded-xl rb:mt-3'>
<Flex gap={4} className="rb:mb-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: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 &&
{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 '>
</span> {versionInfo?.version}
</span>
}
</Flex> </Flex>
{versionInfo && (() => { {introduction
const introduction = getIntroduction(); ? (<>
return introduction ? (<>
<div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4.5 rb:mt-1 rb:mb-2"> <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} {t('version.releaseDate')}: {introduction.releaseDate} | {t('version.name')}: {introduction.codeName}
</div> </div>
@@ -63,8 +66,9 @@ const VersionCard: React.FC = () => {
/> />
))} ))}
</div> </div>
</>) : null; </>)
})()} : <Empty size={88} />
}
</div> </div>
); );
}; };

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 17:30:11 * @Date: 2026-02-03 17:30:11
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-19 15:38:38 * @Last Modified time: 2026-03-25 11:40:38
*/ */
/** /**
* Result Component * Result Component
@@ -382,7 +382,7 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
))} ))}
</div> </div>
} }
if (textPreprocessingTab === 'chunking') { if (textPreprocessingTab === 'chunking' && vo.content) {
return ( return (
<div key={index} className="rb:leading-5"> <div key={index} className="rb:leading-5">
<div className="rb:font-medium">-{t('memoryExtractionEngine.fragment')}{vo.chunk_index}:</div> <div className="rb:font-medium">-{t('memoryExtractionEngine.fragment')}{vo.chunk_index}:</div>

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:50:10 * @Date: 2026-02-03 16:50:10
* @Last Modified by: ZhaoYing * @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 * Model List View
@@ -26,7 +26,7 @@ import { getListLogoUrl } from './utils'
/** /**
* Model list component * 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 { t } = useTranslation();
const keyConfigModalRef = useRef<KeyConfigModalRef>(null) const keyConfigModalRef = useRef<KeyConfigModalRef>(null)
const modelListDetailRef = useRef<ModelListDetailRef>(null) const modelListDetailRef = useRef<ModelListDetailRef>(null)
@@ -101,6 +101,7 @@ const ModelList = forwardRef<BaseRef, { query: any; handleEdit: (vo?: ModelListI
ref={modelListDetailRef} ref={modelListDetailRef}
refresh={getList} refresh={getList}
handleEdit={handleEdit} handleEdit={handleEdit}
handleCloseConfig={handleCloseModel}
/> />
</> </>
) )

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:50:14 * @Date: 2026-02-03 16:50:14
* @Last Modified by: ZhaoYing * @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 * Model Square View
@@ -39,7 +39,9 @@ const ModelSquare = forwardRef <BaseRef, { query: any; }>(({ query }, ref) => {
.then(res => { .then(res => {
const response = res as ModelPlaza[] const response = res as ModelPlaza[]
setList(response || []) setList(response || [])
setActiveProvider(response[0]?.provider || null) if (!activeProvider) {
setActiveProvider(response[0]?.provider || null)
}
}) })
} }

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:49:28 * @Date: 2026-02-03 16:49:28
* @Last Modified by: ZhaoYing * @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 * Custom Model Modal
@@ -148,6 +148,7 @@ const CustomModelModal = forwardRef<CustomModelModalRef, CustomModelModalProps>(
/** Expose methods to parent component */ /** Expose methods to parent component */
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
handleOpen, handleOpen,
handleClose
})); }));
return ( return (
<RbModal <RbModal

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:49:45 * @Date: 2026-02-03 16:49:45
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-24 16:55:30 * @Last Modified time: 2026-03-25 12:28:07
*/ */
/** /**
* Model List Detail Drawer * Model List Detail Drawer
@@ -31,12 +31,13 @@ interface ModelListDetailProps {
/** Callback to refresh parent list */ /** Callback to refresh parent list */
refresh?: () => void; refresh?: () => void;
handleEdit: (vo?: ModelListItem) => void; handleEdit: (vo?: ModelListItem) => void;
handleCloseConfig?: () => void;
} }
/** /**
* Model list detail drawer component * 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 { t } = useTranslation();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [data, setData] = useState<ProviderModelItem>({} as ProviderModelItem) const [data, setData] = useState<ProviderModelItem>({} as ProviderModelItem)
@@ -84,6 +85,8 @@ const ModelListDetail = forwardRef<ModelListDetailRef, ModelListDetailProps>(({
setType(null) setType(null)
setOpen(false) setOpen(false)
refresh?.() refresh?.()
multiKeyConfigModalRef.current?.handleClose()
handleCloseConfig?.()
} }
/** Refresh model list */ /** Refresh model list */
const handleRefresh = () => { const handleRefresh = () => {

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:49:55 * @Date: 2026-02-03 16:49:55
* @Last Modified by: ZhaoYing * @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 * Multi-Key Configuration Modal
@@ -95,6 +95,7 @@ const MultiKeyConfigModal = forwardRef<MultiKeyConfigModalRef, MultiKeyConfigMod
/** Expose methods to parent component */ /** Expose methods to parent component */
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
handleOpen, handleOpen,
handleClose
})); }));
return ( return (

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:50:05 * @Date: 2026-02-03 16:50:05
* @Last Modified by: ZhaoYing * @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 * 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"> <div className="rb:w-full rb:h-[calc(100vh-125px)] rb:overflow-y-auto">
{activeTab === 'group' && <GroupModel ref={groupRef} query={query} handleEdit={handleEdit} />} {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} />} {activeTab === 'square' && <ModelSquare query={query} />}
</div> </div>
<GroupModelModal <GroupModelModal

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 16:50:18 * @Date: 2026-02-03 16:50:18
* @Last Modified by: ZhaoYing * @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 * Type definitions for Model Management
@@ -220,6 +220,7 @@ export interface MultiKeyForm {
export interface MultiKeyConfigModalRef { export interface MultiKeyConfigModalRef {
/** Open modal with model data */ /** Open modal with model data */
handleOpen: (vo: ModelListItem, provider?: string) => void; handleOpen: (vo: ModelListItem, provider?: string) => void;
handleClose: () => void;
} }
/** /**
@@ -303,6 +304,7 @@ export interface CustomModelForm {
export interface CustomModelModalRef { export interface CustomModelModalRef {
/** Open modal with optional model plaza item */ /** Open modal with optional model plaza item */
handleOpen: (vo?: ModelListItem) => void; handleOpen: (vo?: ModelListItem) => void;
handleClose: () => void;
} }
/** /**

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 14:10:15 * @Date: 2026-02-03 14:10:15
* @Last Modified by: ZhaoYing * @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 FC, useState, useRef } from 'react';
import type { MenuInfo } from 'rc-menu/lib/interface'; import type { MenuInfo } from 'rc-menu/lib/interface';
@@ -164,7 +164,7 @@ const Ontology: FC = () => {
}} }}
placement="bottomRight" 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> </Dropdown>
</Flex> </Flex>
} }

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 14:10:20 * @Date: 2026-02-03 14:10:20
* @Last Modified by: ZhaoYing * @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 { type FC, useEffect, useState, useRef } from 'react'
import { useParams, useNavigate } from 'react-router-dom'; import { useParams, useNavigate } from 'react-router-dom';
@@ -122,7 +122,7 @@ const Detail: FC = () => {
</Space>} </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"> <Row gutter={12} className="rb:mb-4">
<Col span={6} offset={18}> <Col span={6} offset={18}>
<SearchInput <SearchInput

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 17:46:47 * @Date: 2026-02-03 17:46:47
* @Last Modified by: ZhaoYing * @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 * Self Reflection Engine Configuration Page
@@ -18,13 +18,12 @@ import { useTranslation } from 'react-i18next';
import RbCard from '@/components/RbCard/Card'; import RbCard from '@/components/RbCard/Card';
import { getMemoryReflectionConfig, updateMemoryReflectionConfig, pilotRunMemoryReflectionConfig } from '@/api/memory' import { getMemoryReflectionConfig, updateMemoryReflectionConfig, pilotRunMemoryReflectionConfig } from '@/api/memory'
import type { ConfigForm, Result, ReflexionData, MemoryVerify, QualityAssessment } from './types' 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 Tag from '@/components/Tag'
import { useI18n } from '@/store/locale'; import { useI18n } from '@/store/locale';
import SwitchFormItem from '@/components/FormItem/SwitchFormItem' import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
import LabelWrapper from '@/components/FormItem/LabelWrapper' import LabelWrapper from '@/components/FormItem/LabelWrapper'
import DescWrapper from '@/components/FormItem/DescWrapper' import DescWrapper from '@/components/FormItem/DescWrapper'
import ModelSelect from '@/components/ModelSelect';
/** Configuration list */ /** Configuration list */
const configList = [ const configList = [
@@ -36,9 +35,8 @@ const configList = [
// Reflection model // Reflection model
{ {
key: 'reflection_model_id', key: 'reflection_model_id',
type: 'customSelect', type: 'modelSelect',
url: getModelListUrl, params: { type: 'chat,llm' }, // chat,llm
params: { type: 'chat,llm', page: 1, pagesize: 100, is_active: true }, // chat,llm
}, },
// Iteration period // Iteration period
{ {
@@ -195,7 +193,7 @@ const SelfReflectionEngine: React.FC = () => {
> >
<Flex vertical gap={24}> <Flex vertical gap={24}>
{configList.map(config => { {configList.map(config => {
if (config.type === 'customSelect') { if (config.type === 'modelSelect') {
return ( return (
<div key={config.key}> <div key={config.key}>
<LabelWrapper title={t(`reflectionEngine.${config.key}`)} className="rb:mb-3"> <LabelWrapper title={t(`reflectionEngine.${config.key}`)} className="rb:mb-3">
@@ -205,12 +203,8 @@ const SelfReflectionEngine: React.FC = () => {
name={config.key} name={config.key}
className="rb:mb-0!" className="rb:mb-0!"
> >
<CustomSelect <ModelSelect
url={config.url as string}
params={config.params} params={config.params}
valueKey='id'
labelKey='name'
hasAll={false}
placeholder={t('common.pleaseSelect')} placeholder={t('common.pleaseSelect')}
disabled={!values?.reflection_enabled && config.key !== 'reflection_enabled'} disabled={!values?.reflection_enabled && config.key !== 'reflection_enabled'}
/> />

View File

@@ -1,8 +1,8 @@
/* /*
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 17:49:09 * @Date: 2026-02-03 17:49:09
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 17:49:09 * @Last Modified time: 2026-03-25 11:45:54
*/ */
/** /**
* Space Modal Component * Space Modal Component
@@ -17,13 +17,12 @@ import type { SpaceModalData, SpaceModalRef, Space, StorageType } from '../types
import RbModal from '@/components/RbModal' import RbModal from '@/components/RbModal'
import { createWorkspace } from '@/api/workspaces' import { createWorkspace } from '@/api/workspaces'
import RadioGroupCard from '@/components/RadioGroupCard' import RadioGroupCard from '@/components/RadioGroupCard'
import { getModelListUrl } from '@/api/models'
import CustomSelect from '@/components/CustomSelect'
import UploadImages from '@/components/Upload/UploadImages' import UploadImages from '@/components/Upload/UploadImages'
import { getFileLink } from '@/api/fileStorage' import { getFileLink } from '@/api/fileStorage'
import ragIcon from '@/assets/images/space/rag.png' import ragIcon from '@/assets/images/space/rag.png'
import neo4jIcon from '@/assets/images/space/neo4j.png' import neo4jIcon from '@/assets/images/space/neo4j.png'
import { stringRegExp } from '@/utils/validator'; import { stringRegExp } from '@/utils/validator';
import ModelSelect from '@/components/ModelSelect';
const FormItem = Form.Item; const FormItem = Form.Item;
@@ -206,12 +205,8 @@ const SpaceModal = forwardRef<SpaceModalRef, SpaceModalProps>(({
name="llm" name="llm"
rules={[{ required: true, message: t('common.selectPlaceholder', { title: t('space.llmModel') }) }]} rules={[{ required: true, message: t('common.selectPlaceholder', { title: t('space.llmModel') }) }]}
> >
<CustomSelect <ModelSelect
url={getModelListUrl} params={{ type: 'llm,chat' }}
params={{ type: 'llm,chat', pagesize: 100, is_active: true }}
valueKey="id"
labelKey="name"
hasAll={false}
placeholder={t('common.selectPlaceholder', { title: t('space.llmModel') })} placeholder={t('common.selectPlaceholder', { title: t('space.llmModel') })}
className="rb:w-full!" className="rb:w-full!"
/> />
@@ -221,12 +216,8 @@ const SpaceModal = forwardRef<SpaceModalRef, SpaceModalProps>(({
name="embedding" name="embedding"
rules={[{ required: true, message: t('common.selectPlaceholder', { title: t('space.embeddingModel') }) }]} rules={[{ required: true, message: t('common.selectPlaceholder', { title: t('space.embeddingModel') }) }]}
> >
<CustomSelect <ModelSelect
url={getModelListUrl} params={{ type: 'embedding' }}
params={{ type: 'embedding', pagesize: 100, is_active: true }}
valueKey="id"
labelKey="name"
hasAll={false}
placeholder={t('common.selectPlaceholder', { title: t('space.embeddingModel') })} placeholder={t('common.selectPlaceholder', { title: t('space.embeddingModel') })}
className="rb:w-full!" className="rb:w-full!"
/> />
@@ -236,12 +227,8 @@ const SpaceModal = forwardRef<SpaceModalRef, SpaceModalProps>(({
name="rerank" name="rerank"
rules={[{ required: true, message: t('common.selectPlaceholder', { title: t('space.rerankModel') }) }]} rules={[{ required: true, message: t('common.selectPlaceholder', { title: t('space.rerankModel') }) }]}
> >
<CustomSelect <ModelSelect
url={getModelListUrl} params={{ type: 'rerank' }}
params={{ type: 'rerank', pagesize: 100, is_active: true }}
valueKey="id"
labelKey="name"
hasAll={false}
placeholder={t('common.selectPlaceholder', { title: t('space.rerankModel') })} placeholder={t('common.selectPlaceholder', { title: t('space.rerankModel') })}
className="rb:w-full!" className="rb:w-full!"
/> />

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 17:51:08 * @Date: 2026-02-03 17:51:08
* @Last Modified by: ZhaoYing * @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 * User Management Page
@@ -72,7 +72,7 @@ const UserManagement: React.FC = () => {
className: 'rb:text-[#212332]' 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', dataIndex: 'email',
key: 'email', key: 'email',
width: 210, width: 210,
@@ -121,7 +121,7 @@ const UserManagement: React.FC = () => {
key: 'action', key: 'action',
width: 137, width: 137,
render: (_, record) => ( render: (_, record) => (
<Flex wrap> <Flex vertical justify="start" align="start">
{record.is_active && {record.is_active &&
<Button <Button
type="link" type="link"

View File

@@ -1,8 +1,8 @@
/* /*
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-03-16 15:00:07 * @Date: 2026-03-16 15:00:07
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-16 15:00:07 * @Last Modified time: 2026-03-25 12:09:39
*/ */
import { type FC, useRef, useState, useEffect } from 'react' import { type FC, useRef, useState, useEffect } from 'react'
import { Flex, Dropdown, type MenuProps, Slider } from 'antd' import { Flex, Dropdown, type MenuProps, Slider } from 'antd'
@@ -114,7 +114,7 @@ const AudioPlayer: FC<AudioPlayerProps> = ({ src, fileName, fileSize }) => {
<Flex align="center" gap={12}> <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: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: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 className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4.5">{fileSize || '-'}</div>
</div> </div>
</Flex> </Flex>

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 18:32:23 * @Date: 2026-02-03 18:32:23
* @Last Modified by: ZhaoYing * @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 { type FC, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
@@ -130,7 +130,7 @@ const PerceptualLastInfo: FC = () => {
'rb:bg-[#F6F6F6]': type !== key 'rb:bg-[#F6F6F6]': type !== key
})} })}
onClick={() => setType(key)} onClick={() => setType(key)}
>{key}</div>))} >{t(`perceptualDetail.${key}`)}</div>))}
</Flex> </Flex>
{loading {loading
? <Skeleton active /> ? <Skeleton active />
@@ -147,7 +147,7 @@ const PerceptualLastInfo: FC = () => {
<Flex gap={12} align="center"> <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 className="rb:w-7.5 rb:h-9 rb:bg-cover rb:bg-[url('@/assets/images/userMemory/file.svg')]"></div>
<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"> <div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4.5">
{fileSize || '-'} {fileSize || '-'}
</div> </div>

View File

@@ -1,8 +1,8 @@
/* /*
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 18:31:50 * @Date: 2026-02-03 18:31:50
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-16 15:02:00 * @Last Modified time: 2026-03-25 11:50:16
*/ */
import { useEffect, useState, useRef, forwardRef, useImperativeHandle } from 'react' import { useEffect, useState, useRef, forwardRef, useImperativeHandle } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
@@ -83,7 +83,8 @@ const Suggestions = forwardRef<{ handleRefresh: () => void; }, { refresh: () =>
title={t('statementDetail.suggestions')} title={t('statementDetail.suggestions')}
headerType="borderless" headerType="borderless"
headerClassName="rb:min-h-[46px]! rb:font-[MiSans-Bold] rb:font-bold" 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 {suggestions?.suggestions && suggestions?.suggestions.length > 0
? <Flex vertical gap={16} className="rb:h-full! rb:overflow-y-auto!"> ? <Flex vertical gap={16} className="rb:h-full! rb:overflow-y-auto!">

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-01-07 20:37:34 * @Date: 2026-01-07 20:37:34
* @Last Modified by: ZhaoYing * @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 { useEffect, useState, useMemo, forwardRef, useImperativeHandle, useRef } from 'react'
import { useTranslation } from 'react-i18next' 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-[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: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:bg-white rb:rounded-lg rb:mt-2 rb:h-29.5">
<div className="rb:h-29.5 rb:w-full rb:bg-cover rb:bg-[url('@/assets/images/userMemory/forget.png')]"></div> <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> </div>
</div> </div>

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-01-08 19:46:02 * @Date: 2026-01-08 19:46:02
* @Last Modified by: ZhaoYing * @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 { forwardRef, useImperativeHandle, useRef, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
@@ -91,7 +91,7 @@ const ImplicitDetail = forwardRef<{ handleRefresh: () => void; }, { refresh: ()
headerType="borderless" headerType="borderless"
headerClassName="rb:min-h-[50px]! rb:font-[MiSans-Bold] rb:font-bold" headerClassName="rb:min-h-[50px]! rb:font-[MiSans-Bold] rb:font-bold"
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-54px)]" 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 <RadioGroupButton
value={activeTab} value={activeTab}

View File

@@ -1,8 +1,8 @@
/* /*
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-01-12 14:42:02 * @Date: 2026-01-12 14:42:02
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-16 15:10:17 * @Last Modified time: 2026-03-25 11:55:36
*/ */
import { type FC, useEffect, useState, useMemo, useRef } from 'react' import { type FC, useEffect, useState, useMemo, useRef } from 'react'
import clsx from 'clsx' import clsx from 'clsx'
@@ -157,34 +157,44 @@ const WorkingDetail: FC = () => {
:( :(
<Row gutter={16}> <Row gutter={16}>
<Col span={5}> <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"> <RbCard
<InfiniteScroll title={t('workingDetail.conversation')}
dataLength={data.length} headerType="borderless"
next={loadMore} headerClassName="rb:min-h-[58px]! rb:font-[MiSans-Bold] rb:font-bold"
hasMore={hasMore} bodyClassName='rb:p-3! rb:pt-0! rb:h-[calc(100%-58px)]'
loader={null} className="rb:h-[calc(100vh-88px)]!"
scrollableTarget="conversation-list" >
> <div id="conversation-list" className="rb:h-full! rb:overflow-y-auto">
{data.map(item => ( <InfiniteScroll
<Flex dataLength={data.length}
key={item.id} next={loadMore}
gap={12} hasMore={hasMore}
align="center" loader={null}
className={clsx("rb:cursor-pointer rb:rounded-xl rb:h-12 rb:py-1! rb:px-3! rb:hover:bg-[#F6F6F6]", { scrollableTarget="conversation-list"
'rb:bg-[#171719] rb:hover:bg-[#171719]! rb:text-white': item.id === selected?.id, >
})} <Flex vertical gap={8}>
onClick={() => setSelected(item)} {data.map(item => (
> <Flex
<div className="rb:size-6 rb:bg-cover rb:bg-[url('@/assets/images/userMemory/chat.svg')]"></div> key={item.id}
<Tooltip title={item.title}> gap={12}
<div className="rb:leading-5 rb:wrap-break-word rb:line-clamp-2 rb:flex-1"> align="center"
{item.title} className={clsx("rb:cursor-pointer rb:rounded-xl rb:h-12 rb:py-1! rb:px-3! rb:hover:bg-[#F6F6F6]", {
</div> 'rb:bg-[#171719] rb:hover:bg-[#171719]! rb:text-white': item.id === selected?.id,
</Tooltip> })}
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> </Flex>
))} </InfiniteScroll>
</InfiniteScroll> </div>
</div> </RbCard>
</Col> </Col>
{selected && <> {selected && <>
<Col flex="auto" className="rb:h-full"> <Col flex="auto" className="rb:h-full">
@@ -193,7 +203,7 @@ const WorkingDetail: FC = () => {
headerType="borderless" headerType="borderless"
headerClassName="rb:min-h-[42px]! rb:pt-4! rb:font-[MiSans-Bold] rb:font-bold" 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)]' 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> <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!"> <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" headerType="borderless"
headerClassName="rb:min-h-[50px]! rb:font-[MiSans-Bold] rb:font-bold rb:leading-5.5" 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!' 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 {detailLoading
? <Skeleton active /> ? <Skeleton active />

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-01-07 20:37:34 * @Date: 2026-01-07 20:37:34
* @Last Modified by: ZhaoYing * @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 { type FC, useState, useMemo, useRef } from 'react'
import { useParams, useNavigate } from 'react-router-dom' import { useParams, useNavigate } from 'react-router-dom'
@@ -114,7 +114,7 @@ const Detail: FC = () => {
</Space> </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 === 'EMOTIONAL_MEMORY' && <StatementDetail ref={statementDetailRef} refresh={handleRefresh} />}
{type === 'FORGET_MEMORY' && <ForgetDetail ref={forgetDetailRef} />} {type === 'FORGET_MEMORY' && <ForgetDetail ref={forgetDetailRef} />}
{type === 'IMPLICIT_MEMORY' && <ImplicitDetail ref={implicitDetailRef} refresh={handleRefresh} />} {type === 'IMPLICIT_MEMORY' && <ImplicitDetail ref={implicitDetailRef} refresh={handleRefresh} />}

View File

@@ -1,10 +1,14 @@
import type { FC } from 'react'; import type { FC } from 'react';
import { Select, Divider } from 'antd'; import { Select, Divider } from 'antd';
// import { Node } from '@antv/x6';
import type { GraphRef } from '../types'
import { PlusOutlined, MinusOutlined, FileAddOutlined } from '@ant-design/icons' import { PlusOutlined, MinusOutlined, FileAddOutlined } from '@ant-design/icons'
import clsx from 'clsx'
import { Node } from '@antv/x6';
import type { GraphRef } from '../types'
interface CanvasToolbarProps { interface CanvasToolbarProps {
/** Currently selected node */
selectedNode: Node | null;
miniMapRef: React.RefObject<HTMLDivElement>; miniMapRef: React.RefObject<HTMLDivElement>;
graphRef: GraphRef; graphRef: GraphRef;
isHandMode: boolean; isHandMode: boolean;
@@ -14,6 +18,7 @@ interface CanvasToolbarProps {
} }
const CanvasToolbar: FC<CanvasToolbarProps> = ({ const CanvasToolbar: FC<CanvasToolbarProps> = ({
selectedNode,
miniMapRef, miniMapRef,
graphRef, graphRef,
zoomLevel, zoomLevel,
@@ -26,9 +31,15 @@ const CanvasToolbar: FC<CanvasToolbarProps> = ({
return ( 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)} /> <MinusOutlined className="rb:text-[16px] rb:cursor-pointer" onClick={() => graphRef.current?.zoom(-0.1)} />
<Select <Select
value={Math.round(zoomLevel * 100)} value={Math.round(zoomLevel * 100)}

View File

@@ -13,6 +13,9 @@
border-color: rgba(91, 97, 103, 0.30); border-color: rgba(91, 97, 103, 0.30);
border-radius: 8px; border-radius: 8px;
} }
.default:global(.ant-collapse .ant-collapse-content) {
padding-top: 12px;
}
.collapse-item { .collapse-item {
font-size: 12px; font-size: 12px;
line-height: 16px; line-height: 16px;

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2025-12-23 16:22:51 * @Date: 2025-12-23 16:22:51
* @Last Modified by: ZhaoYing * @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 { type FC, useState, useEffect, useMemo } from 'react';
import { LexicalComposer } from '@lexical/react/LexicalComposer'; import { LexicalComposer } from '@lexical/react/LexicalComposer';
@@ -185,7 +185,7 @@ const Editor: FC<LexicalEditorProps> =({
// Calculate line height based on size prop // Calculate line height based on size prop
const lineHeight = useMemo(() => { 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]) }, [size])
// Calculate placeholder minimum height // Calculate placeholder minimum height
@@ -228,7 +228,7 @@ const Editor: FC<LexicalEditorProps> =({
<ContentEditable <ContentEditable
style={{ style={{
minHeight: minheight, 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', border: variant === 'borderless' ? 'none' : '1px solid #EBEBEB',
borderRadius: '8px', borderRadius: '8px',
outline: 'none', outline: 'none',

View File

@@ -79,7 +79,7 @@ const ConditionNode: ReactShapeConfig['component'] = ({ node }) => {
{item.expressions.length > 0 && <Flex vertical gap={2}> {item.expressions.length > 0 && <Flex vertical gap={2}>
{item.expressions.map((expression: any, eIndex: number) => ( {item.expressions.map((expression: any, eIndex: number) => (
<div key={eIndex} className="rb:relative"> <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"> <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') {caculateIsSet(expression, 'cases')
? <> ? <>

View File

@@ -29,7 +29,7 @@ const ModelConfig: FC = () => {
{model_id && ( {model_id && (
<RbCard <RbCard
title={t('workflow.config.llm.parameterSettings')} 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!" bodyClassName="rb:pt-[14px]! rb:px-2! rb:pb-2!"
className="rb-border! rb:mb-4!" className="rb-border! rb:mb-4!"
variant="outlined" variant="outlined"

View File

@@ -212,10 +212,11 @@ const ToolConfig: FC<{ options: Suggestion[]; }> = ({
onChange={(value) => form.setFieldValue(['tool_parameters', parameter.name], value)} onChange={(value) => form.setFieldValue(['tool_parameters', parameter.name], value)}
/> />
: <Editor : <Editor
height={32}
variant="outlined" variant="outlined"
options={options} type="input"
size="small" size="small"
height={28}
options={options}
placeholder={t('common.pleaseEnter')} placeholder={t('common.pleaseEnter')}
/> />
} }

View File

@@ -73,6 +73,7 @@ const Workflow = forwardRef<WorkflowRef, { onFeaturesLoad?: (features: FeaturesC
<div ref={containerRef} className="rb:w-full rb:h-full" /> <div ref={containerRef} className="rb:w-full rb:h-full" />
{/* 地图工具栏 */} {/* 地图工具栏 */}
<CanvasToolbar <CanvasToolbar
selectedNode={selectedNode}
miniMapRef={miniMapRef} miniMapRef={miniMapRef}
graphRef={graphRef} graphRef={graphRef}
isHandMode={isHandMode} isHandMode={isHandMode}