feat(web): use bg replace img

This commit is contained in:
zhaoying
2026-04-01 12:03:56 +08:00
parent c9ca5df05c
commit d3cd66fc6e
30 changed files with 104 additions and 279 deletions

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>退出</title>
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="记忆库-个人记忆-遗忘记忆" transform="translate(-1357, -24)" stroke="#171719">
<g id="返回空间" transform="translate(1349, 16)">
<g id="退出" transform="translate(16, 16) scale(-1, 1) translate(-16, -16)translate(8, 8)">
<g id="编组-7" transform="translate(3.5, 2.5)">
<path d="M3.47826087,11 L1.8,11 C0.80588745,11 0,10.1941125 0,9.2 L0,1.8 C-2.22044605e-16,0.80588745 0.80588745,-2.22044605e-16 1.8,-4.4408921e-16 L3.47826087,0 L3.47826087,0" id="路径"></path>
<line x1="9.56521739" y1="5.5" x2="2.60869565" y2="5.5" id="路径-6"></line>
<polyline id="路径" points="7.82608696 3.20833333 10 5.5 7.82608696 7.79166667"></polyline>
</g>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -74,9 +74,9 @@ const ButtonCheckbox: FC<ButtonCheckboxProps> = ({
onClick={handleChange} onClick={handleChange}
> >
{/* Display unchecked icon when not checked */} {/* Display unchecked icon when not checked */}
{icon && !checked && <img src={icon} className="rb:size-4" />} {icon && !checked && <img src={icon} alt={icon} className="rb:size-4" />}
{/* Display checked icon when checked */} {/* Display checked icon when checked */}
{checkedIcon && checked && <img src={checkedIcon} className="rb:w-4 rb:h-4 rb:mr-1" />} {checkedIcon && checked && <img src={checkedIcon} alt={checkedIcon} className="rb:w-4 rb:h-4 rb:mr-1" />}
{children} {children}
</Flex> </Flex>
); );

View File

