sg-paisou 0.0.0 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.npm.md +322 -0
- package/dist/ai-chat-sdk.es.js +22610 -0
- package/dist/ai-chat-sdk.es.js.map +1 -0
- package/dist/ai-chat-sdk.umd.js +300 -0
- package/dist/ai-chat-sdk.umd.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/types/index.d.ts +48 -0
- package/package.json +58 -11
- package/.idea/GitCommitMessageStorage.xml +0 -8
- package/.idea/modules.xml +0 -8
- package/.idea/sg-paisou-web.iml +0 -12
- package/.idea/vcs.xml +0 -6
- package/.vscode/settings.json +0 -2
- package/auto-imports.d.ts +0 -10
- package/components.d.ts +0 -18
- package/index.html +0 -21
- package/src/App.vue +0 -38
- package/src/assets/images/Camera-icon.png +0 -0
- package/src/assets/images/anger.png +0 -0
- package/src/assets/images/answer-icon.png +0 -0
- package/src/assets/images/back.png +0 -0
- package/src/assets/images/bg-img.png +0 -0
- package/src/assets/images/collect.png +0 -0
- package/src/assets/images/collected.png +0 -0
- package/src/assets/images/empty-bookmark.png +0 -0
- package/src/assets/images/empty-history.png +0 -0
- package/src/assets/images/feedback-thinkie-img.png +0 -0
- package/src/assets/images/history.png +0 -0
- package/src/assets/images/image 5.png +0 -0
- package/src/assets/images/insolubility.png +0 -0
- package/src/assets/images/key-points.png +0 -0
- package/src/assets/images/photograph-icon.png +0 -0
- package/src/assets/images/praise-icon.png +0 -0
- package/src/assets/images/praiseing-icon.png +0 -0
- package/src/assets/images/question.png +0 -0
- package/src/assets/images/smiling.png +0 -0
- package/src/assets/images/solution-icon.png +0 -0
- package/src/assets/images/star-icon.png +0 -0
- package/src/assets/images/trample-icon.png +0 -0
- package/src/assets/images/trampleing-icon.png +0 -0
- package/src/assets/images/volume-icon.png +0 -0
- package/src/assets/images/volumeing-icon.png +0 -0
- package/src/components/AIChatSDK/AIChatComponent.vue +0 -963
- package/src/components/AIChatSDK/component/Dialogs.vue +0 -340
- package/src/components/AIChatSDK/component/SpecialQuestions.vue +0 -208
- package/src/components/AIChatSDK/index.ts +0 -146
- package/src/components/AIChatSDK/style.scss +0 -432
- package/src/components/AIChatSDK/utils/imageUtils.ts +0 -61
- package/src/components/AIChatSDK/utils/latex.ts +0 -34
- package/src/components/AIChatSDK/utils/mergeConfig.ts +0 -125
- package/src/components/ImagePreview.vue +0 -62
- package/src/components/PageHeader/index.vue +0 -121
- package/src/config.ts +0 -11
- package/src/env.d.ts +0 -11
- package/src/main.ts +0 -12
- package/src/router.ts +0 -20
- package/src/style.css +0 -33
- package/src/type.ts +0 -106
- package/src/utils/TTS_README.md +0 -232
- package/src/utils/bridge.ts +0 -42
- package/src/utils/index.ts +0 -8
- package/src/utils/listenOsEvent.ts +0 -3
- package/src/utils/messageToast.ts +0 -43
- package/src/utils/render.ts +0 -81
- package/src/utils/request.ts +0 -87
- package/src/utils/tts.ts +0 -319
- package/src/utils/typewriter.ts +0 -61
- package/src/utils/useSSE.ts +0 -113
- package/src/views/History/index.vue +0 -419
- package/src/views/QuestionChatPage/index.vue +0 -480
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.app.json +0 -24
- package/tsconfig.json +0 -7
- package/tsconfig.node.json +0 -22
- package/vite.config.ts +0 -41
- /package/{public → dist}/mathjax/all-packages.js +0 -0
- /package/{public → dist}/mathjax/talEditorConfig.js +0 -0
- /package/{public → dist}/mathjax/tex-svg.js +0 -0
- /package/{src/components/AIChatSDK/types.ts → dist/types/types.d.ts} +0 -0
package/src/utils/tts.ts
DELETED
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
import { ENV_PATH_SSE } from "../config";
|
|
2
|
-
import { getRequestHeader } from "./request";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* TTS音频播放队列管理器
|
|
6
|
-
*/
|
|
7
|
-
class TTSPlayer {
|
|
8
|
-
private audioQueue: HTMLAudioElement[] = []
|
|
9
|
-
private isPlaying = false
|
|
10
|
-
private isMuted = false
|
|
11
|
-
private currentAudio: HTMLAudioElement | null = null
|
|
12
|
-
private manualPlayAudio: HTMLAudioElement | null = null // 手动播放的音频
|
|
13
|
-
private manualPlayMessageId: string | null = null // 手动播放的消息ID
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 添加音频到队列
|
|
17
|
-
*/
|
|
18
|
-
addAudio(audioBlob: Blob) {
|
|
19
|
-
if (this.isMuted) {
|
|
20
|
-
console.log('[TTS] Skipping audio - player is muted')
|
|
21
|
-
return
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const audio = new Audio(URL.createObjectURL(audioBlob))
|
|
25
|
-
this.audioQueue.push(audio)
|
|
26
|
-
console.log(`[TTS] Audio added to queue. Queue length: ${this.audioQueue.length}`)
|
|
27
|
-
|
|
28
|
-
// 如果当前没有播放且未静音,开始播放
|
|
29
|
-
if (!this.isPlaying && !this.isMuted) {
|
|
30
|
-
this.playNext()
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 播放下一个音频
|
|
36
|
-
*/
|
|
37
|
-
private playNext() {
|
|
38
|
-
if (this.audioQueue.length === 0 || this.isMuted) {
|
|
39
|
-
this.isPlaying = false
|
|
40
|
-
this.currentAudio = null
|
|
41
|
-
console.log('[TTS] Playback finished or muted')
|
|
42
|
-
return
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
this.isPlaying = true
|
|
46
|
-
this.currentAudio = this.audioQueue.shift()!
|
|
47
|
-
console.log(`[TTS] Playing audio. Remaining in queue: ${this.audioQueue.length}`)
|
|
48
|
-
|
|
49
|
-
this.currentAudio.onended = () => {
|
|
50
|
-
console.log('[TTS] Audio ended')
|
|
51
|
-
// 释放资源
|
|
52
|
-
if (this.currentAudio) {
|
|
53
|
-
URL.revokeObjectURL(this.currentAudio.src)
|
|
54
|
-
}
|
|
55
|
-
this.playNext()
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
this.currentAudio.onerror = (e) => {
|
|
59
|
-
console.error('[TTS] Audio playback error:', e)
|
|
60
|
-
if (this.currentAudio) {
|
|
61
|
-
URL.revokeObjectURL(this.currentAudio.src)
|
|
62
|
-
}
|
|
63
|
-
this.playNext()
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
this.currentAudio.play().catch(err => {
|
|
67
|
-
console.error('[TTS] Failed to play audio:', err)
|
|
68
|
-
this.playNext()
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* 设置静音状态
|
|
74
|
-
*/
|
|
75
|
-
setMuted(muted: boolean) {
|
|
76
|
-
console.log(`[TTS] Setting muted state to: ${muted}`)
|
|
77
|
-
this.isMuted = muted
|
|
78
|
-
|
|
79
|
-
if (muted) {
|
|
80
|
-
// 停止当前播放
|
|
81
|
-
if (this.currentAudio) {
|
|
82
|
-
this.currentAudio.pause()
|
|
83
|
-
this.currentAudio.currentTime = 0
|
|
84
|
-
URL.revokeObjectURL(this.currentAudio.src)
|
|
85
|
-
this.currentAudio = null
|
|
86
|
-
console.log('[TTS] Current audio stopped')
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// 清空队列
|
|
90
|
-
const queueLength = this.audioQueue.length
|
|
91
|
-
this.audioQueue.forEach(audio => {
|
|
92
|
-
URL.revokeObjectURL(audio.src)
|
|
93
|
-
})
|
|
94
|
-
this.audioQueue = []
|
|
95
|
-
this.isPlaying = false
|
|
96
|
-
console.log(`[TTS] Cleared ${queueLength} audio(s) from queue`)
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* 清空队列
|
|
102
|
-
*/
|
|
103
|
-
clear() {
|
|
104
|
-
this.setMuted(true)
|
|
105
|
-
this.isMuted = false
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* 手动播放单个消息的TTS
|
|
110
|
-
* 优先级高于自动播放队列
|
|
111
|
-
*/
|
|
112
|
-
playManual(audioBlob: Blob, messageId: string, onStart?: () => void, onEnd?: () => void) {
|
|
113
|
-
// 停止当前手动播放
|
|
114
|
-
if (this.manualPlayAudio) {
|
|
115
|
-
this.manualPlayAudio.pause()
|
|
116
|
-
URL.revokeObjectURL(this.manualPlayAudio.src)
|
|
117
|
-
this.manualPlayAudio = null
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// 暂停自动播放队列
|
|
121
|
-
if (this.currentAudio && this.isPlaying) {
|
|
122
|
-
this.currentAudio.pause()
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
this.manualPlayMessageId = messageId
|
|
126
|
-
this.manualPlayAudio = new Audio(URL.createObjectURL(audioBlob))
|
|
127
|
-
|
|
128
|
-
console.log(`[TTS Manual] Playing message: ${messageId}`)
|
|
129
|
-
onStart?.()
|
|
130
|
-
|
|
131
|
-
this.manualPlayAudio.onended = () => {
|
|
132
|
-
console.log(`[TTS Manual] Playback ended for message: ${messageId}`)
|
|
133
|
-
if (this.manualPlayAudio) {
|
|
134
|
-
URL.revokeObjectURL(this.manualPlayAudio.src)
|
|
135
|
-
}
|
|
136
|
-
this.manualPlayAudio = null
|
|
137
|
-
this.manualPlayMessageId = null
|
|
138
|
-
onEnd?.()
|
|
139
|
-
|
|
140
|
-
// 恢复自动播放队列
|
|
141
|
-
if (this.currentAudio && this.isPlaying && !this.isMuted) {
|
|
142
|
-
this.currentAudio.play().catch(err => {
|
|
143
|
-
console.error('[TTS] Failed to resume auto-play:', err)
|
|
144
|
-
this.playNext()
|
|
145
|
-
})
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
this.manualPlayAudio.onerror = (e) => {
|
|
150
|
-
console.error('[TTS Manual] Playback error:', e)
|
|
151
|
-
if (this.manualPlayAudio) {
|
|
152
|
-
URL.revokeObjectURL(this.manualPlayAudio.src)
|
|
153
|
-
}
|
|
154
|
-
this.manualPlayAudio = null
|
|
155
|
-
this.manualPlayMessageId = null
|
|
156
|
-
onEnd?.()
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
this.manualPlayAudio.play().catch(err => {
|
|
160
|
-
console.error('[TTS Manual] Failed to play:', err)
|
|
161
|
-
onEnd?.()
|
|
162
|
-
})
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* 停止手动播放
|
|
167
|
-
*/
|
|
168
|
-
stopManual(messageId?: string) {
|
|
169
|
-
if (messageId && this.manualPlayMessageId !== messageId) {
|
|
170
|
-
return
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (this.manualPlayAudio) {
|
|
174
|
-
console.log(`[TTS Manual] Stopping playback`)
|
|
175
|
-
this.manualPlayAudio.pause()
|
|
176
|
-
URL.revokeObjectURL(this.manualPlayAudio.src)
|
|
177
|
-
this.manualPlayAudio = null
|
|
178
|
-
this.manualPlayMessageId = null
|
|
179
|
-
|
|
180
|
-
// 恢复自动播放队列
|
|
181
|
-
if (this.currentAudio && this.isPlaying && !this.isMuted) {
|
|
182
|
-
this.currentAudio.play().catch(err => {
|
|
183
|
-
console.error('[TTS] Failed to resume auto-play:', err)
|
|
184
|
-
this.playNext()
|
|
185
|
-
})
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* 检查消息是否正在手动播放
|
|
192
|
-
*/
|
|
193
|
-
isManualPlaying(messageId: string): boolean {
|
|
194
|
-
return this.manualPlayMessageId === messageId && this.manualPlayAudio !== null
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// 创建全局TTS播放器实例
|
|
199
|
-
export const ttsPlayer = new TTSPlayer()
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* 请求TTS音频流(支持流式响应)
|
|
203
|
-
*/
|
|
204
|
-
export const fetchTTSAudio = async (
|
|
205
|
-
sessionId: string,
|
|
206
|
-
sessionDetailId: string,
|
|
207
|
-
text: string
|
|
208
|
-
): Promise<Blob> => {
|
|
209
|
-
const questionInfo = JSON.parse(sessionStorage.getItem('questionInfo') || '{}')
|
|
210
|
-
const headerObj = getRequestHeader()
|
|
211
|
-
|
|
212
|
-
const response = await fetch(`${ENV_PATH_SSE[questionInfo.envNumber]}/v1/sg/tts`, {
|
|
213
|
-
method: 'POST',
|
|
214
|
-
headers: {
|
|
215
|
-
'Content-Type': 'application/json',
|
|
216
|
-
...headerObj
|
|
217
|
-
},
|
|
218
|
-
body: JSON.stringify({
|
|
219
|
-
sessionId,
|
|
220
|
-
sessionDetailId,
|
|
221
|
-
text
|
|
222
|
-
})
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
if (!response.ok) {
|
|
226
|
-
throw new Error(`TTS request failed: ${response.statusText}`)
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// 如果是流式响应,读取完整的流
|
|
230
|
-
if (response.body) {
|
|
231
|
-
const reader = response.body.getReader()
|
|
232
|
-
const chunks: Uint8Array[] = []
|
|
233
|
-
|
|
234
|
-
while (true) {
|
|
235
|
-
const { done, value } = await reader.read()
|
|
236
|
-
if (done) break
|
|
237
|
-
if (value) chunks.push(value)
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// 合并所有chunks
|
|
241
|
-
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0)
|
|
242
|
-
const result = new Uint8Array(totalLength)
|
|
243
|
-
let offset = 0
|
|
244
|
-
for (const chunk of chunks) {
|
|
245
|
-
result.set(chunk, offset)
|
|
246
|
-
offset += chunk.length
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
return new Blob([result], { type: 'audio/mpeg' })
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return await response.blob()
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* 请求并播放TTS音频(自动播放队列)
|
|
257
|
-
*/
|
|
258
|
-
export const playTTSAudio = async (
|
|
259
|
-
sessionId: string,
|
|
260
|
-
sessionDetailId: string,
|
|
261
|
-
text: string,
|
|
262
|
-
isMuted: boolean
|
|
263
|
-
) => {
|
|
264
|
-
if (isMuted || !text.trim()) {
|
|
265
|
-
console.log('[TTS] Skipping TTS request - muted or empty text')
|
|
266
|
-
return
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
console.log(`[TTS] Requesting TTS for text: "${text.substring(0, 50)}..."`)
|
|
270
|
-
|
|
271
|
-
try {
|
|
272
|
-
const audioBlob = await fetchTTSAudio(sessionId, sessionDetailId, text)
|
|
273
|
-
console.log(`[TTS] Received audio blob, size: ${audioBlob.size} bytes`)
|
|
274
|
-
ttsPlayer.addAudio(audioBlob)
|
|
275
|
-
} catch (error) {
|
|
276
|
-
console.error('[TTS] Failed to fetch TTS audio:', error)
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* 手动播放消息的TTS(用于播放按钮)
|
|
282
|
-
*/
|
|
283
|
-
export const playMessageTTS = async (
|
|
284
|
-
sessionId: string,
|
|
285
|
-
messageId: string,
|
|
286
|
-
text: string,
|
|
287
|
-
onStart?: () => void,
|
|
288
|
-
onEnd?: () => void
|
|
289
|
-
) => {
|
|
290
|
-
if (!text.trim()) {
|
|
291
|
-
console.log('[TTS Manual] Skipping - empty text')
|
|
292
|
-
return
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
console.log(`[TTS Manual] Requesting TTS for message: ${messageId}`)
|
|
296
|
-
|
|
297
|
-
try {
|
|
298
|
-
const audioBlob = await fetchTTSAudio(sessionId, messageId, text)
|
|
299
|
-
console.log(`[TTS Manual] Received audio blob, size: ${audioBlob.size} bytes`)
|
|
300
|
-
ttsPlayer.playManual(audioBlob, messageId, onStart, onEnd)
|
|
301
|
-
} catch (error) {
|
|
302
|
-
console.error('[TTS Manual] Failed to fetch TTS audio:', error)
|
|
303
|
-
onEnd?.()
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* 停止手动播放消息的TTS
|
|
309
|
-
*/
|
|
310
|
-
export const stopMessageTTS = (messageId?: string) => {
|
|
311
|
-
ttsPlayer.stopManual(messageId)
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* 检查消息是否正在播放
|
|
316
|
-
*/
|
|
317
|
-
export const isMessagePlaying = (messageId: string): boolean => {
|
|
318
|
-
return ttsPlayer.isManualPlaying(messageId)
|
|
319
|
-
}
|
package/src/utils/typewriter.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 打字机效果工具函数
|
|
3
|
-
* 按单词显示文本,而不是按字符
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export interface TypewriterOptions {
|
|
7
|
-
text: string
|
|
8
|
-
onUpdate: (displayedText: string) => void
|
|
9
|
-
onComplete: () => void
|
|
10
|
-
wordDelay?: number // 每个单词的延迟时间(毫秒)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class Typewriter {
|
|
14
|
-
private words: string[]
|
|
15
|
-
private currentIndex: number = 0
|
|
16
|
-
private timer: number | null = null
|
|
17
|
-
private options: TypewriterOptions
|
|
18
|
-
|
|
19
|
-
constructor(options: TypewriterOptions) {
|
|
20
|
-
this.options = {
|
|
21
|
-
wordDelay: 1000, // 默认50ms
|
|
22
|
-
...options
|
|
23
|
-
}
|
|
24
|
-
// 按空格分割成单词
|
|
25
|
-
this.words = this.options.text.split(/(\s+)/)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
start() {
|
|
29
|
-
this.displayNextWord()
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
private displayNextWord() {
|
|
33
|
-
if (this.currentIndex >= this.words.length) {
|
|
34
|
-
this.options.onComplete()
|
|
35
|
-
return
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const displayedText = this.words.slice(0, this.currentIndex + 1).join('')
|
|
39
|
-
this.options.onUpdate(displayedText)
|
|
40
|
-
this.currentIndex++
|
|
41
|
-
|
|
42
|
-
this.timer = window.setTimeout(() => {
|
|
43
|
-
this.displayNextWord()
|
|
44
|
-
}, this.options.wordDelay)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
stop() {
|
|
48
|
-
if (this.timer) {
|
|
49
|
-
clearTimeout(this.timer)
|
|
50
|
-
this.timer = null
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
skip() {
|
|
55
|
-
this.stop()
|
|
56
|
-
const fullText = this.words.join('')
|
|
57
|
-
this.options.onUpdate(fullText)
|
|
58
|
-
this.options.onComplete()
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
package/src/utils/useSSE.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { fetchEventSource } from "@microsoft/fetch-event-source";
|
|
2
|
-
import { getRequestHeader } from "./request";
|
|
3
|
-
import { ENV_PATH_SSE } from "../config";
|
|
4
|
-
|
|
5
|
-
const abortCtrl = new AbortController();
|
|
6
|
-
const signal = abortCtrl.signal;
|
|
7
|
-
|
|
8
|
-
const useSSE = <T = Record<string, unknown>>(
|
|
9
|
-
url: string,
|
|
10
|
-
payload: Record<string, unknown>,
|
|
11
|
-
customHeader: Record<string, string>,
|
|
12
|
-
method: "GET" | "POST",
|
|
13
|
-
options: {
|
|
14
|
-
onopen?: () => void;
|
|
15
|
-
onmessage?: (data: T) => void;
|
|
16
|
-
onerror?: (error: unknown) => void;
|
|
17
|
-
onclose?: () => void;
|
|
18
|
-
}
|
|
19
|
-
) => {
|
|
20
|
-
const hash = payload.hash;
|
|
21
|
-
const startSSE = async () => {
|
|
22
|
-
await fetchEventSource(url, {
|
|
23
|
-
method,
|
|
24
|
-
signal,
|
|
25
|
-
headers: {
|
|
26
|
-
"Content-Type": "application/json",
|
|
27
|
-
...customHeader,
|
|
28
|
-
},
|
|
29
|
-
body: JSON.stringify(payload),
|
|
30
|
-
onopen: async (response) => {
|
|
31
|
-
if (!response.ok) {
|
|
32
|
-
options.onerror?.(response.statusText);
|
|
33
|
-
} else {
|
|
34
|
-
options.onopen?.();
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
onmessage: (e: any) => {
|
|
38
|
-
try {
|
|
39
|
-
if (e.event === 'finish') {
|
|
40
|
-
options.onmessage?.({ type: e.event } as any);
|
|
41
|
-
options.onclose?.();
|
|
42
|
-
} else {
|
|
43
|
-
const data = JSON.parse(e.data || '{}') as T;
|
|
44
|
-
options.onmessage?.(payload.hash ? { ...data, hash, type: e.event } : { ...data, type: e.event });
|
|
45
|
-
}
|
|
46
|
-
} catch (error) {
|
|
47
|
-
options.onerror?.(error);
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
onerror: (error) => {
|
|
51
|
-
abortCtrl.abort();
|
|
52
|
-
options.onerror?.(error);
|
|
53
|
-
throw new Error(`error->e: ${error}`);
|
|
54
|
-
},
|
|
55
|
-
openWhenHidden: true,
|
|
56
|
-
onclose: () => {
|
|
57
|
-
options.onclose?.();
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
};
|
|
61
|
-
return {
|
|
62
|
-
startSSE,
|
|
63
|
-
abortCtrl,
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// 新增:解释题目的流式请求
|
|
68
|
-
export const explainQuestionSSE = (
|
|
69
|
-
params: {
|
|
70
|
-
sessionId: string
|
|
71
|
-
content: string
|
|
72
|
-
recommendQuestions?: boolean
|
|
73
|
-
},
|
|
74
|
-
onMessage: (e: {
|
|
75
|
-
id?: string
|
|
76
|
-
msgId?: string
|
|
77
|
-
event: string
|
|
78
|
-
data: any
|
|
79
|
-
}) => void,
|
|
80
|
-
onError: (e: any) => void,
|
|
81
|
-
onClose: () => void
|
|
82
|
-
) => {
|
|
83
|
-
const questionInfo = JSON.parse(sessionStorage.getItem('questionInfo') || '{}');
|
|
84
|
-
console.log('explainQuestionSSE', params)
|
|
85
|
-
const headerObj = getRequestHeader();
|
|
86
|
-
|
|
87
|
-
const { startSSE, abortCtrl } = useSSE(
|
|
88
|
-
`${ENV_PATH_SSE[questionInfo.envNumber]}/v1/sg/explain-question`,
|
|
89
|
-
{
|
|
90
|
-
sessionId: params.sessionId,
|
|
91
|
-
content: params.content,
|
|
92
|
-
recommendQuestions: params.recommendQuestions || false
|
|
93
|
-
},
|
|
94
|
-
headerObj as any,
|
|
95
|
-
"POST",
|
|
96
|
-
{
|
|
97
|
-
onmessage: (e: any) => {
|
|
98
|
-
onMessage(e);
|
|
99
|
-
},
|
|
100
|
-
onerror(e: any) {
|
|
101
|
-
onError(e);
|
|
102
|
-
},
|
|
103
|
-
onclose() {
|
|
104
|
-
onClose();
|
|
105
|
-
},
|
|
106
|
-
}
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
startSSE,
|
|
111
|
-
abort: () => abortCtrl.abort()
|
|
112
|
-
};
|
|
113
|
-
};
|