Browse Source

refactor(agent): 优化消息气泡布局和样式

- 调整消息气泡的内边距和圆角样式,提升视觉一致性
- 移除冗余的播放列表容器和按钮,简化UI结构
- 修复变量命名错误,将`mate`改为`meta`
weicu
lxm 1 year ago
parent
commit
4ed2d05d73
  1. 6
      .gitignore
  2. 12
      lib/modules/agent/views/agent_view.dart
  3. 205
      lib/modules/agent/views/message_bubble.dart
  4. 3
      lib/modules/home/controllers/home_controller.dart

6
.gitignore

@ -136,3 +136,9 @@ coverage/
*.js_
*.js.deps
*.js.map
linux/flutter/generated_plugin_registrant.cc
linux/flutter/generated_plugin_registrant.h
linux/flutter/generated_plugins.cmake
windows/flutter/generated_plugin_registrant.cc
windows/flutter/generated_plugin_registrant.h
windows/flutter/generated_plugins.cmake

12
lib/modules/agent/views/agent_view.dart

@ -149,8 +149,11 @@ class AgentView extends StatelessWidget {
// 聊天内容
Expanded(
child: Obx(
() => ListView.builder(
() => Align(
alignment: Alignment.topCenter,
child: ListView.builder(
controller: controller.scrollController,
shrinkWrap: true,
reverse: true,
padding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 16),
@ -167,13 +170,14 @@ class AgentView extends StatelessWidget {
isRecognizing: message.isRecognizing,
hasImage: message.hasImage,
imagePath: message.imagePath,
mate: message.meta,
meta: message.meta,
),
);
},
),
),
),
),
// 输入区域
Container(
@ -308,7 +312,7 @@ class AgentView extends StatelessWidget {
if (isTextMode) {
// 文本输入模式 - 注意观察图片模式时的高度变化
return Container(
height: 44,
//height: 44,
padding: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Colors.grey[200],
@ -378,7 +382,7 @@ class AgentView extends StatelessWidget {
}
},
child: Container(
height: 44,
height: 50,
padding:
const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(

205
lib/modules/agent/views/message_bubble.dart

@ -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,
);
}),
],
),
),
);
}

3
lib/modules/home/controllers/home_controller.dart

@ -103,6 +103,9 @@ class HomeController extends GetxController {
// 设置监听器监听蓝牙服务状态变化
_setupStateListeners();
// 在初始化时自动触发一次刷新设备连接状态
refreshDeviceConnection();
}
/// 设置状态监听器

Loading…
Cancel
Save