From 8ac573030c8fc795d9a30afb739f44393f8b63eb Mon Sep 17 00:00:00 2001 From: cuilei <ray_tsu1@163.com> Date: 星期一, 18 八月 2025 18:03:07 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- src/main/java/org/jeecg/modules/feishu/service/FeishuUserService.java | 635 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 635 insertions(+), 0 deletions(-) diff --git a/src/main/java/org/jeecg/modules/feishu/service/FeishuUserService.java b/src/main/java/org/jeecg/modules/feishu/service/FeishuUserService.java new file mode 100644 index 0000000..92d6b09 --- /dev/null +++ b/src/main/java/org/jeecg/modules/feishu/service/FeishuUserService.java @@ -0,0 +1,635 @@ +package org.jeecg.modules.feishu.service; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.util.PasswordUtil; +import org.jeecg.common.util.RestUtil; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.andon.dto.AndonButtonDTO; +import org.jeecg.modules.mes.entity.FeishuUser; +import org.jeecg.modules.system.entity.SysUser; +import org.jeecg.modules.system.service.ISysUserService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@Service +@Slf4j +public class FeishuUserService { + // 绫讳腑瀹氫箟妯℃澘甯搁噺锛堜究浜庣淮鎶わ級 + private static final String FIRST_LEVEL_TEMPLATE = "銆愬伐鑹哄畨鐏�慭n%s 路 %s 鍙戣捣浜嗗伐鑹哄畨鐏紝璇�%d鍒嗛挓鍐呭湪PDA涓婅繘琛屽搷搴斿鐞嗭紒锛侊紒"; + private static final String SECOND_LEVEL_TEMPLATE = "銆愬伐鑹哄畨鐏�慭n%s 路 %s 鍙戣捣鐨勫伐鑹哄畨鐏紝%s鏈湪%d鍒嗛挓鍐呭搷搴旓紝璇峰敖蹇潱淇冭繘琛屽搷搴斿鐞嗭紒锛侊紒"; + @Resource + private ISysUserService sysUserService; + + @Resource + private RestTemplate restTemplate; + + @Value("${feishu.appId:}") + private String appId; + + @Value("${feishu.appSecret:}") + private String appSecret; + + @Value("${feishu.url:}") + private String feishuUrl; + + // 瀹氭椂浠诲姟绾跨▼姹狅紙鏀寔澶氱骇鍝嶅簲璋冨害锛� + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5); + private final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); + + /** + * 鍚屾椋炰功閮ㄩ棬鐢ㄦ埛鍒扮郴缁熺敤鎴疯〃 + */ + public void syncFeishuDepartmentUsers(String departmentId) { + try { + log.info("寮�濮嬪悓姝ラ涔﹂儴闂ㄧ敤鎴凤紝閮ㄩ棬ID: {}", departmentId); + + // 1. 鑾峰彇椋炰功璁块棶浠ょ墝 + String accessToken = getFeishuAccessToken(); + if (oConvertUtils.isEmpty(accessToken)) { + log.error("鑾峰彇椋炰功璁块棶浠ょ墝澶辫触锛岀粓姝㈠悓姝ユ祦绋�"); + return; + } + + // 2. 鑾峰彇閮ㄩ棬涓嬬殑鐢ㄦ埛鍒楄〃 + List<FeishuUser> feishuUsers = getDepartmentUsers(accessToken, departmentId); + log.info("鑾峰彇鍒伴涔﹂儴闂ㄧ敤鎴锋暟閲�: {}", feishuUsers.size()); + + // 3. 鍚屾鍒扮郴缁熺敤鎴疯〃 + int successCount = 0; + int updateCount = 0; + int addCount = 0; + + for (FeishuUser feishuUser : feishuUsers) { + try { + boolean isUpdated = syncFeishuUserToSystem(feishuUser); + successCount++; + if (isUpdated) { + updateCount++; + } else { + addCount++; + } + } catch (Exception e) { + log.error("鍚屾椋炰功鐢ㄦ埛澶辫触锛岀敤鎴稩D: {}", feishuUser.getUserId(), e); + } + } + + log.info("椋炰功鐢ㄦ埛鍚屾瀹屾垚锛屾�诲鐞�: {}锛屾柊澧�: {}锛屾洿鏂�: {}", successCount, addCount, updateCount); + } catch (Exception e) { + log.error("鍚屾椋炰功閮ㄩ棬鐢ㄦ埛澶辫触锛岄儴闂↖D: {}", departmentId, e); + throw new RuntimeException("鍚屾椋炰功鐢ㄦ埛澶辫触: " + e.getMessage()); + } + } + + public String getFeishuAccessToken() { + try { + String url = feishuUrl + "open-apis/auth/v3/tenant_access_token/internal"; + + log.info("寮�濮嬭幏鍙栭涔﹁闂护鐗岋紝AppId: {}", + appId != null ? appId.substring(0, Math.min(appId.length(), 10)) + "..." : "null"); + + JSONObject params = new JSONObject(); + params.put("app_id", appId); + params.put("app_secret", appSecret); + + log.debug("鑾峰彇浠ょ墝璇锋眰鍙傛暟: {}", params.toJSONString()); + + JSONObject result = RestUtil.post(url, params); + + log.info("鑾峰彇椋炰功璁块棶浠ょ墝鍝嶅簲: {}", result != null ? result.toJSONString() : "null"); + + if (result != null && result.getInteger("code") == 0) { + String accessToken = result.getString("tenant_access_token"); + log.info("鎴愬姛鑾峰彇椋炰功璁块棶浠ょ墝锛屼护鐗岄暱搴�: {}", accessToken != null ? accessToken.length() : 0); + return accessToken; + } else { + log.error("鑾峰彇椋炰功璁块棶浠ょ墝澶辫触锛屽搷搴�: {}", result != null ? result.toJSONString() : "null"); + if (result != null) { + log.error("閿欒鐮�: {}, 閿欒淇℃伅: {}", result.getInteger("code"), result.getString("msg")); + } + return null; + } + } catch (Exception e) { + log.error("鑾峰彇椋炰功璁块棶浠ょ墝寮傚父", e); + return null; + } + } + + /** + * 鍙戦�佸畨鐏�氱煡娑堟伅锛堟敮鎸佷竴銆佷簩銆佷笁绾у搷搴旓級 + * 娴佺▼锛� + * 1. APP鐐瑰嚮鍙戦�佷竴绾у搷搴旓紙鍒濈骇鍝嶅簲锛� + * 2. 涓�绾у搷搴旀椂闀垮悗妫�鏌ョ姸鎬侊紝鏈鐞嗗垯鍙戦�佷簩绾� + * 3. 浜岀骇鍝嶅簲鏃堕暱鍚庢鏌ョ姸鎬侊紝鏈鐞嗗垯鍙戦�佷笁绾� + */ + public boolean sendAndonNotification(String accessToken, AndonButtonDTO andonOrde) { + try { + String currentTime = sdf.format(new Date()); + log.info("銆恵}銆戣Е鍙戜竴绾у搷搴旓紙鍒濈骇鍝嶅簲锛夛紝瀹夌伅ID: {}", currentTime, andonOrde.getId()); + + // 1. 鍙傛暟楠岃瘉 + if (!validateNotificationParams(andonOrde)) { + return false; + } + if (accessToken == null || accessToken.isEmpty()) { + log.error("璁块棶浠ょ墝涓虹┖锛屾棤娉曞彂閫佸畨鐏�氱煡"); + return false; + } + + // 2. 鍙戦�佷竴绾у搷搴旈�氱煡锛堝嵆鏃跺彂閫侊級 + boolean firstLevelResult = sendLevelNotification(accessToken, andonOrde, 1); + + // 3. 璋冨害浜岀骇鍝嶅簲閫氱煡锛堝欢杩熸椂闂�=涓�绾у搷搴旀椂闀匡級 + if (firstLevelResult) { + int secondDelay = andonOrde.getUpgradeResponseDuration(); + String secondTime = sdf.format(new Date(System.currentTimeMillis() + secondDelay * 60 * 1000L)); + log.info("銆恵}銆戜竴绾у搷搴旇皟搴︿簩绾ч�氱煡锛屽欢杩焮}鍒嗛挓锛岄璁″彂閫佹椂闂�: {}", + currentTime, secondDelay, secondTime); + scheduleNextLevelNotification(accessToken, andonOrde, 1, secondDelay); + } else { + log.warn("涓�绾ч�氱煡鍙戦�佸け璐ワ紝缁堟鍚庣画閫氱煡娴佺▼锛屽畨鐏疘D: {}", andonOrde.getId()); + } + + return firstLevelResult; + } catch (Exception e) { + log.error("澶勭悊瀹夌伅閫氱煡寮傚父锛屽畨鐏疘D: {}", andonOrde != null ? andonOrde.getId() : "鏈煡", e); + return false; + } + } + + /** + * 鍙戦�佹寚瀹氱骇鍒殑閫氱煡 + * @param level 1-涓�绾э紝2-浜岀骇锛�3-涓夌骇 + */ + private boolean sendLevelNotification(String accessToken, AndonButtonDTO andonOrde, int level) { + try { + String levelDesc = getLevelDesc(level); + String openId = getResponderOpenId(andonOrde, level); + String currentTime = sdf.format(new Date()); + log.info("銆恵}銆戝紑濮嬪彂閫亄}绾у畨鐏�氱煡锛屾帴鏀朵汉openId: {}, 瀹夌伅ID: {}", + currentTime, levelDesc, openId, andonOrde.getId()); + + // 鏋勫缓璇锋眰URL + String url = feishuUrl + "open-apis/im/v1/messages?receive_id_type=open_id"; + log.info("{}绾ч�氱煡璇锋眰URL: {}", levelDesc, url); + + // 璁剧疆璇锋眰澶� + HttpHeaders headers = new HttpHeaders(); + String authHeader = "Bearer " + accessToken; + headers.add("Authorization", authHeader); + headers.add("Content-Type", "application/json; charset=utf-8"); + log.info("璁剧疆{}绾ч�氱煡璇锋眰澶�: Authorization = {}", levelDesc, + authHeader.substring(0, Math.min(30, authHeader.length())) + "..."); + + // 鏋勫缓娑堟伅鍐呭 + JSONObject content = new JSONObject(); + String notificationContent = buildNotificationContent(andonOrde, level); + content.put("text", notificationContent); + log.debug("銆恵}銆憑}绾ч�氱煡鍐呭: {}", currentTime, levelDesc, notificationContent); + + // 鏋勫缓璇锋眰浣� + JSONObject requestBody = new JSONObject(); + requestBody.put("receive_id", openId); + requestBody.put("msg_type", "text"); + requestBody.put("content", content.toJSONString()); + requestBody.put("uuid", "andon_" + andonOrde.getId() + "_level_" + level + "_" + System.currentTimeMillis()); + + // 鍙戦�佽姹� + HttpEntity<String> requestEntity = new HttpEntity<>(requestBody.toJSONString(), headers); + ResponseEntity<String> response = restTemplate.exchange( + url, HttpMethod.POST, requestEntity, String.class + ); + + // 瑙f瀽鍝嶅簲 + JSONObject result = JSONObject.parseObject(response.getBody()); + log.debug("{}绾ч�氱煡API鍝嶅簲: {}", levelDesc, result != null ? result.toJSONString() : "null"); + + if (result != null && result.getInteger("code") == 0) { + JSONObject data = result.getJSONObject("data"); + if (data != null) { + log.info("銆恵}銆憑}绾у畨鐏�氱煡鍙戦�佹垚鍔燂紝娑堟伅ID: {}, 瀹夌伅ID: {}", + currentTime, levelDesc, data.getString("message_id"), andonOrde.getId()); + return true; + } else { + log.warn("{}绾ч�氱煡鍝嶅簲data涓虹┖锛屽畨鐏疘D: {}", levelDesc, andonOrde.getId()); + return false; + } + } else { + log.error("鍙戦�亄}绾у畨鐏�氱煡澶辫触锛屽畨鐏疘D: {}", levelDesc, andonOrde.getId()); + if (result != null) { + log.error("閿欒鐮�: {}, 閿欒淇℃伅: {}", result.getInteger("code"), result.getString("msg")); + } + return false; + } + + } catch (Exception e) { + log.error("鍙戦�亄}绾у畨鐏�氱煡寮傚父锛屽畨鐏疘D: {}", getLevelDesc(level), andonOrde.getId(), e); + return false; + } + } + + /** + * 璋冨害涓嬩竴绾ч�氱煡锛�1鈫�2鈫�3锛� + * @param currentLevel 褰撳墠绾у埆 + * @param delayMinutes 寤惰繜鍒嗛挓鏁帮紙鐢卞綋鍓嶇骇鍒搷搴旀椂闀垮喅瀹氾級 + */ + private void scheduleNextLevelNotification(String accessToken, AndonButtonDTO andonOrde, int currentLevel, int delayMinutes) { + int nextLevel = currentLevel + 1; + if (nextLevel > 3) { + log.info("宸插埌杈炬渶楂樼骇鍒�氱煡锛屾棤闇�缁х画璋冨害锛屽畨鐏疘D: {}", andonOrde.getId()); + return; + } + + String currentLevelDesc = getLevelDesc(currentLevel); + String nextLevelDesc = getLevelDesc(nextLevel); + String scheduleTime = sdf.format(new Date()); + String executeTime = sdf.format(new Date(System.currentTimeMillis() + delayMinutes * 60 * 1000L)); + + log.info("銆恵}銆戣皟搴}閫氱煡锛屽欢杩焮}鍒嗛挓锛堝綋鍓嶇骇鍒珄}鏃堕暱锛夛紝棰勮鎵ц鏃堕棿: {}", + scheduleTime, nextLevelDesc, delayMinutes, currentLevelDesc, executeTime); + + scheduler.schedule(() -> { + try { + String currentExecuteTime = sdf.format(new Date()); + log.info("銆恵}銆戝紑濮嬫墽琛寋}閫氱煡妫�鏌ワ紝瀹夌伅ID: {}", currentExecuteTime, nextLevelDesc, andonOrde.getId()); + + // 妫�鏌ヨ鍗曠姸鎬侊細3琛ㄧず宸插搷搴旓紝鏃犻渶鍙戦�佷笅涓�绾� + if (andonOrde.getOrderStatus() != null && "3".equals(andonOrde.getOrderStatus())) { + log.info("銆恵}銆戣鍗曞凡鍝嶅簲锛坰tatus=3锛夛紝鍙栨秷{}閫氱煡鍙戦�侊紝瀹夌伅ID: {}", + currentExecuteTime, nextLevelDesc, andonOrde.getId()); + return; + } + + // 妫�鏌ヤ笅涓�绾у搷搴斾汉鏄惁鏈夋晥 + if (!hasValidResponder(andonOrde, nextLevel)) { + log.warn("銆恵}銆憑}鍝嶅簲浜轰俊鎭棤鏁堬紝鍙栨秷閫氱煡鍙戦�侊紝瀹夌伅ID: {}", + currentExecuteTime, nextLevelDesc, andonOrde.getId()); + return; + } + + // 鍙戦�佷笅涓�绾ч�氱煡 + boolean nextLevelResult = sendLevelNotification(accessToken, andonOrde, nextLevel); + if (nextLevelResult && nextLevel < 3) { + + int nextDelay = getResponseDuration(andonOrde, nextLevel); + String nextExecuteTime = sdf.format(new Date(System.currentTimeMillis() + nextDelay * 60 * 1000L)); + log.info("銆恵}銆憑}閫氱煡璋冨害涓夌骇閫氱煡锛屽欢杩焮}鍒嗛挓锛岄璁″彂閫佹椂闂�: {}", + currentExecuteTime, nextLevelDesc, nextDelay, nextExecuteTime); + scheduleNextLevelNotification(accessToken, andonOrde, nextLevel, nextDelay); + } else if (!nextLevelResult) { + log.warn("銆恵}銆憑}閫氱煡鍙戦�佸け璐ワ紝缁堟鍚庣画璋冨害锛屽畨鐏疘D: {}", + currentExecuteTime, nextLevelDesc, andonOrde.getId()); + } + + } catch (Exception e) { + log.error("鎵ц{}璋冨害浠诲姟寮傚父锛屽畨鐏疘D: {}", nextLevelDesc, andonOrde.getId(), e); + } + }, delayMinutes, TimeUnit.MINUTES); + } + /** + * 鏋勫缓閫氱煡鍐呭锛堜紭鍖栧垎闅旂锛屾彁鍗囧彲璇绘�э級 + */ + private String buildNotificationContent(AndonButtonDTO andonOrde, int level) { + // 鑾峰彇宸ュ巶鍚嶇О鍜屼骇绾垮悕绉帮紝鍋氱┖鍊间繚鎶� + String parentFactoryName = andonOrde.getParentFactoryName() != null ? andonOrde.getParentFactoryName() : "鏈煡宸ュ巶"; + String factoryName = andonOrde.getFactoryName() != null ? andonOrde.getFactoryName() : "鏈煡浜х嚎"; + String content; + + if (level == 1) { + // 涓�绾фā鏉匡細浣跨敤"路"鍒嗛殧宸ュ巶鍜屼骇绾� + int firstDuration = andonOrde.getUpgradeResponseDuration() != null ? andonOrde.getUpgradeResponseDuration() : 0; + content = String.format(FIRST_LEVEL_TEMPLATE, parentFactoryName, factoryName, firstDuration); + } else { + // 浜岀骇妯℃澘锛氫繚鎸佷竴鑷寸殑鍒嗛殧椋庢牸 + String prevResponder = getResponderName(andonOrde, level - 1); + int prevDuration = getResponseDuration(andonOrde, level - 1); + + prevResponder = oConvertUtils.isEmpty(prevResponder) ? "鏈煡浜哄憳" : prevResponder; + prevDuration = Math.max(prevDuration, 0); + + content = String.format(SECOND_LEVEL_TEMPLATE, parentFactoryName, factoryName, prevResponder, prevDuration); + } + + log.debug("鏋勫缓{}绾ч�氱煡鍐呭: {}", level, content); + return content; + } +// /** +// * 鏋勫缓閫氱煡鍐呭锛堟寜绾у埆浣跨敤涓嶅悓妯℃澘锛� +// */ +// private String buildNotificationContent(AndonButtonDTO andonOrde, int level) { +// String factoryName = andonOrde.getFactoryName() != null ? andonOrde.getFactoryName() : "鏈煡浜х嚎"; +// +// if (level == 1) { +// // 涓�绾фā鏉匡細銆愬伐鑹哄畨鐏�慩XX浜х嚎鍙戣捣浜嗗伐鑹哄畨鐏紝璇穢x鍒嗛挓鍐呭湪PDA涓婅繘琛屽搷搴斿鐞嗭紒锛侊紒 +// return String.format("銆愬伐鑹哄畨鐏�慭n%s浜х嚎鍙戣捣浜嗗伐鑹哄畨鐏紝璇�%d鍒嗛挓鍐呭湪PDA涓婅繘琛屽搷搴斿鐞嗭紒锛侊紒", +// factoryName, +// andonOrde.getUpgradeResponseDuration()); +// } else { +// // 浜�/涓夌骇妯℃澘锛氥�愬伐鑹哄畨鐏�慩XX锛堜骇绾匡級鍙戣捣鐨勫伐鑹哄畨鐏紝xxx锛堜笂涓�绾у搷搴斾汉锛夋湭鍦▁x鍒嗛挓鍐呭搷搴旓紝璇峰敖蹇潱淇冭繘琛屽搷搴斿鐞嗭紒锛侊紒 +// String prevLevelDesc = getLevelDesc(level - 1); +// String prevResponder = getResponderName(andonOrde, level - 1); +// int prevDuration = getResponseDuration(andonOrde, level - 1); +// +// return String.format("銆愬伐鑹哄畨鐏�慭n%s锛堜骇绾匡級鍙戣捣鐨勫伐鑹哄畨鐏紝%s锛�%s鍝嶅簲浜猴級鏈湪%d鍒嗛挓鍐呭搷搴旓紝璇峰敖蹇潱淇冭繘琛屽搷搴斿鐞嗭紒锛侊紒", +// factoryName, +// prevResponder, +// prevLevelDesc, +// prevDuration); +// } +// } + + /** + * 楠岃瘉閫氱煡鐩稿叧鍙傛暟 + */ + private boolean validateNotificationParams(AndonButtonDTO andonOrde) { + if (andonOrde == null) { + log.error("瀹夌伅璁㈠崟淇℃伅涓虹┖"); + return false; + } + if (andonOrde.getId() == null) { + log.error("瀹夌伅ID涓虹┖"); + return false; + } + // 涓�绾у搷搴旀牎楠岋紙蹇呴�夛級 + if (andonOrde.getResponderOpenId() == null || andonOrde.getResponderOpenId().isEmpty() + || andonOrde.getUpgradeResponseDuration() == null || andonOrde.getUpgradeResponseDuration() <= 0) { + log.error("涓�绾у搷搴斾汉淇℃伅鏃犳晥锛坥penId鎴栨椂闀跨己澶憋級锛屽畨鐏疘D: {}", andonOrde.getId()); + return false; + } + // 浜岀骇鍝嶅簲鏍¢獙锛堣嫢瀛樺湪鍒欏繀閫夊畬鏁达級 + if (andonOrde.getSecondResponderOpenId() != null && !andonOrde.getSecondResponderOpenId().isEmpty()) { + if (andonOrde.getSecondUpgradeResponseDuration() == null || andonOrde.getSecondUpgradeResponseDuration() <= 0) { + log.error("浜岀骇鍝嶅簲浜哄瓨鍦ㄤ絾鏃堕暱鏃犳晥锛屽畨鐏疘D: {}", andonOrde.getId()); + return false; + } + } + // 涓夌骇鍝嶅簲鏍¢獙锛堣嫢瀛樺湪鍒欏繀閫夊畬鏁达級 + if (andonOrde.getThirdResponderOpenId() != null && !andonOrde.getThirdResponderOpenId().isEmpty()) { + if (andonOrde.getSecondUpgradeResponseDuration() == null || andonOrde.getSecondUpgradeResponseDuration() <= 0) { + log.error("涓夌骇鍝嶅簲浜哄瓨鍦ㄤ絾浜岀骇鏃堕暱鏃犳晥锛堜笁绾т緷璧栦簩绾ф椂闀匡級锛屽畨鐏疘D: {}", andonOrde.getId()); + return false; + } + } + return true; + } + + // 宸ュ叿鏂规硶锛氳幏鍙栫骇鍒弿杩� + private String getLevelDesc(int level) { + switch (level) { + case 1: return "涓�绾�"; + case 2: return "浜岀骇"; + case 3: return "涓夌骇"; + default: return "鏈煡绾у埆"; + } + } + + // 宸ュ叿鏂规硶锛氳幏鍙栧搷搴斾汉openId + private String getResponderOpenId(AndonButtonDTO andonOrde, int level) { + switch (level) { + case 1: return andonOrde.getResponderOpenId(); + case 2: return andonOrde.getSecondResponderOpenId(); + case 3: return andonOrde.getThirdResponderOpenId(); + default: return null; + } + } + + // 宸ュ叿鏂规硶锛氳幏鍙栧搷搴斾汉鍚嶇О + private String getResponderName(AndonButtonDTO andonOrde, int level) { + String name = null; + switch (level) { + case 1: + name = andonOrde.getResponder(); + break; + case 2: + name = andonOrde.getSecondResponder(); + break; + case 3: + name = andonOrde.getThirdResponder(); + break; + default: + name = null; + } + return name != null ? name : "鏈煡鍝嶅簲浜�"; + } + + // 宸ュ叿鏂规硶锛氳幏鍙栧搷搴旀椂闀匡紙涓�绾�=浜岀骇寤惰繜锛屼簩绾�=涓夌骇寤惰繜锛� + private int getResponseDuration(AndonButtonDTO andonOrde, int level) { + int duration = 0; + switch (level) { + case 1: + duration = andonOrde.getUpgradeResponseDuration() != null ? andonOrde.getUpgradeResponseDuration() : 0; + break; + case 2: + duration = andonOrde.getSecondUpgradeResponseDuration() != null ? andonOrde.getSecondUpgradeResponseDuration() : 0; + break; + case 3: + duration = 0; // 涓夌骇鏄渶鍚庝竴绾э紝鏃犻渶寤惰繜 + break; + default: + duration = 0; + } + return duration; + } + + // 宸ュ叿鏂规硶锛氬垽鏂寚瀹氱骇鍒搷搴斾汉鏄惁鏈夋晥 + private boolean hasValidResponder(AndonButtonDTO andonOrde, int level) { + String openId = getResponderOpenId(andonOrde, level); + return openId != null && !openId.isEmpty(); + } + + /** + * 鑾峰彇閮ㄩ棬鐢ㄦ埛鍒楄〃锛堢洿灞炲憳宸ワ級 + */ + private List<FeishuUser> getDepartmentUsers(String accessToken, String departmentId) { + List<FeishuUser> userList = new ArrayList<>(); + try { + log.info("寮�濮嬭幏鍙栭涔﹂儴闂ㄧ敤鎴峰垪琛紝閮ㄩ棬ID: {}", departmentId); + + if (accessToken == null || accessToken.isEmpty()) { + log.error("璁块棶浠ょ墝涓虹┖锛屾棤娉曠户缁墽琛�"); + return userList; + } + log.info("浣跨敤鐨勮闂护鐗屽墠缂�: Bearer {}", accessToken.substring(0, Math.min(20, accessToken.length())) + "..."); + + String url = feishuUrl + "open-apis/contact/v3/users/find_by_department"; + String pageToken = null; + int pageNumber = 1; + + do { + StringBuilder urlBuilder = new StringBuilder(url); + urlBuilder.append("?department_id=").append(departmentId); + urlBuilder.append("&department_id_type=open_department_id"); + urlBuilder.append("&page_size=50"); + urlBuilder.append("&user_id_type=open_id"); + + if (pageToken != null && !pageToken.isEmpty()) { + urlBuilder.append("&page_token=").append(pageToken); + } + + log.info("璇锋眰绗瑊}椤垫暟鎹紝URL: {}", pageNumber, urlBuilder.toString()); + + HttpHeaders headers = new HttpHeaders(); + String authHeader = "Bearer " + accessToken; + headers.add("Authorization", authHeader); + headers.add("Content-Type", "application/json; charset=utf-8"); + log.info("璁剧疆璇锋眰澶�: Authorization = {}", authHeader.substring(0, Math.min(30, authHeader.length())) + "..."); + + HttpEntity<String> requestEntity = new HttpEntity<>(headers); + ResponseEntity<String> response = restTemplate.exchange( + urlBuilder.toString(), HttpMethod.GET, requestEntity, String.class + ); + + JSONObject result = JSONObject.parseObject(response.getBody()); + log.debug("绗瑊}椤礎PI鍝嶅簲: {}", pageNumber, result != null ? result.toJSONString() : "null"); + + if (result != null && result.getInteger("code") == 0) { + JSONObject data = result.getJSONObject("data"); + if (data != null) { + Object items = data.get("items"); + log.info("绗瑊}椤靛師濮嬬敤鎴锋暟鎹暟閲�: {}", pageNumber, items instanceof List ? ((List<?>) items).size() : 0); + + if (items != null) { + List<FeishuUser> pageUsers = parseUsers(items); + userList.addAll(pageUsers); + log.info("绗瑊}椤佃В鏋愬悗鐢ㄦ埛鏁伴噺: {}", pageNumber, pageUsers.size()); + } + + pageToken = data.getString("page_token"); + boolean hasMore = data.getBooleanValue("has_more"); + log.info("绗瑊}椤礹as_more: {}, page_token: {}", pageNumber, hasMore, pageToken); + pageNumber++; + } else { + log.warn("绗瑊}椤礵ata涓虹┖", pageNumber); + break; + } + } else { + log.error("鑾峰彇椋炰功閮ㄩ棬鐢ㄦ埛鍒楄〃澶辫触锛屽搷搴�: {}", result != null ? result.toJSONString() : "null"); + if (result != null) { + log.error("閿欒鐮�: {}, 閿欒淇℃伅: {}", result.getInteger("code"), result.getString("msg")); + } + break; + } + } while (pageToken != null && !pageToken.isEmpty()); + + log.info("鑾峰彇椋炰功閮ㄩ棬鐢ㄦ埛瀹屾垚锛屾�荤敤鎴锋暟閲�: {}", userList.size()); + + } catch (Exception e) { + log.error("鑾峰彇椋炰功閮ㄩ棬鐢ㄦ埛鍒楄〃寮傚父", e); + } + return userList; + } + + /** + * 瑙f瀽鐢ㄦ埛鏁版嵁 + */ + @SuppressWarnings("unchecked") + private List<FeishuUser> parseUsers(Object items) { + Logger log = LoggerFactory.getLogger(FeishuUserService.class); + List<FeishuUser> userList = new ArrayList<>(); + if (!(items instanceof List)) { + log.warn("瑙f瀽鐢ㄦ埛鏁版嵁澶辫触锛宨tems涓嶆槸鍒楄〃绫诲瀷: {}", items); + return userList; + } + List<?> userItems = (List<?>) items; + log.info("寮�濮嬭В鏋愰涔︾敤鎴峰垪琛紝鍏眥}鏉¤褰�", userItems.size()); + for (Object item : userItems) { + if (item == null || !(item instanceof Map)) { + log.warn("璺宠繃鏃犳晥鐢ㄦ埛鏁版嵁椤癸紝绫诲瀷涓嶅尮閰�: {}", item != null ? item.getClass() : "null"); + continue; + } + Map<String, Object> userMap = (Map<String, Object>) item; + FeishuUser user = new FeishuUser(); + user.setOpenId((String) userMap.getOrDefault("open_id", "")); + + String name = (String) userMap.getOrDefault("name", ""); + if (name.contains(" ")) { + String[] parts = name.split(" "); + if (parts.length == 2) { + user.setUsername(parts[0].trim()); + user.setRealname(parts[1].trim()); + user.setWorkNo(parts[0].trim()); + } else { + user.setUsername(name); + user.setRealname(name); + user.setWorkNo(""); + log.warn("椋炰功鐢ㄦ埛name瀛楁鏍煎紡寮傚父锛屾棤娉曟媶鍒嗭紝鍘熷鍊硷細{}", name); + } + } else { + user.setUsername(name); + user.setRealname(name); + user.setWorkNo(""); + log.warn("椋炰功鐢ㄦ埛name瀛楁鏃犵┖鏍煎垎闅旓紝鏃犳硶鎷嗗垎锛屽師濮嬪�硷細{}", name); + } + + user.setEnName((String) userMap.getOrDefault("en_name", "")); + user.setDescription((String) userMap.getOrDefault("description", "")); + Object mobileVisibleObj = userMap.get("mobile_visible"); + user.setMobileVisible(mobileVisibleObj instanceof Boolean ? (Boolean) mobileVisibleObj : false); + + Object avatarObj = userMap.get("avatar"); + if (avatarObj instanceof Map) { + Map<String, Object> avatarMap = (Map<String, Object>) avatarObj; + user.setAvatar240((String) avatarMap.getOrDefault("avatar_240", "")); + user.setAvatar640((String) avatarMap.getOrDefault("avatar_640", "")); + user.setAvatar72((String) avatarMap.getOrDefault("avatar_72", "")); + user.setAvatarOrigin((String) avatarMap.getOrDefault("avatar_origin", "")); + } else { + log.info("鐢ㄦ埛[{}]鏈缃ご鍍忔垨澶村儚鏍煎紡寮傚父", user.getRealname()); + } + + user.setPassword("123456"); + user.setOpenId((String) userMap.getOrDefault("open_id", "")); + userList.add(user); + } + + return userList; + } + + /** + * 鍚屾鍗曚釜椋炰功鐢ㄦ埛鍒扮郴缁� + */ + private boolean syncFeishuUserToSystem(FeishuUser feishuUser) { + String username = feishuUser.getUsername(); + SysUser existUser = sysUserService.getUserByName(username); + SysUser sysUser = new SysUser(); + sysUser.setUsername(username); + sysUser.setStatus(1); + sysUser.setDelFlag(0); + sysUser.setAvatar(feishuUser.getAvatar640()); + sysUser.setRealname(feishuUser.getRealname()); + sysUser.setWorkNo(feishuUser.getWorkNo()); + String password = "123456", salt = oConvertUtils.randomGen(8); + String passwordEncode = PasswordUtil.encrypt(sysUser.getUsername(), password, salt); + sysUser.setSalt(salt); + sysUser.setPassword(passwordEncode); + sysUser.setOpenId(feishuUser.getOpenId()); + + if (existUser == null) { + sysUserService.addUserWithRole(sysUser, "5"); + log.info("鏂板鐢ㄦ埛: {}", username); + return false; + } else { + sysUser.setId(existUser.getId()); + sysUserService.editUser(sysUser); + log.info("鏇存柊鐢ㄦ埛: {}", username); + return true; + } + } +} -- Gitblit v1.9.3