获取频道成员
获取频道内所有成员
Copy
// 获取频道内所有成员
List<WKChannelMember> members = WKIM.shared.channelMemberManager.getMembers(channelId: channelId);
获取频道内指定用户的成员信息
Copy
// 获取频道内指定用户的成员信息
WKChannelMember? member = WKIM.shared.channelMemberManager.getMember(channelId: channelId, uid: uid);
完整成员获取示例
Copy
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表示黑名单状态
}
}
事件监听
刷新频道成员监听
Copy
// 刷新频道成员
WKIM.shared.channelMemberManager.addOnRefreshMemberListener('key', (WKChannelMember member, bool isEnd) {
// todo 刷新会话列表
});
// 移除刷新频道成员监听
WKIM.shared.channelMemberManager.removeRefreshMemberListener('key');
key为监听的唯一标识,可以为任意字符串,添加监听和移出监听时需要传入相同的key
完整事件监听管理
Copy
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 频道成员对象
Copy
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
}
字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
channelID | String | 频道ID |
channelType | int | 频道类型 |
memberUID | String | 成员ID |
memberName | String | 成员名称 |
memberRemark | String | 成员备注 |
memberAvatar | String | 成员头像URL |
role | int | 成员角色(0=普通成员,1=管理员,2=群主) |
status | int | 成员状态(1=正常,2=黑名单) |
isDeleted | int | 是否删除(0=否,1=是) |
version | int | 版本号 |
robot | int | 是否机器人(0=否,1=是) |
forbiddenExpirationTime | int | 禁言到期时间戳 |
成员角色说明
| 角色值 | 说明 |
|---|---|
0 | 普通成员 |
1 | 管理员 |
2 | 群主 |
成员状态说明
| 状态值 | 说明 |
|---|---|
1 | 正常 |
2 | 黑名单 |
Flutter Widget 集成示例
成员列表组件
Copy
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')}';
}
}

