跳转到主要内容
频道成员管理提供了完整的群组成员管理功能,包括成员信息获取、成员状态监听、权限管理等核心能力。

获取频道成员

获取频道内所有成员

// 获取频道内所有成员
List<WKChannelMember> members = WKIM.shared.channelMemberManager.getMembers(channelId: channelId);

获取频道内指定用户的成员信息

// 获取频道内指定用户的成员信息
WKChannelMember? member = WKIM.shared.channelMemberManager.getMember(channelId: channelId, uid: uid);

完整成员获取示例

class ChannelMemberManager {
  
  // 获取所有成员
  static List<WKChannelMember> getAllMembers(String channelId) {
    try {
      final members = WKIM.shared.channelMemberManager.getMembers(channelId: channelId);
      print('获取到 ${members.length} 个成员');
      return members;
    } catch (error) {
      print('获取成员列表失败: $error');
      return [];
    }
  }
  
  // 获取指定成员信息
  static WKChannelMember? getMemberInfo(String channelId, String uid) {
    try {
      final member = WKIM.shared.channelMemberManager.getMember(channelId: channelId, uid: uid);
      if (member != null) {
        print('获取成员信息成功: ${member.memberName}');
      }
      return member;
    } catch (error) {
      print('获取成员信息失败: $error');
      return null;
    }
  }
  
  // 按角色筛选成员
  static List<WKChannelMember> getMembersByRole(String channelId, int role) {
    final allMembers = getAllMembers(channelId);
    return allMembers.where((member) => member.role == role).toList();
  }
  
  // 获取管理员列表
  static List<WKChannelMember> getAdminMembers(String channelId) {
    return getMembersByRole(channelId, 1); // 假设1为管理员角色
  }
  
  // 获取普通成员列表
  static List<WKChannelMember> getNormalMembers(String channelId) {
    return getMembersByRole(channelId, 0); // 假设0为普通成员角色
  }
  
  // 搜索成员
  static List<WKChannelMember> searchMembers(String channelId, String keyword) {
    if (keyword.trim().isEmpty) {
      return [];
    }
    
    final allMembers = getAllMembers(channelId);
    return allMembers.where((member) {
      final name = member.memberName.toLowerCase();
      final remark = member.memberRemark.toLowerCase();
      final uid = member.memberUID.toLowerCase();
      final searchKey = keyword.toLowerCase();
      
      return name.contains(searchKey) || 
             remark.contains(searchKey) || 
             uid.contains(searchKey);
    }).toList();
  }
  
  // 获取在线成员(需要结合频道信息)
  static List<WKChannelMember> getOnlineMembers(String channelId) {
    final allMembers = getAllMembers(channelId);
    // 这里需要结合频道管理器获取在线状态
    return allMembers.where((member) {
      final channel = WKIM.shared.channelManager.getChannel(member.memberUID, WKChannelType.personal);
      return channel?.online == 1;
    }).toList();
  }
  
  // 获取成员显示名称
  static String getMemberDisplayName(WKChannelMember member) {
    if (member.memberRemark.isNotEmpty) {
      return member.memberRemark;
    }
    if (member.memberName.isNotEmpty) {
      return member.memberName;
    }
    return member.memberUID;
  }
  
  // 检查成员是否为管理员
  static bool isAdmin(WKChannelMember member) {
    return member.role == 1; // 假设1为管理员角色
  }
  
  // 检查成员是否被禁言
  static bool isMuted(WKChannelMember member) {
    if (member.forbiddenExpirationTime == 0) {
      return false;
    }
    final now = DateTime.now().millisecondsSinceEpoch ~/ 1000;
    return member.forbiddenExpirationTime > now;
  }
  
  // 检查成员是否在黑名单
  static bool isBlacklisted(WKChannelMember member) {
    return member.status == 2; // 2表示黑名单状态
  }
}

事件监听

刷新频道成员监听

// 刷新频道成员
WKIM.shared.channelMemberManager.addOnRefreshMemberListener('key', (WKChannelMember member, bool isEnd) {
    // todo 刷新会话列表
});

// 移除刷新频道成员监听
WKIM.shared.channelMemberManager.removeRefreshMemberListener('key');
key为监听的唯一标识,可以为任意字符串,添加监听和移出监听时需要传入相同的key

完整事件监听管理

class ChannelMemberListener {
  static final Map<String, Function> _refreshListeners = {};
  static StreamController<ChannelMemberUpdateEvent>? _updateController;
  
  // 获取成员更新流
  static Stream<ChannelMemberUpdateEvent> get memberUpdateStream {
    _updateController ??= StreamController<ChannelMemberUpdateEvent>.broadcast();
    return _updateController!.stream;
  }
  
