From 16c7d2b261ff65c3e78a15688e004a5c44fb08cc Mon Sep 17 00:00:00 2001
From: wangdongbo <949818794@qq.com>
Date: Thu, 22 Jan 2026 16:35:05 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E9=97=B4=E5=BC=80=E5=8F=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
App.vue | 18 +-
pages/message/chat.scss | 20 +-
pages/message/components/chat-input.vue | 30 +-
pages/message/components/head-card.vue | 2 +-
pages/message/index.vue | 45 ++-
pages/message/message.vue | 84 +++--
static/icon/changyongyu.png | Bin 0 -> 2793 bytes
static/icon/fuzhenyuyue.png | Bin 0 -> 3537 bytes
static/icon/icon-chinese-rx.png | Bin 0 -> 4406 bytes
static/icon/icon-western-rx.png | Bin 0 -> 3880 bytes
static/icon/jieshuzixun.png | Bin 0 -> 4352 bytes
static/icon/kaichufang.png | Bin 0 -> 1346 bytes
static/icon/kaiyizhu.png | Bin 0 -> 2637 bytes
static/icon/kaizhongyao.png | Bin 0 -> 1288 bytes
static/icon/paizhao.png | Bin 0 -> 3663 bytes
static/icon/quxiaobingtuikuan.png | Bin 0 -> 3930 bytes
static/icon/xuanjiaowenzhang.png | Bin 0 -> 2708 bytes
static/icon/zhaopian.png | Bin 0 -> 2922 bytes
static/icon/zhenliaoyijian.png | Bin 0 -> 3057 bytes
store/account.js | 14 +-
utils/chat-utils.js | 5 +
utils/tim-chat.js | 478 ++++++++++++++----------
22 files changed, 429 insertions(+), 267 deletions(-)
create mode 100644 static/icon/changyongyu.png
create mode 100644 static/icon/fuzhenyuyue.png
create mode 100644 static/icon/icon-chinese-rx.png
create mode 100644 static/icon/icon-western-rx.png
create mode 100644 static/icon/jieshuzixun.png
create mode 100644 static/icon/kaichufang.png
create mode 100644 static/icon/kaiyizhu.png
create mode 100644 static/icon/kaizhongyao.png
create mode 100644 static/icon/paizhao.png
create mode 100644 static/icon/quxiaobingtuikuan.png
create mode 100644 static/icon/xuanjiaowenzhang.png
create mode 100644 static/icon/zhaopian.png
create mode 100644 static/icon/zhenliaoyijian.png
diff --git a/App.vue b/App.vue
index 7fe422c..bffc016 100644
--- a/App.vue
+++ b/App.vue
@@ -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);
+ // }
},
};
diff --git a/pages/message/chat.scss b/pages/message/chat.scss
index 62ece8f..a885920 100644
--- a/pages/message/chat.scss
+++ b/pages/message/chat.scss
@@ -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;
}
diff --git a/pages/message/components/chat-input.vue b/pages/message/components/chat-input.vue
index f103256..571e398 100644
--- a/pages/message/components/chat-input.vue
+++ b/pages/message/components/chat-input.vue
@@ -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() {
diff --git a/pages/message/components/head-card.vue b/pages/message/components/head-card.vue
index cc94bc4..568b64e 100644
--- a/pages/message/components/head-card.vue
+++ b/pages/message/components/head-card.vue
@@ -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) {
diff --git a/pages/message/index.vue b/pages/message/index.vue
index c84fce7..19d0432 100644
--- a/pages/message/index.vue
+++ b/pages/message/index.vue
@@ -50,19 +50,19 @@
-
+
-
+
@@ -113,8 +113,8 @@
v-if="!isEvaluationPopupOpen"
:timChatManager="timChatManager"
:formatTime="formatTime"
- @scrollToBottom="scrollToBottom"
- @messageSent="scrollToBottom"
+ @scrollToBottom="() => scrollToBottom(true)"
+ @messageSent="() => scrollToBottom(true)"
/>
@@ -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 = ``;
- setTimeout(() => {
- scrollIntoView.value = `msg-${lastMessage.ID}`;
- }, 300);
+ const targetId = `msg-${lastMessage.ID}`;
+
+ if (immediate) {
+ // 立即滚动:先清空再设置,触发滚动
+ scrollIntoView.value = '';
+ nextTick(() => {
+ scrollIntoView.value = targetId;
+ });
+ } else {
+ // 正常滚动,使用短延迟确保DOM更新
+ scrollIntoView.value = '';
+ setTimeout(() => {
+ scrollIntoView.value = targetId;
+ }, 50);
+ }
}
};
diff --git a/pages/message/message.vue b/pages/message/message.vue
index 7e1d423..0cacc4d 100644
--- a/pages/message/message.vue
+++ b/pages/message/message.vue
@@ -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管理器未初始化");
}
-
// 直接调用getGroupList,它会自动等待SDK就绪
const result = await globalTimChatManager.getGroupList();
-
if (result && result.success && result.groupList) {
conversationList.value = result.groupList
.map((group) => ({
@@ -220,34 +215,72 @@ const extractMessagePreview = (message) => {
return "暂无消息";
};
-// 设置消息监听,实时更新列表
-const setupMessageListener = () => {
+// 设置会话列表监听,实时更新列表
+const setupConversationListener = () => {
if (!globalTimChatManager) return;
+ // 监听会话列表更新事件
+ globalTimChatManager.setCallback("onConversationListUpdated", (eventData) => {
+ console.log("会话列表更新事件:", eventData);
+
+ // 如果是新消息导致的会话更新
+ 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 existingConversation = conversationList.value[conversationIndex];
+ existingConversation.lastMessage = conversation.lastMessage || "暂无消息";
+ existingConversation.lastMessageTime = conversation.lastMessageTime || Date.now();
+ existingConversation.unreadCount = conversation.unreadCount || 0;
+
+ // 将该会话移到顶部
+ const [updatedConversation] = conversationList.value.splice(
+ conversationIndex,
+ 1
+ );
+ conversationList.value.unshift(updatedConversation);
+
+ 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];
- conversation.lastMessage = extractMessagePreview(message);
- conversation.lastMessageTime = message.lastTime || Date.now();
+ // 只更新未读数,其他信息由 onConversationListUpdated 事件处理
conversation.unreadCount = (conversation.unreadCount || 0) + 1;
-
- // 将该会话移到顶部
- const [updatedConversation] = conversationList.value.splice(
- conversationIndex,
- 1
- );
- conversationList.value.unshift(updatedConversation);
-
- console.log("已更新会话:", conversation.name);
+ 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);
}
});
diff --git a/static/icon/changyongyu.png b/static/icon/changyongyu.png
new file mode 100644
index 0000000000000000000000000000000000000000..7e6de393c77f68bd2a781a5718272b3a253628a0
GIT binary patch
literal 2793
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
LNkvXXu0mjfrVGGJ
literal 0
HcmV?d00001
diff --git a/static/icon/icon-chinese-rx.png b/static/icon/icon-chinese-rx.png
new file mode 100644
index 0000000000000000000000000000000000000000..10ee891d7137aa4c92c56830a6c7938e266b2f3d
GIT binary patch
literal 4406
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
literal 0
HcmV?d00001
diff --git a/static/icon/icon-western-rx.png b/static/icon/icon-western-rx.png
new file mode 100644
index 0000000000000000000000000000000000000000..00cb9a8c93c7bb49e8a37b61163965203c92c31f
GIT binary patch
literal 3880
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
Eg2io%BLDyZ
literal 0
HcmV?d00001
diff --git a/static/icon/kaiyizhu.png b/static/icon/kaiyizhu.png
new file mode 100644
index 0000000000000000000000000000000000000000..e47bc0c927bc3c3b234f7a8eb14275a6753eca66
GIT binary patch
literal 2637
zcmV-T3bOTyP)=>}TJ;eKl|pI1-!$egpmrZUqm6XTc7z8;nM9*=_E#k9{5ESbgYA
zpS2+?Hy9cLAo5^v3ItsSZUO5f{Ezk`@N;lH_$K%YI2g=~;IiA?XCM1I#<6uj`n=2-
z!2S#^-U<@{67~mk!P($GsMrPW0n5P2;A`L@kmObCSbgYApZYe&E@J{?o5TLZDa3LY
zfTCxDlc;tr@YT7R*7eWO=4Hk*rm@XotvLaYsJwCrU_J$G2J67F;Im-Z%^c0uoHtto$V`Y#1R&ur!1Cqbdhi`ERn6S3;qs`a)ayu9
z0FvAfoJp2XfZu^Hf~juSU@cEr8`v++f>INJ#115}3&20Ym%(&1YqGWrqFPg_FR=h5
zGXr?2ZX~0>fzN~Cw)ojun>B8E)6(QZPUL2w0v*`b0Mzwt=L9-CLsWGZD{EpvPS(NG37~IY
z`|e1fZvkhwzVESESqBE>MvmmF!|wJ?eF=b~PO`3MxS#wqm33i2j;@Y4>(Xs}S5EDatC|<$!6`UR5-Z(U
zIlD08aMI!@6@YQ&3ql2INpKJ9_CTK&03z
zMtCipCb{k0^=5F*wd;bjmM#y@_`|Zoux0C$!RY8%@`C#JAcw0WPTNLx6o6ho172dL
zNyqNGdsFb}<6DEVv0RI9OMYZzZ}7}>&$n&Qc!ONZXG=`I4PsjaV5@g{d{BwSa#+qsg51h+gWQGyDC6^yOW5NB
zN;KuLS}oTjL2j2sT!#cV1Yqr}z)x$M@>y0#LI)=0Sgyle%>w+8Enf$vv|25uH$A*o8H*Jz;pbvc|
z^^?PRIX^-H{9;-T@w$h2Y|GYQ#b5rB_)eKV9>Z7nXhXAit^&*%nsmyS$Q%Xmy{LSp
z4@bq}X{e8%3`aWU%VL&Czyal}duS>?Kmn>Fpg29kBcQnOO_80wI*Uy@6Ye$M7{+P}
zUFf1mz(}DPM8TcCI*W}~Gi!`ttjq!o=6FN_-W_aA)jLH7-c^91I0Br#I*U!QxQ?!j
zVXTfj^WPXA0ekX~+a58knQ*V?PKRu!yvHM8XFDBnwp3$cFtAerw#OJ)4M~TA?Fz61
zU;991`7$8qI~3pz;uiin;JLZy=)KP4lkPW$v8cIdlk+zeU^kfvn&QlJbI;MU&cGPP
z$~sOT{^fkP0=z=!mqBIuG9c%#D1e7T?q3<1SgYseo}*9Pp7y#ijFqmyKEJ`BjUoR2@6h!SrT_d!ruJ`6k;;vj%Yd9-
z8gbn4+#*1<^,L8>-$rr!Zi)n#VRGRjp><+dg7HUUuRReD?jQnh(UemlT-sy?%D
zW{&2Xf$uBuEw?SM+XRUA-cIYMHBCD9lON9yzJKh|K}N5xRFX6|b2Qgf9DeFVF6H#o
zEzwd(0Z_^t^~>q=CP>A+4E*~u76(_YS(WG;FiGzRbQ^DO=4h^|6g}=l4wpxqj&EuD
z-BEyO|7O}dL1oDpkVCob=w(s?BE?oP>NPN2Hg&R*yA=_a9kZTP0DCj=En5F3@_V$E
z4aR_+T^w;Z>Bz1EM5FxL_`jm%s_CBrIg`7tBYFyef*;~x4G6Da(^l4-0l8Weao4qX
zPXQc_BX3*!-;thjy+T(8-gSA?-wI?buu>h#=*^!r97m&$C
zz$rM*v@~n8#s$>e-U~`@nyHcq-e@0)8pb
z2b5SGDl;c@GsjcO`38^~@%73x7oZ-9VqOK;vpx^Z2R8v9R7!j%fuFc$Y;!OdbDC$4
zpzY~}xB+^N%T0iKA{6JPjQd&lQieyxGL~KUnRym-F=H9i*yiA+g!|1cm*`DFau=W;
zn_@@7c5o#)neDT|kHBhhA9xYG1AJ?siDiz}hraZwZ)40hCNQ=+_*`tP07(ZGCcwnR
zA>(b})x`7I_Y2@FQ#j-FAL-x5wnxBoz%RJ@r4laz2$$XFKKt0$F^<)T(C2x^0QSdC
vZ_B#JCjbBd|NljvzC!>200v1!K~w_(hvP?wp{zty00000NkvXXu0mjfBl!tj
literal 0
HcmV?d00001
diff --git a/static/icon/kaizhongyao.png b/static/icon/kaizhongyao.png
new file mode 100644
index 0000000000000000000000000000000000000000..f9d649e5f04635d8ceda22b06d4986650ab078aa
GIT binary patch
literal 1288
zcmV+j1^4=iP)ASdGWa(&HPs@t3k6|BI3rvZZaXk%jdSFX+mb%_vtpEq-m6|*f8&JcXuuHAZ2?N4Pp+QI*)KCk@IXHz}Qj*vPM7}`S
zq6Vjhyzr2aRlo)3X?h3?;u6O)Ai}3a$fdGf<3izn1>E#F>Uu`@i8LUhSHyBcSSHL>
z(CdWj9ojS0fC$#AdY{lN%yrOnpVLsWcSQrPa8Q*G2(=1&4>~PnHIy}=0xp}~Wh-j4
zxZ7!()qR!$C33?KDHHb^>LSoG*G$Jekjxc)TMRiJ6uY4n8!3}}^aNuB_j
z)@7g#jlMYFfSmCy*z2FEVlwvcNjrSx&rpz41@+95UZ>St^9|@|v%nXLhU((_^&63e
zadIL^(1=zq%`+fJY^HeTdy8@Y{CDzy%XfcZZ*^|)5vPuvnKf|0#d-p)b(;O%=xZuw
zKcXRCd@=N$T`Tz?zj*0#WN~Q@9B@Sz1{2VVX5YXY!Sm5aG%n2=IdI6n{&qMN1ol1fkkOq4vro%0MGA-{;Bb<$HwK@#rHD$IgvPtb%Kg(>!g!HQ1>!
z_P5L19j{vzjnyI;aKIH@4Lw35TD_#=C1i4RUMqbP)*(j~hHRwL6WHI2{24EGglP#ttEq
zHxBV+5oqaf+5&vD3~*M7KWSVi)Jv>$nr7)KYk({j@L28C9QPV(67=qLTFMHjXn<^2
zxJGlXKMgS>n>2c^aT+Qzh8mzs1YAzbHRlPSVNQZx%U$o#hLHxS77;i0D$TnEzDP9O
zmw=ldt6a~>Cb0~_BEq}E4$b)?te}zoh=xo8E;yIcL*Q{9i#WD{BAdw13!8MjMCcNZ
z3GB@^BnoP%g<}bv0=t1kB#8|a+0|@Z_*CH1YSsFyLcj2vz5EbUGJ0000NVrTSwP9l~h&w~-PP`sIw*(f|Mz
zk-CZ^%on(mMfRS4oFU4cM@WN+K5b3KhJySp$Ff)aBdF#3o)}BIyh9ah6>1?N2S)n5
z<;rB$=Qb4T!z$N#;J0GL?lp3WL=@8kd-6mvU`16Dh8sxWMF+gp$3Lrb%Rn4Fiu`?6
zcD6NtHFvhKw^h02RG7fGv#>sh&_ySrf#?x*Qp7-HKqMGVxAe-YPJ27t6*Co0-QG-J8R*I|+~rkgAdXCbMAhp{qaZyl=D9MPgwcL+QKN
z8VV)4V3;|Yum&fS?nbnuo0RJE4f(z@V#vZH%+ZNTP@J*#QV2w=G1G?OCHYrPs$Gd^
zafT=+g}8ZhY2&gi{(~Llr}SWxx^
zTwOKn0(Gc#v2pX_V)F7&WQ&|bv9D~UDwyIqsu)L~|IB?LJL;x8Yp^(+!~gt|*6O3g
z(LSTi8?U2k7(!MfJB`2SqRr4!5mZXw64?6EkRPonm0TiY3II=h?MnjlJc@>&P3a`y
zjk*#p;mE2kN8tNaAGCw*d8aJbR|
zHUcURGaYYLp+JU}31W@S?!e8Koeez>!H^t<%211<$0AB4C5A-c;k^eI1FcJ72-kjB
zE(XnW_ueUGq}zv-dixGIS)*5uCB}wWn8LSazC^JX#zANDA9*
zJ3H^@miqZj>!t3-i$1Iw9b#i5>qY~akisbVk8%h9+$vB1dwBqsHC7Hc*f+ZYLo>5B
zy}_Wdy^rU~Z6~KP^`0x3-q?TN1kIlLRg-JxlP6r*44@bFn@7!&TIyDbr!#~}&iT4X
z3;#yu*BigXrWrdL$4WV~?k-7zm2DeXrQD9BmqZZdvY=Y_HRoN?0!YsMB+-1ucw+-I
zYJI9-Z-0$O9Mf)zy%6|VbF%FmUWsDVYRsZdfBYUxnJ_XlJKhLTbIMN|wyytCutvQ6
z1mH%)^d`2|A$}q|U$?YQctT-3w0|V$E1Mue!5Hoxz_eBgM&(L)v{%;-(qUF<6{aCLk0b*fH<4Feu|D8u!jGE7_VDa
zY9jD$*uYNnqX`9z;~#flGzJgK9rKAddZBX-XnISQcdF6WiBL(=%M)
zR0e|WEpa#Mdc_F-XZDBJ>%$iO(S2p@?ep2@Kiz*1YBo$y+hB_xl4S*-f_=WHrMgV)
zY#Gk`Le_e@W1yJ`wy(2{>X}xzg9Z7p9Bs)9zEF=p
z)DOqBF6KS9zh$ygd}f1h(kb6z^N?Jc*J)|d1th8przv#$(NY0rYTZAcmQ*b`444P^
z>@~SZnaLg+%LL$k|6M0A3_w8Z+cz`}w}U8lGph6BSI!Qx>^7t~R_lG{9w17RP`X#%
zMS6M`pc@OFTgknZzWkeWfvNd
z0ABH-pm0@4ow|CI?CEaXYmC}p!9Y5b+zw4DHCti~sByKKGLY_se6zNTirGI9rkgrKJ=&KzxK7o@kXm&{9@CD_
z`0S)wE7=OtZ#JrCWlWq)$n@FyR^TZ$=HugX|MjiUzDNU|kWG^58!5(zZtKUn3zs8z
z^=z?rFR{tNhW)nmA=^EOu1AJb&pL*`!VKdia?_+6?(+T8B$w@M6J%4v6kak+v=h!{O^u
zUt!WAFBg^5mBj9p_l(m~nIvey-+SL~cgA%;^#6o~A{U!SCv!YszUndjehKWYRCs9w
zZ<>}(r!K_x*F!ry`cP$Zrg5zYRuN_aJw2x_f~j)KR49t8ui}~8Pol;F?Va2)LpJ_~BGPp`
zsFC8;z%aj+D|hAw3azFSYM+q;gV~JZyFb4CQ%wuS#}bL#1{fn>o9uE|iAT=vjh?{E
zvUfdUy4x-8?%QL6$K*w$WY#x%2rw4PLBRYxEdp5c1~YYEUBedLbT5jFo)0)X+WYR=
zIgVt*N2}~5Zm7&Uwoh=pY6h6&TtbcIKbCshxHe2HCun_D{2go7(kwe-7k8|xRK|>*kvYJB+G2KMJ;%6Tqpv3Pu?{y|nfZ>r+e^?zcmLev`wo1;X3l!RP$u<1?OmED)P
z5y=lSNL7xdZ3ZMvT~+SB1SbYK85h*}NGQZT2C0Yu#u@D#CagdNrDmK~vu@?U6%o8n
z@+9(>0!_;35heAT;t*UrRHoq@aH1b>6kw!rrv*?d|1q%<|3D@4DZMn<0Hw#`Y?Gi|
zyVnD9Z?_e$-2oAyZZm65R2p1ufS7W}T=Xz-!`YKd+j6+~9OX`tkIX1X+S
zm??^ZtM^IViVjBhr0IQUnKiQh`%7HweMC=2++ShQ`2JoJ9&UU3C{-c=7}iubWo(t{
z5qIzL%7p+ewm9o13{pkLNyf%9rXu$L-X)LqpLfACu{wr%g&UUxreihYslk=}<~czE
zWU}Hwd*lW8pWhOv`PHyR61R)u2n|5U|9n-*F=(CUfJt+du>re5aD!J@i21KWgbDFq
bKX?t$C;l{jzO+b}umVt5)l#WcvJCqV+_3%h
literal 0
HcmV?d00001
diff --git a/static/icon/quxiaobingtuikuan.png b/static/icon/quxiaobingtuikuan.png
new file mode 100644
index 0000000000000000000000000000000000000000..97c24a321ac59b9ac012d892bd73ff786e74d600
GIT binary patch
literal 3930
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
a=>cZ4X{qjWfo&%<07E_GjZ$5gsQ&@{f?g~D
literal 0
HcmV?d00001
diff --git a/static/icon/xuanjiaowenzhang.png b/static/icon/xuanjiaowenzhang.png
new file mode 100644
index 0000000000000000000000000000000000000000..dffdb3734f15d82eddd1b83619eb4eaba2cc5e29
GIT binary patch
literal 2708
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
literal 0
HcmV?d00001
diff --git a/static/icon/zhenliaoyijian.png b/static/icon/zhenliaoyijian.png
new file mode 100644
index 0000000000000000000000000000000000000000..08851f4651b41b21b8125bce812553dab26a34dd
GIT binary patch
literal 3057
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 {
const isIMInitialized = ref(false);
// 医生信息
const doctorInfo = ref(null);
-
+
async function login(phoneCode = '') {
if (loading.value) return;
loading.value = true;
@@ -39,8 +39,8 @@ export default defineStore("accountStore", () => {
}
account.value = res.data;
openid.value = res.data.openid;
- await getDoctorInfo(openid.value);
-
+
+
// 登录成功后初始化腾讯IM
try {
console.log('开始初始化腾讯IM,userID:', res.data.openid);
@@ -51,7 +51,7 @@ export default defineStore("accountStore", () => {
console.error('腾讯IM初始化失败:', imError);
// IM初始化失败不影响登录流程
}
-
+ await getDoctorInfo(openid.value);
return res.data
}
}
@@ -61,7 +61,7 @@ export default defineStore("accountStore", () => {
}
loading.value = false
}
-
+
async function getDoctorInfo() {
try {
const res = await api('getCorpMemberData', {
@@ -88,7 +88,7 @@ export default defineStore("accountStore", () => {
return false;
}
}
-
+
// 退出登录
async function logout() {
try {
@@ -101,7 +101,7 @@ export default defineStore("accountStore", () => {
} catch (error) {
console.error('退出腾讯IM失败:', error);
}
-
+
// 清空账户信息
account.value = null;
openid.value = "";
diff --git a/utils/chat-utils.js b/utils/chat-utils.js
index 01164ee..f172069 100644
--- a/utils/chat-utils.js
+++ b/utils/chat-utils.js
@@ -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);
diff --git a/utils/tim-chat.js b/utils/tim-chat.js
index 631aec1..d57d8ce 100644
--- a/utils/tim-chat.js
+++ b/utils/tim-chat.js
@@ -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(`� 心跳恢复正常(之前失败${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,124 +1045,104 @@ 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('获取会话列表成功')
+
+ const groupConversations = conversationResponse.data.conversationList.filter(conversation => {
+ return conversation.conversationID && conversation.conversationID.startsWith('GROUP')
+ })
- 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.length)
- console.log('群聊会话列表:', groupConversations)
-
- const groupsWithInfo = await Promise.all(
- groupConversations.map(async (conversation) => {
- const groupName = typeof conversation.groupProfile.name === 'string' ? conversation.groupProfile.name : 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
- }
+ // 先获取一次群组列表,避免在循环中重复调用
+ 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) => {
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
+ const groupName = conversation.groupProfile?.name || ''
+ const [doctorId, patientName] = groupName.split('|')
+ const groupID = conversation.conversationID.replace('GROUP', '')
+
+ // 从已获取的群组列表中查找
+ 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 lastMessageTime = Date.now()
+
+ if (lastMessage) {
+ if (lastMessage.type === 'TIMTextElem') {
+ lastMessageText = lastMessage.payload.text
+ } else if (lastMessage.type === 'TIMImageElem') {
+ lastMessageText = '[图片]'
+ } else if (lastMessage.type === 'TIMSoundElem') {
+ lastMessageText = '[语音]'
+ } else if (lastMessage.type === 'TIMCustomElem') {
+ lastMessageText = lastMessage.payload.data || '[自定义消息]'
+ } else {
+ lastMessageText = '[未知消息类型]'
}
+
+ lastMessageTime = (lastMessage.lastTime || lastMessage.time || 0) * 1000
+ }
+
+ return {
+ ...groupInfo,
+ groupID: groupID,
+ doctorId,
+ patientName,
+ conversationID: conversation.conversationID,
+ lastMessage: lastMessageText,
+ lastMessageTime: lastMessageTime,
+ unreadCount: conversation.unreadCount || 0
}
} catch (error) {
- console.error(`获取群组 ${groupID} 信息失败:`, error)
- }
-
- const lastMessage = conversation.lastMessage
- 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') {
- lastMessageText = '[图片]'
- } else if (lastMessage.type === 'TIMSoundElem') {
- lastMessageText = '[语音]'
- } else if (lastMessage.type === 'TIMCustomElem') {
- lastMessageText = lastMessage.payload.data ? lastMessage.payload.data : '[自定义消息]'
- } else {
- lastMessageText = '[未知消息类型]'
+ console.error(`处理群聊会话失败:`, error)
+ return {
+ groupID: conversation.conversationID,
+ name: conversation.groupProfile?.name || '问诊群聊',
+ doctorId: '',
+ patientName: '',
+ avatar: '/static/home/avatar.svg',
+ lastMessage: '获取失败',
+ lastMessageTime: Date.now(),
+ unreadCount: conversation.unreadCount || 0,
+ memberCount: 0
}
+ }
+ })
+ )
- if (lastMessage.lastTime) {
- lastMessageTime = lastMessage.lastTime * 1000
- } else if (lastMessage.time) {
- lastMessageTime = lastMessage.time * 1000
- }
- } else {
- console.log(`群聊 ${groupID} 没有最后一条消息`)
- lastMessageText = '暂无消息'
- }
-
- return {
- ...groupInfo,
- groupID: groupID,
- doctorId,
- patientName,
- conversationID: conversation.conversationID,
- lastMessage: lastMessageText,
- lastMessageTime: lastMessageTime,
- unreadCount: conversation.unreadCount || 0
- }
- } catch (error) {
- console.error(`处理群聊会话失败:`, error)
- return {
- groupID: conversation.conversationID,
- name: conversation.groupProfile.name,
- doctorId,
- patientName,
- avatar: '/static/home/avatar.svg',
- lastMessage: '获取失败',
- lastMessageTime: Date.now(),
- unreadCount: conversation.unreadCount || 0,
- memberCount: 0
- }
- }
+ console.log('处理后的群聊列表数量:', groupsWithInfo.length)
+ resolve({
+ success: true,
+ groupList: groupsWithInfo,
+ totalCount: groupsWithInfo.length,
+ data: conversationResponse.data
})
- )
-
- console.log('处理后的群聊列表:', groupsWithInfo)
- resolve({
- success: true,
- groupList: groupsWithInfo,
- totalCount: groupsWithInfo.length,
- data: conversationResponse.data
})
- }).catch((imError) => {
- console.error('获取会话列表失败:', imError)
- reject({
- success: false,
- error: 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('无法获取群聊ID,conversationID:', 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('无法获取群聊ID,conversationID:', 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('无法获取群聊ID,conversationID:', 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('无法获取群聊ID,conversationID:', 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,