package com.xuqm.im.service; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.xuqm.common.exception.BusinessException; import com.xuqm.im.entity.ImGroupEntity; import com.xuqm.im.entity.ImGroupMuteEntity; import com.xuqm.im.repository.ImGroupRepository; import com.xuqm.im.repository.ImGroupMuteRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; @Service public class ImGroupService { private final ImGroupRepository groupRepository; private final ImGroupMuteRepository muteRepository; private final ObjectMapper objectMapper; public ImGroupService(ImGroupRepository groupRepository, ImGroupMuteRepository muteRepository, ObjectMapper objectMapper) { this.groupRepository = groupRepository; this.muteRepository = muteRepository; this.objectMapper = objectMapper; } @Transactional public ImGroupEntity create(String appId, String name, String creatorId, List memberIds) { List members = new ArrayList<>(memberIds); if (!members.contains(creatorId)) members.add(creatorId); ImGroupEntity group = new ImGroupEntity(); group.setId(UUID.randomUUID().toString()); group.setAppId(appId); group.setName(name); group.setCreatorId(creatorId); group.setMemberIds(toJson(members)); group.setAdminIds(toJson(List.of(creatorId))); group.setAnnouncement(null); group.setCreatedAt(LocalDateTime.now()); return groupRepository.save(group); } public ImGroupEntity get(String groupId) { return groupRepository.findById(groupId) .orElseThrow(() -> new BusinessException(404, "群组不存在")); } public ImGroupEntity get(String groupId, String requesterId) { ImGroupEntity group = get(groupId); if (!memberIds(group).contains(requesterId) && !group.getCreatorId().equals(requesterId)) { throw new BusinessException(403, "不在群内"); } return group; } @Transactional public ImGroupEntity addMember(String groupId, String userId, String operatorId) { ImGroupEntity group = get(groupId); ensureCanManage(group, operatorId); List members = fromJson(group.getMemberIds()); if (!members.contains(userId)) { members.add(userId); group.setMemberIds(toJson(members)); groupRepository.save(group); } return group; } @Transactional public ImGroupEntity removeMember(String groupId, String userId, String operatorId) { ImGroupEntity group = get(groupId); List admins = fromJson(group.getAdminIds()); if (!admins.contains(operatorId) && !group.getCreatorId().equals(operatorId)) { throw new BusinessException(403, "无权操作"); } List members = new ArrayList<>(fromJson(group.getMemberIds())); members.remove(userId); group.setMemberIds(toJson(members)); return groupRepository.save(group); } @Transactional public ImGroupEntity update(String groupId, String operatorId, String name, String announcement) { ImGroupEntity group = get(groupId); ensureCanManage(group, operatorId); if (name != null && !name.isBlank()) { group.setName(name); } if (announcement != null) { group.setAnnouncement(announcement); } return groupRepository.save(group); } @Transactional public ImGroupEntity setRole(String groupId, String operatorId, String userId, String role) { ImGroupEntity group = get(groupId); ensureCanManage(group, operatorId); List admins = new ArrayList<>(fromJson(group.getAdminIds())); if ("ADMIN".equalsIgnoreCase(role)) { if (!admins.contains(userId)) admins.add(userId); } else { admins.remove(userId); if (userId.equals(group.getCreatorId())) { throw new BusinessException(403, "群主不能降级"); } } group.setAdminIds(toJson(admins)); return groupRepository.save(group); } @Transactional public ImGroupEntity muteMember(String groupId, String operatorId, String userId, long minutes) { ImGroupEntity group = get(groupId); ensureCanManage(group, operatorId); ImGroupMuteEntity mute = muteRepository .findByGroupIdAndUserIdAndMutedUntilAfter(groupId, userId, LocalDateTime.now()) .orElseGet(() -> { ImGroupMuteEntity entity = new ImGroupMuteEntity(); entity.setId(UUID.randomUUID().toString()); entity.setGroupId(groupId); entity.setUserId(userId); entity.setCreatedAt(LocalDateTime.now()); return entity; }); mute.setMutedUntil(LocalDateTime.now().plusMinutes(Math.max(minutes, 0))); mute.setUpdatedAt(LocalDateTime.now()); muteRepository.save(mute); return group; } @Transactional public void dismiss(String groupId, String operatorId) { ImGroupEntity group = get(groupId); if (!group.getCreatorId().equals(operatorId)) { throw new BusinessException(403, "只有群主可以解散群"); } muteRepository.deleteByGroupId(groupId); groupRepository.delete(group); } public boolean isMemberMuted(String groupId, String userId) { return muteRepository.findByGroupIdAndUserIdAndMutedUntilAfter(groupId, userId, LocalDateTime.now()).isPresent(); } public List memberIds(ImGroupEntity group) { return fromJson(group.getMemberIds()); } public List adminIds(ImGroupEntity group) { return fromJson(group.getAdminIds()); } public List listByApp(String appId) { return groupRepository.findByAppId(appId); } public List listUserGroups(String appId, String userId) { return groupRepository.findUserGroups(appId, userId); } private String toJson(List list) { try { return objectMapper.writeValueAsString(list); } catch (Exception e) { return "[]"; } } private List fromJson(String json) { try { return objectMapper.readValue(json, new TypeReference<>() {}); } catch (Exception e) { return new ArrayList<>(); } } private void ensureCanManage(ImGroupEntity group, String operatorId) { List admins = fromJson(group.getAdminIds()); if (!admins.contains(operatorId) && !group.getCreatorId().equals(operatorId)) { throw new BusinessException(403, "无权操作"); } } }