package com.gs.xky.service.Impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.dingtalk.api.DefaultDingTalkClient; import com.dingtalk.api.DingTalkClient; import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request; import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response; import com.gs.xky.entity.DingtalkInfo; import com.gs.xky.entity.DingtalkMsg; import com.gs.xky.entity.MesStaff; import com.gs.xky.mapper.DingtalkInfoMapper; import com.gs.xky.mapper.DingtalkMsgMapper; import com.gs.xky.mapper.MesStaffMapper; import com.gs.xky.service.DingtalkInfoService; import com.gs.xky.service.SimpleExample; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * @author 28567 * @description 针对表【DINGTALK_INFO】的数据库操作Service实现 * @createDate 2025-06-20 16:12:48 */ @Service @RequiredArgsConstructor @Slf4j public class DingtalkInfoServiceImpl extends ServiceImpl implements DingtalkInfoService { private final SimpleExample simpleExample; private final DingtalkMsgMapper dingtalkMsgMapper; private final MesStaffMapper mesStaffMapper; @Override public boolean sendMessage(String releaseNo) { try { // 查询钉钉消息内容 LambdaQueryWrapper msgWrapper = new LambdaQueryWrapper<>(); msgWrapper.eq(DingtalkMsg::getReleaseNo, releaseNo); DingtalkMsg dingtalkMsg = dingtalkMsgMapper.selectOne(msgWrapper); if (dingtalkMsg == null) { log.error("未找到检验单号为 {} 的钉钉消息内容", releaseNo); return false; } // 格式化日期 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); String createDateStr = (dingtalkMsg.getCreateDate() != null) ? dateFormat.format(dingtalkMsg.getCreateDate()) : "未知"; // 构建消息内容 String message = String.format("供应商[%s] 来料日期[%s] 项目[%s] 料号[%s]的不合格检验单被[%s]审批为[%s],请查收!", dingtalkMsg.getSuppName(), createDateStr, dingtalkMsg.getProjectCodes(), dingtalkMsg.getItemNo(), dingtalkMsg.getFname(), dingtalkMsg.getFngHandle()); // 收集需要推送的人员sid List sidList = new ArrayList<>(); // 1. 固定推送人员(isSendDingtalk=1) List fixedList = baseMapper.selectList( new LambdaQueryWrapper().eq(DingtalkInfo::getIsSendDingtalk, 1) ); for (DingtalkInfo info : fixedList) { sidList.add(info.getSid()); } // 2. 采购人员(employeeName) if (StringUtils.hasText(dingtalkMsg.getEmployeeName())) { MesStaff buyer = mesStaffMapper.selectOne( new LambdaQueryWrapper().eq(MesStaff::getStaffName, dingtalkMsg.getEmployeeName()) ); if (buyer != null) { DingtalkInfo buyerInfo = baseMapper.selectOne( new LambdaQueryWrapper().eq(DingtalkInfo::getSid, buyer.getId()) ); if (buyerInfo != null) sidList.add(buyerInfo.getSid()); } } // 3. 审核人(modify1By) if (StringUtils.hasText(dingtalkMsg.getModify1By())) { MesStaff auditor = mesStaffMapper.selectOne( new LambdaQueryWrapper().eq(MesStaff::getStaffNo, dingtalkMsg.getModify1By()) ); if (auditor != null) { DingtalkInfo auditorInfo = baseMapper.selectOne( new LambdaQueryWrapper().eq(DingtalkInfo::getSid, auditor.getId()) ); if (auditorInfo != null) sidList.add(auditorInfo.getSid()); } } // 4. 根据收集的sid获取dingtalkId (复用getDingtalkUserIdList的关键逻辑) List userIdList = getDingtalkUserIdListBySids(sidList); if (userIdList == null || userIdList.isEmpty()) { log.warn("没有需要发送钉钉消息的用户"); return false; } // 通过钉钉发送消息 String userIdListStr = String.join(",", userIdList); OapiMessageCorpconversationAsyncsendV2Response rsp = sendMessage(userIdListStr, message); System.out.println(rsp.getBody()); log.info("成功发送钉钉消息: {}", message); return true; } catch (Exception e) { log.error("发送钉钉消息失败", e); return false; } } /** * 根据指定的sid列表获取钉钉用户ID列表 * * @param sidList sid列表 * @return 钉钉用户ID列表 */ private List getDingtalkUserIdListBySids(List sidList) { try { if (sidList == null || sidList.isEmpty()) { return new ArrayList<>(); } // 去重 sidList = sidList.stream().distinct().collect(Collectors.toList()); // 根据sid查询DingtalkInfo List list = baseMapper.selectList( new LambdaQueryWrapper().in(DingtalkInfo::getSid, sidList) ); if (list == null || list.isEmpty()) { return new ArrayList<>(); } // 使用stream流过滤出list中dingtalkId为空的数据 List emptyDingtalkIdList = list.stream() .filter(info -> !StringUtils.hasText(info.getDingtalkId())) .collect(Collectors.toList()); // 如果存在为空的数据就通过钉钉的接口获取,为dingtalkId赋值,并且更新数据库 if (!emptyDingtalkIdList.isEmpty()) { String accessToken = simpleExample.getAccessToken(); for (DingtalkInfo info : emptyDingtalkIdList) { if (StringUtils.hasText(info.getPhone())) { try { // 通过手机号获取钉钉用户ID com.dingtalk.api.response.OapiV2UserGetbymobileResponse response = simpleExample.getOapiV2UserGetbymobileResponse(info.getPhone(), accessToken); if (response != null && response.getResult() != null) { info.setDingtalkId(response.getResult().getUserid()); // 更新数据库 updateById(info); } } catch (Exception e) { log.error("获取钉钉用户ID失败,手机号:{}", info.getPhone(), e); } } } } // 不存在为空的数据或者处理完空数据后,返回所有有效的dingtalkId列表 return list.stream() .map(DingtalkInfo::getDingtalkId) .filter(StringUtils::hasText) .distinct() .collect(Collectors.toList()); } catch (Exception e) { log.error("获取钉钉用户列表失败", e); return new ArrayList<>(); } } private OapiMessageCorpconversationAsyncsendV2Response sendMessage(String userIdListStr, String message) throws Exception { String accessToken = simpleExample.getAccessToken(); DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2"); OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request(); request.setAgentId(3917187842L); request.setUseridList(userIdListStr); request.setToAllUser(false); OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg(); msg.setMsgtype("text"); msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text()); msg.getText().setContent(message); request.setMsg(msg); return client.execute(request, accessToken); } /** * 获取isSendDingtalk=1的用户的钉钉用户ID列表(保留原有方法,向后兼容) */ private List getDingtalkUserIdList() { try { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.ge(DingtalkInfo::getIsSendDingtalk, 1); List list = list(wrapper); if (list == null || list.isEmpty()) { return new ArrayList<>(); } // 使用stream流过滤出list中dingtalkId为空的数据 List emptyDingtalkIdList = list.stream() .filter(info -> !StringUtils.hasText(info.getDingtalkId())) .collect(Collectors.toList()); // 如果存在为空的数据就通过钉钉的接口获取,为dingtalkId赋值,并且更新数据库 if (!emptyDingtalkIdList.isEmpty()) { String accessToken = simpleExample.getAccessToken(); for (DingtalkInfo info : emptyDingtalkIdList) { if (StringUtils.hasText(info.getPhone())) { try { // 通过手机号获取钉钉用户ID com.dingtalk.api.response.OapiV2UserGetbymobileResponse response = simpleExample.getOapiV2UserGetbymobileResponse(info.getPhone(), accessToken); if (response != null && response.getResult() != null) { info.setDingtalkId(response.getResult().getUserid()); // 更新数据库 updateById(info); } } catch (Exception e) { log.error("获取钉钉用户ID失败,手机号:{}", info.getPhone(), e); } } } } // 不存在为空的数据或者处理完空数据后,返回所有有效的dingtalkId列表 return list.stream() .map(DingtalkInfo::getDingtalkId) .filter(StringUtils::hasText) .distinct() .collect(Collectors.toList()); } catch (Exception e) { log.error("获取钉钉用户列表失败", e); return new ArrayList<>(); } } }