chore: 整理项目结构,清理归档文件,更新部署配置
This commit is contained in:
@@ -280,16 +280,15 @@ export async function sendMessage(data: SendMessageRequest): Promise<SendMessage
|
||||
const response: any = await apiClient.post('/h5/conversations/current/messages', data, {
|
||||
timeout: 30000,
|
||||
})
|
||||
// response = {code:0, data: {user_message:..., ai_reply:...}, message:"success"}
|
||||
// response.data = 业务数据 {user_message:..., ai_reply:..., ...}
|
||||
const raw = response.data
|
||||
// 注意:apiClient 拦截器返回的是 {code: 0, data: {...}, message: "success"} 包装对象,
|
||||
// 需要通过 response.data 获取实际业务数据
|
||||
// 修复字段映射:后端返回 id/sender_type,H5前端期望 message_id/message_type
|
||||
return {
|
||||
user_message: mapMessage(raw.user_message),
|
||||
ai_reply: raw.ai_reply ? mapMessage(raw.ai_reply) : raw.ai_reply,
|
||||
is_guidance: raw.is_guidance,
|
||||
ai_reply_count: raw.ai_reply_count,
|
||||
can_call_agent: raw.can_call_agent,
|
||||
user_message: mapMessage(response.data.user_message),
|
||||
ai_reply: response.data.ai_reply ? mapMessage(response.data.ai_reply) : response.data.ai_reply,
|
||||
is_guidance: response.data.is_guidance,
|
||||
ai_reply_count: response.data.ai_reply_count,
|
||||
can_call_agent: response.data.can_call_agent,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,8 +115,9 @@ export async function uploadImage(file: File): Promise<{
|
||||
'/messages/image',
|
||||
formData,
|
||||
{
|
||||
// ISS-B4 修复:不显式设置 Content-Type,让浏览器自动生成带 boundary 的 multipart/form-data
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'Content-Type': undefined,
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -141,8 +142,9 @@ export async function uploadMessageFile(file: File): Promise<{
|
||||
'/messages/file',
|
||||
formData,
|
||||
{
|
||||
// ISS-B4 修复:不显式设置 Content-Type,让浏览器自动生成带 boundary 的 multipart/form-data
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'Content-Type': undefined,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -47,19 +47,46 @@ export async function uploadFile(file: File | Blob, blobNamePrefix: string = 'pa
|
||||
formData.append('file', file as File)
|
||||
}
|
||||
|
||||
// 发送上传请求(60 秒超时,大文件上传可能较慢)
|
||||
// 注意:必须显式删除 Content-Type,让浏览器自动生成带 boundary 的 multipart/form-data
|
||||
// 原因:apiClient 实例默认设置了 'Content-Type': 'application/json'
|
||||
// 如果不覆盖,Axios 会保留 application/json,后端无法解析 FormData 中的 file 字段
|
||||
const response: any = await apiClient.post('/upload', formData, {
|
||||
headers: {
|
||||
'Content-Type': undefined,
|
||||
},
|
||||
timeout: 60000,
|
||||
})
|
||||
// ISS-B3 修复:上传带自动重试(3次,指数退避 1s→2s→4s)
|
||||
return await uploadWithRetry(formData)
|
||||
}
|
||||
|
||||
// 响应拦截器已确保 code === 0
|
||||
// response = {code:0, data: {url:"...",...}, message:"success"}(拦截器返回值)
|
||||
// response.data = 业务数据 {url:"...", filename:"...", ...}
|
||||
return response.data as UploadResponse
|
||||
/**
|
||||
* 上传重试包装函数
|
||||
*
|
||||
* 做什么:对文件上传请求进行自动重试,最多 3 次
|
||||
* 为什么:网络波动时避免用户手动重试,提升上传成功率
|
||||
* 重试策略:指数退避(1秒 → 2秒 → 4秒),最多 3 次重试(共 4 次尝试)
|
||||
*
|
||||
* @param formData - 已构建好的 FormData 对象
|
||||
* @param maxRetries - 最大重试次数(默认 3)
|
||||
* @returns 上传响应数据
|
||||
*/
|
||||
async function uploadWithRetry(formData: FormData, maxRetries: number = 3): Promise<UploadResponse> {
|
||||
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
// 发送上传请求(60 秒超时,大文件上传可能较慢)
|
||||
// 注意:必须显式删除 Content-Type,让浏览器自动生成带 boundary 的 multipart/form-data
|
||||
// 原因:apiClient 实例默认设置了 'Content-Type': 'application/json'
|
||||
// 如果不覆盖,Axios 会保留 application/json,后端无法解析 FormData 中的 file 字段
|
||||
const response: any = await apiClient.post('/upload', formData, {
|
||||
headers: {
|
||||
'Content-Type': undefined,
|
||||
},
|
||||
timeout: 60000,
|
||||
})
|
||||
// 响应拦截器已确保 code === 0
|
||||
// response = {code:0, data: {url:"...",...}, message:"success"}(拦截器返回值)
|
||||
// response.data = 业务数据 {url:"...", filename:"...", ...}
|
||||
return response.data as UploadResponse
|
||||
} catch (err) {
|
||||
if (attempt === maxRetries) throw err
|
||||
// 指数退避:1s, 2s, 4s
|
||||
const delay = 1000 * Math.pow(2, attempt)
|
||||
console.warn(`[Upload H5] 上传失败,${delay / 1000}秒后重试(第 ${attempt + 1}/${maxRetries} 次)`)
|
||||
await new Promise(r => setTimeout(r, delay))
|
||||
}
|
||||
}
|
||||
// 不应到达此处,但 TypeScript 需要返回值
|
||||
throw new Error('上传失败:已达最大重试次数')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user