Browse Source

同步通讯录

luolinsong 1 month ago
parent
commit
cdd694406c

+ 30 - 0
fs-service/src/main/java/com/fs/company/domain/WxRoom.java

@@ -0,0 +1,30 @@
+package com.fs.company.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 微信群聊信息表 wx_room
+ */
+@Data
+public class WxRoom {
+    private Long id; //主键
+    private String roomId;//群聊唯一标识
+    private String roomName;//群名称
+    private String roomOwnerId;//群主ID
+    private Integer chatroomMaxCount;//群聊最大人数
+    private Integer memberCount;//群成员数量
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(fill = FieldFill.INSERT)
+    private Date createTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(fill = FieldFill.INSERT)
+    private Date updateTime;
+
+}

+ 30 - 0
fs-service/src/main/java/com/fs/company/domain/WxRoomMembers.java

@@ -0,0 +1,30 @@
+package com.fs.company.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 群成员对象 wx_room_members
+ */
+@Data
+public class WxRoomMembers {
+    private Long id;//主键
+    private String roomId;//群聊唯一标识
+    private String roomName;//群名称
+    private String roomOwnerId;//群主ID
+    private String roomMemberId;//群成员wx号
+    private String roomMemberName;//群成员wx名称
+    private Integer chatroomMemberFlag;//群等级:1普通 9群主
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(fill = FieldFill.INSERT)
+    private Date createTime;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(fill = FieldFill.INSERT)
+    private Date updateTime;
+
+}

+ 41 - 0
fs-service/src/main/java/com/fs/company/mapper/WxRoomMapper.java

@@ -0,0 +1,41 @@
+package com.fs.company.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.company.domain.CompanyWxClient;
+import com.fs.company.domain.WxRoom;
+import jodd.introspector.Mapper;
+
+import java.util.List;
+
+
+public interface WxRoomMapper extends BaseMapper<WxRoom>  {
+    /**
+     * 根据ID查询群聊信息
+     */
+    WxRoom selectWxRoomById(Long id);
+
+    /**
+     * 查询群聊信息列表
+     */
+    List<WxRoom> selectWxRoomList(WxRoom wxRoom);
+
+    /**
+     * 新增群聊信息
+     */
+    int insertWxRoom(WxRoom wxRoom);
+
+    /**
+     * 修改群聊信息
+     */
+    int updateWxRoom(WxRoom wxRoom);
+
+    /**
+     * 删除群聊信息
+     */
+    int deleteWxRoomById(Long id);
+
+    /**
+     * 批量删除群聊信息
+     */
+    int deleteWxRoomByIds(Long[] ids);
+}

+ 49 - 0
fs-service/src/main/java/com/fs/company/mapper/WxRoomMembersMapper.java

@@ -0,0 +1,49 @@
+package com.fs.company.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.company.domain.WxRoom;
+import com.fs.company.domain.WxRoomMembers;
+
+import java.util.List;
+
+public interface WxRoomMembersMapper extends BaseMapper<WxRoomMembers> {
+    /**
+     * 根据ID查询群成员信息
+     */
+    WxRoomMembers selectWxRoomMembersById(Long id);
+
+    /**
+     * 查询群成员信息列表
+     */
+    List<WxRoomMembers> selectWxRoomMembersList(WxRoomMembers wxRoomMembers);
+
+    /**
+     * 新增群成员信息
+     */
+    int insertWxRoomMembers(WxRoomMembers wxRoomMembers);
+
+    /**
+     * 修改群成员信息
+     */
+    int updateWxRoomMembers(WxRoomMembers wxRoomMembers);
+
+    /**
+     * 删除群成员信息
+     */
+    int deleteWxRoomMembersById(Long id);
+
+    /**
+     * 批量删除群成员信息
+     */
+    int deleteWxRoomMembersByIds(Long[] ids);
+
+    /**
+     * 根据群ID删除群成员信息
+     */
+    int deleteWxRoomMembersByRoomId(String roomId);
+
+    /**
+     * 根据群ID查询群成员数量
+     */
+    int selectMemberCountByRoomId(String roomId);
+}

+ 73 - 0
fs-service/src/main/java/com/fs/company/service/IWxRoomMembersService.java

