|
|
|
@ -15,7 +15,7 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
final bool isRecognizing; |
|
|
|
final bool hasImage; |
|
|
|
final String? imagePath; |
|
|
|
final Map? mate; |
|
|
|
final Map? meta; |
|
|
|
|
|
|
|
const MessageBubble({ |
|
|
|
Key? key, |
|
|
|
@ -25,7 +25,7 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
this.isRecognizing = false, |
|
|
|
this.hasImage = false, |
|
|
|
this.imagePath, |
|
|
|
this.mate, |
|
|
|
this.meta, |
|
|
|
}) : super(key: key); |
|
|
|
|
|
|
|
@override |
|
|
|
@ -39,8 +39,8 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
isUser ? MainAxisAlignment.end : MainAxisAlignment.start, |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
if (!isUser) _buildAvatar(isUser, context), |
|
|
|
const SizedBox(width: 8), |
|
|
|
//if (!isUser) _buildAvatar(isUser, context), |
|
|
|
//const SizedBox(width: 8), |
|
|
|
Flexible( |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: |
|
|
|
@ -50,15 +50,23 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
padding: hasImage |
|
|
|
? (message == '[图片]' |
|
|
|
? EdgeInsets.zero |
|
|
|
: const EdgeInsets.all(12)) |
|
|
|
: const EdgeInsets.all(12), |
|
|
|
: isUser |
|
|
|
? const EdgeInsets.fromLTRB( |
|
|
|
12, 12, 16, 12) // 用户消息右侧多一点内边距 |
|
|
|
: const EdgeInsets.fromLTRB( |
|
|
|
16, 12, 12, 12)) // AI消息左侧多一点内边距 |
|
|
|
: isUser |
|
|
|
? const EdgeInsets.fromLTRB( |
|
|
|
12, 12, 16, 12) // 用户消息右侧多一点内边距 |
|
|
|
: const EdgeInsets.fromLTRB( |
|
|
|
16, 12, 12, 12), // AI消息左侧多一点内边距 |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: _getBubbleColor(context), |
|
|
|
borderRadius: BorderRadius.circular(18).copyWith( |
|
|
|
bottomLeft: isUser |
|
|
|
topLeft: isUser |
|
|
|
? const Radius.circular(18) |
|
|
|
: const Radius.circular(4), |
|
|
|
bottomRight: !isUser |
|
|
|
topRight: !isUser |
|
|
|
? const Radius.circular(18) |
|
|
|
: const Radius.circular(4), |
|
|
|
), |
|
|
|
@ -86,8 +94,8 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(width: 8), |
|
|
|
if (isUser) _buildAvatar(isUser, context), |
|
|
|
//const SizedBox(width: 8), |
|
|
|
//if (isUser) _buildAvatar(isUser, context), |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
@ -231,28 +239,29 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
} |
|
|
|
|
|
|
|
// 判断消息内容,显示特殊卡片 |
|
|
|
if (!isUser && mate != null) { |
|
|
|
if (mate!.keys.contains('card_music')) { |
|
|
|
final musicId = mate!['card_music']['id'].toString(); |
|
|
|
final musicName = mate!['card_music']['name'] as String; |
|
|
|
final musicUrl = mate!['card_music']['url'] as String; |
|
|
|
final musicSinger = mate!['card_music']['sgener'] as String; |
|
|
|
final musicImage = mate!['card_music']['image'] as String; |
|
|
|
if (!isUser && meta != null) { |
|
|
|
// 判断消息类型,显示不同的卡片 |
|
|
|
if (meta!.keys.contains('card_music')) { |
|
|
|
final musicId = meta!['card_music']['id'].toString(); |
|
|
|
final musicName = meta!['card_music']['name'] as String; |
|
|
|
final musicUrl = meta!['card_music']['url'] as String; |
|
|
|
final musicSinger = meta!['card_music']['sgener'] as String; |
|
|
|
final musicImage = meta!['card_music']['image'] as String; |
|
|
|
//音乐卡片 |
|
|
|
return _buildMusicItem( |
|
|
|
context, musicId, musicName, musicUrl, musicSinger, musicImage); |
|
|
|
} else if (mate!.keys.contains('card_musiclist')) { |
|
|
|
final rawList = mate!['card_musiclist']['musics'] as List; |
|
|
|
} else if (meta!.keys.contains('card_musiclist')) { |
|
|
|
final rawList = meta!['card_musiclist']['musics'] as List; |
|
|
|
final playlist = |
|
|
|
rawList.map((e) => Map<String, dynamic>.from(e)).toList(); |
|
|
|
//音乐播放列表 |
|
|
|
return _buildMusicContent(context, playlist); |
|
|
|
} else if (mate!.keys.contains('card_weather')) { |
|
|
|
final city = mate!['card_weather']['city'] as String; |
|
|
|
final rawList = mate!['card_weather']['dayweather'] as List; |
|
|
|
} else if (meta!.keys.contains('card_weather')) { |
|
|
|
final city = meta!['card_weather']['city'] as String; |
|
|
|
final rawList = meta!['card_weather']['dayweather'] as List; |
|
|
|
final daylist = |
|
|
|
rawList.map((e) => Map<String, dynamic>.from(e)).toList(); |
|
|
|
final now = mate!['card_weather']['day'] as Map<String, dynamic>; |
|
|
|
final now = meta!['card_weather']['day'] as Map<String, dynamic>; |
|
|
|
//天气 |
|
|
|
return _buildWeatherContent( |
|
|
|
context, |
|
|
|
@ -321,21 +330,22 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(height: 12), |
|
|
|
Container( |
|
|
|
padding: const EdgeInsets.all(12), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Colors.white, |
|
|
|
borderRadius: BorderRadius.circular(12), |
|
|
|
boxShadow: [ |
|
|
|
BoxShadow( |
|
|
|
color: Colors.black.withOpacity(0.03), |
|
|
|
blurRadius: 3, |
|
|
|
spreadRadius: 1, |
|
|
|
offset: const Offset(0, 1), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: Column( |
|
|
|
// Container( |
|
|
|
// padding: const EdgeInsets.all(12), |
|
|
|
// decoration: BoxDecoration( |
|
|
|
// color: Colors.white, |
|
|
|
// borderRadius: BorderRadius.circular(12), |
|
|
|
// boxShadow: [ |
|
|
|
// BoxShadow( |
|
|
|
// color: Colors.black.withOpacity(0.03), |
|
|
|
// blurRadius: 3, |
|
|
|
// spreadRadius: 1, |
|
|
|
// offset: const Offset(0, 1), |
|
|
|
// ), |
|
|
|
// ], |
|
|
|
// ), |
|
|
|
// child: |
|
|
|
Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Row( |
|
|
|
@ -359,7 +369,7 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
const SizedBox(height: 10), |
|
|
|
|
|
|
|
// 动态生成音乐条目 |
|
|
|
...playlist.asMap().entries.map((entry) { |
|
|
|
...playlist.asMap().entries.take(4).map((entry) { |
|
|
|
final index = entry.key; |
|
|
|
final item = entry.value; |
|
|
|
final id = item["id"]?.toString() ?? ""; |
|
|
|
@ -396,47 +406,47 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(height: 10), |
|
|
|
Row( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
Expanded( |
|
|
|
child: OutlinedButton.icon( |
|
|
|
onPressed: () {}, |
|
|
|
icon: Icon(Icons.play_arrow, size: 16), |
|
|
|
label: Text('播放全部'), |
|
|
|
style: OutlinedButton.styleFrom( |
|
|
|
foregroundColor: Theme.of(context).primaryColor, |
|
|
|
side: BorderSide( |
|
|
|
color: Theme.of(context).primaryColor.withOpacity(0.5)), |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4), |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(16), |
|
|
|
), |
|
|
|
textStyle: TextStyle(fontSize: 12), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(width: 8), |
|
|
|
Expanded( |
|
|
|
child: OutlinedButton.icon( |
|
|
|
onPressed: () {}, |
|
|
|
icon: Icon(Icons.shuffle, size: 16), |
|
|
|
label: Text('随机播放'), |
|
|
|
style: OutlinedButton.styleFrom( |
|
|
|
foregroundColor: Colors.grey[700], |
|
|
|
side: BorderSide(color: Colors.grey[400]!), |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4), |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(16), |
|
|
|
), |
|
|
|
textStyle: TextStyle(fontSize: 12), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
//), |
|
|
|
//const SizedBox(height: 10), |
|
|
|
// Row( |
|
|
|
// mainAxisSize: MainAxisSize.min, |
|
|
|
// children: [ |
|
|
|
// Expanded( |
|
|
|
// child: OutlinedButton.icon( |
|
|
|
// onPressed: () {}, |
|
|
|
// icon: Icon(Icons.play_arrow, size: 16), |
|
|
|
// label: Text('播放全部'), |
|
|
|
// style: OutlinedButton.styleFrom( |
|
|
|
// foregroundColor: Theme.of(context).primaryColor, |
|
|
|
// side: BorderSide( |
|
|
|
// color: Theme.of(context).primaryColor.withOpacity(0.5)), |
|
|
|
// padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4), |
|
|
|
// shape: RoundedRectangleBorder( |
|
|
|
// borderRadius: BorderRadius.circular(16), |
|
|
|
// ), |
|
|
|
// textStyle: TextStyle(fontSize: 12), |
|
|
|
// ), |
|
|
|
// ), |
|
|
|
// ), |
|
|
|
// SizedBox(width: 8), |
|
|
|
// Expanded( |
|
|
|
// child: OutlinedButton.icon( |
|
|
|
// onPressed: () {}, |
|
|
|
// icon: Icon(Icons.shuffle, size: 16), |
|
|
|
// label: Text('随机播放'), |
|
|
|
// style: OutlinedButton.styleFrom( |
|
|
|
// foregroundColor: Colors.grey[700], |
|
|
|
// side: BorderSide(color: Colors.grey[400]!), |
|
|
|
// padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4), |
|
|
|
// shape: RoundedRectangleBorder( |
|
|
|
// borderRadius: BorderRadius.circular(16), |
|
|
|
// ), |
|
|
|
// textStyle: TextStyle(fontSize: 12), |
|
|
|
// ), |
|
|
|
// ), |
|
|
|
// ), |
|
|
|
// ], |
|
|
|
// ), |
|
|
|
], |
|
|
|
); |
|
|
|
} |
|
|
|
@ -578,22 +588,44 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
'coverUrl': image, |
|
|
|
}; |
|
|
|
controller.musicStatus(); //刷新状态 |
|
|
|
return Padding( |
|
|
|
return Container( |
|
|
|
padding: const EdgeInsets.all(12), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Colors.white, |
|
|
|
borderRadius: BorderRadius.circular(12), |
|
|
|
boxShadow: [ |
|
|
|
BoxShadow( |
|
|
|
color: Colors.black.withOpacity(0.03), |
|
|
|
blurRadius: 3, |
|
|
|
spreadRadius: 1, |
|
|
|
offset: const Offset(0, 1), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: Padding( |
|
|
|
padding: const EdgeInsets.symmetric(vertical: 8), |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
Container( |
|
|
|
width: 38, |
|
|
|
height: 38, |
|
|
|
width: 50, |
|
|
|
height: 50, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Colors.grey[100], |
|
|
|
borderRadius: BorderRadius.circular(8), |
|
|
|
image: image.isNotEmpty |
|
|
|
? DecorationImage( |
|
|
|
image: NetworkImage(image), |
|
|
|
fit: BoxFit.cover, |
|
|
|
) |
|
|
|
: null, |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
child: image.isEmpty |
|
|
|
? Icon( |
|
|
|
Icons.music_note, |
|
|
|
size: 18, |
|
|
|
color: Theme.of(context).primaryColor, |
|
|
|
), |
|
|
|
) |
|
|
|
: null, |
|
|
|
), |
|
|
|
const SizedBox(width: 12), |
|
|
|
Expanded( |
|
|
|
@ -647,11 +679,12 @@ class MessageBubble extends GetView<AgentController> { |
|
|
|
), |
|
|
|
padding: EdgeInsets.zero, |
|
|
|
constraints: BoxConstraints(), |
|
|
|
iconSize: 24, |
|
|
|
iconSize: 36, |
|
|
|
); |
|
|
|
}), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|