测试消息发送,修复已知问题

This commit is contained in:
cc 2025-04-03 13:21:01 +08:00
parent 5d78bb86a3
commit 582343c437
6 changed files with 5226 additions and 171 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,7 @@
"API_TYPE": "stageMode" "API_TYPE": "stageMode"
} }
], ],
"BUILD_MODE": "debug", "BUILD_MODE": "debug"
"USE_NORMALIZED_OHMURL": true
}, },
"HVIGOR": { "HVIGOR": {
"IS_INCREMENTAL": true, "IS_INCREMENTAL": true,
@ -16,19 +15,19 @@
"IS_HVIGORFILE_TYPE_CHECK": false, "IS_HVIGORFILE_TYPE_CHECK": false,
"TASK_TIME": { "TASK_TIME": {
"1043bfc77febe75fafec0c4309faccf1": { "1043bfc77febe75fafec0c4309faccf1": {
"ConfigureCmake": 144333, "ConfigureCmake": 198417,
"PreCheckSyscap": 397584, "PreCheckSyscap": 366291,
"ProcessIntegratedHsp": 716042, "ProcessIntegratedHsp": 7834000,
"BuildNativeWithCmake": 153583, "BuildNativeWithCmake": 2433792,
"SyscapTransform": 1068125, "SyscapTransform": 4341084,
"BuildNativeWithNinja": 633209, "BuildNativeWithNinja": 2475333,
"BuildJS": 912000, "BuildJS": 2653334,
"SignHap": 450709, "SignHap": 1709458,
"CollectDebugSymbol": 1302500, "CollectDebugSymbol": 3067292,
"assembleHap": 71000 "assembleHap": 169292
} }
}, },
"TOTAL_TIME": 214114959, "TOTAL_TIME": 748077750,
"BUILD_ID": "202504022245222400" "BUILD_ID": "202504031317266900"
} }
} }

View File

