| pom.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/gs/xky/entity/DingtalkMsg.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/gs/xky/service/DingtalkInfoService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/gs/xky/service/Impl/DingtalkInfoServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/gs/xky/service/Impl/MesQaItemsDetect01ServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/gs/xky/service/XkyService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/gs/xky/task/ScheduledTasks.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/application.yml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/mapper/VwCjScSjTsBbMonthMapper.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/test/java/com/gs/xky/XkyApplicationTests.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
pom.xml
@@ -96,13 +96,6 @@ <artifactId>hutool-all</artifactId> <version>5.8.18</version> </dependency> <!-- Apache POI for Excel (required by Hutool) --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.3</version> </dependency> </dependencies> <build> src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java
@@ -25,26 +25,19 @@ /** * 应用的 AgentId */ public static final Long AGENT_ID = 4104598880L; public static final Long AGENT_ID = 3303296035L; /** * 应用的 AppKey */ public static final String TALK_APP_KEY = "dinggglb3pttl1x0gn0c"; public static final String TALK_APP_KEY = "dingnpc4kma0t19nphhd"; /** * 应用的 AppSecret */ public static final String TALK_APP_SECRET = "Zc7r0Mb7bPsC_xy7ryrWoEnE5OzHEXibUMPDCA2LBusJ9pYzIolRk_OdZuLvNExf"; public static final String TALK_APP_SECRET = "uMecvKIfErf9htigYIyjI3svHpXEEDWROy2v1cXw7V6EXIG09oQI5N5e-EMqBo4r"; //群聊机器人相关 public static final String CUSTOM_ROBOT_TOKEN = "c2849e46cb0d91b0721c377742938b8ac5ef57e3c9eeab918e2cd5dd9c3aad2a"; public static final String SECRET = "SEC382027a5c81ea5152b71b687fb2c1ebf26acbde035355da6ab2fb37306454134"; //企业微信 public static final String CORPID = "wwabe21b935901a7d8"; public static final String CORPSECRET = "Z-7fNbZjrd80ypz69U14j8FMxI_fpUxcT6PksxlvKaY"; public static final String TXL_CORPSECRET = "T64bdcV7fo0hvW10W3NJYmGUmlBYxYMfiW6EiUJ9VPM"; } src/main/java/com/gs/xky/entity/DingtalkMsg.java
@@ -51,4 +51,8 @@ * 审核人 */ private String modify1By; /** * 料品名称 */ private String itemName; } src/main/java/com/gs/xky/service/DingtalkInfoService.java
@@ -11,15 +11,4 @@ public interface DingtalkInfoService extends IService<DingtalkInfo> { boolean sendMessage(String releaseNo); boolean sendActionCardMessage() throws Exception; /** * 发送文件消息 * * @param filePath 本地文件路径 * @return 是否发送成功 * @throws Exception 异常 */ boolean sendFileMessage(String filePath) throws Exception; } src/main/java/com/gs/xky/service/Impl/DingtalkInfoServiceImpl.java
@@ -14,13 +14,11 @@ import com.gs.xky.mapper.MesStaffMapper; import com.gs.xky.service.DingtalkInfoService; import com.gs.xky.service.SimpleExample; import com.taobao.api.FileItem; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; @@ -132,95 +130,6 @@ } } @Override public boolean sendActionCardMessage() { try { // 1. 获取需要推送的用户列表(可以是固定推送用户) List<DingtalkInfo> fixedList = baseMapper.selectList( new LambdaQueryWrapper<DingtalkInfo>().eq(DingtalkInfo::getIsHead, 1) ); List<Long> sidList = fixedList.stream() .map(DingtalkInfo::getSid) .collect(Collectors.toList()); List<String> userIdList = getDingtalkUserIdListBySids(sidList); if (userIdList == null || userIdList.isEmpty()) { log.warn("没有需要发送钉钉消息的用户"); return false; } String userIdListStr = String.join(",", userIdList); // 2. 构建消息内容 String title = "生产数据看板"; String markdown = "请点击下方按钮查看详细BI报表"; String singleTitle = "查看报表"; String singleUrl = "http://192.168.1.22:8081/design?fid=rpte6045ab079b211f0824bd3cfd50c6b93&fserid=4b198960bedd11f09f6f792bfe147b64&fsharetype=3"; // 3. 发送消息 OapiMessageCorpconversationAsyncsendV2Response rsp = sendActionCardMessage(userIdListStr, title, markdown, singleTitle, singleUrl); log.info("成功发送ActionCard消息: {}", rsp.getBody()); return true; } catch (Exception e) { log.error("发送ActionCard消息失败", e); return false; } } @Override public boolean sendFileMessage(String filePath) throws Exception { try { // 1. 检查文件是否存在 File file = new File(filePath); if (!file.exists()) { log.error("文件不存在: {}", filePath); return false; } // 2. 获取需要推送的用户列表(可根据实际需求调整,这里使用isHead=1的用户) List<DingtalkInfo> fixedList = baseMapper.selectList( new LambdaQueryWrapper<DingtalkInfo>().eq(DingtalkInfo::getIsHead, 1) ); if (fixedList == null || fixedList.isEmpty()) { log.warn("没有需要发送文件的用户(isHead=1)"); return false; } List<String> sidList = fixedList.stream() .map(DingtalkInfo::getPhone) .collect(Collectors.toList()); List<String> userIdList = getDingtalkUserIdListByPhones(sidList); if (userIdList == null || userIdList.isEmpty()) { log.warn("没有有效的钉钉用户ID"); return false; } String userIdListStr = String.join(",", userIdList); // 3. 上传文件到钉钉服务器 log.info("开始上传文件: {}", filePath); String mediaId = uploadMedia(filePath, "file"); // 4. 发送文件消息 log.info("开始发送文件消息,mediaId: {}", mediaId); OapiMessageCorpconversationAsyncsendV2Response response = sendFileMessageByMediaId(userIdListStr, mediaId); log.info("文件消息发送响应: {}", response.getBody()); return response.getErrcode() == 0; } catch (Exception e) { log.error("发送文件消息失败", e); throw e; } } /** * 根据指定的sid列表获取钉钉用户ID列表 * @@ -285,72 +194,13 @@ } } private List<String> getDingtalkUserIdListByPhones(List<String> phoneList) { try { if (phoneList == null || phoneList.isEmpty()) { return new ArrayList<>(); } // 去重 phoneList = phoneList.stream().distinct().collect(Collectors.toList()); // 根据sid查询DingtalkInfo List<DingtalkInfo> list = baseMapper.selectList( new LambdaQueryWrapper<DingtalkInfo>().in(DingtalkInfo::getPhone, phoneList) ); if (list == null || list.isEmpty()) { return new ArrayList<>(); } // 使用stream流过滤出list中dingtalkId为空的数据 List<DingtalkInfo> 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(4104598880L); request.setAgentId(3917187842L); request.setUseridList(userIdListStr); request.setToAllUser(false); @@ -358,135 +208,6 @@ msg.setMsgtype("text"); msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text()); msg.getText().setContent(message); request.setMsg(msg); return client.execute(request, accessToken); } /** * 发送link消息(在钉钉内置浏览器中打开) * * @param userIdListStr 用户ID列表,逗号分隔 * @param title 消息标题 * @param text 消息内容 * @param messageUrl 点击消息后跳转的URL * @param picUrl 图片URL(可选) * @return 响应结果 * @throws Exception 异常 */ private OapiMessageCorpconversationAsyncsendV2Response sendLinkMessage(String userIdListStr, String title, String text, String messageUrl, String picUrl) 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(4104598880L); request.setUseridList(userIdListStr); request.setToAllUser(false); OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg(); msg.setMsgtype("link"); msg.setLink(new OapiMessageCorpconversationAsyncsendV2Request.Link()); msg.getLink().setTitle(title); msg.getLink().setText(text); msg.getLink().setMessageUrl(messageUrl); if (StringUtils.hasText(picUrl)) { msg.getLink().setPicUrl(picUrl); } request.setMsg(msg); return client.execute(request, accessToken); } /** * 发送ActionCard消息(在外部浏览器中打开链接,适合BI等外部系统) * * @param userIdListStr 用户ID列表,逗号分隔 * @param title 消息标题 * @param markdown 消息内容(支持Markdown格式) * @param singleTitle 按钮文字,例如:"查看详情" * @param singleUrl 点击按钮后跳转的URL(外部链接) * @return 响应结果 * @throws Exception 异常 */ private OapiMessageCorpconversationAsyncsendV2Response sendActionCardMessage(String userIdListStr, String title, String markdown, String singleTitle, String singleUrl) 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(4104598880L); request.setUseridList(userIdListStr); request.setToAllUser(false); OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg(); msg.setMsgtype("action_card"); msg.setActionCard(new OapiMessageCorpconversationAsyncsendV2Request.ActionCard()); msg.getActionCard().setTitle(title); msg.getActionCard().setMarkdown(markdown); msg.getActionCard().setSingleTitle(singleTitle); msg.getActionCard().setSingleUrl(singleUrl); request.setMsg(msg); return client.execute(request, accessToken); } /** * 上传文件到钉钉服务器,获取media_id * * @param filePath 本地文件路径 * @param fileType 文件类型:file(普通文件), voice(语音文件), video(视频文件), image(图片文件) * @return media_id * @throws Exception 异常 */ private String uploadMedia(String filePath, String fileType) throws Exception { String accessToken = simpleExample.getAccessToken(); DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/media/upload"); com.dingtalk.api.request.OapiMediaUploadRequest request = new com.dingtalk.api.request.OapiMediaUploadRequest(); request.setType(fileType); // 使用 FileItem 包装文件 File file = new File(filePath); FileItem fileItem = new FileItem(file); request.setMedia(fileItem); com.dingtalk.api.response.OapiMediaUploadResponse response = client.execute(request, accessToken); if (response.getErrcode() == 0) { log.info("文件上传成功,media_id: {}", response.getMediaId()); return response.getMediaId(); } else { log.error("文件上传失败,错误码: {}, 错误信息: {}", response.getErrcode(), response.getErrmsg()); throw new Exception("文件上传失败: " + response.getErrmsg()); } } /** * 通过media_id发送文件消息 * * @param userIdListStr 用户ID列表,逗号分隔 * @param mediaId 文件的media_id(通过uploadMedia方法获取) * @return 响应结果 * @throws Exception 异常 */ private OapiMessageCorpconversationAsyncsendV2Response sendFileMessageByMediaId(String userIdListStr, String mediaId) 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(4104598880L); request.setUseridList(userIdListStr); request.setToAllUser(false); OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg(); msg.setMsgtype("file"); msg.setFile(new OapiMessageCorpconversationAsyncsendV2Request.File()); msg.getFile().setMediaId(mediaId); request.setMsg(msg); return client.execute(request, accessToken); src/main/java/com/gs/xky/service/Impl/MesQaItemsDetect01ServiceImpl.java
@@ -47,6 +47,11 @@ List<String> collect = list.stream().filter(s -> !StrUtil.isNotEmpty(s.getFcheckResu())).map(MesQaItemsDetect01::getReleaseNo).collect(Collectors.toList()); if (CollUtil.isEmpty(collect)) { return true; } LambdaUpdateWrapper<MesQaItemsDetect01> updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.in(MesQaItemsDetect01::getReleaseNo, collect); if (remove(wrapper)) { src/main/java/com/gs/xky/service/XkyService.java
@@ -97,7 +97,7 @@ private void processBatchDeliveries(List<XkyEntity> batchDeliveries) { batchDeliveries.forEach(deliveryNo -> { try { if ("6".equals(deliveryNo.getStatus()) || "0".equals(deliveryNo.getLogisticsStatus())) { if ("6".equals(deliveryNo.getStatus()) || "8".equals(deliveryNo.getStatus()) || "0".equals(deliveryNo.getLogisticsStatus())) { log.info("【processBatchDeliveries】移除送货单: {}", deliveryNo.getDeliveryNo()); remove1(deliveryNo); } else if ("1".equals(deliveryNo.getStatus()) && ("2".equals(deliveryNo.getLogisticsStatus()) || "1".equals(deliveryNo.getLogisticsStatus()))) { src/main/java/com/gs/xky/task/ScheduledTasks.java
@@ -1,157 +1,133 @@ package com.gs.xky.task; import com.gs.xky.service.VwCjScSjTsBbService; import cn.hutool.core.collection.ListUtil; import com.gs.xky.config.DingTalkParam; import com.gs.xky.config.DingTalkResponse; import com.gs.xky.dto.EmployeeInfo; import com.gs.xky.entity.MesInvItemArn; import com.gs.xky.service.*; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.io.IOException; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; @Component @RequiredArgsConstructor public class ScheduledTasks { private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class); private final VwCjScSjTsBbService vwCjScSjTsBbService; private final AtomicBoolean exportTaskRunning = new AtomicBoolean(false); // private final XkyService xkyService; // private final ApiService apiService; // private final MesStaffService staffService; // private final DeliveryNoticeService deliveryNoticeService; // private final MesInvItemArnService invItemArnService; // private final Executor taskExecutor; // 注入通用线程池 private final XkyService xkyService; private final ApiService apiService; private final MesStaffService staffService; private final DeliveryNoticeService deliveryNoticeService; private final MesInvItemArnService invItemArnService; private final Executor taskExecutor; // 注入通用线程池 // 用于标记各任务是否正在执行 // private final AtomicBoolean isDeviceDataRunning = new AtomicBoolean(false); // private final AtomicBoolean isCompensateRunning = new AtomicBoolean(false); // private final AtomicBoolean isDingTalkRunning = new AtomicBoolean(false); private final AtomicBoolean isDeviceDataRunning = new AtomicBoolean(false); private final AtomicBoolean isCompensateRunning = new AtomicBoolean(false); private final AtomicBoolean isDingTalkRunning = new AtomicBoolean(false); /** * 每天上午9点执行 * 导出生产数据并发送钉钉消息 * 每五分钟执行一次 * 获取设备最近的一条记录 */ @Async("taskExecutor") @Scheduled(cron = "0 0 12,16 * * ?") public void exportAndSendProductionDataTask() { if (!exportTaskRunning.compareAndSet(false, true)) { log.warn("生产数据导出任务正在执行中,跳过本次执行"); @Scheduled(cron = "0 0/5 * * * ?") public void getDeviceRealTimeData() { // 如果任务已经在运行,则跳过本次执行 if (!isDeviceDataRunning.compareAndSet(false, true)) { log.info("【getDeviceRealTimeData】上一次任务还在执行中,跳过本次执行"); return; } try { log.info("开始执行生产数据导出并发送钉钉任务"); boolean result = vwCjScSjTsBbService.exportAndSendToDingtalk(); log.info("【getDeviceRealTimeData】开始获取设备实时数据"); if (result) { log.info("生产数据导出并发送钉钉任务执行成功"); } else { log.error("生产数据导出并发送钉钉任务执行失败"); // 使用异步执行,避免阻塞调度线程 CompletableFuture.runAsync(() -> { try { xkyService.GetSaveDetail(); log.info("【getDeviceRealTimeData】获取设备实时数据成功"); } catch (IOException e) { log.error("【getDeviceRealTimeData】获取设备实时数据异常: {}", e.getMessage(), e); } finally { isDeviceDataRunning.set(false); } } catch (Exception e) { log.error("生产数据导出并发送钉钉任务执行异常", e); } finally { exportTaskRunning.set(false); } }, taskExecutor); } // /** // * 每五分钟执行一次 // * 获取协客云最近的一条记录 // */ // @Scheduled(cron = "0 0/5 * * * ?") // public void getDeviceRealTimeData() { // // 如果任务已经在运行,则跳过本次执行 // if (!isDeviceDataRunning.compareAndSet(false, true)) { // log.info("【getDeviceRealTimeData】上一次任务还在执行中,跳过本次执行"); // return; // } // // log.info("【getDeviceRealTimeData】开始获取设备实时数据"); // // // 使用异步执行,避免阻塞调度线程 // CompletableFuture.runAsync(() -> { // try { // xkyService.GetSaveDetail(); // log.info("【getDeviceRealTimeData】获取设备实时数据成功"); // } catch (IOException e) { // log.error("【getDeviceRealTimeData】获取设备实时数据异常: {}", e.getMessage(), e); // } finally { // isDeviceDataRunning.set(false); // } // }, taskExecutor); // } // // /** // * 定时执行补偿逻辑 // */ // @Scheduled(cron = "10 3,8,13,18,23,28,33,38,43,48,53,58 * * * ?") // public void compensateMethod() { // // 如果任务已经在运行,则跳过本次执行 // if (!isCompensateRunning.compareAndSet(false, true)) { // log.info("【compensateMethod】上一次任务还在执行中,跳过本次执行"); // return; // } // // log.info("【compensateMethod】开始执行补偿逻辑"); // // // 使用异步执行,避免阻塞调度线程 // CompletableFuture.runAsync(() -> { // try { // // 补偿逻辑 // List<MesInvItemArn> itemArnMinus = invItemArnService.getItemArnMinus(); // deliveryNoticeService.processMesInvItemArnStatusAsync(itemArnMinus); // log.info("【compensateMethod】补偿逻辑执行成功"); // } catch (Exception e) { // log.error("【compensateMethod】补偿逻辑执行异常: {}", e.getMessage(), e); // } finally { // isCompensateRunning.set(false); // } // }, taskExecutor); // } // // /** // * 定时获取钉钉数据 // */ // @Scheduled(cron = "0 0/53 * * * ?") // public void getDinTalkData() { // // 如果任务已经在运行,则跳过本次执行 // if (!isDingTalkRunning.compareAndSet(false, true)) { // log.info("【getDinTalkData】上一次任务还在执行中,跳过本次执行"); // return; // } // // log.info("【getDinTalkData】开始获取钉钉数据"); // // // 使用异步执行,避免阻塞调度线程 // CompletableFuture.runAsync(() -> { // try { // DingTalkParam dingTalkParam = new DingTalkParam(1); // DingTalkResponse<EmployeeInfo> employeeInfoDingTalkResponse = // apiService.sendListRequest(dingTalkParam, EmployeeInfo.class, // "http://192.168.1.64/eHR/eHRExternalService/Service.ashx"); // // List<EmployeeInfo> collect = employeeInfoDingTalkResponse.getData().stream() // .filter(s -> "造梦者(浙江)科技有限公司".equals(s.getCUnitName())) // .collect(Collectors.toList()); // // log.info("【getDinTalkData】获取到{}条员工数据", collect.size()); // // List<List<EmployeeInfo>> partition = ListUtil.partition(collect, 100); // partition.forEach(staffService::UpdateStaff); // // log.info("【getDinTalkData】钉钉数据处理完成"); // } catch (IOException e) { // log.error("【getDinTalkData】获取钉钉数据异常: {}", e.getMessage(), e); // } finally { // isDingTalkRunning.set(false); // } // }, taskExecutor); // } /** * 定时执行补偿逻辑 */ @Scheduled(cron = "10 3,8,13,18,23,28,33,38,43,48,53,58 * * * ?") public void compensateMethod() { // 如果任务已经在运行,则跳过本次执行 if (!isCompensateRunning.compareAndSet(false, true)) { log.info("【compensateMethod】上一次任务还在执行中,跳过本次执行"); return; } log.info("【compensateMethod】开始执行补偿逻辑"); // 使用异步执行,避免阻塞调度线程 CompletableFuture.runAsync(() -> { try { // 补偿逻辑 List<MesInvItemArn> itemArnMinus = invItemArnService.getItemArnMinus(); deliveryNoticeService.processMesInvItemArnStatusAsync(itemArnMinus); log.info("【compensateMethod】补偿逻辑执行成功"); } catch (Exception e) { log.error("【compensateMethod】补偿逻辑执行异常: {}", e.getMessage(), e); } finally { isCompensateRunning.set(false); } }, taskExecutor); } /** * 定时获取钉钉数据 */ @Scheduled(cron = "0 0/53 * * * ?") public void getDinTalkData() { // 如果任务已经在运行,则跳过本次执行 if (!isDingTalkRunning.compareAndSet(false, true)) { log.info("【getDinTalkData】上一次任务还在执行中,跳过本次执行"); return; } log.info("【getDinTalkData】开始获取钉钉数据"); // 使用异步执行,避免阻塞调度线程 CompletableFuture.runAsync(() -> { try { DingTalkParam dingTalkParam = new DingTalkParam(1); DingTalkResponse<EmployeeInfo> employeeInfoDingTalkResponse = apiService.sendListRequest(dingTalkParam, EmployeeInfo.class, "http://192.168.1.64/eHR/eHRExternalService/Service.ashx"); List<EmployeeInfo> collect = employeeInfoDingTalkResponse.getData().stream() .filter(s -> "造梦者(浙江)科技有限公司".equals(s.getCUnitName())) .collect(Collectors.toList()); log.info("【getDinTalkData】获取到{}条员工数据", collect.size()); List<List<EmployeeInfo>> partition = ListUtil.partition(collect, 100); partition.forEach(staffService::UpdateStaff); log.info("【getDinTalkData】钉钉数据处理完成"); } catch (IOException e) { log.error("【getDinTalkData】获取钉钉数据异常: {}", e.getMessage(), e); } finally { isDingTalkRunning.set(false); } }, taskExecutor); } } src/main/resources/application.yml
@@ -5,9 +5,9 @@ datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: oracle.jdbc.OracleDriver url: jdbc:oracle:thin:@192.168.1.22:1521/ORCL username: hm_prd password: hmprd url: jdbc:oracle:thin:@192.168.1.104:1521/ORCL username: zmz_prd password: zmzprd druid: initialSize: 5 minIdle: 5 src/main/resources/mapper/VwCjScSjTsBbMonthMapper.xml
@@ -4,27 +4,4 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.gs.xky.mapper.VwCjScSjTsBbMonthMapper"> <resultMap id="BaseResultMap" type="com.gs.xky.entity.VwCjScSjTsBbMonth"> <result property="itemName" column="ITEM_NAME" /> <result property="itemNo" column="ITEM_NO" /> <result property="departmentname" column="DEPARTMENTNAME" /> <result property="departmentcode" column="DEPARTMENTCODE" /> <result property="daa001" column="DAA001" /> <result property="lineName" column="LINE_NAME" /> <result property="lineNo" column="LINE_NO" /> <result property="daa008" column="DAA008" /> <result property="yjkg" column="YJKG" /> <result property="sjkg" column="SJKG" /> <result property="sq" column="SQ" /> <result property="rk" column="RK" /> <result property="sqwwg" column="SQWWG" /> <result property="rkwwg" column="RKWWG" /> <result property="sqwrk" column="SQWRK" /> </resultMap> <sql id="Base_Column_List"> ITEM_NAME,ITEM_NO,DEPARTMENTNAME,DEPARTMENTCODE,DAA001,LINE_NAME, LINE_NO,DAA008,YJKG,SJKG,SQ, RK,SQWWG,RKWWG,SQWRK </sql> </mapper> src/test/java/com/gs/xky/XkyApplicationTests.java
@@ -1,7 +1,14 @@ package com.gs.xky; import com.gs.xky.service.VwCjScSjTsBbService; import com.gs.xky.service.WorkWXService; import com.alibaba.fastjson.JSONObject; import com.gs.xky.config.ApiResponse; import com.gs.xky.config.BodyParam; import com.gs.xky.config.DataAcquisitionConfiguration; import com.gs.xky.config.XkyCommonParam; import com.gs.xky.dto.BarcodeDeliveryNo; import com.gs.xky.dto.XkyDetail; import com.gs.xky.dto.XkyEntity; import com.gs.xky.service.*; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -13,126 +20,168 @@ class XkyApplicationTests { public static final String URL = "http://192.168.1.64/eHR/eHRExternalService/Service.ashx"; @Autowired private VwCjScSjTsBbService vwCjScSjTsBbService; private XkyService xkyService; @Autowired private WorkWXService workWXService; private ApiService apiService; /** * 测试导出生产数据并发送钉钉消息 * 功能:查询VW_CJ_SC_SJ_TS_BB表数据 -> 导出Excel -> 发送钉钉文件消息 */ @Autowired private MesStaffService staffService; @Autowired private DeliveryNoticeService deliveryNoticeService; @Autowired private TblBarcodeInformationService barcodeInformationService; @Autowired private MesInvItemArnService invItemArnService; @Autowired private PurchaseService service; @Autowired private DingtalkInfoService dingtalkInfoService; @Test void testExportAndSendProductionData() throws Exception { System.out.println("=== 开始测试导出生产数据并发送钉钉 ==="); void contextLoads() throws IOException { // try { // boolean result = vwCjScSjTsBbService.exportAndSendToDingtalk(); // List<MesInvItemArn> itemArnMinus = invItemArnService.getItemArnMinus(); // // if (result) { // System.out.println("✓ 生产数据导出并发送成功"); // System.out.println(" - 数据已从 VW_CJ_SC_SJ_TS_BB 表查询"); // System.out.println(" - Excel 文件已生成并保存到 D:\\BIFile\\"); // System.out.println(" - 钉钉文件消息已发送"); // } else { // System.out.println("✗ 生产数据导出或发送失败"); // } // } catch (Exception e) { // System.out.println("✗ 导出并发送时发生异常: " + e.getMessage()); // e.printStackTrace(); // } // deliveryNoticeService.processMesInvItemArnStatusAsync(itemArnMinus); System.out.println("=== 测试结束 ==="); } @Test void testGetCheckinDataByQwStaff() { System.out.println("=== 开始测试通过QW_STAFF表获取打卡数据 ==="); try { long currentTime = System.currentTimeMillis() / 1000; long oneDaySeconds = 86400; long endTime = (currentTime / oneDaySeconds) * oneDaySeconds - 1; long startTime = endTime - oneDaySeconds + 1; System.out.println(" - 开始时间: " + new java.util.Date(startTime * 1000)); System.out.println(" - 结束时间: " + new java.util.Date(endTime * 1000)); List<WorkWXService.CheckinData> checkinDataList = workWXService.getCheckinDataByQwStaff(startTime, endTime); if (checkinDataList != null && !checkinDataList.isEmpty()) { System.out.println("✓ 成功获取打卡数据"); System.out.println(" - 打卡记录总数: " + checkinDataList.size()); System.out.println(" - 前5条数据:"); checkinDataList.stream().limit(5).forEach(data -> { System.out.println(" * userid: " + data.getUserid() + ", 打卡时间: " + new java.util.Date(data.getCheckinTime() * 1000) + ", 打卡类型: " + data.getCheckinType() + ", 异常类型: " + data.getExceptionType() + ", 地点: " + data.getLocationDetail()); }); } else { System.out.println("✗ 获取的打卡数据为空(可能QW_STAFF表无数据或时间范围内无打卡记录)"); } } catch (IOException e) { System.out.println("✗ 获取打卡数据失败: " + e.getMessage()); e.printStackTrace(); } System.out.println("=== 测试结束 ==="); public void getDeviceRealTimeData() throws IOException { // xkyService.GetSaveDetail(); } @Test void testGetWorkWXUserList() { System.out.println("=== 开始测试获取企业微信用户列表 ==="); void cs() throws IOException { try { List<WorkWXService.WorkWXUser> userList = workWXService.getUserList(); String str = "22251123LM3X"; if (userList != null && !userList.isEmpty()) { System.out.println("✓ 成功获取企业微信用户列表"); System.out.println(" - 用户总数: " + userList.size()); System.out.println(" - 前10条数据:"); userList.stream().limit(10).forEach(user -> { System.out.println(" * userid: " + user.getUserid() + ", 姓名: " + user.getName() + ", 部门: " + user.getDepartment()); }); } else { System.out.println("✗ 获取的用户列表为空"); String[] split = str.split(";"); for (String s : split) { XkyCommonParam param = XkyCommonParam.GetInit(); // 创建 BodyParam 对象并赋值 BodyParam bodyParam = new BodyParam(); bodyParam.setErpCode(DataAcquisitionConfiguration.TEST_ERP_CODE); bodyParam.setDeliveryNo(s); param.setBody(bodyParam); ApiResponse<XkyDetail> detail = apiService.sendListRequest(param, XkyDetail.class, "https://openapi.xiekeyun.com/delivery/getDetail.json"); XkyDetail deliveryNo = detail.getData(); System.out.println((JSONObject) JSONObject.toJSON(deliveryNo)); if (deliveryNo == null) { System.out.println("为空的送货单号" + s); return; } } catch (IOException e) { System.out.println("✗ 获取用户列表失败: " + e.getMessage()); e.printStackTrace(); System.out.println("送货单状态" + deliveryNo.getStatus()); if ("6".equals(deliveryNo.getStatus()) || "8".equals(deliveryNo.getStatus()) || "0".equals(deliveryNo.getLogisticsStatus())) { XkyEntity xkyEntity = new XkyEntity(); xkyEntity.setDeliveryNo(deliveryNo.getDeliveryNo()); xkyService.remove1(xkyEntity); } else if ("1".equals(deliveryNo.getStatus()) && ("2".equals(deliveryNo.getLogisticsStatus()) || "1".equals(deliveryNo.getLogisticsStatus()))) { XkyDetail detail1 = deliveryNo; deliveryNoticeService.saveDeliveryNotice(detail1); List<BarcodeDeliveryNo> barcodeDeliveryNos = GetBarcodeInformation(deliveryNo.getDeliveryNo()); barcodeInformationService.SaveBarcodeInformation(barcodeDeliveryNos, deliveryNo.getDeliveryNo()); if ("2".equals(deliveryNo.getLogisticsStatus())) { deliveryNoticeService.callPdaReceiptBtn("送货单签收[BTNOK[PL017[" + deliveryNo.getDeliveryNo(), ""); } } } } System.out.println("=== 测试结束 ==="); private List<BarcodeDeliveryNo> GetBarcodeInformation(String deliveryNo) throws IOException { XkyCommonParam param = XkyCommonParam.GetInit(); // 创建 BodyParam 对象并赋值 BodyParam bodyParam = new BodyParam(); bodyParam.setErpCode(DataAcquisitionConfiguration.TEST_ERP_CODE); bodyParam.setDeliveryNo(deliveryNo); param.setBody(bodyParam); ApiResponse<BarcodeDeliveryNo> noList = apiService.sendListRequest(param, BarcodeDeliveryNo.class, "https://openapi.xiekeyun.com/barcode/byDeliveryNo.json"); return noList.getDataList(); } @Test void testGetUserDetail() { System.out.println("=== 开始测试获取用户详情 ==="); void cs1() throws IOException { // DingTalkParam dingTalkParam = new DingTalkParam(0); // // DingTalkResponse<EmployeeInfo> employeeInfoDingTalkResponse = apiService.sendListRequest(dingTalkParam, EmployeeInfo.class, "http://192.168.1.64/eHR/eHRExternalService/Service.ashx"); // // //造梦者(浙江)科技有限公司 cUnitName // //http://192.168.1.64/eHR // List<EmployeeInfo> collect = employeeInfoDingTalkResponse.getData().stream().filter(s -> "造梦者(浙江)科技有限公司".equals(s.getCUnitName())).collect(Collectors.toList()); // //System.out.println(collect.size()); // // collect.stream().filter(s->s.getEmployeeId().equals("2025130028")).forEach(System.out::println); // // List<List<EmployeeInfo>> partition = ListUtil.partition(collect, 500); try { String userid = "ShenJuanYue"; WorkWXService.WorkWXUserDetail userDetail = workWXService.getUserDetail(userid); // partition.forEach(list -> { // staffService.SaveStaff(list); // }); // XkyCommonParam param = XkyCommonParam.GetInit(); // String jsonString = JSON.toJSONString(param); // System.out.println(jsonString); } if (userDetail != null && userDetail.getErrcode() == 0) { System.out.println("✓ 成功获取用户详情"); System.out.println(" - userid: " + userDetail.getUserid()); System.out.println(" - 姓名: " + userDetail.getName()); System.out.println(" - 手机号: " + userDetail.getMobile()); System.out.println(" - 职位: " + userDetail.getPosition()); } else { System.out.println("✗ 获取用户详情失败"); } } catch (IOException e) { System.out.println("✗ 获取用户详情失败: " + e.getMessage()); e.printStackTrace(); } @Test void cs2() throws IOException { // DingTalkParam dingTalkParam = new DingTalkParam(1); // // DingTalkResponse<EmployeeInfo> employeeInfoDingTalkResponse = apiService.sendListRequest(dingTalkParam, EmployeeInfo.class, "http://192.168.1.64/eHR/eHRExternalService/Service.ashx"); // // //造梦者(浙江)科技有限公司 cUnitName // //http://192.168.1.64/eHR // List<EmployeeInfo> collect = employeeInfoDingTalkResponse.getData().stream().filter(s -> "造梦者(浙江)科技有限公司".equals(s.getCUnitName())).collect(Collectors.toList()); // System.out.println(collect.size()); // // List<List<EmployeeInfo>> partition = ListUtil.partition(collect, 100); // // partition.forEach(list -> { // staffService.UpdateStaff(list); // // // }); System.out.println("=== 测试结束 ==="); } @Test void cs113() throws Exception { // DingTalkParam dingTalkParam = new DingTalkParam(1); // DingTalkResponse<EmployeeInfo> employeeInfoDingTalkResponse = // apiService.sendListRequest(dingTalkParam, EmployeeInfo.class, // "http://192.168.1.64/eHR/eHRExternalService/Service.ashx"); // // List<EmployeeInfo> collect = employeeInfoDingTalkResponse.getData().stream() // .filter(s -> "造梦者(浙江)科技有限公司".equals(s.getCUnitName())) // .collect(Collectors.toList()); } @Test void cs3() throws Exception { // dingtalkInfoService.sendMessage("CGJY20250412166"); // XkyEntity xkyEntity = new XkyEntity(); // xkyEntity.setDeliveryNo("222505057541"); // xkyService.remove1(xkyEntity); } }