2025-04-18 20:09:21 +08:00
|
|
|
|
import axios from 'axios'
|
|
|
|
|
import { fetchEventSource } from '@microsoft/fetch-event-source'
|
|
|
|
|
|
2025-04-20 22:07:15 +08:00
|
|
|
|
// 判断是否在 Electron 环境中
|
|
|
|
|
const isElectron = window && window.process && window.process.type
|
|
|
|
|
|
2025-04-18 20:09:21 +08:00
|
|
|
|
const service = axios.create({
|
2025-04-20 22:07:15 +08:00
|
|
|
|
baseURL: isElectron ? process.env.VITE_APP_BASE_API : import.meta.env.VITE_APP_BASE_API,
|
2025-04-18 20:09:21 +08:00
|
|
|
|
timeout: 30000
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 请求拦截器
|
|
|
|
|
service.interceptors.request.use(
|
|
|
|
|
config => {
|
|
|
|
|
// 如果配置中已经包含了 Authorization header,则使用配置中的值
|
|
|
|
|
if (!config.headers['Authorization']) {
|
|
|
|
|
const token = localStorage.getItem('token')
|
|
|
|
|
if (token) {
|
|
|
|
|
config.headers['Authorization'] = `Bearer ${token}`
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
config.headers['Content-Type'] = 'application/json'
|
|
|
|
|
return config
|
|
|
|
|
},
|
|
|
|
|
error => {
|
|
|
|
|
return Promise.reject(error)
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 响应拦截器
|
|
|
|
|
service.interceptors.response.use(
|
|
|
|
|
response => {
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
error => {
|
|
|
|
|
return Promise.reject(error)
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// SSE 请求方法
|
|
|
|
|
export const sseRequest = (config) => {
|
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
|
try {
|
2025-04-20 22:07:15 +08:00
|
|
|
|
const baseURL = isElectron ? process.env.VITE_APP_BASE_API : import.meta.env.VITE_APP_BASE_API
|
|
|
|
|
const url = new URL(`${config.url}`, baseURL)
|
2025-04-18 20:09:21 +08:00
|
|
|
|
const ctrl = new AbortController()
|
|
|
|
|
let messageQueue = []
|
|
|
|
|
let resolveQueue = null
|
|
|
|
|
|
|
|
|
|
const messageGenerator = async function* () {
|
|
|
|
|
const source = new fetchEventSource(url.toString(), {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Authorization': config.headers?.Authorization || `Bearer ${localStorage.getItem('token')}`,
|
|
|
|
|
'Content-Type': 'application/json',
|
2025-04-20 22:07:15 +08:00
|
|
|
|
'Accept': 'text/event-stream',
|
|
|
|
|
'Cache-Control': 'no-cache',
|
|
|
|
|
'Connection': 'keep-alive'
|
2025-04-18 20:09:21 +08:00
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify(config.params),
|
|
|
|
|
signal: ctrl.signal,
|
|
|
|
|
openWhenHidden: true,
|
2025-04-20 22:07:15 +08:00
|
|
|
|
credentials: 'include',
|
|
|
|
|
keepalive: true,
|
|
|
|
|
retry: 1000,
|
|
|
|
|
onopen(response) {
|
|
|
|
|
if (response.ok && response.headers.get('content-type')?.includes('text/event-stream')) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
throw new Error(`Failed to open SSE connection: ${response.status} ${response.statusText}`);
|
|
|
|
|
},
|
2025-04-18 20:09:21 +08:00
|
|
|
|
onmessage: (event) => {
|
|
|
|
|
try {
|
|
|
|
|
const data = JSON.parse(event.data)
|
|
|
|
|
if (resolveQueue) {
|
|
|
|
|
resolveQueue(data)
|
|
|
|
|
resolveQueue = null
|
|
|
|
|
} else {
|
|
|
|
|
messageQueue.push(data)
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error parsing SSE message:', error)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onerror: (error) => {
|
|
|
|
|
console.error('EventSource failed:', error)
|
|
|
|
|
ctrl.abort()
|
|
|
|
|
if (resolveQueue) {
|
|
|
|
|
resolveQueue(null)
|
|
|
|
|
resolveQueue = null
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onclose: () => {
|
|
|
|
|
console.log('Connection closed')
|
|
|
|
|
if (resolveQueue) {
|
|
|
|
|
resolveQueue(null)
|
|
|
|
|
resolveQueue = null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
while (true) {
|
|
|
|
|
if (messageQueue.length > 0) {
|
|
|
|
|
yield messageQueue.shift()
|
|
|
|
|
} else {
|
|
|
|
|
const message = await new Promise(resolve => {
|
|
|
|
|
resolveQueue = resolve
|
|
|
|
|
})
|
|
|
|
|
if (message === null) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
yield message
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
ctrl.abort()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resolve(messageGenerator())
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('SSE request setup failed:', error)
|
|
|
|
|
resolve((async function* () {})())
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default service
|