@@ -0,0 +1,73 @@
+package com.fs.company.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.company.domain.WxRoom;
+import com.fs.company.domain.WxRoomMembers;
+
+import java.util.List;
+
+public interface IWxRoomMembersService extends IService<WxRoomMembers> {
+    /**
+     * 查询群成员信息
+     *
+     * @param id 群成员ID
+     * @return 群成员信息
+     */
+    WxRoomMembers selectWxRoomMembersById(Long id);
+
+    /**
+     * 查询群成员信息列表
+     *
+     * @param wxRoomMembers 群成员信息
+     * @return 群成员集合
+     */
+    List<WxRoomMembers> selectWxRoomMembersList(WxRoomMembers wxRoomMembers);
+
+    /**
+     * 新增群成员信息
+     *
+     * @param wxRoomMembers 群成员信息
+     * @return 结果
+     */
+    int insertWxRoomMembers(WxRoomMembers wxRoomMembers);
+
+    /**
+     * 修改群成员信息
+     *
+     * @param wxRoomMembers 群成员信息
+     * @return 结果
+     */
+    int updateWxRoomMembers(WxRoomMembers wxRoomMembers);
+
+    /**
+     * 批量删除群成员信息
+     *
+     * @param ids 需要删除的群成员ID
+     * @return 结果
+     */
+    int deleteWxRoomMembersByIds(Long[] ids);
+
+    /**
+     * 删除群成员信息信息
+     *
+     * @param id 群成员ID
+     * @return 结果
+     */
+    int deleteWxRoomMembersById(Long id);
+
+    /**
+     * 根据群ID删除群成员信息
+     *
+     * @param roomId 群ID
+     * @return 结果
+     */
+    int deleteWxRoomMembersByRoomId(String roomId);
+
+    /**
+     * 根据群ID查询群成员数量
+     *
+     * @param roomId 群ID
+     * @return 成员数量
+     */
+    int selectMemberCountByRoomId(String roomId);
+}

+ 56 - 0
fs-service/src/main/java/com/fs/company/service/IWxRoomService.java

@@ -0,0 +1,56 @@
+package com.fs.company.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.company.domain.WxRoom;
+
+import java.util.List;
+
+public interface IWxRoomService extends IService<WxRoom> {
+    /**
+     * 查询群聊信息
+     *
+     * @param id 群聊ID
+     * @return 群聊信息
+     */
+    WxRoom selectWxRoomById(Long id);
+
+    /**
+     * 查询群聊信息列表
+     *
+     * @param wxRoom 群聊信息
+     * @return 群聊集合
+     */
+    List<WxRoom> selectWxRoomList(WxRoom wxRoom);
+
+    /**
+     * 新增群聊信息
+     *
+     * @param wxRoom 群聊信息
+     * @return 结果
+     */
+    int insertWxRoom(WxRoom wxRoom);
+
+    /**
+     * 修改群聊信息
+     *
+     * @param wxRoom 群聊信息
+     * @return 结果
+     */
+    int updateWxRoom(WxRoom wxRoom);
+
+    /**
+     * 批量删除群聊信息
+     *
+     * @param ids 需要删除的群聊ID
+     * @return 结果
+     */
+    int deleteWxRoomByIds(Long[] ids);
+
+    /**
+     * 删除群聊信息信息
+     *
+     * @param id 群聊ID
+     * @return 结果
+     */
+    int deleteWxRoomById(Long id);
+}

+ 242 - 21
fs-service/src/main/java/com/fs/company/service/impl/CompanyWxServiceImpl.java

@@ -1,25 +1,23 @@
 package com.fs.company.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.annotation.DataScope;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCacheT;
 import com.fs.common.utils.DateUtils;
-import com.fs.company.domain.Company;
-import com.fs.company.domain.CompanyUser;
-import com.fs.company.domain.CompanyWxAccount;
-import com.fs.company.domain.CompanyWxClient;
+import com.fs.company.domain.*;
 import com.fs.company.mapper.CompanyWxAccountMapper;
 import com.fs.company.mapper.CompanyWxClientMapper;
-import com.fs.company.service.ICompanyService;
-import com.fs.company.service.ICompanyUserService;
-import com.fs.company.service.ICompanyWxAccountService;
+import com.fs.company.service.*;
 import com.fs.wxcid.domain.CidIpadServerUser;
 import com.fs.wxcid.domain.WxContact;
+import com.fs.wxcid.dto.friend.ContactItem;
 import com.fs.wxcid.dto.friend.ContactListResponse;
 import com.fs.wxcid.dto.friend.GetContactDetailsResponseData;
 import com.fs.wxcid.dto.login.LoginStatusResponseData;
+import com.fs.wxcid.dto.message.ChatroomMember;
 import com.fs.wxcid.dto.message.UserNameWrapper;
 import com.fs.wxcid.dto.user.UserInfo;
 import com.fs.wxcid.dto.user.UserInfoExt;
