From da75abb22328c814d201d24ab4e04fd73b0eb0cd Mon Sep 17 00:00:00 2001 From: zhaoying Date: Thu, 22 Jan 2026 12:26:37 +0800 Subject: [PATCH] feat(web): user memory feature optimize --- web/src/i18n/en.ts | 1 + web/src/i18n/zh.ts | 1 + .../components/PageHeader.tsx | 6 ++--- .../components/RelationshipNetwork.tsx | 10 +++++--- .../components/Suggestions.tsx | 7 +++++- .../UserMemoryDetail/pages/ImplicitDetail.tsx | 24 ++++++++++++------- .../pages/StatementDetail.tsx | 19 +++++++++++---- .../UserMemoryDetail/pages/WorkingDetail.tsx | 20 ++++++++-------- .../views/UserMemoryDetail/pages/index.tsx | 21 ++++++++++++---- 9 files changed, 75 insertions(+), 34 deletions(-) diff --git a/web/src/i18n/en.ts b/web/src/i18n/en.ts index bc757797..1df2eb6d 100644 --- a/web/src/i18n/en.ts +++ b/web/src/i18n/en.ts @@ -2064,6 +2064,7 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re stability: 'Stability', resilience: 'Resilience', suggestions: 'Personalized Suggestions', + suggestionLoading: 'Your personalized suggestions are being generated', }, reflectionEngine: { reflectionEngineConfig: 'Reflection Engine Configuration', diff --git a/web/src/i18n/zh.ts b/web/src/i18n/zh.ts index 2e88ad4a..44f17f49 100644 --- a/web/src/i18n/zh.ts +++ b/web/src/i18n/zh.ts @@ -2158,6 +2158,7 @@ export const zh = { stability: '稳定性', resilience: '恢复力', suggestions: '个性化建议', + suggestionLoading: '您的个性化建议正在生成中', }, reflectionEngine: { reflectionEngineConfig: '反思引擎配置', diff --git a/web/src/views/UserMemoryDetail/components/PageHeader.tsx b/web/src/views/UserMemoryDetail/components/PageHeader.tsx index 68cdada8..2c457067 100644 --- a/web/src/views/UserMemoryDetail/components/PageHeader.tsx +++ b/web/src/views/UserMemoryDetail/components/PageHeader.tsx @@ -35,13 +35,13 @@ const PageHeader: FC = ({ {operation} - - {extra} - + ); }; diff --git a/web/src/views/UserMemoryDetail/components/RelationshipNetwork.tsx b/web/src/views/UserMemoryDetail/components/RelationshipNetwork.tsx index 7a927479..55e94270 100644 --- a/web/src/views/UserMemoryDetail/components/RelationshipNetwork.tsx +++ b/web/src/views/UserMemoryDetail/components/RelationshipNetwork.tsx @@ -266,7 +266,7 @@ const RelationshipNetwork:FC = () => { size={[197.81, 150]} /> : <> -
{selectedNode.name}
+ {selectedNode.name &&
{selectedNode.name}
}
<>
{t('userMemory.memoryContent')}
@@ -297,7 +297,8 @@ const RelationshipNetwork:FC = () => { {selectedNode.label === 'Statement' && <> {(['emotion_keywords', 'emotion_type', 'emotion_subject', 'importance_score'] as const).map(key => { const statementProps = selectedNode.properties as StatementNodeProperties; - if ((key === 'emotion_keywords' && statementProps[key]?.length > 0) || statementProps[key]) { + if ((key === 'emotion_keywords' && statementProps[key]?.length > 0) || typeof statementProps[key] === 'string') { + console.log('statementProps[key]', statementProps[key]) return (
{t(`userMemory.Statement_${key}`)} @@ -321,7 +322,10 @@ const RelationshipNetwork:FC = () => {
{t(`userMemory.ExtractedEntity_${key}`)}
- {entityProps[key]} + {Array.isArray(entityProps[key]) && entityProps[key].length > 0 + ? entityProps[key].map((vo, index) =>
- {vo}
) + : entityProps[key] + }
) diff --git a/web/src/views/UserMemoryDetail/components/Suggestions.tsx b/web/src/views/UserMemoryDetail/components/Suggestions.tsx index c2c8ca8b..2687e457 100644 --- a/web/src/views/UserMemoryDetail/components/Suggestions.tsx +++ b/web/src/views/UserMemoryDetail/components/Suggestions.tsx @@ -21,6 +21,7 @@ interface Suggestions { const Suggestions = forwardRef<{ handleRefresh: () => void; }>((_props, ref) => { const { t } = useTranslation() const { id } = useParams() + const [loading, setLoading] = useState(false) const [suggestions, setSuggestions] = useState(null) useEffect(() => { @@ -31,10 +32,14 @@ const Suggestions = forwardRef<{ handleRefresh: () => void; }>((_props, ref) => if (!id) { return } + setLoading(true) getEmotionSuggestions(id) .then((res) => { setSuggestions(res as Suggestions) }) + .finally(() => { + setLoading(false) + }) } useImperativeHandle(ref, () => ({ @@ -63,7 +68,7 @@ const Suggestions = forwardRef<{ handleRefresh: () => void; }>((_props, ref) => ))}
- : + : } ) diff --git a/web/src/views/UserMemoryDetail/pages/ImplicitDetail.tsx b/web/src/views/UserMemoryDetail/pages/ImplicitDetail.tsx index d79407da..dfe5c1ee 100644 --- a/web/src/views/UserMemoryDetail/pages/ImplicitDetail.tsx +++ b/web/src/views/UserMemoryDetail/pages/ImplicitDetail.tsx @@ -20,14 +20,22 @@ const ImplicitDetail = forwardRef<{ handleRefresh: () => void; }>((_props, ref) const habitsRef = useRef<{ handleRefresh: () => void; }>(null) const handleRefresh = () => { - if (!id) return - generateProfile(id) - .then(() => { - preferencesRef.current?.handleRefresh() - portraitRef.current?.handleRefresh() - interestAreasRef.current?.handleRefresh() - habitsRef.current?.handleRefresh() - }) + if (!id) { + return Promise.resolve() + } + return new Promise((resolve, reject) => { + generateProfile(id) + .then(() => { + preferencesRef.current?.handleRefresh() + portraitRef.current?.handleRefresh() + interestAreasRef.current?.handleRefresh() + habitsRef.current?.handleRefresh() + resolve(true) + }) + .catch((error) => { + reject(error) + }) + }) } useImperativeHandle(ref, () => ({ handleRefresh diff --git a/web/src/views/UserMemoryDetail/pages/StatementDetail.tsx b/web/src/views/UserMemoryDetail/pages/StatementDetail.tsx index 6515263e..72d35c60 100644 --- a/web/src/views/UserMemoryDetail/pages/StatementDetail.tsx +++ b/web/src/views/UserMemoryDetail/pages/StatementDetail.tsx @@ -13,11 +13,20 @@ const StatementDetail = forwardRef((_props, ref) => { const { id } = useParams() const suggestionsRef = useRef<{ handleRefresh: () => void; }>(null) const handleRefresh = () => { - if (!id) return - generateSuggestions(id) - .then(() => { - suggestionsRef.current?.handleRefresh() - }) + if (!id) { + return Promise.resolve() + } + + return new Promise((resolve, reject) => { + generateSuggestions(id) + .then(() => { + suggestionsRef.current?.handleRefresh() + resolve(true) + }) + .catch((error) => { + reject(error) + }) + }) } useImperativeHandle(ref, () => ({ handleRefresh diff --git a/web/src/views/UserMemoryDetail/pages/WorkingDetail.tsx b/web/src/views/UserMemoryDetail/pages/WorkingDetail.tsx index 7ba7c414..843a3b23 100644 --- a/web/src/views/UserMemoryDetail/pages/WorkingDetail.tsx +++ b/web/src/views/UserMemoryDetail/pages/WorkingDetail.tsx @@ -2,7 +2,7 @@ import { type FC, useEffect, useState, useMemo } from 'react' import clsx from 'clsx' import { useTranslation } from 'react-i18next' import { useParams } from 'react-router-dom' -import { Row, Col, Select, Form, Space, Skeleton, Input, Button, Divider } from 'antd' +import { Row, Col, Skeleton, Button, Divider, Tooltip } from 'antd' import RbCard from '@/components/RbCard/Card' import { getConversations, @@ -10,7 +10,6 @@ import { getConversationDetail, } from '@/api/memory' import { formatDateTime } from '@/utils/format' -import Tag from '@/components/Tag' import RbAlert from '@/components/RbAlert' import Empty from '@/components/Empty' import ChatContent from '@/components/Chat/ChatContent' @@ -33,7 +32,6 @@ interface Detail { const WorkingDetail: FC = () => { const { t } = useTranslation() const { id } = useParams() - const [form] = Form.useForm() const [loading, setLoading] = useState(false) const [data, setData] = useState([]) const [messagesLoading, setMessagesLoading] = useState(false) @@ -110,13 +108,15 @@ const WorkingDetail: FC = () => {
{data.map(item => (
-
setSelected(item)} - > - {item.title} -
+ +
setSelected(item)} + > + {item.title} +
+
))}
diff --git a/web/src/views/UserMemoryDetail/pages/index.tsx b/web/src/views/UserMemoryDetail/pages/index.tsx index 16004edc..c5dea163 100644 --- a/web/src/views/UserMemoryDetail/pages/index.tsx +++ b/web/src/views/UserMemoryDetail/pages/index.tsx @@ -2,6 +2,7 @@ import { type FC, useEffect, useState, useMemo, useRef } from 'react' import { useParams, useNavigate } from 'react-router-dom' import { useTranslation } from 'react-i18next' import { Dropdown, Button } from 'antd' +import { LoadingOutlined } from '@ant-design/icons'; import PageHeader from '../components/PageHeader' import StatementDetail from './StatementDetail' @@ -46,18 +47,30 @@ const Detail: FC = () => { const onClick = ({ key }: { key: string }) => { navigate(`/user-memory/detail/${id}/${key}`, { replace: true }) } + + const [loading, setLoading] = useState(false) const handleRefresh = () => { + setLoading(true) + let response: any = null switch(type) { case 'FORGET_MEMORY': forgetDetailRef.current?.handleRefresh() break; case 'EMOTIONAL_MEMORY': - statementDetailRef.current?.handleRefresh() + response = statementDetailRef.current?.handleRefresh() break case 'IMPLICIT_MEMORY': - implicitDetailRef.current?.handleRefresh() + response = implicitDetailRef.current?.handleRefresh() break } + + if (response instanceof Promise) { + response.finally(() => { + setLoading(false) + }) + } else { + setLoading(false) + } } if (type === 'GRAPH') { @@ -80,8 +93,8 @@ const Detail: FC = () => { } extra={['FORGET_MEMORY', 'EMOTIONAL_MEMORY', 'IMPLICIT_MEMORY'].includes(type as string) && - } />