import { type FC, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import clsx from 'clsx' import { Row, Col, Skeleton } from 'antd' import { useParams } from 'react-router-dom' import aboutUs from '@/assets/images/userMemory/aboutUs.svg' import down from '@/assets/images/userMemory/down.svg' import interestDistribution from '@/assets/images/userMemory/interestDistribution.svg' import RbCard from '@/components/RbCard/Card' import type { Data } from './types' import { getChunkSummaryTag, getUserProfile, getTotalRagMemoryCountByUser, getChunkInsight, } from '@/api/memory' import Empty from '@/components/Empty' import ConversationMemory from './components/ConversationMemory' const tagColors = ['21, 94, 239', '156, 111, 255', '255, 93, 52', '54, 159, 33'] interface TitleProps { type: string; title: string icon: string t: (key: string) => string; expanded: boolean; onClick: (type: string) => void; } const Title: FC = ({ type, title, icon, t, expanded, onClick }) => (
{title} onClick(type)}> {t(`userMemory.${expanded ? 'foldUp' : 'expanded'}`)}
) const Rag: FC = () => { const { t } = useTranslation() const { id } = useParams() const [data, setData] = useState(null) const [expanded, setExpanded] = useState(['aboutUs', 'memoryInsight',]) const [summary, setSummary] = useState('') const [loading, setLoading] = useState>({ detail: true, summary: true, insight: true, }) const [memory, setMemory] = useState(null) const [insight, setInsight] = useState('') const [tags, setTags] = useState<{ tag: string; frequency: number }[]>([]) const [personas, setPersonas] = useState([]) useEffect(() => { if (!id) return getMemory() getSummary() getDetail() getInsightReport() }, [id]) const handleTitleClick = (key: string) => { setExpanded(expanded.includes(key) ? expanded.filter((item) => item !== key) : [...expanded, key]) } // 用户记忆详情 const getDetail = () => { if (!id) return setLoading(prev => ({ ...prev, detail: true })) getUserProfile(id).then((res) => { setData((res as Data)) }) .finally(() => { setLoading(prev => ({ ...prev, detail: false })) }) } // 记忆总览 const getMemory = () => { if (!id) return getTotalRagMemoryCountByUser(id).then((res) => { setMemory(res as number || 0) }) } // 用户摘要 const getSummary = () => { if (!id) return setLoading(prev => ({ ...prev, summary: true })) getChunkSummaryTag(id).then((res) => { const response = res as { summary?: string; tags?: { tag: string; frequency: number }[]; personas?: string[] } setSummary(response.summary || null) setTags(response.tags || []) setPersonas(response.personas || []) }) .finally(() => { setLoading(prev => ({ ...prev, summary: false })) }) } // 记忆洞察 const getInsightReport = () => { if (!id) return setLoading(prev => ({ ...prev, insight: true })) getChunkInsight(id).then((res) => { setInsight((res as { insight?: string }).insight || null) }) .finally(() => { setLoading(prev => ({ ...prev, insight: false })) }) } const name = loading.detail ? '' : data?.name && data?.name !== '' ? data.name : id return (
{name?.[0]}
{name}
{personas?.join(' | ')}
{tags?.map((tag, tagIndex) => ( {tag.tag}({tag.frequency}) ))}
{/* 记忆总量 */}
{t('userMemory.totalNumOfMemories')}
{memory || 0}
{/* 关于我 */} <> {expanded.includes('aboutUs') && ( <> {loading.summary ? <Skeleton className="rb:mt-4" /> : summary ? <div className="rb:font-regular rb:leading-5.5 rb:pt-4"> {summary || '-'} </div> : <Empty size={88} className="rb:mt-12 rb:mb-20.25" /> } </> )} </> {/* 记忆洞察 */} <> <Title type="memoryInsight" title={t('userMemory.memoryInsight')} icon={interestDistribution} t={t} expanded={expanded.includes('memoryInsight')} onClick={handleTitleClick} /> {expanded.includes('memoryInsight') && ( <> {loading.insight ? <Skeleton className="rb:mt-4" /> : insight ? <div className="rb:font-regular rb:leading-5.5 rb:pt-4"> {insight || '-'} </div> : <Empty size={88} className="rb:mt-12 rb:mb-20.25" /> } </> )} </> </RbCard> </Col> <Col span={16}> <ConversationMemory /> </Col> </Row> ) } export default Rag