会话间开发

This commit is contained in:
wangdongbo 2026-01-22 16:35:05 +08:00
parent cd4693bad4
commit 16c7d2b261
22 changed files with 429 additions and 267 deletions

18
App.vue
View File

@ -15,15 +15,15 @@ export default {
onHide: function () {
console.log("App Hide");
// 退退IM
try {
if (globalTimChatManager && globalTimChatManager.tim) {
console.log('小程序退出开始退出腾讯IM');
globalTimChatManager.destroy();
console.log('腾讯IM退出成功');
}
} catch (error) {
console.error('退出腾讯IM失败:', error);
}
// try {
// if (globalTimChatManager && globalTimChatManager.tim) {
// console.log('退退IM');
// globalTimChatManager.destroy();
// console.log('IM退');
// }
// } catch (error) {
// console.error('退IM:', error);
// }
},
};
</script>

View File

@ -120,7 +120,6 @@ $primary-color: #0877F1;
}
.system-message {
// background-color: #f0f0f0;
border-radius: 16rpx;
padding: 12rpx;
margin: 20rpx 24rpx;
@ -141,7 +140,7 @@ $primary-color: #0877F1;
}
.message-item {
margin-bottom: 16rpx;
margin-bottom: 30rpx;
}
.message-content {
@ -162,14 +161,14 @@ $primary-color: #0877F1;
width: 60rpx;
height: 60rpx;
border-radius: 50%;
margin-top: 28rpx; // 向下移动与气泡箭头对齐
margin-top: 10rpx;
}
.user-msg-avatar {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
margin-top: 28rpx; // 向下移动与气泡箭头对齐
margin-top: 10rpx;
}
// 消息气泡容器
@ -1040,6 +1039,19 @@ $primary-color: #0877F1;
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 {
margin-right: 8rpx;
}

View File

