import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:loopin/IM/im_service.dart'; import 'package:loopin/pages/groupChat/controller/group_detail_controller.dart'; import 'package:loopin/styles/index.dart'; import 'package:tencent_cloud_chat_sdk/enum/group_member_filter_enum.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_param.dart'; class MemberActionSheet extends StatefulWidget { final String groupID; final Function(List selected) onAction; final String title; final String actionLabel; final bool showButton; final bool showSelf; const MemberActionSheet({ super.key, required this.groupID, required this.onAction, this.title = "", this.actionLabel = "确认", this.showButton = true, this.showSelf = false, }); @override State createState() => _MemberActionSheetState(); } class _MemberActionSheetState extends State { String _query = ""; final Set _selectedIDs = {}; // 选中的 userID 集合 late List members = []; late List searchMemberList = []; String nextSeq = '0'; String searchCursor = ''; bool hasMore = false; // 普通列表用 bool loading = false; bool isFinished = false; // 搜索列表用 bool loading2 = false; //搜索 // @override void initState() { super.initState(); if (widget.showSelf) { final self = Get.find().selfInfo.value!; members.insert(0, self); } getMemberData(); } //群成员 Future getMemberData() async { if (loading) return; loading = true; final res = await ImService.instance.getGroupMemberList( groupID: widget.groupID, filter: GroupMemberFilterTypeEnum.V2TIM_GROUP_MEMBER_FILTER_COMMON, nextSeq: nextSeq, count: 100, ); if (res.success && res.data != null) { logger.e(res.data!.nextSeq); nextSeq = res.data!.nextSeq ?? '0'; final mem = res.data!.memberInfoList ?? []; setState(() { members.addAll(mem); hasMore = res.data!.nextSeq == '0' ? false : true; loading = false; }); } } ///搜索群成员 Future searchMember({bool loadMore = false}) async { if (loading2) return; if (_query.isEmpty) { setState(() { _query = ''; }); return; } loading2 = true; final param = V2TimGroupMemberSearchParam( keywordList: [_query], groupIDList: [widget.groupID], isSearchMemberUserID: true, isSearchMemberNickName: true, isSearchMemberRemark: true, isSearchMemberNameCard: true, keywordListMatchType: V2TimGroupMemberSearchParam.V2TIM_KEYWORD_LIST_MATCH_TYPE_OR, searchCount: 100, searchCursor: searchCursor, ); final res = await ImService.instance.searchGroupMembers(param: param); if (res.success && res.data != null) { isFinished = res.data!.isFinished ?? true; final searchCursor = res.data!.nextCursor ?? ''; final data = res.data!.groupMemberSearchResultItems; // 搜索结果群的成员 if (data != null && data[widget.groupID] != null) { List list = (data[widget.groupID] as List).cast(); if (!widget.showSelf) { // 过滤自己 final self = Get.find().selfInfo.value!; list = list.where((item) => item.userID != self.userID).toList(); } if (loadMore) { searchMemberList.addAll(list); } else { searchMemberList = list; } } logger.w(hasMore); logger.w(searchCursor); logger.w(data); } setState(() { loading2 = false; }); } String handleText(String? text, String defaultValue) { if (text == null || text.trim().isEmpty) return defaultValue; return text; } @override Widget build(BuildContext context) { List filteredMembers; if (_query.isEmpty) { filteredMembers = members; } else { filteredMembers = searchMemberList; } return SafeArea( child: GestureDetector( behavior: HitTestBehavior.translucent, // 点击空白区域也能触发 onTap: () { FocusScope.of(context).unfocus(); }, child: Scaffold( backgroundColor: Colors.white, appBar: AppBar( centerTitle: true, forceMaterialTransparency: true, bottom: PreferredSize( preferredSize: const Size.fromHeight(1.0), child: Container( color: Colors.grey[300], height: 1.0, ), ), title: Text( widget.title, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () { Navigator.pop(context); }, ), ), body: Column( children: [ SizedBox(height: 10), // 搜索框 Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: TextField( decoration: InputDecoration( prefixIcon: const Icon(Icons.search), hintText: "搜索成员", contentPadding: const EdgeInsets.symmetric(vertical: 8), border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)), ), onChanged: (value) { setState(() { _query = value.trim(); searchMember(); }); }, ), ), const SizedBox(height: 8), // 成员列表 Expanded( child: EasyRefresh( footer: ClassicFooter( dragText: '加载更多', armedText: '释放加载', readyText: '加载中...', processingText: '加载中...', processedText: '加载完成', noMoreText: '没有更多了~', failedText: '加载失败,请重试', messageText: '最后更新于 %T', ), onLoad: () async { // if (_query.isNotEmpty && (!isFinished)) { await searchMember(loadMore: true); return !isFinished ? IndicatorResult.success : IndicatorResult.noMore; } else if (hasMore) { await getMemberData(); return hasMore ? IndicatorResult.success : IndicatorResult.noMore; } }, child: ListView.builder( itemCount: filteredMembers.length, itemBuilder: (context, index) { final m = filteredMembers[index]; final id = m.userID; final uname = handleText(m.nameCard, ''); final nickname = handleText(m.nickName, '未知昵称'); final showName = uname.isEmpty ? nickname : uname; return InkWell( onTap: () { setState(() { if (_selectedIDs.contains(id)) { _selectedIDs.remove(id); } else { _selectedIDs.add(id); } }); }, child: Padding( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), child: Row( children: [ // 左侧圆形头像 CircleAvatar( radius: 20, backgroundImage: m.faceUrl != null ? NetworkImage(m.faceUrl!) : null, child: m.faceUrl == null ? const Icon(Icons.person) : null, ), const SizedBox(width: 12), // 用户名 Expanded( child: Text( showName, style: const TextStyle(fontSize: 14), overflow: TextOverflow.ellipsis, ), ), if (widget.showButton) // 复选框 Container( width: 24, height: 24, alignment: Alignment.center, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all(color: _selectedIDs.contains(id) ? FStyle.primaryColor : Colors.grey), color: _selectedIDs.contains(id) ? FStyle.primaryColor : Colors.transparent, ), child: _selectedIDs.contains(id) ? const Icon(Icons.check, size: 16, color: Colors.white) : null, ), ], ), ), ); }, ), ), ), // 底部操作按钮 if (widget.showButton) Padding( padding: const EdgeInsets.all(16), child: ElevatedButton( style: ElevatedButton.styleFrom( minimumSize: const Size(double.infinity, 48), backgroundColor: FStyle.primaryColor, ), onPressed: _selectedIDs.isEmpty ? null : () { Navigator.pop(context); widget.onAction(_selectedIDs.toList()); }, child: Text( "${widget.actionLabel}(${_selectedIDs.length})", style: TextStyle( color: _selectedIDs.isNotEmpty ? Colors.white : Colors.black, ), ), ), ), ], ), ), ), ); } }