From 3aac44ea5ee6afbba7358124c8c2f38e5a6eb9ad Mon Sep 17 00:00:00 2001
From: tjx <t2856754968@163.com>
Date: 星期三, 24 十二月 2025 19:41:04 +0800
Subject: [PATCH] 11

---
 src/main/java/com/gs/dingtalk/service/WorkWXService.java |  135 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 135 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/gs/dingtalk/service/WorkWXService.java b/src/main/java/com/gs/dingtalk/service/WorkWXService.java
index 9c11791..265e68c 100644
--- a/src/main/java/com/gs/dingtalk/service/WorkWXService.java
+++ b/src/main/java/com/gs/dingtalk/service/WorkWXService.java
@@ -710,6 +710,7 @@
     }
 
     @Data
+    @com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
     public static class CheckinTime {
         @JsonProperty("work_sec")
         private Integer workSec;
@@ -824,4 +825,138 @@
         private Integer timelineId;
         private String deviceid;
     }
+
+    // ==================== 璁惧鎵撳崱鏁版嵁缁撴瀯 ====================
+
+    @Data
+    @com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
+    private static class WorkWXHardwareCheckinResponse {
+        private Integer errcode;
+        private String errmsg;
+        private List<HardwareCheckinData> checkindata;
+    }
+
+    @Data
+    @com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
+    public static class HardwareCheckinData {
+        private String userid;
+        @JsonProperty("checkin_time")
+        private Long checkinTime;
+        @JsonProperty("device_sn")
+        private String deviceSn;
+        @JsonProperty("device_name")
+        private String deviceName;
+    }
+
+    /**
+     * 鑾峰彇璁惧鎵撳崱鏁版嵁
+     * 鎺ュ彛鏂囨。: https://developer.work.weixin.qq.com/document/path/94126
+     * 1. 鑾峰彇璁板綍鏃堕棿璺ㄥ害涓嶈秴杩囦竴涓湀
+     * 2. 鐢ㄦ埛鍒楄〃涓嶈秴杩�100涓紝鑻ョ敤鎴疯秴杩�100涓紝璇峰垎鎵硅幏鍙�
+     *
+     * @param startTime  寮�濮嬫椂闂存埑锛堢锛�
+     * @param endTime    缁撴潫鏃堕棿鎴筹紙绉掞級
+     * @param useridList 鐢ㄦ埛ID鍒楄〃
+     * @return 璁惧鎵撳崱鏁版嵁鍒楄〃
+     */
+    public List<HardwareCheckinData> getHardwareCheckinData(long startTime, long endTime, List<String> useridList) throws IOException {
+        String accessToken = getAccessToken();
+        String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/hardware/get_hardware_checkin_data?access_token=%s", accessToken);
+
+        List<HardwareCheckinData> 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("filter_type", 1);  // 1琛ㄧず鎸塽serid杩囨护
+            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();
+
+                WorkWXHardwareCheckinResponse checkinResponse = objectMapper.readValue(responseBody, WorkWXHardwareCheckinResponse.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());
+                }
+            }
+
+            // 鎵规闂寸瓑寰�500ms锛岄伩鍏嶈姹傝繃浜庨绻�
+            if (i < batchCount - 1) {
+                try {
+                    Thread.sleep(500);
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                    log.warn("鎵规闂寸瓑寰呰涓柇");
+                }
+            }
+        }
+
+        log.info("璁惧鎵撳崱鏁版嵁鑾峰彇瀹屾垚锛屾�昏褰曟暟: {}", allCheckinData.size());
+        return allCheckinData;
+    }
+
+    /**
+     * 鏍规嵁QW_STAFF琛ㄨ幏鍙栬澶囨墦鍗℃暟鎹�
+     *
+     * @param startTime 寮�濮嬫椂闂存埑锛堢锛�
+     * @param endTime   缁撴潫鏃堕棿鎴筹紙绉掞級
+     * @return 璁惧鎵撳崱鏁版嵁鍒楄〃
+     */
+    public List<HardwareCheckinData> getHardwareCheckinDataByQwStaff(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 getHardwareCheckinData(startTime, endTime, useridList);
+    }
 }

--
Gitblit v1.9.3