@@ -54,7 +54,7 @@ const ModelSelect: FC<ModelSelectProps> = ({
const logo = getListLogoUrl(item.provider, item.logo as string); const logo = getListLogoUrl(item.provider, item.logo as string);
return ( return (
<Flex align="center" gap={8}> <Flex align="center" gap={8}>
{logo && <img src={logo} className="rb:size-5 rb:rounded-md" alt="" />} {logo && <img src={logo} className="rb:size-5 rb:rounded-md" alt={logo} />}
<div className={`rb:flex-1 rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap ${fontClassName}`}>{item.name}</div> <div className={`rb:flex-1 rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap ${fontClassName}`}>{item.name}</div>
</Flex> </Flex>
); );
@@ -75,7 +75,7 @@ const ModelSelect: FC<ModelSelectProps> = ({
return ( return (
<Flex align="center" gap={8}> <Flex align="center" gap={8}>
<Flex align="center" gap={8}> <Flex align="center" gap={8}>
{logo && <img src={logo} className="rb:size-5 rb:rounded-md" alt="" />} {logo && <img src={logo} className="rb:size-5 rb:rounded-md" alt={logo} />}
<span className="rb:wrap-break-word rb:line-clamp-1">{data.name as string}</span> <span className="rb:wrap-break-word rb:line-clamp-1">{data.name as string}</span>
</Flex> </Flex>
{data.capability?.length > 0 && ( {data.capability?.length > 0 && (

View File

@@ -106,7 +106,7 @@ const RadioGroupCard: FC<RadioCardProps> = ({
{/* Use custom render or default card layout */} {/* Use custom render or default card layout */}
{itemRender ? itemRender(option) : ( {itemRender ? itemRender(option) : (
<> <>
{option.icon && <img src={option.icon} className={clsx("rb:size-10", { {option.icon && <img src={option.icon} alt={option.icon} className={clsx("rb:size-10", {
'rb:m-[0_auto] rb:mb-3': !block, 'rb:m-[0_auto] rb:mb-3': !block,
})} />} })} />}
<div> <div>

View File

@@ -44,7 +44,7 @@ const RbModal: FC<ModalProps> = ({
{...props} {...props}
> >
{/* Scrollable content container */} {/* Scrollable content container */}
<div className='rb:max-h-137.5 rb:overflow-y-auto rb:overflow-x-hidden'> <div className='rb:max-h-[calc(100vh-202px)] rb:overflow-y-auto rb:overflow-x-hidden'>
{children} {children}
</div> </div>
</Modal> </Modal>

View File

@@ -91,7 +91,7 @@ const RbTable = forwardRef(<T = Record<string, unknown>, Q = Record<string, unkn
initialData, initialData,
emptySize = 160, emptySize = 160,
emptyText, emptyText,
isScroll = false, isScroll = true,
scrollX, scrollX,
scrollY, scrollY,
currentPageKey = 'page', currentPageKey = 'page',

View File

@@ -405,7 +405,7 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
<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">
{modelLogo {modelLogo
? <img src={modelLogo} className="rb:size-4 rb:rounded-md" alt="" /> ? <img src={modelLogo} className="rb:size-4 rb:rounded-md" alt={modelLogo} />
: defaultModel?.name : defaultModel?.name
? <div className="rb:size-4 rb:bg-[url('@/assets/images/application/model.svg')]"></div> : null} ? <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')}

View File

@@ -12,10 +12,6 @@ import { useTranslation } from 'react-i18next';
import clsx from 'clsx'; import clsx from 'clsx';
import styles from '../index.module.css' import styles from '../index.module.css'
import editIcon from '@/assets/images/edit_hover.svg'
import copyIcon from '@/assets/images/copy_hover.svg'
import exportIcon from '@/assets/images/export_hover.svg'
import deleteIcon from '@/assets/images/delete_hover.svg'
import type { Application, ApplicationModalRef } from '@/views/ApplicationManagement/types'; import type { Application, ApplicationModalRef } from '@/views/ApplicationManagement/types';
import ApplicationModal from '@/views/ApplicationManagement/components/ApplicationModal' import ApplicationModal from '@/views/ApplicationManagement/components/ApplicationModal'
import type { CopyModalRef, AgentRef, ClusterRef, WorkflowRef, FeaturesConfigForm } from '../types' import type { CopyModalRef, AgentRef, ClusterRef, WorkflowRef, FeaturesConfigForm } from '../types'
@@ -38,10 +34,10 @@ const sharingTabKeys = [
* Menu icon mapping * Menu icon mapping
*/ */
const menuIcons: Record<string, string> = { const menuIcons: Record<string, string> = {
edit: editIcon, edit: "rb:bg-[url('@/assets/images/common/edit_bold.svg')]",
copy: copyIcon, copy: "rb:bg-[url('@/assets/images/copy_hover.svg')]",
export: exportIcon, export: "rb:bg-[url('@/assets/images/export_hover.svg')]",
delete: deleteIcon delete: "rb:bg-[url('@/assets/images/common/delete_red_big.svg')]"
} }
/** /**
@@ -70,7 +66,7 @@ interface ConfigHeaderProps {
* Configuration header component * Configuration header component
* Displays application name, tabs, and action buttons * Displays application name, tabs, and action buttons
*/ */
const ConfigHeader: FC<ConfigHeaderProps> = ({ const ConfigHeader: FC<ConfigHeaderProps> = ({
application, activeTab, handleChangeTab, refresh, application, activeTab, handleChangeTab, refresh,
workflowRef, workflowRef,
appRef, appRef,
@@ -172,7 +168,8 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
const formatMenuItems = useMemo(() => { const formatMenuItems = useMemo(() => {
const items = (application?.type !== 'multi_agent' ? ['edit', 'copy', 'export', 'delete'] : ['edit', 'copy', 'delete']).map(key => ({ const items = (application?.type !== 'multi_agent' ? ['edit', 'copy', 'export', 'delete'] : ['edit', 'copy', 'delete']).map(key => ({
key, key,
icon: <img src={menuIcons[key]} className="rb:w-4 rb:h-4 rb:mr-2" />, icon: <div className={`rb:size-4 rb:mr-2 ${menuIcons[key]}`} />,
danger: key === 'delete',
label: t(`common.${key}`), label: t(`common.${key}`),
})) }))
return items return items
@@ -182,7 +179,7 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
appRef?.current?.handleSaveFeaturesConfig?.(value) appRef?.current?.handleSaveFeaturesConfig?.(value)
onFeaturesChange?.(value) onFeaturesChange?.(value)
}, [appRef, onFeaturesChange]) }, [appRef, onFeaturesChange])
return ( return (
<> <>
<PageHeader <PageHeader
@@ -250,9 +247,9 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
</Popover> </Popover>
</Flex> </Flex>
: <Flex justify="flex-end"> : <Flex justify="flex-end">
<Flex align="center" className="rb:leading-5 rb:text-[14px] rb:text-[#5B6167] rb:font-regular rb:cursor-pointer" onClick={goToApplication}> <Flex align="center" gap={8} className="rb:leading-5 rb:text-[14px] rb:text-[#5B6167] rb:font-regular rb:cursor-pointer" onClick={goToApplication}>
<div <div
className="rb:mr-2 rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/logout.svg')]" className="rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/logout.svg')]"
></div> ></div>
{t('common.return')} {t('common.return')}
</Flex> </Flex>

View File

@@ -17,10 +17,6 @@ import { useNavigate } from 'react-router-dom';
import { Flex } from 'antd'; import { Flex } from 'antd';
import Card from './Card'; import Card from './Card';
import applicationIcon from '@/assets/images/home/application.svg';
import knowledgeIcon from '@/assets/images/home/knowledge.svg';
import memoryConversationIcon from '@/assets/images/home/memoryConversation.svg';
import helpCenterIcon from '@/assets/images/menu/helpCenter_active.svg'
/** Quick operation items configuration */ /** Quick operation items configuration */
const quickOperations = [ const quickOperations = [
@@ -37,12 +33,11 @@ const bgStyleList = [
'rb:bg-[rgba(77,168,255,0.1)]' 'rb:bg-[rgba(77,168,255,0.1)]'
] ]
/** Icon mapping for quick operations */ const quickOperationIconsClassNames: Record<string, string> = {
const quickOperationIcons: {[key: string]: string | undefined} = { createNewApplication: 'rb:bg-[url("@/assets/images/home/application.svg")]',
createNewApplication: applicationIcon, createNewKnowledge: 'rb:bg-[url("@/assets/images/home/knowledge.svg")]',
createNewKnowledge: knowledgeIcon, memoryConversation: 'rb:bg-[url("@/assets/images/home/memoryConversation.svg")]',
memoryConversation: memoryConversationIcon, helpCenter: 'rb:bg-[url("@/assets/images/menu/helpCenter_active.svg")]'
helpCenter: helpCenterIcon
} }
const QuickOperation:FC = () => { const QuickOperation:FC = () => {
const { t, i18n } = useTranslation() const { t, i18n } = useTranslation()
@@ -76,7 +71,7 @@ const QuickOperation:FC = () => {
{quickOperations.map((item, index) => ( {quickOperations.map((item, index) => (
<Flex key={item.key} align="center" gap={20} className={clsx("rb:relative rb:rounded-xl rb:py-2! rb:px-3! rb:cursor-pointer", bgStyleList[index])} onClick={() => handleJump(item.url)}> <Flex key={item.key} align="center" gap={20} className={clsx("rb:relative rb:rounded-xl rb:py-2! rb:px-3! rb:cursor-pointer", bgStyleList[index])} onClick={() => handleJump(item.url)}>
<div className="rb:size-8 rb:rounded-lg rb:p-1 rb:bg-[#FFFFFF]"> <div className="rb:size-8 rb:rounded-lg rb:p-1 rb:bg-[#FFFFFF]">
<img className="rb:size-6" src={quickOperationIcons[item.key]} /> <div className={`rb:size-6 rb:bg-cover ${quickOperationIconsClassNames[item.key]}`}></div>
</div> </div>
<div> <div>
<div className="rb:text-[14px] rb:leading-5 rb:font-medium">{t(`dashboard.${item.key}`)}</div> <div className="rb:text-[14px] rb:leading-5 rb:font-medium">{t(`dashboard.${item.key}`)}</div>

View File

@@ -15,10 +15,6 @@ import clsx from 'clsx'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Skeleton, Flex } from 'antd'; import { Skeleton, Flex } from 'antd';
import chunkCountIcon from '@/assets/images/home/chunk_count.svg';
import statementsCountIcon from '@/assets/images/home/statements_count.svg';
import tripletCountIcon from '@/assets/images/home/triplet_count.svg';
import temporalCountIcon from '@/assets/images/home/temporal_count.svg';
import activityEmpty from '@/assets/images/home/ActivityEmpty.svg' import activityEmpty from '@/assets/images/home/ActivityEmpty.svg'
import Empty from '@/components/Empty'; import Empty from '@/components/Empty';
import Card from './Card'; import Card from './Card';
@@ -49,10 +45,10 @@ interface RecentActivities {
/** Activity list configuration */ /** Activity list configuration */
const activityList = [ const activityList = [
{ key: 'chunk_count', icon: chunkCountIcon }, { key: 'chunk_count', iconClass: "rb:bg-[url('@/assets/images/home/chunk_count.svg')]" },
{ key: 'statements_count', icon: statementsCountIcon }, { key: 'statements_count', iconClass: "rb:bg-[url('@/assets/images/home/statements_count.svg')]" },
{ key: 'triplet_count', icon: tripletCountIcon }, { key: 'triplet_count', iconClass: "rb:bg-[url('@/assets/images/home/triplet_count.svg')]" },
{ key: 'temporal_count', icon: temporalCountIcon }, { key: 'temporal_count', iconClass: "rb:bg-[url('@/assets/images/home/temporal_count.svg')]" },
] ]
const RecentActivity:FC = () => { const RecentActivity:FC = () => {
@@ -89,7 +85,7 @@ const RecentActivity:FC = () => {
{activityList.map((item) => ( {activityList.map((item) => (
<Flex key={item.key} align="center" justify="space-between" className={clsx("rb:not-italic")}> <Flex key={item.key} align="center" justify="space-between" className={clsx("rb:not-italic")}>
<Flex align="center" gap={20}> <Flex align="center" gap={20}>
<img className="rb:size-10" src={item.icon} /> <div className={clsx("rb:size-6 rb:bg-cover", item.iconClass)}></div>
<div> <div>
<div className="rb:text-[16px] rb:leading-5.5 rb:font-medium">{t(`dashboard.${item.key}`)}</div> <div className="rb:text-[16px] rb:leading-5.5 rb:font-medium">{t(`dashboard.${item.key}`)}</div>
<div className="rb:text-[#7B8085] rb:text-[14px] rb:font-regular rb:mt-1 rb:leading-4.5"> <div className="rb:text-[#7B8085] rb:text-[14px] rb:font-regular rb:mt-1 rb:leading-4.5">

View File

@@ -2,13 +2,9 @@ import { type FC } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Flex } from 'antd' import { Flex } from 'antd'
import modelIcon from '@/assets/images/index/model_mgt.svg'
import spaceIcon from '@/assets/images/index/space_mgt.svg'
import userIcon from '@/assets/images/index/user_mgt.svg'
import helpCenterIcon from '@/assets/images/index/help_center.svg'
interface QuickAction { interface QuickAction {
key: string; key: string;
icon: string; iconClass: string;
title: string; title: string;
onClick?: () => void; onClick?: () => void;
} }
@@ -40,50 +36,25 @@ const QuickActions: FC<QuickActionsProps> = ({ onNavigate }) => {
const quickActions: QuickAction[] = [ const quickActions: QuickAction[] = [
{ {
key: 'model-management', key: 'model-management',
icon: modelIcon, iconClass: "rb:bg-[url('@/assets/images/index/model_mgt.svg')]",
title: t('quickActions.modelManagement'), title: t('quickActions.modelManagement'),
onClick: () => onNavigate?.('/model') onClick: () => onNavigate?.('/model')
}, },
{ {
key: 'space-management', key: 'space-management',
icon: spaceIcon, iconClass: "rb:bg-[url('@/assets/images/index/space_mgt.svg')]",
title: t('quickActions.spaceManagement'), title: t('quickActions.spaceManagement'),
onClick: () => onNavigate?.('/space') onClick: () => onNavigate?.('/space')
}, },
// {
// key: 'workflow-orchestration',
// icon: workflowIcon,
// title: t('quickActions.workflowOrchestration'),
// onClick: () => onNavigate?.('/workflow')
// },
{ {
key: 'user-management', key: 'user-management',
icon: userIcon, iconClass: "rb:bg-[url('@/assets/images/index/user_mgt.svg')]",
title: t('quickActions.userManagement'), title: t('quickActions.userManagement'),
onClick: () => onNavigate?.('/user-management') onClick: () => onNavigate?.('/user-management')
}, },
// {
// key: 'data-export',
// icon: dataExportIcon,
// title: t('quickActions.dataExport'),
// onClick: () => onNavigate?.('/')
// },
// {
// key: 'log-query',
// icon: logIcon,
// title: t('quickActions.logQuery'),
// onClick: () => onNavigate?.('/log')
// },
// {
// key: 'notification-reminder',
// icon: noteIcon,
// title: t('quickActions.notificationReminder'),
// onClick: () => onNavigate?.('/notification-reminder')
// },
{ {
key: 'help-center', key: 'help-center',
icon: helpCenterIcon, iconClass: "rb:bg-[url('@/assets/images/index/help_center.svg')]",
title: t('quickActions.helpCenter'), title: t('quickActions.helpCenter'),
onClick: openHelpCenter onClick: openHelpCenter
} }
@@ -105,7 +76,7 @@ const QuickActions: FC<QuickActionsProps> = ({ onNavigate }) => {
className="rb:cursor-pointer" className="rb:cursor-pointer"
onClick={action.onClick} onClick={action.onClick}
> >
<img src={action.icon} className='rb:size-10 rb:mx-auto' /> <div className={`rb:size-10 rb:mx-auto ${action.iconClass}`}></div>
<div className="rb:text-[12px] rb:max-w-18.25 rb:text-[#5B6167] rb:text-center rb:leading-3.5"> <div className="rb:text-[12px] rb:max-w-18.25 rb:text-[#5B6167] rb:text-center rb:leading-3.5">
{action.title} {action.title}
</div> </div>

View File

@@ -102,7 +102,7 @@ const Index = () => {
<Row gutter={12}> <Row gutter={12}>
<Col flex="1"> <Col flex="1">
<Flex vertical> <Flex vertical>
<div className='rb:w-full rb:h-26 rb:p-4 rb:bg-cover rb:bg-[url("@/assets/images/index/index_bg@2x.png")]'> <div className='rb:w-full rb:h-26 rb:p-4 rb:bg-cover rb:bg-[url("@/assets/images/index/index_bg@2x.png")] rb:rounded-xl rb:overflow-hidden'>
<div className="rb:font-[MiSans-Bold] rb:font-bold rb:text-white rb:text-[18px] rb:leading-7"> <div className="rb:font-[MiSans-Bold] rb:font-bold rb:text-white rb:text-[18px] rb:leading-7">
{t('index.spaceTitle')} {t('index.spaceTitle')}
</div> </div>

View File

@@ -54,7 +54,7 @@ const PageHeader: FC<ConfigHeaderProps> = ({
<div className="rb:flex rb:items-center rb:gap-3"> <div className="rb:flex rb:items-center rb:gap-3">
<Button type="primary" ghost className="rb:h-6! rb:px-2! rb:leading-5.5!" onClick={goBack}> <Button type="primary" ghost className="rb:h-6! rb:px-2! rb:leading-5.5!" onClick={goBack}>
<img src={logoutIcon} className="rb:w-4 rb:h-4" /> <div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/logout_hover.svg')]" />
{t('common.return')} {t('common.return')}
</Button> </Button>
{extra} {extra}

View File

@@ -16,8 +16,6 @@ import { Row, Col, Skeleton, Spin, Flex, Tooltip } from 'antd'
import { LoadingOutlined } from '@ant-design/icons'; import { LoadingOutlined } from '@ant-design/icons';
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import aboutUs from '@/assets/images/userMemory/aboutUs.svg'
import memoryInsight from '@/assets/images/userMemory/memoryInsight.svg'
import RbCard from '@/components/RbCard/Card' import RbCard from '@/components/RbCard/Card'
import type { Data } from './types' import type { Data } from './types'
import { import {
@@ -34,12 +32,12 @@ import ConversationMemory from './components/ConversationMemory'
*/ */
interface TitleProps { interface TitleProps {
title: string title: string
icon: string iconClassName: string
} }
/** Collapsible section title */ /** Collapsible section title */
const Title: FC<TitleProps> = ({ title, icon }) => ( const Title: FC<TitleProps> = ({ title, iconClassName }) => (
<Flex align="center" gap={4} className="rb:font-medium rb:leading-5 rb:mb-2.25!"> <Flex align="center" gap={4} className="rb:font-medium rb:leading-5 rb:mb-2.25!">
<img src={icon} className="rb:size-4.5 rb:ml-0.5" /> <div className={`rb:size-4.5 rb:ml-0.5 rb:bg-cover ${iconClassName}`} />
{title} {title}
</Flex> </Flex>
) )
@@ -143,7 +141,7 @@ const Rag: FC = () => {
<> <>
<Title <Title
title={t('userMemory.aboutMe')} title={t('userMemory.aboutMe')}
icon={aboutUs} iconClassName="rb:bg-[url('@/assets/images/userMemory/aboutUs.svg')]"
/> />
<div className="rb:bg-[#F6F6F6] rb:rounded-lg rb:py-2.5 rb:px-3 rb:mb-4"> <div className="rb:bg-[#F6F6F6] rb:rounded-lg rb:py-2.5 rb:px-3 rb:mb-4">
{loading.summary {loading.summary
@@ -160,7 +158,7 @@ const Rag: FC = () => {
<> <>
<Title <Title
title={t('userMemory.memoryInsight')} title={t('userMemory.memoryInsight')}
icon={memoryInsight} iconClassName="rb:bg-[url('@/assets/images/userMemory/memoryInsight.svg')]"
/> />
<div className="rb:bg-[#F6F6F6] rb:rounded-lg rb:py-2.5 rb:px-3"> <div className="rb:bg-[#F6F6F6] rb:rounded-lg rb:py-2.5 rb:px-3">
{loading.insight {loading.insight

View File

@@ -1,65 +0,0 @@
/*
* @Author: ZhaoYing
* @Date: 2026-02-03 18:32:30
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-02-03 18:32:30
*/
/**
* Page Header Component
* Header with navigation and operation buttons
*/
import { type FC, type ReactNode } from 'react';
import { useNavigate } from 'react-router-dom';
import { Layout, Button } from 'antd';
import { useTranslation } from 'react-i18next';
import logoutIcon from '@/assets/images/logout_hover.svg'
const { Header } = Layout;
/**
* Component props
*/
interface ConfigHeaderProps {
name?: string;
operation?: ReactNode;
source?: 'detail' | 'node';
extra?: ReactNode;
}
const PageHeader: FC<ConfigHeaderProps> = ({
name,
operation,
source = 'detail',
extra
}) => {
const { t } = useTranslation();
const navigate = useNavigate();
/** Navigate back */
const goBack = () => {
if (source === 'detail') {
navigate('/user-memory', { replace: true })
} else {
navigate(-1)
}
}
return (
<Header className="rb:w-full rb:h-16 rb:flex rb:justify-between rb:p-[16px_16px_16px_24px]! rb:border-b rb:border-[#EAECEE] rb:leading-8">
<div className="rb:h-8 rb:flex rb:items-center rb:font-medium">
{t('userMemory.memoryWindow', { name: name })}
{operation}
</div>
<div className="rb:flex rb:items-center rb:gap-3">
<Button type="primary" ghost className="rb:h-6! rb:px-2! rb:leading-5.5!" onClick={goBack}>
<img src={logoutIcon} className="rb:w-4 rb:h-4" />
{t('common.return')}
</Button>
{extra}
</div>
</Header>
);
};
export default PageHeader;

View File

@@ -104,7 +104,7 @@ const GraphDetail = forwardRef<GraphDetailRef>((_props, ref) => {
<Space size={12}> <Space size={12}>
<Button <Button
className="rb:px-2! rb:gap-0.5!" className="rb:px-2! rb:gap-0.5!"
icon={<div className="rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/common/return.svg')]"></div>} icon={<div className="rb:bg-[url('@/assets/images/workflow/return.svg')] rb:size-4 rb:bg-cover"></div>}
onClick={() => navigate(-1)} onClick={() => navigate(-1)}
> >
{t('common.return')} {t('common.return')}

View File

@@ -106,7 +106,7 @@ const Detail: FC = () => {
} }
<Button <Button
className="rb:px-2! rb:gap-0.5!" className="rb:px-2! rb:gap-0.5!"
icon={<div className="rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/common/return.svg')]"></div>} icon={<div className="rb:bg-[url('@/assets/images/workflow/return.svg')] rb:size-4 rb:bg-cover"></div>}
onClick={handleGoBack} onClick={handleGoBack}
> >
{t('common.return')} {t('common.return')}

View File

@@ -137,7 +137,7 @@ const Runtime: FC<{ item: ChatItem; index: number;}> = ({
key: vo.node_id, key: vo.node_id,
label: <div className={clsx("rb:flex rb:justify-between rb:items-center", getStatus(vo.status))}> label: <div className={clsx("rb:flex rb:justify-between rb:items-center", getStatus(vo.status))}>
<div className="rb:flex rb:items-center rb:gap-1 rb:flex-1"> <div className="rb:flex rb:items-center rb:gap-1 rb:flex-1">
{vo.icon && <img src={vo.icon} className="rb:size-4" />} {vo.icon && <div className={`rb:size-4 rb:bg-cover ${vo.icon}`} />}
<div className="rb:wrap-break-word rb:line-clamp-1">{vo.node_name}</div> <div className="rb:wrap-break-word rb:line-clamp-1">{vo.node_name}</div>
</div> </div>
<span> <span>

View File

@@ -45,11 +45,7 @@ const VariableComponent: React.FC<{ nodeKey: NodeKey; data: Suggestion }> = ({
{data.isContext ? ( {data.isContext ? (
<span style={{ fontSize: '12px', marginRight: '4px' }}>📄</span> <span style={{ fontSize: '12px', marginRight: '4px' }}>📄</span>
) : data.group !== 'CONVERSATION' ? ( ) : data.group !== 'CONVERSATION' ? (
<img <div className={`rb:size-4 rb:mr-1 rb:bg-cover ${data.nodeData?.icon}`} />
src={data.nodeData?.icon}
style={{ width: '12px', height: '12px', marginRight: '4px' }}
alt=""
/>
) : null} ) : null}
{!data.isContext && data.group !== 'CONVERSATION' && ( {!data.isContext && data.group !== 'CONVERSATION' && (
<> <>

View File

@@ -288,11 +288,7 @@ const AutocompletePlugin: FC<{ options: Suggestion[], enableJinja2?: boolean }>
return ( return (
<div key={nodeId}> <div key={nodeId}>
<Flex align="center" gap={4} className="rb:px-3! rb:text-[12px] rb:py-1.25! rb:font-medium rb:text-[#5B6167]"> <Flex align="center" gap={4} className="rb:px-3! rb:text-[12px] rb:py-1.25! rb:font-medium rb:text-[#5B6167]">
{nodeIcon && <img {nodeIcon && <div className={`rb:size-3 rb:bg-cover ${nodeIcon}`} />}
src={nodeIcon}
className="rb:size-3"
alt=""
/>}
{nodeName} {nodeName}
</Flex> </Flex>
{nodeOptions.map((option) => { {nodeOptions.map((option) => {

View File

@@ -49,7 +49,7 @@ const NodeLibrary: FC<{ collapsed: boolean; handleToggle: () => void }> = ({ col
e.dataTransfer.setData('application/json', JSON.stringify(node)); e.dataTransfer.setData('application/json', JSON.stringify(node));
}} }}
> >
<img src={node.icon} className="rb:size-6 rb:cursor-pointer" /> <div className={`rb:size-6 rb:cursor-pointer rb:bg-cover ${node.icon}`} />
</div> </div>
</Tooltip> </Tooltip>
)) ))
@@ -77,7 +77,7 @@ const NodeLibrary: FC<{ collapsed: boolean; handleToggle: () => void }> = ({ col
e.dataTransfer.setData('application/json', JSON.stringify(node)); e.dataTransfer.setData('application/json', JSON.stringify(node));
}} }}
> >
<img src={node.icon} className="rb:size-6" /> <div className={`rb:size-6 rb:bg-cover ${node.icon}`} />
<span className="rb:font-medium rb:text-[12px] rb:leading-4">{t(`workflow.${node.type}`)}</span> <span className="rb:font-medium rb:text-[12px] rb:leading-4">{t(`workflow.${node.type}`)}</span>
</Flex> </Flex>
))} ))}

View File

@@ -151,7 +151,7 @@ const AddNode: ReactShapeConfig['component'] = ({ node, graph }) => {
e.currentTarget.style.background = 'white'; e.currentTarget.style.background = 'white';
}} }}
> >
<img src={nodeType.icon} className="rb:w-4 rb:h-4" /> <div className={`rb:size-4 rb:bg-cover ${nodeType.icon}`} />
<span style={{ fontSize: '14px' }}>{t(`workflow.${nodeType.type}`)}</span> <span style={{ fontSize: '14px' }}>{t(`workflow.${nodeType.type}`)}</span>
</div> </div>
))} ))}

View File

@@ -52,7 +52,7 @@ const ConditionNode: ReactShapeConfig['component'] = ({ node }) => {
})}> })}>
<NodeTools node={node} /> <NodeTools node={node} />
<Flex align="center" gap={8} className="rb:flex-1"> <Flex align="center" gap={8} className="rb:flex-1">
<img src={data.icon} className="rb:size-6" /> <div className={`rb:size-6 rb:bg-cover ${data.icon}`} />
<div className="rb:wrap-break-word rb:line-clamp-1">{data.name ?? t(`workflow.${data.type}`)}</div> <div className="rb:wrap-break-word rb:line-clamp-1">{data.name ?? t(`workflow.${data.type}`)}</div>
</Flex> </Flex>

View File

@@ -126,7 +126,7 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
})}> })}>
<NodeTools node={node} /> <NodeTools node={node} />
<Flex align="center" gap={8} className="rb:flex-1"> <Flex align="center" gap={8} className="rb:flex-1">
<img src={data.icon} className="rb:size-6" /> <div className={`rb:size-6 rb:bg-cover ${data.icon}`} />
<div className="rb:wrap-break-word rb:line-clamp-1">{data.name ?? t(`workflow.${data.type}`)}</div> <div className="rb:wrap-break-word rb:line-clamp-1">{data.name ?? t(`workflow.${data.type}`)}</div>
</Flex> </Flex>
<div className="rb:mt-3 rb:min-h-[calc(100%-36px)] rb:w-full rb:bg-[radial-gradient(circle,#939AB1_1px,#F0F3F8_1px)] rb:shadow-[0px_2px_4px_0px_rgba(23,23,25,0.03)] rb:rounded-[10px] rb:bg-size-[12px_12px]"></div> <div className="rb:mt-3 rb:min-h-[calc(100%-36px)] rb:w-full rb:bg-[radial-gradient(circle,#939AB1_1px,#F0F3F8_1px)] rb:shadow-[0px_2px_4px_0px_rgba(23,23,25,0.03)] rb:rounded-[10px] rb:bg-size-[12px_12px]"></div>

View File

@@ -16,7 +16,7 @@ const NormalNode: ReactShapeConfig['component'] = ({ node }) => {
})}> })}>
<NodeTools node={node} /> <NodeTools node={node} />
<Flex align="center" gap={8} className="rb:flex-1"> <Flex align="center" gap={8} className="rb:flex-1">
<img src={data.icon} className="rb:size-6" /> <div className={`rb:size-6 rb:bg-cover ${data.icon}`} />
<div className="rb:wrap-break-word rb:line-clamp-1">{data.name ?? t(`workflow.${data.type}`)}</div> <div className="rb:wrap-break-word rb:line-clamp-1">{data.name ?? t(`workflow.${data.type}`)}</div>
</Flex> </Flex>

View File

@@ -5,7 +5,7 @@
* @Last Modified time: 2026-03-30 15:14:02 * @Last Modified time: 2026-03-30 15:14:02
*/ */
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Popover } from 'antd'; import { Flex, Popover } from 'antd';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { nodeLibrary, graphNodeLibrary, edgeAttrs, nodeWidth } from '../constant'; import { nodeLibrary, graphNodeLibrary, edgeAttrs, nodeWidth } from '../constant';
@@ -286,21 +286,16 @@ const PortClickHandler: React.FC<PortClickHandlerProps> = ({ graph }) => {
}; };
const content = ( const content = (
<div style={{ maxHeight: '300px', overflowY: 'auto', minWidth: `${nodeWidth}px` }}> <Flex vertical gap={16} className="rb:max-h-[300px] rb:overflow-y-auto rb:p-3" style={{ minWidth: `${nodeWidth}px` }}>
{nodeLibrary.map((category, categoryIndex) => { {nodeLibrary.map((category) => {
const sourceNodeData = sourceNode?.getData(); const sourceNodeData = sourceNode?.getData();
const isChildOfLoop = sourceNodeData?.cycle && graph?.getNodes().find((n: any) => n.getData()?.id === sourceNodeData.cycle && n.getData()?.type === 'loop'); const isChildOfLoop = sourceNodeData?.cycle && graph?.getNodes().find((n: any) => n.getData()?.id === sourceNodeData.cycle && n.getData()?.type === 'loop');
const isChildOfIteration = sourceNodeData?.cycle && graph?.getNodes().find((n: any) => n.getData()?.id === sourceNodeData.cycle && n.getData()?.type === 'iteration'); const isChildOfIteration = sourceNodeData?.cycle && graph?.getNodes().find((n: any) => n.getData()?.id === sourceNodeData.cycle && n.getData()?.type === 'iteration');
let filteredNodes; let filteredNodes;
if (isChildOfLoop) { if (isChildOfLoop || isChildOfIteration) {
// Use same filtering as AddNode for child nodes of loop, but allow break
filteredNodes = category.nodes.filter(nodeType => !['start', 'end', 'loop', 'cycle-start', 'iteration'].includes(nodeType.type));
} else if (isChildOfIteration) {
// Filter out loop and iteration nodes for children of iteration nodes, but allow break
filteredNodes = category.nodes.filter(nodeType => !['start', 'end', 'loop', 'cycle-start', 'iteration'].includes(nodeType.type)); filteredNodes = category.nodes.filter(nodeType => !['start', 'end', 'loop', 'cycle-start', 'iteration'].includes(nodeType.type));
} else { } else {
// Original filtering for non-loop child nodes
filteredNodes = category.nodes.filter(nodeType => filteredNodes = category.nodes.filter(nodeType =>
nodeType.type !== 'start' && nodeType.type !== 'cycle-start' && nodeType.type !== 'break' nodeType.type !== 'start' && nodeType.type !== 'cycle-start' && nodeType.type !== 'break'
); );
@@ -310,36 +305,27 @@ const PortClickHandler: React.FC<PortClickHandlerProps> = ({ graph }) => {
return ( return (
<div key={category.category}> <div key={category.category}>
{categoryIndex > 0 && <div style={{ height: '1px', background: '#f0f0f0', margin: '4px 0' }} />} <div className="rb:font-semibold rb:mb-2 rb:text-[12px] rb:leading-4.5 rb:pl-1">
<div style={{ padding: '4px 12px', fontSize: '12px', color: '#999', fontWeight: 'bold' }}>
{t(`workflow.${category.category}`)} {t(`workflow.${category.category}`)}
</div> </div>
{filteredNodes.map((nodeType) => ( <Flex gap={6} vertical>
<div {filteredNodes.map((nodeType) => (
key={nodeType.type} <Flex
style={{ key={nodeType.type}
padding: '8px 12px', align="center"
cursor: 'pointer', gap={8}
display: 'flex', className="rb:rounded-xl rb:p-2! rb:border rb:border-[#EBEBEB] rb:cursor-pointer rb:hover:border rb:hover:border-[#171719]!"
alignItems: 'center', onClick={() => handleNodeSelect(nodeType)}
gap: '8px', >
}} <div className={`rb:size-6 rb:bg-cover ${nodeType.icon}`} />
onClick={() => handleNodeSelect(nodeType)} <span className="rb:font-medium rb:text-[12px] rb:leading-4">{t(`workflow.${nodeType.type}`)}</span>
onMouseEnter={(e) => { </Flex>
e.currentTarget.style.background = '#f0f8ff'; ))}
}} </Flex>
onMouseLeave={(e) => {
e.currentTarget.style.background = 'white';
}}
>
<img src={nodeType.icon} className="rb:w-4 rb:h-4" />
<span style={{ fontSize: '14px' }}>{t(`workflow.${nodeType.type}`)}</span>
</div>
))}
</div> </div>
); );
})} })}
</div> </Flex>
); );
if (!tempElement) return null; if (!tempElement) return null;

View File

@@ -73,11 +73,7 @@ const VariableSelect: FC<VariableSelectProps> = ({
> >
{filterOption.nodeData?.icon && filterOption.nodeData?.name && ( {filterOption.nodeData?.icon && filterOption.nodeData?.name && (
<> <>
<img <div className={`rb:size-3 rb:mr-1 rb:bg-cover ${filterOption.nodeData.icon}`} />
src={filterOption.nodeData.icon}
style={{ width: '12px', height: '12px', marginRight: '4px' }}
alt=""
/>
{filterOption.nodeData.name} {filterOption.nodeData.name}
<span className="rb:text-[#DFE4ED] rb:mx-0.5">/</span> <span className="rb:text-[#DFE4ED] rb:mx-0.5">/</span>
</> </>
@@ -111,11 +107,7 @@ const VariableSelect: FC<VariableSelectProps> = ({
*/ */
const groupedOptions = Object.entries(groupedSuggestions).map(([_nodeId, suggestions]) => ({ const groupedOptions = Object.entries(groupedSuggestions).map(([_nodeId, suggestions]) => ({
label: <Flex align="center" gap={4}> label: <Flex align="center" gap={4}>
{suggestions[0].nodeData.icon && <img {suggestions[0].nodeData.icon && <div className={`rb:size-3 ${suggestions[0].nodeData.icon}`} />}
src={suggestions[0].nodeData.icon}
className="rb:size-3"
alt=""
/>}
{suggestions[0].nodeData.name} {suggestions[0].nodeData.name}
</Flex>, </Flex>,
options: suggestions.map(s => ({ options: suggestions.map(s => ({

View File

@@ -474,7 +474,7 @@ const Properties: FC<PropertiesProps> = ({
label: t(`workflow.${category.category}`), label: t(`workflow.${category.category}`),
options: category.nodes.filter(item => !['cycle-start', 'break'].includes(item.type)).map(node => ({ options: category.nodes.filter(item => !['cycle-start', 'break'].includes(item.type)).map(node => ({
label: <div className="rb:flex rb:items-center rb:gap-2 rb:flex-1"> label: <div className="rb:flex rb:items-center rb:gap-2 rb:flex-1">
<img src={node.icon} className="rb:size-3.5" /> <div className={`rb:size-3.5 rb:bg-cover ${node.icon}`} />
<div className="rb:wrap-break-word rb:line-clamp-1">{t(`workflow.${node.type}`)}</div> <div className="rb:wrap-break-word rb:line-clamp-1">{t(`workflow.${node.type}`)}</div>
</div>, </div>,
value: node.type value: node.type

View File

@@ -13,28 +13,6 @@ import NoteNode from './components/Nodes/NoteNode';
import type { PortMetadata, GroupMetadata } from '@antv/x6/lib/model/port'; import type { PortMetadata, GroupMetadata } from '@antv/x6/lib/model/port';
import type { ReactShapeConfig } from '@antv/x6-react-shape'; import type { ReactShapeConfig } from '@antv/x6-react-shape';
// Import workflow icons
import startIcon from '@/assets/images/workflow/start.svg';
import endIcon from '@/assets/images/workflow/end.svg';
import llmIcon from '@/assets/images/workflow/llm.svg';
import ragIcon from '@/assets/images/workflow/rag.svg';
import parameterExtractionIcon from '@/assets/images/workflow/parameter_extraction.svg';
import conditionIcon from '@/assets/images/workflow/condition.svg';
import iterationIcon from '@/assets/images/workflow/iteration.svg';
import loopIcon from '@/assets/images/workflow/loop.svg';
import aggregatorIcon from '@/assets/images/workflow/aggregator.svg';
import httpRequestIcon from '@/assets/images/workflow/http_request.svg';
import toolsIcon from '@/assets/images/workflow/tools.svg';
import codeExecutionIcon from '@/assets/images/workflow/code_execution.svg';
import templateRenderingIcon from '@/assets/images/workflow/template_rendering.svg';
import questionClassifierIcon from '@/assets/images/workflow/question-classifier.svg'
import breakIcon from '@/assets/images/workflow/break.svg'
import assignerIcon from '@/assets/images/workflow/assigner.svg'
import memoryReadIcon from '@/assets/images/workflow/memory-read.svg'
import memoryWriteIcon from '@/assets/images/workflow/memory-write.svg'
import unknownIcon from '@/assets/images/workflow/unknown.svg'
import documentExtractorIcon from '@/assets/images/workflow/document-extractor.svg'
import { memoryConfigListUrl } from '@/api/memory' import { memoryConfigListUrl } from '@/api/memory'
import type { NodeLibrary } from './types' import type { NodeLibrary } from './types'
@@ -46,7 +24,7 @@ export const nodeLibrary: NodeLibrary[] = [
{ {
category: "coreNode", category: "coreNode",
nodes: [ nodes: [
{ type: "start", icon: startIcon, { type: "start", icon: 'rb:bg-[url("@/assets/images/workflow/start.svg")]',
config: { config: {
variables: { variables: {
type: 'define', type: 'define',
@@ -87,7 +65,7 @@ export const nodeLibrary: NodeLibrary[] = [
} }
}, },
{ {
type: "end", icon: endIcon, type: "end", icon: 'rb:bg-[url("@/assets/images/workflow/end.svg")]',
config: { config: {
output: { output: {
type: 'editor' type: 'editor'
@@ -100,7 +78,7 @@ export const nodeLibrary: NodeLibrary[] = [
{ {
category: "aiAndCognitiveProcessing", category: "aiAndCognitiveProcessing",
nodes: [ nodes: [
{ type: "llm", icon: llmIcon, { type: "llm", icon: 'rb:bg-[url("@/assets/images/workflow/llm.svg")]',
config: { config: {
model_id: { model_id: {
type: 'define', type: 'define',
@@ -154,7 +132,7 @@ export const nodeLibrary: NodeLibrary[] = [
} }
} }
}, },
{ type: "knowledge-retrieval", icon: ragIcon, { type: "knowledge-retrieval", icon: 'rb:bg-[url("@/assets/images/workflow/rag.svg")]',
config: { config: {
query: { query: {
type: 'variableList', type: 'variableList',
@@ -164,7 +142,7 @@ export const nodeLibrary: NodeLibrary[] = [
} }
} }
}, },
{ type: "parameter-extractor", icon: parameterExtractionIcon, { type: "parameter-extractor", icon: 'rb:bg-[url("@/assets/images/workflow/parameter_extraction.svg")]',
config: { config: {
model_id: { model_id: {
type: 'modelSelect', type: 'modelSelect',
@@ -191,7 +169,7 @@ export const nodeLibrary: NodeLibrary[] = [
{ {
category: "cognitiveUpgrading", category: "cognitiveUpgrading",
nodes: [ nodes: [
{ type: "memory-read", icon: memoryReadIcon, { type: "memory-read", icon: 'rb:bg-[url("@/assets/images/workflow/memory-read.svg")]',
config: { config: {
message: { message: {
type: 'editor', type: 'editor',
@@ -214,7 +192,7 @@ export const nodeLibrary: NodeLibrary[] = [
} }
} }
}, },
{ type: "memory-write", icon: memoryWriteIcon, { type: "memory-write", icon: 'rb:bg-[url("@/assets/images/workflow/memory-write.svg")]',
config: { config: {
message: { message: {
type: 'editor', type: 'editor',
@@ -240,7 +218,7 @@ export const nodeLibrary: NodeLibrary[] = [
{ {
category: "flowControl", category: "flowControl",
nodes: [ nodes: [
{ type: "if-else", icon: conditionIcon, { type: "if-else", icon: 'rb:bg-[url("@/assets/images/workflow/condition.svg")]',
config: { config: {
cases: { cases: {
type: 'caseList', type: 'caseList',
@@ -253,7 +231,7 @@ export const nodeLibrary: NodeLibrary[] = [
} }
} }
}, },
{ type: "question-classifier", icon: questionClassifierIcon, { type: "question-classifier", icon: 'rb:bg-[url("@/assets/images/workflow/question-classifier.svg")]',
config: { config: {
model_id: { model_id: {
type: 'modelSelect', type: 'modelSelect',
@@ -277,7 +255,7 @@ export const nodeLibrary: NodeLibrary[] = [
} }
} }
}, },
{ type: "iteration", icon: iterationIcon, { type: "iteration", icon: 'rb:bg-[url("@/assets/images/workflow/iteration.svg")]',
config: { config: {
input: { input: {
type: 'variableList', type: 'variableList',
@@ -310,7 +288,7 @@ export const nodeLibrary: NodeLibrary[] = [
} }
}, },
}, },
{ type: "loop", icon: loopIcon, { type: "loop", icon: 'rb:bg-[url("@/assets/images/workflow/loop.svg")]',
config: { config: {
cycle_vars: { cycle_vars: {
type: 'cycleVarsList', type: 'cycleVarsList',
@@ -333,9 +311,10 @@ export const nodeLibrary: NodeLibrary[] = [
}, },
} }
}, },
{ type: "cycle-start", icon: startIcon }, { type: "cycle-start", icon: 'rb:bg-[url("@/assets/images/workflow/start.svg")]'},
{ type: "break", icon: breakIcon }, { type: "break", icon: 'rb:bg-[url("@/assets/images/workflow/break.svg")]'},
{ type: "var-aggregator", icon: aggregatorIcon, {
type: "var-aggregator", icon: 'rb:bg-[url("@/assets/images/workflow/aggregator.svg")]',
config: { config: {
group: { group: {
type: 'switch', type: 'switch',
@@ -350,7 +329,7 @@ export const nodeLibrary: NodeLibrary[] = [
} }
} }
}, },
{ type: "assigner", icon: assignerIcon, { type: "assigner", icon: 'rb:bg-[url("@/assets/images/workflow/assigner.svg")]',
config: { config: {
assignments: { assignments: {
type: 'assignmentList', type: 'assignmentList',
@@ -363,7 +342,7 @@ export const nodeLibrary: NodeLibrary[] = [
{ {
category: "externalInteraction", category: "externalInteraction",
nodes: [ nodes: [
{ type: "http-request", icon: httpRequestIcon, { type: "http-request", icon: 'rb:bg-[url("@/assets/images/workflow/http_request.svg")]',
config: { config: {
method: { method: {
type: 'select', type: 'select',
@@ -423,7 +402,7 @@ export const nodeLibrary: NodeLibrary[] = [
} }
} }
}, },
{ type: "tool", icon: toolsIcon, { type: "tool", icon: 'rb:bg-[url("@/assets/images/workflow/tools.svg")]',
config: { config: {
tool_id: { tool_id: {
type: 'cascader' type: 'cascader'
@@ -433,7 +412,7 @@ export const nodeLibrary: NodeLibrary[] = [
} }
} }
}, },
{ type: "code", icon: codeExecutionIcon, { type: "code", icon: 'rb:bg-[url("@/assets/images/workflow/code_execution.svg")]',
config: { config: {
input_variables: { input_variables: {
type: 'inputList', type: 'inputList',
@@ -459,7 +438,7 @@ export const nodeLibrary: NodeLibrary[] = [
}, },
} }
}, },
{ type: "jinja-render", icon: templateRenderingIcon, { type: "jinja-render", icon: 'rb:bg-[url("@/assets/images/workflow/template_rendering.svg")]',
config: { config: {
mapping: { mapping: {
type: 'mappingList', type: 'mappingList',
@@ -474,7 +453,7 @@ export const nodeLibrary: NodeLibrary[] = [
}, },
} }
}, },
{ type: "document-extractor", icon: documentExtractorIcon, { type: "document-extractor", icon: 'rb:bg-[url("@/assets/images/workflow/document-extractor.svg")]',
config: { config: {
file_selector: { file_selector: {
type: 'variableList', type: 'variableList',
@@ -527,7 +506,8 @@ export const THEME_MAP: Record<string, { outer: string; title: string; bg: strin
} }
export const notesConfig = { export const notesConfig = {
type: "notes", icon: templateRenderingIcon, type: "notes",
icon: 'rb:bg-[url("@/assets/images/workflow/unknown.svg")]',
config: { config: {
text: { text: {
type: 'define', type: 'define',
@@ -555,11 +535,11 @@ export const notesConfig = {
} }
export const unknownNode = { export const unknownNode = {
type: 'unknown', type: 'unknown',
icon: unknownIcon icon: 'rb:bg-[url("@/assets/images/workflow/unknown.svg")]'
} }
export const noteNode = { export const noteNode = {
type: 'notes', type: 'notes',
icon: unknownIcon icon: 'rb:bg-[url("@/assets/images/workflow/unknown.svg")]'
} }
export const nodeWidth = 240; export const nodeWidth = 240;
@@ -702,7 +682,7 @@ const defaultPortGroup = {
body: { body: {
width: 1, width: 1,
height: 8, height: 8,
x: -1, x: 0.75,
magnet: true, magnet: true,
stroke: port_color, stroke: port_color,
strokeWidth: edge_width, strokeWidth: edge_width,
@@ -738,7 +718,7 @@ const leftPortGroup = {
body: { body: {
width: 1, width: 1,
height: 8, height: 8,
x: -1, x: -1.75,
y: -4, y: -4,
magnet: true, magnet: true,
stroke: port_color, stroke: port_color,

View File

@@ -68,7 +68,7 @@ const Workflow = forwardRef<WorkflowRef, { onFeaturesLoad?: (features: FeaturesC
{/* 右侧画布区域 */} {/* 右侧画布区域 */}
<div <div
className={clsx(`rb:fixed rb:top-18.5 rb:bottom-2.5 rb:left-0 rb:right-0 rb:transition-all`)} className={clsx(`rb:fixed rb:top-16 rb:bottom-0 rb:left-0 rb:right-0 rb:transition-all`)}
onDrop={onDrop} onDrop={onDrop}
onDragOver={onDragOver} onDragOver={onDragOver}
> >