From a5c10b6ce376e1a02f123daf3f0295a299d11863 Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Sat, 25 Oct 2025 10:46:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(agent=5Fview):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E5=8C=BA=E5=9F=9F=E7=82=B9=E5=87=BB=E6=94=B6?= =?UTF-8?q?=E8=B5=B7=E9=94=AE=E7=9B=98=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E7=84=A6=E7=82=B9=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 FocusNode 用于控制 TextField 焦点 - 点击聊天区域时收起键盘并收起扩展选项 - 切换输入模式时自动管理焦点状态 --- lib/modules/agent/views/agent_view.dart | 200 +++++++++++++----------- 1 file changed, 113 insertions(+), 87 deletions(-) diff --git a/lib/modules/agent/views/agent_view.dart b/lib/modules/agent/views/agent_view.dart index d24352ca6..90c66e6b8 100644 --- a/lib/modules/agent/views/agent_view.dart +++ b/lib/modules/agent/views/agent_view.dart @@ -25,6 +25,9 @@ class _AgentViewState extends State with WidgetsBindingObserver { late MessageActionController messageActionController; double _keyboardHeight = 0; + // 👇 新增:用于控制 TextField 焦点 + final FocusNode _textFocusNode = FocusNode(); + @override void initState() { super.initState(); @@ -35,6 +38,7 @@ class _AgentViewState extends State with WidgetsBindingObserver { @override void dispose() { + _textFocusNode.dispose(); WidgetsBinding.instance.removeObserver(this); super.dispose(); } @@ -286,65 +290,102 @@ class _AgentViewState extends State with WidgetsBindingObserver { children: [ // 聊天内容 Expanded( - child: Obx(() { - return Align( - alignment: Alignment.topCenter, - child: ListView.builder( - controller: controller.scrollController, - shrinkWrap: true, - reverse: true, - padding: EdgeInsets.symmetric( - vertical: 16.h, horizontal: 16.w), - itemCount: controller.messages.length + - (controller.hasMoreMessages.value ? 1 : 0), - itemBuilder: (context, index) { - // 如果是最后一项且有更多消息,显示加载指示器 - if (index == controller.messages.length && - controller.hasMoreMessages.value) { - return _buildLoadMoreIndicator(); - } + child: GestureDetector( + onTap: () { + // 点击聊天区域时,收起键盘并切换工具显示状态 + FocusScope.of(context).unfocus(); + if (controller.isPlusOptionsExpanded.value) { + controller.collapsePlusOptions(); + } + }, + child: Obx(() { + return Align( + alignment: Alignment.topCenter, + child: ListView.builder( + controller: controller.scrollController, + shrinkWrap: true, + reverse: true, + padding: EdgeInsets.symmetric( + vertical: 16.h, horizontal: 16.w), + itemCount: controller.messages.length + + (controller.hasMoreMessages.value ? 1 : 0), + itemBuilder: (context, index) { + // 如果是最后一项且有更多消息,显示加载指示器 + if (index == controller.messages.length && + controller.hasMoreMessages.value) { + return _buildLoadMoreIndicator(); + } - final message = controller - .messages[controller.messages.length - 1 - index]; - return index == 0 - ? IntroStepBuilder( - group: 'ai', - order: 4, - getOverlayPosition: - IntroOverlayBuilder.overlayPosition, - overlayBuilder: (params) { - return IntroOverlayBuilder.aiBuilder( - params, - controller.noviceGuideService.aiStepsList[ - controller - .noviceGuideService.aiStep]['end'], - onFinish: () async { - if (controller.noviceGuideService.aiStep < - 5) { - await Future.delayed( - const Duration(milliseconds: 300)); - controller.noviceGuideService.aiStep++; - Intro.of(Get.context!) - .start(group: 'ai', reset: true); - } - }, - onTap: () async { - params.onFinish(); - if (controller.noviceGuideService.aiStep < - 5) { - await Future.delayed( - const Duration(milliseconds: 300)); - controller.noviceGuideService.aiStep++; - Intro.of(Get.context!) - .start(group: 'ai', reset: true); - } - }, - ); - }, - builder: - (BuildContext context, GlobalKey key) => - Padding( - key: key, + final message = controller + .messages[controller.messages.length - 1 - index]; + return index == 0 + ? IntroStepBuilder( + group: 'ai', + order: 4, + getOverlayPosition: + IntroOverlayBuilder.overlayPosition, + overlayBuilder: (params) { + return IntroOverlayBuilder.aiBuilder( + params, + controller.noviceGuideService.aiStepsList[ + controller.noviceGuideService + .aiStep]['end'], + onFinish: () async { + if (controller + .noviceGuideService.aiStep < + 5) { + await Future.delayed(const Duration( + milliseconds: 300)); + controller + .noviceGuideService.aiStep++; + Intro.of(Get.context!) + .start(group: 'ai', reset: true); + } + }, + onTap: () async { + params.onFinish(); + if (controller + .noviceGuideService.aiStep < + 5) { + await Future.delayed(const Duration( + milliseconds: 300)); + controller + .noviceGuideService.aiStep++; + Intro.of(Get.context!) + .start(group: 'ai', reset: true); + } + }, + ); + }, + builder: + (BuildContext context, GlobalKey key) => + Padding( + key: key, + padding: EdgeInsets.only(bottom: 8.h), + child: GestureDetector( + onLongPressStart: + (LongPressStartDetails details) { + messageActionController + .onLongPressMessage(context, + isDarkMode, details, message); + }, + child: MessageBubble( + sessionid: message.sessionid, + isUser: message.isUser, + message: message.text, + timestamp: message.timestamp, + isRecognizing: message.isRecognizing, + hasImage: message.hasImage, + imagePath: message.imagePath, + meta: message.meta, + functionCalls: message.functionCalls, + isToolCallsExpanded: + message.isToolCallsExpanded, + ), + ), + ), + ) + : Padding( padding: EdgeInsets.only(bottom: 8.h), child: GestureDetector( onLongPressStart: @@ -367,35 +408,12 @@ class _AgentViewState extends State with WidgetsBindingObserver { message.isToolCallsExpanded, ), ), - ), - ) - : Padding( - padding: EdgeInsets.only(bottom: 8.h), - child: GestureDetector( - onLongPressStart: - (LongPressStartDetails details) { - messageActionController.onLongPressMessage( - context, isDarkMode, details, message); - }, - child: MessageBubble( - sessionid: message.sessionid, - isUser: message.isUser, - message: message.text, - timestamp: message.timestamp, - isRecognizing: message.isRecognizing, - hasImage: message.hasImage, - imagePath: message.imagePath, - meta: message.meta, - functionCalls: message.functionCalls, - isToolCallsExpanded: - message.isToolCallsExpanded, - ), - ), - ); - }, - ), - ); - }), + ); + }, + ), + ); + }), + ), ), // 输入区域 @@ -553,6 +571,13 @@ class _AgentViewState extends State with WidgetsBindingObserver { return GestureDetector( onTap: () { controller.toggleInputMode(); + // 切换模式时,确保焦点正确 + if (!isTextMode) { + // 切换到语音模式时,请求焦点 + Future.delayed(Duration.zero, () { + _textFocusNode.requestFocus(); + }); + } }, child: Container( width: 44.w, @@ -652,6 +677,7 @@ class _AgentViewState extends State with WidgetsBindingObserver { controller.isImageInputActive.value; return TextField( + focusNode: _textFocusNode, // 绑定焦点节点 controller: controller.textController, maxLines: isImageActive ? 3