Files
xk-admin/apps/web-antd/src/views/business/chat/utils/request.ts
李琦 52a1cb1ce5
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
feat:诊所问题优化,气泡卡片优化,修复了导入药品的时候无法打开开方组件并且切换tab的问题
2026-07-28 16:53:31 +08:00

393 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { message } from 'ant-design-vue';
import axios from 'axios';
import { useAccessStore } from '@vben/stores';
// 创建 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';
// 消息类型映射 - 根据用户提供的完整映射更新
const messageTypeMap: any = {
text: 0,
image: 1,
audio: 2,
video: 3,
prescription: 4,
'medical-record': 5,
'video-call': 6,
'audio-call': 7,
file: 8,
register: 10,
'patient-experience': 11,
'product-card': 12,
'end-consultation': 13,
};
// 确保 receiver_user_id 有 user- 前缀(如果是患者端)
const receiverId = data.receiverId.toString();
const normalizedReceiverId = receiverId.startsWith('user-') ? receiverId : `user-${receiverId}`;
// 确保 sender_user_id小助手保持 doctor_assistant医生端补 doctor- 前缀
const senderId = data.senderId.toString();
const normalizedSenderId =
senderId === 'doctor_assistant' || senderId.startsWith('doctor-')
? senderId
: `doctor-${senderId}`;
const requestData = {
room_id: data.roomId,
sender_user_id: normalizedSenderId,
receiver_user_id: normalizedReceiverId,
message_type: messageTypeMap[data.type] || 0,
message_content: data.content || '',
duration: data.duration || 0,
};
// 如果包含通话信令添加call_id和call_status
if (data.callId) {
requestData.call_id = data.callId;
}
if (data.callStatus) {
requestData.call_status = data.callStatus;
}
// 从 accessStore 获取 Token
const accessStore = useAccessStore();
const token = accessStore.accessToken;
return axios
.post(apiUrl, requestData, {
headers: {
'Content-Type': 'application/json',
'Authorization': token ? (token.startsWith('Bearer ') ? token : `Bearer ${token}`) : '',
},
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('缺少通话状态');
}
// 确保 receiver_user_id 有 user- 前缀(如果是患者端)
const receiverId = signalData.receiver_user_id;
const normalizedReceiverId = receiverId.startsWith('user-') || receiverId.startsWith('doctor-')
? receiverId
: `user-${receiverId}`;
// 构建通话信令请求数据
const requestData = {
sender_user_id: signalData.sender_user_id,
receiver_user_id: normalizedReceiverId,
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);
// 从 accessStore 获取 Token
const accessStore = useAccessStore();
const token = accessStore.accessToken;
return axios
.post(apiUrl, requestData, {
headers: {
'Content-Type': 'application/json',
'Authorization': token ? (token.startsWith('Bearer ') ? token : `Bearer ${token}`) : '',
},
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;