@@ -28,10 +26,10 @@ import com.fs.wxcid.mapper.wx.ModContactDbMapper;
 import com.fs.wxcid.service.*;
 import com.fs.wxcid.service.impl.LoginServiceImpl;
 import com.fs.wxcid.service.impl.UserServiceImpl;
-import com.fs.wxcid.vo.VerifyUserValidTicketListVo;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.time.LocalDateTime;
 import java.util.*;
@@ -39,7 +37,7 @@ import java.util.stream.Collectors;
 
 /**
  * 企微账号Service业务层处理
- * 
+ *
  * @author fs
  * @date 2024-12-09
  */
@@ -49,6 +47,12 @@ public class CompanyWxServiceImpl extends ServiceImpl<CompanyWxAccountMapper, Co
     private final static String FRIEND_KEY = "cid:wx:friend-list:";
     private final static List<String> REMOVE_FRIEND_STR_ARRAY = Arrays.asList("weixin", "fmessage", "medianote", "gh_3dfda90e39d6", "qqmail");
     private final static String IS_ROOM_KEY = "@chatroom";
+
+
+
+    private static final long SYNC_INTERVAL = 30 * 1000; // 同步间隔时间
+    private static final int BATCH_SIZE = 100; // 批量插入批次大小
+
     @Autowired
     private CompanyWxAccountMapper companyWxAccountMapper;
     @Autowired
@@ -77,10 +81,16 @@ public class CompanyWxServiceImpl extends ServiceImpl<CompanyWxAccountMapper, Co
     private ModContactDbMapper modContactDbMapper;
     @Autowired
     private IWxContactService wxContactService;
+    @Autowired
+    private IWxRoomService wxRoomService;
+    @Autowired
+    private IWxRoomMembersService wxRoomMembersService;
+
+
 
     /**
      * 查询企微账号
-     * 
+     *
      * @param id 企微账号ID
      * @return 企微账号
      */
@@ -92,7 +102,7 @@ public class CompanyWxServiceImpl extends ServiceImpl<CompanyWxAccountMapper, Co
 
     /**
      * 查询企微账号列表
-     * 
+     *
      * @param companyWxAccount 企微账号
      * @return 企微账号
      */
@@ -110,7 +120,7 @@ public class CompanyWxServiceImpl extends ServiceImpl<CompanyWxAccountMapper, Co
 
     /**
      * 新增企微账号
-     * 
+     *
      * @param companyWxAccount 企微账号
      * @return 结果
      */
@@ -123,7 +133,7 @@ public class CompanyWxServiceImpl extends ServiceImpl<CompanyWxAccountMapper, Co
 
     /**
      * 修改企微账号
-     * 
+     *
      * @param companyWxAccount 企微账号
      * @return 结果
      */
@@ -135,7 +145,7 @@ public class CompanyWxServiceImpl extends ServiceImpl<CompanyWxAccountMapper, Co
 
     /**
      * 批量删除企微账号
-     * 
+     *
      * @param ids 需要删除的企微账号ID
      * @return 结果
      */
@@ -147,7 +157,7 @@ public class CompanyWxServiceImpl extends ServiceImpl<CompanyWxAccountMapper, Co
 
     /**
      * 删除企微账号信息
-     * 
+     *
      * @param id 企微账号ID
      * @return 结果
      */
