feat(web): work memory support page
This commit is contained in:
@@ -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 })
|
||||||
|
|||||||
@@ -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 && <>
|
||||||
|
|||||||
Reference in New Issue
Block a user