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("同步飞书用户失败,用户ID: {}", feishuUser.getUserId(), e);
|
}
|
}
|
|
log.info("飞书用户同步完成,总处理: {},新增: {},更新: {}", successCount, addCount, updateCount);
|
} catch (Exception e) {
|
log.error("同步飞书部门用户失败,部门ID: {}", 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("一级通知发送失败,终止后续通知流程,安灯ID: {}", andonOrde.getId());
|
}
|
|
return firstLevelResult;
|
} catch (Exception e) {
|
log.error("处理安灯通知异常,安灯ID: {}", 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
|
);
|
|
// 解析响应
|
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为空,安灯ID: {}", levelDesc, andonOrde.getId());
|
return false;
|
}
|
} else {
|
log.error("发送{}级安灯通知失败,安灯ID: {}", levelDesc, andonOrde.getId());
|
if (result != null) {
|
log.error("错误码: {}, 错误信息: {}", result.getInteger("code"), result.getString("msg"));
|
}
|
return false;
|
}
|
|
} catch (Exception e) {
|
log.error("发送{}级安灯通知异常,安灯ID: {}", 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("已到达最高级别通知,无需继续调度,安灯ID: {}", 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("【{}】订单已响应(status=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("【{}】{}通知发送失败,终止后续调度,安灯ID: {}",
|
currentExecuteTime, nextLevelDesc, andonOrde.getId());
|
}
|
|
} catch (Exception e) {
|
log.error("执行{}调度任务异常,安灯ID: {}", 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) {
|
// // 一级模板:【工艺安灯】XXX产线发起了工艺安灯,请xx分钟内在PDA上进行响应处理!!!
|
// return String.format("【工艺安灯】\n%s产线发起了工艺安灯,请%d分钟内在PDA上进行响应处理!!!",
|
// factoryName,
|
// andonOrde.getUpgradeResponseDuration());
|
// } else {
|
// // 二/三级模板:【工艺安灯】XXX(产线)发起的工艺安灯,xxx(上一级响应人)未在xx分钟内响应,请尽快督促进行响应处理!!!
|
// 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("一级响应人信息无效(openId或时长缺失),安灯ID: {}", andonOrde.getId());
|
return false;
|
}
|
// 二级响应校验(若存在则必选完整)
|
if (andonOrde.getSecondResponderOpenId() != null && !andonOrde.getSecondResponderOpenId().isEmpty()) {
|
if (andonOrde.getSecondUpgradeResponseDuration() == null || andonOrde.getSecondUpgradeResponseDuration() <= 0) {
|
log.error("二级响应人存在但时长无效,安灯ID: {}", andonOrde.getId());
|
return false;
|
}
|
}
|
// 三级响应校验(若存在则必选完整)
|
if (andonOrde.getThirdResponderOpenId() != null && !andonOrde.getThirdResponderOpenId().isEmpty()) {
|
if (andonOrde.getSecondUpgradeResponseDuration() == null || andonOrde.getSecondUpgradeResponseDuration() <= 0) {
|
log.error("三级响应人存在但二级时长无效(三级依赖二级时长),安灯ID: {}", 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("第{}页API响应: {}", 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("第{}页has_more: {}, page_token: {}", pageNumber, hasMore, pageToken);
|
pageNumber++;
|
} else {
|
log.warn("第{}页data为空", 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;
|
}
|
|
/**
|
* 解析用户数据
|
*/
|
@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("解析用户数据失败,items不是列表类型: {}", 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;
|
}
|
}
|
}
|