@@ -274,17 +284,228 @@ public class CompanyWxServiceImpl extends ServiceImpl<CompanyWxAccountMapper, Co
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void syncWx(Long accountId) {
+        // 1. 参数校验
+        if (accountId == null) {
+            log.error("同步微信信息失败:accountId不能为空");
+            throw new IllegalArgumentException("accountId不能为空");
+        }
+
+        // 2. 获取账号信息并更新同步时间
         CompanyWxAccount account = getById(accountId);
+        if (account == null) {
+            log.error("同步微信信息失败:个微账号不存在,accountId={}", accountId);
+            throw new RuntimeException("个微账号不存在,accountId=" + accountId);
+        }
         account.setSyncFriendTime(LocalDateTime.now());
-        String key = FRIEND_KEY + accountId;
-        friendListRedis.deleteObject(key);
-        ContactListResponse response = friendService.getContactListNotKey(accountId);
-        List<String> friendList = response.getContactList().getContactUsernameList().stream().filter(e -> !REMOVE_FRIEND_STR_ARRAY.contains(e)).collect(Collectors.toList());
-        friendListRedis.setCacheObject(key, friendList);
-        updateById(account);
+
+        try {
+            // 3. 清理Redis缓存
+            String key = FRIEND_KEY + accountId;
+            friendListRedis.deleteObject(key);
+
+            // 4. 获取好友列表并过滤
+            ContactListResponse response = friendService.getContactListNotKey(accountId);
+            List<String> friendList = getFilteredFriendList(response);
+            if (CollectionUtils.isEmpty(friendList)) {
+                log.info("账号暂无需要同步的微信好友/群聊,accountId={}", accountId);
+                updateById(account);
+                return;
+            }
+
+            // 5. 缓存好友列表到Redis
+            friendListRedis.setCacheObject(key, friendList);
+
+            // 6. 同步联系人信息
+            syncContactDetails(accountId, account, friendList);
+
+            // 7. 更新账号信息
+            updateById(account);
+
+            log.info("微信信息同步完成,accountId={},同步联系人数量={}", accountId, friendList.size());
+        } catch (Exception e) {
+            log.error("同步微信信息异常,accountId={}", accountId, e);
+            throw e;
+        }
+    }
+
+    /**
+     * 获取过滤后的好友列表
+     */
+    private List<String> getFilteredFriendList(ContactListResponse response) {
+        if (response == null || response.getContactList() == null ||
+                CollectionUtils.isEmpty(response.getContactList().getContactUsernameList())) {
+            return Collections.emptyList();
+        }
+        // 过滤掉无效的好友标识
+        return response.getContactList().getContactUsernameList()
+                .stream().filter(e -> !REMOVE_FRIEND_STR_ARRAY.contains(e)).collect(Collectors.toList());
     }
 
