commit
This commit is contained in:
@@ -1,17 +1,7 @@
|
||||
package com.budwk.app.base.config;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.constant.RedisConstant;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.integration.jedis.RedisService;
|
||||
import org.nutz.ioc.impl.PropertiesProxy;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
@@ -33,19 +23,17 @@ public class DataCenterProperties {
|
||||
|
||||
@Inject
|
||||
private PropertiesProxy conf;
|
||||
@Inject
|
||||
private RedisService redisService;
|
||||
|
||||
private String appId;
|
||||
private String tokenUrl;
|
||||
private Map<String, String> codes = new HashMap<>();
|
||||
private String key;
|
||||
private String secret;
|
||||
private Map<String, String> urls = new HashMap<>();
|
||||
|
||||
public void init() {
|
||||
Map<String, String> all = conf.toMap();
|
||||
appId = all.get("data-center.app-id");
|
||||
tokenUrl = all.get("data-center.token-url");
|
||||
extract(all, "data-center.codes.", codes);
|
||||
key = all.get("data-center.key");
|
||||
secret = all.get("data-center.secret");
|
||||
extract(all, "data-center.urls.", urls);
|
||||
}
|
||||
|
||||
@@ -61,59 +49,4 @@ public class DataCenterProperties {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取配置
|
||||
* @param key 接口类型枚举
|
||||
* @return 相关配置
|
||||
*/
|
||||
public Credential credential(String key) {
|
||||
String code = codes.get(key);
|
||||
String url = urls.get(key);
|
||||
if (code == null || url == null) {
|
||||
throw new BaseException("未知业务: " + key);
|
||||
}
|
||||
String token = getToken(Integer.parseInt(code), key);
|
||||
return new Credential(url, token);
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public static class Credential {
|
||||
private String url;
|
||||
private String token;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取token
|
||||
* @param code
|
||||
* @param keyPrefix
|
||||
* @return token
|
||||
*/
|
||||
private String getToken(Integer code, String keyPrefix) {
|
||||
String dateCenterPrefix = RedisConstant.DATE_CENTER_PREFIX + keyPrefix;
|
||||
String token = redisService.get(dateCenterPrefix);
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
return token;
|
||||
} else {
|
||||
HttpRequest httpRequest = HttpUtil.createPost(tokenUrl);
|
||||
Map<String, Object> reqBody = Map.of(
|
||||
"appId", appId,
|
||||
"code", code
|
||||
);
|
||||
httpRequest.body(JSONUtil.toJsonStr(reqBody));
|
||||
JSONObject resp = JSONUtil.parseObj(httpRequest.execute().body());
|
||||
|
||||
if (resp.getInt("code") != 200) {
|
||||
throw new BaseException("获取token失败: " + resp.getStr("msg"));
|
||||
} else {
|
||||
JSONObject data = resp.getJSONObject("data");
|
||||
String tokenStr = data.getStr("token");
|
||||
Integer expire = data.getInt("expire");
|
||||
redisService.setex(dateCenterPrefix, expire, tokenStr);
|
||||
return tokenStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class Sys_user extends BaseModel implements Serializable {
|
||||
@Column
|
||||
@Comment("工号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 120)
|
||||
@DataCenterColumn(name = "工号", key = "JGH")
|
||||
@DataCenterColumn(name = "工号", key = "ZGH")
|
||||
private String loginname;
|
||||
|
||||
@Column
|
||||
@@ -108,13 +108,12 @@ public class Sys_user extends BaseModel implements Serializable {
|
||||
@Column
|
||||
@Comment("手机号码")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@DataCenterColumn(name = "手机号码", key = "SJHM")
|
||||
@DataCenterColumn(name = "手机号码", key = "YDDH")
|
||||
private String mobile;
|
||||
|
||||
@Column
|
||||
@Comment("学历")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
@DataCenterColumn(name = "学历", key = "ZGXLM", dict = "USER_EDUCATION")
|
||||
private String education;
|
||||
|
||||
@Column
|
||||
@@ -131,19 +130,16 @@ public class Sys_user extends BaseModel implements Serializable {
|
||||
@Column
|
||||
@Comment("岗位类别")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
@DataCenterColumn(name = "岗位类别", key = "JRGWDJM",dict = "USER_JOB_CATEGORY")
|
||||
private String jobCategory;
|
||||
|
||||
@Column
|
||||
@Comment("职称")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
@DataCenterColumn(name = "职称", key = "DQZC", dict = "USER_PROFESSIONAL_TITLE")
|
||||
private String professionalTitle;
|
||||
|
||||
@Column
|
||||
@Comment("职级")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
@DataCenterColumn(name = "取得职称等级码", key = "QDZCDJM", dict = "USER_PROFESSIONAL_LEVEL")
|
||||
private String professionalLevel;
|
||||
|
||||
@Column
|
||||
@@ -179,7 +175,7 @@ public class Sys_user extends BaseModel implements Serializable {
|
||||
@Column
|
||||
@Comment("来校时间")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 10)
|
||||
@DataCenterColumn(name = "来校时间", key = "LXRQ")
|
||||
@DataCenterColumn(name = "来校时间", key = "LXNY")
|
||||
private String arrivalAtSchoolDate;
|
||||
|
||||
@Column
|
||||
@@ -195,7 +191,7 @@ public class Sys_user extends BaseModel implements Serializable {
|
||||
@Column
|
||||
@Comment("在职状态")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
@DataCenterColumn(name = "当前状态码", key = "DQZTM", dict = "USER_STATE")
|
||||
@DataCenterColumn(name = "当前状态码", key = "DQZT", dict = "USER_STATE")
|
||||
private String userState;
|
||||
|
||||
@Column
|
||||
@@ -207,19 +203,17 @@ public class Sys_user extends BaseModel implements Serializable {
|
||||
@Column
|
||||
@Comment("在岗情况")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
@DataCenterColumn(name = "在岗情况码", key = "ZGQKM", dict = "USER_DUTY_SITUATION")
|
||||
private String dutySituation;
|
||||
|
||||
@Column
|
||||
@Comment("教职工类别码")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
@DataCenterColumn(name = "教职工类别码", key = "JZGLBM", dict = "USER_PERSON_TYPE")
|
||||
@DataCenterColumn(name = "教职工类别码", key = "RYLX", dict = "USER_PERSON_TYPE")
|
||||
private String personType;
|
||||
|
||||
@Column
|
||||
@Comment("编制类别码")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
@DataCenterColumn(name = "编制类别码", key = "BZLBM", dict = "USER_PREPARED_BY_TYPE")
|
||||
private String preparedBy;
|
||||
|
||||
@Column
|
||||
@@ -269,7 +263,7 @@ public class Sys_user extends BaseModel implements Serializable {
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@DataCenterColumn(name = "单位", key = "DWH")
|
||||
@DataCenterColumn(name = "单位", key = "SZDWH")
|
||||
private String unitId;
|
||||
|
||||
@Column
|
||||
|
||||
@@ -1,28 +1,14 @@
|
||||
package com.budwk.app.sys.services.impl;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.config.DataCenterProperties;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.sys.models.Sys_data_dict;
|
||||
import com.budwk.app.sys.models.Sys_dict;
|
||||
import com.budwk.app.sys.services.SysDataDictPullService;
|
||||
import com.budwk.app.sys.services.SysDictService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
@@ -35,14 +21,6 @@ import java.util.Map;
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class SysDataDictPullServiceImpl extends BaseServiceImpl<Sys_dict> implements SysDataDictPullService {
|
||||
|
||||
@Inject
|
||||
private DataCenterProperties dcPro;
|
||||
@Inject
|
||||
private SysDictService dictService;
|
||||
|
||||
// code
|
||||
private final static String KEY_PREFIX = "user_";
|
||||
|
||||
public SysDataDictPullServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
@@ -50,57 +28,7 @@ public class SysDataDictPullServiceImpl extends BaseServiceImpl<Sys_dict> implem
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void pullDataDict() {
|
||||
Map<String, String> urls = dcPro.getUrls();
|
||||
List<String> list = urls.keySet().stream().filter(o -> o.startsWith(KEY_PREFIX.toUpperCase())).toList();
|
||||
|
||||
List<Sys_data_dict> dataDictList = new ArrayList<>();
|
||||
|
||||
for (String key : list) {
|
||||
// 获取配置
|
||||
DataCenterProperties.Credential credential = dcPro.credential(key);
|
||||
String url = credential.getUrl();
|
||||
String token = credential.getToken();
|
||||
|
||||
// 请求数据
|
||||
HttpRequest httpRequest = HttpUtil.createPost(url);
|
||||
httpRequest.header("Content-Type", "application/json");
|
||||
httpRequest.header("X-H3C-TOKEN", token);
|
||||
httpRequest.body(JSONUtil.toJsonStr(Map.of()));
|
||||
|
||||
String resBody = httpRequest.execute().body();
|
||||
JSONObject jsonBody = JSONUtil.parseObj(resBody);
|
||||
|
||||
if (jsonBody.getInt("code") != 200) {
|
||||
log.error("获取{}字典数据失败,错误码: {};错误原因:{}", key, jsonBody.getInt("code"), jsonBody.getStr("msg"));
|
||||
}
|
||||
List<NutMap> data = Json.fromJsonAsList(NutMap.class, jsonBody.getStr("data"));
|
||||
|
||||
// 先删除
|
||||
Sys_dict sysDict = dao().fetch(Sys_dict.class, Cnd.where(Sys_dict::getCode, "=", key));
|
||||
dao().clear(Sys_dict.class, Cnd.where(Sys_dict::getParentId, "=", sysDict.getId()));
|
||||
|
||||
// 组合数据
|
||||
data.forEach(o -> {
|
||||
Sys_dict dict = new Sys_dict();
|
||||
dict.setParentId(sysDict.getId());
|
||||
|
||||
dict.setPath(dictService.getSubPath("sys_dict", "path", sysDict.getPath()));
|
||||
dict.setName(o.getString("xbname"));
|
||||
dict.setCode(o.getString("xbname"));
|
||||
dict.setDisabled(false);
|
||||
dict.setHasChildren(false);
|
||||
dao().insert(dict);
|
||||
|
||||
Sys_data_dict sysDataDict = new Sys_data_dict();
|
||||
sysDataDict.setParentCode(key);
|
||||
sysDataDict.setCode(o.getString("xbcode"));
|
||||
sysDataDict.setName(o.getString("xbname"));
|
||||
|
||||
dataDictList.add(sysDataDict);
|
||||
|
||||
});
|
||||
|
||||
dao().insert(dataDictList);
|
||||
}
|
||||
// 旧数据中心字典接口已停用,避免继续误调旧token/code模式接口。
|
||||
throw new BaseException("旧数据中心字典拉取接口已停用");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,33 @@
|
||||
package com.budwk.app.sys.services.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.http.Header;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.config.DataCenterProperties;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.sys.enums.Api2UnitFiledMap;
|
||||
import com.budwk.app.sys.models.Sys_unit;
|
||||
import com.budwk.app.sys.services.SysDataUnitPullService;
|
||||
import com.budwk.app.sys.utils.DataCenterUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -40,8 +41,11 @@ import java.util.stream.Collectors;
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class SysDataUnitPullServiceImpl extends BaseServiceImpl<Sys_unit> implements SysDataUnitPullService {
|
||||
|
||||
private static final String DMP_UNIT_KEY = "unit";
|
||||
private static final int DMP_PAGE_SIZE = 1000;
|
||||
|
||||
@Inject
|
||||
private DataCenterProperties dcPro;
|
||||
private DataCenterProperties dataCenterProperties;
|
||||
|
||||
public SysDataUnitPullServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
@@ -51,11 +55,7 @@ public class SysDataUnitPullServiceImpl extends BaseServiceImpl<Sys_unit> implem
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void updateUnits() {
|
||||
Sql sql = Sqls.create("select id from sys_unit group by id");
|
||||
sql.setCallback(Sqls.callback.strList());
|
||||
dao().execute(sql);
|
||||
List<String> unitIds = sql.getList(String.class);
|
||||
updateUnits(unitIds);
|
||||
updateUnits(List.of());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,65 +64,211 @@ public class SysDataUnitPullServiceImpl extends BaseServiceImpl<Sys_unit> implem
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void updateUnits(List<String> unitIds) {
|
||||
// token url参数
|
||||
Map<String, String> tokenParams = Map.of(
|
||||
"grant_type", "password",
|
||||
"scope", "read",
|
||||
"username", "3848A3C738EFBB2C2E76E0D59B419DACA16A80F3AB0354CD",
|
||||
"password", "3848A3C738EFBB2C2E76E0D59B419DACA16A80F3AB0354CD"
|
||||
);
|
||||
String accessToken = getDmpAccessToken();
|
||||
List<JSONObject> rawDataList = distinctDmpUnits(pullDmpUnits(getDmpUnitUrl(), accessToken));
|
||||
Set<String> parentCodes = rawDataList.stream()
|
||||
.map(v -> v.getStr("LSDWH"))
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
String params = URLUtil.buildQuery(tokenParams, StandardCharsets.UTF_8);
|
||||
String tokenUrl = "https://bd.whcp.edu.cn/sjjkfwpt/api/bd-api/oauth/token" + (StrUtil.isBlank(params) ? "" : "?" + params);
|
||||
HttpRequest tokenHttpRequest = HttpUtil.createPost(tokenUrl);
|
||||
tokenHttpRequest.header("Content-Type", "application/json");
|
||||
tokenHttpRequest.header("Authorization", "Basic MTE0OjU5M2UwNGI4YTE4NWRlMzkyNjY4ZmY0ZDJhZGMyZTEw");
|
||||
rawDataList.stream()
|
||||
.sorted(Comparator.comparingInt(this::getUnitLevel))
|
||||
.forEach(raw -> saveOrUpdateUnit(raw, parentCodes));
|
||||
|
||||
log.info("请求token: {}", tokenHttpRequest);
|
||||
String tokenResBody = tokenHttpRequest.execute().body();
|
||||
log.info("信息中心单位数据同步完成,本次接口返回单位数量: {},待检查单位编码数量: {}", rawDataList.size(), unitIds == null ? 0 : unitIds.size());
|
||||
}
|
||||
|
||||
log.info("请求token结果: {}", tokenResBody);
|
||||
/**
|
||||
* 获取信息中心开放平台访问令牌。
|
||||
* 参数来自 data-center.token-url、data-center.key、data-center.secret;
|
||||
* 返回值为后续单位接口 body 中 access_token 使用的字符串。
|
||||
*/
|
||||
private String getDmpAccessToken() {
|
||||
String tokenUrl = dataCenterProperties.getTokenUrl();
|
||||
if (StrUtil.isBlank(tokenUrl)) {
|
||||
throw new BaseException("未配置信息中心token地址: data-center.token-url");
|
||||
}
|
||||
String key = dataCenterProperties.getKey();
|
||||
if (StrUtil.isBlank(key)) {
|
||||
throw new BaseException("未配置信息中心token key: data-center.key");
|
||||
}
|
||||
String secret = dataCenterProperties.getSecret();
|
||||
if (StrUtil.isBlank(secret)) {
|
||||
throw new BaseException("未配置信息中心token secret: data-center.secret");
|
||||
}
|
||||
|
||||
String params = URLUtil.buildQuery(Map.of("key", key, "secret", secret), StandardCharsets.UTF_8);
|
||||
String tokenResBody = HttpUtil.createGet(tokenUrl + "?" + params).execute().body();
|
||||
JSONObject tokenJsonBody = JSONUtil.parseObj(tokenResBody);
|
||||
|
||||
// 请求数据
|
||||
HttpRequest httpRequest = HttpUtil.createGet("https://bd.whcp.edu.cn/sjjkfwpt/api/bd-api/get/YXSDWJBSJZLB");
|
||||
httpRequest.form(Map.of("access_token", tokenJsonBody.getStr("access_token"), "pageSize", 100, "page", 1));
|
||||
log.info("请求单位数据: {}", httpRequest);
|
||||
String resBody = httpRequest.execute().body();
|
||||
log.info("请求单位数据结果: {}", resBody);
|
||||
JSONObject jsonBody = JSONUtil.parseObj(resBody);
|
||||
|
||||
if (jsonBody.getInt("code") != 200) {
|
||||
throw new BaseException("获取单位数据失败,错误码: " + jsonBody.getInt("code") + ";错误原因:" + jsonBody.getStr("msg"));
|
||||
String accessToken = tokenJsonBody.getStr("access_token");
|
||||
if (StrUtil.isBlank(accessToken) && tokenJsonBody.getJSONObject("result") != null) {
|
||||
accessToken = tokenJsonBody.getJSONObject("result").getStr("access_token");
|
||||
}
|
||||
if (StrUtil.isBlank(accessToken) && tokenJsonBody.getJSONObject("data") != null) {
|
||||
accessToken = tokenJsonBody.getJSONObject("data").getStr("access_token");
|
||||
}
|
||||
if (StrUtil.isBlank(accessToken)) {
|
||||
accessToken = tokenJsonBody.getStr("token");
|
||||
}
|
||||
if (StrUtil.isBlank(accessToken)) {
|
||||
throw new BaseException("获取信息中心token失败");
|
||||
}
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
// 需要新增的单位
|
||||
List<Sys_unit> insertList = new ArrayList<>();
|
||||
// 需要更新的单位
|
||||
List<Sys_unit> updateList = new ArrayList<>();
|
||||
/**
|
||||
* 读取信息中心单位接口地址。
|
||||
* 配置项为 data-center.urls.unit,返回值为单位全量接口URL。
|
||||
*/
|
||||
private String getDmpUnitUrl() {
|
||||
String url = dataCenterProperties.getUrls().get(DMP_UNIT_KEY);
|
||||
if (StrUtil.isBlank(url)) {
|
||||
throw new BaseException("未配置信息中心单位接口地址: data-center.urls." + DMP_UNIT_KEY);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
// 拉取过来的数据,全部的单位,一万四千多条,这里只保留 “部门类”
|
||||
List<JSONObject> data = jsonBody.getJSONArray("data").stream()
|
||||
.map(o -> (JSONObject) o)
|
||||
.toList();
|
||||
/**
|
||||
* 分页拉取单位接口数据。
|
||||
* 入参 url 为单位接口地址,accessToken 为信息中心令牌;
|
||||
* 请求 body 包含 access_token、per_page、page;
|
||||
* 返回值为 result.data 合并后的单位原始 JSON 列表。
|
||||
*/
|
||||
private List<JSONObject> pullDmpUnits(String url, String accessToken) {
|
||||
List<JSONObject> rawDataList = new ArrayList<>();
|
||||
int page = 1;
|
||||
int maxPage = 1;
|
||||
int total = 0;
|
||||
|
||||
Map<String, String> api2db = Arrays.stream(Api2UnitFiledMap.values())
|
||||
.collect(Collectors.toMap(e -> e.apiField, e -> e.dbColumn));
|
||||
for (JSONObject row : data) {
|
||||
Sys_unit unit = DataCenterUtil.mapJsonToBean(row, Sys_unit.class, api2db);
|
||||
unit.setUnitcode(unit.getId());
|
||||
unit.setUnitTypeCode(1);
|
||||
do {
|
||||
HttpRequest httpRequest = HttpUtil.createPost(url);
|
||||
httpRequest.header(Header.CONTENT_TYPE, "application/json");
|
||||
httpRequest.body(JSONUtil.toJsonStr(Map.of(
|
||||
"access_token", accessToken,
|
||||
"per_page", String.valueOf(DMP_PAGE_SIZE),
|
||||
"page", String.valueOf(page)
|
||||
)));
|
||||
|
||||
if (unitIds.contains(unit.getId())) {
|
||||
// 存在则更新
|
||||
updateList.add(unit);
|
||||
} else {
|
||||
// 不存在则新增
|
||||
insertList.add(unit);
|
||||
log.info("请求信息中心单位数据,第{}页: {}", page, httpRequest);
|
||||
String resBody = httpRequest.execute().body();
|
||||
log.info("请求信息中心单位数据第{}页结果: {}", page, resBody);
|
||||
JSONObject jsonBody = JSONUtil.parseObj(resBody);
|
||||
|
||||
if (jsonBody.getInt("code") != 10000) {
|
||||
throw new BaseException("获取信息中心单位数据失败,错误码: " + jsonBody.getInt("code") + ";错误原因:" + jsonBody.getStr("message"));
|
||||
}
|
||||
|
||||
JSONObject result = jsonBody.getJSONObject("result");
|
||||
if (result == null) {
|
||||
break;
|
||||
}
|
||||
total = result.getInt("total", total);
|
||||
maxPage = result.getInt("max_page", maxPage);
|
||||
JSONArray data = result.getJSONArray("data");
|
||||
if (CollUtil.isNotEmpty(data)) {
|
||||
rawDataList.addAll(data.stream().map(v -> (JSONObject) v).toList());
|
||||
}
|
||||
log.info("信息中心单位数据拉取进度: {}/{}", rawDataList.size(), total);
|
||||
page++;
|
||||
} while (page <= maxPage);
|
||||
|
||||
return rawDataList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按单位代码去重,避免接口分页或源数据重复导致同一 DWDM 重复写入。
|
||||
*/
|
||||
private List<JSONObject> distinctDmpUnits(List<JSONObject> rawDataList) {
|
||||
Map<String, JSONObject> unitMap = new LinkedHashMap<>();
|
||||
for (JSONObject raw : rawDataList) {
|
||||
String unitCode = raw.getStr("DWDM");
|
||||
if (StrUtil.isBlank(unitCode)) {
|
||||
continue;
|
||||
}
|
||||
unitMap.putIfAbsent(unitCode, raw);
|
||||
}
|
||||
log.info("本次拉取单位数据,新增{}条,更新{}条", insertList.size(), updateList.size());
|
||||
dao().insert(insertList);
|
||||
dao().update(updateList);
|
||||
return new ArrayList<>(unitMap.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存或更新单位。
|
||||
* DWDM 对应系统单位 id/unitcode,DWMC 对应名称,LSDWH 对应父级单位号,DWCC 对应单位层级。
|
||||
*/
|
||||
private void saveOrUpdateUnit(JSONObject raw, Set<String> parentCodes) {
|
||||
String unitCode = raw.getStr("DWDM");
|
||||
if (StrUtil.isBlank(unitCode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String parentId = getParentId(unitCode, raw.getStr("LSDWH"));
|
||||
Sys_unit unit = fetch(unitCode);
|
||||
if (unit == null) {
|
||||
unit = new Sys_unit();
|
||||
unit.setId(unitCode);
|
||||
unit.setUnitcode(unitCode);
|
||||
unit.setPath(getUnitPath(parentId));
|
||||
setUnitValue(unit, raw, parentId, parentCodes);
|
||||
dao().fastInsert(unit);
|
||||
} else {
|
||||
setUnitValue(unit, raw, parentId, parentCodes);
|
||||
if (StrUtil.isBlank(unit.getPath())) {
|
||||
unit.setPath(getUnitPath(parentId));
|
||||
}
|
||||
dao().updateIgnoreNull(unit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据接口字段给系统单位赋值。
|
||||
* DWYXBS 表示单位是否有效,DWCC 表示单位层次;当前项目用 unitTypeCode=1 识别业务可选单位。
|
||||
*/
|
||||
private void setUnitValue(Sys_unit unit, JSONObject raw, String parentId, Set<String> parentCodes) {
|
||||
String unitCode = raw.getStr("DWDM");
|
||||
String unitName = raw.getStr("DWMC");
|
||||
String aliasName = StrUtil.blankToDefault(raw.getStr("DWJC"), unitName);
|
||||
Integer unitLevel = raw.getInt("DWCC");
|
||||
boolean availableBusinessUnit = "是".equals(raw.getStr("DWYXBS")) && Integer.valueOf(2).equals(unitLevel);
|
||||
|
||||
unit.setParentId(parentId);
|
||||
unit.setName(unitName);
|
||||
unit.setAliasName(aliasName);
|
||||
unit.setUnitcode(unitCode);
|
||||
unit.setAddress(raw.getStr("DWDZ"));
|
||||
unit.setUnitLevel(unitLevel);
|
||||
unit.setUnitType(raw.getStr("DWLB"));
|
||||
unit.setUnitTypeCode(availableBusinessUnit ? 1 : 0);
|
||||
unit.setHasChildren(parentCodes.contains(unitCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算父级单位号。
|
||||
* LSDWH 为空、等于自身或本地不存在该父级时按根级处理,避免错误父级影响单位树保存。
|
||||
*/
|
||||
private String getParentId(String unitCode, String parentCode) {
|
||||
if (StrUtil.isBlank(parentCode) || unitCode.equals(parentCode)) {
|
||||
return "";
|
||||
}
|
||||
Sys_unit parentUnit = fetch(parentCode);
|
||||
return parentUnit == null ? "" : parentCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据父级 path 生成当前单位 path。
|
||||
* 父级为空时生成根节点 path,父级存在时在父级 path 下生成子节点 path。
|
||||
*/
|
||||
private String getUnitPath(String parentId) {
|
||||
String parentPath = "";
|
||||
if (StrUtil.isNotBlank(parentId)) {
|
||||
Sys_unit parentUnit = fetch(parentId);
|
||||
parentPath = parentUnit == null ? "" : parentUnit.getPath();
|
||||
}
|
||||
return getSubPath("sys_unit", "path", parentPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* DWCC 为单位层次,排序时用于尽量先处理父级单位,便于后续子级找到父节点。
|
||||
*/
|
||||
private int getUnitLevel(JSONObject raw) {
|
||||
return raw.getInt("DWCC", 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ import java.util.stream.Collectors;
|
||||
@Slf4j
|
||||
public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source> implements SysDataUserPullService {
|
||||
|
||||
private static final String DMP_TEACHER_KEY = "teacher";
|
||||
private static final String DMP_DISPATCH_KEY = "dispatch";
|
||||
private static final int DMP_PAGE_SIZE = 1000;
|
||||
|
||||
@Inject
|
||||
private SysDictService sysDictService;
|
||||
@Inject
|
||||
@@ -115,48 +119,14 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
|
||||
// 字典码表Map,key为父级编码,value为子级字典列表
|
||||
Map<String, List<Sys_data_dict>> dataDictMap = dataDictList.stream().collect(Collectors.groupingBy(Sys_data_dict::getParentCode));
|
||||
|
||||
// token url参数
|
||||
Map<String, String> tokenParams = Map.of(
|
||||
"grant_type", "password",
|
||||
"scope", "read",
|
||||
"username", "3848A3C738EFBB2C2E76E0D59B419DACA16A80F3AB0354CD",
|
||||
"password", "3848A3C738EFBB2C2E76E0D59B419DACA16A80F3AB0354CD"
|
||||
);
|
||||
|
||||
String params = URLUtil.buildQuery(tokenParams, StandardCharsets.UTF_8);
|
||||
String tokenUrl = "https://bd.whcp.edu.cn/sjjkfwpt/api/bd-api/oauth/token" + (StrUtil.isBlank(params) ? "" : "?" + params);
|
||||
HttpRequest tokenHttpRequest = HttpUtil.createPost(tokenUrl);
|
||||
tokenHttpRequest.header("Content-Type", "application/json");
|
||||
tokenHttpRequest.header("Authorization", "Basic MTE0OjU5M2UwNGI4YTE4NWRlMzkyNjY4ZmY0ZDJhZGMyZTEw");
|
||||
|
||||
log.info("请求token: {}", tokenHttpRequest);
|
||||
String tokenResBody = tokenHttpRequest.execute().body();
|
||||
log.info("请求token结果: {}", tokenResBody);
|
||||
|
||||
JSONObject tokenJsonBody = JSONUtil.parseObj(tokenResBody);
|
||||
|
||||
// 请求数据
|
||||
HttpRequest httpRequest = HttpUtil.createGet("https://bd.whcp.edu.cn/sjjkfwpt/api/bd-api/get/JZGJCSJZLB");
|
||||
httpRequest.form(Map.of("access_token", tokenJsonBody.getStr("access_token"), "pageSize", 5000, "page", 1));
|
||||
|
||||
log.info("请求人员数据: {}", httpRequest);
|
||||
String resBody = httpRequest.execute().body();
|
||||
log.info("请求人员数据结果: {}", resBody);
|
||||
JSONObject jsonBody = JSONUtil.parseObj(resBody);
|
||||
|
||||
if (jsonBody.getInt("code") != 200) {
|
||||
throw new BaseException("获取人员数据失败,错误码: " + jsonBody.getInt("code") + ";错误原因:" + jsonBody.getStr("msg"));
|
||||
}
|
||||
|
||||
String accessToken = getDmpAccessToken();
|
||||
List<JSONObject> rawDataList = new ArrayList<>();
|
||||
JSONArray data = jsonBody.getJSONArray("data");
|
||||
rawDataList.addAll(pullDmpUsers(getDmpUrl(DMP_TEACHER_KEY), accessToken, "在岗教职工"));
|
||||
rawDataList.addAll(pullDmpUsers(getDmpUrl(DMP_DISPATCH_KEY), accessToken, "在岗劳务派遣"));
|
||||
rawDataList = distinctDmpUsers(rawDataList);
|
||||
|
||||
if (!data.isEmpty()) {
|
||||
// 先收集所有原始数据
|
||||
rawDataList = data.stream().map(v -> (JSONObject) v).toList();
|
||||
log.info("数据拉取进度: {}/{}", rawDataList.size(), jsonBody.getInt("total"));
|
||||
} else {
|
||||
log.warn("当前未获取到数据");
|
||||
if (rawDataList.isEmpty()) {
|
||||
log.warn("当前未获取到人员数据");
|
||||
}
|
||||
|
||||
Date nowDate = new Date();
|
||||
@@ -172,14 +142,16 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
|
||||
if (mapping.field.getType() == String.class) {
|
||||
|
||||
if (StrUtil.isNotBlank(mapping.dict)) {
|
||||
Sys_data_dict sysDataDict = dataDictMap.get(mapping.dict).stream()
|
||||
.filter(v -> raw.getStr(mapping.key)
|
||||
.equals(v.getCode())).findFirst().orElse(new Sys_data_dict());
|
||||
mapping.field.set(sysUser, sysDataDict.getName());
|
||||
List<Sys_data_dict> sysDataDicts = dataDictMap.getOrDefault(mapping.dict, Collections.emptyList());
|
||||
Sys_data_dict sysDataDict = sysDataDicts.stream()
|
||||
.filter(v -> raw.getStr(mapping.key, "").equals(v.getCode()))
|
||||
.findFirst().orElse(new Sys_data_dict());
|
||||
mapping.field.set(sysUser, StrUtil.blankToDefault(sysDataDict.getName(), raw.getStr(mapping.key)));
|
||||
} else {
|
||||
// 特殊处理 根据身份证号获取性别和出生年月
|
||||
if ("SFZJH".equals(mapping.field.getName())) {
|
||||
if ("SFZJH".equals(mapping.key)) {
|
||||
String idCard = raw.getStr(mapping.key);
|
||||
mapping.field.set(sysUser, idCard);
|
||||
// 设置出生年月
|
||||
try {
|
||||
sysUser.setBirthday(IdcardUtil.getBirthDate(idCard));
|
||||
@@ -206,10 +178,12 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
|
||||
|
||||
log.info("用户数据初始化完成,等待插入,当前数据条数{}", latestSourceList.size());
|
||||
// 插入到数据库
|
||||
dao().insert(latestSourceList);
|
||||
if (CollUtil.isNotEmpty(latestSourceList)) {
|
||||
dao().insert(latestSourceList);
|
||||
}
|
||||
|
||||
// 人员的单位数据和数据库的单位数据比较,如果人员里面有单位不存在,去更新单位数据
|
||||
List<String> sourceUnitIds = latestSourceList.stream().map(Sys_user_source::getUnitId).distinct().toList();
|
||||
List<String> sourceUnitIds = latestSourceList.stream().map(Sys_user_source::getUnitId).filter(StrUtil::isNotBlank).distinct().toList();
|
||||
Sql sql = Sqls.create("select id from sys_unit group by id");
|
||||
sql.setCallback(Sqls.callback.strList());
|
||||
dao().execute(sql);
|
||||
@@ -225,6 +199,122 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取信息中心开放平台访问令牌。
|
||||
* 返回值为接口后续调用使用的 access_token 字符串。
|
||||
*/
|
||||
private String getDmpAccessToken() {
|
||||
String tokenUrl = dataCenterProperties.getTokenUrl();
|
||||
if (StrUtil.isBlank(tokenUrl)) {
|
||||
throw new BaseException("未配置信息中心token地址: data-center.token-url");
|
||||
}
|
||||
String key = dataCenterProperties.getKey();
|
||||
if (StrUtil.isBlank(key)) {
|
||||
throw new BaseException("未配置信息中心token key: data-center.key");
|
||||
}
|
||||
String secret = dataCenterProperties.getSecret();
|
||||
if (StrUtil.isBlank(secret)) {
|
||||
throw new BaseException("未配置信息中心token secret: data-center.secret");
|
||||
}
|
||||
// 信息中心token接口要求key和secret通过URL参数传入,配置中分开维护,调用时统一组装。
|
||||
String params = URLUtil.buildQuery(Map.of("key", key, "secret", secret), StandardCharsets.UTF_8);
|
||||
HttpRequest tokenHttpRequest = HttpUtil.createGet(tokenUrl + "?" + params);
|
||||
log.info("请求信息中心token: {}", tokenHttpRequest);
|
||||
String tokenResBody = tokenHttpRequest.execute().body();
|
||||
log.info("请求信息中心token结果: {}", tokenResBody);
|
||||
|
||||
JSONObject tokenJsonBody = JSONUtil.parseObj(tokenResBody);
|
||||
String accessToken = tokenJsonBody.getStr("access_token");
|
||||
if (StrUtil.isBlank(accessToken) && tokenJsonBody.getJSONObject("result") != null) {
|
||||
accessToken = tokenJsonBody.getJSONObject("result").getStr("access_token");
|
||||
}
|
||||
if (StrUtil.isBlank(accessToken) && tokenJsonBody.getJSONObject("data") != null) {
|
||||
accessToken = tokenJsonBody.getJSONObject("data").getStr("access_token");
|
||||
}
|
||||
if (StrUtil.isBlank(accessToken)) {
|
||||
accessToken = tokenJsonBody.getStr("token");
|
||||
}
|
||||
if (StrUtil.isBlank(accessToken)) {
|
||||
throw new BaseException("获取信息中心token失败");
|
||||
}
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取信息中心人员接口地址。
|
||||
* 入参 key 对应 data-center.urls 下的配置项,返回值为具体接口URL。
|
||||
*/
|
||||
private String getDmpUrl(String key) {
|
||||
String url = dataCenterProperties.getUrls().get(key);
|
||||
if (StrUtil.isBlank(url)) {
|
||||
throw new BaseException("未配置信息中心人员接口地址: data-center.urls." + key);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页拉取单个人员接口数据。
|
||||
* 入参 url 为人员接口地址,accessToken 为信息中心令牌,sourceName 用于日志区分接口来源。
|
||||
* 返回值为该接口所有分页合并后的原始人员 JSON 列表。
|
||||
*/
|
||||
private List<JSONObject> pullDmpUsers(String url, String accessToken, String sourceName) {
|
||||
List<JSONObject> rawDataList = new ArrayList<>();
|
||||
int page = 1;
|
||||
int maxPage = 1;
|
||||
int total = 0;
|
||||
|
||||
do {
|
||||
// 信息中心接口单页最多返回1000条,按page循环拉完当前接口全部数据。
|
||||
HttpRequest httpRequest = HttpUtil.createPost(url);
|
||||
httpRequest.header(Header.CONTENT_TYPE, "application/json");
|
||||
httpRequest.body(JSONUtil.toJsonStr(Map.of(
|
||||
"access_token", accessToken,
|
||||
"per_page", String.valueOf(DMP_PAGE_SIZE),
|
||||
"page", String.valueOf(page)
|
||||
)));
|
||||
|
||||
log.info("请求{}人员数据,第{}页: {}", sourceName, page, httpRequest);
|
||||
String resBody = httpRequest.execute().body();
|
||||
log.info("请求{}人员数据第{}页结果: {}", sourceName, page, resBody);
|
||||
JSONObject jsonBody = JSONUtil.parseObj(resBody);
|
||||
|
||||
if (jsonBody.getInt("code") != 10000) {
|
||||
throw new BaseException("获取" + sourceName + "人员数据失败,错误码: " + jsonBody.getInt("code") + ";错误原因:" + jsonBody.getStr("message"));
|
||||
}
|
||||
|
||||
JSONObject result = jsonBody.getJSONObject("result");
|
||||
if (result == null) {
|
||||
break;
|
||||
}
|
||||
total = result.getInt("total", total);
|
||||
maxPage = result.getInt("max_page", maxPage);
|
||||
JSONArray data = result.getJSONArray("data");
|
||||
if (CollUtil.isNotEmpty(data)) {
|
||||
rawDataList.addAll(data.stream().map(v -> (JSONObject) v).toList());
|
||||
}
|
||||
log.info("{}人员数据拉取进度: {}/{}", sourceName, rawDataList.size(), total);
|
||||
page++;
|
||||
} while (page <= maxPage);
|
||||
|
||||
return rawDataList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并两个接口数据时按职工号去重,避免同一批次出现重复人员。
|
||||
* 返回值保持第一次出现的数据,用于后续统一映射入库。
|
||||
*/
|
||||
private List<JSONObject> distinctDmpUsers(List<JSONObject> rawDataList) {
|
||||
Map<String, JSONObject> userMap = new LinkedHashMap<>();
|
||||
for (JSONObject raw : rawDataList) {
|
||||
String loginName = raw.getStr("ZGH");
|
||||
if (StrUtil.isBlank(loginName)) {
|
||||
loginName = raw.getStr("ID");
|
||||
}
|
||||
userMap.putIfAbsent(loginName, raw);
|
||||
}
|
||||
return new ArrayList<>(userMap.values());
|
||||
}
|
||||
|
||||
@Async
|
||||
private void updateDict(List<Sys_user_source> userSources) {
|
||||
//判断是否要更新在职状态字典
|
||||
@@ -388,70 +478,7 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
|
||||
|
||||
@Override
|
||||
public Map<String, NutMap> pullFinance() {
|
||||
// 获取配置文件 接口地址 和 token
|
||||
DataCenterProperties.Credential credential = dataCenterProperties.credential("finance");
|
||||
String url = credential.getUrl();
|
||||
String token = credential.getToken();
|
||||
|
||||
List<JSONObject> rawDataList = new ArrayList<>();
|
||||
String year = String.valueOf(DateUtil.thisYear());
|
||||
String month = String.valueOf(DateUtil.thisMonth() + 1);
|
||||
|
||||
int pageNum = 1;
|
||||
int pageSize = 1000;
|
||||
int totalPages = 1;
|
||||
int totalCount = 0;
|
||||
do {
|
||||
HttpRequest httpRequest = HttpUtil.createPost(url);
|
||||
httpRequest.header(Header.CONTENT_TYPE, "application/json");
|
||||
httpRequest.header("Accept-Encoding", "gzip, deflate, br");
|
||||
httpRequest.header("X-H3C-TOKEN", token);
|
||||
Map<String, Object> reqBody = Map.of(
|
||||
"nf", year,
|
||||
"yf", month,
|
||||
"pageNum", pageNum,
|
||||
"pageSize", pageSize
|
||||
);
|
||||
httpRequest.body(JSONUtil.toJsonStr(reqBody));
|
||||
|
||||
JSONObject resp = JSONUtil.parseObj(httpRequest.execute().body());
|
||||
if (resp.getInt("code") != 0) {
|
||||
throw new BaseException("获取财务数据失败,错误码: " + resp.getInt("code") + ";错误原因:" + resp.getStr("msg"));
|
||||
}
|
||||
|
||||
JSONObject data = resp.getJSONObject("data");
|
||||
if (pageNum == 1) {
|
||||
totalCount = data.getInt("total", 0);
|
||||
// totalPages = data.getInt("pages", 0);
|
||||
totalPages = (int) Math.ceil((double) totalCount / pageSize);
|
||||
}
|
||||
|
||||
JSONArray records = data.getJSONArray("records");
|
||||
if (CollUtil.isNotEmpty(records)) {
|
||||
rawDataList.addAll(records.stream().map(v -> (JSONObject) v).toList());
|
||||
log.info("数据拉取进度: {}/{}", rawDataList.size(), totalCount);
|
||||
}
|
||||
pageNum++; // 只加页码
|
||||
} while (pageNum <= totalPages);
|
||||
|
||||
// 接口数据输出
|
||||
log.info("数据拉取结果: {}", rawDataList);
|
||||
|
||||
// 最后结果数据
|
||||
Map<String, NutMap> result = new HashMap<>();
|
||||
|
||||
Map<String, String> api2db = Arrays.stream(Api2FinanceFiledMap.values())
|
||||
.collect(Collectors.toMap(e -> e.apiField, e -> e.dbColumn));
|
||||
|
||||
for (JSONObject row : rawDataList) {
|
||||
NutMap nutMap = DataCenterUtil.mapJsonToBean(row, NutMap.class, api2db);
|
||||
result.put(nutMap.getString("loginname"), nutMap);
|
||||
}
|
||||
|
||||
// 输出结果
|
||||
log.info("财务数据拉取转换结果: {}", result);
|
||||
|
||||
log.info("数据拉取完成,共拉取 {} 条数据", result.size());
|
||||
return result;
|
||||
// 旧数据中心财务接口已停用,避免继续调用旧token/code模式接口。
|
||||
throw new BaseException("旧数据中心财务拉取接口已停用");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user