diff --git a/web/src/assets/images/common/close_grey.svg b/web/src/assets/images/common/close_grey.svg
new file mode 100644
index 00000000..6797b67f
--- /dev/null
+++ b/web/src/assets/images/common/close_grey.svg
@@ -0,0 +1,15 @@
+
+
\ No newline at end of file
diff --git a/web/src/assets/images/logout.svg b/web/src/assets/images/logout.svg
deleted file mode 100644
index eedaccc4..00000000
--- a/web/src/assets/images/logout.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
\ No newline at end of file
diff --git a/web/src/assets/images/logout_grey.svg b/web/src/assets/images/logout_grey.svg
new file mode 100644
index 00000000..b9b566c3
--- /dev/null
+++ b/web/src/assets/images/logout_grey.svg
@@ -0,0 +1,19 @@
+
+
\ No newline at end of file
diff --git a/web/src/assets/images/logout_hover.svg b/web/src/assets/images/logout_hover.svg
deleted file mode 100644
index d77ab292..00000000
--- a/web/src/assets/images/logout_hover.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
\ No newline at end of file
diff --git a/web/src/components/CodeMirrorEditor/index.tsx b/web/src/components/CodeMirrorEditor/index.tsx
index ec2a6780..23729dcc 100644
--- a/web/src/components/CodeMirrorEditor/index.tsx
+++ b/web/src/components/CodeMirrorEditor/index.tsx
@@ -1,8 +1,8 @@
/*
* @Author: ZhaoYing
* @Date: 2026-02-04 17:20:52
- * @Last Modified by: ZhaoYing
- * @Last Modified time: 2026-02-04 17:20:52
+ * @Last Modified by: ZhaoYing
+ * @Last Modified time: 2026-04-16 11:46:39
*/
import { useEffect, useRef, useMemo } from 'react';
import { EditorView, basicSetup } from 'codemirror';
@@ -35,7 +35,7 @@ interface CodeMirrorEditorProps {
height?: string;
size?: 'default' | 'small';
placeholder?: string;
- variant?: 'outlined' | 'borderless';
+ variant?: 'outlined' | 'borderless' | 'filled';
}
/**
@@ -156,7 +156,7 @@ const CodeMirrorEditor = ({
);
};
diff --git a/web/src/components/PageTabs/index.module.css b/web/src/components/PageTabs/index.module.css
index 5e071b38..c33dcd61 100644
--- a/web/src/components/PageTabs/index.module.css
+++ b/web/src/components/PageTabs/index.module.css
@@ -1,5 +1,6 @@
.page-tabs:global(.ant-segmented) {
padding: 4px;
+ margin-left: 4px;
}
.page-tabs:global(.ant-segmented .ant-segmented-item-label) {
line-height: 24px;
diff --git a/web/src/components/RbSlider/index.tsx b/web/src/components/RbSlider/index.tsx
index c37cdc47..70b9fa84 100644
--- a/web/src/components/RbSlider/index.tsx
+++ b/web/src/components/RbSlider/index.tsx
@@ -44,6 +44,7 @@ const RbSlider: FC = ({
className = '',
prefix,
inputClassName,
+ disabled,
...rest
}) => {
const [curValue, setCurValue] = useState(0)
@@ -83,6 +84,7 @@ const RbSlider: FC = ({
max={max}
step={step}
value={curValue}
+ disabled={disabled}
onChange={handleSliderChange}
classNames={size === 'small' ? {
rail: 'rb:w-[calc(100%-6px)]!'
@@ -96,6 +98,7 @@ const RbSlider: FC = ({
max={max}
step={step as number}
value={curValue}
+ disabled={disabled}
onChange={handleInputChange}
prefix={prefix}
className={`${inputClassName || '' } rb:w-20!`}
diff --git a/web/src/components/SiderMenu/index.tsx b/web/src/components/SiderMenu/index.tsx
index c85f3c9f..0d482c79 100644
--- a/web/src/components/SiderMenu/index.tsx
+++ b/web/src/components/SiderMenu/index.tsx
@@ -337,7 +337,7 @@ const Menu: FC<{
onClick={goToSpace}
className="rb-border-t rb:pt-5! rb:pb-2.5! rb:absolute rb:bottom-2.5 rb:right-5 rb:left-5 rb:text-[13px] rb:text-[#5B6167] rb:hover:text-[#212332] rb:leading-4.5 rb:font-regular rb:text-center rb:mt-2.25 rb:cursor-pointer"
>
-
+
{collapsed ? null : t('common.returnToSpace')}
}
diff --git a/web/src/components/Tag/index.tsx b/web/src/components/Tag/index.tsx
index 71a20ae9..f07f5cad 100644
--- a/web/src/components/Tag/index.tsx
+++ b/web/src/components/Tag/index.tsx
@@ -18,7 +18,7 @@ import { type FC, type ReactNode } from 'react'
/** Props interface for Tag component */
export interface TagProps {
/** Color theme for the tag */
- color?: 'processing' | 'error' | 'success' | 'warning' | 'default',
+ color?: 'processing' | 'error' | 'success' | 'warning' | 'default' | 'purple' | 'dark',
/** Tag content */
children: ReactNode;
/** Additional CSS classes */
@@ -32,6 +32,8 @@ const colors = {
success: 'rb:text-[#369F21] rb:border-[rgba(54,159,33,0.25)] rb:bg-[rgba(54,159,33,0.06)]',
warning: 'rb:text-[#FF5D34] rb:border-[rgba(255,93,52,0.30)] rb:bg-[rgba(255,93,52,0.08)]',
default: 'rb:text-[#5B6167] rb:border-[rgba(91,97,103,0.30)] rb:bg-[rgba(91,97,103,0.08)]',
+ purple: 'rb:text-[#9C6FFF] rb:border-[rgba(156,111,255,0.25)] rb:bg-[rgba(156,111,255,0.06)]',
+ dark: 'rb:text-[#171719] rb:border-[rgba(23,23,25,0.25)] rb:bg-[rgba(23,23,25,0.06)]'
}
/** Custom tag component with color themes */
diff --git a/web/src/styles/index.css b/web/src/styles/index.css
index 66051085..84b5ec01 100644
--- a/web/src/styles/index.css
+++ b/web/src/styles/index.css
@@ -353,6 +353,26 @@ body {
background-color: transparent;
border: none;
}
+.cm-editor-filled {
+ background: #F6F6F6;
+ border-radius: 8px;
+}
+.cm-editor-filled .ͼ1 .cm-lineNumbers .cm-gutterElement {
+ border-radius: 8px 0 0 8px;
+}
+.cm-editor-filled .ͼ4 .cm-line {
+ border-radius: 0 8px 8px 0;
+}
+.cm-editor-filled .ͼ2 .cm-activeLineGutter,
+.cm-editor-filled .ͼ2 .cm-activeLine {
+ background: transparent;
+}
+.cm-editor-filled .ͼ1 .cm-placeholder {
+ color: rgba(23, 23, 25, 0.25);
+}
+.cm-editor-filled .ͼ1 .cm-lineNumbers .cm-gutterElement {
+ color: #212332;
+}
::-webkit-scrollbar {
width: 6px;
height: 8px;
diff --git a/web/src/views/ApplicationConfig/components/ConfigHeader.tsx b/web/src/views/ApplicationConfig/components/ConfigHeader.tsx
index a3a9bd7b..112a1e3d 100644
--- a/web/src/views/ApplicationConfig/components/ConfigHeader.tsx
+++ b/web/src/views/ApplicationConfig/components/ConfigHeader.tsx
@@ -253,7 +253,7 @@ const ConfigHeader: FC = ({
:
{t('common.return')}
diff --git a/web/src/views/ApplicationManagement/MySharing.tsx b/web/src/views/ApplicationManagement/MySharing.tsx
index e24cce0b..8fb5b2c0 100644
--- a/web/src/views/ApplicationManagement/MySharing.tsx
+++ b/web/src/views/ApplicationManagement/MySharing.tsx
@@ -2,27 +2,33 @@
* @Author: ZhaoYing
* @Date: 2026-02-03 16:34:12
* @Last Modified by: ZhaoYing
- * @Last Modified time: 2026-03-26 14:39:18
+ * @Last Modified time: 2026-04-16 11:19:20
*/
import React, { useState, useEffect, useMemo, type MouseEvent } from 'react';
import { useTranslation } from 'react-i18next';
-import { Button, App, Flex, Collapse } from 'antd';
+import { App, Flex, Row, Col, Space } from 'antd';
import clsx from 'clsx';
import type { MySharedOutItem } from './types';
import { mySharedOutList, cancelShare, cancelSpaceShare } from '@/api/application'
import BodyWrapper from '@/components/Empty/BodyWrapper'
+import RbCard from '@/components/RbCard/Card'
+import RbDescriptions from '@/components/RbDescriptions'
+import Tag from '@/components/Tag'
const MySharing: React.FC = () => {
const { t } = useTranslation();
const { modal } = App.useApp();
+ const [loading, setLoading] = useState(false)
const [data, setData] = useState([])
useEffect(() => { getList() }, [])
const getList = () => {
+ setLoading(true)
mySharedOutList()
.then(res => setData(res as MySharedOutItem[]))
+ .finally(() => setLoading(false))
}
/** Group items by target_workspace_id */
@@ -80,89 +86,114 @@ const MySharing: React.FC = () => {
window.open(url);
}
+ const [selectedWorkspace, setSelectedWorkspace] = useState(null)
+ const [appList, setAppList] = useState([])
+
+ useEffect(() => {
+ if (grouped.length === 0) {
+ setSelectedWorkspace(null)
+ setAppList([])
+ return
+ }
+ const current = grouped.find(g => g.workspace.target_workspace_id === selectedWorkspace)
+ if (current) {
+ setAppList(current.items)
+ } else {
+ setSelectedWorkspace(grouped[0].workspace.target_workspace_id)
+ setAppList(grouped[0].items)
+ }
+ }, [grouped, selectedWorkspace])
+
+ const handleSelectWorkspace = async (target_workspace_id: string) => {
+ if (target_workspace_id === selectedWorkspace) return
+ setSelectedWorkspace(target_workspace_id);
+ const filterWorkspace = grouped.find(item => item.workspace.target_workspace_id === target_workspace_id);
+
+ setAppList(filterWorkspace?.items || [])
+ };
+
return (
-
-
- {grouped.map(({ workspace, items }) => (
-
+
+
+
+ {grouped.map(({ workspace, items }) => (
+ handleSelectWorkspace(workspace.target_workspace_id)}
+ >
{workspace.target_workspace_icon
- ?
- :
- {workspace.target_workspace_name[0]}
-
+ ?
+ :
+ {workspace.target_workspace_name[0]}
+
}
-
{workspace.target_workspace_name}
-
{t('application.appCount', { count: items.length })}
+
{workspace.target_workspace_name}
+
{t('application.appCount', { count: items.length })}
- ),
- extra: (
-
- ),
- children: (
-
- {items.map(item => (
-
handleEdit(item)}>
-
handleCancelOne(item, e)}
- />
-
-
- {item.source_app_name[0]}
-
- {item.source_app_name}
-
-
-
- {t('application.type')}
-
- {t(`application.${item.source_app_type}`)}
-
-
-
- {t('application.version')}
- {item.source_app_version}
-
-
- {t('application.permission')}
-
- {t(`application.${item.permission}`)}
-
-
-
- {t('application.souceStatus')}
- {item.source_app_is_active ? t('application.sourceActive') : t('application.sourceInactive')}
-
-
-
- ))}
-
- ),
- }]}
- />
- ))}
-
-
- );
+ >
+
+ ))}
+
+
+
+
+ {appList.map(item => (
+
{item.source_app_name.trim()[0]}}
+ subTitle={
+ {t(`application.${item.source_app_type}`)}
+ {item.source_app_is_active ? t('application.sourceActive') : t('application.sourceInactive')}
+ }
+ extra={ handleCancelOne(item, e)}
+ >
}
+ bodyClassName="rb:py-6! rb:px-4!"
+ className="rb:cursor-pointer"
+ onClick={() => handleEdit(item)}
+ >
+ {t(`application.${item.permission}`)}
+ },
+ ]}
+ />
+
+ ))}
+
+
+
+
+ )
};
export default MySharing;
diff --git a/web/src/views/Home/components/TopCardList.tsx b/web/src/views/Home/components/TopCardList.tsx
index 6052192f..e54073b7 100644
--- a/web/src/views/Home/components/TopCardList.tsx
+++ b/web/src/views/Home/components/TopCardList.tsx
@@ -61,6 +61,7 @@ const TopCardList: FC<{data?: DashboardData}> = ({ data }) => {
= 0,
+ 'rb:text-[#FFFFFF]': item.key === 'total_memory'
})}>
{data?.[`${item.key}_change` as keyof DashboardData] && typeof data?.[item.key as keyof DashboardData] === 'number'
? (100 * data?.[`${item.key}_change` as keyof DashboardData]).toFixed(2)
diff --git a/web/src/views/Ontology/components/PageHeader.tsx b/web/src/views/Ontology/components/PageHeader.tsx
deleted file mode 100644
index a4a75928..00000000
--- a/web/src/views/Ontology/components/PageHeader.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * @Author: ZhaoYing
- * @Date: 2026-02-03 14:10:24
- * @Last Modified by: ZhaoYing
- * @Last Modified time: 2026-03-06 11:25:59
- */
-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;
-
-/**
- * Props for PageHeader component
- */
-interface ConfigHeaderProps {
- /** Page title/name */
- name?: string | ReactNode;
- /** Subtitle content displayed below the title */
- subTitle?: ReactNode | string;
- /** Extra content displayed on the right side */
- extra?: ReactNode;
-}
-
-/**
- * Page header component for ontology pages
- * Displays title, subtitle, back button and extra actions
- * @param props - Component props
- */
-const PageHeader: FC = ({
- name,
- subTitle,
- extra
-}) => {
- const { t } = useTranslation();
- const navigate = useNavigate();
-
- /**
- * Navigate back to previous page
- */
- const goBack = () => {
- navigate(-1)
- }
- return (
-
-
-
- {name}
-
-
{subTitle}
-
-
-
-
- {extra}
-
-
- );
-};
-
-export default PageHeader;
\ No newline at end of file
diff --git a/web/src/views/Ontology/pages/Detail.tsx b/web/src/views/Ontology/pages/Detail.tsx
index b6ee5953..7b9da496 100644
--- a/web/src/views/Ontology/pages/Detail.tsx
+++ b/web/src/views/Ontology/pages/Detail.tsx
@@ -122,7 +122,7 @@ const Detail: FC = () => {
)}
navigate(-1)}>
{t('common.return')}
diff --git a/web/src/views/Workflow/components/Editor/Jinja2Editor.tsx b/web/src/views/Workflow/components/Editor/Jinja2Editor.tsx
index 9a21a3b2..a4f20f9f 100644
--- a/web/src/views/Workflow/components/Editor/Jinja2Editor.tsx
+++ b/web/src/views/Workflow/components/Editor/Jinja2Editor.tsx
@@ -2,7 +2,7 @@
* @Author: ZhaoYing
* @Date: 2026-04-02 15:15:36
* @Last Modified by: ZhaoYing
- * @Last Modified time: 2026-04-07 14:48:00
+ * @Last Modified time: 2026-04-16 11:34:41
*/
import { type FC, useEffect, useMemo } from 'react';
import { LexicalComposer } from '@lexical/react/LexicalComposer';
@@ -81,7 +81,7 @@ export interface Jinja2EditorProps {
value?: string;
onChange?: (value: string) => void;
options?: Suggestion[];
- variant?: 'outlined' | 'borderless';
+ variant?: 'outlined' | 'borderless' | 'filled';
height?: number;
size?: 'default' | 'small';
className?: string;
diff --git a/web/src/views/Workflow/components/Editor/index.tsx b/web/src/views/Workflow/components/Editor/index.tsx
index 52a4f23e..119c17db 100644
--- a/web/src/views/Workflow/components/Editor/index.tsx
+++ b/web/src/views/Workflow/components/Editor/index.tsx
@@ -2,7 +2,7 @@
* @Author: ZhaoYing
* @Date: 2025-12-23 16:22:51
* @Last Modified by: ZhaoYing
- * @Last Modified time: 2026-04-07 16:29:36
+ * @Last Modified time: 2026-04-16 12:04:37
*/
import { type FC, useState, useMemo } from 'react';
import { LexicalComposer } from '@lexical/react/LexicalComposer';
@@ -25,7 +25,7 @@ export interface LexicalEditorProps {
value?: string;
onChange?: (value: string) => void;
options?: Suggestion[];
- variant?: 'outlined' | 'borderless';
+ variant?: 'outlined' | 'borderless' | 'filled';
height?: number;
fontSize?: number;
lineHeight?: number;
@@ -60,6 +60,7 @@ const Editor: FC =({
}) => {
console.log('Editor value', value)
const [_count, setCount] = useState(0);
+ const [focused, setFocused] = useState(false);
if (language === 'jinja2') {
return (
@@ -90,7 +91,7 @@ const Editor: FC =({
// Calculate minimum height based on type and size
const minheight = useMemo(() => {
if (type === 'input') {
- return `${height ? height : size === 'small' && variant === 'borderless' ? 18 : size === 'small' ? 26 : 30}px`
+ return `${height ? height : size === 'small' && ['borderless', 'filled'].includes(variant) ? 18 : size === 'small' ? 26 : 30}px`
}
return `${height ? height : size === 'small' ? 60 : 120}px`
}, [type, size, height, variant])
@@ -103,7 +104,7 @@ const Editor: FC =({
// Calculate line height based on size prop
const lineHeight = useMemo(() => {
return `${height ? height - 10 : size === 'small' && variant === 'borderless' ? 18 : size === 'small' ? 16 : 20}px`
- }, [size])
+ }, [size, height, variant])
// Calculate placeholder minimum height
const placeHolderMinheight = useMemo(() => {
@@ -112,20 +113,24 @@ const Editor: FC =({
return (
-
+
type === 'input' && setFocused(true)}
+ onBlur={() => type === 'input' && setFocused(false)}
/>
}
placeholder={
@@ -133,12 +138,13 @@ const Editor: FC =({
style={{
minHeight: placeHolderMinheight,
position: 'absolute',
- top: variant === 'borderless' ? '2px' : '6px',
- left: variant === 'borderless' ? '0' : '11px',
- color: '#A8A9AA',
+ top: variant === 'outlined' ? '6px' : type === 'input' ? '6px' : '2px',
+ left: variant === 'outlined' ? '11px' : type === 'input' ? '8px' : '0',
+ color: 'rgba(23,23,25,0.25)',
fontSize: fontSize,
lineHeight: placeHolderMinheight,
pointerEvents: 'none',
+ borderRadius: '8px',
}}
>
{placeholder}
diff --git a/web/src/views/Workflow/components/Editor/plugin/AutocompletePlugin.tsx b/web/src/views/Workflow/components/Editor/plugin/AutocompletePlugin.tsx
index 6d3b7a4f..a5ea9771 100644
--- a/web/src/views/Workflow/components/Editor/plugin/AutocompletePlugin.tsx
+++ b/web/src/views/Workflow/components/Editor/plugin/AutocompletePlugin.tsx
@@ -5,6 +5,7 @@
* @Last Modified time: 2026-04-13 14:00:07
*/
import { useEffect, useLayoutEffect, useState, useRef, type FC } from 'react';
+import { createPortal } from 'react-dom';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { $getSelection, $isRangeSelection, COMMAND_PRIORITY_HIGH, KEY_ENTER_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND } from 'lexical';
import { Space, Flex } from 'antd';
@@ -35,61 +36,62 @@ const AutocompletePlugin: FC<{ options: Suggestion[] }> = ({ options }) => {
const [selectedIndex, setSelectedIndex] = useState(0);
const [popupPosition, setPopupPosition] = useState({ top: 0, left: 0, anchorBottom: 0 });
const [expandedParent, setExpandedParent] = useState(null);
- const [childPanelTop, setChildPanelTop] = useState(0);
+ const [childPanelPos, setChildPanelPos] = useState({ top: 0, right: 0 });
+ const [activePanel, setActivePanel] = useState<'main' | 'child'>('main');
+ const [childActiveIndex, setChildActiveIndex] = useState(-1);
const popupRef = useRef(null);
const itemRefs = useRef