Files
java-template/utils/message_integration_plan_updated.md
T
BrunoGaoandClaude e402548e45 fix: 修复customer_id字段缺失问题,完成数据库schema同步
数据库修复:
- t_user_health_data_daily: 添加customer_id字段(租户ID)
- t_user_health_data_weekly: 添加customer_id字段(租户ID)

ljwx-boot同步更新:
- TUserHealthDataDailyMapper.xml: 添加customer_id字段映射
- TUserHealthDataWeeklyMapper.xml: 添加customer_id字段映射

其他改进:
- 告警规则缓存优化
- Redis缓存性能提升
- 健康数据处理性能优化
- 添加完整的文档和工具脚本

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
2025-09-10 13:49:59 +08:00

549 lines
19 KiB
Markdown

# 基于实际代码的消息数据流集成方案
基于对ljwx-boot、ljwx-bigscreen、ljwx-phone、ljwx-watch四个平台的详细代码分析,提供一个贴合实际情况的消息数据流集成优化方案。
## 一、现有架构分析
### 1.1 数据库表结构(已存在)
**t_device_message (主消息表)**
```sql
CREATE TABLE t_device_message (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
device_sn VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
org_id VARCHAR(50),
user_id VARCHAR(50),
customer_id BIGINT NOT NULL DEFAULT 0,
message_type VARCHAR(50) NOT NULL, -- job/task/announcement/notification/system_alert
sender_type VARCHAR(50) NOT NULL, -- system/admin/user
receiver_type VARCHAR(50) NOT NULL, -- device/user/department
message_status VARCHAR(50) DEFAULT 'pending', -- pending/delivered/acknowledged
responded_number INTEGER DEFAULT 0,
sent_time DATETIME DEFAULT CURRENT_TIMESTAMP,
received_time DATETIME NULL,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
```
**t_device_message_detail (消息详情表)**
```sql
CREATE TABLE t_device_message_detail (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
message_id BIGINT NOT NULL,
device_sn VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
message_type VARCHAR(50) NOT NULL,
sender_type VARCHAR(50) NOT NULL,
receiver_type VARCHAR(50) NOT NULL,
message_status VARCHAR(50) DEFAULT 'pending',
sent_time DATETIME,
received_time DATETIME,
customer_id BIGINT NOT NULL,
org_id BIGINT,
-- 新增字段用于统计和跟踪
delivery_status VARCHAR(50), -- pending/delivered/acknowledged/failed/expired
channel VARCHAR(50), -- message/push/wechat/watch
response_time INTEGER, -- 响应时间(秒)
acknowledge_time DATETIME, -- 确认时间
target_type VARCHAR(50), -- user/device/department/organization
target_id VARCHAR(255) -- 目标ID
);
```
### 1.2 现有消息流程
```
ljwx-admin/ljwx-bigscreen → t_device_message → ljwx-phone → ljwx-watch
↓ (手动发送) ↓ (API查询) ↓ (蓝牙) ↓ (用户确认)
告警规则触发 定时获取消息 转发给手表 反向确认回传
```
## 二、各平台现状分析
### 2.1 ljwx-boot (Java后端)
**现有接口**:
- `TDeviceMessageController` - CRUD操作
- `DeviceMessageServiceImpl` - 兼容性服务层
- 支持消息的发送、接收、保存
**优化需求**:
- 增强消息生命周期管理
- 添加实时状态同步
- 支持批量操作和统计
### 2.2 ljwx-bigscreen (Python大屏)
**现有功能**:
- `DeviceMessage`、`DeviceMessageDetail` SQLAlchemy模型
- `/DeviceMessage/send`、`/receive` API接口
- 告警自动转消息机制 (`system_event_alert.py`)
- 消息统计和展示功能
**优化需求**:
- 增强消息跟踪界面
- 实时状态更新
- 完善统计报表
### 2.3 ljwx-phone (Flutter移动端)
**现有功能**:
- `Message`、`MessageInfo` Dart模型
- `ApiService.getDeviceMessages()` - 获取消息
- `markMessageAsRead()` - 标记已读
- 消息列表和详情UI
- 蓝牙消息转发给手表
**优化需求**:
- 实时消息推送
- 批量操作优化
- 离线消息同步
### 2.4 ljwx-watch (HarmonyOS手表)
**现有功能**:
- HTTP和蓝牙双模式消息接收
- `fetchMessageFromServer()` - HTTP拉取
- 蓝牙GATT命令处理
- 系统通知显示和用户确认
**优化需求**:
- 消息确认回传优化
- 显示效果增强
- 电池优化
## 三、集成优化方案
### 3.1 消息统一模型扩展
在现有数据库基础上增加字段,支持完整的消息生命周期:
```sql
-- 扩展 t_device_message 表
ALTER TABLE t_device_message ADD COLUMN title VARCHAR(500);
ALTER TABLE t_device_message ADD COLUMN content TEXT;
ALTER TABLE t_device_message ADD COLUMN priority INTEGER DEFAULT 3;
ALTER TABLE t_device_message ADD COLUMN urgency VARCHAR(20) DEFAULT 'medium';
ALTER TABLE t_device_message ADD COLUMN channels JSON; -- ["message","push","wechat","watch"]
ALTER TABLE t_device_message ADD COLUMN require_ack BOOLEAN DEFAULT false;
ALTER TABLE t_device_message ADD COLUMN expiry_time DATETIME;
ALTER TABLE t_device_message ADD COLUMN metadata JSON;
-- 扩展 t_device_message_detail 表
ALTER TABLE t_device_message_detail ADD COLUMN distribution_id VARCHAR(255);
ALTER TABLE t_device_message_detail ADD COLUMN target_type VARCHAR(50);
ALTER TABLE t_device_message_detail ADD COLUMN target_id VARCHAR(255);
ALTER TABLE t_device_message_detail ADD COLUMN delivery_status VARCHAR(50);
ALTER TABLE t_device_message_detail ADD COLUMN channel VARCHAR(50);
ALTER TABLE t_device_message_detail ADD COLUMN response_time INTEGER;
ALTER TABLE t_device_message_detail ADD COLUMN acknowledge_time DATETIME;
ALTER TABLE t_device_message_detail ADD COLUMN delivery_details JSON;
```
### 3.2 ljwx-boot 服务层增强
基于现有的 `TDeviceMessageServiceImpl` 扩展功能:
```java
@Service
public class EnhancedMessageService extends TDeviceMessageServiceImpl {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 统一消息发布接口
*/
@Transactional
public Long publishMessage(UnifiedMessageRequest request) {
// 1. 保存主消息
TDeviceMessage message = buildDeviceMessage(request);
save(message);
// 2. 创建分发记录
List<TDeviceMessageDetail> details = createDistributionDetails(message, request);
messageDetailService.saveBatch(details);
// 3. 发布到Redis
publishToRedis(message, details);
// 4. 记录生命周期事件
recordLifecycleEvent(message.getId(), "created", getCurrentUser());
return message.getId();
}
/**
* 消息状态批量更新
*/
public void updateMessageStatus(Long messageId, String status, List<String> targetIds) {
// 更新主消息状态
TDeviceMessage message = getById(messageId);
message.setMessageStatus(status);
updateById(message);
// 更新详情状态
LambdaUpdateWrapper<TDeviceMessageDetail> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(TDeviceMessageDetail::getMessageId, messageId)
.in(TDeviceMessageDetail::getTargetId, targetIds)
.set(TDeviceMessageDetail::getDeliveryStatus, status)
.set(TDeviceMessageDetail::getAcknowledgeTime, LocalDateTime.now());
messageDetailService.update(wrapper);
// 发布状态更新事件
publishStatusUpdate(messageId, status);
}
private void publishToRedis(TDeviceMessage message, List<TDeviceMessageDetail> details) {
for (TDeviceMessageDetail detail : details) {
String channel = "message:" + detail.getChannel();
Map<String, Object> payload = buildRedisPayload(message, detail);
redisTemplate.convertAndSend(channel, payload);
}
}
}
```
### 3.3 ljwx-phone 实时消息集成
在现有Flutter代码基础上增加Redis订阅:
```dart
// lib/services/enhanced_message_service.dart
class EnhancedMessageService extends ApiService {
StreamSubscription<String>? _redisSubscription;
final StreamController<Message> _messageStreamController = StreamController<Message>.broadcast();
Stream<Message> get messageStream => _messageStreamController.stream;
@override
void initState() {
super.initState();
_subscribeToRedisMessages();
_startPeriodicSync(); // 保持现有的定时同步作为备用
}
void _subscribeToRedisMessages() {
// 订阅Redis消息通道
String channel = 'message:${deviceSn}';
_redisSubscription = RedisClient.subscribe(channel).listen((data) {
try {
Map<String, dynamic> messageData = jsonDecode(data);
Message message = Message.fromJson(messageData);
// 更新本地存储
_updateLocalMessage(message);
// 发布给UI层
_messageStreamController.add(message);
// 转发给手表(如果连接)
if (BluetoothService().isConnected) {
BluetoothService().forwardMessageToWatch(messageData);
}
} catch (e) {
print('解析Redis消息失败: $e');
}
});
}
@override
Future<bool> markMessageAsRead(String deviceSn, {
DateTime? receivedTime,
String? messageId,
Map<String, dynamic>? originalMessage
}) async {
// 调用现有API
final success = await super.markMessageAsRead(deviceSn,
receivedTime: receivedTime, messageId: messageId, originalMessage: originalMessage);
if (success) {
// 发布确认事件到Redis
Map<String, dynamic> ackEvent = {
'type': 'message_acknowledged',
'messageId': messageId,
'deviceSn': deviceSn,
'acknowledgeTime': receivedTime?.toIso8601String() ?? DateTime.now().toIso8601String(),
'source': 'phone'
};
RedisClient.publish('message:acknowledgments', jsonEncode(ackEvent));
}
return success;
}
}
```
### 3.4 ljwx-bigscreen 增强消息跟踪
基于现有的消息处理代码增加实时跟踪:
```python
# bigScreen/enhanced_message_tracking.py
class EnhancedMessageTracker:
@staticmethod
def create_message_with_tracking(message_data):
"""创建消息并启用跟踪"""
try:
# 使用现有的DeviceMessage模型
message = DeviceMessage(
device_sn=message_data.get('device_sn'),
message=message_data.get('content'),
message_type=message_data.get('message_type', 'notification'),
sender_type=message_data.get('sender_type', 'admin'),
receiver_type=message_data.get('receiver_type', 'device'),
org_id=message_data.get('org_id'),
user_id=message_data.get('user_id'),
customer_id=message_data.get('customer_id', 0),
# 新增字段
title=message_data.get('title'),
priority=message_data.get('priority', 3),
urgency=message_data.get('urgency', 'medium'),
require_ack=message_data.get('require_ack', False),
channels=json.dumps(message_data.get('channels', ['message'])),
metadata=json.dumps(message_data.get('metadata', {}))
)
db.session.add(message)
db.session.commit()
# 创建分发记录
targets = message_data.get('targets', [])
for target in targets:
detail = DeviceMessageDetail(
message_id=message.id,
device_sn=target.get('device_sn'),
message=message.message,
message_type=message.message_type,
sender_type=message.sender_type,
receiver_type=message.receiver_type,
customer_id=message.customer_id,
org_id=message.org_id,
# 新增字段
target_type=target.get('target_type', 'device'),
target_id=target.get('target_id'),
delivery_status='pending',
channel=target.get('channel', 'message')
)
db.session.add(detail)
db.session.commit()
# 发布到Redis
redis_client.publish(f'message:created', json.dumps({
'messageId': message.id,
'targets': [detail.device_sn for detail in message.details]
}))
return message
except Exception as e:
db.session.rollback()
print(f"创建消息失败: {e}")
return None
@staticmethod
def get_message_lifecycle(message_id):
"""获取消息生命周期报告"""
message = DeviceMessage.query.get(message_id)
if not message:
return None
details = DeviceMessageDetail.query.filter_by(message_id=message_id).all()
# 计算统计数据
total_targets = len(details)
delivered = sum(1 for d in details if d.delivery_status in ['delivered', 'acknowledged'])
acknowledged = sum(1 for d in details if d.delivery_status == 'acknowledged')
pending = sum(1 for d in details if d.delivery_status == 'pending')
failed = sum(1 for d in details if d.delivery_status == 'failed')
# 计算响应时间
response_times = [d.response_time for d in details if d.response_time]
avg_response_time = sum(response_times) / len(response_times) if response_times else 0
return {
'messageId': message_id,
'messageType': message.message_type,
'createTime': message.create_time.isoformat(),
'sentTime': message.sent_time.isoformat() if message.sent_time else None,
'progress': {
'totalTargets': total_targets,
'delivered': delivered,
'acknowledged': acknowledged,
'pending': pending,
'failed': failed,
'completionRate': (acknowledged / total_targets * 100) if total_targets > 0 else 0,
'avgResponseTime': avg_response_time
},
'details': [
{
'targetId': d.target_id,
'deviceSn': d.device_sn,
'deliveryStatus': d.delivery_status,
'channel': d.channel,
'responseTime': d.response_time,
'acknowledgeTime': d.acknowledge_time.isoformat() if d.acknowledge_time else None
}
for d in details
]
}
# bigScreen.py 新增API端点
@app.route('/api/message/lifecycle/<int:message_id>', methods=['GET'])
def get_message_lifecycle(message_id):
"""获取消息生命周期"""
lifecycle_data = EnhancedMessageTracker.get_message_lifecycle(message_id)
if lifecycle_data:
return jsonify({'success': True, 'data': lifecycle_data})
else:
return jsonify({'success': False, 'error': '消息不存在'}), 404
@app.route('/api/message/stats/<int:org_id>', methods=['GET'])
def get_organization_message_stats(org_id):
"""获取组织消息统计"""
start_date = request.args.get('startDate')
end_date = request.args.get('endDate')
query = DeviceMessage.query.filter_by(org_id=str(org_id))
if start_date:
query = query.filter(DeviceMessage.create_time >= datetime.fromisoformat(start_date))
if end_date:
query = query.filter(DeviceMessage.create_time <= datetime.fromisoformat(end_date))
messages = query.all()
# 生成统计数据
stats = {
'totalMessages': len(messages),
'messageTypes': {},
'dailyTrend': {},
'avgCompletionRate': 0,
'avgResponseTime': 0
}
# ... 统计计算逻辑
return jsonify({'success': True, 'data': stats})
```
### 3.5 ljwx-watch 消息处理优化
基于现有的HTTP和蓝牙双模式,增加确认反馈优化:
```java
// HttpService.java 消息确认增强
public void enhancedMessageConfirmation(JSONObject message) {
try {
String messageId = message.getString("message_id");
// 构建增强的确认响应
JSONObject enhancedResponse = new JSONObject();
enhancedResponse.put("type", "message_acknowledgment");
enhancedResponse.put("messageId", messageId);
enhancedResponse.put("deviceSn", dataManager.getDeviceSn());
enhancedResponse.put("acknowledgeTime", getCurrentTimestamp());
enhancedResponse.put("responseTime", calculateResponseTime(message));
enhancedResponse.put("channel", "http");
enhancedResponse.put("deviceInfo", getDeviceInfo());
enhancedResponse.put("userAction", "acknowledged"); // 用户主动确认
// 复制原消息字段
copyOriginalMessageFields(enhancedResponse, message);
// 发送确认
String confirmUrl = dataManager.getFetchMessageUrl() + "/acknowledge";
JSONObject response = postDataToServer(confirmUrl, enhancedResponse);
if (response != null && response.getBoolean("success")) {
Log.i(TAG, "✅ 消息确认发送成功: " + messageId);
// 本地标记为已确认
markMessageAsAcknowledged(messageId);
} else {
Log.w(TAG, "⚠️ 消息确认发送失败: " + messageId);
// 缓存确认,稍后重试
cacheAcknowledgment(enhancedResponse);
}
} catch (Exception e) {
Log.e(TAG, "❌ 消息确认处理异常: " + e.getMessage());
}
}
private int calculateResponseTime(JSONObject message) {
try {
String sentTimeStr = message.getString("sent_time");
long sentTime = parseTimestamp(sentTimeStr);
long currentTime = System.currentTimeMillis();
return (int) ((currentTime - sentTime) / 1000); // 返回秒数
} catch (Exception e) {
return -1; // 无法计算响应时间
}
}
private JSONObject getDeviceInfo() {
JSONObject deviceInfo = new JSONObject();
try {
deviceInfo.put("watchModel", "HarmonyOS Watch");
deviceInfo.put("osVersion", "4.0");
deviceInfo.put("appVersion", getAppVersion());
deviceInfo.put("batteryLevel", getBatteryLevel());
deviceInfo.put("signalStrength", getSignalStrength());
} catch (Exception e) {
Log.w(TAG, "获取设备信息失败: " + e.getMessage());
}
return deviceInfo;
}
```
## 四、实施路径
### 4.1 阶段一:数据库扩展(1周)
1. 执行SQL脚本扩展现有表结构
2. 更新ljwx-boot实体类
3. 更新ljwx-bigscreen SQLAlchemy模型
4. 数据迁移和兼容性测试
### 4.2 阶段二:后端服务增强(2周)
1. ljwx-boot增强消息服务
2. ljwx-bigscreen增强跟踪功能
3. Redis集成和实时通信
4. API接口联调测试
### 4.3 阶段三:移动端实时化(1周)
1. ljwx-phone集成Redis订阅
2. 增强消息确认机制
3. 蓝牙通信优化
4. 离线同步完善
### 4.4 阶段四:手表端优化(1周)
1. ljwx-watch确认反馈增强
2. 消息显示优化
3. 电池性能优化
4. 端到端测试
### 4.5 阶段五:整体联调(1周)
1. 四端数据流测试
2. 性能压力测试
3. 用户体验优化
4. 文档和培训
## 五、预期效果
1. **完整数据流打通**: 平台→手机→手表→确认回传的完整链路
2. **实时状态同步**: 基于Redis的实时消息推送和状态更新
3. **全面生命周期跟踪**: 从消息创建到确认完成的全流程监控
4. **增强统计分析**: 组织级、部门级、个人级的多维度分析
5. **向后兼容**: 保持现有API和数据结构的兼容性
此方案基于现有代码架构,最大程度复用已有功能,通过渐进式改进实现完整的消息数据流集成。