Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
P
poc-fe
Project
Project
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
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
poc
poc-fe
Commits
1a700198
Commit
1a700198
authored
Feb 27, 2025
by
tyyin lan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 首页推理内容展示
parent
f928e0c5
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
202 additions
and
155 deletions
+202
-155
bubble-loading.gif
src/assets/images/home/bubble-loading.gif
+0
-0
footer-operation.vue
src/views/home/components/footer-operation.vue
+141
-142
message-item.vue
src/views/home/components/message-item.vue
+45
-3
home.vue
src/views/home/home.vue
+6
-0
types.d.ts
src/views/home/types.d.ts
+1
-0
fetch-event-stream-source.ts
src/views/home/utils/fetch-event-stream-source.ts
+9
-10
No files found.
src/assets/images/home/bubble-loading.gif
0 → 100644
View file @
1a700198
3.98 KB
src/views/home/components/footer-operation.vue
View file @
1a700198
<
script
setup
lang=
"ts"
>
import
{
computed
,
nextTick
,
ref
,
shallowRef
,
toValue
,
useTemplateRef
,
watch
}
from
'vue'
import
{
computed
,
h
,
nextTick
,
ref
,
shallowRef
,
useTemplateRef
,
watch
,
toValue
}
from
'vue'
import
type
{
AgentApplicationRecordItem
,
MessageItemInterface
}
from
'../types'
import
{
fetchAgentApplicationSelectList
,
fetchFileUpload
}
from
'@/apis/home-agent'
import
{
nanoid
}
from
'nanoid'
...
...
@@ -13,6 +13,8 @@ import { UploadStatus } from '@/enums/upload-status'
import
{
useUploadImage
}
from
'@/composables/useUploadImage'
import
{
useSystemLanguageStore
}
from
'@/store/modules/system-language'
import
{
PluginType
}
from
'@/enums/plugin'
import
{
NAvatar
,
NEllipsis
}
from
'naive-ui'
import
type
{
SelectRenderLabel
,
SelectRenderTag
}
from
'naive-ui'
interface
Props
{
currentSessionId
:
string
...
...
@@ -47,7 +49,6 @@ const { uploadImageList, handleLimitUploadImage, handleUploadImage, handleRemove
let
fileUploadController
=
shallowRef
<
AbortController
|
null
>
(
null
)
const
isShowApplicationSelectMenu
=
ref
(
false
)
const
agentApplicationSelectList
=
ref
<
AgentApplicationRecordItem
[]
>
([])
const
currentLatestMessageItemKeyMap
=
ref
(
new
Map
<
'assistant'
|
'user'
,
string
>
())
...
...
@@ -99,30 +100,14 @@ watch(
function
getAgentApplicationSelectList
()
{
fetchAgentApplicationSelectList
<
AgentApplicationRecordItem
[]
>
().
then
((
res
)
=>
{
agentApplicationSelectList
.
value
=
res
.
data
if
(
res
.
data
&&
Array
.
isArray
(
res
.
data
))
{
agentApplicationSelectList
.
value
=
res
.
data
.
map
((
item
)
=>
({
...
item
,
class
:
'application-menu-item'
}))
}
currentAgentApplication
.
value
=
res
.
data
[
0
]
})
}
function
handleApplicationSelectMenuSwitchShow
()
{
isShowApplicationSelectMenu
.
value
=
!
isShowApplicationSelectMenu
.
value
}
function
handleApplicationSelectBtnBlur
()
{
setTimeout
(()
=>
{
isShowApplicationSelectMenu
.
value
=
false
},
100
)
}
function
handleApplicationChange
(
agentApplicationItem
:
AgentApplicationRecordItem
)
{
if
(
currentAgentApplication
.
value
.
agentId
===
agentApplicationItem
.
agentId
)
{
return
}
currentAgentApplication
.
value
=
toValue
(
agentApplicationItem
)
}
function
handleCreateNewSession
()
{
if
(
isAgentResponding
.
value
)
{
window
.
$message
.
ctWarning
(
t
(
'home_module.interrupt_dialogue_prompt'
)).
then
(()
=>
{
...
...
@@ -166,6 +151,7 @@ function questionSubmit() {
avatar
:
''
,
name
:
''
,
imageUrl
:
uploadImageList
.
value
?.[
0
]?.
url
||
''
,
reasoningContent
:
''
,
})
const
agentAvatar
=
currentAgentApplication
.
value
.
agentAvatar
...
...
@@ -181,6 +167,7 @@ function questionSubmit() {
avatar
:
agentAvatar
,
name
:
agentName
,
pluginName
:
''
,
reasoningContent
:
''
,
})
setTimeout
(()
=>
{
...
...
@@ -192,6 +179,7 @@ function questionSubmit() {
// let isFirstClip = true
let
messageContent
=
''
let
reasoningContent
=
''
currentFetchEventSourceController
.
value
=
fetchEventStreamSource
(
'/agentApplicationRest/callAgentApplication.json'
,
...
...
@@ -204,25 +192,38 @@ function questionSubmit() {
imageUrl
:
uploadImageList
.
value
?.[
0
]?.
url
||
''
,
// 图片链接
},
{
onmessage
:
(
message
)
=>
{
messageContent
+=
message
onResponse
:
(
data
)
=>
{
// 推理内容
if
(
data
.
reasoningContent
)
{
reasoningContent
+=
data
.
reasoningContent
emit
(
'updateSpecifyMessageItem'
,
currentLatestMessageItemKeyMap
.
value
.
get
(
'assistant'
)
!
,
{
content
:
message
Content
,
reasoningContent
:
reasoning
Content
,
})
messageListScrollToBottomThrottle
()
},
onFunction
:
(
name
)
=>
{
}
// 回复消息
if
(
data
.
message
)
{
messageContent
+=
data
.
message
emit
(
'updateSpecifyMessageItem'
,
currentLatestMessageItemKeyMap
.
value
.
get
(
'assistant'
)
!
,
{
pluginName
:
name
,
content
:
messageContent
,
})
nextTick
(()
=>
{
emit
(
'messageListScrollToBottom'
)
messageListScrollToBottomThrottle
()
}
// 插件
if
(
data
.
function
&&
data
.
function
.
name
)
{
emit
(
'updateSpecifyMessageItem'
,
currentLatestMessageItemKeyMap
.
value
.
get
(
'assistant'
)
!
,
{
pluginName
:
data
.
function
.
name
,
})
},
messageListScrollToBottomThrottle
()
}
},
onend
:
()
=>
{
setTimeout
(()
=>
{
emit
(
'updateSpecifyMessageItem'
,
currentLatestMessageItemKeyMap
.
value
.
get
(
'assistant'
)
!
,
{
...
...
@@ -351,96 +352,85 @@ function handleSelectImage(cb: () => void) {
defineExpose
({
clearSessionReferenceFile
:
handleFileUploadCancel
,
})
const
selectMenuRenderLabel
:
SelectRenderLabel
=
(
option
)
=>
{
return
h
(
'div'
,
{
style
:
{
display
:
'flex'
,
alignItems
:
'center'
,
width
:
'100%'
,
},
},
[
h
(
NAvatar
,
{
src
:
option
.
agentAvatar
as
string
,
size
:
22
,
color
:
'#fff'
,
'object-fit'
:
'contain'
,
style
:
{
marginRight
:
'6px'
,
flexShrink
:
0
,
},
}),
h
(
NEllipsis
,
{
style
:
{
width
:
'100%'
,
marginRight
:
'6px'
}
},
{
default
:
()
=>
option
.
agentTitle
}),
h
(
'span'
,
{
style
:
{
justifySelf
:
'end'
,
fontSize
:
'12px'
,
color
:
'#0B7DFF'
,
textAlign
:
'end'
,
marginLeft
:
'auto'
}
},
[
`
${
option
.
points
as
string
}${
t
(
'equity_module.points2'
)}
/
${
t
(
'common_module.time'
)}
`
],
),
],
)
}
const
selectMenuRenderTag
:
SelectRenderTag
=
({
option
})
=>
{
return
h
(
'div'
,
{
style
:
{
display
:
'flex'
,
alignItems
:
'center'
,
},
},
[
h
(
NAvatar
,
{
src
:
option
.
agentAvatar
as
string
,
size
:
22
,
color
:
'#fff'
,
'object-fit'
:
'contain'
,
style
:
{
marginRight
:
'6px'
,
flexShrink
:
0
,
},
}),
h
(
NEllipsis
,
{
style
:
{
width
:
'100%'
}
},
{
default
:
()
=>
option
.
agentTitle
}),
],
)
}
function
onAgentApplicationInfoUpdate
(
_key
:
string
,
option
:
AgentApplicationRecordItem
)
{
currentAgentApplication
.
value
=
toValue
(
option
)
}
</
script
>
<
template
>
<div
class=
"mt-auto pr-[10px]"
>
<div
class=
"mb-[10px] flex select-none justify-between"
>
<!--
<div
class=
"relative box-border flex h-[34px] w-[145px] cursor-pointer items-center rounded-[10px] border border-[#9EA3FF] px-[12px]"
>
<div
class=
"flex w-full items-center justify-between"
>
<div
class=
"flex items-center"
>
<div
class=
"bg-px-home-cuixiang_icon-png mr-[5px] h-[16px] w-[16px]"
></div>
<div
class=
"text-[14px]"
>
萃想AI
</div>
</div>
<Up
theme=
"outline"
size=
"18"
fill=
"#333"
:stroke-width=
"3"
/>
</div>
<div
class=
"absolute -top-[10px] left-1/2 w-[200px] -translate-x-1/2 -translate-y-full rounded-[10px] bg-[#fff] p-[6px] shadow-md"
>
hello
</div>
</div>
-->
<div
class=
"relative"
>
<n-button
class=
"application-select-btn !h-[34px] !rounded-[10px] !p-0"
@
click=
"handleApplicationSelectMenuSwitchShow"
@
blur=
"handleApplicationSelectBtnBlur"
>
<div
class=
"box-border flex !w-[160px] w-full items-center justify-between px-[12px]"
>
<div
class=
"mr-[5px] flex flex-1 items-center overflow-hidden"
>
<div
class=
"mr-[10px] h-[16px] w-[16px] rounded-[6px] bg-cover bg-no-repeat"
:class=
"
{ 'bg-px-home-cuixiang_icon-png': !currentAgentApplication.agentAvatar }"
:style="{ backgroundImage: `url(${currentAgentApplication.agentAvatar})` }"
>
</div>
<div
class=
"flex-1 truncate text-start text-[14px]"
>
{{
currentAgentApplication
.
agentTitle
||
'-'
}}
</div>
</div>
<i
class=
"iconfont icon-left rotate-90 text-[12px] transition-[rotate] duration-300 ease-in-out"
:class=
"
{ '!rotate-270': isShowApplicationSelectMenu }"
>
</i>
</div>
</n-button>
<Transition
name=
"application-select-menu"
>
<ul
v-show=
"isShowApplicationSelectMenu"
class=
"absolute -top-[10px] left-0 w-[240px] -translate-y-full rounded-[6px] bg-[#fff] p-[10px] pb-[4px] pr-0 shadow-md"
>
<n-virtual-list
style=
"max-height: 200px"
:item-size=
"35"
:items=
"agentApplicationSelectList"
key-field=
"agentId"
items-style=
"padding-right: 10px;"
>
<template
#
default=
"
{ item }">
<li
class=
"relative mb-[6px] flex cursor-pointer items-center overflow-hidden rounded-[4px] bg-[#f3f3f5] py-[4px] pl-[10px] pr-[16px] transition hover:bg-[#E7E7E7]"
@
click=
"handleApplicationChange(item)"
>
<div
class=
"mr-[10px] h-[16px] w-[16px] rounded-[6px] bg-cover bg-no-repeat"
:class=
"
{ 'bg-px-home-cuixiang_icon-png': !item.agentAvatar }"
:style="{ backgroundImage: `url(${item.agentAvatar})` }"
>
</div>
<div
class=
"flex-1 overflow-hidden"
>
<n-ellipsis
:tooltip=
"
{ placement: 'right' }">
{{
item
.
agentTitle
}}
</n-ellipsis>
</div>
<div
class=
"pl-[8px] text-[12px] text-[#0B7DFF]"
>
<template
v-if=
"item.points && item.points !== 0"
>
{{
item
.
points
}}{{
t
(
'equity_module.points2'
)
}}
/
{{
t
(
'common_module.time'
)
}}
</
template
>
<
template
v-else-if=
"item.points && item.points === 0"
>
{{
t
(
'common_module.free'
)
}}
</
template
>
</div>
<i
v-if=
"item.agentId === currentAgentApplication.agentId"
class=
"iconfont icon-xuanze absolute bottom-0 right-0 text-[14px] text-[#777ef9]"
></i>
</li>
</template>
</n-virtual-list>
</ul>
</Transition>
<div
class=
"w-[190px]"
>
<n-select
:value=
"currentAgentApplication.agentId"
class=
"application-menu"
:options=
"agentApplicationSelectList"
:render-label=
"selectMenuRenderLabel"
:render-tag=
"selectMenuRenderTag"
label-field=
"agentTitle"
value-field=
"agentId"
placement=
"top-start"
:consistent-menu-width=
"false"
:menu-props=
"
{ style: { maxWidth: '220px' }, class: 'application-menu-popup' }"
:on-update:value="onAgentApplicationInfoUpdate"
/>
</div>
<div
class=
"flex items-center"
>
...
...
@@ -450,7 +440,7 @@ defineExpose({
<template
#
trigger
>
<n-button
v-show=
"currentAgentApplication.isDocumentParsing === 'Y'"
class=
"application-select-btn !mr-[
14
px] !h-[34px] !rounded-[10px] !p-0"
class=
"application-select-btn !mr-[
8
px] !h-[34px] !rounded-[10px] !p-0"
@
click=
"handleFileUploadPopup"
>
<div
class=
"box-border flex w-full items-center justify-between px-[12px]"
>
...
...
@@ -471,14 +461,14 @@ defineExpose({
<div
class=
"text-[14px]"
:class=
"{
'w-[
11
0px]': isEnglishLanguage && isEnableUploadImage,
'w-[
21
0px]': !isEnglishLanguage && isEnableUploadImage,
'w-[2
6
0px]': !isEnableUploadImage,
'w-[
9
0px]': isEnglishLanguage && isEnableUploadImage,
'w-[
19
0px]': !isEnglishLanguage && isEnableUploadImage,
'w-[2
4
0px]': !isEnableUploadImage,
}"
>
<
n-e
llipsis
:tooltip=
"{ width: 400 }"
>
<
NE
llipsis
:tooltip=
"{ width: 400 }"
>
{{ currentInputFileInfo.fileName }}
</
n-e
llipsis>
</
NE
llipsis>
</div>
<div
class=
"ml-[10px]"
>
...
...
@@ -519,7 +509,7 @@ defineExpose({
<
template
#
trigger
>
<n-button
v-show=
"isEnableUploadImage"
class=
"upload-image-btn !mr-[
14
px] !h-[34px] !rounded-[10px] !p-0"
class=
"upload-image-btn !mr-[
8
px] !h-[34px] !rounded-[10px] !p-0"
@
click=
"handleSelectImage(handleClick)"
>
<div
class=
"box-border flex w-full items-center justify-between px-[12px]"
>
...
...
@@ -624,20 +614,6 @@ defineExpose({
}
}
.application-select-menu-enter-active
,
.application-select-menu-leave-active
{
transition-timing-function
:
ease-in-out
;
transition-duration
:
0
.2s
;
transition-property
:
opacity
,
scale
;
transform-origin
:
left
center
;
}
.application-select-menu-enter-from
,
.application-select-menu-leave-to
{
opacity
:
0
;
scale
:
0
.8
;
}
.file-upload-enter-active
,
.file-upload-leave-active
{
transition-timing-function
:
ease-in-out
;
...
...
@@ -649,4 +625,27 @@ defineExpose({
.file-upload-leave-to
{
opacity
:
0
;
}
:deep
(
.application-menu
)
{
.n-base-selection
{
border-radius
:
10px
;
}
.n-base-selection__border
{
border-color
:
#9ea3ff
;
}
.n-base-selection-label
{
height
:
34px
;
}
.application-menu-inner
.select-item-image
{
width
:
16px
;
height
:
16px
;
}
}
:global
(
.application-menu-item
.n-base-select-option__content
)
{
width
:
100%
;
}
</
style
>
src/views/home/components/message-item.vue
View file @
1a700198
<
script
setup
lang=
"ts"
>
import
{
computed
,
readonly
}
from
'vue'
import
{
CheckOne
}
from
'@icon-park/vue-next'
import
{
computed
,
readonly
,
ref
}
from
'vue'
import
{
CheckOne
,
Down
}
from
'@icon-park/vue-next'
import
type
{
MessageItemInterface
}
from
'../types'
import
{
useUserStore
}
from
'@/store/modules/user'
import
MessageBubbleLoading
from
'./message-bubble-loading.vue'
...
...
@@ -16,6 +16,7 @@ const { t } = useI18n()
const
userStore
=
useUserStore
()
const
agentDefaultAvatarUrl
=
readonly
({
url
:
'https://gsst-poe-sit.gz.bcebos.com/icon/agent-avatar.png'
})
const
isShowReasoningContent
=
ref
(
true
)
const
isAgentMessage
=
computed
(()
=>
{
return
props
.
messageItem
.
role
===
'assistant'
...
...
@@ -28,6 +29,10 @@ const avatarUrl = computed(() => {
const
name
=
computed
(()
=>
{
return
isAgentMessage
.
value
?
props
.
messageItem
.
name
||
'AI助理'
:
userStore
.
userInfo
.
nickName
})
function
handleShowReasoningContentSwitch
()
{
isShowReasoningContent
.
value
=
!
isShowReasoningContent
.
value
}
</
script
>
<
template
>
...
...
@@ -36,7 +41,44 @@ const name = computed(() => {
<img
class=
"h-[36px] w-[36px] rounded-[6px] object-cover"
:src=
"avatarUrl"
alt=
"Avatar"
/>
<div
class=
"ml-[11px] overflow-hidden"
>
<div
class=
"mb-[7px] text-[12px] text-[#999]"
>
<template
v-if=
"isAgentMessage && messageItem.name === 'Deepseek R1'"
>
<div
class=
"mb-[7px] select-none text-[14px]"
>
<div
class=
"inline-flex cursor-pointer"
@
click=
"handleShowReasoningContentSwitch"
>
<span
class=
"mr-[6px]"
>
{{
name
}}
</span>
<Down
theme=
"outline"
size=
"21"
fill=
"#333"
:stroke-width=
"3"
class=
"transition-[rotate] duration-100 ease-linear"
:class=
"
{ '-rotate-180': isShowReasoningContent }"
/>
</div>
</div>
<n-collapse-transition
:show=
"isShowReasoningContent"
>
<div
class=
"my-[14px] border-l-[1px] border-solid border-l-[#ccc] p-[13px]"
>
<div>
<img
v-if=
"!messageItem.reasoningContent && !messageItem.content"
src=
"@/assets/images/home/bubble-loading.gif"
alt=
"bubble-loading"
/>
<template
v-else
>
<MarkdownRender
:raw-text-content=
"
messageItem.reasoningContent
? messageItem.reasoningContent
: t('common_module.dialogue_module.empty_message_content')
"
color=
"#999"
/>
</
template
>
</div>
</div>
</n-collapse-transition>
</template>
<div
v-else
class=
"mb-[7px] text-[12px] text-[#999]"
>
{{ name }}
</div>
...
...
src/views/home/home.vue
View file @
1a700198
...
...
@@ -58,6 +58,10 @@ const currentFetchEventSourceController = ref<AbortController | null>(null)
// '对于初学者的编程学习资源,可以从以下几个方面进行推荐:\n\n### 一、在线教程与网站\n\n1. **w3school**:这是一个非常全面的编程学习网站,提供了从基础到高级的教程,包括HTML、CSS、JavaScript、SQL等,适合初学者逐步深入学习。\n2. **慕课网**:慕课网上有许多免费课程,涵盖了前端、后端开发,移动开发等多个方面,初学者可以根据自己的兴趣选择相应的课程。\n3. **Coursera**:该网站提供世界名校的网络公开课程,其中也包括计算机编程的相关课程,初学者可以接触到国际一流的教学资源。\n\n### 二、书籍推荐\n\n1. **《Python编程快速上手》**:这本书是为零基础读者打造的Python入门书籍,内容系统且详细,每个知识点都深入浅出,非常适合初学者。\n2. **《C++ Primer Plus》**:这本书是C++语言学习的理想图书,通过大量短小精悍的程序详细阐述了C++的基本概念和技术,对初学者极为友好。\n\n### 三、实践项目与刷题网站\n\n1. **Stack Overflow**:这是一个程序设计领域的问答网站,初学者在遇到编程难题时可以在这里寻找解决方案,同时也可以学习到其他技术大牛的经验和技巧。\n2. **GitHub**:作为全球最大的开源代码托管仓库,GitHub上有无穷无尽的开源代码供初学者学习和参考,阅读源码是一个快速提升编程能力的好方法。\n\n### 四、社区与论坛\n\n1. **CSDN软件开发网**:这是国内知名的软件开发社区,提供了大量的编程资源和经验分享,初学者可以在这里交流学习心得,获取最新的技术动态。\n\n综上所述,初学者可以根据自己的学习需求和兴趣选择合适的编程学习资源。从在线教程、书籍阅读到实践项目和社区交流,多方面的学习将有助于初学者快速掌握编程技能并不断提升自己。',
// timestamp: 1726654851735,
// isAnswerLoading: false,
// avatar: 'http://localhost:8848/fe/src/assets/images/home/agent-avatar.png',
// name: 'lisa',
// reasoningContent:
// '对于初学者的编程学习资源,可以从以下几个方面进行推荐:\n\n### 一、在线教程与网站\n\n1. **w3school**:这是一个非常全面的编程学习网站,提供了从基础到高级的教程,包括HTML、CSS、JavaScript、SQL等,适合初学者逐步深入学习。\n2. **慕课网**:慕课网上有许多免费课程,涵盖了前端、后端开发,移动开发等多个方面,初学者可以根据自己的兴趣选择相应的课程。\n3. **Coursera**:该网站提供世界名校的网络公开课程,其中也包括计算机编程的相关课程,初学者可以接触到国际一流的教学资源。\n\n### 二、书籍推荐\n\n1. **《Python编程快速上手》**:这本书是为零基础读者打造的Python入门书籍,内容系统且详细,每个知识点都深入浅出,非常适合初学者。\n2. **《C++ Primer Plus》**:这本书是C++语言学习的理想图书,通过大量短小精悍的程序详细阐述了C++的基本概念和技术,对初学者极为友好。\n\n### 三、实践项目与刷题网站\n\n1. **Stack Overflow**:这是一个程序设计领域的问答网站,初学者在遇到编程难题时可以在这里寻找解决方案,同时也可以学习到其他技术大牛的经验和技巧。\n2. **GitHub**:作为全球最大的开源代码托管仓库,GitHub上有无穷无尽的开源代码供初学者学习和参考,阅读源码是一个快速提升编程能力的好方法。\n\n### 四、社区与论坛\n\n1. **CSDN软件开发网**:这是国内知名的软件开发社区,提供了大量的编程资源和经验分享,初学者可以在这里交流学习心得,获取最新的技术动态。\n\n综上所述,初学者可以根据自己的学习需求和兴趣选择合适的编程学习资源。从在线教程、书籍阅读到实践项目和社区交流,多方面的学习将有助于初学者快速掌握编程技能并不断提升自己',
// })
const
homeContainerWidthWatchDebounce
=
debounce
((
newWidth
)
=>
{
...
...
@@ -165,6 +169,7 @@ function onGetMessageRecordList(recordId: string) {
content
:
string
timestamp
:
number
imageUrl
:
string
reasoningContent
:
string
}[]
>
(
recordId
)
.
then
((
res
)
=>
{
...
...
@@ -181,6 +186,7 @@ function onGetMessageRecordList(recordId: string) {
avatar
:
recordItem
.
agentAvatar
,
timestamp
:
recordItem
.
timestamp
,
imageUrl
:
recordItem
?.
imageUrl
||
''
,
reasoningContent
:
recordItem
.
reasoningContent
||
''
,
},
]
})
...
...
src/views/home/types.d.ts
View file @
1a700198
...
...
@@ -20,4 +20,5 @@ export interface MessageItemInterface {
name
:
string
pluginName
?:
string
imageUrl
?:
string
reasoningContent
:
string
}
src/views/home/utils/fetch-event-stream-source.ts
View file @
1a700198
...
...
@@ -4,9 +4,14 @@ import { useUserStore } from '@/store/modules/user'
import
{
languageKeyTransform
}
from
'@/utils/language-key-transform'
import
{
fetchEventSource
}
from
'@microsoft/fetch-event-source'
interface
ResponseData
{
message
:
string
reasoningContent
:
string
function
:
{
name
:
string
}
}
interface
Options
{
onFunction
?:
(
name
:
string
)
=>
void
onmessage
?:
(
message
:
string
)
=>
void
onResponse
?:
(
data
:
ResponseData
)
=>
void
onend
?:
()
=>
void
onclose
?:
()
=>
void
onerror
?:
(
err
:
Error
)
=>
void
...
...
@@ -16,8 +21,7 @@ export default function fetchEventStreamSource(
url
:
string
,
payload
:
object
=
{},
options
:
Options
=
{
onFunction
:
(
_name
:
string
)
=>
{},
onmessage
:
(
_message
:
string
)
=>
{},
onResponse
:
(
_data
:
ResponseData
)
=>
{},
onend
:
()
=>
{},
onclose
:
()
=>
{},
onerror
:
(
_err
:
Error
)
=>
{},
...
...
@@ -48,13 +52,8 @@ export default function fetchEventStreamSource(
try
{
const
data
=
JSON
.
parse
(
e
.
data
)
if
(
data
.
function
&&
data
.
function
.
name
)
{
options
.
onFunction
&&
options
.
onFunction
(
data
.
function
.
name
)
return
}
if
(
data
.
code
===
0
||
data
.
code
===
'0'
)
{
data
.
message
&&
options
.
onmessage
&&
options
.
onmessage
(
data
.
message
)
data
&&
options
.
onResponse
&&
options
.
onResponse
(
data
)
}
else
{
options
.
onerror
&&
options
.
onerror
(
new
Error
(
data
.
message
))
...
...
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