@ -146,8 +146,9 @@ const sendTextMessage = async () => {
};
//
const sendImageMessage = async (imageUrl) => {
await sendMessage('image', imageUrl);
const sendImageMessage = async (imageFile) => {
console.log('chat-input sendImageMessage 被调用,参数:', imageFile);
await sendMessage('image', imageFile);
};
//
@ -164,6 +165,7 @@ const sendMessage = async (messageType, data) => {
() => validateBeforeSend(false, false, props.timChatManager),
() => {
showMorePanel.value = false;
//
emit('messageSent');
},
cloudCustomData.value
@ -197,7 +199,13 @@ const toggleMorePanel = () => {
//
const showImagePicker = () => {
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) => {
console.error('选择图片失败:', err);
if (!err.errMsg?.includes('permission') && !err.errMsg?.includes('auth') && !err.errMsg?.includes('拒绝') && !err.errMsg?.includes('未授权')) {
@ -213,7 +221,13 @@ const showImagePicker = () => {
const takePhoto = () => {
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) => {
console.error('拍照失败:', err);
if (!err.errMsg?.includes('permission') && !err.errMsg?.includes('auth') && !err.errMsg?.includes('拒绝') && !err.errMsg?.includes('未授权')) {
@ -315,10 +329,10 @@ const sendSurveyMessage = async () => {
const morePanelButtons = [
{ text: '照片', icon: '/static/home/photo.png', action: showImagePicker },
{ text: '拍摄', icon: '/static/home/video.png', action: takePhoto },
// { text: '', icon: '/static/home/doctor.png', action: sendSymptomMessage },
// { text: '', icon: '/static/home/doctor.png', action: sendPrescriptionMessage },
// { text: '', icon: '/static/home/doctor.png', action: sendRefillMessage },
// { text: '', icon: '/static/home/doctor.png', action: sendSurveyMessage }
// { text: '', icon: '/static/home/avatar.svg', action: sendSymptomMessage },
// { text: '', icon: '/static/home/avatar.svg', action: sendPrescriptionMessage },
// { text: '', icon: '/static/home/avatar.svg', action: sendRefillMessage },
// { text: '', icon: '/static/home/avatar.svg', action: sendSurveyMessage }
];
function handleInputFocus() {

View File

@ -45,7 +45,7 @@ const props = defineProps({
})
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() {
if (!hasFilledDescription.value) {

View File

@ -50,19 +50,19 @@
<!-- 消息内容 -->
<view v-else class="message-content">
<!-- 头像 -->
<!-- 医生头像左侧 -->
<image
v-if="message.flow === 'in'"
class="doctor-msg-avatar"
:src="chatMember[message.from]?.avatar"
:src="chatMember[message.from]?.avatar || '/static/default-avatar.png'"
mode="aspectFill"
/>
<!-- 用户头像右侧 -->
<!-- 患者头像右侧 -->
<image
v-if="message.flow === 'out'"
class="user-msg-avatar"
:src="chatMember[message.from]?.avatar"
:src="chatMember[message.from]?.avatar || '/static/home/avatar.svg'"
mode="aspectFill"
/>
@ -113,8 +113,8 @@
v-if="!isEvaluationPopupOpen"
:timChatManager="timChatManager"
:formatTime="formatTime"
@scrollToBottom="scrollToBottom"
@messageSent="scrollToBottom"
@scrollToBottom="() => scrollToBottom(true)"
@messageSent="() => scrollToBottom(true)"
/>
</view>
</template>
@ -170,7 +170,7 @@ const updateNavigationTitle = () => {
const chatInfo = ref({
conversationID: "",
userID: "",
avatar: "/static/home/doctor.png",
avatar: "/static/home/avatar.svg",
});
//
@ -196,6 +196,11 @@ function isSystemMessage(message) {
//
function getBubbleClass(message) {
//
if (message.type === "TIMImageElem") {
return "image-bubble";
}
if (message.type === "TIMCustomElem") {
return message.flow === "out" ? "user-bubble" : "doctor-bubble-blue";
}
@ -279,10 +284,9 @@ const initTIMCallbacks = async () => {
if (!existingMessage) {
messageList.value.push(message);
console.log("✓ 添加消息到列表,当前消息数量:", messageList.value.length);
// 使
nextTick(() => {
setTimeout(() => {
scrollToBottom();
}, 100);
scrollToBottom(true);
});
}
});
@ -473,13 +477,24 @@ const playVoice = (message) => {
};
//
const scrollToBottom = () => {
const scrollToBottom = (immediate = false) => {
if (messageList.value.length > 0) {
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(() => {
scrollIntoView.value = `msg-${lastMessage.ID}`;
}, 300);
scrollIntoView.value = targetId;
}, 50);
}
}
};

View File

@ -122,20 +122,15 @@ const initIM = async () => {
//
const loadConversationList = async () => {
if (loading.value) return;
loading.value = true;
// loading.value = true;
try {
console.log("开始加载群聊列表");
// globalTimChatManager
if (!globalTimChatManager || !globalTimChatManager.getGroupList) {
throw new Error("IM管理器未初始化");
}
// getGroupListSDK
const result = await globalTimChatManager.getGroupList();
if (result && result.success && result.groupList) {
conversationList.value = result.groupList
.map((group) => ({
@ -220,25 +215,31 @@ const extractMessagePreview = (message) => {
return "暂无消息";
};
//
const setupMessageListener = () => {
//
const setupConversationListener = () => {
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(
(conv) => conv.conversationID === conversationID
);
if (conversationIndex !== -1) {
//
const conversation = conversationList.value[conversationIndex];
conversation.lastMessage = extractMessagePreview(message);
conversation.lastMessageTime = message.lastTime || Date.now();
conversation.unreadCount = (conversation.unreadCount || 0) + 1;
const existingConversation = conversationList.value[conversationIndex];
existingConversation.lastMessage = conversation.lastMessage || "暂无消息";
existingConversation.lastMessageTime = conversation.lastMessageTime || Date.now();
existingConversation.unreadCount = conversation.unreadCount || 0;
//
const [updatedConversation] = conversationList.value.splice(
@ -247,7 +248,39 @@ const setupMessageListener = () => {
);
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;
}
//
setupMessageListener();
//
//
await loadConversationList();
//
setupConversationListener();
} catch (error) {
console.error("页面初始化失败:", error);
uni.showToast({
@ -359,6 +392,7 @@ onShow(async () => {
onHide(() => {
//
if (globalTimChatManager) {
globalTimChatManager.setCallback("onConversationListUpdated", null);
globalTimChatManager.setCallback("onMessageReceived", null);
}
});

BIN
static/icon/changyongyu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
static/icon/fuzhenyuyue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
static/icon/jieshuzixun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
static/icon/kaichufang.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
static/icon/kaiyizhu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
static/icon/kaizhongyao.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
static/icon/paizhao.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
static/icon/zhaopian.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -39,7 +39,7 @@ export default defineStore("accountStore", () => {
}
account.value = res.data;
openid.value = res.data.openid;
await getDoctorInfo(openid.value);
// 登录成功后初始化腾讯IM
try {
@ -51,7 +51,7 @@ export default defineStore("accountStore", () => {
console.error('腾讯IM初始化失败:', imError);
// IM初始化失败不影响登录流程
}
await getDoctorInfo(openid.value);
return res.data
}
}

View File

@ -486,6 +486,8 @@ export const sendCustomMessage = async (messageData, timChatManager, validateBef
* @param {function} onSuccess - 成功回调
*/
export const sendMessage = async (messageType, data, timChatManager, validateBeforeSend, onSuccess, cloudCustomData) => {
console.log('chat-utils sendMessage 被调用:', { messageType, data });
if (!validateBeforeSend()) {
return;
}
@ -497,7 +499,9 @@ export const sendMessage = async (messageType, data, timChatManager, validateBef
result = await timChatManager.sendTextMessage(data, cloudCustomData);
break;
case 'image':
console.log('准备发送图片消息,数据:', data);
result = await timChatManager.sendImageMessage(data, cloudCustomData);
console.log('图片消息发送结果:', result);
break;
case 'voice':
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) {
console.log('消息发送成功');
if (onSuccess) onSuccess();
} else {
console.error('发送消息失败:', result?.error);

View File

@ -427,27 +427,18 @@ class TimChatManager {
userID: this.currentUserID,
userSig: this.currentUserSig
}).then(() => {
console.log('腾讯IM登录成功')
console.log('腾讯IM登录请求成功等待SDK_READY事件...')
this.isLoggingIn = false
this.isLoggedIn = true
// 不在这里设置 isLoggedIn = true等待 onSDKReady 事件
this.reconnectAttempts = 0
// 启动心跳检测
this.startHeartbeat()
// 启动登录状态检测
this.startLoginStatusCheck()
// 触发登录状态变化回调
// 触发登录状态变化回调(登录中状态)
this.triggerCallback('onLoginStatusChanged', {
isLoggedIn: true,
isLoggedIn: false,
userID: this.currentUserID,
reason: 'LOGIN_SUCCESS'
reason: 'LOGIN_REQUESTED',
message: '登录请求成功等待SDK就绪...'
})
// 获取会话列表(确保连接正常)
this.getConversationList()
resolve()
}).catch(error => {
console.error('腾讯IM登录失败:', error)
@ -691,7 +682,6 @@ class TimChatManager {
})
this.startLoginStatusCheck()
this.startHeartbeat() // 启动心跳检测
this.getConversationList()
}
// SDK Not Ready 事件
@ -712,11 +702,8 @@ class TimChatManager {
event.data.forEach(message => {
const existingMessage = this.messageList.find(msg => msg.ID === message.ID)
if (existingMessage) return
if (!this.filterMessage(message)) return
const convertedMessage = this.convertMessageFormat(message)
// 确保使用消息本身的conversationID而不是当前会话ID
if (!convertedMessage.conversationID) {
convertedMessage.conversationID = message.conversationID
}
@ -731,30 +718,22 @@ class TimChatManager {
messageType: convertedMessage.type,
from: convertedMessage.from
})
console.log(event)
// 缓存功能已移除
// 判断是否为当前会话的消息必须有currentConversationID且匹配才显示
const isCurrentConversation = this.currentConversationID &&
messageConversationID === this.currentConversationID
console.log('消息会话匹配检查:', {
isCurrentConversation,
hasCurrentConversationID: !!this.currentConversationID,
conversationIDMatch: messageConversationID === this.currentConversationID
})
if (isCurrentConversation) {
// 当前会话的消息,触发回调
console.log('✓ 消息属于当前会话,触发显示')
this.triggerCallback('onMessageReceived', convertedMessage)
// 处理已读状态
if (this.currentConversationID) {
this.markConversationAsRead(this.currentConversationID)
}
this.triggerCallback('onConversationListUpdated', {
reason: 'NEW_MESSAGE_RECEIVED_IN_CURRENT_CONVERSATION',
conversation: {
@ -928,7 +907,6 @@ class TimChatManager {
return true
}
// 启动心跳检测(优化版:使用配置常量)
startHeartbeat() {
this.stopHeartbeat()
@ -952,14 +930,26 @@ class TimChatManager {
return
}
// 确保方法存在
if (typeof this.tim.getConversationList !== 'function') {
console.log('⏸ 心跳检测SDK方法不可用跳过检测')
return
}
this.tim.getConversationList()
.then(() => {
if (this.heartbeatFailCount > 0) {
console.log(`💚 心跳恢复正常(之前失败${this.heartbeatFailCount}次)`)
console.log(`<EFBFBD> 心跳恢复正常(之前失败${this.heartbeatFailCount}次)`)
}
this.heartbeatFailCount = 0 // 重置失败计数
})
.catch((error) => {
// 如果是SDK未就绪错误不计入失败次数这是临时状态
if (error && error.message && error.message.includes('sdk not ready')) {
console.log('⏸ 心跳检测SDK未就绪跳过本次检测')
return
}
this.heartbeatFailCount++
console.error(`💔 心跳失败 (${this.heartbeatFailCount}/${MAX_HEARTBEAT_FAIL}):`, error.message)
@ -1009,14 +999,6 @@ class TimChatManager {
setTimeout(checkSDKReady, 500)
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
const maxWaitTime = 30000 // 最多等待30秒
const checkInterval = 1000 // 每秒检查一次
let timeoutHandle = null
const checkSDKReady = () => {
if (this.isLoggedIn) {
console.log('SDK已ready开始获取群聊列表')
if (timeoutHandle) clearTimeout(timeoutHandle)
this.getGroupListInternal().then(resolve).catch(reject)
} else if (waitTime >= maxWaitTime) {
console.error('等待SDK就绪超时')
if (timeoutHandle) clearTimeout(timeoutHandle)
reject(new Error('SDK初始化超时请检查网络连接'))
} else {
waitTime += checkInterval
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) => {
console.log('开始获取群聊列表')
// 确保SDK已就绪再调用getConversationList
const ensureSDKReady = () => {
if (!this.isLoggedIn) {
console.log('SDK未就绪等待中...')
setTimeout(ensureSDKReady, 500)
return
}
// 直接调用SDK就绪检查已在getGroupList()中完成
this.tim.getConversationList()
.then(async (conversationResponse) => {
console.log('获取会话列表成功')
this.tim.getConversationList().then(async (conversationResponse) => {
console.clear()
console.log('获取会话列表成功:', conversationResponse)
const groupConversations = conversationResponse.data.conversationList.filter(conversation => {
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(
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('|')
try {
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 = groupListResponse.data.groupList.find(g => g.groupID === groupID)
if (group) {
groupInfo = {
...groupInfo,
name: group.name || '问诊群聊',
memberCount: group.memberCount || 0
}
}
} catch (error) {
console.error(`获取群组 ${groupID} 信息失败:`, error)
// 从已获取的群组列表中查找
const group = allGroups.find(g => g.groupID === groupID)
const groupInfo = {
groupID: groupID,
name: group?.name || '问诊群聊',
avatar: '/static/home/avatar.svg',
memberCount: group?.memberCount || 0
}
const lastMessage = conversation.lastMessage
let lastMessageText = ''
let lastMessageText = '暂无消息'
let lastMessageTime = Date.now()
if (lastMessage) {
console.log(`群聊 ${groupID} 最后一条消息:`, lastMessage)
if (lastMessage.type === 'TIMTextElem') {
lastMessageText = lastMessage.payload.text
} else if (lastMessage.type === 'TIMImageElem') {
@ -1118,19 +1093,12 @@ class TimChatManager {
} else if (lastMessage.type === 'TIMSoundElem') {
lastMessageText = '[语音]'
} else if (lastMessage.type === 'TIMCustomElem') {
lastMessageText = lastMessage.payload.data ? lastMessage.payload.data : '[自定义消息]'
lastMessageText = lastMessage.payload.data || '[自定义消息]'
} else {
lastMessageText = '[未知消息类型]'
}
if (lastMessage.lastTime) {
lastMessageTime = lastMessage.lastTime * 1000
} else if (lastMessage.time) {
lastMessageTime = lastMessage.time * 1000
}
} else {
console.log(`群聊 ${groupID} 没有最后一条消息`)
lastMessageText = '暂无消息'
lastMessageTime = (lastMessage.lastTime || lastMessage.time || 0) * 1000
}
return {
@ -1147,9 +1115,9 @@ class TimChatManager {
console.error(`处理群聊会话失败:`, error)
return {
groupID: conversation.conversationID,
name: conversation.groupProfile.name,
doctorId,
patientName,
name: conversation.groupProfile?.name || '问诊群聊',
doctorId: '',
patientName: '',
avatar: '/static/home/avatar.svg',
lastMessage: '获取失败',
lastMessageTime: Date.now(),
@ -1160,24 +1128,21 @@ class TimChatManager {
})
)
console.log('处理后的群聊列表:', groupsWithInfo)
console.log('处理后的群聊列表数量:', groupsWithInfo.length)
resolve({
success: true,
groupList: groupsWithInfo,
totalCount: groupsWithInfo.length,
data: conversationResponse.data
})
}).catch((imError) => {
})
.catch((imError) => {
console.error('获取会话列表失败:', imError)
reject({
success: false,
error: imError
})
})
}
// 开始检查SDK就绪状态
ensureSDKReady()
})
}
@ -1564,7 +1529,7 @@ class TimChatManager {
payload: this.convertDBPayloadToIMPayload(msgType, msgBody.MsgContent),
lastTime: lastTime,
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,
MsgSeq: dbMsg.MsgSeq, // 保留 MsgSeq 用于分页
}
@ -2074,29 +2039,42 @@ class TimChatManager {
if (!this.tim) {
this.triggerCallback('onError', 'IM未初始化')
return
return { success: false, error: 'IM未初始化' }
}
if (!this.conversation) {
this.triggerCallback('onError', '群聊会话不存在')
return { success: false, error: '群聊会话不存在' }
// 检查登录状态
if (!this.isLoggedIn) {
console.error('IM未登录无法发送消息');
this.triggerCallback('onError', 'IM未登录请稍后重试')
return { success: false, error: 'IM未登录' }
}
let groupID = null
if (this.conversation.groupProfile && this.conversation.groupProfile.groupID) {
groupID = this.conversation.groupProfile.groupID
} else if (this.conversation.conversationID) {
groupID = this.conversation.conversationID.replace('GROUP', '')
// 优先使用 currentConversationID如果没有则尝试从 conversation 获取
let conversationID = this.currentConversationID;
if (!conversationID && this.conversation) {
conversationID = this.conversation.conversationID;
}
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) {
console.error('无法获取群聊IDconversationID:', conversationID);
this.triggerCallback('onError', '无法获取群聊ID')
return { success: false, error: '无法获取群聊ID' }
}
// 确保使用当前会话的conversationID
const conversationID = this.conversation.conversationID || this.currentConversationID
const localMessage = {
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
flow: 'out',
@ -2127,39 +2105,75 @@ class TimChatManager {
} catch (error) {
console.error('文本消息发送失败:', error)
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 }
}
}
// 发送图片消息
async sendImageMessage(imageFile) {
console.log('sendImageMessage 被调用,参数:', imageFile);
if (!this.tim) {
this.triggerCallback('onError', 'IM未初始化')
return
return { success: false, error: 'IM未初始化' }
}
if (!this.conversation) {
this.triggerCallback('onError', '群聊会话不存在')
return { success: false, error: '群聊会话不存在' }
// 检查登录状态
if (!this.isLoggedIn) {
console.error('IM未登录无法发送消息');
this.triggerCallback('onError', 'IM未登录请稍后重试')
return { success: false, error: 'IM未登录' }
}
let groupID = null
if (this.conversation.groupProfile && this.conversation.groupProfile.groupID) {
groupID = this.conversation.groupProfile.groupID
} else if (this.conversation.conversationID) {
groupID = this.conversation.conversationID.replace('GROUP', '')
// 优先使用 currentConversationID如果没有则尝试从 conversation 获取
let conversationID = this.currentConversationID;
if (!conversationID && this.conversation) {
conversationID = this.conversation.conversationID;
}
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) {
console.error('无法获取群聊IDconversationID:', conversationID);
this.triggerCallback('onError', '无法获取群聊ID')
return { success: false, error: '无法获取群聊ID' }
}
// 确保使用当前会话的conversationID
const conversationID = this.conversation.conversationID || this.currentConversationID
console.log('发送图片消息conversationID:', conversationID, 'groupID:', groupID);
// 处理文件对象 - 确保获取正确的文件
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 = {
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
@ -2167,7 +2181,7 @@ class TimChatManager {
type: 'TIMImageElem',
payload: {
imageInfoArray: [{
url: this.getImageUrl(imageFile),
url: this.getImageUrl(actualFile),
width: imageInfo.width,
height: imageInfo.height
}]
@ -2186,19 +2200,33 @@ class TimChatManager {
// 触发消息接收回调让UI立即显示
this.triggerCallback('onMessageReceived', localMessage)
console.log('准备创建 TIM 图片消息groupID:', groupID, 'file:', actualFile);
const message = this.tim.createImageMessage({
to: groupID,
conversationType: TIM.TYPES.CONV_GROUP,
payload: { file: imageFile }
payload: { file: actualFile }
})
console.log('TIM 图片消息已创建:', message);
try {
await this.tim.sendMessage(message)
console.log('开始发送图片消息...');
const sendResult = await this.tim.sendMessage(message);
console.log('图片消息发送成功:', sendResult);
localMessage.status = 'success'
return { success: true, message: localMessage }
} catch (error) {
console.error('图片消息发送失败:', error)
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 }
}
}
@ -2207,29 +2235,42 @@ class TimChatManager {
async sendVoiceMessage(voiceFile, duration) {
if (!this.tim) {
this.triggerCallback('onError', 'IM未初始化')
return
return { success: false, error: 'IM未初始化' }
}
if (!this.conversation) {
this.triggerCallback('onError', '群聊会话不存在')
return { success: false, error: '群聊会话不存在' }
// 检查登录状态
if (!this.isLoggedIn) {
console.error('IM未登录无法发送消息');
this.triggerCallback('onError', 'IM未登录请稍后重试')
return { success: false, error: 'IM未登录' }
}
let groupID = null
if (this.conversation.groupProfile && this.conversation.groupProfile.groupID) {
groupID = this.conversation.groupProfile.groupID
} else if (this.conversation.conversationID) {
groupID = this.conversation.conversationID.replace('GROUP', '')
// 优先使用 currentConversationID如果没有则尝试从 conversation 获取
let conversationID = this.currentConversationID;
if (!conversationID && this.conversation) {
conversationID = this.conversation.conversationID;
}
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) {
console.error('无法获取群聊IDconversationID:', conversationID);
this.triggerCallback('onError', '无法获取群聊ID')
return { success: false, error: '无法获取群聊ID' }
}
// 确保使用当前会话的conversationID
const conversationID = this.conversation.conversationID || this.currentConversationID
const localMessage = {
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
flow: 'out',
@ -2262,6 +2303,14 @@ class TimChatManager {
} catch (error) {
console.error('语音消息发送失败:', error)
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 }
}
}
@ -2270,29 +2319,42 @@ class TimChatManager {
async sendCustomMessage(messageData) {
if (!this.tim) {
this.triggerCallback('onError', 'IM未初始化')
return
return { success: false, error: 'IM未初始化' }
}
if (!this.conversation) {
this.triggerCallback('onError', '群聊会话不存在')
return { success: false, error: '群聊会话不存在' }
// 检查登录状态
if (!this.isLoggedIn) {
console.error('IM未登录无法发送消息');
this.triggerCallback('onError', 'IM未登录请稍后重试')
return { success: false, error: 'IM未登录' }
}
let groupID = null
if (this.conversation.groupProfile && this.conversation.groupProfile.groupID) {
groupID = this.conversation.groupProfile.groupID
} else if (this.conversation.conversationID) {
groupID = this.conversation.conversationID.replace('GROUP', '')
// 优先使用 currentConversationID如果没有则尝试从 conversation 获取
let conversationID = this.currentConversationID;
if (!conversationID && this.conversation) {
conversationID = this.conversation.conversationID;
}
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) {
console.error('无法获取群聊IDconversationID:', conversationID);
this.triggerCallback('onError', '无法获取群聊ID')
return { success: false, error: '无法获取群聊ID' }
}
// 确保使用当前会话的conversationID
const conversationID = this.conversation.conversationID || this.currentConversationID
const localMessage = {
ID: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
flow: 'out',
@ -2330,6 +2392,14 @@ class TimChatManager {
} catch (error) {
console.error('自定义消息发送失败:', error)
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 }
}
}
@ -2364,7 +2434,7 @@ class TimChatManager {
payload: timMessage.payload,
lastTime: lastTime,
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: timMessage.conversationID
}
@ -2408,12 +2478,19 @@ class TimChatManager {
}
getImageUrl(imageFile) {
// 处理 tempFiles 数组格式
if (imageFile?.tempFiles?.length > 0) {
return imageFile.tempFiles[0].tempFilePath
}
// 处理单个文件对象
if (imageFile?.tempFilePath) {
return imageFile.tempFilePath
}
// 处理字符串路径
if (typeof imageFile === 'string') {
return imageFile
}
console.warn('无法获取图片URL使用默认图片:', imageFile);
return '/static/home/photo.png'
}
@ -2422,17 +2499,22 @@ class TimChatManager {
return new Promise((resolve) => {
let imagePath = '';
// 获取图片路径
// 获取图片路径 - 处理多种格式
if (imageFile?.tempFiles?.length > 0) {
imagePath = imageFile.tempFiles[0].tempFilePath;
} else if (imageFile?.tempFilePath) {
imagePath = imageFile.tempFilePath;
} else if (typeof imageFile === 'string') {
imagePath = imageFile;
} else {
console.warn('无法获取图片路径,使用默认尺寸:', imageFile);
// 默认尺寸
resolve({ width: 400, height: 300 });
return;
}
console.log('获取图片信息,路径:', imagePath);
// 使用uni.getImageInfo获取图片尺寸
uni.getImageInfo({
src: imagePath,