diff --git a/lib/widget/live/live_room_guest_list_dialog.dart b/lib/widget/live/live_room_guest_list_dialog.dart new file mode 100644 index 0000000..8ba417d --- /dev/null +++ b/lib/widget/live/live_room_guest_list_dialog.dart @@ -0,0 +1,380 @@ +import 'dart:convert'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:dating_touchme_app/im/im_manager.dart'; +import 'package:dating_touchme_app/network/network_service.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; + +/// 嘉宾列表对话框 +class LiveRoomGuestListDialog extends StatefulWidget { + final int initialTab; // 0: 女嘉宾, 1: 男嘉宾 + + const LiveRoomGuestListDialog({super.key, required this.initialTab}); + + @override + State createState() => + _LiveRoomGuestListDialogState(); +} + +class _LiveRoomGuestListDialogState extends State { + late int _selectedTab; // 0: 女嘉宾, 1: 男嘉宾 + List> _guestList = []; + bool _isLoading = true; + + @override + void initState() { + super.initState(); + _selectedTab = widget.initialTab; + _loadContacts(); + } + + Future _loadContacts() async { + setState(() { + _isLoading = true; + }); + + try { + // 获取会话列表 + final conversations = await IMManager.instance.getConversations(); + + if (conversations.isEmpty) { + setState(() { + _guestList = []; + _isLoading = false; + }); + return; + } + + final networkService = NetworkService(); + final List> guestList = []; + + // 遍历每个会话,获取联系人信息 + for (final conversation in conversations) { + try { + final userId = conversation.id; + if (userId.isEmpty) continue; + + // 获取环信用户信息 + final contactsMap = await IMManager.instance.getContacts(userId); + final emUserInfo = contactsMap[userId]; + + // 获取用户详细信息(包含性别) + final response = await networkService.userApi.getBaseUserInfo(userId); + + if (response.data.isSuccess && response.data.data != null) { + final userBaseData = response.data.data!; + + // 尝试从环信用户信息的扩展信息中获取性别等信息 + int? genderCode; + int? age; + String? cityName; + int? vipLevel; + + if (emUserInfo?.ext != null) { + try { + final extJson = json.decode(emUserInfo!.ext!); + if (extJson is Map) { + genderCode = extJson['genderCode'] is int + ? extJson['genderCode'] as int + : int.tryParse(extJson['genderCode']?.toString() ?? '0'); + age = extJson['age'] is int + ? extJson['age'] as int + : int.tryParse(extJson['age']?.toString() ?? ''); + cityName = extJson['cityName']?.toString(); + vipLevel = extJson['vipLevel'] is int + ? extJson['vipLevel'] as int + : int.tryParse(extJson['vipLevel']?.toString() ?? ''); + } + } catch (e) { + print('解析扩展信息失败: $e'); + } + } + + guestList.add({ + 'userId': userId, + 'avatar': emUserInfo?.avatarUrl ?? '', + 'name': emUserInfo?.nickName ?? userBaseData.nickName, + 'age': age, + 'location': cityName ?? '', + 'vipLevel': vipLevel, + 'genderCode': genderCode ?? 0, // 0-男, 1-女 + 'hasMaleGuest': false, // TODO: 根据实际业务逻辑判断 + 'hasFemaleGuest': false, // TODO: 根据实际业务逻辑判断 + }); + } + } catch (e) { + print('获取用户信息失败: ${conversation.id}, $e'); + } + } + + setState(() { + _guestList = guestList; + _isLoading = false; + }); + } catch (e) { + print('获取联系人列表失败: $e'); + setState(() { + _guestList = []; + _isLoading = false; + }); + } + } + + @override + Widget build(BuildContext context) { + return Container( + height: MediaQuery.of(context).size.height * 0.7, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(20.w)), + ), + child: Column( + children: [ + // 标签页头部 + Container( + padding: EdgeInsets.symmetric(horizontal: 20.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox(width: 60.w), + _buildTabButton('女嘉宾', 0), + SizedBox(width: 40.w), + _buildTabButton('男嘉宾', 1), + SizedBox(width: 60.w), + ], + ), + ), + Divider(height: 1, color: Colors.grey[200]), + // 列表内容 + Expanded(child: _buildGuestList()), + ], + ), + ); + } + + Widget _buildTabButton(String title, int index) { + final isSelected = _selectedTab == index; + return GestureDetector( + onTap: () { + setState(() { + _selectedTab = index; + }); + }, + child: Container( + padding: EdgeInsets.symmetric(vertical: 10.w), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: isSelected + ? const Color.fromRGBO(117, 98, 249, 1) + : Colors.transparent, + width: 1.5, + ), + ), + ), + child: Text( + title, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16.w, + fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, + color: isSelected + ? const Color.fromRGBO(117, 98, 249, 1) + : Colors.grey[600], + ), + ), + ), + ); + } + + Widget _buildGuestList() { + if (_isLoading) { + return Center(child: CircularProgressIndicator()); + } + + // 根据性别筛选联系人 + // genderCode: 0-男, 1-女 + final filteredList = _guestList.where((guest) { + final genderCode = guest['genderCode'] as int? ?? 0; + if (_selectedTab == 0) { + // 女嘉宾标签页,显示女性(genderCode == 1) + return genderCode == 1; + } else { + // 男嘉宾标签页,显示男性(genderCode == 0) + return genderCode == 0; + } + }).toList(); + + if (filteredList.isEmpty) { + return Center( + child: Text( + '暂无${_selectedTab == 0 ? "女" : "男"}嘉宾', + style: TextStyle(fontSize: 14.w, color: Colors.grey[500]), + ), + ); + } + + return ListView.builder( + padding: EdgeInsets.symmetric(horizontal: 15.w, vertical: 10.w), + itemCount: filteredList.length, + itemBuilder: (context, index) { + return _buildGuestItem(filteredList[index]); + }, + ); + } + + Widget _buildGuestItem(Map guest) { + // 根据当前标签页判断是否已有对应性别的嘉宾 + final hasGuest = _selectedTab == 0 + ? (guest['hasMaleGuest'] as bool? ?? false) + : (guest['hasFemaleGuest'] as bool? ?? false); + final vipLevel = guest['vipLevel'] as int?; + + return Container( + margin: EdgeInsets.only(bottom: 15.w), + child: Row( + children: [ + // 头像 + ClipRRect( + borderRadius: BorderRadius.circular(20.w), + child: CachedNetworkImage( + imageUrl: guest['avatar'] as String? ?? '', + width: 40.w, + height: 40.w, + fit: BoxFit.cover, + placeholder: (context, url) => Container( + width: 40.w, + height: 40.w, + color: Colors.grey[300], + child: Center( + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.grey[600], + ), + ), + ), + errorWidget: (context, url, error) => Container( + width: 40.w, + height: 40.w, + color: Colors.grey[300], + child: Icon(Icons.person, size: 24.w), + ), + ), + ), + SizedBox(width: 12.w), + // 用户信息 + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + guest['name'] as String? ?? '', + style: TextStyle( + fontSize: 15.w, + fontWeight: FontWeight.w500, + color: Colors.black87, + ), + ), + if (vipLevel != null && vipLevel > 0) ...[ + SizedBox(width: 6.w), + Container( + padding: EdgeInsets.symmetric( + horizontal: 6.w, + vertical: 2.w, + ), + decoration: BoxDecoration( + color: const Color(0xFFFF6B35), + borderRadius: BorderRadius.circular(10.w), + ), + child: Text( + 'VIP $vipLevel', + style: TextStyle( + fontSize: 10.w, + color: Colors.white, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ], + ), + SizedBox(height: 4.w), + Text( + _buildUserInfoText(guest['age'], guest['location']), + style: TextStyle(fontSize: 12.w, color: Colors.grey[600]), + ), + ], + ), + ), + // 操作按钮 + _buildActionButton(hasGuest), + ], + ), + ); + } + + Widget _buildActionButton(bool hasGuest) { + if (hasGuest) { + return Container( + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.w), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.circular(15.w), + ), + child: Text( + '已有${_selectedTab == 0 ? "男" : "女"}嘉宾', + style: TextStyle(fontSize: 12.w, color: Colors.grey[600]), + ), + ); + } else { + return GestureDetector( + onTap: () { + // TODO: 实现邀请功能 + SmartDialog.showToast('邀请${_selectedTab == 0 ? "女" : "男"}嘉宾'); + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.w), + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: [ + Color.fromRGBO(117, 98, 249, 1), + Color.fromRGBO(131, 89, 255, 1), + ], + ), + borderRadius: BorderRadius.circular(15.w), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.videocam, size: 14.w, color: Colors.white), + SizedBox(width: 4.w), + Text( + '邀请', + style: TextStyle( + fontSize: 12.w, + color: Colors.white, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ); + } + } + + String _buildUserInfoText(int? age, String? location) { + final parts = []; + if (age != null) { + parts.add('${age}岁'); + } + if (location != null && location.isNotEmpty) { + parts.add(location); + } + return parts.isEmpty ? '' : parts.join('·'); + } +}