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
74833085
Commit
74833085
authored
Oct 22, 2025
by
Liu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:接入工具模式下展示推荐问接口
parent
cbeae79d
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
93 additions
and
85 deletions
+93
-85
src/api/home.ts
+9
-0
src/components/ChatEditor/index.tsx
+6
-6
src/pages/Chat/Chat.tsx
+2
-2
src/pages/Home/HomeNew.tsx
+33
-46
src/pages/Home/components/QuestionList/QuestionList.tsx
+43
-31
No files found.
src/api/home.ts
View file @
74833085
...
@@ -15,3 +15,12 @@ export function fetchQuestionList(data: any) {
...
@@ -15,3 +15,12 @@ export function fetchQuestionList(data: any) {
export
function
fetchToolList
()
{
export
function
fetchToolList
()
{
return
http
.
post
(
'/config-center/api/tool/mobile/v1/get_tool_list'
)
return
http
.
post
(
'/config-center/api/tool/mobile/v1/get_tool_list'
)
}
}
/**
* 查询 提质增效 推荐问题列表
* @params
* toolId: 工具id
*/
export
function
fetchEfficiencyQuestionList
(
data
:
any
)
{
return
http
.
post
(
'/conversation/api/conversation/mobile/v1/generate_gueston'
,
data
)
}
src/components/ChatEditor/index.tsx
View file @
74833085
...
@@ -14,7 +14,7 @@ interface ChatEditorProps {
...
@@ -14,7 +14,7 @@ interface ChatEditorProps {
onChange
?:
(
value
:
string
)
=>
void
onChange
?:
(
value
:
string
)
=>
void
onFocus
?:
()
=>
void
onFocus
?:
()
=>
void
onSubmit
?:
(
value
:
string
,
toolId
?:
string
)
=>
void
onSubmit
?:
(
value
:
string
,
toolId
?:
string
)
=>
void
onToolClick
?:
(
isToolBtn
:
boolean
)
=>
void
onToolClick
?:
(
isToolBtn
:
boolean
,
toolId
?:
string
)
=>
void
placeholders
:
string
[]
placeholders
:
string
[]
showContentTips
?:
boolean
showContentTips
?:
boolean
initialValue
?:
string
initialValue
?:
string
...
@@ -115,23 +115,23 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
...
@@ -115,23 +115,23 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
const
handleToolClick
=
()
=>
{
const
handleToolClick
=
()
=>
{
// 查找"提质增效"工具
// 查找"提质增效"工具
const
efficiencyTool
=
toolList
.
find
((
tool
:
any
)
=>
tool
.
toolName
===
'提质增效'
)
const
efficiencyTool
=
toolList
.
find
((
tool
:
any
)
=>
tool
.
toolName
===
'提质增效'
)
let
currentToolId
=
null
if
(
efficiencyTool
)
{
if
(
efficiencyTool
)
{
setSelectedToolId
(
efficiencyTool
.
toolId
)
setSelectedToolId
(
efficiencyTool
.
toolId
)
currentToolId
=
efficiencyTool
.
toolId
}
}
else
{
else
{
// 如果没有找到"提质增效"工具,使用第一个工具
// 如果没有找到"提质增效"工具,使用第一个工具
if
(
toolList
.
length
>
0
)
{
if
(
toolList
.
length
>
0
)
{
setSelectedToolId
(
toolList
[
0
].
toolId
)
setSelectedToolId
(
toolList
[
0
].
toolId
)
currentToolId
=
toolList
[
0
].
toolId
}
}
}
}
// 切换工具按钮状态
// 切换工具按钮状态
const
newToolBtnState
=
!
isToolBtnActive
const
newToolBtnState
=
!
isToolBtnActive
setIsToolBtnActive
(
newToolBtnState
)
setIsToolBtnActive
(
newToolBtnState
)
// 打印传递的参数 isToolBtn
// 调用父组件的回调函数,传递切换后的状态和工具ID
// eslint-disable-next-line no-console
onToolClick
?.(
newToolBtnState
,
currentToolId
)
console
.
log
(
'ChatEditor 组件接收到 isToolBtn 参数:'
,
newToolBtnState
)
// 调用父组件的回调函数,传递切换后的状态
onToolClick
?.(
newToolBtnState
)
}
}
useEffect
(()
=>
{
useEffect
(()
=>
{
...
...
src/pages/Chat/Chat.tsx
View file @
74833085
...
@@ -333,10 +333,10 @@ export const Chat: React.FC = () => {
...
@@ -333,10 +333,10 @@ export const Chat: React.FC = () => {
</
div
>
</
div
>
<
ChatEditor
<
ChatEditor
onSubmit=
{
(
question
,
toolId
)
=>
handleSubmitQuestion
(
question
,
undefined
,
toolId
)
}
onSubmit=
{
(
question
,
toolId
)
=>
handleSubmitQuestion
(
question
,
undefined
,
toolId
)
}
onToolClick=
{
(
isToolBtn
)
=>
{
onToolClick=
{
(
isToolBtn
,
toolId
)
=>
{
// 发送自定义事件到父组件
// 发送自定义事件到父组件
window
.
dispatchEvent
(
new
CustomEvent
(
'toolButtonClick'
,
{
window
.
dispatchEvent
(
new
CustomEvent
(
'toolButtonClick'
,
{
detail
:
{
isToolBtn
},
detail
:
{
isToolBtn
,
toolId
},
}))
}))
}
}
}
}
placeholders=
{
[]
}
placeholders=
{
[]
}
...
...
src/pages/Home/HomeNew.tsx
View file @
74833085
...
@@ -10,7 +10,7 @@ import HomeIcon2 from '@/assets/homeIcon2.png'
...
@@ -10,7 +10,7 @@ import HomeIcon2 from '@/assets/homeIcon2.png'
import
SmartIce
from
'@/assets/smart-ice.png'
import
SmartIce
from
'@/assets/smart-ice.png'
import
{
createConversation
,
fetchConversations
}
from
'@/store/conversationSlice'
import
{
createConversation
,
fetchConversations
}
from
'@/store/conversationSlice'
import
{
useAppDispatch
}
from
'@/store/hook'
import
{
useAppDispatch
}
from
'@/store/hook'
import
{
fetchQuestionList
}
from
'@/api/home'
import
{
fetch
EfficiencyQuestionList
,
fetch
QuestionList
}
from
'@/api/home'
import
SdreamLoading
from
'@/components/SdreamLoading'
import
SdreamLoading
from
'@/components/SdreamLoading'
import
{
fetchLoginByToken
,
fetchLoginByUid
}
from
'@/api/common'
import
{
fetchLoginByToken
,
fetchLoginByUid
}
from
'@/api/common'
...
@@ -50,6 +50,8 @@ export const Home: React.FC = () => {
...
@@ -50,6 +50,8 @@ export const Home: React.FC = () => {
const
[
productQuestions
,
setProductQuestions
]
=
useState
<
any
>
({
content
:
[]
})
const
[
productQuestions
,
setProductQuestions
]
=
useState
<
any
>
({
content
:
[]
})
const
[
otherQuestions
,
setOtherQuestions
]
=
useState
<
any
>
({
content
:
[]
})
const
[
otherQuestions
,
setOtherQuestions
]
=
useState
<
any
>
({
content
:
[]
})
const
[
isToolBtnActive
,
setIsToolBtnActive
]
=
useState
<
boolean
>
(
false
)
const
[
isToolBtnActive
,
setIsToolBtnActive
]
=
useState
<
boolean
>
(
false
)
// 保存原始的configType为07的数据
const
[
originalOtherQuestions
,
setOriginalOtherQuestions
]
=
useState
<
any
>
({
content
:
[]
})
const
[
token
,
setToken
]
=
useLocalStorageState
<
string
|
undefined
>
(
'__TOKEN__'
,
{
const
[
token
,
setToken
]
=
useLocalStorageState
<
string
|
undefined
>
(
'__TOKEN__'
,
{
defaultValue
:
''
,
defaultValue
:
''
,
...
@@ -73,6 +75,7 @@ export const Home: React.FC = () => {
...
@@ -73,6 +75,7 @@ export const Home: React.FC = () => {
if
(
element
.
configType
===
'07'
)
{
if
(
element
.
configType
===
'07'
)
{
element
.
content
=
JSON
.
parse
(
element
.
content
)
element
.
content
=
JSON
.
parse
(
element
.
content
)
setOtherQuestions
(
element
)
setOtherQuestions
(
element
)
setOriginalOtherQuestions
(
element
)
// 保存原始数据
}
}
}
}
}
}
...
@@ -106,35 +109,45 @@ export const Home: React.FC = () => {
...
@@ -106,35 +109,45 @@ export const Home: React.FC = () => {
}
}
// 处理工具按钮点击
// 处理工具按钮点击
const
_handleToolClick
=
useCallback
((
isToolBtn
:
boolean
)
=>
{
const
_handleToolClick
=
useCallback
(
async
(
isToolBtn
:
boolean
,
toolId
?:
string
)
=>
{
// eslint-disable-next-line no-console
if
(
isToolBtn
&&
toolId
)
{
console
.
log
(
'HomeNew.tsx 接收到 isToolBtn 参数:'
,
isToolBtn
)
// 当isToolBtn为true时,替换configType为07的数据
},
[])
// 先清空数据,确保显示空数据样式
setOtherQuestions
((
prev
:
any
)
=>
({
...
prev
,
content
:
[],
}))
try
{
const
res
=
await
fetchEfficiencyQuestionList
({
toolId
})
if
(
res
&&
res
.
data
&&
res
.
data
.
questions
)
{
setOtherQuestions
((
prev
:
any
)
=>
({
...
prev
,
content
:
res
.
data
.
questions
||
[],
}))
}
}
catch
(
error
)
{
console
.
error
(
'获取工具相关问题失败:'
,
error
)
}
}
else
if
(
!
isToolBtn
)
{
// 当isToolBtn为false时,恢复原始的configType为07的数据
setOtherQuestions
(
originalOtherQuestions
)
}
},
[
originalOtherQuestions
])
// 监听工具按钮点击事件
// 监听工具按钮点击事件
useEffect
(()
=>
{
useEffect
(()
=>
{
const
handleToolClickEvent
=
(
event
:
CustomEvent
)
=>
{
const
handleToolClickEvent
=
(
event
:
CustomEvent
)
=>
{
const
{
isToolBtn
}
=
event
.
detail
const
{
isToolBtn
,
toolId
}
=
event
.
detail
// eslint-disable-next-line no-console
console
.
log
(
'HomeNew.tsx 接收到 isToolBtn 参数:'
,
isToolBtn
)
setIsToolBtnActive
(
isToolBtn
)
setIsToolBtnActive
(
isToolBtn
)
_handleToolClick
(
isToolBtn
,
toolId
)
}
}
window
.
addEventListener
(
'toolButtonClick'
,
handleToolClickEvent
as
EventListener
)
window
.
addEventListener
(
'toolButtonClick'
,
handleToolClickEvent
as
EventListener
)
return
()
=>
{
return
()
=>
{
window
.
removeEventListener
(
'toolButtonClick'
,
handleToolClickEvent
as
EventListener
)
window
.
removeEventListener
(
'toolButtonClick'
,
handleToolClickEvent
as
EventListener
)
}
}
},
[])
},
[
_handleToolClick
])
// 处理创建对话
const
_handleCreateConversation
=
useCallback
((
question
:
string
)
=>
{
dispatch
(
createConversation
({
conversationData
:
{},
shouldNavigate
:
true
,
shouldSendQuestion
:
question
,
}))
},
[
dispatch
])
const
login
=
useCallback
(
async
()
=>
{
const
login
=
useCallback
(
async
()
=>
{
// 防止重复调用
// 防止重复调用
...
@@ -146,15 +159,12 @@ export const Home: React.FC = () => {
...
@@ -146,15 +159,12 @@ export const Home: React.FC = () => {
// 获取查询参数
// 获取查询参数
const
searchParams
=
new
URLSearchParams
(
url
.
search
)
const
searchParams
=
new
URLSearchParams
(
url
.
search
)
const
_loginCode
=
searchParams
.
get
(
'loginCode'
)
const
_loginCode
=
searchParams
.
get
(
'loginCode'
)
let
res
=
{}
as
any
let
res
=
{}
as
any
if
(
viteOutputObj
===
'inner'
)
{
if
(
viteOutputObj
===
'inner'
)
{
if
(
_loginCode
)
{
if
(
_loginCode
)
{
res
=
await
fetchLoginByToken
(
_loginCode
)
res
=
await
fetchLoginByToken
(
_loginCode
)
if
(
res
.
data
)
{
if
(
res
.
data
)
{
setToken
(
res
.
data
.
token
)
setToken
(
res
.
data
.
token
)
// 主动触发 storage 事件,确保其他组件能监听到变化
// 主动触发 storage 事件,确保其他组件能监听到变化
window
.
dispatchEvent
(
window
.
dispatchEvent
(
new
StorageEvent
(
'storage'
,
{
new
StorageEvent
(
'storage'
,
{
...
@@ -165,7 +175,6 @@ export const Home: React.FC = () => {
...
@@ -165,7 +175,6 @@ export const Home: React.FC = () => {
storageArea
:
localStorage
,
storageArea
:
localStorage
,
}),
}),
)
)
await
getQuestionList
()
await
getQuestionList
()
initConversation
()
initConversation
()
dispatch
(
fetchConversations
())
dispatch
(
fetchConversations
())
...
@@ -182,7 +191,6 @@ export const Home: React.FC = () => {
...
@@ -182,7 +191,6 @@ export const Home: React.FC = () => {
res
=
await
fetchLoginByUid
(
'123123'
)
res
=
await
fetchLoginByUid
(
'123123'
)
if
(
res
.
data
)
{
if
(
res
.
data
)
{
setToken
(
res
.
data
.
token
)
setToken
(
res
.
data
.
token
)
// 主动触发 storage 事件,确保其他组件能监听到变化
// 主动触发 storage 事件,确保其他组件能监听到变化
window
.
dispatchEvent
(
window
.
dispatchEvent
(
new
StorageEvent
(
'storage'
,
{
new
StorageEvent
(
'storage'
,
{
...
@@ -193,7 +201,6 @@ export const Home: React.FC = () => {
...
@@ -193,7 +201,6 @@ export const Home: React.FC = () => {
storageArea
:
localStorage
,
storageArea
:
localStorage
,
}),
}),
)
)
await
getQuestionList
()
await
getQuestionList
()
initConversation
()
initConversation
()
dispatch
(
fetchConversations
())
dispatch
(
fetchConversations
())
...
@@ -259,26 +266,6 @@ export const Home: React.FC = () => {
...
@@ -259,26 +266,6 @@ export const Home: React.FC = () => {
style=
{
{
height
:
'calc(100vh - 64px)'
,
background
:
'#FFFFFF'
,
padding
:
'0 30px'
}
}
style=
{
{
height
:
'calc(100vh - 64px)'
,
background
:
'#FFFFFF'
,
padding
:
'0 30px'
}
}
>
>
<
Outlet
/>
<
Outlet
/>
{
/* {showOutlet
? (
<Outlet />
)
: (
<div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', height: '100%' }}>
<Slogan />
<div className="box-border px-[0] mx-auto iptContainer w-full flex-shrink-0 sm:px-0 pb-[18px]">
<ChatEditor
showContentTips
onSubmit={handleCreateConversation}
onToolClick={handleToolClick}
placeholders={RECOMMEND_QUESTIONS_OTHER}
/>
<div className="hidden sm:block w-full text-center mt-[12px] text-[#3333334d] text-[12px]">
内容由AI模型生成,其准确性和完整性无法保证,仅供参考
</div>
</div>
</div>
)} */
}
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
src/pages/Home/components/QuestionList/QuestionList.tsx
View file @
74833085
...
@@ -7,6 +7,7 @@ import Refresh from '@/assets/svg/refresh.svg?react'
...
@@ -7,6 +7,7 @@ import Refresh from '@/assets/svg/refresh.svg?react'
import
{
type
WithAuthProps
,
withAuth
}
from
'@/auth/withAuth'
import
{
type
WithAuthProps
,
withAuth
}
from
'@/auth/withAuth'
import
{
useAppDispatch
}
from
'@/store/hook'
import
{
useAppDispatch
}
from
'@/store/hook'
import
{
createConversation
}
from
'@/store/conversationSlice'
import
{
createConversation
}
from
'@/store/conversationSlice'
import
emptyIcon
from
'@/assets/empty-icon.png'
interface
QuestionListProps
{
interface
QuestionListProps
{
title
:
string
title
:
string
...
@@ -135,38 +136,49 @@ const QuestionListBase: React.FC<QuestionListProps & WithAuthProps> = ({
...
@@ -135,38 +136,49 @@ const QuestionListBase: React.FC<QuestionListProps & WithAuthProps> = ({
)
)
:
null
}
:
null
}
</
h3
>
</
h3
>
<
motion
.
ul
{
questions
.
length
===
0
key=
{
displayedItems
.
join
(
','
)
}
?
(
variants=
{
containerVariants
}
<
div
className=
"mt-[80px] flex flex-col items-center justify-center h-[200px]"
>
initial=
"hidden"
<
div
className=
"flex flex-col items-center"
>
animate=
"visible"
<
Image
src=
{
emptyIcon
}
alt=
"空数据"
className=
"w-[72px] h-[72px]"
/>
className=
"mt-[8px] flex flex-col gap-[8px] w-full"
<
div
className=
"mt-[16px] text-[14px] text-[#27353C]"
>
问题正在路上...
</
div
>
>
{
displayedItems
.
map
((
item
,
index
)
=>
(
<
motion
.
li
key=
{
`question-${item}`
}
custom=
{
index
}
variants=
{
itemVariants
}
initial=
"hidden"
animate=
"visible"
exit=
"exit"
layout
className=
"w-full"
>
<
Button
onPress=
{
()
=>
handleClick
(
item
)
}
color=
"primary"
variant=
"light"
className=
"text-left bg-[#F8FBFF] w-full text-[#333] rounded-[23px] data-[hover=true]:bg-[#F0F8FF] data-[hover=true]:text-primary h-8"
>
<
div
className=
"w-full text-nowrap text-ellipsis overflow-hidden"
>
<
span
className=
"w-[6px] h-[6px] rounded-full inline-block mr-[6px]"
style=
{
{
backgroundColor
:
dotColor
}
}
></
span
>
<
span
className=
"ml-[8px]"
>
{
item
}
</
span
>
</
div
>
</
div
>
</
Button
>
</
div
>
</
motion
.
li
>
)
))
}
:
(
</
motion
.
ul
>
<
motion
.
ul
key=
{
displayedItems
.
join
(
','
)
}
variants=
{
containerVariants
}
initial=
"hidden"
animate=
"visible"
className=
"mt-[8px] flex flex-col gap-[8px] w-full"
>
{
displayedItems
.
map
((
item
,
index
)
=>
(
<
motion
.
li
key=
{
`question-${item}`
}
custom=
{
index
}
variants=
{
itemVariants
}
initial=
"hidden"
animate=
"visible"
exit=
"exit"
layout
className=
"w-full"
>
<
Button
onPress=
{
()
=>
handleClick
(
item
)
}
color=
"primary"
variant=
"light"
className=
"text-left bg-[#F8FBFF] w-full text-[#333] rounded-[23px] data-[hover=true]:bg-[#F0F8FF] data-[hover=true]:text-primary h-8"
>
<
div
className=
"w-full text-nowrap text-ellipsis overflow-hidden"
>
<
span
className=
"w-[6px] h-[6px] rounded-full inline-block mr-[6px]"
style=
{
{
backgroundColor
:
dotColor
}
}
></
span
>
<
span
className=
"ml-[8px]"
>
{
item
}
</
span
>
</
div
>
</
Button
>
</
motion
.
li
>
))
}
</
motion
.
ul
>
)
}
</
div
>
</
div
>
)
)
}
}
...
...
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