Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
center-book
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
center-book
Commits
9ee0bb8c
提交
9ee0bb8c
authored
6月 12, 2024
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: update
上级
5aa3bc6d
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
113 行增加
和
122 行删除
+113
-122
index.jsx
src/common/wangeditor-customer/ai-drawer/index.jsx
+113
-122
没有找到文件。
src/common/wangeditor-customer/ai-drawer/index.jsx
浏览文件 @
9ee0bb8c
import
React
,
{
useState
,
useEffect
,
useCallback
}
from
'react'
;
import
{
SendOutlined
}
from
'@ant-design/icons'
;
import
{
Input
,
Space
,
Button
,
message
}
from
'antd'
;
import
md5
from
'js-md5'
;
import
dayjs
from
'dayjs'
;
import
{
sleep
}
from
'@/utils/common'
;
import
React
,
{
useState
,
useEffect
,
useCallback
}
from
'react'
import
{
SendOutlined
}
from
'@ant-design/icons'
import
{
Input
,
Space
,
Button
,
message
}
from
'antd'
import
md5
from
'js-md5'
import
dayjs
from
'dayjs'
import
{
sleep
}
from
'@/utils/common'
import
'./index.less'
;
import
{
useSelector
,
useDispatch
}
from
'react-redux'
;
import
{
setEditorAi
}
from
'@/store/modules/editor'
;
import
normalAvatar
from
'@/assets/images/icon-normal-avatar.png'
;
import
'./index.less'
import
{
useSelector
,
useDispatch
}
from
'react-redux'
import
{
setEditorAi
}
from
'@/store/modules/editor'
import
normalAvatar
from
'@/assets/images/icon-normal-avatar.png'
const
UUID
=
'f3846153ba784b6d86bdcd5533259c88'
;
const
auth_key
=
'f3846153ba784b6d86bdcd5533259c88'
;
const
auth_secret
=
'HO4IyLEwEOHpeOXBxaLQUOqWslJRGs1M'
;
const
UUID
=
'f3846153ba784b6d86bdcd5533259c88'
const
auth_key
=
'f3846153ba784b6d86bdcd5533259c88'
const
auth_secret
=
'HO4IyLEwEOHpeOXBxaLQUOqWslJRGs1M'
const
AIDrawerComponent
=
(
props
)
=>
{
const
{
selectText
}
=
props
;
const
dispatch
=
useDispatch
()
;
const
{
userInfo
}
=
useSelector
(
(
state
)
=>
state
.
user
);
// 用户状态信息
const
{
editorAi
}
=
useSelector
(
(
state
)
=>
state
.
editor
);
// ai信息设置
const
AIDrawerComponent
=
props
=>
{
const
{
selectText
}
=
props
const
dispatch
=
useDispatch
()
const
{
userInfo
}
=
useSelector
(
state
=>
state
.
user
)
// 用户状态信息
const
{
editorAi
}
=
useSelector
(
state
=>
state
.
editor
)
// ai信息设置
const
[
value
,
setValue
]
=
useState
(
selectText
)
;
// 输入值
const
[
loading
,
setLoading
]
=
useState
(
false
)
;
// loading
const
[
chatId
,
setChatId
]
=
useState
(
null
)
;
// 对话的id
const
[
chatContentList
,
setChatContentList
]
=
useState
([])
;
// 对话数据
const
element
=
document
.
querySelector
(
'#chat-content'
)
;
let
str
=
''
;
const
[
value
,
setValue
]
=
useState
(
selectText
)
// 输入值
const
[
loading
,
setLoading
]
=
useState
(
false
)
// loading
const
[
chatId
,
setChatId
]
=
useState
(
null
)
// 对话的id
const
[
chatContentList
,
setChatContentList
]
=
useState
([])
// 对话数据
const
element
=
document
.
querySelector
(
'#chat-content'
)
let
str
=
''
useEffect
(()
=>
{
if
(
editorAi
&&
Object
.
entries
(
editorAi
).
length
>
0
)
{
let
tempJSON
=
JSON
.
parse
(
JSON
.
stringify
(
chatContentList
))
;
let
conversationId
=
editorAi
.
conversationId
;
const
item
=
tempJSON
.
filter
(
(
item
)
=>
item
.
conversationId
===
conversationId
);
let
tempJSON
=
JSON
.
parse
(
JSON
.
stringify
(
chatContentList
))
let
conversationId
=
editorAi
.
conversationId
const
item
=
tempJSON
.
filter
(
item
=>
item
.
conversationId
===
conversationId
)
if
(
item
&&
item
.
length
>
0
)
{
tempJSON
[
tempJSON
.
length
-
1
]
=
editorAi
;
tempJSON
[
tempJSON
.
length
-
1
]
=
editorAi
}
else
{
tempJSON
.
push
(
editorAi
)
;
tempJSON
.
push
(
editorAi
)
}
setChatId
(
editorAi
.
chatId
)
;
setChatContentList
(
tempJSON
)
;
element
.
scrollTo
(
0
,
999999
)
;
setChatId
(
editorAi
.
chatId
)
setChatContentList
(
tempJSON
)
element
.
scrollTo
(
0
,
999999
)
}
else
{
setLoading
(
false
)
;
setLoading
(
false
)
}
},
[
editorAi
])
;
},
[
editorAi
])
useEffect
(()
=>
{
if
(
selectText
)
{
targetChat
()
;
targetChat
()
}
return
()
=>
{
setValue
(
''
)
;
setChatContentList
([])
;
setChatId
(
null
)
;
}
;
},
[])
;
setValue
(
''
)
setChatContentList
([])
setChatId
(
null
)
}
},
[])
let
cData
=
[]
;
let
buffer
=
''
;
let
cData
=
[]
let
buffer
=
''
const
readBuffer
=
(
reader
,
decoder
)
=>
{
return
reader
.
read
().
then
(
async
({
done
,
value
})
=>
{
if
(
done
)
{
// 处理最后的缓冲数据
setLoading
(
false
)
;
setValue
(
''
)
;
dispatch
(
setEditorAi
({}))
;
str
=
''
;
processBuffer
(
buffer
)
;
return
;
setLoading
(
false
)
setValue
(
''
)
dispatch
(
setEditorAi
({}))
str
=
''
processBuffer
(
buffer
)
return
}
await
sleep
(
80
)
;
buffer
+=
decoder
.
decode
(
value
,
{
stream
:
true
})
;
await
sleep
(
80
)
buffer
+=
decoder
.
decode
(
value
,
{
stream
:
true
})
// 检查缓冲区中是否有完整的消息
const
messages
=
buffer
.
split
(
'
\
n
\
n'
)
;
// 假设每个消息以换行符结束
const
messages
=
buffer
.
split
(
'
\
n
\
n'
)
// 假设每个消息以换行符结束
messages
.
forEach
((
message
,
index
)
=>
{
if
(
index
<
messages
.
length
-
1
)
{
processBuffer
(
message
)
;
processBuffer
(
message
)
}
})
;
buffer
=
messages
[
messages
.
length
-
1
]
;
// 更新缓冲区
readBuffer
(
reader
,
decoder
)
;
})
;
}
;
})
buffer
=
messages
[
messages
.
length
-
1
]
// 更新缓冲区
readBuffer
(
reader
,
decoder
)
})
}
const
processBuffer
=
(
text
)
=>
{
let
aiContent
=
{}
;
const
processBuffer
=
text
=>
{
let
aiContent
=
{}
try
{
const
content
=
text
.
replace
(
/
\n
+/g
,
''
).
split
(
'data:'
)
;
const
content
=
text
.
replace
(
/
\n
+/g
,
''
).
split
(
'data:'
)
if
(
content
instanceof
Array
)
{
const
itemContent
=
JSON
.
parse
(
content
[
1
])
;
const
itemContent
=
JSON
.
parse
(
content
[
1
])
if
(
!
(
itemContent
.
finish
&&
itemContent
.
finish
===
true
))
{
str
+=
itemContent
.
content
;
str
+=
itemContent
.
content
aiContent
=
{
type
:
'ai'
,
content
:
str
,
chatId
:
itemContent
.
chatId
,
avatar
:
itemContent
.
role
.
avatar
,
conversationId
:
itemContent
.
conversationId
,
}
;
dispatch
(
setEditorAi
(
aiContent
))
;
conversationId
:
itemContent
.
conversationId
}
dispatch
(
setEditorAi
(
aiContent
))
}
}
}
catch
{}
}
;
}
// 提交对话
const
targetChat
=
async
()
=>
{
if
(
value
)
{
setLoading
(
true
)
;
const
timestamp
=
Date
.
now
()
;
setLoading
(
true
)
const
timestamp
=
Date
.
now
()
fetch
(
'/openapi/agent/chat/stream/v1'
,
{
fetch
(
'/
api/tiangong/
openapi/agent/chat/stream/v1'
,
{
method
:
'POST'
,
responseType
:
'stream'
,
// 设置响应类型为 'stream'
headers
:
{
...
...
@@ -120,105 +120,96 @@ const AIDrawerComponent = (props) => {
authKey
:
auth_key
,
timestamp
:
timestamp
,
sign
:
md5
(
`
${
auth_key
}${
auth_secret
}${
timestamp
}
`
),
stream
:
true
,
// or change to "false" 不处理流式返回内容
stream
:
true
// or change to "false" 不处理流式返回内容
},
body
:
JSON
.
stringify
({
agentId
:
UUID
,
chatId
:
chatId
,
userChatInput
:
value
,
userChatInput
:
value
}),
mode
:
'cors'
,
mode
:
'cors'
})
.
then
(
(
response
)
=>
{
.
then
(
response
=>
{
// response.body 是一个 ReadableStream 对象
const
stream
=
response
.
body
;
const
stream
=
response
.
body
// 使用流式数据
const
reader
=
stream
.
getReader
()
;
const
decoder
=
new
TextDecoder
()
;
// 用于解码二进制数据流
const
reader
=
stream
.
getReader
()
const
decoder
=
new
TextDecoder
()
// 用于解码二进制数据流
let
userContent
=
{
type
:
'user'
,
content
:
value
,
time
:
Date
.
now
()
,
}
;
let
tempJSON
=
JSON
.
parse
(
JSON
.
stringify
(
chatContentList
))
;
tempJSON
.
push
(
userContent
)
;
setChatContentList
(
tempJSON
)
;
time
:
Date
.
now
()
}
let
tempJSON
=
JSON
.
parse
(
JSON
.
stringify
(
chatContentList
))
tempJSON
.
push
(
userContent
)
setChatContentList
(
tempJSON
)
// 开始读取流数据
readBuffer
(
reader
,
decoder
)
;
readBuffer
(
reader
,
decoder
)
})
.
catch
(
(
error
)
=>
{
.
catch
(
error
=>
{
// 处理请求错误
console
.
error
(
'Request failed:'
,
error
)
;
})
;
console
.
error
(
'Request failed:'
,
error
)
})
}
else
{
message
.
error
(
'请输入对话内容!'
)
;
message
.
error
(
'请输入对话内容!'
)
}
}
;
}
return
(
<
div
className=
'ai-drawer-content'
>
<
div
className=
'ai-chat-container'
>
<
div
className=
'chat-content'
id=
'chat-content'
>
<
div
className=
'chat-content-padd'
>
<
div
className=
"ai-drawer-content"
>
<
div
className=
"ai-chat-container"
>
<
div
className=
"chat-content"
id=
"chat-content"
>
<
div
className=
"chat-content-padd"
>
{
chatContentList
&&
chatContentList
.
length
>
0
&&
chatContentList
.
map
((
item
,
index
)
=>
{
return
(
<
div
className=
{
`chat-content-item`
}
key=
{
index
}
>
{
item
.
type
===
'user'
&&
(
<
div
className=
'time'
>
{
dayjs
(
item
.
time
).
format
(
'YYYY-MM-DD HH:mm'
)
}
</
div
>
)
}
{
item
.
type
===
'user'
&&
<
div
className=
"time"
>
{
dayjs
(
item
.
time
).
format
(
'YYYY-MM-DD HH:mm'
)
}
</
div
>
}
{
item
.
type
===
'ai'
&&
(
<
div
className=
'inside'
>
<
div
className=
'ai-in-content'
>
<
div
className=
'img'
>
<
img
src=
{
item
.
avatar
}
alt=
''
/>
<
div
className=
"inside"
>
<
div
className=
"ai-in-content"
>
<
div
className=
"img"
>
<
img
src=
{
item
.
avatar
}
alt=
""
/>
</
div
>
<
div
className=
'ask-content'
>
{
item
.
content
}
</
div
>
<
div
className=
"ask-content"
>
{
item
.
content
}
</
div
>
</
div
>
</
div
>
)
}
{
item
.
type
===
'user'
&&
(
<
div
className=
'inside inside-user'
>
<
div
className=
'user-in-content'
>
<
div
className=
'ask-content'
>
{
item
.
content
}
</
div
>
<
div
className=
'img'
>
<
img
src=
{
userInfo
.
pic
?
userInfo
.
pic
:
normalAvatar
}
alt=
'用户头像'
/>
<
div
className=
"inside inside-user"
>
<
div
className=
"user-in-content"
>
<
div
className=
"ask-content"
>
{
item
.
content
}
</
div
>
<
div
className=
"img"
>
<
img
src=
{
userInfo
.
pic
?
userInfo
.
pic
:
normalAvatar
}
alt=
"用户头像"
/>
</
div
>
</
div
>
</
div
>
)
}
</
div
>
)
;
)
})
}
</
div
>
</
div
>
</
div
>
<
div
className=
'ai-chat-ask'
>
<
div
className=
'text'
>
<
div
className=
"ai-chat-ask"
>
<
div
className=
"text"
>
<
Input
.
TextArea
value=
{
value
}
defaultValue=
{
value
}
allowClear
disabled=
{
loading
}
onChange=
{
(
e
)
=>
setValue
(
e
.
target
.
value
)
}
palceholder=
'请输入内容'
style=
{
{
height
:
'80px'
,
resize
:
'none'
}
}
></
Input
.
TextArea
>
onChange=
{
e
=>
setValue
(
e
.
target
.
value
)
}
palceholder=
"请输入内容"
style=
{
{
height
:
'80px'
,
resize
:
'none'
}
}
></
Input
.
TextArea
>
</
div
>
<
div
className=
'button'
>
<
Button
type=
'primary'
icon=
{
<
SendOutlined
/>
}
loading=
{
loading
}
size=
'large'
onClick=
{
targetChat
}
></
Button
>
<
div
className=
"button"
>
<
Button
type=
"primary"
icon=
{
<
SendOutlined
/>
}
loading=
{
loading
}
size=
"large"
onClick=
{
targetChat
}
></
Button
>
</
div
>
</
div
>
</
div
>
)
;
}
;
)
}
export
default
AIDrawerComponent
;
export
default
AIDrawerComponent
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论