+    /**
+     * 同步联系人详情信息
+     */
+    private void syncContactDetails(Long accountId, CompanyWxAccount account, List<String> friendList) {
+        List<WxContact> wxContacts = new ArrayList<>();
+        List<WxRoom> wxRooms = new ArrayList<>();
+        List<WxRoomMembers> wxRoomMembersList = new ArrayList<>();
+
+        for (String username : friendList) {
+            try {
+                // 获取联系人详情
+                GetContactDetailsResponseData contactDetails = friendService.getContactDetailsList(accountId, Collections.singletonList(username));
+                if (contactDetails == null || CollectionUtils.isEmpty(contactDetails.getContactList())) {
+                    log.warn("联系人详情为空,username={},accountId={}", username, accountId);
+                    continue;
+                }
+
+                // 根据类型处理不同的联系人
+                List<ContactItem> contactList = contactDetails.getContactList();
+                if (username.endsWith("@chatroom")) {
+                    // 处理群聊信息
+                    convertToWxRoom(contactList, wxRooms);
+                    // 处理群成员信息
+                    convertToWxRoomMembers(contactList, wxRoomMembersList);
+                } else {
+                    // 处理个人好友信息
+                    convertToWxContact(contactList, accountId, account, wxContacts);
+                }
+
+                // 控制同步频率,避免接口限流
+                Thread.sleep(SYNC_INTERVAL);
+            } catch (InterruptedException e) {
+                log.error("同步联系人信息被中断,username={},accountId={}", username, accountId, e);
+                Thread.currentThread().interrupt(); // 恢复中断状态
+                break; // 中断循环,避免无效执行
+            } catch (Exception e) {
+                log.error("同步单个联系人信息失败,username={},accountId={}", username, accountId, e);
+                // 继续处理下一个联系人,不中断整体同步
+                continue;
+            }
+        }
+        // 批量插入数据(设置批次大小,避免一次性插入过多数据)
+        batchSaveData(wxContacts, wxRooms, wxRoomMembersList);
+    }
+
+    /**
+     * 批量保存数据
+     */
+    private void batchSaveData(List<WxContact> wxContacts, List<WxRoom> wxRooms, List<WxRoomMembers> wxRoomMembersList) {
+        // 保存群聊信息
+        if (!CollectionUtils.isEmpty(wxRooms)) {
+            wxRoomService.saveBatch(wxRooms, BATCH_SIZE);
+        }
+        // 保存个人好友信息
+        if (!CollectionUtils.isEmpty(wxContacts)) {
+            wxContactService.saveBatch(wxContacts, BATCH_SIZE);
+        }
+        // 保存群成员信息
+        if (!CollectionUtils.isEmpty(wxRoomMembersList)) {
+            wxRoomMembersService.saveBatch(wxRoomMembersList, BATCH_SIZE);
+        }
+    }
+
+    /**
+     * 转换为WxRoom对象
+     */
+    private void convertToWxRoom(List<ContactItem> contactList, List<WxRoom> wxRooms) {
+        ContactItem contactItem = contactList.get(0);
+        if (contactItem == null) {
+            return;
+        }
+        WxRoom wxRoom = new WxRoom();
+        wxRoom.setRoomId(getStringValue(contactItem.getUserName()));
+        wxRoom.setRoomName(getStringValue(contactItem.getNickName()));
+        wxRoom.setRoomOwnerId(contactItem.getChatRoomOwner());
+        wxRoom.setChatroomMaxCount(parseInt(contactItem.getChatroomMaxCount()));
+        wxRoom.setMemberCount(parseInt(contactItem.getNewChatroomData() != null ? contactItem.getNewChatroomData().getMemberCount() : null));
+        wxRoom.setCreateTime(DateUtils.getNowDate());
+        wxRoom.setUpdateTime(DateUtils.getNowDate());
+        wxRooms.add(wxRoom);
+    }
+
+    /**
+     * 转换为WxRoomMembers对象
+     */
+    private void convertToWxRoomMembers(List<ContactItem> contactList, List<WxRoomMembers> wxRoomMembersList) {
+        ContactItem contactItem = contactList.get(0);
+        if (contactItem == null || contactItem.getNewChatroomData() == null ||
+                CollectionUtils.isEmpty(contactItem.getNewChatroomData().getChatroomMemberList())) {
+            return;
+        }
+
+        String roomId = getStringValue(contactItem.getUserName());
+        String roomName = getStringValue(contactItem.getNickName());
+        String roomOwnerId = contactItem.getChatRoomOwner();
+
+        for (ChatroomMember chatroomMember : contactItem.getNewChatroomData().getChatroomMemberList()) {
+            if (chatroomMember == null) {
+                continue;
+            }
+            WxRoomMembers wxRoomMembers = new WxRoomMembers();
+            wxRoomMembers.setRoomId(roomId);
+            wxRoomMembers.setRoomName(roomName);
+            wxRoomMembers.setRoomOwnerId(roomOwnerId);
+            wxRoomMembers.setRoomMemberId(chatroomMember.getUserName());
+            wxRoomMembers.setRoomMemberName(chatroomMember.getNickName());
+            wxRoomMembers.setChatroomMemberFlag(chatroomMember.getChatroomMemberFlag());
+            wxRoomMembers.setCreateTime(DateUtils.getNowDate());
+            wxRoomMembers.setUpdateTime(DateUtils.getNowDate());
+            wxRoomMembersList.add(wxRoomMembers);
+        }
+    }
+
+    /**
+     * 转换为WxContact对象
+     */
+    private void convertToWxContact(List<ContactItem> contactList, Long accountId,
+                                    CompanyWxAccount account, List<WxContact> wxContacts) {
+        ContactItem contactItem = contactList.get(0);
+        if (contactItem == null) {
+            return;
+        }
+        WxContact wxContact = new WxContact();
+        wxContact.setUserName(getStringValue(contactItem.getUserName()));
+        wxContact.setNickName(getStringValue(contactItem.getNickName()));
+        wxContact.setQuanPin(getStringValue(contactItem.getQuanPin()));
+        wxContact.setSex(contactItem.getSex());
+        wxContact.setAlias(contactItem.getAlias());
+        wxContact.setHeadImgUrl(contactItem.getBigHeadImgUrl());
+        wxContact.setEncryptUserName(contactItem.getEncryptUserName());
+        wxContact.setProvince(contactItem.getProvince());
+        wxContact.setCity(contactItem.getCity());
+        wxContact.setAccountId(accountId);
+        wxContact.setCompanyId(account.getCompanyId());
+        wxContact.setCompanyUserId(account.getCompanyUserId());
+        wxContact.setCreateTime(DateUtils.getNowDate());
+        wxContact.setUpdateTime(DateUtils.getNowDate());
+        wxContacts.add(wxContact);
+    }
+
+    /**
+     * 安全获取字符串值(避免空指针)
+     */
+    private String getStringValue(UserNameWrapper obj) {
+        return obj != null && obj.getStr() != null ? obj.getStr() : "";
+    }
+
+    /**
+     * 安全转换为整数
+     */
+    private Integer parseInt(Object value) {
+        if (value == null) {
+            return 0;
+        }
+        try {
+            return Integer.valueOf(value.toString());
+        } catch (NumberFormatException e) {
+            log.warn("转换整数失败,value={}", value);
+            return 0;
+        }
+    }
+
+
     @Override
     public void isCheckContact(String formUser, Long accountId) {
         GetContactDetailsResponseData details = friendService.getContactDetailsList(accountId, Collections.singletonList(formUser));

+ 56 - 0
fs-service/src/main/java/com/fs/company/service/impl/WxRoomMembersServiceImpl.java

@@ -0,0 +1,56 @@
+package com.fs.company.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.company.domain.WxRoomMembers;
+import com.fs.company.mapper.WxRoomMembersMapper;
+import com.fs.company.service.IWxRoomMembersService;
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import java.util.List;
+
+@Service
+public class WxRoomMembersServiceImpl extends ServiceImpl<WxRoomMembersMapper, WxRoomMembers> implements IWxRoomMembersService {
+
+    @Resource
+    private WxRoomMembersMapper wxRoomMembersMapper;
+
+    @Override
+    public WxRoomMembers selectWxRoomMembersById(Long id) {
+        return wxRoomMembersMapper.selectWxRoomMembersById(id);
+    }
+
+    @Override
+    public List<WxRoomMembers> selectWxRoomMembersList(WxRoomMembers wxRoomMembers) {
+        return wxRoomMembersMapper.selectWxRoomMembersList(wxRoomMembers);
+    }
+
+    @Override
+    public int insertWxRoomMembers(WxRoomMembers wxRoomMembers) {
+        return wxRoomMembersMapper.insertWxRoomMembers(wxRoomMembers);
+    }
+
+    @Override
+    public int updateWxRoomMembers(WxRoomMembers wxRoomMembers) {
+        return wxRoomMembersMapper.updateWxRoomMembers(wxRoomMembers);
+    }
+
+    @Override
+    public int deleteWxRoomMembersByIds(Long[] ids) {
+        return wxRoomMembersMapper.deleteWxRoomMembersByIds(ids);
+    }
+
+    @Override
+    public int deleteWxRoomMembersById(Long id) {
+        return wxRoomMembersMapper.deleteWxRoomMembersById(id);
+    }
+
+    @Override
+    public int deleteWxRoomMembersByRoomId(String roomId) {
+        return wxRoomMembersMapper.deleteWxRoomMembersByRoomId(roomId);
+    }
+
+    @Override
+    public int selectMemberCountByRoomId(String roomId) {
+        return wxRoomMembersMapper.selectMemberCountByRoomId(roomId);
+    }
+}

+ 47 - 0
fs-service/src/main/java/com/fs/company/service/impl/WxRoomServiceImpl.java

@@ -0,0 +1,47 @@
+package com.fs.company.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.company.domain.WxRoom;
+import com.fs.company.mapper.WxRoomMapper;
+import com.fs.company.service.IWxRoomService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Service
+public class WxRoomServiceImpl extends ServiceImpl<WxRoomMapper, WxRoom> implements IWxRoomService {
+
+    @Resource
+    private WxRoomMapper wxRoomMapper;
+
+    @Override
+    public WxRoom selectWxRoomById(Long id) {
+        return wxRoomMapper.selectWxRoomById(id);
+    }
+
+    @Override
+    public List<WxRoom> selectWxRoomList(WxRoom wxRoom) {
+        return wxRoomMapper.selectWxRoomList(wxRoom);
+    }
+
+    @Override
+    public int insertWxRoom(WxRoom wxRoom) {
+        return wxRoomMapper.insertWxRoom(wxRoom);
+    }
+
+    @Override
+    public int updateWxRoom(WxRoom wxRoom) {
+        return wxRoomMapper.updateWxRoom(wxRoom);
+    }
+
+    @Override
+    public int deleteWxRoomByIds(Long[] ids) {
+        return wxRoomMapper.deleteWxRoomByIds(ids);
+    }
+
+    @Override
+    public int deleteWxRoomById(Long id) {
+        return wxRoomMapper.deleteWxRoomById(id);
+    }
+}

+ 10 - 0
fs-service/src/main/java/com/fs/wxcid/dto/friend/ContactItem.java

@@ -2,6 +2,7 @@ package com.fs.wxcid.dto.friend;
 
 import com.alibaba.fastjson.annotation.JSONField;
 import com.fs.wxcid.dto.message.UserNameWrapper;
+import com.fs.wxcid.dto.message.newChatroomDataWrapper;
 import lombok.Data;
 
 /**
@@ -49,5 +50,14 @@ public class ContactItem {
     @JSONField(name = "encryptUserName")
     private String encryptUserName;
 
+
+    @JSONField(name = "chatRoomOwner")
+    private String chatRoomOwner;
+
+    @JSONField(name = "chatroomMaxCount")
+    private String chatroomMaxCount;
+
+    @JSONField(name = "newChatroomData")
+    private newChatroomDataWrapper newChatroomData;
     // 可根据需要补充其他字段...
 }

+ 32 - 0
fs-service/src/main/java/com/fs/wxcid/dto/message/ChatroomMember.java

@@ -0,0 +1,32 @@
+package com.fs.wxcid.dto.message;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+
+@Data
+public class ChatroomMember {
+
+    /**
+     * 成员微信唯一ID(如 wxid_xxx)
+     */
+    @JSONField(name = "userName")
+    private String userName;
+
+    /**
+     * 成员昵称
+     */
+    @JSONField(name = "nickName")
+    private String nickName;
+
+    /**
+     * 成员身份标识(1=普通成员,9=群主/管理员)
+     */
+    @JSONField(name = "chatroomMemberFlag")
+    private Integer chatroomMemberFlag;
+
+    /**
+     * 未知字段(通常为群主ID,保留避免解析报错)
+     */
+    @JSONField(name = "unknow")
+    private String unknow;
+}

