From edb7542fe39bc6fc2c3dea9f8f8382252f3d5478 Mon Sep 17 00:00:00 2001
From: tjx <t2856754968@163.com>
Date: 星期五, 19 十二月 2025 13:38:26 +0800
Subject: [PATCH] 整合钉钉和企业微信

---
 src/test/java/com/gs/dingtalk/DeviceReceivingApplicationTests.java |  142 ++++++++++--
 src/main/java/com/gs/dingtalk/entity/QwStaff.java                  |   48 ++++
 /dev/null                                                          |   35 ---
 src/main/java/com/gs/dingtalk/service/WorkWXService.java           |  372 +++++++++++++++++++++++++++++++++
 src/main/resources/mapper/QwStaffMapper.xml                        |    7 
 src/main/java/com/gs/dingtalk/mapper/QwStaffMapper.java            |   18 +
 6 files changed, 557 insertions(+), 65 deletions(-)

diff --git a/src/main/java/com/gs/dingtalk/entity/QwStaff.java b/src/main/java/com/gs/dingtalk/entity/QwStaff.java
new file mode 100644
index 0000000..a9393e7
--- /dev/null
+++ b/src/main/java/com/gs/dingtalk/entity/QwStaff.java
@@ -0,0 +1,48 @@
+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 QW_STAFF
+ */
+@TableName(value = "QW_STAFF")
+@Data
+public class QwStaff implements Serializable {
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+    /**
+     *
+     */
+    @TableId
+    private Long id;
+    /**
+     *
+     */
+    private String name;
+    /**
+     * 浼佸井鐨剈serid
+     */
+    private String account;
+    /**
+     *
+     */
+    private String position;
+    /**
+     *
+     */
+    private String dept;
+    /**
+     *
+     */
+    private String sex;
+    /**
+     *
+     */
+    private String phone;
+}
\ No newline at end of file
diff --git a/src/main/java/com/gs/dingtalk/mapper/QwStaffMapper.java b/src/main/java/com/gs/dingtalk/mapper/QwStaffMapper.java
new file mode 100644
index 0000000..81f56b7
--- /dev/null
+++ b/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 閽堝琛ㄣ�怮W_STAFF銆戠殑鏁版嵁搴撴搷浣淢apper
+* @createDate 2025-11-26 10:51:47
+* @Entity com.gs.xky.entity.QwStaff
+*/
+public interface QwStaffMapper extends BaseMapper<QwStaff> {
+
+}
+
+
+
+
diff --git a/src/main/java/com/gs/dingtalk/service/WorkWXService.java b/src/main/java/com/gs/dingtalk/service/WorkWXService.java
new file mode 100644
index 0000000..a3c2de7
--- /dev/null
+++ b/src/main/java/com/gs/dingtalk/service/WorkWXService.java
@@ -0,0 +1,372 @@
+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澶辫触锛孒TTP鐘舵�佺爜: {}", 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("鑾峰彇浼佷笟寰俊閫氳褰昦ccess_token澶辫触锛孒TTP鐘舵�佺爜: {}", response.code());
+                throw new IOException("鑾峰彇閫氳褰昦ccess_token澶辫触: " + response.message());
+            }
+
+            String responseBody = response.body().string();
+            WorkWXTokenResponse tokenResponse = objectMapper.readValue(responseBody, WorkWXTokenResponse.class);
+
+            if (tokenResponse.getErrcode() != 0) {
+                log.error("鑾峰彇浼佷笟寰俊閫氳褰昦ccess_token澶辫触锛岄敊璇爜: {}, 閿欒淇℃伅: {}",
+                        tokenResponse.getErrcode(), tokenResponse.getErrmsg());
+                throw new IOException("鑾峰彇閫氳褰昦ccess_token澶辫触: " + tokenResponse.getErrmsg());
+            }
+
+            log.info("鎴愬姛鑾峰彇浼佷笟寰俊閫氳褰昦ccess_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("鑾峰彇浼佷笟寰俊鐢ㄦ埛鍒楄〃澶辫触锛孒TTP鐘舵�佺爜: {}", 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("瑙f瀽鐢ㄦ埛鍒楄〃鍝嶅簲澶辫触", 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琛ㄤ腑娌℃湁鏈夋晥鐨刟ccount鏁版嵁");
+            return new ArrayList<>();
+        }
+
+        log.info("浠嶲W_STAFF琛ㄨ幏鍙栧埌 {} 涓敤鎴穉ccount", 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("鑾峰彇鐢ㄦ埛璇︽儏澶辫触锛孒TTP鐘舵�佺爜: {}", 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 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("姝e湪鑾峰彇绗� {}/{} 鎵规墦鍗℃暟鎹紝鐢ㄦ埛鏁�: {}", 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("鑾峰彇鎵撳崱鏁版嵁澶辫触锛孒TTP鐘舵�佺爜: {}", 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 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;
+    }
+}
diff --git a/src/main/resources/mapper/QwStaffMapper.xml b/src/main/resources/mapper/QwStaffMapper.xml
new file mode 100644
index 0000000..043507b
--- /dev/null
+++ b/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>
diff --git a/src/test/java/com/gs/dingtalk/DeviceReceivingApplicationTests.java b/src/test/java/com/gs/dingtalk/DeviceReceivingApplicationTests.java
index 8de1248..a54334c 100644
--- a/src/test/java/com/gs/dingtalk/DeviceReceivingApplicationTests.java
+++ b/src/test/java/com/gs/dingtalk/DeviceReceivingApplicationTests.java
@@ -3,61 +3,143 @@
 import com.gs.dingtalk.config.URLEncoder;
 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;
 
     @Autowired
-    private SendDingtalkService sendDingtalkService;
+    private VwCjScSjTsBbService vwCjScSjTsBbService;
 
+    @Autowired
+    private WorkWXService workWXService;
+
+    /**
+     * 娴嬭瘯瀵煎嚭鐢熶骇鏁版嵁骞跺彂閫侀拤閽夋秷鎭�
+     * 鍔熻兘锛氭煡璇W_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);
+        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("=== 娴嬭瘯缁撴潫 ===");
     }
 
     @Test
-    void getPhone() throws Exception {
-        sendDingtalkService.getDingTalkUserId();
+    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 sendDingTalk() throws Exception {
-        sendDingtalkService.sendDingTalkFiveMinute();
+    void testGetUserDetail() {
+        System.out.println("=== 寮�濮嬫祴璇曡幏鍙栫敤鎴疯鎯� ===");
+
+        try {
+            String userid = "ShenJuanYue";
+            WorkWXService.WorkWXUserDetail userDetail = workWXService.getUserDetail(userid);
+
+            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();
+        }
+
+        System.out.println("=== 娴嬭瘯缁撴潫 ===");
     }
 
-    @Test
-    void sendDingTalkthirtyMinute() throws Exception {
-        sendDingtalkService.sendDingTalkthirtyMinute();
-    }
-
-    //chatSendMessage
-    @Test
-    void chatSendMessage() throws Exception {
-        sendDingtalkService.chatSendMessage();
-    }
 }
diff --git a/src/test/java/com/gs/dingtalk/MesQaDingtalkServiceTest.java b/src/test/java/com/gs/dingtalk/MesQaDingtalkServiceTest.java
deleted file mode 100644
index e22ac9f..0000000
--- a/src/test/java/com/gs/dingtalk/MesQaDingtalkServiceTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.gs.dingtalk;
-
-import com.gs.dingtalk.dto.QaMsgDto;
-import com.gs.dingtalk.entity.MesQaDingtalk;
-import com.gs.dingtalk.entity.QaSj;
-import com.gs.dingtalk.service.MesQaDingtalkService;
-import com.gs.dingtalk.service.QaSjService;
-import com.gs.dingtalk.service.SimpleExample;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.*;
-
-@SpringBootTest
-class MesQaDingtalkServiceTest {
-
-    @Autowired
-    private MesQaDingtalkService mesQaDingtalkService;
-
-
-    @Test
-    void testSendQaMsgSJ() throws Exception {
-        // 鍑嗗娴嬭瘯鏁版嵁
-        QaMsgDto dto = new QaMsgDto();
-        dto.setLineName("娉ㄥ3鍙锋満");
-        dto.setWorkshopName("娉ㄥ杞﹂棿");
-        dto.setQaType("棣栦欢棣栨瀹屾垚");
-
-        mesQaDingtalkService.sendQaMsgSJ(dto);
-    }
-}

--
Gitblit v1.9.3