package cn.iocoder.yudao.module.wxcp.service.member; import cn.iocoder.yudao.module.wxcp.controller.admin.member.vo.WxCpDepartmentRespVO; import cn.iocoder.yudao.module.wxcp.controller.admin.member.vo.WxCpMemberRespVO; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.WxCpDepart; import me.chanjar.weixin.cp.bean.WxCpUser; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.wxcp.enums.ErrorCodeConstants.WXCP_API_ERROR; /** * 企业微信通讯录 Service 实现类 * * @author 超级管理员 */ @Service @Validated @Slf4j public class WxCpMemberServiceImpl implements WxCpMemberService { /** * 企业微信根部门ID固定为 1 */ private static final Long ROOT_DEPARTMENT_ID = 1L; @Resource private WxCpService wxCpService; @Override public List getDepartmentList() { List departs = listDeparts(); return departs.stream().map(this::toDeptVO).toList(); } @Override public List getDepartmentTree() { List departs = listDeparts(); Map voMap = new LinkedHashMap<>(); for (WxCpDepart d : departs) { voMap.put(d.getId(), toDeptVO(d)); } List roots = new ArrayList<>(); for (WxCpDepartmentRespVO vo : voMap.values()) { Long parentId = vo.getParentId(); WxCpDepartmentRespVO parent = parentId == null ? null : voMap.get(parentId); // 找不到父节点的(含顶级部门)都作为根返回,避免因数据缺失导致部门"消失" if (parent == null || parent == vo) { roots.add(vo); } else { parent.getChildren().add(vo); } } return roots; } @Override public List getMemberList(Long departmentId, Boolean fetchChild) { Long deptId = departmentId != null ? departmentId : ROOT_DEPARTMENT_ID; boolean child = fetchChild == null || fetchChild; List users; try { users = wxCpService.getUserService().listSimpleByDepartment(deptId, child, null); } catch (Exception e) { log.error("[getMemberList][获取企业微信成员失败 deptId={} fetchChild={}]", deptId, child, e); throw exception(WXCP_API_ERROR); } // 部门名映射,用于把成员的部门ID翻译成可读名称 Map deptNameMap = new LinkedHashMap<>(); for (WxCpDepart d : listDeparts()) { deptNameMap.put(d.getId(), d.getName()); } return users.stream().map(u -> toMemberVO(u, deptNameMap)).toList(); } /** * 获取全部部门(平铺)。企业微信 department/list 不传 id 时返回全量。 */ private List listDeparts() { try { List departs = wxCpService.getDepartmentService().list(null); return departs != null ? departs : List.of(); } catch (Exception e) { log.error("[listDeparts][获取企业微信部门失败]", e); throw exception(WXCP_API_ERROR); } } private WxCpDepartmentRespVO toDeptVO(WxCpDepart depart) { WxCpDepartmentRespVO vo = new WxCpDepartmentRespVO(); vo.setId(depart.getId()); vo.setName(depart.getName()); vo.setParentId(depart.getParentId()); vo.setOrder(depart.getOrder()); return vo; } private WxCpMemberRespVO toMemberVO(WxCpUser user, Map deptNameMap) { WxCpMemberRespVO vo = new WxCpMemberRespVO(); vo.setUserId(user.getUserId()); vo.setName(user.getName()); vo.setMobile(user.getMobile()); vo.setEmail(user.getEmail()); vo.setAvatar(user.getAvatar()); // 优先取 position,老接口可能只返回 positions 数组 String position = user.getPosition(); if (position == null && user.getPositions() != null && user.getPositions().length > 0) { position = String.join("、", user.getPositions()); } vo.setPosition(position); vo.setStatus(user.getStatus()); // Gender.getCode() 返回基本类型 int,不能与 null 组成三元表达式,这里单独判断 if (user.getGender() != null) { vo.setGender(user.getGender().getCode()); } Long[] deptIds = user.getDepartIds(); if (deptIds != null && deptIds.length > 0) { List ids = Arrays.asList(deptIds); vo.setDepartmentIds(ids); vo.setDepartmentNames(String.join("、", ids.stream() .map(id -> deptNameMap.getOrDefault(id, "部门" + id)) .toList())); } return vo; } }