feat(web): user memory feature optimize
This commit is contained in:
@@ -2064,6 +2064,7 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
|
|||||||
stability: 'Stability',
|
stability: 'Stability',
|
||||||
resilience: 'Resilience',
|
resilience: 'Resilience',
|
||||||
suggestions: 'Personalized Suggestions',
|
suggestions: 'Personalized Suggestions',
|
||||||
|
suggestionLoading: 'Your personalized suggestions are being generated',
|
||||||
},
|
},
|
||||||
reflectionEngine: {
|
reflectionEngine: {
|
||||||
reflectionEngineConfig: 'Reflection Engine Configuration',
|
reflectionEngineConfig: 'Reflection Engine Configuration',
|
||||||
|
|||||||
@@ -2158,6 +2158,7 @@ export const zh = {
|
|||||||
stability: '稳定性',
|
stability: '稳定性',
|
||||||
resilience: '恢复力',
|
resilience: '恢复力',
|
||||||
suggestions: '个性化建议',
|
suggestions: '个性化建议',
|
||||||
|
suggestionLoading: '您的个性化建议正在生成中',
|
||||||
},
|
},
|
||||||
reflectionEngine: {
|
reflectionEngine: {
|
||||||
reflectionEngineConfig: '反思引擎配置',
|
reflectionEngineConfig: '反思引擎配置',
|
||||||
|
|||||||
@@ -35,13 +35,13 @@ const PageHeader: FC<ConfigHeaderProps> = ({
|
|||||||
{operation}
|
{operation}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Space size={12}>
|
<div className="rb:flex rb:items-center rb:gap-3">
|
||||||
<Button type="primary" ghost className="rb:group rb:h-6! rb:px-2!" 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" />
|
<img src={logoutIcon} className="rb:w-4 rb:h-4" />
|
||||||
{t('common.return')}
|
{t('common.return')}
|
||||||
</Button>
|
</Button>
|
||||||
{extra}
|
{extra}
|
||||||
</Space>
|
</div>
|
||||||
</Header>
|
</Header>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ const RelationshipNetwork:FC = () => {
|
|||||||
size={[197.81, 150]}
|
size={[197.81, 150]}
|
||||||
/>
|
/>
|
||||||
: <>
|
: <>
|
||||||
<div className="rb:bg-[#F6F8FC] rb:border-t rb:border-b rb:border-[#DFE4ED] rb:font-medium rb:py-2 rb:px-4 rb:h-10">{selectedNode.name}</div>
|
{selectedNode.name && <div className="rb:bg-[#F6F8FC] rb:border-t rb:border-b rb:border-[#DFE4ED] rb:font-medium rb:py-2 rb:px-4 rb:h-10">{selectedNode.name}</div>}
|
||||||
<div className="rb:p-4">
|
<div className="rb:p-4">
|
||||||
<>
|
<>
|
||||||
<div className="rb:font-medium rb:leading-5">{t('userMemory.memoryContent')}</div>
|
<div className="rb:font-medium rb:leading-5">{t('userMemory.memoryContent')}</div>
|
||||||
@@ -297,7 +297,8 @@ const RelationshipNetwork:FC = () => {
|
|||||||
{selectedNode.label === 'Statement' && <>
|
{selectedNode.label === 'Statement' && <>
|
||||||
{(['emotion_keywords', 'emotion_type', 'emotion_subject', 'importance_score'] as const).map(key => {
|
{(['emotion_keywords', 'emotion_type', 'emotion_subject', 'importance_score'] as const).map(key => {
|
||||||
const statementProps = selectedNode.properties as StatementNodeProperties;
|
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 (
|
return (
|
||||||
<div className="rb:mt-4" key={key}>
|
<div className="rb:mt-4" key={key}>
|
||||||
{t(`userMemory.Statement_${key}`)}
|
{t(`userMemory.Statement_${key}`)}
|
||||||
@@ -321,7 +322,10 @@ const RelationshipNetwork:FC = () => {
|
|||||||
<div className="rb:mt-4" key={key}>
|
<div className="rb:mt-4" key={key}>
|
||||||
{t(`userMemory.ExtractedEntity_${key}`)}
|
{t(`userMemory.ExtractedEntity_${key}`)}
|
||||||
<div className="rb:text-[#5B6167] rb:font-regular rb:leading-5 rb:mt-1 rb:pb-4 rb:border-b rb:border-[#DFE4ED]">
|
<div className="rb:text-[#5B6167] rb:font-regular rb:leading-5 rb:mt-1 rb:pb-4 rb:border-b rb:border-[#DFE4ED]">
|
||||||
{entityProps[key]}
|
{Array.isArray(entityProps[key]) && entityProps[key].length > 0
|
||||||
|
? entityProps[key].map((vo, index) => <div key={index}>- {vo}</div>)
|
||||||
|
: entityProps[key]
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ interface Suggestions {
|
|||||||
const Suggestions = forwardRef<{ handleRefresh: () => void; }>((_props, ref) => {
|
const Suggestions = forwardRef<{ handleRefresh: () => void; }>((_props, ref) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
const [suggestions, setSuggestions] = useState<Suggestions | null>(null)
|
const [suggestions, setSuggestions] = useState<Suggestions | null>(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -31,10 +32,14 @@ const Suggestions = forwardRef<{ handleRefresh: () => void; }>((_props, ref) =>
|
|||||||
if (!id) {
|
if (!id) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
setLoading(true)
|
||||||
getEmotionSuggestions(id)
|
getEmotionSuggestions(id)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setSuggestions(res as Suggestions)
|
setSuggestions(res as Suggestions)
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setLoading(false)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
@@ -63,7 +68,7 @@ const Suggestions = forwardRef<{ handleRefresh: () => void; }>((_props, ref) =>
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
: <Empty size={88} className="rb:h-full" />
|
: <Empty size={88} subTitle={t(loading ? 'statementDetail.suggestionLoading' : 'empty.tableEmpty')} className="rb:h-full" />
|
||||||
}
|
}
|
||||||
</RbCard>
|
</RbCard>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,14 +20,22 @@ const ImplicitDetail = forwardRef<{ handleRefresh: () => void; }>((_props, ref)
|
|||||||
const habitsRef = useRef<{ handleRefresh: () => void; }>(null)
|
const habitsRef = useRef<{ handleRefresh: () => void; }>(null)
|
||||||
|
|
||||||
const handleRefresh = () => {
|
const handleRefresh = () => {
|
||||||
if (!id) return
|
if (!id) {
|
||||||
generateProfile(id)
|
return Promise.resolve()
|
||||||
.then(() => {
|
}
|
||||||
preferencesRef.current?.handleRefresh()
|
return new Promise((resolve, reject) => {
|
||||||
portraitRef.current?.handleRefresh()
|
generateProfile(id)
|
||||||
interestAreasRef.current?.handleRefresh()
|
.then(() => {
|
||||||
habitsRef.current?.handleRefresh()
|
preferencesRef.current?.handleRefresh()
|
||||||
})
|
portraitRef.current?.handleRefresh()
|
||||||
|
interestAreasRef.current?.handleRefresh()
|
||||||
|
habitsRef.current?.handleRefresh()
|
||||||
|
resolve(true)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
handleRefresh
|
handleRefresh
|
||||||
|
|||||||
@@ -13,11 +13,20 @@ const StatementDetail = forwardRef((_props, ref) => {
|
|||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
const suggestionsRef = useRef<{ handleRefresh: () => void; }>(null)
|
const suggestionsRef = useRef<{ handleRefresh: () => void; }>(null)
|
||||||
const handleRefresh = () => {
|
const handleRefresh = () => {
|
||||||
if (!id) return
|
if (!id) {
|
||||||
generateSuggestions(id)
|
return Promise.resolve()
|
||||||
.then(() => {
|
}
|
||||||
suggestionsRef.current?.handleRefresh()
|
|
||||||
})
|
return new Promise((resolve, reject) => {
|
||||||
|
generateSuggestions(id)
|
||||||
|
.then(() => {
|
||||||
|
suggestionsRef.current?.handleRefresh()
|
||||||
|
resolve(true)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
handleRefresh
|
handleRefresh
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { type FC, useEffect, useState, useMemo } from 'react'
|
|||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
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, 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 RbCard from '@/components/RbCard/Card'
|
||||||
import {
|
import {
|
||||||
getConversations,
|
getConversations,
|
||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
getConversationDetail,
|
getConversationDetail,
|
||||||
} from '@/api/memory'
|
} from '@/api/memory'
|
||||||
import { formatDateTime } from '@/utils/format'
|
import { formatDateTime } from '@/utils/format'
|
||||||
import Tag from '@/components/Tag'
|
|
||||||
import RbAlert from '@/components/RbAlert'
|
import RbAlert from '@/components/RbAlert'
|
||||||
import Empty from '@/components/Empty'
|
import Empty from '@/components/Empty'
|
||||||
import ChatContent from '@/components/Chat/ChatContent'
|
import ChatContent from '@/components/Chat/ChatContent'
|
||||||
@@ -33,7 +32,6 @@ interface Detail {
|
|||||||
const WorkingDetail: FC = () => {
|
const WorkingDetail: FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
const [form] = Form.useForm()
|
|
||||||
const [loading, setLoading] = useState<boolean>(false)
|
const [loading, setLoading] = useState<boolean>(false)
|
||||||
const [data, setData] = useState<Conversation[]>([])
|
const [data, setData] = useState<Conversation[]>([])
|
||||||
const [messagesLoading, setMessagesLoading] = useState<boolean>(false)
|
const [messagesLoading, setMessagesLoading] = useState<boolean>(false)
|
||||||
@@ -110,13 +108,15 @@ const WorkingDetail: FC = () => {
|
|||||||
<div className="rb:h-full! rb:border-r rb:border-[#EAECEE] rb:py-3 rb:px-4">
|
<div className="rb:h-full! rb:border-r rb:border-[#EAECEE] rb:py-3 rb:px-4">
|
||||||
{data.map(item => (
|
{data.map(item => (
|
||||||
<div key={item.id} className="rb:mb-3">
|
<div key={item.id} className="rb:mb-3">
|
||||||
<div className={clsx("rb:p-[8px_13px] rb:rounded-lg rb:leading-5 rb:cursor-pointer rb:hover:bg-[#F0F3F8]", {
|
<Tooltip title={item.title}>
|
||||||
'rb:bg-[#FFFFFF] rb:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.15)] rb:font-medium rb:hover:bg-[#FFFFFF]!': item.id === selected?.id,
|
<div className={clsx("rb:p-[8px_13px] rb:rounded-lg rb:leading-5 rb:cursor-pointer rb:hover:bg-[#F0F3F8] rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap", {
|
||||||
})}
|
'rb:bg-[#FFFFFF] rb:shadow-[0px_2px_4px_0px_rgba(0,0,0,0.15)] rb:font-medium rb:hover:bg-[#FFFFFF]!': item.id === selected?.id,
|
||||||
onClick={() => setSelected(item)}
|
})}
|
||||||
>
|
onClick={() => setSelected(item)}
|
||||||
{item.title}
|
>
|
||||||
</div>
|
{item.title}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { type FC, useEffect, useState, useMemo, useRef } from 'react'
|
|||||||
import { useParams, useNavigate } from 'react-router-dom'
|
import { useParams, useNavigate } from 'react-router-dom'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Dropdown, Button } from 'antd'
|
import { Dropdown, Button } from 'antd'
|
||||||
|
import { LoadingOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
import PageHeader from '../components/PageHeader'
|
import PageHeader from '../components/PageHeader'
|
||||||
import StatementDetail from './StatementDetail'
|
import StatementDetail from './StatementDetail'
|
||||||
@@ -46,18 +47,30 @@ const Detail: FC = () => {
|
|||||||
const onClick = ({ key }: { key: string }) => {
|
const onClick = ({ key }: { key: string }) => {
|
||||||
navigate(`/user-memory/detail/${id}/${key}`, { replace: true })
|
navigate(`/user-memory/detail/${id}/${key}`, { replace: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
const handleRefresh = () => {
|
const handleRefresh = () => {
|
||||||
|
setLoading(true)
|
||||||
|
let response: any = null
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case 'FORGET_MEMORY':
|
case 'FORGET_MEMORY':
|
||||||
forgetDetailRef.current?.handleRefresh()
|
forgetDetailRef.current?.handleRefresh()
|
||||||
break;
|
break;
|
||||||
case 'EMOTIONAL_MEMORY':
|
case 'EMOTIONAL_MEMORY':
|
||||||
statementDetailRef.current?.handleRefresh()
|
response = statementDetailRef.current?.handleRefresh()
|
||||||
break
|
break
|
||||||
case 'IMPLICIT_MEMORY':
|
case 'IMPLICIT_MEMORY':
|
||||||
implicitDetailRef.current?.handleRefresh()
|
response = implicitDetailRef.current?.handleRefresh()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response instanceof Promise) {
|
||||||
|
response.finally(() => {
|
||||||
|
setLoading(false)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'GRAPH') {
|
if (type === 'GRAPH') {
|
||||||
@@ -80,8 +93,8 @@ const Detail: FC = () => {
|
|||||||
</Dropdown>
|
</Dropdown>
|
||||||
}
|
}
|
||||||
extra={['FORGET_MEMORY', 'EMOTIONAL_MEMORY', 'IMPLICIT_MEMORY'].includes(type as string) &&
|
extra={['FORGET_MEMORY', 'EMOTIONAL_MEMORY', 'IMPLICIT_MEMORY'].includes(type as string) &&
|
||||||
<Button type="primary" ghost className="rb:group rb:h-6! rb:px-2!" onClick={handleRefresh}>
|
<Button type="primary" ghost size="small" className="rb:h-6! rb:px-2! rb:leading-5.5!" loading={loading} onClick={handleRefresh}>
|
||||||
<img src={refreshIcon} className="rb:w-4 rb:h-4" />
|
{!loading && <img src={refreshIcon} className="rb:w-4 rb:h-4" /> }
|
||||||
{t('common.refresh')}
|
{t('common.refresh')}
|
||||||
</Button>}
|
</Button>}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user