@ -247,7 +247,7 @@ export type EventCallback = (data: EventData) => void;
// API配置 // API配置
const CHANNEL_API_CONFIG: ApiConfig = { const CHANNEL_API_CONFIG: ApiConfig = {
baseUrl: 'http://139.155.155.67:5243', // Change this to your computer's IP address baseUrl: 'http://139.155.155.67:5243', // Change this to your computer's IP address
pollInterval: 2000, // 轮询间隔(毫秒) pollInterval: 1000, // 轮询间隔(毫秒) - 降低到1秒以提高同步速度
timeout: 10000 // 请求超时(毫秒) timeout: 10000 // 请求超时(毫秒)
}; };
@ -439,12 +439,20 @@ export class ClassRoomService {
// 将消息添加到当前会话 // 将消息添加到当前会话
if (this.currentSession) { if (this.currentSession) {
messages.forEach(message => { messages.forEach(message => {
// 避免添加自己发送的消息(已在本地添加) // 避免添加自己发送的消息通过发送者ID比较而不是消息ID
if (message.senderId !== settingsService.getCurrentAccount()) {
// 检查消息是否已存在(防止重复)
const isDuplicate = this.currentSession?.messages.some(m => m.id === message.id); const isDuplicate = this.currentSession?.messages.some(m => m.id === message.id);
if (!isDuplicate) { if (!isDuplicate) {
// 添加到消息列表
this.currentSession?.messages.push(message); this.currentSession?.messages.push(message);
// 确保消息被添加后立即通知UI // 确保消息被添加后立即通知UI
this.notifyEvent(WebSocketEventType.SEND_MESSAGE, message); this.notifyEvent(WebSocketEventType.SEND_MESSAGE, message);
// 记录接收到的新消息(来自他人)
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO,
`收到新消息 - ID: ${message.id}, 发送者: ${message.senderName}, 内容: ${message.content}`);
}
} }
}); });
} }
@ -714,11 +722,15 @@ export class ClassRoomService {
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `[DEBUG] Server response received - Success: ${response.success}, Message: ${response.message || 'No message'}`); logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `[DEBUG] Server response received - Success: ${response.success}, Message: ${response.message || 'No message'}`);
if (response.success) { if (response.success) {
// 添加到当前会话 // 不再将消息添加到currentSession因为UI层已经添加了本地消息
this.currentSession.messages.push(message); // (已删除): this.currentSession.messages.push(message);
// 不需要再次通知UI因为UI层已经添加了本地消息
// (已删除): this.notifyEvent(WebSocketEventType.SEND_MESSAGE, message);
// 只添加到lastMessageId确保轮询时不重复获取
this.lastMessageId = message.id;
// 通知消息发送
this.notifyEvent(WebSocketEventType.SEND_MESSAGE, message);
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `Message sent successfully: ${message.id}`); logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `Message sent successfully: ${message.id}`);
return true; return true;
@ -941,6 +953,67 @@ export class ClassRoomService {
}); });
} }
} }
// 获取连接状态
public isConnected(): boolean {
return this.connected;
}
// 重新连接方法
public async reconnect(): Promise<boolean> {
// 先断开连接
this.stopPolling();
// 记录重连尝试
logManager.info(LogCategory.NETWORK, LogEventType.SYSTEM_INFO,
`尝试重新连接 - 当前状态: ${this.connected}, 课堂码: ${this.currentClassCode}`);
// 保存当前课堂码
const classCode = this.currentClassCode;
if (!classCode) {
logManager.error(LogCategory.NETWORK, `重连失败: 无课堂码`);
return false;
}
// 重置连接状态
this.connected = false;
// 尝试重新连接
try {
// 验证服务器连接
const response = await this.getRequest('ping');
if (response.success) {
this.connected = true;
// 重新获取课堂数据
const sessionResponse = await this.getRequest(`session/${classCode}`);
if (sessionResponse.success && sessionResponse.data) {
this.currentSession = sessionResponse.data as ClassSessionModel;
this.currentClassCode = classCode;
// 重新开始轮询
this.startPolling();
const connectionEvent: EventConnection = { status: 'reconnected' };
this.notifyEvent('connection', connectionEvent);
logManager.info(LogCategory.NETWORK, LogEventType.SYSTEM_INFO, '课堂服务重连成功');
return true;
} else {
logManager.error(LogCategory.NETWORK, `重新获取课堂数据失败: ${sessionResponse.message}`);
return false;
}
} else {
logManager.error(LogCategory.NETWORK, `重连失败: ${response.message}`);
return false;
}
} catch (error) {
logManager.error(LogCategory.NETWORK, `重连出错: ${error}`);
return false;
}
}
} }
// 导出单例实例 // 导出单例实例

View File

@ -156,7 +156,8 @@ export class LogManager {
new VersionLogItem("1.1.0", "2025-3-31", ["添加用户信息编辑功能", "增加版本日志功能", "改进主题颜色切换效果","添加公告栏","修复已知问题"]), new VersionLogItem("1.1.0", "2025-3-31", ["添加用户信息编辑功能", "增加版本日志功能", "改进主题颜色切换效果","添加公告栏","修复已知问题"]),
new VersionLogItem("1.1.5","2025-4-1",["增加远程测试数据库","优化登录页面","优化用户信息设置","增加退出按钮"]), new VersionLogItem("1.1.5","2025-4-1",["增加远程测试数据库","优化登录页面","优化用户信息设置","增加退出按钮"]),
new VersionLogItem("1.1.7","2025-4-1",["添加测试按钮","修复已知问题"]), new VersionLogItem("1.1.7","2025-4-1",["添加测试按钮","修复已知问题"]),
new VersionLogItem("1.2.0","2025-4-2",["添加课堂功能","修改上课页面逻辑"]) new VersionLogItem("1.2.0","2025-4-2",["添加课堂功能","修改上课页面逻辑"]),
new VersionLogItem("1.2.0 beta","2025-4-3",["测试消息发送","修复已知问题"])
]; ];
} }

View File

