699 lines
20 KiB
JavaScript
699 lines
20 KiB
JavaScript
// 群聊管理器 - 微信小程序专用
|
|
// 处理群聊创建、管理、成员管理、权限控制等功能
|
|
|
|
const apiClient = require('./api-client.js');
|
|
|
|
/**
|
|
* 群聊管理器
|
|
* 功能:
|
|
* 1. 群聊创建和解散
|
|
* 2. 群成员管理
|
|
* 3. 群信息设置
|
|
* 4. 群权限管理
|
|
* 5. @提醒功能
|
|
* 6. 群公告管理
|
|
*/
|
|
class GroupChatManager {
|
|
constructor() {
|
|
this.isInitialized = false;
|
|
|
|
// 群聊配置
|
|
this.groupConfig = {
|
|
// 群聊基本配置
|
|
maxMembers: 500, // 最大成员数
|
|
maxGroupNameLength: 20, // 群名称最大长度
|
|
maxDescriptionLength: 200, // 群描述最大长度
|
|
maxAnnouncementLength: 500, // 群公告最大长度
|
|
|
|
// 权限配置
|
|
permissions: {
|
|
owner: {
|
|
name: '群主',
|
|
level: 3,
|
|
canInvite: true,
|
|
canRemove: true,
|
|
canSetAdmin: true,
|
|
canEditInfo: true,
|
|
canDissolve: true,
|
|
canMute: true,
|
|
canSetAnnouncement: true
|
|
},
|
|
admin: {
|
|
name: '管理员',
|
|
level: 2,
|
|
canInvite: true,
|
|
canRemove: true,
|
|
canSetAdmin: false,
|
|
canEditInfo: true,
|
|
canDissolve: false,
|
|
canMute: true,
|
|
canSetAnnouncement: true
|
|
},
|
|
member: {
|
|
name: '普通成员',
|
|
level: 1,
|
|
canInvite: false,
|
|
canRemove: false,
|
|
canSetAdmin: false,
|
|
canEditInfo: false,
|
|
canDissolve: false,
|
|
canMute: false,
|
|
canSetAnnouncement: false
|
|
}
|
|
},
|
|
|
|
// @提醒配置
|
|
mention: {
|
|
enabled: true,
|
|
maxMentions: 10, // 单条消息最多@10个人
|
|
allMemberKeyword: '所有人' // @全体成员关键词
|
|
},
|
|
|
|
// 群设置默认值
|
|
defaultSettings: {
|
|
allowMemberInvite: true, // 允许成员邀请
|
|
allowMemberModifyInfo: false, // 允许成员修改群信息
|
|
muteAll: false, // 全员禁言
|
|
showMemberNickname: true, // 显示成员昵称
|
|
saveToContacts: true, // 保存到通讯录
|
|
showQRCode: true // 显示群二维码
|
|
}
|
|
};
|
|
|
|
// 群聊缓存
|
|
this.groupCache = new Map();
|
|
this.memberCache = new Map();
|
|
|
|
// 当前用户信息
|
|
this.currentUserId = null;
|
|
|
|
this.init();
|
|
}
|
|
|
|
// 初始化群聊管理器
|
|
async init() {
|
|
if (this.isInitialized) return;
|
|
|
|
console.log('👥 初始化群聊管理器...');
|
|
|
|
try {
|
|
// 获取当前用户ID
|
|
this.currentUserId = wx.getStorageSync('userId');
|
|
|
|
// 加载群聊缓存
|
|
await this.loadGroupCache();
|
|
|
|
this.isInitialized = true;
|
|
console.log('✅ 群聊管理器初始化完成');
|
|
|
|
} catch (error) {
|
|
console.error('❌ 群聊管理器初始化失败:', error);
|
|
}
|
|
}
|
|
|
|
// 👥 ===== 群聊创建和管理 =====
|
|
|
|
// 创建群聊
|
|
async createGroup(groupInfo) {
|
|
try {
|
|
console.log('👥 创建群聊:', groupInfo);
|
|
|
|
// 验证群聊信息
|
|
const validation = this.validateGroupInfo(groupInfo);
|
|
if (!validation.valid) {
|
|
return { success: false, error: validation.error };
|
|
}
|
|
|
|
// 调用API创建群聊
|
|
const response = await apiClient.request({
|
|
url: '/api/v1/groups',
|
|
method: 'POST',
|
|
data: {
|
|
name: groupInfo.name,
|
|
description: groupInfo.description || '',
|
|
avatar: groupInfo.avatar || '',
|
|
memberIds: groupInfo.memberIds || [],
|
|
settings: { ...this.groupConfig.defaultSettings, ...groupInfo.settings }
|
|
}
|
|
});
|
|
|
|
if (response.success) {
|
|
const group = response.data;
|
|
|
|
// 更新本地缓存
|
|
this.updateGroupCache(group);
|
|
|
|
console.log('✅ 群聊创建成功:', group.groupId);
|
|
return { success: true, data: group };
|
|
} else {
|
|
throw new Error(response.error || '创建群聊失败');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ 创建群聊失败:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
// 解散群聊
|
|
async dissolveGroup(groupId) {
|
|
try {
|
|
console.log('👥 解散群聊:', groupId);
|
|
|
|
// 检查权限
|
|
const hasPermission = await this.checkPermission(groupId, 'canDissolve');
|
|
if (!hasPermission) {
|
|
return { success: false, error: '没有解散群聊的权限' };
|
|
}
|
|
|
|
// 调用API解散群聊
|
|
const response = await apiClient.request({
|
|
url: `/api/v1/groups/${groupId}/dissolve`,
|
|
method: 'POST'
|
|
});
|
|
|
|
if (response.success) {
|
|
// 清除本地缓存
|
|
this.groupCache.delete(groupId);
|
|
this.memberCache.delete(groupId);
|
|
|
|
console.log('✅ 群聊解散成功');
|
|
return { success: true };
|
|
} else {
|
|
throw new Error(response.error || '解散群聊失败');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ 解散群聊失败:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
// 退出群聊
|
|
async leaveGroup(groupId) {
|
|
try {
|
|
console.log('👥 退出群聊:', groupId);
|
|
|
|
// 调用API退出群聊
|
|
const response = await apiClient.request({
|
|
url: `/api/v1/groups/${groupId}/leave`,
|
|
method: 'POST'
|
|
});
|
|
|
|
if (response.success) {
|
|
// 清除本地缓存
|
|
this.groupCache.delete(groupId);
|
|
this.memberCache.delete(groupId);
|
|
|
|
console.log('✅ 退出群聊成功');
|
|
return { success: true };
|
|
} else {
|
|
throw new Error(response.error || '退出群聊失败');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ 退出群聊失败:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
// 👤 ===== 群成员管理 =====
|
|
|
|
// 邀请成员
|
|
async inviteMembers(groupId, memberIds) {
|
|
try {
|
|
console.log('👤 邀请成员:', groupId, memberIds);
|
|
|
|
// 检查权限
|
|
const hasPermission = await this.checkPermission(groupId, 'canInvite');
|
|
if (!hasPermission) {
|
|
return { success: false, error: '没有邀请成员的权限' };
|
|
}
|
|
|
|
// 检查成员数量限制
|
|
const currentMembers = await this.getGroupMembers(groupId);
|
|
if (currentMembers.data && currentMembers.data.length + memberIds.length > this.groupConfig.maxMembers) {
|
|
return { success: false, error: `群成员数量不能超过${this.groupConfig.maxMembers}人` };
|
|
}
|
|
|
|
// 调用API邀请成员
|
|
const response = await apiClient.request({
|
|
url: `/api/v1/groups/${groupId}/members`,
|
|
method: 'POST',
|
|
data: {
|
|
memberIds: memberIds
|
|
}
|
|
});
|
|
|
|
if (response.success) {
|
|
// 更新成员缓存
|
|
this.updateMemberCache(groupId, response.data.members);
|
|
|
|
console.log('✅ 邀请成员成功');
|
|
return { success: true, data: response.data };
|
|
} else {
|
|
throw new Error(response.error || '邀请成员失败');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ 邀请成员失败:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
// 移除成员
|
|
async removeMember(groupId, memberId) {
|
|
try {
|
|
console.log('👤 移除成员:', groupId, memberId);
|
|
|
|
// 检查权限
|
|
const hasPermission = await this.checkPermission(groupId, 'canRemove');
|
|
if (!hasPermission) {
|
|
return { success: false, error: '没有移除成员的权限' };
|
|
}
|
|
|
|
// 不能移除自己
|
|
if (memberId === this.currentUserId) {
|
|
return { success: false, error: '不能移除自己,请使用退出群聊功能' };
|
|
}
|
|
|
|
// 调用API移除成员
|
|
const response = await apiClient.request({
|
|
url: `/api/v1/groups/${groupId}/members/${memberId}`,
|
|
method: 'DELETE'
|
|
});
|
|
|
|
if (response.success) {
|
|
// 更新成员缓存
|
|
this.removeMemberFromCache(groupId, memberId);
|
|
|
|
console.log('✅ 移除成员成功');
|
|
return { success: true };
|
|
} else {
|
|
throw new Error(response.error || '移除成员失败');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ 移除成员失败:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
// 设置管理员
|
|
async setAdmin(groupId, memberId, isAdmin) {
|
|
try {
|
|
console.log('👤 设置管理员:', groupId, memberId, isAdmin);
|
|
|
|
// 检查权限
|
|
const hasPermission = await this.checkPermission(groupId, 'canSetAdmin');
|
|
if (!hasPermission) {
|
|
return { success: false, error: '没有设置管理员的权限' };
|
|
}
|
|
|
|
// 调用API设置管理员
|
|
const response = await apiClient.request({
|
|
url: `/api/v1/groups/${groupId}/members/${memberId}/admin`,
|
|
method: 'PUT',
|
|
data: {
|
|
isAdmin: isAdmin
|
|
}
|
|
});
|
|
|
|
if (response.success) {
|
|
// 更新成员缓存
|
|
this.updateMemberRole(groupId, memberId, isAdmin ? 'admin' : 'member');
|
|
|
|
console.log('✅ 设置管理员成功');
|
|
return { success: true };
|
|
} else {
|
|
throw new Error(response.error || '设置管理员失败');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ 设置管理员失败:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
// 获取群成员列表
|
|
async getGroupMembers(groupId, useCache = true) {
|
|
try {
|
|
// 先从缓存获取
|
|
if (useCache && this.memberCache.has(groupId)) {
|
|
const cached = this.memberCache.get(groupId);
|
|
if (Date.now() - cached.timestamp < 300000) { // 5分钟缓存
|
|
return { success: true, data: cached.members };
|
|
}
|
|
}
|
|
|
|
// 从服务器获取
|
|
const response = await apiClient.request({
|
|
url: `/api/v1/groups/${groupId}/members`,
|
|
method: 'GET'
|
|
});
|
|
|
|
if (response.success) {
|
|
const members = response.data || [];
|
|
|
|
// 更新缓存
|
|
this.memberCache.set(groupId, {
|
|
members: members,
|
|
timestamp: Date.now()
|
|
});
|
|
|
|
return { success: true, data: members };
|
|
} else {
|
|
throw new Error(response.error || '获取群成员失败');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ 获取群成员失败:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
// ⚙️ ===== 群信息设置 =====
|
|
|
|
// 更新群信息
|
|
async updateGroupInfo(groupId, updates) {
|
|
try {
|
|
console.log('⚙️ 更新群信息:', groupId, updates);
|
|
|
|
// 检查权限
|
|
const hasPermission = await this.checkPermission(groupId, 'canEditInfo');
|
|
if (!hasPermission) {
|
|
return { success: false, error: '没有修改群信息的权限' };
|
|
}
|
|
|
|
// 验证更新信息
|
|
const validation = this.validateGroupUpdates(updates);
|
|
if (!validation.valid) {
|
|
return { success: false, error: validation.error };
|
|
}
|
|
|
|
// 调用API更新群信息
|
|
const response = await apiClient.request({
|
|
url: `/api/v1/groups/${groupId}`,
|
|
method: 'PUT',
|
|
data: updates
|
|
});
|
|
|
|
if (response.success) {
|
|
// 更新群聊缓存
|
|
this.updateGroupCache(response.data);
|
|
|
|
console.log('✅ 群信息更新成功');
|
|
return { success: true, data: response.data };
|
|
} else {
|
|
throw new Error(response.error || '更新群信息失败');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ 更新群信息失败:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
// 设置群公告
|
|
async setGroupAnnouncement(groupId, announcement) {
|
|
try {
|
|
console.log('⚙️ 设置群公告:', groupId);
|
|
|
|
// 检查权限
|
|
const hasPermission = await this.checkPermission(groupId, 'canSetAnnouncement');
|
|
if (!hasPermission) {
|
|
return { success: false, error: '没有设置群公告的权限' };
|
|
}
|
|
|
|
// 验证公告长度
|
|
if (announcement.length > this.groupConfig.maxAnnouncementLength) {
|
|
return { success: false, error: `群公告不能超过${this.groupConfig.maxAnnouncementLength}字符` };
|
|
}
|
|
|
|
// 调用API设置群公告
|
|
const response = await apiClient.request({
|
|
url: `/api/v1/groups/${groupId}/announcement`,
|
|
method: 'PUT',
|
|
data: {
|
|
announcement: announcement
|
|
}
|
|
});
|
|
|
|
if (response.success) {
|
|
console.log('✅ 群公告设置成功');
|
|
return { success: true };
|
|
} else {
|
|
throw new Error(response.error || '设置群公告失败');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ 设置群公告失败:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
// 📢 ===== @提醒功能 =====
|
|
|
|
// 解析@提醒
|
|
parseMentions(content) {
|
|
const mentions = [];
|
|
const mentionRegex = /@([^\s@]+)/g;
|
|
let match;
|
|
|
|
while ((match = mentionRegex.exec(content)) !== null) {
|
|
const mentionText = match[1];
|
|
|
|
if (mentionText === this.groupConfig.mention.allMemberKeyword) {
|
|
// @全体成员
|
|
mentions.push({
|
|
type: 'all',
|
|
text: mentionText,
|
|
start: match.index,
|
|
end: match.index + match[0].length
|
|
});
|
|
} else {
|
|
// @特定成员
|
|
mentions.push({
|
|
type: 'user',
|
|
text: mentionText,
|
|
start: match.index,
|
|
end: match.index + match[0].length
|
|
});
|
|
}
|
|
}
|
|
|
|
return mentions;
|
|
}
|
|
|
|
// 验证@提醒
|
|
async validateMentions(groupId, mentions) {
|
|
try {
|
|
if (mentions.length > this.groupConfig.mention.maxMentions) {
|
|
return { valid: false, error: `单条消息最多只能@${this.groupConfig.mention.maxMentions}个人` };
|
|
}
|
|
|
|
// 获取群成员列表
|
|
const membersResult = await this.getGroupMembers(groupId);
|
|
if (!membersResult.success) {
|
|
return { valid: false, error: '获取群成员列表失败' };
|
|
}
|
|
|
|
const members = membersResult.data;
|
|
const validMentions = [];
|
|
|
|
for (const mention of mentions) {
|
|
if (mention.type === 'all') {
|
|
// 检查@全体成员权限
|
|
const hasPermission = await this.checkPermission(groupId, 'canMentionAll');
|
|
if (hasPermission) {
|
|
validMentions.push({
|
|
...mention,
|
|
userIds: members.map(m => m.userId)
|
|
});
|
|
}
|
|
} else {
|
|
// 查找对应的成员
|
|
const member = members.find(m =>
|
|
m.nickname === mention.text ||
|
|
m.username === mention.text ||
|
|
m.userId === mention.text
|
|
);
|
|
|
|
if (member) {
|
|
validMentions.push({
|
|
...mention,
|
|
userId: member.userId,
|
|
userIds: [member.userId]
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return { valid: true, mentions: validMentions };
|
|
|
|
} catch (error) {
|
|
console.error('❌ 验证@提醒失败:', error);
|
|
return { valid: false, error: '验证@提醒失败' };
|
|
}
|
|
}
|
|
|
|
// 🔧 ===== 工具方法 =====
|
|
|
|
// 验证群聊信息
|
|
validateGroupInfo(groupInfo) {
|
|
if (!groupInfo.name || groupInfo.name.trim().length === 0) {
|
|
return { valid: false, error: '群名称不能为空' };
|
|
}
|
|
|
|
if (groupInfo.name.length > this.groupConfig.maxGroupNameLength) {
|
|
return { valid: false, error: `群名称不能超过${this.groupConfig.maxGroupNameLength}字符` };
|
|
}
|
|
|
|
if (groupInfo.description && groupInfo.description.length > this.groupConfig.maxDescriptionLength) {
|
|
return { valid: false, error: `群描述不能超过${this.groupConfig.maxDescriptionLength}字符` };
|
|
}
|
|
|
|
if (groupInfo.memberIds && groupInfo.memberIds.length > this.groupConfig.maxMembers) {
|
|
return { valid: false, error: `群成员数量不能超过${this.groupConfig.maxMembers}人` };
|
|
}
|
|
|
|
return { valid: true };
|
|
}
|
|
|
|
// 验证群信息更新
|
|
validateGroupUpdates(updates) {
|
|
if (updates.name !== undefined) {
|
|
if (!updates.name || updates.name.trim().length === 0) {
|
|
return { valid: false, error: '群名称不能为空' };
|
|
}
|
|
|
|
if (updates.name.length > this.groupConfig.maxGroupNameLength) {
|
|
return { valid: false, error: `群名称不能超过${this.groupConfig.maxGroupNameLength}字符` };
|
|
}
|
|
}
|
|
|
|
if (updates.description !== undefined && updates.description.length > this.groupConfig.maxDescriptionLength) {
|
|
return { valid: false, error: `群描述不能超过${this.groupConfig.maxDescriptionLength}字符` };
|
|
}
|
|
|
|
return { valid: true };
|
|
}
|
|
|
|
// 检查权限
|
|
async checkPermission(groupId, permission) {
|
|
try {
|
|
const userRole = await this.getUserRole(groupId, this.currentUserId);
|
|
if (!userRole) return false;
|
|
|
|
const roleConfig = this.groupConfig.permissions[userRole];
|
|
return roleConfig && roleConfig[permission];
|
|
|
|
} catch (error) {
|
|
console.error('❌ 检查权限失败:', error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// 获取用户在群中的角色
|
|
async getUserRole(groupId, userId) {
|
|
try {
|
|
const membersResult = await this.getGroupMembers(groupId);
|
|
if (!membersResult.success) return null;
|
|
|
|
const member = membersResult.data.find(m => m.userId === userId);
|
|
return member ? member.role : null;
|
|
|
|
} catch (error) {
|
|
console.error('❌ 获取用户角色失败:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// 更新群聊缓存
|
|
updateGroupCache(group) {
|
|
this.groupCache.set(group.groupId, {
|
|
...group,
|
|
timestamp: Date.now()
|
|
});
|
|
}
|
|
|
|
// 更新成员缓存
|
|
updateMemberCache(groupId, members) {
|
|
this.memberCache.set(groupId, {
|
|
members: members,
|
|
timestamp: Date.now()
|
|
});
|
|
}
|
|
|
|
// 从缓存中移除成员
|
|
removeMemberFromCache(groupId, memberId) {
|
|
const cached = this.memberCache.get(groupId);
|
|
if (cached) {
|
|
cached.members = cached.members.filter(m => m.userId !== memberId);
|
|
this.memberCache.set(groupId, cached);
|
|
}
|
|
}
|
|
|
|
// 更新成员角色
|
|
updateMemberRole(groupId, memberId, role) {
|
|
const cached = this.memberCache.get(groupId);
|
|
if (cached) {
|
|
const member = cached.members.find(m => m.userId === memberId);
|
|
if (member) {
|
|
member.role = role;
|
|
this.memberCache.set(groupId, cached);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 加载群聊缓存
|
|
async loadGroupCache() {
|
|
try {
|
|
const cached = wx.getStorageSync('groupCache') || {};
|
|
this.groupCache = new Map(Object.entries(cached));
|
|
} catch (error) {
|
|
console.error('❌ 加载群聊缓存失败:', error);
|
|
}
|
|
}
|
|
|
|
// 保存群聊缓存
|
|
saveGroupCache() {
|
|
try {
|
|
const cacheObj = Object.fromEntries(this.groupCache);
|
|
wx.setStorageSync('groupCache', cacheObj);
|
|
} catch (error) {
|
|
console.error('❌ 保存群聊缓存失败:', error);
|
|
}
|
|
}
|
|
|
|
// 获取群聊管理器状态
|
|
getStatus() {
|
|
return {
|
|
isInitialized: this.isInitialized,
|
|
groupCount: this.groupCache.size,
|
|
memberCacheCount: this.memberCache.size,
|
|
currentUserId: this.currentUserId,
|
|
config: this.groupConfig
|
|
};
|
|
}
|
|
|
|
// 清除所有缓存
|
|
clearAllCache() {
|
|
this.groupCache.clear();
|
|
this.memberCache.clear();
|
|
wx.removeStorageSync('groupCache');
|
|
console.log('👥 已清除所有群聊缓存');
|
|
}
|
|
|
|
// 重置管理器
|
|
reset() {
|
|
this.clearAllCache();
|
|
this.currentUserId = null;
|
|
this.isInitialized = false;
|
|
}
|
|
}
|
|
|
|
// 创建全局实例
|
|
const groupChatManager = new GroupChatManager();
|
|
|
|
module.exports = groupChatManager;
|