|
|
|
@ -1,10 +1,12 @@ |
|
|
|
import 'package:common_utils/common_utils.dart'; |
|
|
|
import 'package:deep_voice/modules/agent/views/message_bubble_navigation.dart'; |
|
|
|
import 'weather_card.dart'; |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import 'package:intl/intl.dart'; |
|
|
|
import 'package:get_storage/get_storage.dart'; |
|
|
|
import 'dart:io'; |
|
|
|
import 'package:flutter_markdown/flutter_markdown.dart'; |
|
|
|
|
|
|
|
import '../controllers/agent_controller.dart'; |
|
|
|
|
|
|
|
@ -120,63 +122,63 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
} |
|
|
|
|
|
|
|
/// 构建头像 |
|
|
|
Widget _buildAvatar(bool isUser, BuildContext context) { |
|
|
|
if (isUser) { |
|
|
|
final storage = GetStorage(); |
|
|
|
final localAvatarPath = storage.read<String>('local_avatar') ?? ''; |
|
|
|
// Widget _buildAvatar(bool isUser, BuildContext context) { |
|
|
|
// if (isUser) { |
|
|
|
// final storage = GetStorage(); |
|
|
|
// final localAvatarPath = storage.read<String>('local_avatar') ?? ''; |
|
|
|
|
|
|
|
return Container( |
|
|
|
width: 36, |
|
|
|
height: 36, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: localAvatarPath.isEmpty ? Colors.grey[300] : null, |
|
|
|
borderRadius: BorderRadius.circular(18), |
|
|
|
boxShadow: [ |
|
|
|
BoxShadow( |
|
|
|
color: Colors.black.withOpacity(0.05), |
|
|
|
blurRadius: 2, |
|
|
|
offset: const Offset(0, 1), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: localAvatarPath.isNotEmpty |
|
|
|
? ClipRRect( |
|
|
|
borderRadius: BorderRadius.circular(18), |
|
|
|
child: Image.file( |
|
|
|
File(localAvatarPath), |
|
|
|
fit: BoxFit.cover, |
|
|
|
), |
|
|
|
) |
|
|
|
: Icon( |
|
|
|
Icons.person, |
|
|
|
color: Colors.grey[700], |
|
|
|
size: 20, |
|
|
|
), |
|
|
|
); |
|
|
|
} else { |
|
|
|
// AI头像保持不变 |
|
|
|
return Container( |
|
|
|
width: 36, |
|
|
|
height: 36, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Theme.of(context).primaryColor, |
|
|
|
borderRadius: BorderRadius.circular(18), |
|
|
|
boxShadow: [ |
|
|
|
BoxShadow( |
|
|
|
color: Colors.black.withOpacity(0.05), |
|
|
|
blurRadius: 2, |
|
|
|
offset: const Offset(0, 1), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
Icons.smart_toy_outlined, |
|
|
|
color: Colors.white, |
|
|
|
size: 20, |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
// return Container( |
|
|
|
// width: 36, |
|
|
|
// height: 36, |
|
|
|
// decoration: BoxDecoration( |
|
|
|
// color: localAvatarPath.isEmpty ? Colors.grey[300] : null, |
|
|
|
// borderRadius: BorderRadius.circular(18), |
|
|
|
// boxShadow: [ |
|
|
|
// BoxShadow( |
|
|
|
// color: Colors.black.withOpacity(0.05), |
|
|
|
// blurRadius: 2, |
|
|
|
// offset: const Offset(0, 1), |
|
|
|
// ), |
|
|
|
// ], |
|
|
|
// ), |
|
|
|
// child: localAvatarPath.isNotEmpty |
|
|
|
// ? ClipRRect( |
|
|
|
// borderRadius: BorderRadius.circular(18), |
|
|
|
// child: Image.file( |
|
|
|
// File(localAvatarPath), |
|
|
|
// fit: BoxFit.cover, |
|
|
|
// ), |
|
|
|
// ) |
|
|
|
// : Icon( |
|
|
|
// Icons.person, |
|
|
|
// color: Colors.grey[700], |
|
|
|
// size: 20, |
|
|
|
// ), |
|
|
|
// ); |
|
|
|
// } else { |
|
|
|
// // AI头像保持不变 |
|
|
|
// return Container( |
|
|
|
// width: 36, |
|
|
|
// height: 36, |
|
|
|
// decoration: BoxDecoration( |
|
|
|
// color: Theme.of(context).primaryColor, |
|
|
|
// borderRadius: BorderRadius.circular(18), |
|
|
|
// boxShadow: [ |
|
|
|
// BoxShadow( |
|
|
|
// color: Colors.black.withOpacity(0.05), |
|
|
|
// blurRadius: 2, |
|
|
|
// offset: const Offset(0, 1), |
|
|
|
// ), |
|
|
|
// ], |
|
|
|
// ), |
|
|
|
// child: Icon( |
|
|
|
// Icons.smart_toy_outlined, |
|
|
|
// color: Colors.white, |
|
|
|
// size: 20, |
|
|
|
// ), |
|
|
|
// ); |
|
|
|
// } |
|
|
|
// } |
|
|
|
|
|
|
|
/// 构建消息内容 |
|
|
|
Widget _buildMessageContent(BuildContext context) { |
|
|
|
@ -300,6 +302,81 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
// } |
|
|
|
} |
|
|
|
|
|
|
|
// 使用Markdown渲染AI消息,用户消息仍然使用普通文本 |
|
|
|
if (!isUser) { |
|
|
|
return MarkdownBody( |
|
|
|
data: message, |
|
|
|
styleSheet: MarkdownStyleSheet( |
|
|
|
p: TextStyle( |
|
|
|
color: Theme.of(context).brightness == Brightness.dark |
|
|
|
? Colors.white.withOpacity(0.9) |
|
|
|
: Colors.black87, |
|
|
|
fontSize: 14, |
|
|
|
height: 1.4, |
|
|
|
fontWeight: FontWeight.w400, |
|
|
|
), |
|
|
|
h1: TextStyle( |
|
|
|
color: Theme.of(context).brightness == Brightness.dark |
|
|
|
? Colors.white |
|
|
|
: Colors.black, |
|
|
|
fontSize: 18, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
), |
|
|
|
h2: TextStyle( |
|
|
|
color: Theme.of(context).brightness == Brightness.dark |
|
|
|
? Colors.white |
|
|
|
: Colors.black, |
|
|
|
fontSize: 16, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
), |
|
|
|
h3: TextStyle( |
|
|
|
color: Theme.of(context).brightness == Brightness.dark |
|
|
|
? Colors.white |
|
|
|
: Colors.black, |
|
|
|
fontSize: 15, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
), |
|
|
|
code: TextStyle( |
|
|
|
backgroundColor: Theme.of(context).brightness == Brightness.dark |
|
|
|
? Colors.grey[800] |
|
|
|
: Colors.grey[200], |
|
|
|
fontFamily: 'monospace', |
|
|
|
fontSize: 13, |
|
|
|
), |
|
|
|
codeblockDecoration: BoxDecoration( |
|
|
|
color: Theme.of(context).brightness == Brightness.dark |
|
|
|
? Colors.grey[800] |
|
|
|
: Colors.grey[200], |
|
|
|
borderRadius: BorderRadius.circular(4), |
|
|
|
), |
|
|
|
blockquote: TextStyle( |
|
|
|
color: Theme.of(context).brightness == Brightness.dark |
|
|
|
? Colors.grey[400] |
|
|
|
: Colors.grey[700], |
|
|
|
fontSize: 14, |
|
|
|
fontStyle: FontStyle.italic, |
|
|
|
), |
|
|
|
blockquoteDecoration: BoxDecoration( |
|
|
|
border: Border( |
|
|
|
left: BorderSide( |
|
|
|
color: Theme.of(context).brightness == Brightness.dark |
|
|
|
? Colors.grey[600]! |
|
|
|
: Colors.grey[400]!, |
|
|
|
width: 4, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
listBullet: TextStyle( |
|
|
|
color: Theme.of(context).brightness == Brightness.dark |
|
|
|
? Colors.white.withOpacity(0.9) |
|
|
|
: Colors.black87, |
|
|
|
fontSize: 14, |
|
|
|
), |
|
|
|
), |
|
|
|
selectable: true, |
|
|
|
); |
|
|
|
} |
|
|
|
// 用户消息仍然使用普通文本 |
|
|
|
return Text( |
|
|
|
message, |
|
|
|
style: TextStyle( |
|
|
|
|