+ 18 - 0
fs-service/src/main/java/com/fs/wxcid/dto/message/newChatroomDataWrapper.java

@@ -0,0 +1,18 @@
+package com.fs.wxcid.dto.message;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class newChatroomDataWrapper {
+    /**
+     * 实际的用户名字符串(如 wxid_xxx)
+     */
+    @JSONField(name = "memberCount")
+    private String memberCount;
+
+    @JSONField(name = "chatroomMemberList")
+    private List<ChatroomMember> chatroomMemberList;
+}

+ 83 - 0
fs-service/src/main/resources/mapper/company/WxRoomMapper.xml

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.company.mapper.WxRoomMapper">
+
+    <resultMap type="WxRoom" id="WxRoomResult">
+        <result property="id"    column="id"    />
+        <result property="roomId"    column="room_id"    />
+        <result property="roomName"    column="room_name"    />
+        <result property="roomOwnerId"    column="room_owner_id"    />
+        <result property="chatroomMaxCount"    column="chatroom_max_count"    />
+        <result property="memberCount"    column="member_count"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+    </resultMap>
+
+    <sql id="selectWxRoomVo">
+        select id, room_id, room_name, room_owner_id, chatroom_max_count, member_count, create_time, update_time
+        from wx_room
+    </sql>
+
+    <select id="selectWxRoomById" parameterType="Long" resultMap="WxRoomResult">
+        <include refid="selectWxRoomVo"/>
+        where id = #{id}
+    </select>
+
+    <select id="selectWxRoomList" parameterType="WxRoom" resultMap="WxRoomResult">
+        <include refid="selectWxRoomVo"/>
+        <where>
+            <if test="roomId != null  and roomId != ''"> and room_id = #{roomId}</if>
+            <if test="roomName != null  and roomName != ''"> and room_name like concat('%', #{roomName}, '%')</if>
+            <if test="roomOwnerId != null  and roomOwnerId != ''"> and room_owner_id = #{roomOwnerId}</if>
+        </where>
+    </select>
+
+    <insert id="insertWxRoom" parameterType="WxRoom" useGeneratedKeys="true" keyProperty="id">
+        insert into wx_room
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="roomId != null and roomId != ''">room_id,</if>
+            <if test="roomName != null and roomName != ''">room_name,</if>
+            <if test="roomOwnerId != null and roomOwnerId != ''">room_owner_id,</if>
+            <if test="chatroomMaxCount != null">chatroom_max_count,</if>
+            <if test="memberCount != null">member_count,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="roomId != null and roomId != ''">#{roomId},</if>
+            <if test="roomName != null and roomName != ''">#{roomName},</if>
+            <if test="roomOwnerId != null and roomOwnerId != ''">#{roomOwnerId},</if>
+            <if test="chatroomMaxCount != null">#{chatroomMaxCount},</if>
+            <if test="memberCount != null">#{memberCount},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+        </trim>
+    </insert>
+
+    <update id="updateWxRoom" parameterType="WxRoom">
+        update wx_room
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="roomId != null and roomId != ''">room_id = #{roomId},</if>
+            <if test="roomName != null and roomName != ''">room_name = #{roomName},</if>
+            <if test="roomOwnerId != null and roomOwnerId != ''">room_owner_id = #{roomOwnerId},</if>
+            <if test="chatroomMaxCount != null">chatroom_max_count = #{chatroomMaxCount},</if>
+            <if test="memberCount != null">member_count = #{memberCount},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteWxRoomById" parameterType="Long">
+        delete from wx_room where id = #{id}
+    </delete>
+
+    <delete id="deleteWxRoomByIds" parameterType="Long">
+        delete from wx_room where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+</mapper>

+ 98 - 0
fs-service/src/main/resources/mapper/company/WxRoomMembersMapper.xml

@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.company.mapper.WxRoomMembersMapper">
+
+    <resultMap type="WxRoomMembers" id="WxRoomMembersResult">
+        <result property="id"    column="id"    />
+        <result property="roomId"    column="room_id"    />
+        <result property="roomName"    column="room_name"    />
+        <result property="roomOwnerId"    column="room_owner_id"    />
+        <result property="roomMemberId"    column="room_member_id"    />
+        <result property="roomMemberName"    column="room_member_name"    />
+        <result property="chatroomMemberFlag"    column="chatroom_member_flag"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+    </resultMap>
+
+    <sql id="selectWxRoomMembersVo">
+        select id, room_id, room_name, room_owner_id, room_member_id, room_member_name, chatroom_member_flag, create_time, update_time
+        from wx_room_members
+    </sql>
+
+    <select id="selectWxRoomMembersById" parameterType="Long" resultMap="WxRoomMembersResult">
+        <include refid="selectWxRoomMembersVo"/>
+        where id = #{id}
+    </select>
+
+    <select id="selectWxRoomMembersList" parameterType="WxRoomMembers" resultMap="WxRoomMembersResult">
+        <include refid="selectWxRoomMembersVo"/>
+        <where>
+            <if test="roomId != null  and roomId != ''"> and room_id = #{roomId}</if>
+            <if test="roomName != null  and roomName != ''"> and room_name like concat('%', #{roomName}, '%')</if>
+            <if test="roomOwnerId != null  and roomOwnerId != ''"> and room_owner_id = #{roomOwnerId}</if>
+            <if test="roomMemberId != null  and roomMemberId != ''"> and room_member_id = #{roomMemberId}</if>
+            <if test="roomMemberName != null  and roomMemberName != ''"> and room_member_name like concat('%', #{roomMemberName}, '%')</if>
+            <if test="chatroomMemberFlag != null"> and chatroom_member_flag = #{chatroomMemberFlag}</if>
+        </where>
+    </select>
+
+    <insert id="insertWxRoomMembers" parameterType="WxRoomMembers" useGeneratedKeys="true" keyProperty="id">
+        insert into wx_room_members
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="roomId != null and roomId != ''">room_id,</if>
+            <if test="roomName != null and roomName != ''">room_name,</if>
+            <if test="roomOwnerId != null and roomOwnerId != ''">room_owner_id,</if>
+            <if test="roomMemberId != null and roomMemberId != ''">room_member_id,</if>
+            <if test="roomMemberName != null and roomMemberName != ''">room_member_name,</if>
+            <if test="chatroomMemberFlag != null">chatroom_member_flag,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="roomId != null and roomId != ''">#{roomId},</if>
+            <if test="roomName != null and roomName != ''">#{roomName},</if>
+            <if test="roomOwnerId != null and roomOwnerId != ''">#{roomOwnerId},</if>
+            <if test="roomMemberId != null and roomMemberId != ''">#{roomMemberId},</if>
+            <if test="roomMemberName != null and roomMemberName != ''">#{roomMemberName},</if>
+            <if test="chatroomMemberFlag != null">#{chatroomMemberFlag},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+        </trim>
+    </insert>
+
+    <update id="updateWxRoomMembers" parameterType="WxRoomMembers">
+        update wx_room_members
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="roomId != null and roomId != ''">room_id = #{roomId},</if>
+            <if test="roomName != null and roomName != ''">room_name = #{roomName},</if>
+            <if test="roomOwnerId != null and roomOwnerId != ''">room_owner_id = #{roomOwnerId},</if>
+            <if test="roomMemberId != null and roomMemberId != ''">room_member_id = #{roomMemberId},</if>
+            <if test="roomMemberName != null and roomMemberName != ''">room_member_name = #{roomMemberName},</if>
+            <if test="chatroomMemberFlag != null">chatroom_member_flag = #{chatroomMemberFlag},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteWxRoomMembersById" parameterType="Long">
+        delete from wx_room_members where id = #{id}
+    </delete>
+
+    <delete id="deleteWxRoomMembersByRoomId" parameterType="String">
+        delete from wx_room_members where room_id = #{roomId}
+    </delete>
+
+    <delete id="deleteWxRoomMembersByIds" parameterType="Long">
+        delete from wx_room_members where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+    <select id="selectMemberCountByRoomId" parameterType="String" resultType="int">
+        select count(*) from wx_room_members where room_id = #{roomId}
+    </select>
+
+</mapper>