会话间开发
18
App.vue
@ -15,15 +15,15 @@ export default {
|
|||||||
onHide: function () {
|
onHide: function () {
|
||||||
console.log("App Hide");
|
console.log("App Hide");
|
||||||
// 小程序退出时退出腾讯IM登录
|
// 小程序退出时退出腾讯IM登录
|
||||||
try {
|
// try {
|
||||||
if (globalTimChatManager && globalTimChatManager.tim) {
|
// if (globalTimChatManager && globalTimChatManager.tim) {
|
||||||
console.log('小程序退出,开始退出腾讯IM');
|
// console.log('小程序退出,开始退出腾讯IM');
|
||||||
globalTimChatManager.destroy();
|
// globalTimChatManager.destroy();
|
||||||
console.log('腾讯IM退出成功');
|
// console.log('腾讯IM退出成功');
|
||||||
}
|
// }
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.error('退出腾讯IM失败:', error);
|
// console.error('退出腾讯IM失败:', error);
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -120,7 +120,6 @@ $primary-color: #0877F1;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.system-message {
|
.system-message {
|
||||||
// background-color: #f0f0f0;
|
|
||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
padding: 12rpx;
|
padding: 12rpx;
|
||||||
margin: 20rpx 24rpx;
|
margin: 20rpx 24rpx;
|
||||||
@ -141,7 +140,7 @@ $primary-color: #0877F1;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.message-item {
|
.message-item {
|
||||||
margin-bottom: 16rpx;
|
margin-bottom: 30rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-content {
|
.message-content {
|
||||||
@ -162,14 +161,14 @@ $primary-color: #0877F1;
|
|||||||
width: 60rpx;
|
width: 60rpx;
|
||||||
height: 60rpx;
|
height: 60rpx;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-top: 28rpx; // 向下移动与气泡箭头对齐
|
margin-top: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-msg-avatar {
|
.user-msg-avatar {
|
||||||
width: 60rpx;
|
width: 60rpx;
|
||||||
height: 60rpx;
|
height: 60rpx;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-top: 28rpx; // 向下移动与气泡箭头对齐
|
margin-top: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 消息气泡容器
|
// 消息气泡容器
|
||||||
@ -1040,6 +1039,19 @@ $primary-color: #0877F1;
|
|||||||
object-fit: cover; /* 保持图片比例,裁剪多余部分 */
|
object-fit: cover; /* 保持图片比例,裁剪多余部分 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 图片消息气泡 - 无背景色 */
|
||||||
|
.image-bubble {
|
||||||
|
background: transparent !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移除图片消息气泡的小三角 */
|
||||||
|
.image-bubble::before,
|
||||||
|
.image-bubble::after {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.message-right .message-card {
|
.message-right .message-card {
|
||||||
margin-right: 8rpx;
|
margin-right: 8rpx;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -146,8 +146,9 @@ const sendTextMessage = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 发送图片消息
|
// 发送图片消息
|
||||||
const sendImageMessage = async (imageUrl) => {
|
const sendImageMessage = async (imageFile) => {
|
||||||
await sendMessage('image', imageUrl);
|
console.log('chat-input sendImageMessage 被调用,参数:', imageFile);
|
||||||
|
await sendMessage('image', imageFile);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 发送语音消息
|
// 发送语音消息
|
||||||
@ -164,6 +165,7 @@ const sendMessage = async (messageType, data) => {
|
|||||||
() => validateBeforeSend(false, false, props.timChatManager),
|
() => validateBeforeSend(false, false, props.timChatManager),
|
||||||
() => {
|
() => {
|
||||||
showMorePanel.value = false;
|
showMorePanel.value = false;
|
||||||
|
// 发送成功后滚动到底部
|
||||||
emit('messageSent');
|
emit('messageSent');
|
||||||
},
|
},
|
||||||
cloudCustomData.value
|
cloudCustomData.value
|
||||||
@ -197,7 +199,13 @@ const toggleMorePanel = () => {
|
|||||||
// 处理图片选择
|
// 处理图片选择
|
||||||
const showImagePicker = () => {
|
const showImagePicker = () => {
|
||||||
chooseImage(
|
chooseImage(
|
||||||
(res) => sendImageMessage(res),
|
(res) => {
|
||||||
|
console.log('选择图片成功,返回数据:', res);
|
||||||
|
// 提取实际的文件对象
|
||||||
|
const imageFile = res.tempFiles && res.tempFiles.length > 0 ? res.tempFiles[0] : res;
|
||||||
|
console.log('准备发送图片:', imageFile);
|
||||||
|
sendImageMessage(imageFile);
|
||||||
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
console.error('选择图片失败:', err);
|
console.error('选择图片失败:', err);
|
||||||
if (!err.errMsg?.includes('permission') && !err.errMsg?.includes('auth') && !err.errMsg?.includes('拒绝') && !err.errMsg?.includes('未授权')) {
|
if (!err.errMsg?.includes('permission') && !err.errMsg?.includes('auth') && !err.errMsg?.includes('拒绝') && !err.errMsg?.includes('未授权')) {
|
||||||
@ -213,7 +221,13 @@ const showImagePicker = () => {
|
|||||||
|
|
||||||
const takePhoto = () => {
|
const takePhoto = () => {
|
||||||
takePhotoUtil(
|
takePhotoUtil(
|
||||||
(res) => sendImageMessage(res),
|
(res) => {
|
||||||
|
console.log('拍照成功,返回数据:', res);
|
||||||
|
// 提取实际的文件对象
|
||||||
|
const imageFile = res.tempFiles && res.tempFiles.length > 0 ? res.tempFiles[0] : res;
|
||||||
|
console.log('准备发送图片:', imageFile);
|
||||||
|
sendImageMessage(imageFile);
|
||||||
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
console.error('拍照失败:', err);
|
console.error('拍照失败:', err);
|
||||||
if (!err.errMsg?.includes('permission') && !err.errMsg?.includes('auth') && !err.errMsg?.includes('拒绝') && !err.errMsg?.includes('未授权')) {
|
if (!err.errMsg?.includes('permission') && !err.errMsg?.includes('auth') && !err.errMsg?.includes('拒绝') && !err.errMsg?.includes('未授权')) {
|
||||||
@ -315,10 +329,10 @@ const sendSurveyMessage = async () => {
|
|||||||
const morePanelButtons = [
|
const morePanelButtons = [
|
||||||
{ text: '照片', icon: '/static/home/photo.png', action: showImagePicker },
|
{ text: '照片', icon: '/static/home/photo.png', action: showImagePicker },
|
||||||
{ text: '拍摄', icon: '/static/home/video.png', action: takePhoto },
|
{ text: '拍摄', icon: '/static/home/video.png', action: takePhoto },
|
||||||
// { text: '病情', icon: '/static/home/doctor.png', action: sendSymptomMessage },
|
// { text: '病情', icon: '/static/home/avatar.svg', action: sendSymptomMessage },
|
||||||
// { text: '处方', icon: '/static/home/doctor.png', action: sendPrescriptionMessage },
|
// { text: '处方', icon: '/static/home/avatar.svg', action: sendPrescriptionMessage },
|
||||||
// { text: '续方', icon: '/static/home/doctor.png', action: sendRefillMessage },
|
// { text: '续方', icon: '/static/home/avatar.svg', action: sendRefillMessage },
|
||||||
// { text: '问卷', icon: '/static/home/doctor.png', action: sendSurveyMessage }
|
// { text: '问卷', icon: '/static/home/avatar.svg', action: sendSurveyMessage }
|
||||||
];
|
];
|
||||||
|
|
||||||
function handleInputFocus() {
|
function handleInputFocus() {
|
||||||
|
|||||||
@ -45,7 +45,7 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const hasFilledDescription = computed(() => props.order && ('description' in props.order));
|
const hasFilledDescription = computed(() => props.order && ('description' in props.order));
|
||||||
const avatar = computed(() => props.doctorInfo?.avatar || '/static/home/doctor.png')
|
const avatar = computed(() => props.doctorInfo?.avatar || '/static/home/avatar.svg')
|
||||||
|
|
||||||
function addSymptomDescription() {
|
function addSymptomDescription() {
|
||||||
if (!hasFilledDescription.value) {
|
if (!hasFilledDescription.value) {
|
||||||
|
|||||||
@ -50,19 +50,19 @@
|
|||||||
|
|
||||||
<!-- 消息内容 -->
|
<!-- 消息内容 -->
|
||||||
<view v-else class="message-content">
|
<view v-else class="message-content">
|
||||||
<!-- 头像 -->
|
<!-- 医生头像(左侧) -->
|
||||||
<image
|
<image
|
||||||
v-if="message.flow === 'in'"
|
v-if="message.flow === 'in'"
|
||||||
class="doctor-msg-avatar"
|
class="doctor-msg-avatar"
|
||||||
:src="chatMember[message.from]?.avatar"
|
:src="chatMember[message.from]?.avatar || '/static/default-avatar.png'"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 用户头像(右侧) -->
|
<!-- 患者头像(右侧) -->
|
||||||
<image
|
<image
|
||||||
v-if="message.flow === 'out'"
|
v-if="message.flow === 'out'"
|
||||||
class="user-msg-avatar"
|
class="user-msg-avatar"
|
||||||
:src="chatMember[message.from]?.avatar"
|
:src="chatMember[message.from]?.avatar || '/static/home/avatar.svg'"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -113,8 +113,8 @@
|
|||||||
v-if="!isEvaluationPopupOpen"
|
v-if="!isEvaluationPopupOpen"
|
||||||
:timChatManager="timChatManager"
|
:timChatManager="timChatManager"
|
||||||
:formatTime="formatTime"
|
:formatTime="formatTime"
|
||||||
@scrollToBottom="scrollToBottom"
|
@scrollToBottom="() => scrollToBottom(true)"
|
||||||
@messageSent="scrollToBottom"
|
@messageSent="() => scrollToBottom(true)"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@ -170,7 +170,7 @@ const updateNavigationTitle = () => {
|
|||||||
const chatInfo = ref({
|
const chatInfo = ref({
|
||||||
conversationID: "",
|
conversationID: "",
|
||||||
userID: "",
|
userID: "",
|
||||||
avatar: "/static/home/doctor.png",
|
avatar: "/static/home/avatar.svg",
|
||||||
});
|
});
|
||||||
|
|
||||||
// 评价弹窗状态
|
// 评价弹窗状态
|
||||||
@ -196,6 +196,11 @@ function isSystemMessage(message) {
|
|||||||
|
|
||||||
// 获取消息气泡样式类
|
// 获取消息气泡样式类
|
||||||
function getBubbleClass(message) {
|
function getBubbleClass(message) {
|
||||||
|
// 图片消息不需要气泡背景
|
||||||
|
if (message.type === "TIMImageElem") {
|
||||||
|
return "image-bubble";
|
||||||
|
}
|
||||||
|
|
||||||
if (message.type === "TIMCustomElem") {
|
if (message.type === "TIMCustomElem") {
|
||||||
return message.flow === "out" ? "user-bubble" : "doctor-bubble-blue";
|
return message.flow === "out" ? "user-bubble" : "doctor-bubble-blue";
|
||||||
}
|
}
|
||||||
@ -279,10 +284,9 @@ const initTIMCallbacks = async () => {
|
|||||||
if (!existingMessage) {
|
if (!existingMessage) {
|
||||||
messageList.value.push(message);
|
messageList.value.push(message);
|
||||||
console.log("✓ 添加消息到列表,当前消息数量:", messageList.value.length);
|
console.log("✓ 添加消息到列表,当前消息数量:", messageList.value.length);
|
||||||
|
// 立即滚动到底部,不使用延迟
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
setTimeout(() => {
|
scrollToBottom(true);
|
||||||
scrollToBottom();
|
|
||||||
}, 100);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -473,13 +477,24 @@ const playVoice = (message) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 滚动到底部
|
// 滚动到底部
|
||||||
const scrollToBottom = () => {
|
const scrollToBottom = (immediate = false) => {
|
||||||
if (messageList.value.length > 0) {
|
if (messageList.value.length > 0) {
|
||||||
const lastMessage = messageList.value[messageList.value.length - 1];
|
const lastMessage = messageList.value[messageList.value.length - 1];
|
||||||
scrollIntoView.value = ``;
|
const targetId = `msg-${lastMessage.ID}`;
|
||||||
|
|
||||||
|
if (immediate) {
|
||||||
|
// 立即滚动:先清空再设置,触发滚动
|
||||||
|
scrollIntoView.value = '';
|
||||||
|
nextTick(() => {
|
||||||
|
scrollIntoView.value = targetId;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 正常滚动,使用短延迟确保DOM更新
|
||||||
|
scrollIntoView.value = '';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
scrollIntoView.value = `msg-${lastMessage.ID}`;
|
scrollIntoView.value = targetId;
|
||||||
}, 300);
|
}, 50);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -122,20 +122,15 @@ const initIM = async () => {
|
|||||||
// 加载会话列表
|
// 加载会话列表
|
||||||
const loadConversationList = async () => {
|
const loadConversationList = async () => {
|
||||||
if (loading.value) return;
|
if (loading.value) return;
|
||||||
|
// loading.value = true;
|
||||||
loading.value = true;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log("开始加载群聊列表");
|
console.log("开始加载群聊列表");
|
||||||
|
|
||||||
// 检查 globalTimChatManager 是否存在
|
|
||||||
if (!globalTimChatManager || !globalTimChatManager.getGroupList) {
|
if (!globalTimChatManager || !globalTimChatManager.getGroupList) {
|
||||||
throw new Error("IM管理器未初始化");
|
throw new Error("IM管理器未初始化");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 直接调用getGroupList,它会自动等待SDK就绪
|
// 直接调用getGroupList,它会自动等待SDK就绪
|
||||||
const result = await globalTimChatManager.getGroupList();
|
const result = await globalTimChatManager.getGroupList();
|
||||||
|
|
||||||
if (result && result.success && result.groupList) {
|
if (result && result.success && result.groupList) {
|
||||||
conversationList.value = result.groupList
|
conversationList.value = result.groupList
|
||||||
.map((group) => ({
|
.map((group) => ({
|
||||||
@ -220,25 +215,31 @@ const extractMessagePreview = (message) => {
|
|||||||
return "暂无消息";
|
return "暂无消息";
|
||||||
};
|
};
|
||||||
|
|
||||||
// 设置消息监听,实时更新列表
|
// 设置会话列表监听,实时更新列表
|
||||||
const setupMessageListener = () => {
|
const setupConversationListener = () => {
|
||||||
if (!globalTimChatManager) return;
|
if (!globalTimChatManager) return;
|
||||||
|
|
||||||
globalTimChatManager.setCallback("onMessageReceived", (message) => {
|
// 监听会话列表更新事件
|
||||||
console.log("消息列表页面收到新消息:", message);
|
globalTimChatManager.setCallback("onConversationListUpdated", (eventData) => {
|
||||||
|
console.log("会话列表更新事件:", eventData);
|
||||||
|
|
||||||
// 找到对应的会话并更新
|
// 如果是新消息导致的会话更新
|
||||||
const conversationID = message.conversationID;
|
if (eventData.reason === "NEW_MESSAGE_RECEIVED_IN_CURRENT_CONVERSATION" ||
|
||||||
|
eventData.reason === "NEW_MESSAGE_RECEIVED") {
|
||||||
|
const conversation = eventData.conversation;
|
||||||
|
if (!conversation) return;
|
||||||
|
|
||||||
|
const conversationID = conversation.conversationID;
|
||||||
const conversationIndex = conversationList.value.findIndex(
|
const conversationIndex = conversationList.value.findIndex(
|
||||||
(conv) => conv.conversationID === conversationID
|
(conv) => conv.conversationID === conversationID
|
||||||
);
|
);
|
||||||
|
|
||||||
if (conversationIndex !== -1) {
|
if (conversationIndex !== -1) {
|
||||||
// 更新现有会话
|
// 更新现有会话
|
||||||
const conversation = conversationList.value[conversationIndex];
|
const existingConversation = conversationList.value[conversationIndex];
|
||||||
conversation.lastMessage = extractMessagePreview(message);
|
existingConversation.lastMessage = conversation.lastMessage || "暂无消息";
|
||||||
conversation.lastMessageTime = message.lastTime || Date.now();
|
existingConversation.lastMessageTime = conversation.lastMessageTime || Date.now();
|
||||||
conversation.unreadCount = (conversation.unreadCount || 0) + 1;
|
existingConversation.unreadCount = conversation.unreadCount || 0;
|
||||||
|
|
||||||
// 将该会话移到顶部
|
// 将该会话移到顶部
|
||||||
const [updatedConversation] = conversationList.value.splice(
|
const [updatedConversation] = conversationList.value.splice(
|
||||||
@ -247,7 +248,39 @@ const setupMessageListener = () => {
|
|||||||
);
|
);
|
||||||
conversationList.value.unshift(updatedConversation);
|
conversationList.value.unshift(updatedConversation);
|
||||||
|
|
||||||
console.log("已更新会话:", conversation.name);
|
console.log("已更新会话:", existingConversation.name);
|
||||||
|
} else {
|
||||||
|
// 新会话,添加到列表顶部
|
||||||
|
conversationList.value.unshift({
|
||||||
|
conversationID: conversationID,
|
||||||
|
groupID: conversation.groupID || conversationID.replace("GROUP", ""),
|
||||||
|
name: conversation.name || "问诊群聊",
|
||||||
|
avatar: conversation.avatar || "/static/default-avatar.png",
|
||||||
|
lastMessage: conversation.lastMessage || "暂无消息",
|
||||||
|
lastMessageTime: conversation.lastMessageTime || Date.now(),
|
||||||
|
unreadCount: conversation.unreadCount || 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("已添加新会话");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听消息接收事件(用于更新未读数)
|
||||||
|
globalTimChatManager.setCallback("onMessageReceived", (message) => {
|
||||||
|
console.log("消息列表页面收到新消息:", message);
|
||||||
|
|
||||||
|
// 找到对应的会话并更新未读数
|
||||||
|
const conversationID = message.conversationID;
|
||||||
|
const conversationIndex = conversationList.value.findIndex(
|
||||||
|
(conv) => conv.conversationID === conversationID
|
||||||
|
);
|
||||||
|
|
||||||
|
if (conversationIndex !== -1) {
|
||||||
|
const conversation = conversationList.value[conversationIndex];
|
||||||
|
// 只更新未读数,其他信息由 onConversationListUpdated 事件处理
|
||||||
|
conversation.unreadCount = (conversation.unreadCount || 0) + 1;
|
||||||
|
console.log("已更新会话未读数:", conversation.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -341,11 +374,11 @@ onShow(async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 先设置消息监听
|
// 先加载初始会话列表
|
||||||
setupMessageListener();
|
|
||||||
|
|
||||||
// 加载消息列表
|
|
||||||
await loadConversationList();
|
await loadConversationList();
|
||||||
|
|
||||||
|
// 再设置监听器,后续通过事件更新列表
|
||||||
|
setupConversationListener();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("页面初始化失败:", error);
|
console.error("页面初始化失败:", error);
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
@ -359,6 +392,7 @@ onShow(async () => {
|
|||||||
onHide(() => {
|
onHide(() => {
|
||||||
// 移除消息监听
|
// 移除消息监听
|
||||||
if (globalTimChatManager) {
|
if (globalTimChatManager) {
|
||||||
|
globalTimChatManager.setCallback("onConversationListUpdated", null);
|
||||||
globalTimChatManager.setCallback("onMessageReceived", null);
|
globalTimChatManager.setCallback("onMessageReceived", null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
BIN
static/icon/changyongyu.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
static/icon/fuzhenyuyue.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
static/icon/icon-chinese-rx.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
static/icon/icon-western-rx.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
static/icon/jieshuzixun.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
static/icon/kaichufang.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/icon/kaiyizhu.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
static/icon/kaizhongyao.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/icon/paizhao.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
static/icon/quxiaobingtuikuan.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
static/icon/xuanjiaowenzhang.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
static/icon/zhaopian.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
static/icon/zhenliaoyijian.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
@ -39,7 +39,7 @@ export default defineStore("accountStore", () => {
|
|||||||
}
|
}
|
||||||
account.value = res.data;
|
account.value = res.data;
|
||||||
openid.value = res.data.openid;
|
openid.value = res.data.openid;
|
||||||
await getDoctorInfo(openid.value);
|
|
||||||
|
|
||||||
// 登录成功后初始化腾讯IM
|
// 登录成功后初始化腾讯IM
|
||||||
try {
|
try {
|
||||||
@ -51,7 +51,7 @@ export default defineStore("accountStore", () => {
|
|||||||
console.error('腾讯IM初始化失败:', imError);
|
console.error('腾讯IM初始化失败:', imError);
|
||||||
// IM初始化失败不影响登录流程
|
// IM初始化失败不影响登录流程
|
||||||
}
|
}
|
||||||
|
await getDoctorInfo(openid.value);
|
||||||
return res.data
|
return res.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -486,6 +486,8 @@ export const sendCustomMessage = async (messageData, timChatManager, validateBef
|
|||||||
* @param {function} onSuccess - 成功回调
|
* @param {function} onSuccess - 成功回调
|
||||||
*/
|
*/
|
||||||
export const sendMessage = async (messageType, data, timChatManager, validateBeforeSend, onSuccess, cloudCustomData) => {
|
export const sendMessage = async (messageType, data, timChatManager, validateBeforeSend, onSuccess, cloudCustomData) => {
|
||||||
|
console.log('chat-utils sendMessage 被调用:', { messageType, data });
|
||||||
|
|
||||||
if (!validateBeforeSend()) {
|
if (!validateBeforeSend()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -497,7 +499,9 @@ export const sendMessage = async (messageType, data, timChatManager, validateBef
|
|||||||
result = await timChatManager.sendTextMessage(data, cloudCustomData);
|
result = await timChatManager.sendTextMessage(data, cloudCustomData);
|
||||||
break;
|
break;
|
||||||
case 'image':
|
case 'image':
|
||||||
|
console.log('准备发送图片消息,数据:', data);
|
||||||
result = await timChatManager.sendImageMessage(data, cloudCustomData);
|
result = await timChatManager.sendImageMessage(data, cloudCustomData);
|
||||||
|
console.log('图片消息发送结果:', result);
|
||||||
break;
|
break;
|
||||||
case 'voice':
|
case 'voice':
|
||||||
result = await timChatManager.sendVoiceMessage(data.file, data.duration,cloudCustomData);
|
result = await timChatManager.sendVoiceMessage(data.file, data.duration,cloudCustomData);
|
||||||
@ -508,6 +512,7 @@ export const sendMessage = async (messageType, data, timChatManager, validateBef
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result && result.success) {
|
if (result && result.success) {
|
||||||
|
console.log('消息发送成功');
|
||||||
if (onSuccess) onSuccess();
|
if (onSuccess) onSuccess();
|
||||||
} else {
|
} else {
|
||||||
console.error('发送消息失败:', result?.error);
|
console.error('发送消息失败:', result?.error);
|
||||||
|
|||||||
@ -427,27 +427,18 @@ class TimChatManager {
|
|||||||
userID: this.currentUserID,
|
userID: this.currentUserID,
|
||||||
userSig: this.currentUserSig
|
userSig: this.currentUserSig
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
console.log('腾讯IM登录成功')
|
console.log('腾讯IM登录请求成功,等待SDK_READY事件...')
|
||||||
this.isLoggingIn = false
|
this.isLoggingIn = false
|
||||||
this.isLoggedIn = true
|
// 不在这里设置 isLoggedIn = true,等待 onSDKReady 事件
|
||||||
this.reconnectAttempts = 0
|
this.reconnectAttempts = 0
|
||||||
|
|
||||||
// 启动心跳检测
|
// 触发登录状态变化回调(登录中状态)
|
||||||
this.startHeartbeat()
|
|
||||||
|
|
||||||
// 启动登录状态检测
|
|
||||||
this.startLoginStatusCheck()
|
|
||||||
|
|
||||||
// 触发登录状态变化回调
|
|
||||||
this.triggerCallback('onLoginStatusChanged', {
|
this.triggerCallback('onLoginStatusChanged', {
|
||||||
isLoggedIn: true,
|
isLoggedIn: false,
|
||||||
userID: this.currentUserID,
|
userID: this.currentUserID,
|
||||||
reason: 'LOGIN_SUCCESS'
|
reason: 'LOGIN_REQUESTED',
|
||||||
|
message: '登录请求成功,等待SDK就绪...'
|
||||||
})
|
})
|
||||||
|
|
||||||
// 获取会话列表(确保连接正常)
|
|
||||||
this.getConversationList()
|
|
||||||
|
|
||||||
resolve()
|
resolve()
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error('腾讯IM登录失败:', error)
|
console.error('腾讯IM登录失败:', error)
|
||||||
@ -691,7 +682,6 @@ class TimChatManager {
|
|||||||
})
|
})
|
||||||
this.startLoginStatusCheck()
|
this.startLoginStatusCheck()
|
||||||
this.startHeartbeat() // 启动心跳检测
|
this.startHeartbeat() // 启动心跳检测
|
||||||
this.getConversationList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SDK Not Ready 事件
|
// SDK Not Ready 事件
|
||||||
@ -712,11 +702,8 @@ class TimChatManager {
|
|||||||
event.data.forEach(message => {
|
event.data.forEach(message => {
|
||||||
const existingMessage = this.messageList.find(msg => msg.ID === message.ID)
|
const existingMessage = this.messageList.find(msg => msg.ID === message.ID)
|
||||||
if (existingMessage) return
|
if (existingMessage) return
|
||||||
|
|
||||||
if (!this.filterMessage(message)) return
|
if (!this.filterMessage(message)) return
|
||||||
|
|
||||||
const convertedMessage = this.convertMessageFormat(message)
|
const convertedMessage = this.convertMessageFormat(message)
|
||||||
// 确保使用消息本身的conversationID,而不是当前会话ID
|
|
||||||
if (!convertedMessage.conversationID) {
|
if (!convertedMessage.conversationID) {
|
||||||
convertedMessage.conversationID = message.conversationID
|
convertedMessage.conversationID = message.conversationID
|
||||||
}
|
}
|
||||||
@ -731,30 +718,22 @@ class TimChatManager {
|
|||||||
messageType: convertedMessage.type,
|
messageType: convertedMessage.type,
|
||||||
from: convertedMessage.from
|
from: convertedMessage.from
|
||||||
})
|
})
|
||||||
console.log(event)
|
|
||||||
|
|
||||||
// 缓存功能已移除
|
|
||||||
|
|
||||||
// 判断是否为当前会话的消息(必须有currentConversationID且匹配才显示)
|
// 判断是否为当前会话的消息(必须有currentConversationID且匹配才显示)
|
||||||
const isCurrentConversation = this.currentConversationID &&
|
const isCurrentConversation = this.currentConversationID &&
|
||||||
messageConversationID === this.currentConversationID
|
messageConversationID === this.currentConversationID
|
||||||
|
|
||||||
console.log('消息会话匹配检查:', {
|
console.log('消息会话匹配检查:', {
|
||||||
isCurrentConversation,
|
isCurrentConversation,
|
||||||
hasCurrentConversationID: !!this.currentConversationID,
|
hasCurrentConversationID: !!this.currentConversationID,
|
||||||
conversationIDMatch: messageConversationID === this.currentConversationID
|
conversationIDMatch: messageConversationID === this.currentConversationID
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isCurrentConversation) {
|
if (isCurrentConversation) {
|
||||||
// 当前会话的消息,触发回调
|
// 当前会话的消息,触发回调
|
||||||
console.log('✓ 消息属于当前会话,触发显示')
|
console.log('✓ 消息属于当前会话,触发显示')
|
||||||
this.triggerCallback('onMessageReceived', convertedMessage)
|
this.triggerCallback('onMessageReceived', convertedMessage)
|
||||||
|
|
||||||
// 处理已读状态
|
// 处理已读状态
|
||||||
if (this.currentConversationID) {
|
if (this.currentConversationID) {
|
||||||
this.markConversationAsRead(this.currentConversationID)
|
this.markConversationAsRead(this.currentConversationID)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.triggerCallback('onConversationListUpdated', {
|
this.triggerCallback('onConversationListUpdated', {
|
||||||
reason: 'NEW_MESSAGE_RECEIVED_IN_CURRENT_CONVERSATION',
|
reason: 'NEW_MESSAGE_RECEIVED_IN_CURRENT_CONVERSATION',
|
||||||
conversation: {
|
conversation: {
|
||||||
@ -928,7 +907,6 @@ class TimChatManager {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动心跳检测(优化版:使用配置常量)
|
|
||||||
startHeartbeat() {
|
startHeartbeat() {
|
||||||
this.stopHeartbeat()
|
this.stopHeartbeat()
|
||||||
|
|
||||||
@ -952,14 +930,26 @@ class TimChatManager {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确保方法存在
|
||||||
|
if (typeof this.tim.getConversationList !== 'function') {
|
||||||
|
console.log('⏸ 心跳检测:SDK方法不可用,跳过检测')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.tim.getConversationList()
|
this.tim.getConversationList()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (this.heartbeatFailCount > 0) {
|
if (this.heartbeatFailCount > 0) {
|
||||||
console.log(`💚 心跳恢复正常(之前失败${this.heartbeatFailCount}次)`)
|
console.log(`<EFBFBD> 心跳恢复正常(之前失败${this.heartbeatFailCount}次)`)
|
||||||
}
|
}
|
||||||
this.heartbeatFailCount = 0 // 重置失败计数
|
this.heartbeatFailCount = 0 // 重置失败计数
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
// 如果是SDK未就绪错误,不计入失败次数(这是临时状态)
|
||||||
|
if (error && error.message && error.message.includes('sdk not ready')) {
|
||||||
|
console.log('⏸ 心跳检测:SDK未就绪,跳过本次检测')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.heartbeatFailCount++
|
this.heartbeatFailCount++
|
||||||
console.error(`💔 心跳失败 (${this.heartbeatFailCount}/${MAX_HEARTBEAT_FAIL}):`, error.message)
|
console.error(`💔 心跳失败 (${this.heartbeatFailCount}/${MAX_HEARTBEAT_FAIL}):`, error.message)
|
||||||
|
|
||||||
@ -1009,14 +999,6 @@ class TimChatManager {
|
|||||||
setTimeout(checkSDKReady, 500)
|
setTimeout(checkSDKReady, 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tim.getConversationList({ withGroupInfo: 1, withAllFields: 1 }).then(response => {
|
|
||||||
if (this.conversationID) {
|
|
||||||
this.enterConversation(this.conversationID)
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('获取会话列表失败:', error)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取群聊列表
|
// 获取群聊列表
|
||||||
@ -1032,18 +1014,21 @@ class TimChatManager {
|
|||||||
let waitTime = 0
|
let waitTime = 0
|
||||||
const maxWaitTime = 30000 // 最多等待30秒
|
const maxWaitTime = 30000 // 最多等待30秒
|
||||||
const checkInterval = 1000 // 每秒检查一次
|
const checkInterval = 1000 // 每秒检查一次
|
||||||
|
let timeoutHandle = null
|
||||||
|
|
||||||
const checkSDKReady = () => {
|
const checkSDKReady = () => {
|
||||||
if (this.isLoggedIn) {
|
if (this.isLoggedIn) {
|
||||||
console.log('SDK已ready,开始获取群聊列表')
|
console.log('SDK已ready,开始获取群聊列表')
|
||||||
|
if (timeoutHandle) clearTimeout(timeoutHandle)
|
||||||
this.getGroupListInternal().then(resolve).catch(reject)
|
this.getGroupListInternal().then(resolve).catch(reject)
|
||||||
} else if (waitTime >= maxWaitTime) {
|
} else if (waitTime >= maxWaitTime) {
|
||||||
console.error('等待SDK就绪超时')
|
console.error('等待SDK就绪超时')
|
||||||
|
if (timeoutHandle) clearTimeout(timeoutHandle)
|
||||||
reject(new Error('SDK初始化超时,请检查网络连接'))
|
reject(new Error('SDK初始化超时,请检查网络连接'))
|
||||||
} else {
|
} else {
|
||||||
waitTime += checkInterval
|
waitTime += checkInterval
|
||||||
console.log(`等待SDK就绪... (${Math.floor(waitTime / 1000)}/${Math.floor(maxWaitTime / 1000)}秒)`)
|
console.log(`等待SDK就绪... (${Math.floor(waitTime / 1000)}/${Math.floor(maxWaitTime / 1000)}秒)`)
|
||||||
setTimeout(checkSDKReady, checkInterval)
|
timeoutHandle = setTimeout(checkSDKReady, checkInterval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1060,57 +1045,47 @@ class TimChatManager {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
console.log('开始获取群聊列表')
|
console.log('开始获取群聊列表')
|
||||||
|
|
||||||
// 确保SDK已就绪再调用getConversationList
|
// 直接调用,SDK就绪检查已在getGroupList()中完成
|
||||||
const ensureSDKReady = () => {
|
this.tim.getConversationList()
|
||||||
if (!this.isLoggedIn) {
|
.then(async (conversationResponse) => {
|
||||||
console.log('SDK未就绪,等待中...')
|
console.log('获取会话列表成功')
|
||||||
setTimeout(ensureSDKReady, 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tim.getConversationList().then(async (conversationResponse) => {
|
|
||||||
console.clear()
|
|
||||||
console.log('获取会话列表成功:', conversationResponse)
|
|
||||||
const groupConversations = conversationResponse.data.conversationList.filter(conversation => {
|
const groupConversations = conversationResponse.data.conversationList.filter(conversation => {
|
||||||
return conversation.conversationID && conversation.conversationID.startsWith('GROUP')
|
return conversation.conversationID && conversation.conversationID.startsWith('GROUP')
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('群聊会话列表:', groupConversations)
|
console.log('群聊会话列表数量:', groupConversations.length)
|
||||||
|
|
||||||
|
// 先获取一次群组列表,避免在循环中重复调用
|
||||||
|
let allGroups = []
|
||||||
|
try {
|
||||||
|
const groupListResponse = await this.tim.getGroupList()
|
||||||
|
allGroups = groupListResponse.data.groupList || []
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取群组列表失败:', error)
|
||||||
|
}
|
||||||
|
|
||||||
const groupsWithInfo = await Promise.all(
|
const groupsWithInfo = await Promise.all(
|
||||||
groupConversations.map(async (conversation) => {
|
groupConversations.map(async (conversation) => {
|
||||||
const groupName = typeof conversation.groupProfile.name === 'string' ? conversation.groupProfile.name : conversation.groupProfile.name;
|
try {
|
||||||
|
const groupName = conversation.groupProfile?.name || ''
|
||||||
const [doctorId, patientName] = groupName.split('|')
|
const [doctorId, patientName] = groupName.split('|')
|
||||||
try {
|
|
||||||
const groupID = conversation.conversationID.replace('GROUP', '')
|
const groupID = conversation.conversationID.replace('GROUP', '')
|
||||||
let groupInfo = {
|
|
||||||
groupID: groupID,
|
|
||||||
name: '问诊群聊',
|
|
||||||
avatar: '/static/home/doctor.png',
|
|
||||||
memberCount: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
// 从已获取的群组列表中查找
|
||||||
const groupListResponse = await this.tim.getGroupList()
|
const group = allGroups.find(g => g.groupID === groupID)
|
||||||
const group = groupListResponse.data.groupList.find(g => g.groupID === groupID)
|
const groupInfo = {
|
||||||
if (group) {
|
groupID: groupID,
|
||||||
groupInfo = {
|
name: group?.name || '问诊群聊',
|
||||||
...groupInfo,
|
avatar: '/static/home/avatar.svg',
|
||||||
name: group.name || '问诊群聊',
|
memberCount: group?.memberCount || 0
|
||||||
memberCount: group.memberCount || 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`获取群组 ${groupID} 信息失败:`, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastMessage = conversation.lastMessage
|
const lastMessage = conversation.lastMessage
|
||||||
let lastMessageText = ''
|
let lastMessageText = '暂无消息'
|
||||||
let lastMessageTime = Date.now()
|
let lastMessageTime = Date.now()
|
||||||
|
|
||||||
if (lastMessage) {
|
if (lastMessage) {
|
||||||
console.log(`群聊 ${groupID} 最后一条消息:`, lastMessage)
|
|
||||||
|
|
||||||
if (lastMessage.type === 'TIMTextElem') {
|
if (lastMessage.type === 'TIMTextElem') {
|
||||||
lastMessageText = lastMessage.payload.text
|
lastMessageText = lastMessage.payload.text
|
||||||
} else if (lastMessage.type === 'TIMImageElem') {
|
} else if (lastMessage.type === 'TIMImageElem') {
|
||||||
@ -1118,19 +1093,12 @@ class TimChatManager {
|
|||||||
} else if (lastMessage.type === 'TIMSoundElem') {
|
} else if (lastMessage.type === 'TIMSoundElem') {
|
||||||
lastMessageText = '[语音]'
|
lastMessageText = '[语音]'
|
||||||
} else if (lastMessage.type === 'TIMCustomElem') {
|
} else if (lastMessage.type === 'TIMCustomElem') {
|
||||||
lastMessageText = lastMessage.payload.data ? lastMessage.payload.data : '[自定义消息]'
|
lastMessageText = lastMessage.payload.data || '[自定义消息]'
|
||||||
} else {
|
} else {
|
||||||
lastMessageText = '[未知消息类型]'
|
lastMessageText = '[未知消息类型]'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastMessage.lastTime) {
|
lastMessageTime = (lastMessage.lastTime || lastMessage.time || 0) * 1000
|
||||||
lastMessageTime = lastMessage.lastTime * 1000
|
|
||||||
} else if (lastMessage.time) {
|
|
||||||
lastMessageTime = lastMessage.time * 1000
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log(`群聊 ${groupID} 没有最后一条消息`)
|
|
||||||
lastMessageText = '暂无消息'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -1147,9 +1115,9 @@ class TimChatManager {
|
|||||||
console.error(`处理群聊会话失败:`, error)
|
console.error(`处理群聊会话失败:`, error)
|
||||||
return {
|
return {
|
||||||
groupID: conversation.conversationID,
|
groupID: conversation.conversationID,
|
||||||
name: conversation.groupProfile.name,
|
name: conversation.groupProfile?.name || '问诊群聊',
|
||||||
doctorId,
|
doctorId: '',
|
||||||
patientName,
|
patientName: '',
|
||||||
avatar: '/static/home/avatar.svg',
|
avatar: '/static/home/avatar.svg',
|
||||||
lastMessage: '获取失败',
|
lastMessage: '获取失败',
|
||||||
lastMessageTime: Date.now(),
|
lastMessageTime: Date.now(),
|
||||||
@ -1160,24 +1128,21 @@ class TimChatManager {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log('处理后的群聊列表:', groupsWithInfo)
|
console.log('处理后的群聊列表数量:', groupsWithInfo.length)
|
||||||
resolve({
|
resolve({
|
||||||
success: true,
|
success: true,
|
||||||
groupList: groupsWithInfo,
|
groupList: groupsWithInfo,
|
||||||
totalCount: groupsWithInfo.length,
|
totalCount: groupsWithInfo.length,
|
||||||
data: conversationResponse.data
|
data: conversationResponse.data
|
||||||
})
|
})
|
||||||
}).catch((imError) => {
|
})
|
||||||
|
.catch((imError) => {
|
||||||
console.error('获取会话列表失败:', imError)
|
console.error('获取会话列表失败:', imError)
|
||||||
reject({
|
reject({
|
||||||
success: false,
|
success: false,
|
||||||
error: imError
|
error: imError
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
// 开始检查SDK就绪状态
|
|
||||||
ensureSDKReady()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1564,7 +1529,7 @@ class TimChatManager {
|
|||||||
payload: this.convertDBPayloadToIMPayload(msgType, msgBody.MsgContent),
|
payload: this.convertDBPayloadToIMPayload(msgType, msgBody.MsgContent),
|
||||||
lastTime: lastTime,
|
lastTime: lastTime,
|
||||||
status: 'success',
|
status: 'success',
|
||||||
avatar: flow === 'in' ? '/static/home/doctor.png' : '/static/center/user-avatar.png',
|
avatar: flow === 'in' ? '/static/home/avatar.svg' : '/static/center/user-avatar.png',
|
||||||
conversationID: this.currentConversationID,
|
conversationID: this.currentConversationID,
|
||||||
MsgSeq: dbMsg.MsgSeq, // 保留 MsgSeq 用于分页
|
MsgSeq: dbMsg.MsgSeq, // 保留 MsgSeq 用于分页
|
||||||
}
|
}
|
||||||
@ -2074,29 +2039,42 @@ class TimChatManager {
|
|||||||
|
|
||||||
if (!this.tim) {
|
if (!this.tim) {
|
||||||
this.triggerCallback('onError', 'IM未初始化')
|
this.triggerCallback('onError', 'IM未初始化')
|
||||||
return
|
return { success: false, error: 'IM未初始化' }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.conversation) {
|
// 检查登录状态
|
||||||
this.triggerCallback('onError', '群聊会话不存在')
|
if (!this.isLoggedIn) {
|
||||||
return { success: false, error: '群聊会话不存在' }
|
console.error('IM未登录,无法发送消息');
|
||||||
|
this.triggerCallback('onError', 'IM未登录,请稍后重试')
|
||||||
|
return { success: false, error: 'IM未登录' }
|
||||||
}
|
}
|
||||||
|
|
||||||
let groupID = null
|
// 优先使用 currentConversationID,如果没有则尝试从 conversation 获取
|
||||||
if (this.conversation.groupProfile && this.conversation.groupProfile.groupID) {
|
let conversationID = this.currentConversationID;
|
||||||
groupID = this.conversation.groupProfile.groupID
|
if (!conversationID && this.conversation) {
|
||||||
} else if (this.conversation.conversationID) {
|
conversationID = this.conversation.conversationID;
|
||||||
groupID = this.conversation.conversationID.replace('GROUP', '')
|
}
|
||||||
|
|
||||||
|
if (!conversationID) {
|
||||||
|
console.error('会话ID不存在');
|
||||||
|
this.triggerCallback('onError', '会话不存在,请重新进入聊天')
|
||||||
|
return { success: false, error: '会话ID不存在' }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从 conversationID 提取 groupID
|
||||||
|
let groupID = null;
|
||||||
|
if (conversationID.startsWith('GROUP')) {
|
||||||
|
groupID = conversationID.replace('GROUP', '');
|
||||||
|
} else if (this.conversation?.groupProfile?.groupID) {
|
||||||
|
groupID = this.conversation.groupProfile.groupID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!groupID) {
|
if (!groupID) {
|
||||||
|
console.error('无法获取群聊ID,conversationID:', conversationID);
|
||||||
this.triggerCallback('onError', '无法获取群聊ID')
|
this.triggerCallback('onError', '无法获取群聊ID')
|
||||||
return { success: false, error: '无法获取群聊ID' }
|
return { success: false, error: '无法获取群聊ID' }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保使用当前会话的conversationID
|
|
||||||
const conversationID = this.conversation.conversationID || this.currentConversationID
|
|
||||||
|
|
||||||
const localMessage = {
|
const localMessage = {
|
||||||
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
||||||
flow: 'out',
|
flow: 'out',
|
||||||
@ -2127,39 +2105,75 @@ class TimChatManager {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('文本消息发送失败:', error)
|
console.error('文本消息发送失败:', error)
|
||||||
localMessage.status = 'failed'
|
localMessage.status = 'failed'
|
||||||
|
|
||||||
|
// 如果是因为未登录导致的失败,尝试重连
|
||||||
|
if (error.message && (error.message.includes('not login') || error.message.includes('sdk not ready'))) {
|
||||||
|
console.log('检测到未登录错误,尝试重连...');
|
||||||
|
this.isLoggedIn = false;
|
||||||
|
this.ensureIMConnection();
|
||||||
|
}
|
||||||
|
|
||||||
return { success: false, error }
|
return { success: false, error }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送图片消息
|
// 发送图片消息
|
||||||
async sendImageMessage(imageFile) {
|
async sendImageMessage(imageFile) {
|
||||||
|
console.log('sendImageMessage 被调用,参数:', imageFile);
|
||||||
|
|
||||||
if (!this.tim) {
|
if (!this.tim) {
|
||||||
this.triggerCallback('onError', 'IM未初始化')
|
this.triggerCallback('onError', 'IM未初始化')
|
||||||
return
|
return { success: false, error: 'IM未初始化' }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.conversation) {
|
// 检查登录状态
|
||||||
this.triggerCallback('onError', '群聊会话不存在')
|
if (!this.isLoggedIn) {
|
||||||
return { success: false, error: '群聊会话不存在' }
|
console.error('IM未登录,无法发送消息');
|
||||||
|
this.triggerCallback('onError', 'IM未登录,请稍后重试')
|
||||||
|
return { success: false, error: 'IM未登录' }
|
||||||
}
|
}
|
||||||
|
|
||||||
let groupID = null
|
// 优先使用 currentConversationID,如果没有则尝试从 conversation 获取
|
||||||
if (this.conversation.groupProfile && this.conversation.groupProfile.groupID) {
|
let conversationID = this.currentConversationID;
|
||||||
groupID = this.conversation.groupProfile.groupID
|
if (!conversationID && this.conversation) {
|
||||||
} else if (this.conversation.conversationID) {
|
conversationID = this.conversation.conversationID;
|
||||||
groupID = this.conversation.conversationID.replace('GROUP', '')
|
}
|
||||||
|
|
||||||
|
if (!conversationID) {
|
||||||
|
console.error('会话ID不存在');
|
||||||
|
this.triggerCallback('onError', '会话不存在,请重新进入聊天')
|
||||||
|
return { success: false, error: '会话ID不存在' }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从 conversationID 提取 groupID
|
||||||
|
let groupID = null;
|
||||||
|
if (conversationID.startsWith('GROUP')) {
|
||||||
|
groupID = conversationID.replace('GROUP', '');
|
||||||
|
} else if (this.conversation?.groupProfile?.groupID) {
|
||||||
|
groupID = this.conversation.groupProfile.groupID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!groupID) {
|
if (!groupID) {
|
||||||
|
console.error('无法获取群聊ID,conversationID:', conversationID);
|
||||||
this.triggerCallback('onError', '无法获取群聊ID')
|
this.triggerCallback('onError', '无法获取群聊ID')
|
||||||
return { success: false, error: '无法获取群聊ID' }
|
return { success: false, error: '无法获取群聊ID' }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保使用当前会话的conversationID
|
console.log('发送图片消息,conversationID:', conversationID, 'groupID:', groupID);
|
||||||
const conversationID = this.conversation.conversationID || this.currentConversationID
|
|
||||||
|
// 处理文件对象 - 确保获取正确的文件
|
||||||
|
let actualFile = imageFile;
|
||||||
|
if (imageFile?.tempFiles?.length > 0) {
|
||||||
|
actualFile = imageFile.tempFiles[0];
|
||||||
|
console.log('从 tempFiles 中提取文件:', actualFile);
|
||||||
|
} else if (imageFile?.tempFilePath) {
|
||||||
|
// 如果已经是单个文件对象
|
||||||
|
actualFile = imageFile;
|
||||||
|
console.log('使用单个文件对象:', actualFile);
|
||||||
|
}
|
||||||
|
|
||||||
// 获取图片尺寸信息
|
// 获取图片尺寸信息
|
||||||
const imageInfo = await this.getImageInfo(imageFile);
|
const imageInfo = await this.getImageInfo(actualFile);
|
||||||
|
|
||||||
const localMessage = {
|
const localMessage = {
|
||||||
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
||||||
@ -2167,7 +2181,7 @@ class TimChatManager {
|
|||||||
type: 'TIMImageElem',
|
type: 'TIMImageElem',
|
||||||
payload: {
|
payload: {
|
||||||
imageInfoArray: [{
|
imageInfoArray: [{
|
||||||
url: this.getImageUrl(imageFile),
|
url: this.getImageUrl(actualFile),
|
||||||
width: imageInfo.width,
|
width: imageInfo.width,
|
||||||
height: imageInfo.height
|
height: imageInfo.height
|
||||||
}]
|
}]
|
||||||
@ -2186,19 +2200,33 @@ class TimChatManager {
|
|||||||
// 触发消息接收回调,让UI立即显示
|
// 触发消息接收回调,让UI立即显示
|
||||||
this.triggerCallback('onMessageReceived', localMessage)
|
this.triggerCallback('onMessageReceived', localMessage)
|
||||||
|
|
||||||
|
console.log('准备创建 TIM 图片消息,groupID:', groupID, 'file:', actualFile);
|
||||||
|
|
||||||
const message = this.tim.createImageMessage({
|
const message = this.tim.createImageMessage({
|
||||||
to: groupID,
|
to: groupID,
|
||||||
conversationType: TIM.TYPES.CONV_GROUP,
|
conversationType: TIM.TYPES.CONV_GROUP,
|
||||||
payload: { file: imageFile }
|
payload: { file: actualFile }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log('TIM 图片消息已创建:', message);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.tim.sendMessage(message)
|
console.log('开始发送图片消息...');
|
||||||
|
const sendResult = await this.tim.sendMessage(message);
|
||||||
|
console.log('图片消息发送成功:', sendResult);
|
||||||
localMessage.status = 'success'
|
localMessage.status = 'success'
|
||||||
return { success: true, message: localMessage }
|
return { success: true, message: localMessage }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('图片消息发送失败:', error)
|
console.error('图片消息发送失败:', error)
|
||||||
localMessage.status = 'failed'
|
localMessage.status = 'failed'
|
||||||
|
|
||||||
|
// 如果是因为未登录导致的失败,尝试重连
|
||||||
|
if (error.message && (error.message.includes('not login') || error.message.includes('sdk not ready'))) {
|
||||||
|
console.log('检测到未登录错误,尝试重连...');
|
||||||
|
this.isLoggedIn = false;
|
||||||
|
this.ensureIMConnection();
|
||||||
|
}
|
||||||
|
|
||||||
return { success: false, error }
|
return { success: false, error }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2207,29 +2235,42 @@ class TimChatManager {
|
|||||||
async sendVoiceMessage(voiceFile, duration) {
|
async sendVoiceMessage(voiceFile, duration) {
|
||||||
if (!this.tim) {
|
if (!this.tim) {
|
||||||
this.triggerCallback('onError', 'IM未初始化')
|
this.triggerCallback('onError', 'IM未初始化')
|
||||||
return
|
return { success: false, error: 'IM未初始化' }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.conversation) {
|
// 检查登录状态
|
||||||
this.triggerCallback('onError', '群聊会话不存在')
|
if (!this.isLoggedIn) {
|
||||||
return { success: false, error: '群聊会话不存在' }
|
console.error('IM未登录,无法发送消息');
|
||||||
|
this.triggerCallback('onError', 'IM未登录,请稍后重试')
|
||||||
|
return { success: false, error: 'IM未登录' }
|
||||||
}
|
}
|
||||||
|
|
||||||
let groupID = null
|
// 优先使用 currentConversationID,如果没有则尝试从 conversation 获取
|
||||||
if (this.conversation.groupProfile && this.conversation.groupProfile.groupID) {
|
let conversationID = this.currentConversationID;
|
||||||
groupID = this.conversation.groupProfile.groupID
|
if (!conversationID && this.conversation) {
|
||||||
} else if (this.conversation.conversationID) {
|
conversationID = this.conversation.conversationID;
|
||||||
groupID = this.conversation.conversationID.replace('GROUP', '')
|
}
|
||||||
|
|
||||||
|
if (!conversationID) {
|
||||||
|
console.error('会话ID不存在');
|
||||||
|
this.triggerCallback('onError', '会话不存在,请重新进入聊天')
|
||||||
|
return { success: false, error: '会话ID不存在' }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从 conversationID 提取 groupID
|
||||||
|
let groupID = null;
|
||||||
|
if (conversationID.startsWith('GROUP')) {
|
||||||
|
groupID = conversationID.replace('GROUP', '');
|
||||||
|
} else if (this.conversation?.groupProfile?.groupID) {
|
||||||
|
groupID = this.conversation.groupProfile.groupID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!groupID) {
|
if (!groupID) {
|
||||||
|
console.error('无法获取群聊ID,conversationID:', conversationID);
|
||||||
this.triggerCallback('onError', '无法获取群聊ID')
|
this.triggerCallback('onError', '无法获取群聊ID')
|
||||||
return { success: false, error: '无法获取群聊ID' }
|
return { success: false, error: '无法获取群聊ID' }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保使用当前会话的conversationID
|
|
||||||
const conversationID = this.conversation.conversationID || this.currentConversationID
|
|
||||||
|
|
||||||
const localMessage = {
|
const localMessage = {
|
||||||
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
||||||
flow: 'out',
|
flow: 'out',
|
||||||
@ -2262,6 +2303,14 @@ class TimChatManager {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('语音消息发送失败:', error)
|
console.error('语音消息发送失败:', error)
|
||||||
localMessage.status = 'failed'
|
localMessage.status = 'failed'
|
||||||
|
|
||||||
|
// 如果是因为未登录导致的失败,尝试重连
|
||||||
|
if (error.message && (error.message.includes('not login') || error.message.includes('sdk not ready'))) {
|
||||||
|
console.log('检测到未登录错误,尝试重连...');
|
||||||
|
this.isLoggedIn = false;
|
||||||
|
this.ensureIMConnection();
|
||||||
|
}
|
||||||
|
|
||||||
return { success: false, error }
|
return { success: false, error }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2270,29 +2319,42 @@ class TimChatManager {
|
|||||||
async sendCustomMessage(messageData) {
|
async sendCustomMessage(messageData) {
|
||||||
if (!this.tim) {
|
if (!this.tim) {
|
||||||
this.triggerCallback('onError', 'IM未初始化')
|
this.triggerCallback('onError', 'IM未初始化')
|
||||||
return
|
return { success: false, error: 'IM未初始化' }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.conversation) {
|
// 检查登录状态
|
||||||
this.triggerCallback('onError', '群聊会话不存在')
|
if (!this.isLoggedIn) {
|
||||||
return { success: false, error: '群聊会话不存在' }
|
console.error('IM未登录,无法发送消息');
|
||||||
|
this.triggerCallback('onError', 'IM未登录,请稍后重试')
|
||||||
|
return { success: false, error: 'IM未登录' }
|
||||||
}
|
}
|
||||||
|
|
||||||
let groupID = null
|
// 优先使用 currentConversationID,如果没有则尝试从 conversation 获取
|
||||||
if (this.conversation.groupProfile && this.conversation.groupProfile.groupID) {
|
let conversationID = this.currentConversationID;
|
||||||
groupID = this.conversation.groupProfile.groupID
|
if (!conversationID && this.conversation) {
|
||||||
} else if (this.conversation.conversationID) {
|
conversationID = this.conversation.conversationID;
|
||||||
groupID = this.conversation.conversationID.replace('GROUP', '')
|
}
|
||||||
|
|
||||||
|
if (!conversationID) {
|
||||||
|
console.error('会话ID不存在');
|
||||||
|
this.triggerCallback('onError', '会话不存在,请重新进入聊天')
|
||||||
|
return { success: false, error: '会话ID不存在' }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从 conversationID 提取 groupID
|
||||||
|
let groupID = null;
|
||||||
|
if (conversationID.startsWith('GROUP')) {
|
||||||
|
groupID = conversationID.replace('GROUP', '');
|
||||||
|
} else if (this.conversation?.groupProfile?.groupID) {
|
||||||
|
groupID = this.conversation.groupProfile.groupID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!groupID) {
|
if (!groupID) {
|
||||||
|
console.error('无法获取群聊ID,conversationID:', conversationID);
|
||||||
this.triggerCallback('onError', '无法获取群聊ID')
|
this.triggerCallback('onError', '无法获取群聊ID')
|
||||||
return { success: false, error: '无法获取群聊ID' }
|
return { success: false, error: '无法获取群聊ID' }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保使用当前会话的conversationID
|
|
||||||
const conversationID = this.conversation.conversationID || this.currentConversationID
|
|
||||||
|
|
||||||
const localMessage = {
|
const localMessage = {
|
||||||
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
||||||
flow: 'out',
|
flow: 'out',
|
||||||
@ -2330,6 +2392,14 @@ class TimChatManager {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('自定义消息发送失败:', error)
|
console.error('自定义消息发送失败:', error)
|
||||||
localMessage.status = 'failed'
|
localMessage.status = 'failed'
|
||||||
|
|
||||||
|
// 如果是因为未登录导致的失败,尝试重连
|
||||||
|
if (error.message && (error.message.includes('not login') || error.message.includes('sdk not ready'))) {
|
||||||
|
console.log('检测到未登录错误,尝试重连...');
|
||||||
|
this.isLoggedIn = false;
|
||||||
|
this.ensureIMConnection();
|
||||||
|
}
|
||||||
|
|
||||||
return { success: false, error }
|
return { success: false, error }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2364,7 +2434,7 @@ class TimChatManager {
|
|||||||
payload: timMessage.payload,
|
payload: timMessage.payload,
|
||||||
lastTime: lastTime,
|
lastTime: lastTime,
|
||||||
status: timMessage.status || 'success',
|
status: timMessage.status || 'success',
|
||||||
avatar: timMessage.flow === 'in' ? '/static/home/doctor.png' : '/static/center/user-avatar.png',
|
avatar: timMessage.flow === 'in' ? '/static/home/avatar.svg' : '/static/center/user-avatar.png',
|
||||||
// 优先使用消息本身的conversationID,确保消息归属正确的会话
|
// 优先使用消息本身的conversationID,确保消息归属正确的会话
|
||||||
conversationID: timMessage.conversationID
|
conversationID: timMessage.conversationID
|
||||||
}
|
}
|
||||||
@ -2408,12 +2478,19 @@ class TimChatManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getImageUrl(imageFile) {
|
getImageUrl(imageFile) {
|
||||||
|
// 处理 tempFiles 数组格式
|
||||||
if (imageFile?.tempFiles?.length > 0) {
|
if (imageFile?.tempFiles?.length > 0) {
|
||||||
return imageFile.tempFiles[0].tempFilePath
|
return imageFile.tempFiles[0].tempFilePath
|
||||||
}
|
}
|
||||||
|
// 处理单个文件对象
|
||||||
|
if (imageFile?.tempFilePath) {
|
||||||
|
return imageFile.tempFilePath
|
||||||
|
}
|
||||||
|
// 处理字符串路径
|
||||||
if (typeof imageFile === 'string') {
|
if (typeof imageFile === 'string') {
|
||||||
return imageFile
|
return imageFile
|
||||||
}
|
}
|
||||||
|
console.warn('无法获取图片URL,使用默认图片:', imageFile);
|
||||||
return '/static/home/photo.png'
|
return '/static/home/photo.png'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2422,17 +2499,22 @@ class TimChatManager {
|
|||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
let imagePath = '';
|
let imagePath = '';
|
||||||
|
|
||||||
// 获取图片路径
|
// 获取图片路径 - 处理多种格式
|
||||||
if (imageFile?.tempFiles?.length > 0) {
|
if (imageFile?.tempFiles?.length > 0) {
|
||||||
imagePath = imageFile.tempFiles[0].tempFilePath;
|
imagePath = imageFile.tempFiles[0].tempFilePath;
|
||||||
|
} else if (imageFile?.tempFilePath) {
|
||||||
|
imagePath = imageFile.tempFilePath;
|
||||||
} else if (typeof imageFile === 'string') {
|
} else if (typeof imageFile === 'string') {
|
||||||
imagePath = imageFile;
|
imagePath = imageFile;
|
||||||
} else {
|
} else {
|
||||||
|
console.warn('无法获取图片路径,使用默认尺寸:', imageFile);
|
||||||
// 默认尺寸
|
// 默认尺寸
|
||||||
resolve({ width: 400, height: 300 });
|
resolve({ width: 400, height: 300 });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('获取图片信息,路径:', imagePath);
|
||||||
|
|
||||||
// 使用uni.getImageInfo获取图片尺寸
|
// 使用uni.getImageInfo获取图片尺寸
|
||||||
uni.getImageInfo({
|
uni.getImageInfo({
|
||||||
src: imagePath,
|
src: imagePath,
|
||||||
|
|||||||