更新说明文档,添加日志输出
This commit is contained in:
parent
582343c437
commit
ea6a10a588
2
.hvigor/cache/file-cache.json
vendored
2
.hvigor/cache/file-cache.json
vendored
File diff suppressed because one or more lines are too long
2
.hvigor/cache/task-cache.json
vendored
2
.hvigor/cache/task-cache.json
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,10 @@
|
|||||||
"MODULES": [
|
"MODULES": [
|
||||||
{
|
{
|
||||||
"MODULE_NAME": "1043bfc77febe75fafec0c4309faccf1",
|
"MODULE_NAME": "1043bfc77febe75fafec0c4309faccf1",
|
||||||
"API_TYPE": "stageMode"
|
"API_TYPE": "stageMode",
|
||||||
|
"INCREMENTAL_TASKS": {
|
||||||
|
"COMPILE_ARKTS": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"BUILD_MODE": "debug"
|
"BUILD_MODE": "debug"
|
||||||
@ -15,19 +18,21 @@
|
|||||||
"IS_HVIGORFILE_TYPE_CHECK": false,
|
"IS_HVIGORFILE_TYPE_CHECK": false,
|
||||||
"TASK_TIME": {
|
"TASK_TIME": {
|
||||||
"1043bfc77febe75fafec0c4309faccf1": {
|
"1043bfc77febe75fafec0c4309faccf1": {
|
||||||
"ConfigureCmake": 198417,
|
"ConfigureCmake": 856416,
|
||||||
"PreCheckSyscap": 366291,
|
"PreCheckSyscap": 632458,
|
||||||
"ProcessIntegratedHsp": 7834000,
|
"ProcessIntegratedHsp": 1418083,
|
||||||
"BuildNativeWithCmake": 2433792,
|
"BuildNativeWithCmake": 273041,
|
||||||
"SyscapTransform": 4341084,
|
"SyscapTransform": 36040791,
|
||||||
"BuildNativeWithNinja": 2475333,
|
"BuildNativeWithNinja": 1378666,
|
||||||
"BuildJS": 2653334,
|
"BuildJS": 3533375,
|
||||||
"SignHap": 1709458,
|
"CompileArkTS": 31907849083,
|
||||||
"CollectDebugSymbol": 3067292,
|
"PackageHap": 827841167,
|
||||||
"assembleHap": 169292
|
"SignHap": 5034625,
|
||||||
|
"CollectDebugSymbol": 3993000,
|
||||||
|
"assembleHap": 304292
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"TOTAL_TIME": 748077750,
|
"BUILD_ID": "202504040929560100",
|
||||||
"BUILD_ID": "202504031317266900"
|
"TOTAL_TIME": 34679640584
|
||||||
}
|
}
|
||||||
}
|
}
|
178
README.md
178
README.md
@ -1,64 +1,144 @@
|
|||||||
# ClassMG Communication Server
|
# ClassMG - Interactive Classroom Management System
|
||||||
|
|
||||||
This server enables real-time communication between multiple instances of the ClassMG application running on different devices. It provides a simple HTTP API for message passing, classroom management, and question handling.
|
[English (Current)](README.md) | [中文版](README_CN.md)
|
||||||
|
|
||||||
## Prerequisites
|
## Overview
|
||||||
|
|
||||||
|
ClassMG is a comprehensive classroom management application designed for interactive teaching and learning. The system enables real-time communication between teachers and students, interactive question sessions, and immediate feedback mechanisms, all within a unified digital classroom environment.
|
||||||
|
|
||||||
|
## System Architecture
|
||||||
|
|
||||||
|
ClassMG is built on a client-server architecture:
|
||||||
|
|
||||||
|
- **Client Application**: Developed using HarmonyOS ArkTS for cross-device compatibility
|
||||||
|
- **Communication Server**: Node.js based server that enables real-time message passing and state synchronization
|
||||||
|
- **Local Data Storage**: Secure local storage for user credentials and session data
|
||||||
|
|
||||||
|
## Core Features
|
||||||
|
|
||||||
|
### 1. Classroom Management
|
||||||
|
- **Create Classroom**: Teachers can create virtual classrooms with unique access codes
|
||||||
|
- **Join Classroom**: Students can join using classroom codes
|
||||||
|
- ~~**Classroom Status**: Real-time monitoring of active participants~~
|
||||||
|
- **End Classroom**: Teachers can terminate sessions with proper notification to all participants
|
||||||
|
|
||||||
|
### ~~2. Real-time Communication~~
|
||||||
|
- **Instant Messaging**: Bi-directional communication between teachers and students
|
||||||
|
- **Message Synchronization**: Robust message delivery with automatic retry mechanisms
|
||||||
|
- **Connection Status**: Visual indicators for connection status with troubleshooting options
|
||||||
|
|
||||||
|
### 3. Interactive Questions
|
||||||
|
- **Question Publishing**: Teachers can create and publish multiple-choice questions
|
||||||
|
- **Timed Responses**: Configurable time limits for answering questions
|
||||||
|
- **Answer Submission**: Students can submit answers with immediate confirmation
|
||||||
|
- **Result Analysis**: Visual presentation of response statistics and correctness rates
|
||||||
|
|
||||||
|
### 4. User Experience
|
||||||
|
- **Adaptive Layout**: Responsive interface that works across different screen sizes
|
||||||
|
- **Visual Feedback**: Clear status indicators for all operations
|
||||||
|
- **Error Handling**: Comprehensive error notifications with recovery options
|
||||||
|
- **Theme Customization**: Personalized visual appearance settings
|
||||||
|
|
||||||
|
## Operation Logic
|
||||||
|
|
||||||
|
### Authentication Flow
|
||||||
|
1. Users register with username and password (stored securely)
|
||||||
|
2. Login verification against local credentials
|
||||||
|
3. Role assignment (teacher or student) determines available features
|
||||||
|
|
||||||
|
### Classroom Session Flow
|
||||||
|
1. Teacher creates a classroom with a unique code
|
||||||
|
2. Students join using the provided code
|
||||||
|
3. Real-time synchronization establishes the classroom environment
|
||||||
|
4. Teacher and students can exchange messages and participate in question sessions
|
||||||
|
5. Teacher can end the classroom session, which notifies all participants
|
||||||
|
|
||||||
|
### Messaging System
|
||||||
|
1. Messages are composed and sent from the input area
|
||||||
|
2. Local preview appears immediately for responsive UX
|
||||||
|
3. Messages are transmitted to the server
|
||||||
|
4. Server broadcasts messages to all connected devices
|
||||||
|
5. Polling mechanism ensures message delivery, even after temporary disconnections
|
||||||
|
|
||||||
|
### Question Management
|
||||||
|
1. Teacher creates questions with multiple-choice options
|
||||||
|
2. Students receive questions with configurable countdown timers
|
||||||
|
3. Responses are collected and synchronized across devices
|
||||||
|
4. Results are computed and displayed after the question ends
|
||||||
|
5. Teachers can view detailed statistics while students see personal results
|
||||||
|
|
||||||
|
## Technical Implementation
|
||||||
|
|
||||||
|
### Communication Protocol
|
||||||
|
- HTTP-based API for classroom operations
|
||||||
|
- Polling mechanism for state synchronization
|
||||||
|
- JSON message format for data exchange
|
||||||
|
|
||||||
|
### Data Security
|
||||||
|
- Local credential storage with encryption
|
||||||
|
- Classroom access controlled via unique codes
|
||||||
|
- Session validation for all operations
|
||||||
|
|
||||||
|
### Synchronization Mechanism
|
||||||
|
- Server maintains the source of truth for classroom state
|
||||||
|
- Client polling ensures data consistency
|
||||||
|
- Conflict resolution strategies for concurrent operations
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
- Connection status monitoring
|
||||||
|
- Automatic reconnection attempts
|
||||||
|
- User-friendly error messages with recovery options
|
||||||
|
|
||||||
|
## Server Setup
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
- Node.js (v12 or higher)
|
- Node.js (v12 or higher)
|
||||||
- NPM (Node Package Manager)
|
- NPM (Node Package Manager)
|
||||||
|
|
||||||
## Installation
|
### Installation
|
||||||
|
1. Install Node.js and NPM
|
||||||
|
2. Clone or download the repository
|
||||||
|
3. Install dependencies with `npm install`
|
||||||
|
|
||||||
1. Install Node.js and NPM if you haven't already:
|
### Running the Server
|
||||||
- Download from [nodejs.org](https://nodejs.org/)
|
1. Start with `npm start` or `node server.js`
|
||||||
|
2. Server will run on port 5243 by default
|
||||||
|
3. Note your computer's IP address for client configuration
|
||||||
|
|
||||||
2. Clone or download this repository to your computer
|
## Client Configuration
|
||||||
|
|
||||||
3. Install dependencies:
|
### Development Environment
|
||||||
```bash
|
- DevEco Studio (recommended)
|
||||||
npm install
|
- HarmonyOS SDK
|
||||||
```
|
|
||||||
|
|
||||||
## Running the server
|
### Connection Setup
|
||||||
|
1. Ensure all devices are on the same network
|
||||||
1. Start the server:
|
2. Configure the server address in the client application
|
||||||
```bash
|
3. Compile and deploy to testing devices
|
||||||
npm start
|
|
||||||
```
|
|
||||||
or
|
|
||||||
```bash
|
|
||||||
node server.js
|
|
||||||
```
|
|
||||||
|
|
||||||
2. The server will start on port 5243. Make note of your computer's IP address, which will be displayed in the console output.
|
|
||||||
|
|
||||||
## Connecting ClassMG app to the server
|
|
||||||
|
|
||||||
1. Make sure all devices (server and app clients) are on the same network
|
|
||||||
|
|
||||||
2. Open the ClassMG project in DevEco Studio
|
|
||||||
|
|
||||||
3. Update the `CHANNEL_API_CONFIG.baseUrl` in `entry/src/main/ets/common/ClassRoomService.ets` to:
|
|
||||||
```
|
|
||||||
http://<Your computer's IP address>:5243
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Compile and run the ClassMG app on your devices
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
1. Run the server on one computer
|
|
||||||
2. Run the ClassMG app on two different devices (or emulators)
|
|
||||||
3. Log in as a teacher on one device and create a class
|
|
||||||
4. Log in as a student on the other device and join the class using the class code
|
|
||||||
5. Test messaging, question publishing, and answering functionality
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
- **Connection Issues**: Make sure all devices are on the same network and can reach the server's IP address
|
### Connection Issues
|
||||||
- **Port Conflicts**: If port 5243 is already in use, change the PORT variable in server.js and update the app accordingly
|
- Verify all devices are on the same network
|
||||||
- **CORS Issues**: If experiencing cross-origin problems, verify the CORS middleware is correctly configured in server.js
|
- Check server IP address and port configuration
|
||||||
|
- Use the built-in connection status checker in the application
|
||||||
|
|
||||||
## Note
|
### Message Synchronization
|
||||||
|
- If messages aren't appearing across devices, check connection status
|
||||||
|
- Verify server is running properly
|
||||||
|
- Try reconnecting using the in-app troubleshooting button
|
||||||
|
|
||||||
This is a development server intended for local testing only. For production use, additional security measures would be required.
|
### Layout Problems
|
||||||
|
- If UI elements are misaligned or appear off-screen, restart the application
|
||||||
|
- Different device screen sizes may require application restart after significant layout changes
|
||||||
|
|
||||||
|
## Notes for Developers
|
||||||
|
|
||||||
|
- The system uses a polling mechanism rather than WebSockets for compatibility reasons
|
||||||
|
- Message deduplication is implemented to handle potential duplicate delivery
|
||||||
|
- UI layouts are optimized for both tablet and smartphone form factors
|
||||||
|
- Debug logging can be enabled for troubleshooting purposes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Note**: This document provides an overview of the ClassMG system. For detailed API documentation and developer guides, please refer to the technical documentation.
|
144
README_CN.md
Normal file
144
README_CN.md
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
# ClassMG - 互动式课堂管理系统
|
||||||
|
|
||||||
|
[English](README.md) | [中文版(当前)](README_CN.md)
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
ClassMG是一款全面的课堂管理应用程序,专为互动式教学和学习设计。该系统支持教师和学生之间的实时通信、互动问答环节和即时反馈机制,所有这些功能都在统一的数字课堂环境中实现。
|
||||||
|
|
||||||
|
## 系统架构
|
||||||
|
|
||||||
|
ClassMG基于客户端-服务器架构:
|
||||||
|
|
||||||
|
- **客户端应用**:使用HarmonyOS ArkTS开发,确保跨设备兼容性
|
||||||
|
- **通信服务器**:基于Node.js的服务器,支持实时消息传递和状态同步
|
||||||
|
- **本地数据存储**:用于安全存储用户凭证和会话数据
|
||||||
|
|
||||||
|
## 核心功能
|
||||||
|
|
||||||
|
### 1. 课堂管理
|
||||||
|
- **创建课堂**:教师可以创建具有唯一访问码的虚拟课堂
|
||||||
|
- **加入课堂**:学生可以使用课堂码加入
|
||||||
|
- ~~**课堂状态**:实时监控活跃参与者~~
|
||||||
|
- **结束课堂**:教师可以终止会话,并向所有参与者发送通知
|
||||||
|
|
||||||
|
### ~~2. 实时通信~~
|
||||||
|
- **即时消息**:教师和学生之间的双向通信
|
||||||
|
- **消息同步**:具有自动重试机制的可靠消息传递
|
||||||
|
- **连接状态**:连接状态的可视化指示器,提供故障排除选项
|
||||||
|
|
||||||
|
### 3. 互动问答
|
||||||
|
- **问题发布**:教师可以创建并发布多选题
|
||||||
|
- **定时响应**:可配置的答题时间限制
|
||||||
|
- **提交答案**:学生可以提交答案并获得即时确认
|
||||||
|
- **结果分析**:以可视化方式呈现回答统计和正确率
|
||||||
|
|
||||||
|
### 4. 用户体验
|
||||||
|
- **自适应布局**:适应不同屏幕尺寸的响应式界面
|
||||||
|
- **视觉反馈**:所有操作的清晰状态指示
|
||||||
|
- **错误处理**:全面的错误通知和恢复选项
|
||||||
|
- **主题定制**:个性化的视觉外观设置
|
||||||
|
|
||||||
|
## 操作逻辑
|
||||||
|
|
||||||
|
### 认证流程
|
||||||
|
1. 用户使用用户名和密码注册(安全存储)
|
||||||
|
2. 根据本地凭据进行登录验证
|
||||||
|
3. 角色分配(教师或学生)决定可用功能
|
||||||
|
|
||||||
|
### 课堂会话流程
|
||||||
|
1. 教师创建具有唯一码的课堂
|
||||||
|
2. 学生使用提供的课堂码加入
|
||||||
|
3. 实时同步建立课堂环境
|
||||||
|
4. 教师和学生可以交换消息并参与问答环节
|
||||||
|
5. 教师可以结束课堂会话,系统会通知所有参与者
|
||||||
|
|
||||||
|
### 消息系统
|
||||||
|
1. 从输入区域撰写和发送消息
|
||||||
|
2. 本地预览立即显示,提供响应式用户体验
|
||||||
|
3. 消息传输到服务器
|
||||||
|
4. 服务器向所有连接的设备广播消息
|
||||||
|
5. 轮询机制确保消息传递,即使在临时断开连接后也能同步
|
||||||
|
|
||||||
|
### 问题管理
|
||||||
|
1. 教师创建带有多个选项的问题
|
||||||
|
2. 学生收到问题,并看到可配置的倒计时
|
||||||
|
3. 收集并跨设备同步回答
|
||||||
|
4. 问题结束后计算并显示结果
|
||||||
|
5. 教师可以查看详细统计,而学生能看到个人结果
|
||||||
|
|
||||||
|
## 技术实现
|
||||||
|
|
||||||
|
### 通信协议
|
||||||
|
- 基于HTTP的API用于课堂操作
|
||||||
|
- 轮询机制用于状态同步
|
||||||
|
- JSON消息格式用于数据交换
|
||||||
|
|
||||||
|
### 数据安全
|
||||||
|
- 本地凭证存储带有加密功能
|
||||||
|
- 通过唯一码控制课堂访问
|
||||||
|
- 对所有操作进行会话验证
|
||||||
|
|
||||||
|
### 同步机制
|
||||||
|
- 服务器维护课堂状态的权威来源
|
||||||
|
- 客户端轮询确保数据一致性
|
||||||
|
- 针对并发操作的冲突解决策略
|
||||||
|
|
||||||
|
### 错误处理
|
||||||
|
- 连接状态监控
|
||||||
|
- 自动重连尝试
|
||||||
|
- 用户友好的错误消息和恢复选项
|
||||||
|
|
||||||
|
## 服务器设置
|
||||||
|
|
||||||
|
### 前提条件
|
||||||
|
- Node.js(v12或更高版本)
|
||||||
|
- NPM(Node包管理器)
|
||||||
|
|
||||||
|
### 安装
|
||||||
|
1. 安装Node.js和NPM
|
||||||
|
2. 克隆或下载存储库
|
||||||
|
3. 使用`npm install`安装依赖项
|
||||||
|
|
||||||
|
### 运行服务器
|
||||||
|
1. 使用`npm start`或`node server.js`启动
|
||||||
|
2. 服务器默认运行在5243端口
|
||||||
|
3. 记下计算机的IP地址,用于客户端配置
|
||||||
|
|
||||||
|
## 客户端配置
|
||||||
|
|
||||||
|
### 开发环境
|
||||||
|
- DevEco Studio(推荐)
|
||||||
|
- HarmonyOS SDK
|
||||||
|
|
||||||
|
### 连接设置
|
||||||
|
1. 确保所有设备在同一网络上
|
||||||
|
2. 在客户端应用程序中配置服务器地址
|
||||||
|
3. 编译并部署到测试设备
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 连接问题
|
||||||
|
- 验证所有设备是否在同一网络上
|
||||||
|
- 检查服务器IP地址和端口配置
|
||||||
|
- 使用应用程序内置的连接状态检查器
|
||||||
|
|
||||||
|
### 消息同步
|
||||||
|
- 如果消息未跨设备显示,检查连接状态
|
||||||
|
- 验证服务器是否正常运行
|
||||||
|
- 尝试使用应用内故障排除按钮重新连接
|
||||||
|
|
||||||
|
### 布局问题
|
||||||
|
- 如果UI元素未对齐或在屏幕外显示,请重启应用程序
|
||||||
|
- 不同设备屏幕尺寸可能需要在重大布局更改后重启应用程序
|
||||||
|
|
||||||
|
## 开发者注意事项
|
||||||
|
|
||||||
|
- 系统出于兼容性考虑使用轮询机制而非WebSockets
|
||||||
|
- 实现了消息去重以处理潜在的重复传递
|
||||||
|
- UI布局针对平板电脑和智能手机形态进行了优化
|
||||||
|
- 可以启用调试日志进行故障排除
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**注意**:本文档提供了ClassMG系统的概述。有关详细的API文档和开发者指南,请参阅技术文档。
|
@ -246,11 +246,15 @@ 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', // 使用这个确认工作的地址
|
||||||
pollInterval: 1000, // 轮询间隔(毫秒) - 降低到1秒以提高同步速度
|
pollInterval: 1000,
|
||||||
timeout: 10000 // 请求超时(毫秒)
|
timeout: 10000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 定义日志频道ID和TAG常量
|
||||||
|
const TIAN_CHANNEL_DOMAIN_ID = 0x00201; // 自定义域ID
|
||||||
|
const TIAN_CHANNEL_TAG = 'tianChannel'; // 自定义TAG用于筛选日志
|
||||||
|
|
||||||
// 课堂通信服务
|
// 课堂通信服务
|
||||||
export class ClassRoomService {
|
export class ClassRoomService {
|
||||||
private static instance: ClassRoomService;
|
private static instance: ClassRoomService;
|
||||||
@ -280,7 +284,7 @@ export class ClassRoomService {
|
|||||||
|
|
||||||
private constructor() {
|
private constructor() {
|
||||||
// 初始化
|
// 初始化
|
||||||
hilog.info(0, 'ClassMG', 'ClassRoom Service Initialized');
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, 'ClassRoom Service Initialized');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getInstance(): ClassRoomService {
|
public static getInstance(): ClassRoomService {
|
||||||
@ -298,9 +302,21 @@ export class ClassRoomService {
|
|||||||
|
|
||||||
// 发起HTTP POST请求
|
// 发起HTTP POST请求
|
||||||
private async postRequest(endpoint: string, data: object): Promise<ChannelApiResponse> {
|
private async postRequest(endpoint: string, data: object): Promise<ChannelApiResponse> {
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `开始POST请求: ${endpoint}`);
|
||||||
try {
|
try {
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `创建HTTP客户端`);
|
||||||
const httpRequest = this.createHttpClient();
|
const httpRequest = this.createHttpClient();
|
||||||
|
|
||||||
|
// 记录请求数据摘要
|
||||||
|
let dataStr = "";
|
||||||
|
try {
|
||||||
|
dataStr = JSON.stringify(data).substring(0, 100) + (JSON.stringify(data).length > 100 ? '...' : '');
|
||||||
|
} catch (e) {
|
||||||
|
dataStr = "无法序列化数据";
|
||||||
|
}
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `请求数据(摘要): ${dataStr}`);
|
||||||
|
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `发送请求到: ${CHANNEL_API_CONFIG.baseUrl}/${endpoint}`);
|
||||||
const response = await httpRequest.request(
|
const response = await httpRequest.request(
|
||||||
`${CHANNEL_API_CONFIG.baseUrl}/${endpoint}`,
|
`${CHANNEL_API_CONFIG.baseUrl}/${endpoint}`,
|
||||||
{
|
{
|
||||||
@ -314,14 +330,20 @@ export class ClassRoomService {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `请求完成,销毁HTTP客户端`);
|
||||||
httpRequest.destroy();
|
httpRequest.destroy();
|
||||||
|
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `响应状态码: ${response.responseCode}`);
|
||||||
|
|
||||||
if (response.responseCode === 200) {
|
if (response.responseCode === 200) {
|
||||||
const jsonString: string = response.result ? response.result.toString() : '{}';
|
|
||||||
try {
|
try {
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `开始解析响应JSON`);
|
||||||
|
const jsonString: string = response.result ? response.result.toString() : '{}';
|
||||||
const responseData = JSON.parse(jsonString) as ChannelApiResponse;
|
const responseData = JSON.parse(jsonString) as ChannelApiResponse;
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `解析成功,响应success: ${responseData.success}`);
|
||||||
return responseData;
|
return responseData;
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `解析响应JSON失败: ${parseError}`);
|
||||||
logManager.error(LogCategory.NETWORK, `Error parsing response: ${parseError}`);
|
logManager.error(LogCategory.NETWORK, `Error parsing response: ${parseError}`);
|
||||||
const errorResponse: ChannelApiResponse = {
|
const errorResponse: ChannelApiResponse = {
|
||||||
success: false,
|
success: false,
|
||||||
@ -331,12 +353,20 @@ export class ClassRoomService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hilog.warn(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `HTTP错误状态码: ${response.responseCode}`);
|
||||||
const errorResponse: ChannelApiResponse = {
|
const errorResponse: ChannelApiResponse = {
|
||||||
success: false,
|
success: false,
|
||||||
message: `HTTP error: ${response.responseCode}`
|
message: `HTTP error: ${response.responseCode}`
|
||||||
};
|
};
|
||||||
return errorResponse;
|
return errorResponse;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// 详细记录网络错误
|
||||||
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||||
|
const errorStack = error instanceof Error ? error.stack : 'No stack trace';
|
||||||
|
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `网络请求错误: ${errorMsg}`);
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `错误堆栈: ${errorStack}`);
|
||||||
|
|
||||||
logManager.error(LogCategory.NETWORK, `Network request error: ${error}`);
|
logManager.error(LogCategory.NETWORK, `Network request error: ${error}`);
|
||||||
const errorResponse: ChannelApiResponse = {
|
const errorResponse: ChannelApiResponse = {
|
||||||
success: false,
|
success: false,
|
||||||
@ -685,43 +715,101 @@ export class ClassRoomService {
|
|||||||
|
|
||||||
// 发送消息
|
// 发送消息
|
||||||
public async sendMessage(content: string): Promise<boolean> {
|
public async sendMessage(content: string): Promise<boolean> {
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `========= 开始发送消息 =========`);
|
||||||
|
|
||||||
|
// 检查前提条件
|
||||||
|
if (!this.currentSession) {
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `发送失败: currentSession为空`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.connected) {
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `发送失败: 未连接`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.currentClassCode) {
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `发送失败: currentClassCode为空`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.currentSession || !this.connected || !this.currentClassCode) {
|
if (!this.currentSession || !this.connected || !this.currentClassCode) {
|
||||||
logManager.error(LogCategory.CLASS, `Cannot send message: No active session or not connected`);
|
logManager.error(LogCategory.CLASS, `Cannot send message: No active session or not connected`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug message: Log session and connection information
|
// Debug message: Log session and connection information
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `会话ID: ${this.currentSession.sessionId}`);
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `课堂码: ${this.currentClassCode}`);
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `连接状态: ${this.connected}`);
|
||||||
|
|
||||||
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `[DEBUG] Message sending attempt - Session ID: ${this.currentSession.sessionId}, Class Code: ${this.currentClassCode}, Connection status: ${this.connected}`);
|
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `[DEBUG] Message sending attempt - Session ID: ${this.currentSession.sessionId}, Class Code: ${this.currentClassCode}, Connection status: ${this.connected}`);
|
||||||
|
|
||||||
|
// 获取用户信息
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `获取用户信息`);
|
||||||
const currentAccount = settingsService.getCurrentAccount();
|
const currentAccount = settingsService.getCurrentAccount();
|
||||||
const senderName = this.dbService.getUserNickname(currentAccount) || currentAccount;
|
const senderName = this.dbService.getUserNickname(currentAccount) || currentAccount;
|
||||||
const role = this.isTeacher ? SenderRole.TEACHER : SenderRole.STUDENT;
|
const role = this.isTeacher ? SenderRole.TEACHER : SenderRole.STUDENT;
|
||||||
|
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `用户账号: ${currentAccount}`);
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `用户名称: ${senderName}`);
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `用户角色: ${role}`);
|
||||||
|
|
||||||
// Debug message: Log user information
|
// Debug message: Log user information
|
||||||
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `[DEBUG] Message sender info - Account: ${currentAccount}, Name: ${senderName}, Role: ${role}`);
|
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `[DEBUG] Message sender info - Account: ${currentAccount}, Name: ${senderName}, Role: ${role}`);
|
||||||
|
|
||||||
// 创建消息
|
// 创建消息对象
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `创建消息对象`);
|
||||||
|
try {
|
||||||
|
// 单独记录消息创建过程
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `消息内容: ${content}`);
|
||||||
|
|
||||||
const message = new MessageModel(currentAccount, senderName, role, content);
|
const message = new MessageModel(currentAccount, senderName, role, content);
|
||||||
|
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `消息创建成功,ID: ${message.id}`);
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `消息时间戳: ${message.timestamp.toISOString()}`);
|
||||||
|
|
||||||
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `Creating message: ID=${message.id}, Content=${content}, Sender=${senderName}, Role=${role}`);
|
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `Creating message: ID=${message.id}, Content=${content}, Sender=${senderName}, Role=${role}`);
|
||||||
|
|
||||||
try {
|
// 构建请求
|
||||||
// 发送消息请求
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `构建发送请求`);
|
||||||
const request: SendMessageRequest = {
|
const request: SendMessageRequest = {
|
||||||
classCode: this.currentClassCode,
|
classCode: this.currentClassCode,
|
||||||
message: message
|
message: message
|
||||||
};
|
};
|
||||||
|
|
||||||
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `Sending message to server: ${JSON.stringify(request)}`);
|
// 打印请求对象,但避免过长内容
|
||||||
|
let requestStr = "";
|
||||||
|
try {
|
||||||
|
requestStr = JSON.stringify(request).substring(0, 200) + (JSON.stringify(request).length > 200 ? '...' : '');
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `请求对象(摘要): ${requestStr}`);
|
||||||
|
} catch (e) {
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `无法序列化请求: ${e}`);
|
||||||
|
}
|
||||||
|
|
||||||
// Debug message: Log request details before sending
|
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `发送消息请求: classCode=${this.currentClassCode}, messageId=${message.id}`);
|
||||||
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `[DEBUG] Message request details - Timestamp: ${message.timestamp.toISOString()}, Message ID format check: ${message.id.length > 5 ? 'Valid' : 'Invalid'}`);
|
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `开始发送POST请求到sendMessage`);
|
||||||
const response = await this.postRequest('sendMessage', request);
|
const response = await this.postRequest('sendMessage', request);
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `请求完成,响应success: ${response.success}`);
|
||||||
|
|
||||||
// Debug message: Log response details
|
// 详细记录响应
|
||||||
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `[DEBUG] Server response received - Success: ${response.success}, Message: ${response.message || 'No message'}`);
|
if (response.message) {
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `响应消息: ${response.message}`);
|
||||||
|
}
|
||||||
|
if (response.data) {
|
||||||
|
try {
|
||||||
|
const dataStr = JSON.stringify(response.data).substring(0, 100) +
|
||||||
|
(JSON.stringify(response.data).length > 100 ? '...' : '');
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `响应数据(摘要): ${dataStr}`);
|
||||||
|
} catch (e) {
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `无法序列化响应数据: ${e}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `服务器响应: success=${response.success}, message=${response.message || "无"}`);
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `消息发送成功,更新lastMessageId: ${message.id}`);
|
||||||
// 不再将消息添加到currentSession,因为UI层已经添加了本地消息
|
// 不再将消息添加到currentSession,因为UI层已经添加了本地消息
|
||||||
// (已删除): this.currentSession.messages.push(message);
|
// (已删除): this.currentSession.messages.push(message);
|
||||||
|
|
||||||
@ -732,19 +820,30 @@ export class ClassRoomService {
|
|||||||
this.lastMessageId = message.id;
|
this.lastMessageId = message.id;
|
||||||
|
|
||||||
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `Message sent successfully: ${message.id}`);
|
logManager.info(LogCategory.CLASS, LogEventType.SYSTEM_INFO, `Message sent successfully: ${message.id}`);
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `========= 消息发送成功 =========`);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// Enhanced error logging with response details
|
// Enhanced error logging with response details
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `消息发送失败: ${response.message || '未知错误'}`);
|
||||||
logManager.error(LogCategory.CLASS, `Send message failed: ${response.message || 'Unknown error'}, Response data: ${JSON.stringify(response.data || {})}`);
|
logManager.error(LogCategory.CLASS, `Send message failed: ${response.message || 'Unknown error'}, Response data: ${JSON.stringify(response.data || {})}`);
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `========= 消息发送失败 =========`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Enhanced error logging with error details
|
// 增强错误处理,确保不会崩溃
|
||||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||||
const errorStack = error instanceof Error ? error.stack : 'No stack trace';
|
const errorStack = error instanceof Error ? error.stack : 'No stack trace';
|
||||||
logManager.error(LogCategory.CLASS, `Send message error: ${errorMessage}`);
|
|
||||||
logManager.error(LogCategory.CLASS, `[DEBUG] Error details - Stack: ${errorStack}`);
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `发送消息异常: ${errorMessage}`);
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `错误堆栈: ${errorStack}`);
|
||||||
|
|
||||||
|
logManager.error(LogCategory.CLASS, `发送消息严重错误: ${errorMessage}`);
|
||||||
|
logManager.error(LogCategory.CLASS, `错误详情: ${errorStack}`);
|
||||||
|
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `========= 消息发送异常 =========`);
|
||||||
|
|
||||||
|
// 确保返回false而不是崩溃
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,8 @@ export class LogManager {
|
|||||||
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",["测试消息发送","修复已知问题"])
|
new VersionLogItem("1.2.0 beta","2025-4-3",["测试消息发送","修复已知问题"]),
|
||||||
|
new VersionLogItem("1.2.0 beta1.0","2025-4-3",["更新说明文档","添加日志输出"])
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,11 @@ import { ClassRoomService,
|
|||||||
} from '../common/ClassRoomService';
|
} from '../common/ClassRoomService';
|
||||||
import logManager, { LogCategory, LogEventType } from '../common/logtext';
|
import logManager, { LogCategory, LogEventType } from '../common/logtext';
|
||||||
import http from '@ohos.net.http';
|
import http from '@ohos.net.http';
|
||||||
|
import hilog from '@ohos.hilog';
|
||||||
|
|
||||||
|
// 添加hilog和tianChannel常量
|
||||||
|
const TIAN_CHANNEL_DOMAIN_ID = 0x00201; // 自定义域ID
|
||||||
|
const TIAN_CHANNEL_TAG = 'tianChannel'; // 自定义TAG用于筛选日志
|
||||||
|
|
||||||
// 定义选项对象接口
|
// 定义选项对象接口
|
||||||
interface ScrollOptions {
|
interface ScrollOptions {
|
||||||
@ -396,21 +401,29 @@ struct ClassLivePage {
|
|||||||
|
|
||||||
// 发送消息
|
// 发送消息
|
||||||
private async sendMessage() {
|
private async sendMessage() {
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] ======== 开始UI层消息发送 ========`);
|
||||||
|
|
||||||
if (!this.messageText || this.messageText.trim() === '') {
|
if (!this.messageText || this.messageText.trim() === '') {
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 消息内容为空,不发送`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 防止重复点击、重复发送
|
// 防止重复点击、重复发送
|
||||||
if (this.isLoading) {
|
if (this.isLoading) {
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 正在加载中,防止重复发送`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 设置加载状态为true`);
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
// 保存消息内容,因为后面会清空输入框
|
// 保存消息内容,因为后面会清空输入框
|
||||||
const messageContent = this.messageText.trim();
|
const messageContent = this.messageText.trim();
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 消息内容: ${messageContent}`);
|
||||||
|
|
||||||
// 创建一个本地消息对象用于立即显示
|
// 创建一个本地消息对象用于立即显示
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 创建本地消息对象`);
|
||||||
const localMessage = new MessageModel(
|
const localMessage = new MessageModel(
|
||||||
settingsService.getCurrentAccount(),
|
settingsService.getCurrentAccount(),
|
||||||
settingsService.getUserNickname() || settingsService.getCurrentAccount(),
|
settingsService.getUserNickname() || settingsService.getCurrentAccount(),
|
||||||
@ -420,43 +433,74 @@ struct ClassLivePage {
|
|||||||
|
|
||||||
// 保存消息ID,以便后续可以在发送失败时移除
|
// 保存消息ID,以便后续可以在发送失败时移除
|
||||||
const localMessageId = localMessage.id;
|
const localMessageId = localMessage.id;
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 本地消息ID: ${localMessageId}`);
|
||||||
|
|
||||||
// 清空消息输入框 - 提前清空避免用户重复点击
|
// 清空消息输入框 - 提前清空避免用户重复点击
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 清空输入框`);
|
||||||
this.messageText = '';
|
this.messageText = '';
|
||||||
|
|
||||||
// 先在本地添加消息,让用户立即看到
|
// 先在本地添加消息,让用户立即看到
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 添加消息到本地列表`);
|
||||||
console.info(`添加本地消息: ID=${localMessageId}, 内容=${messageContent}`);
|
console.info(`添加本地消息: ID=${localMessageId}, 内容=${messageContent}`);
|
||||||
this.messages = [...this.messages, localMessage];
|
this.messages = [...this.messages, localMessage];
|
||||||
|
|
||||||
// 自动滚动到最新消息
|
// 自动滚动到最新消息
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 滚动到最新消息`);
|
||||||
this.scrollToLatestMessage();
|
this.scrollToLatestMessage();
|
||||||
|
|
||||||
// 发送消息到服务器
|
// 发送消息到服务器
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 调用服务层发送消息`);
|
||||||
|
try {
|
||||||
const result = await this.classRoomService.sendMessage(messageContent);
|
const result = await this.classRoomService.sendMessage(messageContent);
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 服务层返回结果: ${result}`);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
// 如果发送失败,从消息列表中移除本地消息
|
// 如果发送失败,从消息列表中移除本地消息
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 消息发送失败,移除本地消息: ${localMessageId}`);
|
||||||
console.error(`消息发送失败,移除本地消息: ${localMessageId}`);
|
console.error(`消息发送失败,移除本地消息: ${localMessageId}`);
|
||||||
this.messages = this.messages.filter(msg => msg.id !== localMessageId);
|
this.messages = this.messages.filter(msg => msg.id !== localMessageId);
|
||||||
|
|
||||||
|
// 显示错误提示
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 显示发送失败提示`);
|
||||||
|
promptAction.showToast({
|
||||||
|
message: '消息发送失败,请重试',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 消息发送成功: ${localMessageId}`);
|
||||||
|
console.info(`消息发送成功: ${localMessageId}`);
|
||||||
|
}
|
||||||
|
} catch (serviceError) {
|
||||||
|
// 处理服务层异常
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 服务层异常: ${serviceError}`);
|
||||||
|
|
||||||
|
// 如果发送失败,从消息列表中移除本地消息
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 由于服务层异常,移除本地消息: ${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) {
|
||||||
// 处理错误
|
// 处理错误
|
||||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||||
|
const errorStack = error instanceof Error ? error.stack : 'No stack trace';
|
||||||
|
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 顶层异常: ${errorMessage}`);
|
||||||
|
hilog.error(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 异常堆栈: ${errorStack}`);
|
||||||
|
|
||||||
logManager.error(LogCategory.CLASS, `Send message error: ${errorMessage}`);
|
logManager.error(LogCategory.CLASS, `Send message error: ${errorMessage}`);
|
||||||
promptAction.showToast({
|
promptAction.showToast({
|
||||||
message: '消息发送失败,请重试',
|
message: '消息发送失败,请重试',
|
||||||
duration: 2000
|
duration: 2000
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] 设置加载状态为false`);
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `[UI] ======== 结束UI层消息发送 ========`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user