Skip to content

Commit b6e6c0a

Browse files
committed
feat: chat gpt
1 parent 63c5062 commit b6e6c0a

7 files changed

Lines changed: 622 additions & 40 deletions

File tree

src/pages/chatgpt/fixSse.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { SSE } from './sse'
2+
3+
const initSSE = (apiKey, apiContent) => {
4+
// const source = new SSE(`https://api.openai.com/v1/chat/completions`, {
5+
const source = new SSE(`https://api.zhizengzeng.com/v1/chat/completions`, {
6+
headers: {
7+
'Content-Type': 'application/json',
8+
Authorization: `Bearer ${apiKey}`,
9+
},
10+
method: 'POST',
11+
start: false,
12+
payload: JSON.stringify({
13+
model: 'gpt-3.5-turbo',
14+
stream: true,
15+
messages: [
16+
{
17+
role: 'assistant',
18+
content: apiContent,
19+
},
20+
],
21+
}),
22+
})
23+
return source
24+
}
25+
26+
export default initSSE

src/pages/chatgpt/index.jsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { toPng, toSvg } from 'html-to-image'
88
import { Button, Dropdown, Form, Input, Space, message } from 'antd'
99
import { DownloadOutlined, CopyOutlined } from '@ant-design/icons'
1010
import { copyTextToClipboard } from '@utils/aidFn'
11-
import initSSE from './sse'
11+
import initSSE from './fixSse'
1212

1313
const ChatGpt = () => {
1414
const markmapRef = useRef(null)
@@ -45,24 +45,41 @@ const ChatGpt = () => {
4545
structureResultRef.current = ''
4646
const source = initSSE(apiKey, text)
4747
source.addEventListener('message', (e) => {
48+
console.log('message', e.data)
4849
if (e.data !== '[DONE]') {
50+
console.log('NOT DONE')
4951
const payload = JSON.parse(e.data)
5052
const {
5153
delta: { content },
52-
} = payload.choices[0]
54+
} = payload?.choices[0] || { delta: { content: '' } }
5355
if (content) {
5456
apiResultRef.current += content
5557
setApiResult(apiResultRef.current)
5658
}
5759
} else {
60+
console.log('DONE')
61+
setReadyState(2)
5862
source.close()
5963
}
6064
})
6165

6266
source.addEventListener('readystatechange', (e) => {
6367
setReadyState(e.readyState)
64-
// if (e.readyState === 2) {
65-
// }
68+
console.log('readyState', e.readyState)
69+
if (e.readyState === 2) {
70+
console.log('SSE connection closed')
71+
}
72+
})
73+
74+
source.addEventListener('error', (e) => {
75+
console.error('SSE error:', e)
76+
source.close()
77+
})
78+
source.addEventListener('open', (e) => {
79+
console.log('SSE connection opened:', e)
80+
})
81+
source.addEventListener('abort', (e) => {
82+
console.log('SSE connection closed:', e)
6683
})
6784

6885
source.stream()
@@ -126,12 +143,13 @@ const ChatGpt = () => {
126143
const payload = JSON.parse(e.data)
127144
const {
128145
delta: { content },
129-
} = payload.choices[0]
146+
} = payload?.choices[0] || { delta: { content: '' } }
130147
if (content) {
131148
structureResultRef.current += content
132149
setStructureResult(structureResultRef.current)
133150
}
134151
} else {
152+
setStructureReadyState(2)
135153
source.close()
136154
}
137155
})
@@ -268,7 +286,7 @@ const ChatGpt = () => {
268286
</Space>
269287
)}
270288
</section>
271-
{/* {JSON.stringify(structureReadyState, null, 2)} */}
289+
{JSON.stringify(structureResult, null, 2)}
272290
{structureReadyState === 0 && <h3>Ai 正在理解的需求...</h3>}
273291
{structureReadyState === 1 && <h3>生成中...</h3>}
274292
{structureResult && (

src/pages/chatgpt/scrollBottom.jsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React, { useEffect, useRef } from 'react'
2+
3+
function AutoScrollSection({ messages }) {
4+
const sectionRef = useRef(null)
5+
6+
useEffect(() => {
7+
const section = sectionRef.current
8+
// 滚动到底部
9+
section.scrollTop = section.scrollHeight
10+
}, [messages]) // 只要messages变动,就执行
11+
12+
return (
13+
<section
14+
ref={sectionRef}
15+
style={{
16+
height: 200,
17+
overflowY: 'auto',
18+
border: '1px solid #ccc',
19+
padding: 8,
20+
}}
21+
>
22+
{messages.map((msg, idx) => (
23+
<div key={idx}>{msg}</div>
24+
))}
25+
</section>
26+
)
27+
}
28+
29+
// 使用示例
30+
export default function Demo() {
31+
const [messages, setMessages] = React.useState(['Hello', 'World'])
32+
33+
// 模拟新消息
34+
React.useEffect(() => {
35+
const timer = setInterval(() => {
36+
setMessages((prev) => [...prev, 'New message ' + Date.now()])
37+
}, 2000)
38+
return () => clearInterval(timer)
39+
}, [])
40+
41+
return <AutoScrollSection messages={messages} />
42+
}

0 commit comments

Comments
 (0)