pom.xml
@@ -102,10 +102,11 @@ <version>5.8.18</version> </dependency> <!-- Apache POI for Excel (required by Hutool) --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> <!-- ææ´é«çæ¬ --> <version>5.2.3</version> </dependency> </dependencies> src/main/java/com/gs/dingtalk/config/DataAcquisitionConfiguration.java
@@ -6,21 +6,26 @@ /** * åºç¨ç AgentId */ public static final Long AGENT_ID = 3303296035L; public static final Long AGENT_ID = 4104598880L; /** * åºç¨ç AppKey */ public static final String APP_KEY = "dingyfqkfjecy4cjfyxa"; public static final String TALK_APP_KEY = "dinggglb3pttl1x0gn0c"; /** * åºç¨ç AppSecret */ public static final String APP_SECRET = "nCwmyBw8K-EqAvkuhrhhqFonbLp455awtMa4D4Q-VRaY8U2EDEVsnYSYYfPvjiAX"; public static final String CORP_ID = "ding1dd72cd1d6adf70aa1320dcb25e91351"; public static final String TALK_APP_SECRET = "Zc7r0Mb7bPsC_xy7ryrWoEnE5OzHEXibUMPDCA2LBusJ9pYzIolRk_OdZuLvNExf"; //ç¾¤èæºå¨äººç¸å ³ 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/dingtalk/controller/DingtalkController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,62 @@ package com.gs.dingtalk.controller; import com.gs.dingtalk.config.ResultMessage; import com.gs.dingtalk.dto.NumbericalDto; import com.gs.dingtalk.service.DingtalkInfoService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * ééæ¶æ¯åéæ§å¶å¨ * * @author 28567 * @description æä¾ééæ¶æ¯åéç¸å ³çRESTæ¥å£ * @createDate 2025-01-27 */ @RestController @RequestMapping("/api/dingtalk") @RequiredArgsConstructor @Slf4j public class DingtalkController { private final DingtalkInfoService dingtalkInfoService; /** * åéééæ¶æ¯ * * @param numbericalDto å 嫿£éªåå·ç请æ±åæ° * @return ResultMessage æä½ç»æ */ @PostMapping("/sendMessage") public ResultMessage sendMessage(@RequestBody NumbericalDto numbericalDto) { try { log.info("å¼å§åéééæ¶æ¯ï¼æ£éªåå·ï¼{}", numbericalDto.getReleaseNo()); // åæ°æ ¡éª if (numbericalDto == null || numbericalDto.getReleaseNo() == null || numbericalDto.getReleaseNo().trim().isEmpty()) { log.warn("æ£éªåå·ä¸è½ä¸ºç©º"); return ResultMessage.error("æ£éªåå·ä¸è½ä¸ºç©º"); } // è°ç¨æå¡å±åéæ¶æ¯ boolean result = dingtalkInfoService.sendMessage(numbericalDto.getReleaseNo()); if (result) { log.info("ééæ¶æ¯åéæåï¼æ£éªåå·ï¼{}", numbericalDto.getReleaseNo()); return ResultMessage.ok(); } else { log.warn("ééæ¶æ¯åéå¤±è´¥ï¼æ£éªåå·ï¼{}", numbericalDto.getReleaseNo()); return ResultMessage.error("ééæ¶æ¯åé失败"); } } catch (Exception e) { log.error("åéééæ¶æ¯æ¶åçå¼å¸¸ï¼æ£éªåå·ï¼{}", numbericalDto != null ? numbericalDto.getReleaseNo() : "null", e); return ResultMessage.error(e); } } } src/main/java/com/gs/dingtalk/dto/NumbericalDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,14 @@ package com.gs.dingtalk.dto; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class NumbericalDto { private String releaseNo; } src/main/java/com/gs/dingtalk/entity/DingtalkInfo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,43 @@ package com.gs.dingtalk.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.io.Serializable; /** * @TableName DINGTALK_INFO */ @TableName(value = "DINGTALK_INFO") @Data public class DingtalkInfo implements Serializable { @TableField(exist = false) private static final long serialVersionUID = 1L; /** * SEQ_DingTalk */ @TableId private Long id; /** * èå·¥id */ private Long sid; /** * çµè¯ */ private String phone; /** * ééid */ private String dingtalkId; /** * éééç¥ */ private Integer isSendDingtalk; /** * åºå®æ¨éï¼1表示æ¯åºå®æ¨éç */ private Integer isHead; } src/main/java/com/gs/dingtalk/entity/DingtalkMsg.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,54 @@ package com.gs.dingtalk.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * @TableName DINGTALK_MSG */ @TableName(value = "DINGTALK_MSG") @Data public class DingtalkMsg implements Serializable { @TableField(exist = false) private static final long serialVersionUID = 1L; /** * æ£éªåå· */ private String releaseNo; /** * ä¾åºå */ private String suppName; /** * æ¥ææ¥æ */ private Date createDate; /** * é¡¹ç® */ private String projectCodes; /** * æå· */ private String itemNo; /** * å®¡æ ¸äººä¸æ */ private String fname; /** * å¤çæ¹å¼ */ private String fngHandle; /** * éè´äººå */ private String employeeName; /** * å®¡æ ¸äºº */ private String modify1By; } src/main/java/com/gs/dingtalk/entity/MesStaff.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,125 @@ package com.gs.dingtalk.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * å工信æ¯è¡¨ * * @TableName MES_STAFF */ @TableName(value = "MES_STAFF") @Data @KeySequence(value = "SEQ_MES_STAFF", dbType = DbType.ORACLE) public class MesStaff implements Serializable { @TableField(exist = false) private static final long serialVersionUID = 1L; /** * ID */ @TableId private Long id; /** * åå·¥ç¼ç */ private String staffNo; /** * åå·¥å§å */ private String staffName; /** * é¨é¨ç¼ç */ private String departmentNo; /** * é¨é¨åç§° */ private String departmentName; /** * å²ä½ç¼ç */ private String positionCode; /** * å²ä½åç§° */ private String positionName; /** * ææºå· */ private String phoneNumber; /** * ä»»å²å¼å§æ¥æ */ private Date startDate; /** * 夿³¨ */ private String remark; /** * å建ç»ç» */ private Long createOrg; /** * 使ç¨ç»ç» */ private String useOrg; /** * èªå®ä¹å段3 */ private String remark3; /** * èªå®ä¹å段4 */ private String remark4; /** * èªå®ä¹å段5 */ private String remark5; /** * å建人 */ private String createBy; /** * å建æ¶é´ */ private Date createDate; /** * æ´æ°äºº */ private String lastupdateBy; /** * æ´æ°æ¶é´ */ private Date lastupdateDate; /** * 夿³¨ */ private String memo; /** * ç产线 */ private String lineNo; /** * ç产åå·¥æ è¯ */ private Long workMk; /** * æ¯å¦ç¦ç¨ */ private String fforbidStatus; /** * ä¸å¡åç±»å */ private String operatorType; /** * ç¦»èæ¶é´ */ private Date separationTime; /** * æ¯å¦æ¯å ³é®å²ä½ 0ï¼å¦ï¼1ï¼æ¯ */ private String keyPosts; } src/main/java/com/gs/dingtalk/entity/QwStaff.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,47 @@ package com.gs.dingtalk.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.io.Serializable; /** * * @TableName QW_STAFF */ @TableName(value = "QW_STAFF") @Data @KeySequence(value = "SEQ_QW_STAFF", dbType = DbType.ORACLE) public class QwStaff implements Serializable { @TableField(exist = false) private static final long serialVersionUID = 1L; /** * */ @TableId private Long id; /** * */ private String name; /** * ä¼å¾®çuserid */ private String account; /** * */ private String position; /** * */ private String dept; /** * */ private String sex; /** * */ private String phone; } src/main/java/com/gs/dingtalk/entity/VwCjScSjTsBb.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,83 @@ package com.gs.dingtalk.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.io.Serializable; /** * * @TableName VW_CJ_SC_SJ_TS_BB */ @TableName(value ="VW_CJ_SC_SJ_TS_BB") @Data public class VwCjScSjTsBb implements Serializable { /** * ç©æåç§° */ private String itemName; /** * ç©æç¼ç */ private String itemNo; /** * 车é´åç§° */ private String departmentname; /** * 车é´ç¼ç */ private String daa001; /** * å·¥åå· */ private String lineName; /** * 线ä½åç§° */ private String daa008; /** * é¢è®¡å¼å·¥ */ private String yjkg; /** * å®é å¼å·¥ */ private String sjkg; /** * */ private String sq; /** * å ¥åº */ private String rk; /** * ç³è¯·æªå®å·¥æ° */ private String sqwwg; /** * å ¥åºæªå®å·¥ */ private String rkwwg; /** * ç³è¯·æªå ¥åº */ private String sqwrk; @TableField(exist = false) private static final long serialVersionUID = 1L; } src/main/java/com/gs/dingtalk/entity/VwCjScSjTsBbMonth.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,83 @@ package com.gs.dingtalk.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.io.Serializable; /** * * @TableName VW_CJ_SC_SJ_TS_BB_MONTH */ @TableName(value ="VW_CJ_SC_SJ_TS_BB_MONTH") @Data public class VwCjScSjTsBbMonth implements Serializable { /** * */ private String itemName; /** * */ private String itemNo; /** * */ private String departmentname; /** * */ private String daa001; /** * */ private String lineName; /** * */ private String daa008; /** * */ private String yjkg; /** * */ private String sjkg; /** * */ private String sq; /** * */ private String rk; /** * */ private String sqwwg; /** * */ private String rkwwg; /** * */ private String sqwrk; @TableField(exist = false) private static final long serialVersionUID = 1L; } src/main/java/com/gs/dingtalk/mapper/DingtalkInfoMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.gs.dingtalk.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.gs.dingtalk.entity.DingtalkInfo; /** * @author 28567 * @description é对表ãDINGTALK_INFOãçæ°æ®åºæä½Mapper * @createDate 2025-06-20 16:12:48 * @Entity com.gs.xky.entity.DingtalkInfo */ public interface DingtalkInfoMapper extends BaseMapper<DingtalkInfo> { } src/main/java/com/gs/dingtalk/mapper/DingtalkMsgMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.gs.dingtalk.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.gs.dingtalk.entity.DingtalkMsg; /** * @author 28567 * @description é对表ãDINGTALK_MSGãçæ°æ®åºæä½Mapper * @createDate 2025-06-21 10:07:15 * @Entity com.gs.xky.entity.DingtalkMsg */ public interface DingtalkMsgMapper extends BaseMapper<DingtalkMsg> { } src/main/java/com/gs/dingtalk/mapper/MesStaffMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,23 @@ package com.gs.dingtalk.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.gs.dingtalk.entity.MesStaff; /** * @author 28567 * @description é对表ãMES_STAFF(å工信æ¯è¡¨)ãçæ°æ®åºæä½Mapper * @createDate 2025-02-17 20:59:36 * @Entity com.gs.xky.entity.MesStaff */ public interface MesStaffMapper extends BaseMapper<MesStaff> { long getNextVal(); int updateStaff(); int deleteStaff(); } src/main/java/com/gs/dingtalk/mapper/QwStaffMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.gs.dingtalk.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.gs.dingtalk.entity.QwStaff; /** * @author Administrator * @description é对表ãQW_STAFFãçæ°æ®åºæä½Mapper * @createDate 2025-11-26 10:51:47 * @Entity com.gs.xky.entity.QwStaff */ public interface QwStaffMapper extends BaseMapper<QwStaff> { } src/main/java/com/gs/dingtalk/mapper/VwCjScSjTsBbMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.gs.dingtalk.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.gs.dingtalk.entity.VwCjScSjTsBb; /** * @author Administrator * @description é对表ãVW_CJ_SC_SJ_TS_BBãçæ°æ®åºæä½Mapper * @createDate 2025-11-12 19:44:46 * @Entity generator.domain.VwCjScSjTsBb */ public interface VwCjScSjTsBbMapper extends BaseMapper<VwCjScSjTsBb> { } src/main/java/com/gs/dingtalk/mapper/VwCjScSjTsBbMonthMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.gs.dingtalk.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.gs.dingtalk.entity.VwCjScSjTsBbMonth; /** * @author Administrator * @description é对表ãVW_CJ_SC_SJ_TS_BB_MONTHãçæ°æ®åºæä½Mapper * @createDate 2025-11-12 19:45:00 * @Entity com.gs.xky.entity.VwCjScSjTsBbMonth */ public interface VwCjScSjTsBbMonthMapper extends BaseMapper<VwCjScSjTsBbMonth> { } src/main/java/com/gs/dingtalk/service/DingtalkInfoService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,25 @@ package com.gs.dingtalk.service; import com.baomidou.mybatisplus.extension.service.IService; import com.gs.dingtalk.entity.DingtalkInfo; /** * @author 28567 * @description é对表ãDINGTALK_INFOãçæ°æ®åºæä½Service * @createDate 2025-06-20 16:12:48 */ 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/dingtalk/service/SimpleExample.java
@@ -61,7 +61,7 @@ try { Long timestamp = System.currentTimeMillis(); System.out.println(timestamp); String secret = DataAcquisitionConfiguration.SECRET; String secret = DataAcquisitionConfiguration.TALK_APP_SECRET; String stringToSign = timestamp + "\n" + secret; Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256")); @@ -164,8 +164,8 @@ public String getAccessToken() throws Exception { Client client = createClient(); GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest() .setAppKey(DataAcquisitionConfiguration.APP_KEY) .setAppSecret(DataAcquisitionConfiguration.APP_SECRET); .setAppKey(DataAcquisitionConfiguration.TALK_APP_KEY) .setAppSecret(DataAcquisitionConfiguration.TALK_APP_SECRET); try { GetAccessTokenResponse accessToken = client.getAccessToken(getAccessTokenRequest); return accessToken.body.getAccessToken(); @@ -208,7 +208,7 @@ } public OapiV2UserGetbymobileResponse getOapiV2UserGetbymobileResponse(SendDingtalk s, String accessToken) { public OapiV2UserGetbymobileResponse getOapiV2UserGetbymobileResponse(SendDingtalk s, String accessToken) { DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile"); OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest(); req.setMobile(s.getTelephone()); src/main/java/com/gs/dingtalk/service/VwCjScSjTsBbMonthService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,13 @@ package com.gs.dingtalk.service; import com.baomidou.mybatisplus.extension.service.IService; import com.gs.dingtalk.entity.VwCjScSjTsBbMonth; /** * @author Administrator * @description é对表ãVW_CJ_SC_SJ_TS_BB_MONTHãçæ°æ®åºæä½Service * @createDate 2025-11-12 19:45:00 */ public interface VwCjScSjTsBbMonthService extends IService<VwCjScSjTsBbMonth> { } src/main/java/com/gs/dingtalk/service/VwCjScSjTsBbService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,19 @@ package com.gs.dingtalk.service; import com.baomidou.mybatisplus.extension.service.IService; import com.gs.dingtalk.entity.VwCjScSjTsBb; /** * @author Administrator * @description é对表ãVW_CJ_SC_SJ_TS_BBãçæ°æ®åºæä½Service * @createDate 2025-11-12 19:44:46 */ public interface VwCjScSjTsBbService extends IService<VwCjScSjTsBb> { /** * å¯¼åºæ°æ®å°Excelå¹¶åéééæ¶æ¯ * * @return æ¯å¦æå */ boolean exportAndSendToDingtalk() throws Exception; } src/main/java/com/gs/dingtalk/service/WorkWXService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,403 @@ package com.gs.dingtalk.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; import com.gs.dingtalk.config.DataAcquisitionConfiguration; import com.gs.dingtalk.entity.QwStaff; import com.gs.dingtalk.mapper.QwStaffMapper; import lombok.Data; import lombok.RequiredArgsConstructor; import okhttp3.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class WorkWXService { private static final Logger log = LoggerFactory.getLogger(WorkWXService.class); private final OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(90, TimeUnit.SECONDS) .readTimeout(90, TimeUnit.SECONDS) .build(); private final ObjectMapper objectMapper = new ObjectMapper(); private final QwStaffMapper qwStaffMapper; public String getAccessToken() throws IOException { String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s", DataAcquisitionConfiguration.CORPID, DataAcquisitionConfiguration.CORPSECRET); Request request = new Request.Builder() .url(url) .get() .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { log.error("è·åä¼ä¸å¾®ä¿¡access_token失败ï¼HTTPç¶æç : {}", response.code()); throw new IOException("è·åaccess_token失败: " + response.message()); } String responseBody = response.body().string(); WorkWXTokenResponse tokenResponse = objectMapper.readValue(responseBody, WorkWXTokenResponse.class); if (tokenResponse.getErrcode() != 0) { log.error("è·åä¼ä¸å¾®ä¿¡access_token失败ï¼é误ç : {}, é误信æ¯: {}", tokenResponse.getErrcode(), tokenResponse.getErrmsg()); throw new IOException("è·åaccess_token失败: " + tokenResponse.getErrmsg()); } log.info("æåè·åä¼ä¸å¾®ä¿¡access_tokenï¼æææ: {}ç§", tokenResponse.getExpiresIn()); log.info("access_token : {}", tokenResponse.getAccessToken()); return tokenResponse.getAccessToken(); } } public String getContactAccessToken() throws IOException { String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s", DataAcquisitionConfiguration.CORPID, DataAcquisitionConfiguration.TXL_CORPSECRET); Request request = new Request.Builder() .url(url) .get() .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { log.error("è·åä¼ä¸å¾®ä¿¡é讯å½access_token失败ï¼HTTPç¶æç : {}", response.code()); throw new IOException("è·åé讯å½access_token失败: " + response.message()); } String responseBody = response.body().string(); WorkWXTokenResponse tokenResponse = objectMapper.readValue(responseBody, WorkWXTokenResponse.class); if (tokenResponse.getErrcode() != 0) { log.error("è·åä¼ä¸å¾®ä¿¡é讯å½access_token失败ï¼é误ç : {}, é误信æ¯: {}", tokenResponse.getErrcode(), tokenResponse.getErrmsg()); throw new IOException("è·åé讯å½access_token失败: " + tokenResponse.getErrmsg()); } log.info("æåè·åä¼ä¸å¾®ä¿¡é讯å½access_tokenï¼æææ: {}ç§", tokenResponse.getExpiresIn()); return tokenResponse.getAccessToken(); } } public List<WorkWXUser> getUserList() throws IOException { String accessToken = getContactAccessToken(); String url = String.format( "https://qyapi.weixin.qq.com/cgi-bin/user/list_id?access_token=%s", accessToken); List<WorkWXUser> allUsers = new ArrayList<>(); String cursor = null; do { Map<String, Object> requestBody = new HashMap<>(); requestBody.put("limit", 10000); if (cursor != null) { requestBody.put("cursor", cursor); } MediaType mediaType = MediaType.parse("application/json; charset=UTF-8"); String jsonBody = objectMapper.writeValueAsString(requestBody); RequestBody body = RequestBody.create(mediaType, jsonBody); Request request = new Request.Builder() .url(url) .post(body) .addHeader("Content-Type", "application/json; charset=UTF-8") .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { log.error("è·åä¼ä¸å¾®ä¿¡ç¨æ·å表失败ï¼HTTPç¶æç : {}", response.code()); throw new IOException("è·åç¨æ·å表失败: " + response.message()); } String responseBody = response.body().string(); log.info("è·åç¨æ·å表ååº: {}", responseBody); WorkWXUserListIdResponse userListResponse = objectMapper.readValue(responseBody, WorkWXUserListIdResponse.class); if (userListResponse.getErrcode() != 0) { log.error("è·åä¼ä¸å¾®ä¿¡ç¨æ·å表失败ï¼é误ç : {}, é误信æ¯: {}", userListResponse.getErrcode(), userListResponse.getErrmsg()); throw new IOException("è·åç¨æ·å表失败: " + userListResponse.getErrmsg()); } if (userListResponse.getDeptUser() != null && !userListResponse.getDeptUser().isEmpty()) { allUsers.addAll(userListResponse.getDeptUser()); } cursor = userListResponse.getNextCursor(); } catch (IOException e) { log.error("è§£æç¨æ·å表ååºå¤±è´¥", e); throw e; } } while (cursor != null && !cursor.isEmpty()); log.info("æåè·åä¼ä¸å¾®ä¿¡ç¨æ·å表ï¼ç¨æ·æ°é: {}", allUsers.size()); return allUsers; } public List<CheckinData> getCheckinDataByQwStaff(long startTime, long endTime) throws IOException { List<QwStaff> qwStaffList = qwStaffMapper.selectList(new LambdaQueryWrapper<QwStaff>()); if (qwStaffList == null || qwStaffList.isEmpty()) { log.warn("QW_STAFFè¡¨ä¸æ²¡ææ°æ®"); return new ArrayList<>(); } List<String> useridList = qwStaffList.stream() .map(QwStaff::getAccount) .filter(account -> account != null && !account.isEmpty()) .collect(Collectors.toList()); if (useridList.isEmpty()) { log.warn("QW_STAFFè¡¨ä¸æ²¡æææçaccountæ°æ®"); return new ArrayList<>(); } log.info("ä»QW_STAFF表è·åå° {} ä¸ªç¨æ·account", useridList.size()); return getCheckinData(startTime, endTime, useridList); } public WorkWXUserDetail getUserDetail(String userid) throws IOException { String accessToken = getContactAccessToken(); String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=%s&userid=%s", accessToken, userid); Request request = new Request.Builder() .url(url) .get() .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { log.error("è·åç¨æ·è¯¦æ 失败ï¼HTTPç¶æç : {}", response.code()); throw new IOException("è·åç¨æ·è¯¦æ 失败: " + response.message()); } String responseBody = response.body().string(); log.info("è·åç¨æ·è¯¦æ ååº: {}", responseBody); WorkWXUserDetailResponse userDetailResponse = objectMapper.readValue(responseBody, WorkWXUserDetailResponse.class); if (userDetailResponse.getErrcode() != 0) { log.error("è·åç¨æ·è¯¦æ 失败ï¼é误ç : {}, é误信æ¯: {}", userDetailResponse.getErrcode(), userDetailResponse.getErrmsg()); throw new IOException("è·åç¨æ·è¯¦æ 失败: " + userDetailResponse.getErrmsg()); } log.info("æåè·åç¨æ· {} ç详æ ", userid); return userDetailResponse; } } public int syncUsersToQwStaff() throws IOException { List<WorkWXUser> userList = getUserList(); if (userList == null || userList.isEmpty()) { log.warn("è·åå°çç¨æ·å表为空"); return 0; } int insertCount = 0; for (WorkWXUser user : userList) { if (user.getUserid() == null || user.getUserid().isEmpty()) { continue; } qwStaffMapper.delete( new LambdaQueryWrapper<QwStaff>().eq(QwStaff::getAccount, user.getUserid()) ); QwStaff qwStaff = new QwStaff(); qwStaff.setName(user.getName()); qwStaff.setAccount(user.getUserid()); qwStaff.setDept(user.getDepartment() != null ? user.getDepartment().toString() : null); qwStaffMapper.insert(qwStaff); insertCount++; } log.info("åæ¥ç¨æ·å°QW_STAFFè¡¨å®æï¼åæ¥ç¨æ·æ°: {}", insertCount); return insertCount; } public List<CheckinData> getCheckinData(long startTime, long endTime, List<String> useridList) throws IOException { String accessToken = getAccessToken(); String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckindata?access_token=%s", accessToken); List<CheckinData> allCheckinData = new ArrayList<>(); int batchSize = 100; int totalUsers = useridList.size(); int batchCount = (totalUsers + batchSize - 1) / batchSize; log.info("å¼å§è·åæå¡æ°æ®ï¼æ»ç¨æ·æ°: {}, åæ¹æ°: {}, æ¶é´èå´: {} - {}", totalUsers, batchCount, startTime, endTime); for (int i = 0; i < batchCount; i++) { int fromIndex = i * batchSize; int toIndex = Math.min((i + 1) * batchSize, totalUsers); List<String> batchUserList = useridList.subList(fromIndex, toIndex); log.info("æ£å¨è·å第 {}/{} æ¹æå¡æ°æ®ï¼ç¨æ·æ°: {}", i + 1, batchCount, batchUserList.size()); Map<String, Object> requestBody = new HashMap<>(); requestBody.put("opencheckindatatype", 3); requestBody.put("starttime", startTime); requestBody.put("endtime", endTime); requestBody.put("useridlist", batchUserList); MediaType mediaType = MediaType.parse("application/json; charset=UTF-8"); String jsonBody = objectMapper.writeValueAsString(requestBody); RequestBody body = RequestBody.create(mediaType, jsonBody); Request request = new Request.Builder() .url(url) .post(body) .addHeader("Content-Type", "application/json; charset=UTF-8") .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { log.error("è·åæå¡æ°æ®å¤±è´¥ï¼HTTPç¶æç : {}", response.code()); throw new IOException("è·åæå¡æ°æ®å¤±è´¥: " + response.message()); } String responseBody = response.body().string(); WorkWXCheckinResponse checkinResponse = objectMapper.readValue(responseBody, WorkWXCheckinResponse.class); if (checkinResponse.getErrcode() != 0) { log.error("è·åæå¡æ°æ®å¤±è´¥ï¼é误ç : {}, é误信æ¯: {}", checkinResponse.getErrcode(), checkinResponse.getErrmsg()); throw new IOException("è·åæå¡æ°æ®å¤±è´¥: " + checkinResponse.getErrmsg()); } if (checkinResponse.getCheckindata() != null) { allCheckinData.addAll(checkinResponse.getCheckindata()); log.info("第 {}/{} æ¹è·åå°æå¡è®°å½æ°: {}", i + 1, batchCount, checkinResponse.getCheckindata().size()); } } if (i < batchCount - 1) { try { Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); log.warn("æ¹æ¬¡é´çå¾ è¢«ä¸æ"); } } } log.info("æå¡æ°æ®è·åå®æï¼æ»è®°å½æ°: {}", allCheckinData.size()); return allCheckinData; } @Data private static class WorkWXTokenResponse { private Integer errcode; private String errmsg; @JsonProperty("access_token") private String accessToken; @JsonProperty("expires_in") private Integer expiresIn; } @Data private static class WorkWXUserIdResponse { private Integer errcode; private String errmsg; private String userid; } @Data private static class WorkWXUserListIdResponse { private Integer errcode; private String errmsg; @JsonProperty("next_cursor") private String nextCursor; @JsonProperty("dept_user") private List<WorkWXUser> deptUser; } @Data public static class WorkWXUser { private String userid; private Integer department; private String name; @JsonProperty("open_userid") private String openUserid; } @Data public static class WorkWXUserDetail { private Integer errcode; private String errmsg; private String userid; private String name; private String mobile; private String position; } @Data private static class WorkWXUserDetailResponse extends WorkWXUserDetail { } @Data private static class WorkWXCheckinResponse { private Integer errcode; private String errmsg; private List<CheckinData> checkindata; } @Data public static class CheckinData { private String userid; private String groupname; @JsonProperty("checkin_type") private String checkinType; @JsonProperty("exception_type") private String exceptionType; @JsonProperty("checkin_time") private Long checkinTime; @JsonProperty("location_title") private String locationTitle; @JsonProperty("location_detail") private String locationDetail; private String wifiname; private String notes; private String wifimac; private List<String> mediaids; private Double lat; private Double lng; @JsonProperty("sch_checkin_time") private Long schCheckinTime; private Integer groupid; @JsonProperty("schedule_id") private Integer scheduleId; @JsonProperty("timeline_id") private Integer timelineId; private String deviceid; } } src/main/java/com/gs/dingtalk/service/impl/DingtalkInfoServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,552 @@ package com.gs.dingtalk.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.dingtalk.entity.DingtalkInfo; import com.gs.dingtalk.entity.DingtalkMsg; import com.gs.dingtalk.entity.MesStaff; import com.gs.dingtalk.mapper.DingtalkInfoMapper; import com.gs.dingtalk.mapper.DingtalkMsgMapper; import com.gs.dingtalk.mapper.MesStaffMapper; import com.gs.dingtalk.service.DingtalkInfoService; import com.gs.dingtalk.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; import java.util.Optional; 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<DingtalkInfoMapper, DingtalkInfo> implements DingtalkInfoService { private final SimpleExample simpleExample; private final DingtalkMsgMapper dingtalkMsgMapper; private final MesStaffMapper mesStaffMapper; @Override public boolean sendMessage(String releaseNo) { try { // æ¥è¯¢ééæ¶æ¯å 容 LambdaQueryWrapper<DingtalkMsg> 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()); String message = String.format( "ä¾åºå[%s] æ¥ææ¥æ[%s] 项ç®[%s] æå·[%s]çä¸åæ ¼æ£éªå被[%s]审æ¹ä¸º[%s]ï¼è¯·æ¥æ¶!", Optional.ofNullable(dingtalkMsg.getSuppName()).orElse(" æªç¥ä¾åºå"), createDateStr, Optional.ofNullable(dingtalkMsg.getProjectCodes()).orElse(" æªç¥é¡¹ç®"), Optional.ofNullable(dingtalkMsg.getItemNo()).orElse(" æªç¥æå·"), Optional.ofNullable(dingtalkMsg.getFname()).orElse(" æªç¥å®¡æ¹äºº"), Optional.ofNullable(dingtalkMsg.getFngHandle()).orElse(" æªç¥å®¡æ¹ç»æ")); // æ¶ééè¦æ¨éç人åsid List<Long> sidList = new ArrayList<>(); // 1. åºå®æ¨é人åï¼isSendDingtalk=1ï¼ List<DingtalkInfo> fixedList = baseMapper.selectList( new LambdaQueryWrapper<DingtalkInfo>().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<MesStaff>().eq(MesStaff::getStaffName, dingtalkMsg.getEmployeeName()), false ); if (buyer != null) { DingtalkInfo buyerInfo = baseMapper.selectOne( new LambdaQueryWrapper<DingtalkInfo>().eq(DingtalkInfo::getSid, buyer.getId()), false ); if (buyerInfo != null) sidList.add(buyerInfo.getSid()); } } // 3. å®¡æ ¸äººï¼modify1Byï¼ if (StringUtils.hasText(dingtalkMsg.getModify1By())) { MesStaff auditor = mesStaffMapper.selectOne( new LambdaQueryWrapper<MesStaff>().eq(MesStaff::getStaffNo, dingtalkMsg.getModify1By()) ); if (auditor != null) { DingtalkInfo auditorInfo = baseMapper.selectOne( new LambdaQueryWrapper<DingtalkInfo>().eq(DingtalkInfo::getSid, auditor.getId()) ); if (auditorInfo != null) sidList.add(auditorInfo.getSid()); } } // 4. æ ¹æ®æ¶éçsidè·ådingtalkId (å¤ç¨getDingtalkUserIdListçå ³é®é»è¾) List<String> 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; } } @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å表 * * @param sidList sidå表 * @return ééç¨æ·IDå表 */ private List<String> getDingtalkUserIdListBySids(List<Long> sidList) { try { if (sidList == null || sidList.isEmpty()) { return new ArrayList<>(); } // å»é sidList = sidList.stream().distinct().collect(Collectors.toList()); // æ ¹æ®sidæ¥è¯¢DingtalkInfo List<DingtalkInfo> list = baseMapper.selectList( new LambdaQueryWrapper<DingtalkInfo>().in(DingtalkInfo::getSid, sidList) ); 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 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.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); } /** * åé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); } /** * è·åisSendDingtalk=1çç¨æ·çééç¨æ·IDå表ï¼ä¿çåææ¹æ³ï¼ååå ¼å®¹ï¼ */ private List<String> getDingtalkUserIdList() { try { LambdaQueryWrapper<DingtalkInfo> wrapper = new LambdaQueryWrapper<>(); wrapper.ge(DingtalkInfo::getIsSendDingtalk, 1); List<DingtalkInfo> list = list(wrapper); 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<>(); } } } src/main/java/com/gs/dingtalk/service/impl/VwCjScSjTsBbMonthServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,22 @@ package com.gs.dingtalk.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.gs.dingtalk.entity.VwCjScSjTsBbMonth; import com.gs.dingtalk.mapper.VwCjScSjTsBbMonthMapper; import com.gs.dingtalk.service.VwCjScSjTsBbMonthService; import org.springframework.stereotype.Service; /** * @author Administrator * @description é对表ãVW_CJ_SC_SJ_TS_BB_MONTHãçæ°æ®åºæä½Serviceå®ç° * @createDate 2025-11-12 19:45:00 */ @Service public class VwCjScSjTsBbMonthServiceImpl extends ServiceImpl<VwCjScSjTsBbMonthMapper, VwCjScSjTsBbMonth> implements VwCjScSjTsBbMonthService { } src/main/java/com/gs/dingtalk/service/impl/VwCjScSjTsBbServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,193 @@ package com.gs.dingtalk.service.impl; import cn.hutool.core.io.FileUtil; import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.ExcelWriter; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.gs.dingtalk.entity.VwCjScSjTsBb; import com.gs.dingtalk.entity.VwCjScSjTsBbMonth; import com.gs.dingtalk.mapper.VwCjScSjTsBbMapper; import com.gs.dingtalk.service.DingtalkInfoService; import com.gs.dingtalk.service.VwCjScSjTsBbMonthService; import com.gs.dingtalk.service.VwCjScSjTsBbService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.List; /** * @author Administrator * @description é对表ãVW_CJ_SC_SJ_TS_BBãçæ°æ®åºæä½Serviceå®ç° * @createDate 2025-11-12 16:42:06 */ @Service @Slf4j @RequiredArgsConstructor public class VwCjScSjTsBbServiceImpl extends ServiceImpl<VwCjScSjTsBbMapper, VwCjScSjTsBb> implements VwCjScSjTsBbService { private final DingtalkInfoService dingtalkInfoService; private final VwCjScSjTsBbMonthService vwCjScSjTsBbMonthService; @Override public boolean exportAndSendToDingtalk() throws Exception { String exportFilePath = null; try { // 2. åå¤å¯¼åºæä»¶è·¯å¾ String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); String fileName = "çäº§æ°æ®æ¥è¡¨_" + timestamp + ".xlsx"; exportFilePath = "D:\\BIFile\\" + fileName; // ç¡®ä¿ç®å½åå¨ FileUtil.mkdir("D:\\BIFile"); // 3. 导åºå°Excel log.info("å¼å§å¯¼åºExcelæä»¶: {}", exportFilePath); exportToExcel(exportFilePath); log.info("Excelæä»¶å¯¼åºæå"); // 4. åéééæ¶æ¯ log.info("å¼å§åéééæä»¶æ¶æ¯..."); boolean sendResult = dingtalkInfoService.sendFileMessage(exportFilePath); if (sendResult) { log.info("ééæä»¶æ¶æ¯åéæå"); } else { log.warn("ééæä»¶æ¶æ¯åé失败"); } return sendResult; } catch (Exception e) { log.error("导åºå¹¶åé失败", e); throw e; } finally { // å¯éï¼åéåå é¤ä¸´æ¶æä»¶ // if (exportFilePath != null && FileUtil.exist(exportFilePath)) { // FileUtil.del(exportFilePath); // log.info("ä¸´æ¶æä»¶å·²å é¤: {}", exportFilePath); // } } } /** * å¯¼åºæ°æ®å°Excelï¼ä¸¤ä¸ªsheeté¡µï¼ * * @param filePath æä»¶è·¯å¾ */ private void exportToExcel(String filePath) { // è®¡ç®æ¨å¤©çæ¥æ LocalDate yesterday = LocalDate.now().minusDays(1); String yesterdayStr = yesterday.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); // è®¡ç®æ¬æçèµ·æ¢æ¥æ LocalDate today = LocalDate.now(); LocalDate firstDayOfMonth = today.withDayOfMonth(1); LocalDate lastDayOfMonth = today.withDayOfMonth(today.lengthOfMonth()); String firstDayStr = firstDayOfMonth.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); String lastDayStr = lastDayOfMonth.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); log.info("æ¨å¤©æ¥æ: {}", yesterdayStr); log.info("æ¬æèå´: {} è³ {}", firstDayStr, lastDayStr); // è¿æ»¤æ°æ®ï¼é¢è®¡å¼å·¥å¨æ¨å¤©çæ°æ® List<VwCjScSjTsBb> yesterdayData = list(); // è¿æ»¤æ°æ®ï¼é¢è®¡å¼å·¥å¨æ¬æçæ°æ® List<VwCjScSjTsBbMonth> thisMonthData = vwCjScSjTsBbMonthService.list(); log.info("æ¨å¤©æ°æ®: {} æ¡", yesterdayData.size()); log.info("æ¬ææ°æ®: {} æ¡", thisMonthData.size()); // å建Excelåå ¥å¨ï¼ç¬¬ä¸ä¸ªsheetï¼ ExcelWriter writer = ExcelUtil.getWriter(filePath, "æ¨å¤©å ¥åºå·¥åç³è¯·"); // åå ¥ç¬¬ä¸ä¸ªsheetï¼æ¨å¤©é¢è®¡å¼å·¥çæ°æ® writeSheetData(writer, "æ¨å¤©å ¥åºå·¥åç³è¯·æ°æ®ï¼" + yesterdayStr + "ï¼", yesterdayData); // å建第äºä¸ªsheet writer.setSheet("æ¬æå ¥åºå·¥åç³è¯·"); // åå ¥ç¬¬äºä¸ªsheetï¼æ¬æé¢è®¡å¼å·¥çæ°æ® writeSheetData(writer, thisMonthData, "æ¬æå ¥åºå·¥åç³è¯·æ°æ®ï¼" + firstDayStr + " è³ " + lastDayStr + "ï¼"); // å ³éwriterï¼éæ¾å å writer.close(); } /** * åå ¥å个sheetçæ°æ® * * @param writer Excelåå ¥å¨ * @param dataList æ°æ®å表 * @param title æ é¢ */ private void writeSheetData(ExcelWriter writer, String title, List<VwCjScSjTsBb> dataList) { // æ¸ ç©ºä¹åçå«å设置 writer.clearHeaderAlias(); // 设置表头å«åï¼ä¸æååï¼ writer.addHeaderAlias("departmentname", "车é´"); writer.addHeaderAlias("lineName", "线ä½åç§°"); writer.addHeaderAlias("itemNo", "产åç¼ç "); writer.addHeaderAlias("itemName", "产ååç§°"); writer.addHeaderAlias("daa001", "å·¥åå·"); writer.addHeaderAlias("daa008", "工忰"); writer.addHeaderAlias("sq", "ç³è¯·æ°"); writer.addHeaderAlias("rk", "å ¥åºæ°"); writer.addHeaderAlias("sqwwg", "ç³è¯·æªå®å·¥æ°"); writer.addHeaderAlias("rkwwg", "å ¥åºæªå®å·¥"); writer.addHeaderAlias("sqwrk", "ç³è¯·æªå ¥åº"); writer.addHeaderAlias("yjkg", "é¢è®¡å¼å·¥"); writer.addHeaderAlias("sjkg", "å®é å¼å·¥"); // åå¹¶åå æ ¼ä½ä¸ºæ é¢è¡ writer.merge(14, title); // åå ¥æ°æ®ï¼é»è®¤ä¼ä½¿ç¨å«åä½ä¸ºè¡¨å¤´ writer.write(dataList, true); // 设置å宽èªéåº writer.autoSizeColumnAll(); } private void writeSheetData(ExcelWriter writer, List<VwCjScSjTsBbMonth> dataList, String title) { // æ¸ ç©ºä¹åçå«å设置 writer.clearHeaderAlias(); // 设置表头å«åï¼ä¸æååï¼ writer.addHeaderAlias("departmentname", "车é´"); writer.addHeaderAlias("lineName", "线ä½åç§°"); writer.addHeaderAlias("itemNo", "产åç¼ç "); writer.addHeaderAlias("itemName", "产ååç§°"); writer.addHeaderAlias("daa001", "å·¥åå·"); writer.addHeaderAlias("daa008", "工忰"); writer.addHeaderAlias("sq", "ç³è¯·æ°"); writer.addHeaderAlias("rk", "å ¥åºæ°"); writer.addHeaderAlias("sqwwg", "ç³è¯·æªå®å·¥æ°"); writer.addHeaderAlias("rkwwg", "å ¥åºæªå®å·¥"); writer.addHeaderAlias("sqwrk", "ç³è¯·æªå ¥åº"); writer.addHeaderAlias("yjkg", "é¢è®¡å¼å·¥"); writer.addHeaderAlias("sjkg", "å®é å¼å·¥"); // åå¹¶åå æ ¼ä½ä¸ºæ é¢è¡ writer.merge(14, title); // åå ¥æ°æ®ï¼é»è®¤ä¼ä½¿ç¨å«åä½ä¸ºè¡¨å¤´ writer.write(dataList, true); // 设置å宽èªéåº writer.autoSizeColumnAll(); } } src/main/java/com/gs/dingtalk/task/ScheduledTasks.java
@@ -2,54 +2,90 @@ import com.gs.dingtalk.service.SendDingtalkService; import com.gs.dingtalk.service.VwCjScSjTsBbService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.concurrent.atomic.AtomicBoolean; @Component @RequiredArgsConstructor @Slf4j public class ScheduledTasks { private final SendDingtalkService sendDingtalkService; // private final SendDingtalkService sendDingtalkService; private final VwCjScSjTsBbService vwCjScSjTsBbService; private final AtomicBoolean exportTaskRunning = new AtomicBoolean(false); // /** // * æ¯ä¸¤åéæ§è¡ä¸æ¬¡ // * è·åè®¾å¤æè¿ç䏿¡è®°å½ // * // * @return void // * @author tjx // * @description TODO // * @date 2024/9/27 21:48 // */ // @Scheduled(cron = "0 0/2 * * * ?") // public void getDeviceRealTimeData() { // try { // sendDingtalkService.sendDingTalkFiveMinute(); // log.info("宿¶ä»»å¡ getDeviceRealTimeData æ§è¡æå"); // } catch (Exception e) { // log.error("宿¶ä»»å¡ getDeviceRealTimeData æ§è¡å¤±è´¥: ", e); // } // } // // @Scheduled(cron = "0 0/3 * * * ?") // public void sendDingTalkFifteenMinute() { // try { // sendDingtalkService.sendDingTalkFifteenMinute(); // log.info("宿¶ä»»å¡ sendDingTalkFifteenMinute æ§è¡æå"); // } catch (Exception e) { // log.error("宿¶ä»»å¡ sendDingTalkFifteenMinute æ§è¡å¤±è´¥: ", e); // } // } // // @Scheduled(cron = "0 0/4 * * * ?") // public void sendDingTalkThirtyMinute() { // try { // sendDingtalkService.sendDingTalkthirtyMinute(); // log.info("宿¶ä»»å¡ sendDingTalkThirtyMinute æ§è¡æå"); // } catch (Exception e) { // log.error("宿¶ä»»å¡ sendDingTalkThirtyMinute æ§è¡å¤±è´¥: ", e); // } // } /** * æ¯ä¸¤åéæ§è¡ä¸æ¬¡ * è·åè®¾å¤æè¿ç䏿¡è®°å½ * * @return void * @author tjx * @description TODO * @date 2024/9/27 21:48 * æ¯å¤©ä¸å9ç¹æ§è¡ * 导åºçäº§æ°æ®å¹¶åéééæ¶æ¯ */ @Scheduled(cron = "0 0/2 * * * ?") public void getDeviceRealTimeData() { try { sendDingtalkService.sendDingTalkFiveMinute(); log.info("宿¶ä»»å¡ getDeviceRealTimeData æ§è¡æå"); } catch (Exception e) { log.error("宿¶ä»»å¡ getDeviceRealTimeData æ§è¡å¤±è´¥: ", e); @Async("taskExecutor") @Scheduled(cron = "0 0 12,16 * * ?") public void exportAndSendProductionDataTask() { if (!exportTaskRunning.compareAndSet(false, true)) { log.warn("çäº§æ°æ®å¯¼åºä»»å¡æ£å¨æ§è¡ä¸ï¼è·³è¿æ¬æ¬¡æ§è¡"); return; } } @Scheduled(cron = "0 0/3 * * * ?") public void sendDingTalkFifteenMinute() { try { sendDingtalkService.sendDingTalkFifteenMinute(); log.info("宿¶ä»»å¡ sendDingTalkFifteenMinute æ§è¡æå"); } catch (Exception e) { log.error("宿¶ä»»å¡ sendDingTalkFifteenMinute æ§è¡å¤±è´¥: ", e); } } log.info("å¼å§æ§è¡çäº§æ°æ®å¯¼åºå¹¶åéééä»»å¡"); boolean result = vwCjScSjTsBbService.exportAndSendToDingtalk(); @Scheduled(cron = "0 0/4 * * * ?") public void sendDingTalkThirtyMinute() { try { sendDingtalkService.sendDingTalkthirtyMinute(); log.info("宿¶ä»»å¡ sendDingTalkThirtyMinute æ§è¡æå"); if (result) { log.info("çäº§æ°æ®å¯¼åºå¹¶åééé任塿§è¡æå"); } else { log.error("çäº§æ°æ®å¯¼åºå¹¶åééé任塿§è¡å¤±è´¥"); } } catch (Exception e) { log.error("宿¶ä»»å¡ sendDingTalkThirtyMinute æ§è¡å¤±è´¥: ", e); log.error("çäº§æ°æ®å¯¼åºå¹¶åééé任塿§è¡å¼å¸¸", e); } finally { exportTaskRunning.set(false); } } } 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.0.100:1521/orcl username: yc_dev password: ycdev url: jdbc:oracle:thin:@192.168.1.22:1521/orcl username: hm_prd password: hmprd druid: initialSize: 5 minIdle: 5 src/main/resources/mapper/DingtalkInfoMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,7 @@ <?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.gs.dingtalk.mapper.DingtalkInfoMapper"> </mapper> src/main/resources/mapper/DingtalkMsgMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,8 @@ <?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.gs.dingtalk.mapper.DingtalkMsgMapper"> </mapper> src/main/resources/mapper/MesStaffMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,22 @@ <?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.gs.dingtalk.mapper.MesStaffMapper"> <update id="updateStaff"> update SYS_USER a set SID = (select ID from MES_STAFF where STAFF_NO = a.FCODE and STAFF_NAME = a.FNAME) where 1 = 1 </update> <delete id="deleteStaff"> delete from MES_STAFF where 1 = 1 </delete> <select id="getNextVal" resultType="java.lang.Long"> select SEQ_MES_STAFF.NextVal from dual </select> </mapper> src/main/resources/mapper/QwStaffMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,7 @@ <?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.gs.dingtalk.mapper.QwStaffMapper"> </mapper> src/main/resources/mapper/VwCjScSjTsBbMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,8 @@ <?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.gs.dingtalk.mapper.VwCjScSjTsBbMapper"> </mapper> src/main/resources/mapper/VwCjScSjTsBbMonthMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,7 @@ <?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.gs.dingtalk.mapper.VwCjScSjTsBbMonthMapper"> </mapper> src/test/java/com/gs/dingtalk/DeviceReceivingApplicationTests.java
@@ -1,63 +1,230 @@ package com.gs.dingtalk; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.gs.dingtalk.config.URLEncoder; import com.gs.dingtalk.entity.QwStaff; import com.gs.dingtalk.mapper.QwStaffMapper; import com.gs.dingtalk.service.SendDingtalkService; import com.gs.dingtalk.service.SimpleExample; import com.gs.dingtalk.service.VwCjScSjTsBbService; import com.gs.dingtalk.service.WorkWXService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.List; @SpringBootTest class DeviceReceivingApplicationTests { @Autowired private SimpleExample simpleExample; private VwCjScSjTsBbService vwCjScSjTsBbService; @Autowired private SendDingtalkService sendDingtalkService; private WorkWXService workWXService; @Autowired private QwStaffMapper qwStaffMapper; /** * æµè¯å¯¼åºçäº§æ°æ®å¹¶åéééæ¶æ¯ * åè½ï¼æ¥è¯¢VW_CJ_SC_SJ_TS_BBè¡¨æ°æ® -> 导åºExcel -> åéééæä»¶æ¶æ¯ */ @Test void contextLoads() { //FFFFFFFE long decimal = Long.parseLong("FFFFFFFE", 16); // å°16è¿å¶å符串转æ¢ä¸ºlongç±»åç10è¿å¶æ° BigDecimal a = new BigDecimal(String.valueOf((int) decimal)); BigDecimal b = new BigDecimal("1000"); BigDecimal c = a.divide(b, 3, RoundingMode.HALF_UP); System.out.println(c); void testExportAndSendProductionData() throws Exception { System.out.println("=== å¼å§æµè¯å¯¼åºçäº§æ°æ®å¹¶åééé ==="); try { boolean result = vwCjScSjTsBbService.exportAndSendToDingtalk(); 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(); } System.out.println("=== æµè¯ç»æ ==="); } @Test void cont() { // long resultCode = Long.parseLong("00000001"); // int result = (int) resultCode; // System.out.println(result); void testGetCheckinDataByQwStaff() { System.out.println("=== å¼å§æµè¯éè¿QW_STAFF表è·åæå¡æ°æ® ==="); String encode = URLEncoder.encode(""); System.out.println(encode); // ä¼ä¸å¾®ä¿¡æå¡æ¥å£éå¶ï¼ // 1. è·åè®°å½æ¶é´è·¨åº¦ä¸è¶ è¿30天 // 2. ç¨æ·å表ä¸è¶ è¿100个ãè¥ç¨æ·è¶ è¿100个ï¼è¯·åæ¹è·åï¼å·²å¨Serviceå±å®ç°èªå¨åæ¹ï¼ // 3. æ¥å£è¿åæå¤3000æ¡æå¡æ°æ® // 4. æ åæå¡æ¶é´åªå¯¹äºåºå®æçåèªå®ä¹æç两ç§ç±»åææ // 5. æ¥å£è°ç¨é¢çéå¶ä¸º600次/åéï¼å·²å¨Serviceå±å®ç°æ¹æ¬¡é´å»¶è¿ï¼ try { long currentTime = System.currentTimeMillis() / 1000; long oneDaySeconds = 86400; long thirtyDaysSeconds = 30 * oneDaySeconds; long endTime = (currentTime / oneDaySeconds) * oneDaySeconds - 1; long startTime = endTime - oneDaySeconds + 1; // éªè¯æ¶é´è·¨åº¦ä¸è¶ è¿30天 long timeSpan = endTime - startTime; if (timeSpan > thirtyDaysSeconds) { System.out.println("â æ¶é´è·¨åº¦è¶ è¿30天éå¶: " + (timeSpan / oneDaySeconds) + "天"); return; } System.out.println(" - å¼å§æ¶é´: " + new java.util.Date(startTime * 1000)); System.out.println(" - ç»ææ¶é´: " + new java.util.Date(endTime * 1000)); System.out.println(" - æ¶é´è·¨åº¦: " + (timeSpan / oneDaySeconds) + "天 (éå¶: â¤30天)"); // è·åç¨æ·æ»æ° long totalUsers = qwStaffMapper.selectCount(new LambdaQueryWrapper<QwStaff>() .isNotNull(QwStaff::getAccount) .ne(QwStaff::getAccount, "")); System.out.println(" - QW_STAFFè¡¨ç¨æ·æ»æ°: " + totalUsers); if (totalUsers > 100) { int batchCount = (int) ((totalUsers + 99) / 100); System.out.println(" - å°èªå¨åæ¹å¤ç: " + batchCount + "æ¹ (æ¯æ¹â¤100ç¨æ·)"); } 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("=== æµè¯ç»æ ==="); } @Test void getPhone() throws Exception { sendDingtalkService.getDingTalkUserId(); void testGetCheckinDataById() { System.out.println("=== å¼å§æµè¯éè¿QW_STAFF表è·åæå¡æ°æ® ==="); QwStaff qwStaff = qwStaffMapper.selectById(3); if (qwStaff == null || qwStaff.getAccount() == null || qwStaff.getAccount().isEmpty()) { System.out.println("â æªæ¾å°ID为3çåå·¥æåå·¥account为空"); return; } System.out.println(" - åå·¥å§å: " + qwStaff.getName()); System.out.println(" - å工账å·: " + qwStaff.getAccount()); try { long currentTime = System.currentTimeMillis() / 1000; long oneDaySeconds = 86400; long thirtyDaysSeconds = 30 * oneDaySeconds; // æ¨å¤©ç»ææ¶é´ï¼23:59:59ï¼ long yesterdayEnd = ((currentTime / oneDaySeconds) - 1) * oneDaySeconds + oneDaySeconds - 1; // 20天åå¼å§æ¶é´ï¼00:00:00ï¼ long twentyDaysAgoStart = yesterdayEnd - 20 * oneDaySeconds + 1; long endTime = yesterdayEnd; long startTime = twentyDaysAgoStart; // éªè¯æ¶é´è·¨åº¦ä¸è¶ è¿30天 long timeSpan = endTime - startTime; if (timeSpan > thirtyDaysSeconds) { System.out.println("â æ¶é´è·¨åº¦è¶ è¿30天éå¶: " + (timeSpan / oneDaySeconds) + "天"); return; } System.out.println(" - å¼å§æ¶é´: " + new java.util.Date(startTime * 1000) + " (20天å)"); System.out.println(" - ç»ææ¶é´: " + new java.util.Date(endTime * 1000) + " (æ¨å¤©)"); System.out.println(" - æ¶é´è·¨åº¦: " + (timeSpan / oneDaySeconds) + "天"); List<String> useridList = new java.util.ArrayList<>(); useridList.add(qwStaff.getAccount()); List<WorkWXService.CheckinData> checkinDataList = workWXService.getCheckinData(startTime, endTime, useridList); if (checkinDataList != null && !checkinDataList.isEmpty()) { System.out.println("â æåè·åæå¡æ°æ®"); System.out.println(" - æå¡è®°å½æ»æ°: " + checkinDataList.size()); checkinDataList.forEach(data -> { System.out.println(" * æå¡æ¶é´: " + new java.util.Date(data.getCheckinTime() * 1000) + ", æå¡ç±»å: " + data.getCheckinType() + ", å¼å¸¸ç±»å: " + data.getExceptionType() + ", å°ç¹: " + data.getLocationDetail()); }); } else { System.out.println("â 该å工卿¶é´èå´å æ æå¡è®°å½"); } } catch (IOException e) { System.out.println("â è·åæå¡æ°æ®å¤±è´¥: " + e.getMessage()); e.printStackTrace(); } System.out.println("=== æµè¯ç»æ ==="); } @Test void sendDingTalk() throws Exception { sendDingtalkService.sendDingTalkFiveMinute(); void testGetWorkWXUserList() { System.out.println("=== å¼å§æµè¯è·åä¼ä¸å¾®ä¿¡ç¨æ·å表 ==="); try { List<WorkWXService.WorkWXUser> userList = workWXService.getUserList(); 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("â è·åçç¨æ·å表为空"); } } catch (IOException e) { System.out.println("â è·åç¨æ·å表失败: " + e.getMessage()); e.printStackTrace(); } System.out.println("=== æµè¯ç»æ ==="); } @Test void sendDingTalkthirtyMinute() throws Exception { sendDingtalkService.sendDingTalkthirtyMinute(); void testSyncUsersToQwStaff() { System.out.println("=== å¼å§æµè¯åæ¥ä¼ä¸å¾®ä¿¡ç¨æ·å°QW_STAFF表 ==="); try { int insertCount = workWXService.syncUsersToQwStaff(); System.out.println("â 忥宿"); System.out.println(" - æ°å¢ç¨æ·æ°: " + insertCount); } catch (IOException e) { System.out.println("â åæ¥ç¨æ·å¤±è´¥: " + e.getMessage()); e.printStackTrace(); } System.out.println("=== æµè¯ç»æ ==="); } //chatSendMessage @Test void chatSendMessage() throws Exception { sendDingtalkService.chatSendMessage(); } } src/test/java/com/gs/dingtalk/MesQaDingtalkServiceTest.java
ÎļþÒÑɾ³ý