  // 添加成员刷新监听
  static void addRefreshMemberListener(String key, Function(WKChannelMember, bool) callback) {
    _refreshListeners[key] = callback;
    
    WKIM.shared.channelMemberManager.addOnRefreshMemberListener(key, (WKChannelMember member, bool isEnd) {
      // 调用回调
      callback(member, isEnd);
      
      // 发送到流
      _updateController?.add(ChannelMemberUpdateEvent(
        member: member,
        isEnd: isEnd,
        timestamp: DateTime.now(),
      ));
      
      print('频道成员更新: ${member.memberUID}, isEnd: $isEnd');
    });
  }
  
  // 移除成员刷新监听
  static void removeRefreshMemberListener(String key) {
    _refreshListeners.remove(key);
    WKIM.shared.channelMemberManager.removeRefreshMemberListener(key);
  }
  
  // 移除所有监听
  static void removeAllListeners() {
    for (final key in _refreshListeners.keys) {
      WKIM.shared.channelMemberManager.removeRefreshMemberListener(key);
    }
    _refreshListeners.clear();
  }
  
  // 为特定频道添加监听
  static void addChannelMemberListener(String channelId, Function(WKChannelMember, bool) callback) {
    final key = 'channel_$channelId';
    
    addRefreshMemberListener(key, (WKChannelMember member, bool isEnd) {
      if (member.channelID == channelId) {
        callback(member, isEnd);
      }
    });
  }
  
  // 移除特定频道的监听
  static void removeChannelMemberListener(String channelId) {
    final key = 'channel_$channelId';
    removeRefreshMemberListener(key);
  }
  
  // 销毁
  static void dispose() {
    removeAllListeners();
    _updateController?.close();
    _updateController = null;
  }
}

// 频道成员更新事件
class ChannelMemberUpdateEvent {
  final WKChannelMember member;
  final bool isEnd;
  final DateTime timestamp;
  
  ChannelMemberUpdateEvent({
    required this.member,
    required this.isEnd,
    required this.timestamp,
  });
  
  @override
  String toString() {
    return 'ChannelMemberUpdateEvent{memberUID: ${member.memberUID}, isEnd: $isEnd, timestamp: $timestamp}';
  }
}

数据结构说明

WKChannelMember 频道成员对象

class WKChannelMember {
  String channelID = "";           // 频道ID
  int channelType = 0;             // 频道类型
  String memberUID = "";           // 成员ID
  String memberName = "";          // 成员名称
  String memberRemark = "";        // 成员备注
  String memberAvatar = "";        // 成员头像
  int role = 0;                    // 成员角色
  int status = 0;                  // 成员状态(1:正常,2:黑名单)
  int isDeleted = 0;               // 是否删除
  String createdAt = "";           // 创建时间
  String updatedAt = "";           // 修改时间
  int version = 0;                 // 版本
  int robot = 0;                   // 机器人(0:否,1:是)
  dynamic extraMap;                // 扩展字段
  String remark = "";              // 用户备注
  String memberInviteUID = "";     // 邀请者UID
  int forbiddenExpirationTime = 0; // 被禁言到期时间
  String memberAvatarCacheKey = "";// 成员头像缓存key
}

字段说明

字段类型说明
channelIDString频道ID
channelTypeint频道类型
memberUIDString成员ID
memberNameString成员名称
memberRemarkString成员备注
memberAvatarString成员头像URL
roleint成员角色(0=普通成员,1=管理员,2=群主)
statusint成员状态(1=正常,2=黑名单)
isDeletedint是否删除(0=否,1=是)
versionint版本号
robotint是否机器人(0=否,1=是)
forbiddenExpirationTimeint禁言到期时间戳

成员角色说明

角色值说明
0普通成员
1管理员
2群主

成员状态说明

状态值说明
1正常
2黑名单

Flutter Widget 集成示例

成员列表组件

class ChannelMemberListWidget extends StatefulWidget {
  final String channelId;
  
  const ChannelMemberListWidget({Key? key, required this.channelId}) : super(key: key);
  
  @override
  _ChannelMemberListWidgetState createState() => _ChannelMemberListWidgetState();
}

class _ChannelMemberListWidgetState extends State<ChannelMemberListWidget> {
  List<WKChannelMember> _members = [];
  List<WKChannelMember> _filteredMembers = [];
  bool _loading = true;
  String _searchKeyword = '';
  StreamSubscription<ChannelMemberUpdateEvent>? _subscription;
  
  @override
  void initState() {
    super.initState();
    _loadMembers();
    _setupListener();
  }
  
