|
|
@@ -124,10 +124,7 @@
|
|
|
@click.stop="toggleVoicePlay(msg)">
|
|
|
<text class="voice-duration">{{ msg.duration }}''</text>
|
|
|
<view class="voice-icon-wrapper" :class="{playing: playingVoiceId === msg.messageId}">
|
|
|
- <image
|
|
|
- class="voice-icon"
|
|
|
- :src="msg.fromUserId === userId ? 'http://115.190.125.125:9000/static-images/%E6%88%91%E6%96%B9%E8%AF%AD%E9%9F%B3%E6%B6%88%E6%81%AF' : 'http://115.190.125.125:9000/static-images/%E5%AF%B9%E6%96%B9%E8%AF%AD%E9%9F%B3%E6%B6%88%E6%81%AF'"
|
|
|
- mode="aspectFit"></image>
|
|
|
+ <image class="voice-icon" src="/static/voice-icon.png" mode="aspectFit"></image>
|
|
|
</view>
|
|
|
<!-- 暂停后的继续播放按钮 -->
|
|
|
<view
|
|
|
@@ -267,7 +264,6 @@
|
|
|
<script>
|
|
|
import timManager from '@/utils/tim-manager.js';
|
|
|
import TIM from 'tim-wx-sdk';
|
|
|
-import presenceManager from '@/utils/presence-manager.js';
|
|
|
|
|
|
export default {
|
|
|
data() {
|
|
|
@@ -322,9 +318,7 @@ export default {
|
|
|
voiceVolume: 0.3, // 录音音量(0-1),控制波形高度
|
|
|
playingVoiceId: null, // 当前播放的语音消息ID
|
|
|
pausedVoiceId: null, // 当前暂停的语音消息ID
|
|
|
- currentAudioContext: null, // 当前音频上下文
|
|
|
- onlineStatusPollingTimer: null, // 在线状态轮询定时器
|
|
|
- voiceRecordCancelled: false // 录音是否已被取消(防止权限允许后自动恢复)
|
|
|
+ currentAudioContext: null // 当前音频上下文
|
|
|
};
|
|
|
},
|
|
|
|
|
|
@@ -421,11 +415,16 @@ export default {
|
|
|
// 监听新消息
|
|
|
this.listenMessages();
|
|
|
|
|
|
- // 初始化在线状态监听
|
|
|
- this.initPresence();
|
|
|
-
|
|
|
- // 发送已读回执(标记对方发来的消息为已读)
|
|
|
- this.sendReadReceipt();
|
|
|
+ // 如果有预设消息,自动发送
|
|
|
+ if (options.message) {
|
|
|
+ const message = decodeURIComponent(options.message);
|
|
|
+ console.log('检测到预设消息,准备自动发送:', message);
|
|
|
+ // 等待一下再发送,确保TIM已经初始化完成
|
|
|
+ setTimeout(() => {
|
|
|
+ this.inputText = message;
|
|
|
+ this.sendTextMessage();
|
|
|
+ }, 1500);
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
onUnload() {
|
|
|
@@ -438,9 +437,6 @@ export default {
|
|
|
timManager.tim.off(TIM.EVENT.MESSAGE_STATUS_CHANGED, this.handleStatusChange);
|
|
|
}
|
|
|
*/
|
|
|
-
|
|
|
- // 清理在线状态监听
|
|
|
- this.cleanupPresence();
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
@@ -545,7 +541,7 @@ export default {
|
|
|
|
|
|
// 导入当前用户(确保userId是字符串)
|
|
|
const currentUserRes = await uni.request({
|
|
|
- url: 'http://localhost:8083/api/im/importUser',
|
|
|
+ url: 'http://localhost:1004/api/im/importUser',
|
|
|
method: 'POST',
|
|
|
data: {
|
|
|
userId: String(this.userId),
|
|
|
@@ -560,7 +556,7 @@ export default {
|
|
|
|
|
|
// 导入目标用户(确保userId是字符串)
|
|
|
const targetUserRes = await uni.request({
|
|
|
- url: 'http://localhost:8083/api/im/importUser',
|
|
|
+ url: 'http://localhost:1004/api/im/importUser',
|
|
|
method: 'POST',
|
|
|
data: {
|
|
|
userId: String(this.targetUserId),
|
|
|
@@ -585,7 +581,7 @@ export default {
|
|
|
async getUserSig() {
|
|
|
try {
|
|
|
const [err, res] = await uni.request({
|
|
|
- url: 'http://localhost:8083/api/im/getUserSig',
|
|
|
+ url: 'http://localhost:1004/api/im/getUserSig',
|
|
|
method: 'GET',
|
|
|
data: {
|
|
|
userId: this.userId
|
|
|
@@ -762,65 +758,6 @@ export default {
|
|
|
*/
|
|
|
},
|
|
|
|
|
|
- /**
|
|
|
- * 发送已读回执
|
|
|
- */
|
|
|
- sendReadReceipt() {
|
|
|
- try {
|
|
|
- console.log('📨 发送已读回执给用户:', this.targetUserId);
|
|
|
-
|
|
|
- // 通过WebSocket发送已读回执
|
|
|
- const message = {
|
|
|
- type: 'READ_RECEIPT', // 已读回执类型
|
|
|
- fromUserId: parseInt(this.userId),
|
|
|
- toUserId: parseInt(this.targetUserId),
|
|
|
- timestamp: Date.now()
|
|
|
- };
|
|
|
-
|
|
|
- // 使用presenceManager的WebSocket发送
|
|
|
- const presenceManager = require('@/utils/presence-manager.js').default;
|
|
|
- if (presenceManager.isConnected) {
|
|
|
- presenceManager.sendMessage(message);
|
|
|
- console.log('✅ 已读回执发送成功');
|
|
|
- } else {
|
|
|
- console.warn('⚠️ WebSocket未连接,无法发送已读回执');
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('❌ 发送已读回执失败:', error);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 监听已读回执
|
|
|
- */
|
|
|
- listenReadReceipt() {
|
|
|
- // 在WebSocket消息处理中添加已读回执的监听
|
|
|
- // 这个方法会在initPresence中被调用
|
|
|
- console.log('👂 开始监听已读回执');
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理已读回执
|
|
|
- */
|
|
|
- handleReadReceipt(data) {
|
|
|
- try {
|
|
|
- console.log('📬 收到已读回执:', data);
|
|
|
-
|
|
|
- // 更新本地消息状态为已读
|
|
|
- this.messages.forEach((msg, index) => {
|
|
|
- // 只更新自己发送给对方的消息
|
|
|
- if (msg.fromUserId === this.userId &&
|
|
|
- msg.toUserId === this.targetUserId &&
|
|
|
- msg.sendStatus === 2) { // 只更新已送达的消息
|
|
|
- this.$set(this.messages[index], 'sendStatus', 3); // 更新为已读
|
|
|
- console.log(`✅ 消息 ${msg.messageId} 状态更新为已读`);
|
|
|
- }
|
|
|
- });
|
|
|
- } catch (error) {
|
|
|
- console.error('❌ 处理已读回执失败:', error);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
/**
|
|
|
* 转换消息格式
|
|
|
*/
|
|
|
@@ -1139,7 +1076,7 @@ export default {
|
|
|
|
|
|
// 调用后端同步接口
|
|
|
const res = await uni.request({
|
|
|
- url: 'http://localhost:8083/api/chat/syncTIMMessage',
|
|
|
+ url: 'http://localhost:1004/api/chat/syncTIMMessage',
|
|
|
method: 'POST',
|
|
|
data: syncData,
|
|
|
header: {
|
|
|
@@ -1504,128 +1441,6 @@ export default {
|
|
|
this.inputType = this.inputType === 'text' ? 'voice' : 'text';
|
|
|
},
|
|
|
|
|
|
- /**
|
|
|
- * 初始化在线状态监听
|
|
|
- */
|
|
|
- async initPresence() {
|
|
|
- console.log('🔌 初始化在线状态监听');
|
|
|
- console.log(' - 当前用户ID:', this.userId);
|
|
|
- console.log(' - 对方用户ID:', this.targetUserId);
|
|
|
-
|
|
|
- // 1. 首先通过HTTP API查询对方的在线状态(立即显示)
|
|
|
- try {
|
|
|
- const isOnline = await presenceManager.queryOnlineStatus(this.targetUserId);
|
|
|
- this.isTargetOnline = isOnline;
|
|
|
- console.log(' - HTTP查询初始在线状态:', this.isTargetOnline);
|
|
|
- } catch (error) {
|
|
|
- console.error('❌ HTTP查询在线状态失败:', error);
|
|
|
- this.isTargetOnline = false;
|
|
|
- }
|
|
|
-
|
|
|
- // 2. 连接WebSocket(如果未连接)
|
|
|
- if (!presenceManager.getConnectionStatus()) {
|
|
|
- presenceManager.connect(this.userId);
|
|
|
-
|
|
|
- // 等待WebSocket连接建立
|
|
|
- await this.waitForWebSocketConnection();
|
|
|
- }
|
|
|
-
|
|
|
- // 3. 监听对方用户的在线状态变化
|
|
|
- this.handleStatusChange = (status) => {
|
|
|
- console.log(`👤 对方用户 ${this.targetUserId} 状态变更: ${status}`);
|
|
|
- this.isTargetOnline = (status === 'online');
|
|
|
- console.log(' - 更新后的在线状态:', this.isTargetOnline);
|
|
|
- };
|
|
|
-
|
|
|
- presenceManager.onStatusChange(this.targetUserId, this.handleStatusChange);
|
|
|
- console.log('✅ 已订阅对方用户状态');
|
|
|
-
|
|
|
- // 4. 监听已读回执(通过WebSocket)
|
|
|
- // 注册已读回执的回调
|
|
|
- this.readReceiptCallback = (data) => {
|
|
|
- if (data.type === 'READ_RECEIPT' && data.fromUserId == this.targetUserId) {
|
|
|
- console.log('📬 收到已读回执:', data);
|
|
|
- this.handleReadReceipt(data);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- // 将回调添加到presenceManager的消息处理中
|
|
|
- if (!presenceManager.messageCallbacks) {
|
|
|
- presenceManager.messageCallbacks = [];
|
|
|
- }
|
|
|
- presenceManager.messageCallbacks.push(this.readReceiptCallback);
|
|
|
- console.log('✅ 已监听已读回执');
|
|
|
-
|
|
|
- // 4. 定期轮询在线状态(作为补充,每30秒查询一次)
|
|
|
- this.onlineStatusPollingTimer = setInterval(async () => {
|
|
|
- try {
|
|
|
- const isOnline = await presenceManager.queryOnlineStatus(this.targetUserId);
|
|
|
- if (this.isTargetOnline !== isOnline) {
|
|
|
- console.log(`🔄 轮询检测到状态变化: ${this.isTargetOnline} -> ${isOnline}`);
|
|
|
- this.isTargetOnline = isOnline;
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('❌ 轮询查询在线状态失败:', error);
|
|
|
- }
|
|
|
- }, 30000); // 30秒轮询一次
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 等待WebSocket连接建立
|
|
|
- */
|
|
|
- async waitForWebSocketConnection() {
|
|
|
- return new Promise((resolve) => {
|
|
|
- const maxWaitTime = 5000; // 最多等待5秒
|
|
|
- const startTime = Date.now();
|
|
|
-
|
|
|
- const checkConnection = setInterval(() => {
|
|
|
- if (presenceManager.getConnectionStatus()) {
|
|
|
- console.log('✅ WebSocket已连接');
|
|
|
- clearInterval(checkConnection);
|
|
|
- resolve();
|
|
|
- } else if (Date.now() - startTime > maxWaitTime) {
|
|
|
- console.log('⚠️ WebSocket连接超时,继续使用HTTP轮询');
|
|
|
- clearInterval(checkConnection);
|
|
|
- resolve();
|
|
|
- }
|
|
|
- }, 100);
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 清理在线状态监听
|
|
|
- */
|
|
|
- cleanupPresence() {
|
|
|
- console.log('🔌 清理在线状态监听');
|
|
|
-
|
|
|
- const presenceManager = require('@/utils/presence-manager.js').default;
|
|
|
-
|
|
|
- // 清除轮询定时器
|
|
|
- if (this.onlineStatusPollingTimer) {
|
|
|
- clearInterval(this.onlineStatusPollingTimer);
|
|
|
- this.onlineStatusPollingTimer = null;
|
|
|
- }
|
|
|
-
|
|
|
- // 移除在线状态监听
|
|
|
- if (this.handleStatusChange) {
|
|
|
- presenceManager.offStatusChange(this.targetUserId, this.handleStatusChange);
|
|
|
- this.handleStatusChange = null;
|
|
|
- }
|
|
|
-
|
|
|
- // 移除已读回执回调
|
|
|
- if (this.readReceiptCallback && presenceManager.messageCallbacks) {
|
|
|
- const index = presenceManager.messageCallbacks.indexOf(this.readReceiptCallback);
|
|
|
- if (index > -1) {
|
|
|
- presenceManager.messageCallbacks.splice(index, 1);
|
|
|
- console.log('✅ 已移除已读回执监听');
|
|
|
- }
|
|
|
- this.readReceiptCallback = null;
|
|
|
- }
|
|
|
-
|
|
|
- // 注意:不要断开WebSocket连接,因为其他页面可能还在使用
|
|
|
- // presenceManager.disconnect();
|
|
|
- },
|
|
|
-
|
|
|
/**
|
|
|
* 开始录音
|
|
|
*/
|
|
|
@@ -1652,18 +1467,7 @@ export default {
|
|
|
|
|
|
// 录音开始
|
|
|
this.recorderManager.onStart(() => {
|
|
|
- console.log('✅ 录音开始回调触发, voiceRecordCancelled:', this.voiceRecordCancelled);
|
|
|
-
|
|
|
- // 关键修复:如果录音已被取消,不再恢复录音状态
|
|
|
- if (this.voiceRecordCancelled) {
|
|
|
- console.log('⚠️ 录音已被取消,忽略onStart回调');
|
|
|
- // 立即停止录音
|
|
|
- if (this.recorderManager) {
|
|
|
- this.recorderManager.stop();
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
+ console.log('✅ 录音开始回调触发');
|
|
|
this.isRecording = true;
|
|
|
this.showVoiceRecording = true;
|
|
|
this.voiceStartTime = Date.now();
|
|
|
@@ -1726,7 +1530,6 @@ export default {
|
|
|
// 立即设置录音状态(不等待onStart回调)
|
|
|
this.isRecording = true;
|
|
|
this.showVoiceRecording = true;
|
|
|
- this.voiceRecordCancelled = false; // 重置取消标志
|
|
|
this.voiceStartTime = Date.now();
|
|
|
this.voiceRecordingTime = 0;
|
|
|
this.voiceVolume = 0.3;
|
|
|
@@ -1838,9 +1641,6 @@ export default {
|
|
|
cancelVoiceRecord() {
|
|
|
console.log('❌ 取消录音, voiceCanceling:', this.voiceCanceling);
|
|
|
|
|
|
- // 关键修复:标记录音已被取消,防止onStart回调恢复录音
|
|
|
- this.voiceRecordCancelled = true;
|
|
|
-
|
|
|
// 清除计时器
|
|
|
if (this.voiceRecordingTimer) {
|
|
|
clearInterval(this.voiceRecordingTimer);
|
|
|
@@ -1853,22 +1653,15 @@ export default {
|
|
|
this.voiceCanceling = true;
|
|
|
}
|
|
|
|
|
|
- // 立即隐藏录音UI
|
|
|
- this.isRecording = false;
|
|
|
- this.showVoiceRecording = false;
|
|
|
-
|
|
|
- if (this.recorderManager) {
|
|
|
- // 尝试停止录音(如果已经开始)
|
|
|
- try {
|
|
|
- this.recorderManager.stop();
|
|
|
- } catch (err) {
|
|
|
- console.log('⚠️ 停止录音失败(可能还未开始):', err);
|
|
|
- }
|
|
|
+ if (this.recorderManager && this.isRecording) {
|
|
|
+ this.recorderManager.stop(); // 这会触发onStop回调
|
|
|
+ } else {
|
|
|
+ // 如果没有在录音,直接重置状态
|
|
|
+ this.isRecording = false;
|
|
|
+ this.showVoiceRecording = false;
|
|
|
+ this.voiceCanceling = false;
|
|
|
}
|
|
|
|
|
|
- // 重置取消状态
|
|
|
- this.voiceCanceling = false;
|
|
|
-
|
|
|
uni.showToast({
|
|
|
title: '已取消录音',
|
|
|
icon: 'none'
|
|
|
@@ -1945,7 +1738,7 @@ export default {
|
|
|
|
|
|
// 使用uni.uploadFile上传到后端MinIO接口
|
|
|
const [err, res] = await uni.uploadFile({
|
|
|
- url: 'http://localhost:8083/api/voice/upload',
|
|
|
+ url: 'http://localhost:1004/api/voice/upload',
|
|
|
filePath: this.voiceTempPath,
|
|
|
name: 'file',
|
|
|
header: {
|
|
|
@@ -2150,7 +1943,7 @@ export default {
|
|
|
async getUserMessageLimit() {
|
|
|
try {
|
|
|
const [err, res] = await uni.request({
|
|
|
- url: 'http://localhost:8083/api/chat/getUserMessageLimit',
|
|
|
+ url: 'http://localhost:1004/api/chat/getUserMessageLimit',
|
|
|
method: 'GET',
|
|
|
data: {
|
|
|
userId: this.userId ,// 已在onLoad中初始化的当前用户ID
|