Files
xk-admin/apps/web-antd/src/views/business/chat/utils/request.ts

393 lines
10 KiB
TypeScript
Raw Normal View History

2025-07-19 16:47:52 +08:00
import { message } from 'ant-design-vue';
import axios from 'axios';
2026-01-07 14:22:01 +08:00
import { useAccessStore } from '@vben/stores';
2025-07-19 16:47:52 +08:00
// 创建 Axios 实例
const service = axios.create({
baseURL: '/im-api/',
timeout: 15_000,
});
// 请求拦截器
service.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
console.error('Request error:', error);
return Promise.reject(error);
},
);
// 响应拦截器
service.interceptors.response.use(
(response) => {
const { code, result, message: msg } = response.data;
if (code === 0) {
return result;
} else {
if (code === 401) {
message.error(msg);
localStorage.removeItem('token');
localStorage.removeItem('chatUser');
window.location.href = '/login';
return Promise.reject(new Error(msg));
}
message.error(msg);
return Promise.reject(new Error(msg));
}
},
(error) => {
console.error('Response error:', error);
// 详细的错误处理
if (error.code === 'ECONNABORTED') {
console.log('请求超时,请检查网络连接');
} else if (error.response?.status === 0 || error.message.includes('CORS')) {
console.log('CORS错误检测到,尝试备用方案...');
handleCORSError(error.config);
} else if (error.response?.status >= 400 && error.response?.status < 500) {
console.log('客户端错误:', error.response.status, error.response.data);
} else if (error.response?.status >= 500) {
console.log('服务器错误:', error.response.status);
} else {
console.log('网络错误:', error.message);
}
message.error('网络请求失败');
return Promise.reject(error);
},
);
// CORS错误的备用处理方案
const handleCORSError = (config) => {
console.log('执行CORS错误备用方案...');
const apiUrl = config.url.replace('/api', '');
return fetch(apiUrl, {
method: config.method.toUpperCase(),
headers: {
'Content-Type': 'application/json',
...config.headers,
},
mode: 'cors',
body: config.data ? JSON.stringify(config.data) : undefined,
})
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.catch((error) => {
console.error('备用方案也失败:', error);
throw error;
});
};
// 封装请求方法
export const get = (url, params = {}) => {
return service.get(url, { params });
};
export const post = (url, data = {}) => {
return service.post(url, data);
};
export const upload = (url, file) => {
const formData = new FormData();
formData.append('file', file);
return service.post(url, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
};
// 发送普通消息API
export const sendMessage = (data) => {
const apiUrl = '/im-api/send-to-user';
// 消息类型映射 - 根据用户提供的完整映射更新
2025-08-30 15:31:03 +08:00
const messageTypeMap: any = {
2025-07-19 16:47:52 +08:00
text: 0,
image: 1,
audio: 2,
video: 3,
prescription: 4,
'medical-record': 5,
'video-call': 6,
'audio-call': 7,
file: 8,
2026-01-07 14:22:01 +08:00
register: 10,
'patient-experience': 11,
'product-card': 12,
'end-consultation': 13,
2025-07-19 16:47:52 +08:00
};
2025-12-23 11:05:12 +08:00
// 确保 receiver_user_id 有 user- 前缀(如果是患者端)
const receiverId = data.receiverId.toString();
const normalizedReceiverId = receiverId.startsWith('user-') ? receiverId : `user-${receiverId}`;
// 确保 sender_user_id:小助手保持 doctor_assistant;医生端补 doctor- 前缀
2025-12-23 11:05:12 +08:00
const senderId = data.senderId.toString();
const normalizedSenderId =
senderId === 'doctor_assistant' || senderId.startsWith('doctor-')
? senderId
: `doctor-${senderId}`;
2025-12-23 11:05:12 +08:00
2025-07-19 16:47:52 +08:00
const requestData = {
room_id: data.roomId,
2025-12-23 11:05:12 +08:00
sender_user_id: normalizedSenderId,
receiver_user_id: normalizedReceiverId,
2025-07-19 16:47:52 +08:00
message_type: messageTypeMap[data.type] || 0,
message_content: data.content || '',
2025-07-22 16:55:09 +08:00
duration: data.duration || 0,
2025-07-19 16:47:52 +08:00
};
// 如果包含通话信令,添加call_id和call_status
if (data.callId) {
requestData.call_id = data.callId;
}
if (data.callStatus) {
requestData.call_status = data.callStatus;
}
2026-01-07 14:22:01 +08:00
// 从 accessStore 获取 Token
const accessStore = useAccessStore();
const token = accessStore.accessToken;
2025-07-19 16:47:52 +08:00
return axios
.post(apiUrl, requestData, {
headers: {
'Content-Type': 'application/json',
2026-01-07 14:22:01 +08:00
'Authorization': token ? (token.startsWith('Bearer ') ? token : `Bearer ${token}`) : '',
2025-07-19 16:47:52 +08:00
},
timeout: 15_000,
withCredentials: false,
})
.then((response) => {
console.log('消息发送成功:', response.data);
return response.data;
})
.catch((error) => {
console.error('消息发送失败:', error);
throw error;
});
};
// 专门的通话信令发送方法
export const sendCallSignal = (signalData) => {
const apiUrl = '/api/send-to-user';
// 验证必要参数
if (!signalData.sender_user_id) {
throw new Error('缺少发送方用户ID');
}
if (!signalData.receiver_user_id) {
throw new Error('缺少接收方用户ID');
}
if (!signalData.call_id) {
throw new Error('缺少通话ID');
}
if (!signalData.call_status) {
throw new Error('缺少通话状态');
}
2025-12-23 11:05:12 +08:00
// 确保 receiver_user_id 有 user- 前缀(如果是患者端)
const receiverId = signalData.receiver_user_id;
const normalizedReceiverId = receiverId.startsWith('user-') || receiverId.startsWith('doctor-')
? receiverId
: `user-${receiverId}`;
2025-07-19 16:47:52 +08:00
// 构建通话信令请求数据
const requestData = {
sender_user_id: signalData.sender_user_id,
2025-12-23 11:05:12 +08:00
receiver_user_id: normalizedReceiverId,
2025-07-19 16:47:52 +08:00
message_type: signalData.message_type || 6, // 默认视频通话
message_content:
signalData.message_content || JSON.stringify(signalData.data || {}),
call_id: signalData.call_id,
call_status: signalData.call_status,
// 添加来源标记
isFromHttp: true,
};
console.log('发送通话信令到API:', apiUrl, requestData);
2026-01-07 14:22:01 +08:00
// 从 accessStore 获取 Token
const accessStore = useAccessStore();
const token = accessStore.accessToken;
2025-07-19 16:47:52 +08:00
return axios
.post(apiUrl, requestData, {
headers: {
'Content-Type': 'application/json',
2026-01-07 14:22:01 +08:00
'Authorization': token ? (token.startsWith('Bearer ') ? token : `Bearer ${token}`) : '',
2025-07-19 16:47:52 +08:00
},
timeout: 15_000,
withCredentials: false,
})
.then((response) => {
console.log('通话信令发送成功:', response.data);
return response.data;
})
.catch((error) => {
console.error('通话信令发送失败:', error);
// 提供更详细的错误信息
if (error.response) {
console.error('响应错误:', error.response.data);
console.error('响应状态:', error.response.status);
console.error('响应头:', error.response.headers);
} else if (error.request) {
console.error('请求错误:', error.request);
} else {
console.error('配置错误:', error.message);
}
throw error;
});
};
// 通话相关的便捷方法
export const callAPI = {
// 发起通话邀请
invite: (senderUserId, receiverUserId, callId, callType = 6) => {
return sendCallSignal({
sender_user_id: senderUserId,
receiver_user_id: receiverUserId,
call_id: callId,
call_status: 'invite',
message_type: callType, // 6=视频, 7=语音
});
},
// 接受通话
accept: (senderUserId, receiverUserId, callId, callType = 6) => {
return sendCallSignal({
sender_user_id: senderUserId,
receiver_user_id: receiverUserId,
call_id: callId,
call_status: 'accepted',
message_type: callType,
});
},
// 拒绝通话
reject: (senderUserId, receiverUserId, callId, callType = 6) => {
return sendCallSignal({
sender_user_id: senderUserId,
receiver_user_id: receiverUserId,
call_id: callId,
call_status: 'rejected',
message_type: callType,
});
},
// 结束通话
end: (senderUserId, receiverUserId, callId, callType = 6) => {
return sendCallSignal({
sender_user_id: senderUserId,
receiver_user_id: receiverUserId,
call_id: callId,
call_status: 'ended',
message_type: callType,
});
},
// 发送WebRTC Offer
sendOffer: (
senderUserId,
receiverUserId,
callId,
offerData,
callType = 6,
) => {
return sendCallSignal({
sender_user_id: senderUserId,
receiver_user_id: receiverUserId,
call_id: callId,
call_status: 'offer',
message_type: callType,
data: offerData,
});
},
// 发送WebRTC Answer
sendAnswer: (
senderUserId,
receiverUserId,
callId,
answerData,
callType = 6,
) => {
return sendCallSignal({
sender_user_id: senderUserId,
receiver_user_id: receiverUserId,
call_id: callId,
call_status: 'answer',
message_type: callType,
data: answerData,
});
},
// 发送ICE候选
sendCandidate: (
senderUserId,
receiverUserId,
callId,
candidateData,
callType = 6,
) => {
return sendCallSignal({
sender_user_id: senderUserId,
receiver_user_id: receiverUserId,
call_id: callId,
call_status: 'candidate',
message_type: callType,
data: candidateData,
});
},
// 发送忙线状态
sendBusy: (senderUserId, receiverUserId, callId, callType = 6) => {
return sendCallSignal({
sender_user_id: senderUserId,
receiver_user_id: receiverUserId,
call_id: callId,
call_status: 'busy',
message_type: callType,
});
},
// 发送无人接听
sendNoAnswer: (senderUserId, receiverUserId, callId, callType = 6) => {
return sendCallSignal({
sender_user_id: senderUserId,
receiver_user_id: receiverUserId,
call_id: callId,
call_status: 'no-answer',
message_type: callType,
});
},
// 发送通话失败
sendFailed: (senderUserId, receiverUserId, callId, callType = 6) => {
return sendCallSignal({
sender_user_id: senderUserId,
receiver_user_id: receiverUserId,
call_id: callId,
call_status: 'failed',
message_type: callType,
});
},
};
export default service;