Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
sdream-ai-fe
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
侯明涛
sdream-ai-fe
Commits
30e06255
Commit
30e06255
authored
Aug 09, 2024
by
HoMeTown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 新建会话
parent
7a829213
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
103 additions
and
12 deletions
+103
-12
src/api/conversation.ts
+9
-1
src/auth/AuthContext.tsx
+1
-1
src/layouts/HistoryBar/components/HistoryBarList/index.tsx
+6
-2
src/layouts/Navbar/Navbar.tsx
+24
-0
src/layouts/Navbar/components/NavBarItem/NavBarItem.tsx
+12
-1
src/pages/Chat/Chat.tsx
+13
-3
src/routes/AppRoutes.tsx
+1
-1
src/store/conversationSlice.ts
+36
-3
src/types/conversation.ts
+1
-0
No files found.
src/api/conversation.ts
View file @
30e06255
...
...
@@ -4,6 +4,14 @@ import http from '@/utils/request'
* 查询用户历史会话列表
* @params
*/
export
function
q
ueryUserConversationPage
<
T
>
(
data
:
T
)
{
export
function
fetchQ
ueryUserConversationPage
<
T
>
(
data
:
T
)
{
return
http
.
post
(
'/conversation/api/conversation/mobile/v1/query_user_conversation_page'
,
data
)
}
/**
* 创建会话
* @params { * }
*/
export
function
fetchCreateConversation
<
T
>
(
data
:
T
)
{
return
http
.
post
(
'/conversation/api/conversation/mobile/v1/create_conversation'
,
data
)
}
src/auth/AuthContext.tsx
View file @
30e06255
...
...
@@ -33,7 +33,7 @@ export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
const
[
showLoginTip
,
setShowLoginTip
]
=
useState
(
!
token
)
const
login
=
async
()
=>
{
const
res
=
await
fetchLoginByUid
(
'123'
)
const
res
=
await
fetchLoginByUid
(
'123
123
'
)
if
(
res
.
data
)
{
setToken
(
res
.
data
.
token
)
setIsLoggedIn
(
true
)
...
...
src/layouts/HistoryBar/components/HistoryBarList/index.tsx
View file @
30e06255
...
...
@@ -5,7 +5,7 @@ import EmptyIcon from '@/assets/svg/empty.svg?react'
import
{
useAppSelector
}
from
'@/store/hook'
export
const
HistoryBarList
:
React
.
FC
=
()
=>
{
const
{
conversations
}
=
useAppSelector
(
state
=>
state
.
conversation
)
const
{
c
urrentConversationId
,
c
onversations
}
=
useAppSelector
(
state
=>
state
.
conversation
)
return
(
conversations
.
length
!==
0
...
...
@@ -30,7 +30,11 @@ export const HistoryBarList: React.FC = () => {
{
item
.
conversationId
?
(
<
Button
color=
"primary"
variant=
"light"
className=
"text-left w-full text-[#333] rounded-[23px] data-[hover=true]:bg-[#E5F6FF] data-[hover=true]:text-primary"
>
<
Button
color=
"primary"
variant=
"light"
className=
{
`text-left w-full text-[#333] rounded-[23px] data-[hover=true]:bg-[#E5F6FF] data-[hover=true]:text-primary ${currentConversationId === item.conversationId ? 'bg-[#E5F6FF] text-primary' : ''}`
}
>
<
div
className=
"w-full text-nowrap text-ellipsis overflow-hidden"
>
<
span
>
{
item
.
conversationTitle
}
</
span
>
</
div
>
...
...
src/layouts/Navbar/Navbar.tsx
View file @
30e06255
import
type
React
from
'react'
import
{
motion
}
from
'framer-motion'
import
{
useEffect
}
from
'react'
import
{
useNavigate
}
from
'react-router-dom'
import
styles
from
'./Navbar.module.less'
import
{
NavBarItem
}
from
'./components/NavBarItem'
import
{
User
}
from
'./components/User'
import
{
clearNavigationFlag
,
createConversation
}
from
'@/store/conversationSlice'
import
type
{
WithAuthProps
}
from
'@/auth/withAuth'
import
{
withAuth
}
from
'@/auth/withAuth'
import
{
NAV_BAR_ITEMS
}
from
'@/config/nav'
import
{
useAppDispatch
,
useAppSelector
}
from
'@/store/hook'
interface
NavbarProps
{
isHistoryVisible
:
boolean
...
...
@@ -13,10 +17,23 @@ interface NavbarProps {
}
const
NavbarBase
:
React
.
FC
<
NavbarProps
&
WithAuthProps
>
=
({
isHistoryVisible
,
checkAuth
,
onSetHistoryVisible
})
=>
{
const
dispatch
=
useAppDispatch
()
const
navigate
=
useNavigate
()
const
{
currentConversationId
,
shouldNavigateToNewConversation
}
=
useAppSelector
(
state
=>
state
.
conversation
)
const
handleCreateConversation
=
()
=>
{
dispatch
(
createConversation
({}))
}
const
handleClick
=
(
type
:
string
|
undefined
)
=>
{
if
(
!
checkAuth
())
return
if
(
type
===
'add'
)
{
handleCreateConversation
()
}
if
(
type
===
'history'
)
{
onSetHistoryVisible
(
!
isHistoryVisible
)
}
...
...
@@ -25,6 +42,13 @@ const NavbarBase: React.FC<NavbarProps & WithAuthProps> = ({ isHistoryVisible, c
onSetHistoryVisible
(
false
)
}
useEffect
(()
=>
{
if
(
shouldNavigateToNewConversation
&&
currentConversationId
)
{
navigate
(
`/chat/
${
currentConversationId
}
`
)
dispatch
(
clearNavigationFlag
())
}
},
[
shouldNavigateToNewConversation
,
currentConversationId
,
navigate
,
dispatch
])
return
(
<
motion
.
nav
className=
"h-full flex-shrink-0 flex flex-col items-center justify-center"
>
<
motion
.
div
className=
{
`${styles.layoutNavBarAgent} sm:flex hidden w-[64px] bg-white gap-[24px]`
}
>
...
...
src/layouts/Navbar/components/NavBarItem/NavBarItem.tsx
View file @
30e06255
import
React
from
'react'
import
{
motion
}
from
'framer-motion'
import
{
Button
,
Tooltip
}
from
'@nextui-org/react'
import
{
useNavigate
}
from
'react-router-dom'
import
{
NavBarDivider
}
from
'../NavBarDivider'
import
styles
from
'./NavBarItem.module.less'
import
Logo
from
'@/assets/svg/logo.svg?react'
...
...
@@ -12,12 +13,22 @@ interface NavBarItemProps {
type
:
string
}
export
const
NavBarItem
:
React
.
FC
<
NavBarItemProps
>
=
({
onClick
,
icon
,
label
,
type
})
=>
{
const
navigate
=
useNavigate
()
const
handleClickLogo
=
()
=>
{
navigate
(
'/'
)
}
if
(
label
===
''
&&
icon
===
''
)
{
return
<
NavBarDivider
/>
}
if
(
label
===
''
&&
icon
!==
''
)
{
return
(
<
motion
.
div
className=
"nav-logo"
>
<
motion
.
div
whileHover=
{
{
scale
:
1.05
}
}
transition=
{
{
type
:
'spring'
,
stiffness
:
400
,
damping
:
10
}
}
className=
"nav-logo cursor-pointer"
onClick=
{
handleClickLogo
}
>
<
Logo
/>
</
motion
.
div
>
)
...
...
src/pages/Chat/Chat.tsx
View file @
30e06255
import
React
from
'react'
import
React
,
{
useEffect
}
from
'react'
import
{
useParams
}
from
'react-router-dom'
import
{
useAppDispatch
,
useAppSelector
}
from
'@/store/hook'
import
{
setCurrentConversation
}
from
'@/store/conversationSlice'
export
const
Chat
:
React
.
FC
=
()
=>
{
const
{
chatId
}
=
useParams
<
{
chatId
:
string
}
>
()
const
{
id
}
=
useParams
<
{
id
:
string
}
>
()
const
dispatch
=
useAppDispatch
()
const
{
currentConversationId
}
=
useAppSelector
(
state
=>
state
.
conversation
)
useEffect
(()
=>
{
if
(
id
&&
id
!==
currentConversationId
)
{
dispatch
(
setCurrentConversation
(
id
))
// dispatch(fetchConversationDetails(id))
}
},
[
id
,
currentConversationId
,
dispatch
])
return
(
<
h1
>
聊天页面 - Chat ID:
{
chatI
d
}
{
i
d
}
</
h1
>
)
}
src/routes/AppRoutes.tsx
View file @
30e06255
...
...
@@ -7,7 +7,7 @@ export const AppRoutes: React.FC = () => {
return
(
<
Routes
>
<
Route
path=
"/"
element=
{
<
Home
/>
}
/>
<
Route
path=
"/chat/:
chatI
d"
element=
{
<
Chat
/>
}
/>
<
Route
path=
"/chat/:
i
d"
element=
{
<
Chat
/>
}
/>
</
Routes
>
)
}
src/store/conversationSlice.ts
View file @
30e06255
...
...
@@ -2,20 +2,21 @@ import type { PayloadAction } from '@reduxjs/toolkit'
import
{
createAsyncThunk
,
createSlice
}
from
'@reduxjs/toolkit'
import
{
processConversationData
}
from
'./conversationSlice.helper'
import
type
{
Conversation
,
ConversationState
}
from
'@/types/conversation'
import
{
q
ueryUserConversationPage
}
from
'@/api/conversation'
import
{
fetchCreateConversation
,
fetchQ
ueryUserConversationPage
}
from
'@/api/conversation'
const
initialState
:
ConversationState
=
{
conversations
:
[],
currentConversationId
:
null
,
isLoading
:
false
,
error
:
null
,
shouldNavigateToNewConversation
:
false
,
}
export
const
fetchConversations
=
createAsyncThunk
(
'conversation/fetchConversations'
,
async
(
_
,
{
rejectWithValue
})
=>
{
try
{
const
response
=
await
q
ueryUserConversationPage
({
const
response
=
await
fetchQ
ueryUserConversationPage
({
keyword
:
''
,
pageNum
:
0
,
pageSize
:
100
,
...
...
@@ -30,6 +31,22 @@ export const fetchConversations = createAsyncThunk(
},
)
export
const
createConversation
=
createAsyncThunk
<
{
conversation
:
Conversation
,
shouldNavigate
:
boolean
},
Partial
<
Conversation
>
,
{
state
:
{
conversation
:
ConversationState
}
}
>
(
'conversation/createConversation'
,
async
(
conversationData
,
{
dispatch
})
=>
{
const
response
=
await
fetchCreateConversation
(
conversationData
)
const
newConversation
=
response
.
data
dispatch
(
fetchConversations
())
return
{
conversation
:
newConversation
,
shouldNavigate
:
true
}
},
)
const
conversationSlice
=
createSlice
({
name
:
'conversation'
,
initialState
,
...
...
@@ -40,6 +57,9 @@ const conversationSlice = createSlice({
addConversation
:
(
state
,
action
:
PayloadAction
<
Conversation
>
)
=>
{
state
.
conversations
.
unshift
(
action
.
payload
)
},
clearNavigationFlag
:
(
state
)
=>
{
state
.
shouldNavigateToNewConversation
=
false
},
removeConversation
:
(
state
,
action
:
PayloadAction
<
string
>
)
=>
{
state
.
conversations
=
state
.
conversations
.
filter
(
conv
=>
conv
.
conversationId
!==
action
.
payload
)
if
(
state
.
currentConversationId
===
action
.
payload
)
{
...
...
@@ -61,9 +81,22 @@ const conversationSlice = createSlice({
state
.
isLoading
=
false
state
.
error
=
action
.
payload
as
string
})
.
addCase
(
createConversation
.
pending
,
(
state
)
=>
{
state
.
isLoading
=
true
state
.
error
=
null
})
.
addCase
(
createConversation
.
fulfilled
,
(
state
,
action
)
=>
{
state
.
isLoading
=
false
state
.
currentConversationId
=
action
.
payload
.
conversation
.
conversationId
state
.
shouldNavigateToNewConversation
=
action
.
payload
.
shouldNavigate
})
.
addCase
(
createConversation
.
rejected
,
(
state
,
action
)
=>
{
state
.
isLoading
=
false
state
.
error
=
action
.
error
.
message
||
'Failed to create conversation'
})
},
})
export
const
{
setCurrentConversation
}
=
conversationSlice
.
actions
export
const
{
setCurrentConversation
,
clearNavigationFlag
}
=
conversationSlice
.
actions
export
default
conversationSlice
.
reducer
src/types/conversation.ts
View file @
30e06255
...
...
@@ -11,5 +11,6 @@ export interface ConversationState {
conversations
:
Conversation
[]
currentConversationId
:
string
|
null
isLoading
:
boolean
shouldNavigateToNewConversation
:
boolean
error
:
string
|
null
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment