feat(web): work memory support page

This commit is contained in:
zhaoying
2026-03-19 18:41:33 +08:00
parent 6bc4f04293
commit 27b782e12a
2 changed files with 49 additions and 23 deletions

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing * @Author: ZhaoYing
* @Date: 2026-02-03 14:00:06 * @Date: 2026-02-03 14:00:06
* @Last Modified by: ZhaoYing * @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-13 10:48:41 * @Last Modified time: 2026-03-19 18:35:10
*/ */
import { request } from '@/utils/request' import { request } from '@/utils/request'
import type { AxiosRequestConfig } from 'axios' import type { AxiosRequestConfig } from 'axios'
@@ -218,8 +218,8 @@ export const getExplicitMemory = (end_user_id: string) => {
export const getExplicitMemoryDetails = (data: { end_user_id: string, memory_id: string; }) => { export const getExplicitMemoryDetails = (data: { end_user_id: string, memory_id: string; }) => {
return request.post(`/memory/explicit-memory/details`, data) return request.post(`/memory/explicit-memory/details`, data)
} }
export const getConversations = (end_user_id: string) => { export const getConversations = (end_user_id: string, page = 1, pagesize = 20) => {
return request.get(`/memory/work/${end_user_id}/conversations`) return request.get(`/memory/work/${end_user_id}/conversations`, { page, pagesize })
} }
export const getConversationMessages = (end_user_id: string, conversation_id: string) => { export const getConversationMessages = (end_user_id: string, conversation_id: string) => {
return request.get(`/memory/work/${end_user_id}/messages`, { conversation_id }) return request.get(`/memory/work/${end_user_id}/messages`, { conversation_id })

View File

@@ -1,8 +1,10 @@
import { type FC, useEffect, useState, useMemo } from 'react' import { type FC, useEffect, useState, useMemo, useRef } 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, Skeleton, Button, Divider, Tooltip } from 'antd' import { Row, Col, Skeleton, Button, Divider, Tooltip } from 'antd'
import InfiniteScroll from 'react-infinite-scroll-component'
import RbCard from '@/components/RbCard/Card' import RbCard from '@/components/RbCard/Card'
import { import {
getConversations, getConversations,
@@ -34,6 +36,8 @@ const WorkingDetail: FC = () => {
const { id } = useParams() const { id } = useParams()
const [loading, setLoading] = useState<boolean>(false) const [loading, setLoading] = useState<boolean>(false)
const [data, setData] = useState<Conversation[]>([]) const [data, setData] = useState<Conversation[]>([])
const [hasMore, setHasMore] = useState<boolean>(true)
const pageRef = useRef<number>(1)
const [messagesLoading, setMessagesLoading] = useState<boolean>(false) const [messagesLoading, setMessagesLoading] = useState<boolean>(false)
const [messages, setMessages] = useState<ChatItem[]>([]) const [messages, setMessages] = useState<ChatItem[]>([])
const [detailLoading, setDetailLoading] = useState<boolean>(false) const [detailLoading, setDetailLoading] = useState<boolean>(false)
@@ -51,16 +55,30 @@ const WorkingDetail: FC = () => {
setSelected(null) setSelected(null)
setDetail(null) setDetail(null)
setData([]) setData([])
getConversations(id).then((res) => { setHasMore(true)
const response = res as Conversation[] pageRef.current = 1
setData(response) getConversations(id, 1).then((res) => {
setSelected(response[0] || null) const response = res as { items: Conversation[], page: { hasnext: boolean } }
setData(response.items)
setSelected(response.items[0] || null)
setHasMore(response.page.hasnext)
}) })
.finally(() => { .finally(() => {
setLoading(false) setLoading(false)
}) })
} }
const loadMore = () => {
if (!id) return
const nextPage = pageRef.current + 1
getConversations(id, nextPage).then((res) => {
const response = res as {items: Conversation[], page: { hasnext: boolean }}
setData(prev => [...prev, ...response.items])
pageRef.current = nextPage
setHasMore(response.page.hasnext)
})
}
useEffect(() => { useEffect(() => {
if (!id || !selected || !selected.id) return if (!id || !selected || !selected.id) return
getDetail(selected.id) getDetail(selected.id)
@@ -103,22 +121,30 @@ const WorkingDetail: FC = () => {
: data.length === 0 : data.length === 0
? <Empty /> ? <Empty />
:( :(
<Row gutter={16} className="rb:h-full"> <Row gutter={16}>
<Col span={5}> <Col span={5}>
<div className="rb:h-full! rb:border-r rb:border-[#EAECEE] rb:py-3 rb:px-4"> <div id="conversation-list" className="rb:h-[calc(100vh-76px)]! rb:border-r rb:border-[#EAECEE] rb:py-3 rb:px-4 rb:overflow-y-auto">
{data.map(item => ( <InfiniteScroll
<div key={item.id} className="rb:mb-3"> dataLength={data.length}
<Tooltip title={item.title}> next={loadMore}
<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", { hasMore={hasMore}
'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, loader={null}
})} scrollableTarget="conversation-list"
onClick={() => setSelected(item)} >
> {data.map(item => (
{item.title} <div key={item.id} className="rb:mb-3">
</div> <Tooltip title={item.title}>
</Tooltip> <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", {
</div> '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)}
>
{item.title}
</div>
</Tooltip>
</div>
))}
</InfiniteScroll>
</div> </div>
</Col> </Col>
{selected && <> {selected && <>