@ -183,14 +183,17 @@ struct ClassLivePage {
// 检查消息是否已经存在(防止重复) // 检查消息是否已经存在(防止重复)
const existingMessage = this.messages.find(m => m.id === message.id); const existingMessage = this.messages.find(m => m.id === message.id);
if (!existingMessage) { if (!existingMessage) {
// 输出调试信息
console.info(`收到新消息事件: ID=${message.id}, 发送者=${message.senderName}, 内容=${message.content}`);
// 使用新数组方式更新消息列表,确保 UI 刷新 // 使用新数组方式更新消息列表,确保 UI 刷新
this.messages = [...this.messages, message]; this.messages = [...this.messages, message];
// 新消息到达时自动滚动到底部 // 新消息到达时自动滚动到底部
this.scrollToLatestMessage(); this.scrollToLatestMessage();
} else {
// 添加日志以便调试 // 记录重复消息(不常见,但可能发生)
console.info(`收到新消息: ${message.content} from ${message.senderName}`); console.info(`收到重复消息,已忽略: ID=${message.id}`);
} }
} }
}; };
@ -398,6 +401,12 @@ struct ClassLivePage {
} }
try { try {
// 防止重复点击、重复发送
if (this.isLoading) {
return;
}
this.isLoading = true;
// 保存消息内容,因为后面会清空输入框 // 保存消息内容,因为后面会清空输入框
const messageContent = this.messageText.trim(); const messageContent = this.messageText.trim();
@ -409,12 +418,16 @@ struct ClassLivePage {
messageContent messageContent
); );
// 先在本地添加消息,让用户立即看到 // 保存消息ID以便后续可以在发送失败时移除
this.messages = [...this.messages, localMessage]; const localMessageId = localMessage.id;
// 清空消息输入框 // 清空消息输入框 - 提前清空避免用户重复点击
this.messageText = ''; this.messageText = '';
// 先在本地添加消息,让用户立即看到
console.info(`添加本地消息: ID=${localMessageId}, 内容=${messageContent}`);
this.messages = [...this.messages, localMessage];
// 自动滚动到最新消息 // 自动滚动到最新消息
this.scrollToLatestMessage(); this.scrollToLatestMessage();
@ -422,13 +435,17 @@ struct ClassLivePage {
const result = await this.classRoomService.sendMessage(messageContent); const result = await this.classRoomService.sendMessage(messageContent);
if (!result) { if (!result) {
// 如果发送失败,显示错误提示 // 如果发送失败,从消息列表中移除本地消息
console.error(`消息发送失败,移除本地消息: ${localMessageId}`);
this.messages = this.messages.filter(msg => msg.id !== localMessageId);
// 显示错误提示
promptAction.showToast({ promptAction.showToast({
message: '消息发送失败,请重试', message: '消息发送失败,请重试',
duration: 2000 duration: 2000
}); });
} else {
// 可以选择在此处将刚才添加的本地消息移除,或者标记为发送失败 console.info(`消息发送成功: ${localMessageId}`);
} }
} catch (error) { } catch (error) {
// 处理错误 // 处理错误
@ -438,6 +455,8 @@ struct ClassLivePage {
message: '消息发送失败,请重试', message: '消息发送失败,请重试',
duration: 2000 duration: 2000
}); });
} finally {
this.isLoading = false;
} }
} }
@ -569,13 +588,8 @@ struct ClassLivePage {
try { try {
const result = await this.classRoomService.endClassSession(); const result = await this.classRoomService.endClassSession();
if (result) { if (!result) {
// 返回上课页面 - 使用明确的导航而不是back() // 只在失败时显示错误提示,成功时不跳转,等待服务器通知
router.pushUrl({
url: 'pages/ClassPage'
} as RouterUrlOptions);
} else {
// 显示错误提示
const primaryButton: DialogButton = { const primaryButton: DialogButton = {
value: '确定', value: '确定',
action: () => {} action: () => {}
@ -588,6 +602,7 @@ struct ClassLivePage {
}; };
AlertDialog.show(alertConfig); AlertDialog.show(alertConfig);
} }
// 成功时不做任何操作等待endClassCallback处理跳转
} catch (error) { } catch (error) {
// 显示错误提示 // 显示错误提示
const primaryButton: DialogButton = { const primaryButton: DialogButton = {
@ -742,6 +757,20 @@ struct ClassLivePage {
.fontColor(Color.White) .fontColor(Color.White)
} }
Row() {
// 添加连接检查按钮
Button("检查")
.fontSize(14)
.fontWeight(FontWeight.Medium)
.backgroundColor('rgba(255,255,255,0.2)')
.borderRadius(16)
.fontColor(Color.White)
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
.margin({ right: 8 })
.onClick(() => {
this.checkConnectionStatus();
})
// 教师端显示结束课堂按钮 // 教师端显示结束课堂按钮
if (this.mode === ClassLiveMode.TEACHER) { if (this.mode === ClassLiveMode.TEACHER) {
Button("结束课堂") Button("结束课堂")
@ -756,13 +785,16 @@ struct ClassLivePage {
}) })
} }
} }
}
.width('100%') .width('100%')
.backgroundColor(this.settings.themeColor) .backgroundColor(this.settings.themeColor)
.height(60) .height(60)
.justifyContent(FlexAlign.SpaceBetween) .justifyContent(FlexAlign.SpaceBetween)
.padding({ left: 16, right: 16 }) .padding({ left: 16, right: 16 })
// 课堂内容区域,包含聊天功能 // 使用Flex布局来确保页面元素适应不同屏幕尺寸
Flex({ direction: FlexDirection.Column }) {
// 顶部固定区域(课堂信息和通知)
Column() { Column() {
// 课堂信息区域 // 课堂信息区域
Column() { Column() {
@ -781,7 +813,7 @@ struct ClassLivePage {
.padding(10) .padding(10)
.backgroundColor('#f5f5f5') .backgroundColor('#f5f5f5')
.borderRadius(8) .borderRadius(8)
.margin({ top: 10, bottom: 10 }) .margin({ bottom: 10 })
// 通知消息 // 通知消息
if (this.currentQuestion) { if (this.currentQuestion) {
@ -808,8 +840,10 @@ struct ClassLivePage {
.borderRadius(8) .borderRadius(8)
.margin({ bottom: 10 }) .margin({ bottom: 10 })
} }
}
.width('100%')
// 聊天历史记录区域 // 聊天历史记录区域(可伸缩)
Column() { Column() {
Text("聊天记录") Text("聊天记录")
.fontSize(18) .fontSize(18)
@ -871,9 +905,36 @@ struct ClassLivePage {
this.scrollToLatestMessage(); this.scrollToLatestMessage();
}) })
} }
.flexGrow(1) // 使聊天记录区域占用所有可用空间
.width('100%') .width('100%')
.layoutWeight(1)
.margin({ bottom: 10 }) // 底部固定区域 (错误消息、加载状态和输入框)
Column() {
// 错误消息和加载状态
if (this.errorMessage) {
Text(this.errorMessage)
.fontSize(14)
.fontColor('#F56C6C')
.width('100%')
.textAlign(TextAlign.Center)
.margin({ top: 8, bottom: 8 })
}
if (this.isLoading) {
Row() {
LoadingProgress()
.width(24)
.height(24)
.margin({ right: 10 })
Text("处理中...")
.fontSize(14)
.fontColor('#666')
}
.justifyContent(FlexAlign.Center)
.width('100%')
.margin({ top: 8, bottom: 8 })
}
// 消息输入区域 // 消息输入区域
Row() { Row() {
@ -898,36 +959,12 @@ struct ClassLivePage {
}) })
} }
.width('100%') .width('100%')
.margin({ top: 10 }) .padding({ top: 8, bottom: 8 })
// 错误消息和加载状态
if (this.errorMessage) {
Text(this.errorMessage)
.fontSize(14)
.fontColor('#F56C6C')
.width('100%')
.textAlign(TextAlign.Center)
.margin({ top: 10 })
}
if (this.isLoading) {
Row() {
LoadingProgress()
.width(24)
.height(24)
.margin({ right: 10 })
Text("处理中...")
.fontSize(14)
.fontColor('#666')
}
.justifyContent(FlexAlign.Center)
.width('100%')
.margin({ top: 10 })
}
} }
.width('100%') .width('100%')
.height('100%') }
.width('100%')
.layoutWeight(1) // 确保Flex容器占据全部可用空间
.padding(16) .padding(16)
} }
.width('100%') .width('100%')
@ -1355,52 +1392,65 @@ struct ClassLivePage {
ForEach(this.currentQuestion.options, (option: QuestionOption, index: number) => { ForEach(this.currentQuestion.options, (option: QuestionOption, index: number) => {
Column() { Column() {
Row() { Row() {
Text(`选项 ${String.fromCharCode(65 + index)}: ${option.content}`) Text(`选项 ${String.fromCharCode(65 + index)}`)
.fontSize(16) .fontSize(16)
.fontWeight(index === this.currentQuestion?.correctOption ? FontWeight.Bold : FontWeight.Normal) .fontWeight(FontWeight.Medium)
.fontColor(index === this.currentQuestion?.correctOption ? '#67C23A' : '#333')
}
.width('100%')
.margin({ bottom: 4 })
Row() { Text(`${this.getOptionStats(index).count}票`)
// 进度条 .fontSize(16)
Column() { .fontWeight(FontWeight.Medium)
Stack({ alignContent: Alignment.Start }) {
Row()
.width('100%')
.height(20)
.backgroundColor('#f0f0f0')
.borderRadius(10)
Row() Text(`${this.getOptionStats(index).percentage}%`)
.width(`${this.getOptionStats(index).percentage}%`) .fontSize(16)
.height(20) .fontColor(this.getOptionStats(index).percentage > 50 ? '#67C23A' : '#F56C6C')
.backgroundColor(index === this.currentQuestion?.correctOption ? '#67C23A' : '#409EFF') .fontWeight(FontWeight.Medium)
.borderRadius(10)
}
}
.layoutWeight(1)
// 百分比和人数
Text(`${this.getOptionStats(index).percentage}% (${this.getOptionStats(index).count}人)`)
.fontSize(14)
.fontColor('#666')
.margin({ left: 8 })
.width(100)
.textAlign(TextAlign.End)
} }
.width('100%') .width('100%')
}
.width('100%')
.margin({ bottom: 12 })
.padding(10) .padding(10)
.borderRadius(8) .borderRadius(8)
.backgroundColor(index === this.currentQuestion?.correctOption ? '#f0f9eb' : '#f9f9f9') .backgroundColor('#f5f5f5')
.margin({ bottom: 8 })
}
}) })
} }
} }
.width('100%') }
// 增加检查连接状态方法
private checkConnectionStatus() {
try {
const connectionStatus = this.classRoomService.isConnected() ? '已连接' : '未连接';
const messageCount = this.messages.length;
const lastMessageId = this.messages.length > 0 ? this.messages[this.messages.length - 1].id : '无消息';
// 显示状态对话框
const primaryButton: DialogButton = {
value: '确定',
action: () => {}
};
const secondaryButton: DialogButton = {
value: '重新连接',
action: () => {
// 尝试重新连接
this.classRoomService.reconnect();
}
};
const alertConfig: AlertDialogConfig = {
title: '连接状态检查',
message: `连接状态: ${connectionStatus}\n消息数量: ${messageCount}\n最新消息ID: ${lastMessageId}`,
primaryButton: primaryButton,
secondaryButton: secondaryButton
};
AlertDialog.show(alertConfig);
// 记录日志
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO,
`连接状态: ${connectionStatus}, 消息数量: ${messageCount}, 最新消息ID: ${lastMessageId}`);
} catch (error) {
console.error(`检查连接状态出错: ${error}`);
}
} }
// 题目统计窗口 // 题目统计窗口