实现钉钉部门同步功能:递归获取所有部门并保存ding_dept_id,修复类型转换错误
This commit is contained in:
parent
949eecaf37
commit
ff1363f55d
@ -152,6 +152,17 @@ public class DingTalkController {
|
||||
return Result.success(dingTalkService.getDepartmentList());
|
||||
}
|
||||
|
||||
@Operation(summary = "同步钉钉部门")
|
||||
@PostMapping("/sync-departments")
|
||||
public Result<Integer> syncDepartments() {
|
||||
try {
|
||||
return Result.success(dingTalkService.syncDepartments());
|
||||
} catch (Exception e) {
|
||||
log.error("同步钉钉部门失败", e);
|
||||
return Result.error("同步钉钉部门失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "同步钉钉用户")
|
||||
@PostMapping("/sync-users")
|
||||
public Result<Integer> syncUsers() {
|
||||
|
||||
@ -2,8 +2,10 @@ package com.designhub.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.designhub.common.ResultCode;
|
||||
import com.designhub.entity.Department;
|
||||
import com.designhub.entity.DingTalkConfig;
|
||||
import com.designhub.exception.BusinessException;
|
||||
import com.designhub.mapper.DepartmentMapper;
|
||||
import com.designhub.mapper.DingTalkConfigMapper;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@ -32,6 +34,7 @@ public class DingTalkService {
|
||||
private final DingTalkConfigMapper configMapper;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final RestTemplate restTemplate = new RestTemplate();
|
||||
private final DepartmentMapper departmentMapper;
|
||||
|
||||
private static final String DINGTALK_API_BASE = "https://oapi.dingtalk.com";
|
||||
|
||||
@ -441,17 +444,24 @@ public class DingTalkService {
|
||||
Map<String, Object> result = (Map<String, Object>) body.get("result");
|
||||
|
||||
// 获取部门信息
|
||||
List<Long> deptIdList = (List<Long>) result.get("dept_id_list");
|
||||
if (deptIdList != null && !deptIdList.isEmpty()) {
|
||||
Object deptIdListObj = result.get("dept_id_list");
|
||||
if (deptIdListObj != null) {
|
||||
List<Map<String, Object>> departments = new ArrayList<>();
|
||||
for (Long deptId : deptIdList) {
|
||||
Map<String, Object> deptInfo = getDepartmentInfo(deptId.toString());
|
||||
if (deptInfo != null) {
|
||||
departments.add(deptInfo);
|
||||
List<?> deptIdList = (List<?>) deptIdListObj;
|
||||
if (!deptIdList.isEmpty()) {
|
||||
for (Object deptIdObj : deptIdList) {
|
||||
// 处理Integer或Long类型
|
||||
String deptIdStr = deptIdObj != null ? deptIdObj.toString() : null;
|
||||
if (deptIdStr != null) {
|
||||
Map<String, Object> deptInfo = getDepartmentInfo(deptIdStr);
|
||||
if (deptInfo != null) {
|
||||
departments.add(deptInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
result.put("departments", departments);
|
||||
log.info("获取到用户部门信息: userId={}, departments={}", userId, departments.size());
|
||||
}
|
||||
result.put("departments", departments);
|
||||
log.info("获取到用户部门信息: userId={}, departments={}", userId, departments.size());
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -503,6 +513,127 @@ public class DingTalkService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步钉钉部门到系统数据库
|
||||
* 递归获取所有部门,保存或更新到数据库,并设置ding_dept_id
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int syncDepartments() {
|
||||
DingTalkConfig config = getConfig();
|
||||
if (config == null) {
|
||||
throw new BusinessException(ResultCode.PARAM_ERROR, "钉钉未配置");
|
||||
}
|
||||
|
||||
log.info("开始同步钉钉部门...");
|
||||
int syncCount = 0;
|
||||
|
||||
try {
|
||||
String accessToken = getAccessToken(config);
|
||||
if (accessToken == null) {
|
||||
throw new BusinessException(ResultCode.PARAM_ERROR, "获取钉钉访问令牌失败");
|
||||
}
|
||||
|
||||
// 递归获取所有部门(从根部门开始)
|
||||
List<Map<String, Object>> allDepartments = getAllDepartmentsRecursive(accessToken, 1L);
|
||||
|
||||
log.info("从钉钉获取到 {} 个部门", allDepartments.size());
|
||||
|
||||
// 同步每个部门到数据库
|
||||
for (Map<String, Object> dingDept : allDepartments) {
|
||||
Object deptIdObj = dingDept.get("dept_id");
|
||||
String dingDeptId = deptIdObj != null ? deptIdObj.toString() : null;
|
||||
String deptName = (String) dingDept.get("name");
|
||||
Object parentIdObj = dingDept.get("parent_id");
|
||||
String parentDingDeptId = parentIdObj != null ? parentIdObj.toString() : null;
|
||||
|
||||
if (dingDeptId == null || deptName == null) {
|
||||
log.warn("跳过无效的部门信息: {}", dingDept);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 查找系统部门(通过ding_dept_id或名称)
|
||||
com.designhub.entity.Department sysDept = departmentMapper.selectOne(
|
||||
new LambdaQueryWrapper<com.designhub.entity.Department>()
|
||||
.eq(com.designhub.entity.Department::getDingDeptId, dingDeptId)
|
||||
.eq(com.designhub.entity.Department::getDeleted, 0)
|
||||
.last("LIMIT 1")
|
||||
);
|
||||
|
||||
if (sysDept == null) {
|
||||
// 通过名称查找
|
||||
sysDept = departmentMapper.selectOne(
|
||||
new LambdaQueryWrapper<com.designhub.entity.Department>()
|
||||
.eq(com.designhub.entity.Department::getDeptName, deptName)
|
||||
.eq(com.designhub.entity.Department::getDeleted, 0)
|
||||
.last("LIMIT 1")
|
||||
);
|
||||
}
|
||||
|
||||
if (sysDept != null) {
|
||||
// 更新现有部门:设置ding_dept_id
|
||||
sysDept.setDingDeptId(dingDeptId);
|
||||
departmentMapper.updateById(sysDept);
|
||||
log.info("更新部门: id={}, name={}, ding_dept_id={}", sysDept.getId(), deptName, dingDeptId);
|
||||
} else {
|
||||
// 部门不存在,可以选择创建或跳过
|
||||
// 这里选择跳过,因为部门应该先在系统中创建
|
||||
log.warn("系统部门不存在,跳过同步: name={}, ding_dept_id={}", deptName, dingDeptId);
|
||||
}
|
||||
syncCount++;
|
||||
}
|
||||
|
||||
log.info("同步钉钉部门完成,共处理 {} 个部门", syncCount);
|
||||
return syncCount;
|
||||
} catch (Exception e) {
|
||||
log.error("同步钉钉部门失败", e);
|
||||
throw new BusinessException(ResultCode.DINGTALK_API_ERROR, "同步钉钉部门失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归获取所有部门
|
||||
*/
|
||||
private List<Map<String, Object>> getAllDepartmentsRecursive(String accessToken, Long parentDeptId) {
|
||||
List<Map<String, Object>> allDepartments = new ArrayList<>();
|
||||
|
||||
try {
|
||||
String url = String.format("%s/topapi/v2/department/listsub?access_token=%s",
|
||||
DINGTALK_API_BASE, accessToken);
|
||||
|
||||
Map<String, Object> request = new HashMap<>();
|
||||
request.put("dept_id", parentDeptId);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(request, headers);
|
||||
|
||||
ResponseEntity<Map> response = restTemplate.postForEntity(url, entity, Map.class);
|
||||
Map<String, Object> body = response.getBody();
|
||||
|
||||
if (body != null) {
|
||||
Object errcode = body.get("errcode");
|
||||
if (errcode != null && (errcode.equals(0) || errcode.equals(0L) || "0".equals(errcode.toString()))) {
|
||||
List<Map<String, Object>> subDepts = (List<Map<String, Object>>) body.get("result");
|
||||
if (subDepts != null) {
|
||||
for (Map<String, Object> dept : subDepts) {
|
||||
allDepartments.add(dept);
|
||||
// 递归获取子部门
|
||||
Object deptIdObj = dept.get("dept_id");
|
||||
if (deptIdObj != null) {
|
||||
Long deptId = deptIdObj instanceof Long ? (Long) deptIdObj : Long.parseLong(deptIdObj.toString());
|
||||
allDepartments.addAll(getAllDepartmentsRecursive(accessToken, deptId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取部门列表失败: parentDeptId={}", parentDeptId, e);
|
||||
}
|
||||
|
||||
return allDepartments;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步钉钉用户
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user