  @override
  void dispose() {
    _subscription?.cancel();
    ChannelMemberListener.removeChannelMemberListener(widget.channelId);
    super.dispose();
  }
  
  void _loadMembers() {
    setState(() {
      _loading = true;
    });
    
    final members = ChannelMemberManager.getAllMembers(widget.channelId);
    
    setState(() {
      _members = members;
      _filteredMembers = members;
      _loading = false;
    });
  }
  
  void _setupListener() {
    // 添加成员更新监听
    ChannelMemberListener.addChannelMemberListener(widget.channelId, (member, isEnd) {
      if (isEnd) {
        _loadMembers();
      }
    });
    
    // 监听成员更新流
    _subscription = ChannelMemberListener.memberUpdateStream.listen((event) {
      if (event.member.channelID == widget.channelId && event.isEnd) {
        _loadMembers();
      }
    });
  }
  
  void _searchMembers(String keyword) {
    setState(() {
      _searchKeyword = keyword;
      if (keyword.isEmpty) {
        _filteredMembers = _members;
      } else {
        _filteredMembers = ChannelMemberManager.searchMembers(widget.channelId, keyword);
      }
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 搜索框
        Padding(
          padding: EdgeInsets.all(16),
          child: TextField(
            decoration: InputDecoration(
              hintText: '搜索成员',
              prefixIcon: Icon(Icons.search),
              border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
              ),
            ),
            onChanged: _searchMembers,
          ),
        ),
        
        // 成员列表
        Expanded(
          child: _loading
            ? Center(child: CircularProgressIndicator())
            : _filteredMembers.isEmpty
              ? Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(Icons.people_outline, size: 64, color: Colors.grey),
                      SizedBox(height: 16),
                      Text('暂无成员', style: TextStyle(color: Colors.grey)),
                    ],
                  ),
                )
              : ListView.builder(
                  itemCount: _filteredMembers.length,
                  itemBuilder: (context, index) {
                    final member = _filteredMembers[index];
                    return _buildMemberItem(member);
                  },
                ),
        ),
      ],
    );
  }
  
  Widget _buildMemberItem(WKChannelMember member) {
    return ListTile(
      leading: CircleAvatar(
        backgroundImage: member.memberAvatar.isNotEmpty 
          ? NetworkImage(member.memberAvatar)
          : null,
        child: member.memberAvatar.isEmpty 
          ? Text(member.memberUID.substring(0, 1).toUpperCase())
          : null,
      ),
      title: Text(
        ChannelMemberManager.getMemberDisplayName(member),
        style: TextStyle(fontWeight: FontWeight.w500),
      ),
      subtitle: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('ID: ${member.memberUID}'),
          if (ChannelMemberManager.isMuted(member))
            Text('已禁言', style: TextStyle(color: Colors.red, fontSize: 12)),
        ],
      ),
      trailing: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          if (ChannelMemberManager.isAdmin(member))
            Container(
              padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2),
              decoration: BoxDecoration(
                color: Colors.orange,
                borderRadius: BorderRadius.circular(4),
              ),
              child: Text(
                '管理员',
                style: TextStyle(color: Colors.white, fontSize: 10),
              ),
            ),
          if (member.robot == 1)
            Container(
              margin: EdgeInsets.only(left: 4),
              padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2),
              decoration: BoxDecoration(
                color: Colors.blue,
                borderRadius: BorderRadius.circular(4),
              ),
              child: Text(
                '机器人',
                style: TextStyle(color: Colors.white, fontSize: 10),
              ),
            ),
        ],
      ),
      onTap: () {
        _showMemberDetails(member);
      },
    );
  }
  
  void _showMemberDetails(WKChannelMember member) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('成员详情'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('姓名: ${member.memberName}'),
            Text('ID: ${member.memberUID}'),
            Text('角色: ${_getRoleText(member.role)}'),
            Text('状态: ${_getStatusText(member.status)}'),
            if (member.memberRemark.isNotEmpty)
              Text('备注: ${member.memberRemark}'),
            if (ChannelMemberManager.isMuted(member))
              Text('禁言到期: ${_formatTime(member.forbiddenExpirationTime)}'),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('关闭'),
          ),
        ],
      ),
    );
  }
  
  String _getRoleText(int role) {
    switch (role) {
      case 0: return '普通成员';
      case 1: return '管理员';
      case 2: return '群主';
      default: return '未知';
    }
  }
  
  String _getStatusText(int status) {
    switch (status) {
      case 1: return '正常';
      case 2: return '黑名单';
      default: return '未知';
    }
  }
  
  String _formatTime(int timestamp) {
    if (timestamp == 0) return '永久';
    final date = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
    return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')} ${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}';
  }
}

下一步