optimize: UI update

This commit is contained in:
zhaoying
2025-12-16 11:26:41 +08:00
parent ea0a445d5b
commit 9b2f603454
10 changed files with 84 additions and 41 deletions

View File

@@ -34,12 +34,12 @@ const ButtonCheckbox: FC<ButtonCheckboxProps> = ({
}
return (
<div className={clsx("rb:flex rb:items-center rb:border rb:rounded-[8px] rb:px-[8px] rb:text-[12px] rb:h-[24px] rb:cursor-pointer rb:hover:bg-[#F0F3F8]", {
<div className={clsx("rb:flex rb:items-center rb:border rb:rounded-lg rb:px-2 rb:text-[12px] rb:h-6 rb:cursor-pointer rb:hover:bg-[#F0F3F8]", {
"rb:bg-[rgba(21,94,239,0.06)] rb:border-[#155EEF] rb:text-[#155EEF]": checked,
"rb:border-[#DFE4ED] rb:text-[#212332]": !checked,
})} onClick={handleChange}>
{icon && !checked && <img src={icon} className="rb:w-[16px] rb:h-[16px] rb:mr-[4px]" />}
{checkedIcon && checked && <img src={checkedIcon} className="rb:w-[16px] rb:h-[16px] rb:mr-[4px]" />}
{icon && !checked && <img src={icon} className="rb:w-4 rb:h-4 rb:mr-1" />}
{checkedIcon && checked && <img src={checkedIcon} className="rb:w-4 rb:h-4 rb:mr-1" />}
{children}
</div>
);

View File

@@ -9,7 +9,7 @@ interface ApiResponse<T> {
items?: T[];
}
interface CustomSelectProps {
interface CustomSelectProps extends Omit<SelectProps, 'filterOption'> {
url: string;
params?: Record<string, unknown>;
valueKey?: string;

View File

@@ -29,7 +29,7 @@ interface PageScrollListProps {
const PageScrollList = forwardRef<PageScrollListRef, PageScrollListProps>(({
renderItem,
query = {},
query,
url,
column = 4,
className = '',
@@ -51,11 +51,11 @@ const PageScrollList = forwardRef<PageScrollListRef, PageScrollListProps>(({
request.get(url, {
page: page,
pagesize: PAGE_SIZE,
...query,
...(query||{}),
})
.then((res) => {
const response = res as ApiResponse;
const results = Array.isArray(response.items) ? response.items : Array.isArray(response.hosts) ? response.hosts : Array.isArray(response) ? response : [];
const results = Array.isArray(response.items) ? response.items : Array.isArray(response) ? response : [];
if (flag) {
setData(results);
} else {

View File

@@ -16,7 +16,7 @@ const colors = {
const RbAlert: FC<RbAlertProps> = ({ color = 'blue', icon, className, children }) => {
return (
<div className={`${colors[color]} ${className} rb:p-[6px_9px] rb:flex rb:items-center rb:text-[12px] rb:font-regular rb:leading-[16px] rb:border-[1px] rb:rounded-[6px]`}>
<div className={`${colors[color]} ${className} rb:p-[6px_9px] rb:flex rb:items-center rb:text-[12px] rb:font-regular rb:leading-4 rb:border rb:rounded-md`}>
{icon && <span className="rb:text-[16px] rb:mr-[9px]">{icon}</span>}
{children}
</div>

View File

@@ -52,7 +52,7 @@ const RbCard: FC<RbCardProps> = ({
title={typeof title === 'function' ? title() : title ?
<div className="rb:flex rb:items-center">
{avatarUrl
? <img src={avatarUrl} className="rb:mr-[13px] rb:w-[48px] rb:h-[48px] rb:rounded-[8px]" />
? <img src={avatarUrl} className="rb:mr-3.25 rb:w-12 rb:h-12 rb:rounded-lg" />
: avatar ? avatar : null
}
<div className={

View File

@@ -1,6 +1,6 @@
import { type FC, type ReactNode } from 'react'
interface TagProps {
export interface TagProps {
color?: 'processing' | 'error' | 'success' | 'warning' | 'default',
children: ReactNode;
className?: string;
@@ -16,7 +16,7 @@ const colors = {
const Tag: FC<TagProps> = ({ color = 'processing', children, className }) => {
return (
<span className={`rb:inline-block rb:px-[4px] rb:py-[2px] rb:rounded-[4px] rb:text-[12px] rb:font-regular! rb:leading-[16px] rb:border-[1px] ${colors[color]} ${className || ''}`}>
<span className={`rb:inline-block rb:px-1 rb:py-0.5 rb:rounded-sm rb:text-[12px] rb:font-regular! rb:leading-4 rb:border ${colors[color]} ${className || ''}`}>
{children}
</span>
)

View File

@@ -8,6 +8,7 @@ const NoPermission = () => {
return (
<Empty
url={noPermission}
size={[240, 240]}
title={t('empty.noPermission')}
subTitle={t('empty.noPermissionDesc')}
className="rb:h-[calc(100vh-84px)]"

View File

@@ -8,6 +8,7 @@ const NotFound = () => {
return (
<Empty
url={notFoundImg}
size={[328, 146]}
title={t('empty.notFound')}
subTitle={t('empty.notFoundDesc')}
className="rb:h-[calc(100vh-84px)]"

View File

@@ -7,16 +7,17 @@ export interface Data {
other_address: string;
created_at: string;
updated_at: string;
},
memory_num: {
total: number;
counts: {
dialogue: number;
chunk: number;
statement: number;
entity: number;
}
},
memory_num: {
total: number;
counts: {
dialogue: number;
chunk: number;
statement: number;
entity: number;
}
},
name?: string;
}
export interface ConfigModalData {
llm: string;

View File

@@ -1,4 +1,4 @@
import React, { type FC, useEffect, useState, useRef } from 'react'
import React, { type FC, useEffect, useState, useRef, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useParams } from 'react-router-dom'
import { Col } from 'antd'
@@ -29,13 +29,9 @@ const RelationshipNetwork:FC = () => {
const [categories, setCategories] = useState<{ name: string }[]>([])
const [selectedNode, setSelectedNode] = useState<Node | null>(null)
useEffect(() => {
if (!id) return
getEdgeData()
}, [id])
// 关系网络
const getEdgeData = () => {
const getEdgeData = useCallback(() => {
if (!id) return
setSelectedNode(null)
getMemorySearchEdges(id).then((res) => {
@@ -45,20 +41,20 @@ const RelationshipNetwork:FC = () => {
const categories: { name: string }[] = []
list.forEach(item => {
if (item.edge) {
if (item.edge && item.edge.target_id && item.edge.source_id) {
links.push({
...item.edge,
target: item.edge?.target_id,
source: item.edge?.source_id,
target: item.edge.target_id,
source: item.edge.source_id,
})
}
if (item.sourceNode) {
nodes.push(item.sourceNode)
categories.push({name: item.sourceNode.entity_type})
categories.push({name: item.sourceNode.entity_type || 'Unknown'})
}
if (item.targetNode) {
nodes.push(item.targetNode)
categories.push({name: item.targetNode.entity_type})
categories.push({name: item.targetNode.entity_type || 'Unknown'})
}
})
@@ -76,14 +72,58 @@ const RelationshipNetwork:FC = () => {
setLinks(uniqueLinks)
setCategories(uniqueCategories)
// Calculate node frequency based on appearance in links
const nodeFrequency = new Map<string, number>()
// Count each node's appearance in links (both as source and target)
uniqueLinks.forEach(link => {
// Increment source node frequency (only if source exists and is a string)
if (typeof link.source === 'string') {
nodeFrequency.set(link.source, (nodeFrequency.get(link.source) || 0) + 1)
}
// Increment target node frequency (only if target exists and is a string)
if (typeof link.target === 'string') {
nodeFrequency.set(link.target, (nodeFrequency.get(link.target) || 0) + 1)
}
})
// Set minimum frequency to 1 for nodes not in any links
uniqueNodes.forEach(node => {
if (node.id && typeof node.id === 'string') {
if (!nodeFrequency.has(node.id)) {
nodeFrequency.set(node.id, 1)
}
}
})
uniqueNodes.map(item => {
const index = uniqueCategories.findIndex((n) => n.name === item.entity_type)
const index = uniqueCategories.findIndex((n) => n.name === (item.entity_type || 'Unknown'))
item.category = index
item.symbolSize = index < 10 ? 5 : index <100 ? 8 : 10
// Get frequency for the node, ensuring id is a string
const frequency = (item.id && typeof item.id === 'string') ? (nodeFrequency.get(item.id) || 1) : 1
// Set symbolSize based on frequency
// Adjust these thresholds based on expected frequency ranges
if (frequency <= 1) {
item.symbolSize = 5
} else if (frequency <= 10) {
item.symbolSize = 10
} else if (frequency <= 15) {
item.symbolSize = 15
} else if (frequency <= 20) {
item.symbolSize = 25
} else {
item.symbolSize = 35
}
})
setNodes(uniqueNodes)
})
}
}, [id])
useEffect(() => {
if (!id) return
getEdgeData()
}, [id])
useEffect(() => {
const handleResize = () => {
@@ -95,7 +135,7 @@ const RelationshipNetwork:FC = () => {
});
}
}
const resizeObserver = new ResizeObserver(handleResize)
const chartElement = chartRef.current?.getEchartsInstance().getDom().parentElement
if (chartElement) {
@@ -106,6 +146,8 @@ const RelationshipNetwork:FC = () => {
resizeObserver.disconnect()
}
}, [nodes])
console.log('nodes', nodes)
return (
<>
{/* 关系网络 */}
@@ -175,12 +217,10 @@ const RelationshipNetwork:FC = () => {
if (params.dataType === 'node') {
// 处理节点点击事件
console.log('Node clicked:', params.data);
setSelectedNode(params.data)
if (selectedNode?.id === params.data.id) {
setSelectedNode(null)
} else {
setSelectedNode(params.data)
}
// 使用函数式更新避免状态依赖问题
setSelectedNode(prevSelected =>
prevSelected?.id === params.data.id ? null : params.data
)
}
}
}}