import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../controllers/chat_controller.dart'; import '../models/message_model.dart'; import '../../../data/services/volcano_tts_service.dart'; class ChatView extends GetView { const ChatView({Key? key}) : super(key: key); Widget _buildMessage(Message message) { final isUser = message.role == 'user'; return Padding( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), child: Row( mainAxisAlignment: isUser ? MainAxisAlignment.end : MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ if (!isUser) ...[ CircleAvatar( radius: 20.r, backgroundImage: AssetImage(controller.agentAvatar), backgroundColor: Colors.transparent, ), SizedBox(width: 12.w), ], Flexible( child: Container( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h), decoration: BoxDecoration( color: isUser ? const Color(0xFF4A6FE5) : const Color(0xFFF5F5F5), borderRadius: BorderRadius.only( topLeft: Radius.circular(isUser ? 18.r : 4.r), topRight: Radius.circular(isUser ? 4.r : 18.r), bottomLeft: Radius.circular(18.r), bottomRight: Radius.circular(18.r), ), ), child: Text( message.content, style: TextStyle( fontSize: 16.sp, color: isUser ? Colors.white : Colors.black87, height: 1.5, ), ), ), ), if (isUser) ...[ SizedBox(width: 12.w), CircleAvatar( radius: 20.r, backgroundColor: const Color(0xFFEEF4FF), child: Icon( Icons.person, color: const Color(0xFF4A6FE5), size: 24.sp, ), ), ], ], ), ); } @override Widget build(BuildContext context) { // 添加布局完成后的回调 WidgetsBinding.instance.addPostFrameCallback((_) { if (controller.scrollController.hasClients) { controller.scrollController.jumpTo( controller.scrollController.position.maxScrollExtent, ); } }); return WillPopScope( onWillPop: () async { final tts = Get.find(); await tts.stop(); Get.delete(); // 删除控制器 return true; }, child: Scaffold( backgroundColor: Colors.white, appBar: AppBar( backgroundColor: Colors.white, elevation: 0, leading: IconButton( icon: Icon( Icons.arrow_back_ios, color: Colors.black, size: 20.sp, ), onPressed: () async { final tts = Get.find(); await tts.stop(); Get.delete(); // 删除控制器 Get.back(); }, ), title: Column( children: [ Text( controller.agentName, style: TextStyle( fontSize: 17.sp, fontWeight: FontWeight.w600, color: Colors.black, ), ), if (controller.agentSubtitle != null) Text( controller.agentSubtitle!, style: TextStyle( fontSize: 12.sp, color: Colors.grey[600], ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), centerTitle: true, actions: [ IconButton( icon: Obx(() => Icon( Get.find().isEnabled.value ? Icons.volume_up : Icons.volume_off, color: Colors.black, size: 24.sp, )), onPressed: controller.toggleTTS, ), IconButton( icon: Icon( Icons.more_horiz, color: Colors.black, size: 24.sp, ), onPressed: () { Get.bottomSheet( Container( padding: EdgeInsets.all(20.w), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(20.r), topRight: Radius.circular(20.r), ), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( leading: const Icon(Icons.delete_outline, color: Colors.red), title: const Text('清空对话'), onTap: () { Get.back(); controller.clearChat(); }, ), ], ), ), ); }, ), ], ), body: Column( children: [ Expanded( child: Obx(() => ListView.builder( controller: controller.scrollController, padding: EdgeInsets.symmetric(vertical: 16.h), itemCount: controller.messages.length, itemBuilder: (context, index) => _buildMessage(controller.messages[index]), physics: const AlwaysScrollableScrollPhysics(), clipBehavior: Clip.none, keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, )), ), Obx(() => controller.isLoading.value ? Container( padding: EdgeInsets.symmetric(vertical: 8.h), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 16.w, height: 16.w, child: const CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Color(0xFF4A6FE5)), ), ), SizedBox(width: 8.w), Text( '正在思考...', style: TextStyle( fontSize: 14.sp, color: Colors.grey[600], ), ), ], ), ) : const SizedBox.shrink(), ), Container( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), decoration: BoxDecoration( color: Colors.white, border: Border( top: BorderSide( color: Colors.grey[200]!, width: 1, ), ), ), child: SafeArea( child: Row( children: [ Expanded( child: Container( padding: EdgeInsets.symmetric(horizontal: 16.w), decoration: BoxDecoration( color: Colors.grey[100], borderRadius: BorderRadius.circular(24.r), ), child: TextField( controller: controller.textController, decoration: InputDecoration( hintText: '发消息...', hintStyle: TextStyle( color: Colors.grey[400], fontSize: 16.sp, ), border: InputBorder.none, ), style: TextStyle( fontSize: 16.sp, ), maxLines: 1, textInputAction: TextInputAction.send, onSubmitted: controller.sendMessage, ), ), ), SizedBox(width: 12.w), GestureDetector( onTap: () { if (controller.textController.text.isNotEmpty) { controller.sendMessage(controller.textController.text); } }, child: Container( width: 40.w, height: 40.w, decoration: BoxDecoration( color: const Color(0xFF4A6FE5), borderRadius: BorderRadius.circular(20.r), ), child: Icon( Icons.send, color: Colors.white, size: 20.sp, ), ), ), ], ), ), ), ], ), ), ); } }