-
{t(`reflectionEngine.qualityAssessmentObj.${key}`)}
-
- {item[key as keyof QualityAssessment]}
-
+
+
+ }
+ {result.quality_assessments.length > 0 &&
+
+ setExpanded(p => ({ ...p, quality: !p.quality }))}>
+ {t('reflectionEngine.qualityAssessment')}
+
+
+
+ {expanded.quality && result.quality_assessments.map((item, index) => (
+
+
+ {t(`reflectionEngine.qualityAssessmentObj.score`)}
+ {item.score}
- ))}
-
- ))}
-
- )}
- {result.memory_verifies.length > 0 && (
-
- {result.memory_verifies.map((item, index) => (
-
- {['has_privacy', 'privacy_types', 'summary'].map(key => (
-
-
{t(`reflectionEngine.privacyAuditObj.${key}`)}
-
- {key === 'has_privacy'
- ? {t(`reflectionEngine.privacyAuditObj.${item[key as keyof MemoryVerify]}`)}
- : key === 'privacy_types' ? (item[key as keyof MemoryVerify] as string[]).join('、')
- : item[key as keyof MemoryVerify]
- }
-
+
+
{t(`reflectionEngine.qualityAssessmentObj.summary`)}
+
{item.summary}
+
+ ))}
+
+
+ }
+ {result.memory_verifies.length > 0 &&
+
+ setExpanded(p => ({ ...p, privacy: !p.privacy }))}>
+ {t('reflectionEngine.privacyAudit')}
+
+
+
+ {expanded.privacy && result.memory_verifies.map((item, index) => (
+
+
+ {t(`reflectionEngine.privacyAuditObj.has_privacy`)}
+ {item.has_privacy}
- ))}
-
- ))}
-
- )}
- >}
-
+
+
+
+
{t(`reflectionEngine.privacyAuditObj.privacy_types`)}
+
{item.privacy_types.join(', ')}
+
+
+
+
{t(`reflectionEngine.privacyAuditObj.summary`)}
+
{item.summary}
+
+ ))}
+
+
+ }
+ >}
+
+
);
diff --git a/web/src/views/UserMemoryDetail/pages/ExplicitDetail.tsx b/web/src/views/UserMemoryDetail/pages/ExplicitDetail.tsx
index 185ed02d..55623c7e 100644
--- a/web/src/views/UserMemoryDetail/pages/ExplicitDetail.tsx
+++ b/web/src/views/UserMemoryDetail/pages/ExplicitDetail.tsx
@@ -7,7 +7,8 @@
import { type FC, useEffect, useState, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { useParams } from 'react-router-dom'
-import { Skeleton, Row, Col, Flex } from 'antd'
+import { Skeleton, Row, Col, Flex, DatePicker, Pagination } from 'antd'
+import type { Dayjs } from 'dayjs'
import * as echarts from 'echarts'
import 'echarts-wordcloud'
@@ -41,6 +42,7 @@ export interface SemanticMemory {
/** Combined API response containing both memory categories. */
interface Data {
+ total: number;
episodic_memories: EpisodicMemory[];
semantic_memories: SemanticMemory[]
}
@@ -71,7 +73,19 @@ const ExplicitDetail: FC = () => {
/** Keeps a stable reference to the ECharts instance for cleanup. */
const chartInstance = useRef
(null)
const [loading, setLoading] = useState(false)
- const [data, setData] = useState({ episodic_memories: [], semantic_memories: [] })
+ const [data, setData] = useState({ episodic_memories: [], semantic_memories: [], total: 0 })
+ const [dateRange, setDateRange] = useState<[Dayjs | null, Dayjs | null] | null>(null)
+ const [page, setPage] = useState(1)
+ const PAGE_SIZE = 10
+
+ const filteredEpisodic = dateRange?.[0] && dateRange?.[1]
+ ? data.episodic_memories.filter(item => {
+ const ts = item.created_at
+ return ts >= dateRange[0]!.startOf('day').valueOf() && ts <= dateRange[1]!.endOf('day').valueOf()
+ })
+ : data.episodic_memories
+
+ const pagedEpisodic = filteredEpisodic.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE)
/* Fetch data whenever the route user ID changes. */
useEffect(() => {
@@ -131,35 +145,77 @@ const ExplicitDetail: FC = () => {
})
return () => { chartInstance.current?.dispose(); chartInstance.current = null }
}, [data.semantic_memories])
+
+ /* Redraw the word cloud when the container dimensions change. */
+ useEffect(() => {
+ const target = wordCloudRef.current?.parentElement
+ if (!target) return
+ const observer = new ResizeObserver(() => {
+ if (!chartInstance.current) return
+ chartInstance.current.resize()
+ chartInstance.current.setOption({ series: [{ type: 'wordCloud' }] })
+ })
+ observer.observe(target)
+ return () => {
+ observer.disconnect()
+ chartInstance.current?.dispose();
+ chartInstance.current = null
+ }
+ }, [])
+
return (
{t('explicitDetail.episodic_memories')}}
+ extra={{t('table.totalRecords', { total: data.total })}}
headerType="borderless"
- headerClassName="rb:min-h-[50px]! rb:font-[MiSans-Bold] rb:font-bold"
- bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-50px)] rb:overflow-y-auto!"
+ headerClassName="rb:min-h-[50px]!"
+ bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-50px)]"
className="rb:h-full!"
>
{loading ?
- : data.episodic_memories?.length > 0 ? (
-
- {data.episodic_memories.map(item => (
- handleView(item)}
- >
-
- {item.title}
- {formatDateTime(item.created_at)}
-
-
{item.content}
-
- ))}
+ : (
+
+
+
+ { setDateRange(val); setPage(1) }}
+ allowClear
+ />
+
+
+
+ {pagedEpisodic.length > 0 ? pagedEpisodic.map(item => (
+
handleView(item)}
+ >
+
+ {item.title}
+ {formatDateTime(item.created_at)}
+
+
{item.content}
+
+ )) :
}
+
+ {filteredEpisodic.length > PAGE_SIZE && (
+
+ )}
- ) :
+ )
}
diff --git a/web/src/views/UserMemoryDetail/pages/WorkingDetail.tsx b/web/src/views/UserMemoryDetail/pages/WorkingDetail.tsx
index 2e288988..fd4844a9 100644
--- a/web/src/views/UserMemoryDetail/pages/WorkingDetail.tsx
+++ b/web/src/views/UserMemoryDetail/pages/WorkingDetail.tsx
@@ -197,7 +197,7 @@ const WorkingDetail: FC = () => {
{selected && <>
-
+