From 9ce06b8ae14c84eb67b8c97db15765f0deb5d68e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AD=90=E8=B4=A4?= Date: Thu, 26 Feb 2026 18:26:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=92=E7=89=88=E4=BC=98=E5=8C=96=E5=AE=8C?= =?UTF-8?q?=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/discover/month_task_detail.dart | 142 +++++++++++++++ lib/pages/discover/settlement_page.dart | 31 +++- lib/pages/home/content_card.dart | 45 ++--- lib/pages/message/conversation_tab.dart | 41 ++++- .../live/live_room_anchor_showcase.dart | 161 +++++++++++------ lib/widget/live/month_task_dialog.dart | 166 ++++++++++++++++++ 6 files changed, 485 insertions(+), 101 deletions(-) create mode 100644 lib/pages/discover/month_task_detail.dart create mode 100644 lib/widget/live/month_task_dialog.dart diff --git a/lib/pages/discover/month_task_detail.dart b/lib/pages/discover/month_task_detail.dart new file mode 100644 index 0000000..8258672 --- /dev/null +++ b/lib/pages/discover/month_task_detail.dart @@ -0,0 +1,142 @@ +import 'package:dating_touchme_app/components/page_appbar.dart'; +import 'package:dating_touchme_app/controller/discover/room_controller.dart'; +import 'package:dating_touchme_app/model/discover/task_template_data.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +class MonthTaskDetail extends StatefulWidget { + const MonthTaskDetail({super.key}); + + @override + State createState() => _MonthTaskDetailState(); +} + +class _MonthTaskDetailState extends State { + @override + Widget build(BuildContext context) { + + final roomController = Get.find(); + return Obx( + () { + return Scaffold( + appBar: PageAppbar(title: "任务详情"), + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.symmetric( + vertical: 20.w, + horizontal: 15.w + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + IntrinsicHeight( + child: Container( + margin: EdgeInsets.only(bottom: 21.w), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(width: 1.w, color: const Color.fromRGBO(212, 212, 212, 1)) + ) + ), + child: Row( + children: [ + Container( + width: 229.w, + decoration: BoxDecoration( + border: Border( + right: BorderSide(width: 1.w, color: const Color.fromRGBO(212, 212, 212, 1)) + ) + ), + child: Column( + children: [ + Container( + height: 37.w, + color: const Color.fromRGBO(247, 247, 247, 1), + child: Center( + child: Text( + "任务详情", + style: TextStyle( + fontSize: 14.w + ), + ), + ), + ), + for (int i = 0; i < roomController.taskTemplateData.value.subList!.length; i++) + Container( + padding: EdgeInsets.only(left: 14.w, right: 18.w, top: 8.w, bottom: 8.w), + decoration: BoxDecoration( + border: i < roomController.taskTemplateData.value.subList!.length - 1 ? Border( + bottom: BorderSide(width: 1.w, color: const Color.fromRGBO(212, 212, 212, 1)) + ) : null + ), + alignment: Alignment.centerLeft, + child: Text( + "${i + 1}.${ + roomController.taskTemplateData.value.subList![i].subTaskDesc ?? "" + }", + style: TextStyle( + fontSize: 14.w + ), + ), + ), + ], + ), + ), + Expanded( + child: Column( + children: [ + Container( + height: 37.w, + color: const Color.fromRGBO(247, 247, 247, 1), + child: Center( + child: Text( + "任务奖励", + style: TextStyle( + fontSize: 14.w + ), + ), + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.only(left: 14.w, right: 18.w), + alignment: Alignment.center, + child: Text( + "${roomController.taskTemplateData.value.rewardValue ?? ""}元", + style: TextStyle( + fontSize: 18.w, + color: const Color.fromRGBO(239, 19, 46, 1) + ), + ), + ), + ) + ], + ), + ) + ], + ), + ), + ), + Text( + "任务说明", + style: TextStyle( + fontSize: 14.w + ), + ), + SizedBox(height: 6.w,), + Text( + "${roomController.taskTemplateData.value.taskDesc ?? ""}", + style: TextStyle( + fontSize: 14.w, + color: const Color.fromRGBO(144, 144, 144, 1) + ), + ) + ], + ), + ), + ), + ); + } + ); + } +} diff --git a/lib/pages/discover/settlement_page.dart b/lib/pages/discover/settlement_page.dart index ddee3ee..db3b71e 100644 --- a/lib/pages/discover/settlement_page.dart +++ b/lib/pages/discover/settlement_page.dart @@ -3,6 +3,7 @@ import 'package:dating_touchme_app/components/page_appbar.dart'; import 'package:dating_touchme_app/extension/ex_widget.dart'; import 'package:dating_touchme_app/generated/assets.dart'; import 'package:dating_touchme_app/pages/setting/match_task_page.dart'; +import 'package:dating_touchme_app/widget/live/month_task_dialog.dart'; import 'package:dating_touchme_app/widget/live/today_task_dialog.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -254,11 +255,35 @@ class _SettlementPageState extends State { } }), SizedBox(height: 7.w,), - if(false) Image.asset( + Image.asset( Assets.imagesSettlementMonth, width: 325.w, - ).onTap(() { - Get.to(() => MatchTaskPage()); + ).onTap(() async { + try{ + await _roomController.getTaskData(); + + FocusScope.of(context).unfocus(); + // 隐藏 overlay + SmartDialog.dismiss(); + _roomController.setDialogDismiss(true); + + + + SmartDialog.show( + alignment: Alignment.bottomCenter, + maskColor: TDTheme.of(context).fontGyColor2, + onDismiss: (){ + _roomController.setDialogDismiss(false); + }, + + builder: (_) { + return MonthTaskDialog(); + }, + ); + } catch (e){ + SmartDialog.showToast('暂无任务'); + + } }), Spacer(), Container( diff --git a/lib/pages/home/content_card.dart b/lib/pages/home/content_card.dart index fdf2ab5..65b8af4 100644 --- a/lib/pages/home/content_card.dart +++ b/lib/pages/home/content_card.dart @@ -138,16 +138,7 @@ class _CardHeader extends StatelessWidget { color: Color.fromRGBO(38, 199, 124, 1), ), ), - ).onTap(() async { - late final RoomController roomController; - - if (Get.isRegistered()) { - roomController = Get.find(); - } else { - roomController = Get.put(RoomController()); - } - await roomController.joinChannel(item.isLiveChannelId ?? ""); - }), + ), ], ), ], @@ -171,31 +162,15 @@ class _CardHeader extends StatelessWidget { InkWell( onTap: () async { // 点击事件处理 - if (isLive) { - // 进入直播间逻辑 - try { - // 1. 隐藏直播间小窗口(如果存在) - if (Get.isRegistered()) { - final overlayController = Get.find(); - overlayController.hide(); - } + if (item.liveStreaming) { + late final RoomController roomController; - // 2. 获取 RoomController 实例 - final roomController = Get.isRegistered() - ? Get.find() - : Get.put(RoomController()); - - // 3. 如果当前已经在直播间,先退出当前直播间 - // leaveChannel 内部会处理未在频道时的情况 - await roomController.leaveChannel(); - - // 4. 跳转到新的直播间页面 - // 这里暂时使用 id: 0,实际频道信息由后端/进入逻辑决定 - await Get.to(() => const LiveRoomPage(id: 0)); - } catch (e) { - print('❌ [ContentCard] 进入直播间失败: $e'); - SmartDialog.showToast('进入直播间失败,请重试'); + if (Get.isRegistered()) { + roomController = Get.find(); + } else { + roomController = Get.put(RoomController()); } + await roomController.joinChannel(item.isLiveChannelId ?? ""); } else if (isOnline) { // HI按钮点击逻辑 - 跳转到聊天页面 try { @@ -230,7 +205,7 @@ class _CardHeader extends StatelessWidget { }, child: Image.asset( _getButtonImage(isLive, isOnline), - width: isLive ? 60 : 50, + width: item.liveStreaming ? 60 : 50, height: 30, ), ), @@ -239,7 +214,7 @@ class _CardHeader extends StatelessWidget { } String _getButtonImage(bool isLive, bool isOnline) { - if (isLive) { + if (item.liveStreaming) { return Assets.imagesLiveIcon; // 直播显示直播间按钮(放在HI位置) } else if (isOnline) { return Assets.imagesHiIcon; // 在线显示HI按钮 diff --git a/lib/pages/message/conversation_tab.dart b/lib/pages/message/conversation_tab.dart index fb2dc42..4e523fe 100644 --- a/lib/pages/message/conversation_tab.dart +++ b/lib/pages/message/conversation_tab.dart @@ -225,15 +225,42 @@ class _BuildConversationItemState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: Text( - userInfo?.nickName ?? conversation.id, // 如果没有昵称,显示用户ID - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Colors.black, - ), + child: Row( + children: [ + Flexible( + child: Text( + userInfo?.nickName ?? conversation.id, // 如果没有昵称,显示用户ID + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + ), + ), + if(isOnline) Container( + width: 33.w, + height: 13.w, + margin: EdgeInsets.only(left: 6.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(13.w)), + color: const Color.fromRGBO(234, 255, 219, 1) + ), + child: Center( + child: Text( + "在线", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(38, 199, 124, 1) + ), + ), + ), + ), + ], ), ), + SizedBox(width: 6.w,), Text( controller.formatMessageTime( message?.serverTime ?? 0, diff --git a/lib/widget/live/live_room_anchor_showcase.dart b/lib/widget/live/live_room_anchor_showcase.dart index 6ea54e6..4e0bab4 100644 --- a/lib/widget/live/live_room_anchor_showcase.dart +++ b/lib/widget/live/live_room_anchor_showcase.dart @@ -1,5 +1,6 @@ import 'package:agora_rtc_engine/agora_rtc_engine.dart'; import 'package:dating_touchme_app/controller/discover/room_controller.dart'; +import 'package:dating_touchme_app/controller/global.dart'; import 'package:dating_touchme_app/extension/ex_widget.dart'; import 'package:dating_touchme_app/generated/assets.dart'; import 'package:dating_touchme_app/model/rtc/rtc_channel_detail.dart'; @@ -12,7 +13,9 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; +import '../../model/live/live_chat_message.dart'; import 'live_room_invitation_list.dart'; +import 'live_room_user_profile_dialog.dart'; class LiveRoomAnchorShowcase extends StatefulWidget { const LiveRoomAnchorShowcase({super.key}); @@ -336,32 +339,67 @@ class _LiveRoomAnchorShowcaseState extends State { Positioned( bottom: 5.w, right: 5.w, - child: GestureDetector( - onTap: (){ - if(userInfo.isFriend == true){ - return; - } - _showGiftPopupForUser(userInfo, 2); - }, - child: Container( - width: 47.w, - height: 20.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(20.w), - ), - color: Colors.white, - ), - child: Center( - child: Text( - userInfo.isFriend != true ? "加好友" : '好友', - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(117, 98, 249, 1), + child: Row( + children: [ + GestureDetector( + onTap: (){ + if(userInfo.isFriend == true){ + return; + } + _showGiftPopupForUser(userInfo, 2); + }, + child: Container( + width: 47.w, + height: 20.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(20.w), + ), + color: Colors.white, + ), + child: Center( + child: Text( + userInfo.isFriend != true ? "加好友" : '好友', + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(117, 98, 249, 1), + ), + ), + ), ), ), - ), - ), + SizedBox(width: 5.w,), + Container( + width: 20.w, + height: 20.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(4.w), + ), + color: const Color.fromRGBO(0, 0, 0, .65), + ), + child: Center( + child: Image.asset( + userInfo.isMicrophoneOn + ? Assets.imagesMicOpen + : Assets.imagesMicClose, + width: 10.w, + height: 11.w, + ), + ), + ).onTap(() { + if((isLeft && _roomController.currentRole == CurrentRole.maleAudience) || (!isLeft && _roomController.currentRole == CurrentRole.femaleAudience)){ + userInfo.isMicrophoneOn = !(userInfo.isMicrophoneOn ?? false); + + RTCManager.instance.muteLocalAudio(!(userInfo.isMicrophoneOn ?? false)); + + _roomController.changeMic(userInfo.isMicrophoneOn ?? false); + setState(() { + + }); + } + }), + ], ), ), Positioned( @@ -369,43 +407,54 @@ class _LiveRoomAnchorShowcaseState extends State { bottom: 5.w, child: Row( children: [ - Container( - width: 20.w, - height: 20.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(4.w), - ), - color: const Color.fromRGBO(0, 0, 0, .65), - ), - child: Center( - child: Image.asset( - userInfo.isMicrophoneOn - ? Assets.imagesMicOpen - : Assets.imagesMicClose, - width: 10.w, - height: 11.w, - ), + ClipOval( + child: Image.network( + userInfo.profilePhoto, + width: 15.w, + height: 15.w, + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) { + return Image.asset( + Assets.imagesUserAvatar, + width: 15.w, + height: 15.w, + ); + }, ), ).onTap(() { - if((isLeft && _roomController.currentRole == CurrentRole.maleAudience) || (!isLeft && _roomController.currentRole == CurrentRole.femaleAudience)){ - userInfo.isMicrophoneOn = !(userInfo.isMicrophoneOn ?? false); - - RTCManager.instance.muteLocalAudio(!(userInfo.isMicrophoneOn ?? false)); - - _roomController.changeMic(userInfo.isMicrophoneOn ?? false); - setState(() { - - }); + // 检查是否是当前用户自己的消息 + final currentUserId = GlobalData().userId ?? GlobalData().userData?.id; + if (currentUserId != null && currentUserId == userInfo.userId) { + // 是自己的头像,不显示弹框 + return; } + // 不是自己的消息,显示用户资料对话框 + showUserProfileDialog( + context, + LiveChatMessage( + userId: userInfo.userId, + uid: userInfo.uid, + userName: userInfo.nickName, + avatar: userInfo.profilePhoto, + content: "", + timestamp: 0 + ), + () => + _showGiftPopupForUser(userInfo, 1), + ); }), SizedBox(width: 5.w), - Text( - userInfo.nickName, - style: TextStyle( - fontSize: 11.w, - color: Colors.white, - fontWeight: FontWeight.w500, + SizedBox( + width: 70.w, + child: Text( + userInfo.nickName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 11.w, + color: Colors.white, + fontWeight: FontWeight.w500, + ), ), ), ], diff --git a/lib/widget/live/month_task_dialog.dart b/lib/widget/live/month_task_dialog.dart new file mode 100644 index 0000000..ae8089b --- /dev/null +++ b/lib/widget/live/month_task_dialog.dart @@ -0,0 +1,166 @@ +import 'package:dating_touchme_app/controller/discover/room_controller.dart'; +import 'package:dating_touchme_app/extension/ex_widget.dart'; +import 'package:dating_touchme_app/model/discover/task_data.dart'; +import 'package:dating_touchme_app/pages/discover/task_detail.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:get/get.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; + +import '../../pages/discover/month_task_detail.dart'; + +class MonthTaskDialog extends StatefulWidget { + const MonthTaskDialog({super.key}); + + @override + State createState() => _MonthTaskDialogState(); +} + +class _MonthTaskDialogState extends State { + @override + Widget build(BuildContext context) { + + final roomController = Get.find(); + return ClipRRect( + borderRadius: BorderRadius.vertical(top: Radius.circular(9.w)), + child: Material( + color: Colors.white, + child: Container( + width: 375.w, + height: 336.w, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color.fromRGBO(236, 224, 255, 1), // 0% + Color.fromRGBO(247, 247, 247, 1), // 100% + ], + ), + ), + child: Column( + children: [ + SizedBox( + height: 77.w, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 68.w, + padding: EdgeInsets.only(left: 15.w), + alignment: Alignment.centerLeft, + child: Icon( + Icons.keyboard_arrow_left, + size: 26.w, + color: const Color.fromRGBO(144, 144, 144, 1), + ), + ), + Text( + "本月任务", + style: TextStyle( + fontSize: 21.w, + fontWeight: FontWeight.w700 + ), + ), + Container( + width: 68.w, + height: 22.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.horizontal(left: Radius.circular(22.w)), + color: Colors.white + ), + child: Center( + child: Text( + "任务详情", + style: TextStyle( + fontSize: 12.w, + color: const Color.fromRGBO(144, 144, 144, 1) + ), + ), + ), + ).onTap(() async { + // 隐藏键盘 + FocusScope.of(context).unfocus(); + // 隐藏 overlay + await roomController.getTaskTemplateData(); + await SmartDialog.dismiss(); + Get.to(() => MonthTaskDetail()); + }) + ], + ), + ), + SingleChildScrollView( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: Column( + children: [ + ...roomController.taskData.value.subList!.map((e){ + return TaskItem(item: e,); + }) + ], + ), + ), + ) + ], + ), + ), + ), + ); + } +} + + +class TaskItem extends StatefulWidget { + final SubList item; + const TaskItem({super.key, required this.item}); + + @override + State createState() => _TaskItemState(); +} + +class _TaskItemState extends State { + @override + Widget build(BuildContext context) { + return Container( + width: 350.w, + margin: EdgeInsets.only(bottom: 10.w), + padding: EdgeInsets.only( + top: 15.w, + right: 10.w, + bottom: 21.w, + left: 12.w + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.item.subTaskDesc ?? "", + style: TextStyle( + fontSize: 14.w + ), + ), + Text( + "${widget.item.completeCount ?? ""}/${widget.item.requiredCount ?? ""}${widget.item.sort == 1 ? "分钟" : widget.item.sort == 2 ? "对" : "人"}", + style: TextStyle( + fontSize: 12.w, + color: const Color.fromRGBO(144, 144, 144, 1) + ), + ) + ], + ), + SizedBox(height: 10.w,), + TDProgress( + type: TDProgressType.linear, + value: ((widget.item.completeCount ?? 0) / (widget.item.requiredCount ?? 0)), + strokeWidth: 6, + progressLabelPosition: TDProgressLabelPosition.inside, + showLabel: false, + ) + ], + ), + ); + } +}