增加服务端exception与schedule扥类文件

This commit is contained in:
renhao02 2025-02-28 17:08:09 +08:00
parent 54df592222
commit 6812c00e95
9 changed files with 3151 additions and 0 deletions

View File

@ -0,0 +1,12 @@
package com.aisino.iles.lawenforcement.exception;
public class DataSyncException extends RuntimeException {
public DataSyncException(String message) {
super(message);
}
public DataSyncException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,16 @@
package com.aisino.iles.lawenforcement.schedule.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* application 属性schedule.enabled设置为true的时候,开启调度任务
*/
@Configuration
@EnableScheduling
@ConditionalOnProperty(prefix = "scheduler", name = "enabled", havingValue = "true")
public class SchedulerConfig {
}

View File

@ -0,0 +1,520 @@
package com.aisino.iles.lawenforcement.schedule.service;
import com.aisino.iles.common.util.StringUtils;
import com.aisino.iles.lawenforcement.model.Agency;
import com.aisino.iles.lawenforcement.repository.AgencyRepository;
import com.aisino.iles.lawenforcement.service.AuthService;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.smartlx.sso.client.model.AccessToken;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.util.*;
import java.util.stream.Collectors;
/**
* 同步执法机构信息数据
*/
@Service
@Slf4j
public class AgencyScheduleService {
private final AgencyRepository agencyRepository;
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
private final AuthService authService; // 用于获取和刷新令牌
@Value("${third-party.agency.query:}")
private String agencyUrl;
@Value("${third-party.enterprise.yddh:}") // 使用正确的配置项获取令牌标识
private String agencyTokenMobilePhone;
public AgencyScheduleService(AgencyRepository agencyRepository, RestTemplate restTemplate, ObjectMapper objectMapper, AuthService authService) {
this.agencyRepository = agencyRepository;
this.restTemplate = restTemplate;
this.objectMapper = objectMapper;
this.authService = authService;
}
@Scheduled(cron = "${scheduler.task.agency.cron.expression:0 0 1 * * ?}")
@Transactional
public void scheduleTask() {
log.info("开始执行执法机构信息同步任务...");
if (agencyUrl == null || agencyUrl.isEmpty()) {
log.error("执法机构API URL (third-party.agency.query) 未配置.");
return;
}
if (agencyTokenMobilePhone == null || agencyTokenMobilePhone.isEmpty()) {
log.error("执法机构API令牌IDNO (third-party.enterprise.idno) 未配置.");
return;
}
try {
// 单次请求获取所有 dwlb=1 的机构信息
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("page", 1);
requestBody.put("limit", 4000); // 设置较大的限制以获取所有数据根据实际情况调整
Map<String, String> entity = new HashMap<>();
entity.put("dwlb", "1"); // 只获取 dwlb=1 的机构
requestBody.put("entity", entity);
log.info("准备从API获取所有 dwlb=1 的机构数据. URL: {}, TokenIDNO: {}", agencyUrl, agencyTokenMobilePhone);
String responseBody = fetchDataFromApi(requestBody, agencyUrl);
List<ApiAgency> allApiAgencies = new ArrayList<>();
if (responseBody != null) {
ApiResponse apiResponse = objectMapper.readValue(responseBody, ApiResponse.class);
if (apiResponse != null && apiResponse.isSuccess() && apiResponse.getData() != null) {
allApiAgencies.addAll(apiResponse.getData().getList());
// 检查是否需要分页获取
int totalPages = apiResponse.getData().getTotalPage();
int currentPage = 1;
// 如果有多页数据继续获取剩余页
while (currentPage < totalPages) {
currentPage++;
requestBody.put("page", currentPage);
log.info("获取第 {} 页机构数据,共 {} 页", currentPage, totalPages);
String pageResponseBody = fetchDataFromApi(requestBody, agencyUrl);
if (pageResponseBody != null) {
ApiResponse pageApiResponse = objectMapper.readValue(pageResponseBody, ApiResponse.class);
if (pageApiResponse != null && pageApiResponse.isSuccess() && pageApiResponse.getData() != null) {
allApiAgencies.addAll(pageApiResponse.getData().getList());
} else {
log.warn("获取第 {} 页数据失败. Code: {}, Msg: {}",
currentPage,
pageApiResponse != null ? pageApiResponse.getCode() : "N/A",
pageApiResponse != null ? pageApiResponse.getMsg() : "N/A");
}
}
}
log.info("共获取 {} 页数据,总计 {} 条机构记录", totalPages, allApiAgencies.size());
} else {
log.warn("API响应表明操作未成功或数据为空. Code: {}, Msg: {}",
apiResponse != null ? apiResponse.getCode() : "N/A",
apiResponse != null ? apiResponse.getMsg() : "N/A");
}
}
if (allApiAgencies.isEmpty()) {
log.info("未从API获取到任何执法机构数据。");
return;
}
// 去重 gajgjgdm 为准
List<ApiAgency> distinctApiAgencies = allApiAgencies.stream()
.filter(apiAgency -> apiAgency.getGajgjgdm() != null)
.collect(Collectors.toMap(ApiAgency::getGajgjgdm, p -> p, (p, q) -> p))
.values()
.stream()
.toList();
log.info("从API获取到 {} 条去重后的执法机构数据,准备进行处理...", distinctApiAgencies.size());
// 筛选出 01610100000000000 及其所有下级机构
String rootAgencyCode = "01610100000000000";
// 构建机构代码到API机构的映射方便后续处理
Map<String, ApiAgency> apiAgencyMap = distinctApiAgencies.stream()
.collect(Collectors.toMap(ApiAgency::getGajgjgdm, a -> a, (a1, a2) -> a1));
// 找出所有属于 01610100000000000 下级的机构包括自身
Set<String> relevantAgencyCodes = new HashSet<>();
relevantAgencyCodes.add(rootAgencyCode); // 添加根机构自身
// 递归查找所有下级机构
findAllChildAgencies(rootAgencyCode, apiAgencyMap, relevantAgencyCodes);
log.info("筛选出 {} 条与根机构 {} 相关的机构数据", relevantAgencyCodes.size(), rootAgencyCode);
// 筛选出相关的机构数据
List<ApiAgency> relevantApiAgencies = distinctApiAgencies.stream()
.filter(agency -> relevantAgencyCodes.contains(agency.getGajgjgdm()))
.toList();
Map<String, Agency> processedAgencies = new HashMap<>();
List<Agency> agenciesToSave = new ArrayList<>();
// 先处理所有机构的基本信息并存入 processedAgencies
for (ApiAgency apiAgency : relevantApiAgencies) {
if (apiAgency.getGajgmc() == null || apiAgency.getGajgmc().isEmpty()) {
log.warn("API返回的机构数据缺少 gajgmc (机构名称),跳过此条记录: {}", apiAgency);
continue;
}
// 检查 gajgjgdm 是否为空因为它仍然是重要的属性
if (apiAgency.getGajgjgdm() == null) {
log.warn("API返回的机构数据缺少 gajgjgjgdm (机构代码),但仍会尝试按名称处理: {}", apiAgency);
// 决定是否跳过或者允许没有代码的机构如果业务允许
continue; // 如果 gajgjgdm 必须存在则取消注释此行
}
Agency agency = agencyRepository.findByAgencyCode(apiAgency.getGajgjgdm()).orElse(new Agency());
agency.setAgencyName(apiAgency.getGajgmc());
agency.setAgencyCode(apiAgency.getGajgjgdm()); // 执法机构代码即使通过名称找到也用API的code更新
agency.setOrderNum(apiAgency.getXssx()); // 排序号
// 执法机构简码 - 使用StringUtils.trimEven0
agency.setAgencySimpleCode(generateAgencySimpleCode(apiAgency.getGajgjgdm()));
agenciesToSave.add(agency);
processedAgencies.put(agency.getAgencyCode(), agency);
}
// 再次遍历设置父级关系
for (Agency currentAgency : agenciesToSave) {
ApiAgency correspondingApiAgency = relevantApiAgencies.stream()
.filter(aa -> currentAgency.getAgencyCode().equals(aa.getGajgjgdm()))
.findFirst()
.orElse(null);
if (correspondingApiAgency != null && correspondingApiAgency.getSjgajgjgdm() != null) {
Agency parentAgency = processedAgencies.get(correspondingApiAgency.getSjgajgjgdm());
if (parentAgency != null) {
currentAgency.setParent(parentAgency);
} else {
// 如果在本次同步的数据中找不到父级尝试从数据库中查找已存在的父级
Optional<Agency> parentInDb = agencyRepository.findByAgencyCode(correspondingApiAgency.getSjgajgjgdm());
parentInDb.ifPresent(currentAgency::setParent);
if (parentInDb.isEmpty()) {
log.warn("机构 {} (代码: {}) 的上级机构 (代码: {}) 在本次同步和数据库中均未找到。",
currentAgency.getAgencyName(), currentAgency.getAgencyCode(), correspondingApiAgency.getSjgajgjgdm());
}
}
}
}
// 计算并设置执法机构级别
Map<String, Integer> agencyLevelsCache = new HashMap<>();
int anchorLevel = 2;
// 第一遍递归计算并缓存所有级别
for (Agency agency : agenciesToSave) {
computeAndCacheLevelRecursive(agency, agencyLevelsCache, rootAgencyCode, anchorLevel, processedAgencies);
}
// 第二遍从缓存中设置级别到实体
for (Agency agency : agenciesToSave) {
agency.setAgencyLevel(agencyLevelsCache.get(agency.getAgencyCode()));
}
// 根据级别设置是否为叶子节点
for (Agency agency : agenciesToSave) {
agency.setLeaf(processedAgencies.values().stream()
.noneMatch(a -> a.getParent() != null && a.getParent().getAgencyCode().equals(agency.getAgencyCode())));
}
// 在所有父子关系和级别设置完毕后计算路径
for (Agency agency : agenciesToSave) {
agency.setAgencyPath(calculateAgencyPath(agency, processedAgencies, agencyRepository));
}
if (!agenciesToSave.isEmpty()) {
agencyRepository.saveAll(agenciesToSave);
log.info("成功同步 {} 条执法机构信息到数据库。", agenciesToSave.size());
} else {
log.info("没有需要保存的执法机构信息。");
}
} catch (JsonProcessingException e) {
log.error("解析API响应时发生JSON处理错误。", e);
} catch (Exception e) {
log.error("执行执法机构信息同步任务时发生未知错误。", e);
}
log.info("执法机构信息同步任务结束。");
}
/**
* 递归查找所有下级机构
*
* @param agencyCode 当前机构代码
* @param apiAgencyMap 所有API机构的映射
* @param collectedCodes 收集的相关机构代码集合
*/
private void findAllChildAgencies(String agencyCode, Map<String, ApiAgency> apiAgencyMap, Set<String> collectedCodes) {
// 查找所有直接下级机构
apiAgencyMap.values().stream()
.filter(agency -> agencyCode.equals(agency.getSjgajgjgdm()))
.forEach(childAgency -> {
String childCode = childAgency.getGajgjgdm();
if (childCode != null && !collectedCodes.contains(childCode)) {
collectedCodes.add(childCode);
// 递归查找子机构的下级
findAllChildAgencies(childCode, apiAgencyMap, collectedCodes);
}
});
}
/**
* 从外部API获取数据包含令牌刷新和重试逻辑
*
* @param requestBody 请求体
* @param url API的URL
* @return API响应体字符串如果失败则返回null或抛出异常
* @throws JsonProcessingException 如果请求体序列化失败
*/
@SneakyThrows
private String fetchDataFromApi(Map<String, Object> requestBody, String url) throws JsonProcessingException {
int maxRetries = 2; // 允许一次初始尝试和一次重试
for (int attempt = 1; attempt <= maxRetries; attempt++) {
AccessToken accessToken = authService.getTokenBackend(agencyTokenMobilePhone);
if (accessToken == null || accessToken.getAccess_token() == null) {
log.error("获取访问令牌失败 (尝试 {}/{})URL: {}. 请检查AuthService配置和令牌提供者。", attempt, maxRetries, url);
throw new RuntimeException("获取API调用的访问令牌失败。");
}
String currentToken = accessToken.getAccess_token();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(currentToken);
HttpEntity<String> entity = new HttpEntity<>(objectMapper.writeValueAsString(requestBody), headers);
ResponseEntity<String> responseEntity;
try {
log.info("尝试API调用 (尝试 {}/{}) 到 URL: {},请求体: {}", attempt, maxRetries, url, requestBody);
responseEntity = restTemplate.postForEntity(url, entity, String.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
log.info("API调用成功 (尝试 {}/{})URL: {}", attempt, maxRetries, url);
return responseEntity.getBody();
} else {
log.error("API调用失败 (尝试 {}/{}),状态码 {}: {}. URL: {}, 请求体: {}",
attempt, maxRetries, responseEntity.getStatusCode(), responseEntity.getBody(), url, requestBody);
// 对于非2xx但非401的错误当前不重试
return null; // 或根据需要抛出特定异常
}
} catch (HttpClientErrorException e) {
if (e.getStatusCode() == HttpStatus.UNAUTHORIZED) {
log.warn("API调用未授权 (尝试 {}/{}),可能令牌已过期. URL: {}. 正在尝试刷新令牌...",
attempt, maxRetries, url);
if (attempt < maxRetries) {
try {
authService.refreshTokenBackend(accessToken.getAccess_token(), accessToken.getToken_type(), accessToken.getRefresh_token(), agencyTokenMobilePhone); // 请求刷新令牌
log.info("请求刷新令牌成功。下一次尝试将使用新令牌。");
// 循环将继续下一次迭代将再次调用getTokenBackendByYddh
} catch (Exception refreshException) {
log.error("请求刷新令牌期间发生异常: {}. 中止对URL: {} 的重试。",
refreshException.getMessage(), url, refreshException);
throw new RuntimeException("API调用未授权后请求刷新令牌失败。", refreshException);
}
} else {
log.error("API调用未授权尝试 {} 次后仍然失败 (已达最大重试次数)URL: {}.", attempt, url);
throw new RuntimeException("多次重试后API调用因授权问题失败URL: " + url, e);
}
} else {
// 其他 HttpClientErrorException (非401的4xx或5xx错误)
log.error("API调用时发生HttpClientErrorException (尝试 {}/{})URL {}: {} - {}. 请求体: {}",
attempt, maxRetries, url, e.getStatusCode(), e.getResponseBodyAsString(), requestBody, e);
throw e; // 重新抛出其他HTTP客户端错误
}
} catch (RestClientException e) {
// 一般的 RestClientException (例如网络问题)
log.error("API调用时发生RestClientException (尝试 {}/{})URL {}: {}. 请求体: {}",
attempt, maxRetries, url, e.getMessage(), requestBody, e);
if (attempt == maxRetries) { // 如果是最后一次尝试则抛出异常
throw e;
}
log.warn("发生RestClientException后进行重试尝试 {}/{}URL: {}", attempt, maxRetries, url);
// 可选在重试网络相关错误前添加短暂延迟
// try { Thread.sleep(1000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); }
}
}
// 如果循环结束仍未返回或抛出异常 (理论上不应发生)
log.error("多次重试后未能成功从API获取数据URL: {}", url);
throw new RuntimeException("多次重试后未能从API获取数据URL: " + url);
}
/**
* 生成执法机构简码
*
* @param gajgjgdm 完整的执法机构代码
* @return 生成的执法机构简码
*/
private String generateAgencySimpleCode(String gajgjgdm) {
if (gajgjgdm == null || gajgjgdm.isEmpty()) {
return null;
}
return StringUtils.trimEven0(gajgjgdm);
}
/**
* 计算并生成机构的层级路径字符串
* 路径由机构代码组成 '.' 分隔从最高层级到当前机构
* 例如root.parent.child.currentAgencyCode
*
* @param currentAgency 需要计算路径的当前机构实体父级关系应已在此实体中设置
* @param processedAgencies 当前批次中已处理的机构映射 (agencyCode -> Agency)此方法当前未使用但保留以备将来扩展
* @param agencyRepository 机构仓库此方法当前未使用但保留以备将来扩展
* @return 生成的机构路径字符串如果无法生成例如机构或其代码为空则返回null
* 如果达到最大层级深度则返回以 "ERROR_MAX_DEPTH_" 开头的路径
*/
private String calculateAgencyPath(Agency currentAgency, Map<String, Agency> processedAgencies, AgencyRepository agencyRepository) {
if (currentAgency == null || currentAgency.getAgencyCode() == null) {
log.warn("计算机构路径时,当前机构或机构代码为空。");
return null;
}
// Placeholder log removed as we are implementing the logic now.
List<String> pathParts = new ArrayList<>();
Agency tempAgency = currentAgency;
int depth = 0;
final int maxDepth = 20; // Max depth to prevent infinite loops in case of data issues
while (tempAgency != null && depth < maxDepth) {
if (tempAgency.getAgencyCode() == null) {
log.warn("在为起始机构 '{}' ({}) 计算路径时,遇到机构代码为空的机构。当前已构建路径: [{}]. 跳过此路径部分。",
currentAgency.getAgencyName(), currentAgency.getAgencyCode(), String.join(".", pathParts));
break; // 或根据需求处理例如对此空代码使用占位符
}
pathParts.add(tempAgency.getAgencySimpleCode());
tempAgency = tempAgency.getParent(); // 正确地向上遍历父级链
depth++;
}
if (depth >= maxDepth) {
log.error("calculateAgencyPath: 机构 '{}' (代码: {}) 计算路径时达到最大深度 ({})。可能存在循环依赖或层级过深。已构建路径: [{}]",
maxDepth, currentAgency.getAgencyName(), currentAgency.getAgencyCode(), String.join(".", pathParts));
// 返回一个独特的错误路径或根据需求处理例如返回已构建路径并添加错误前缀
Collections.reverse(pathParts); // 反转已有的路径部分使其顺序正确
return "ERROR_MAX_DEPTH_" + String.join(".", pathParts);
}
if (pathParts.isEmpty()) {
log.warn("calculateAgencyPath: 机构 '{}' (代码: {}) 的路径部分列表为空。将其自身代码作为路径返回。", currentAgency.getAgencyName(), currentAgency.getAgencyCode());
return currentAgency.getAgencyCode(); // 理想情况下如果当前机构及其代码有效则不应发生此情况
}
Collections.reverse(pathParts);
return String.join(".", pathParts);
}
/**
* 递归计算并缓存机构级别
* "西安市应急管理局" 为级别2其子级为父级级别+1
*
* @param agency 当前处理的机构
* @param levelCache 存储已计算级别的缓存 (agencyCode -> level)
* @param anchorAgencyCode 锚点机构代码
* @param anchorLevel 锚点机构的级别
* @param allAgenciesMap 当前批次中已处理的机构映射 (agencyCode -> Agency)用于查找父级实体
*/
private void computeAndCacheLevelRecursive(Agency agency, Map<String, Integer> levelCache,
String anchorAgencyCode, int anchorLevel,
Map<String, Agency> allAgenciesMap) {
if (agency == null || agency.getAgencyCode() == null || levelCache.containsKey(agency.getAgencyCode())) {
return; // 无效机构或已处理
}
// 锚点机构处理
if (anchorAgencyCode.equals(agency.getAgencyCode())) {
levelCache.put(agency.getAgencyCode(), anchorLevel);
return;
}
// 非锚点机构依赖父级级别
Agency parent = agency.getParent(); // 父级关系应已在此前步骤中设置
if (parent == null) {
// 没有父级且不是锚点机构无法通过此逻辑确定级别
log.warn("机构 '{}' ({}) 非锚点且无父级,无法基于锚点逻辑确定其级别。",
agency.getAgencyName(), agency.getAgencyCode());
levelCache.put(agency.getAgencyCode(), null); // 标记为无法计算或设为默认值
return;
}
// 确保父级级别已计算递归调用
computeAndCacheLevelRecursive(parent, levelCache, anchorAgencyCode, anchorLevel, allAgenciesMap);
Integer parentLevel = levelCache.get(parent.getAgencyCode());
if (parentLevel != null) {
levelCache.put(agency.getAgencyCode(), parentLevel + 1);
} else {
// 父级级别未能确定则子级也无法确定
log.warn("未能确定父级机构 '{}' ({}) 的级别,因此无法确定子级机构 '{}' ({}) 的级别。",
parent.getAgencyName(), parent.getAgencyCode(),
agency.getAgencyName(), agency.getAgencyCode());
levelCache.put(agency.getAgencyCode(), null); // 标记为无法计算或设为默认值
}
}
// --- Inner DTO classes for API Response ---
@Getter
@Setter
private static class ApiResponse {
private String code;
private boolean success;
private ApiData data;
private String msg;
}
@Getter
@Setter
private static class ApiData {
private int offset;
private int limit;
@JsonAlias("totalCount")
private String totalCountStr;
private List<ApiAgency> list;
@JsonProperty("totalPage")
private int totalPage;
public int getTotalCount() {
try {
return Integer.parseInt(totalCountStr);
} catch (NumberFormatException e) {
return 0;
}
}
}
@Getter
@Setter
@ToString
private static class ApiAgency {
private String ywlsh;
@JsonProperty("gajgjgdm")
private String gajgjgdm;
@JsonProperty("sjgajgjgdm")
private String sjgajgjgdm;
@JsonProperty("gajgmc")
private String gajgmc;
@JsonProperty("xssx")
private Integer xssx;
private String sjztdm;
@JsonProperty("gajgmcjc")
private String gajgmcjc;
private String dwlb;
private String xzqhdm;
@JsonProperty("gajgmclbdm")
private String gajgmclbdm;
@JsonProperty("gajgbmlbdm")
private String gajgbmlbdm;
private Integer subnum;
}
}

View File

@ -0,0 +1,230 @@
package com.aisino.iles.lawenforcement.schedule.service;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aisino.iles.lawenforcement.model.Enterprise;
import com.aisino.iles.lawenforcement.model.Enterprise_;
import com.aisino.iles.lawenforcement.repository.*;
import com.aisino.iles.lawenforcement.service.AuthService;
import com.smartlx.sso.client.model.AccessToken;
import com.smartlx.sso.client.properties.SsoClientProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* 企业设备接入信息定时任务
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class EnterpriseJoinScheduleService {
private final EnterpriseRepository enterpriseRepository;
private final EnterpriseCameraRepository enterpriseCameraRepository;
private final EnterpriseWarnRepository enterpriseWarnRepository;
private final AuthService authService;
private final SsoClientProperties ssoClientProperties;
@Value("${third-party.enterprise.yddh:}") // 使用正确的配置项获取令牌标识
private String tokenMobilePhone;
@Value("${third-party.enterprise.selfInsAndSelfReport:}")
private String selfInsAndSelfReportUrl;
public Page<Enterprise> pageEnterprise(int page, int limit) {
Specification<Enterprise> spec = (root, query, cb) -> cb.and(cb.equal(root.get(Enterprise_.delFlag), 0), cb.isNotNull(root.get(Enterprise_.unifiedSocialCode)));
return enterpriseRepository.findAll(spec, PageRequest.of(page, limit));
}
/**
* 企业摄像头信息和预警信息同步任务
* 每天定时执行通过配置文件动态指定 cron 表达式
*/
@Scheduled(cron = "0 0 1 * * ?")
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void scheduledUpdateEnterpriseTask() {
log.info("===== 开始执行企业摄像头信息和预警信息同步任务 =====");
int page = 0;
final int limit = 2000;
Page<Enterprise> pageResult;
do {
// 分页查询企业信息
pageResult = pageEnterprise(page, limit);
List<Enterprise> enterprises = pageResult.getContent();
if (!enterprises.isEmpty()) {
// 更新企业摄像头信息和预警信息
batchUpdate(enterprises);
log.info("已处理企业数据page={}, size={}", page, enterprises.size());
}
page++;
} while (pageResult.hasNext());
log.info("===== 企业摄像头信息和预警信息同步任务完成 =====");
}
@Transactional(propagation = Propagation.MANDATORY)
public void batchUpdate(List<Enterprise> enterprises) {
List<String> unifiedSocialCodes = enterprises.stream().map(Enterprise::getUnifiedSocialCode).collect(Collectors.toList());
List<Map<String, Object>> cameraList = enterpriseCameraRepository.countGroupByUnifiedSocialCode(unifiedSocialCodes);
Map<String, Long> cameraMap = cameraList.stream().collect(Collectors.toMap(row -> (String) row.get("unified_social_code"), row -> ((Number) row.get("num")).longValue()));
// List<Map<String, Object>> warnList = enterpriseWarnRepository.countGroupByUnifiedSocialCode(unifiedSocialCodes);
// Map<String, Long> warnMap = warnList.stream().collect(Collectors.toMap(row -> (String) row.get("unified_social_code"), row -> ((Number) row.get("num")).longValue()));
// 批量更新视频接入状态
enterprises.forEach(enterprise -> {
Long count = cameraMap.getOrDefault(enterprise.getUnifiedSocialCode(), 0L);
enterprise.setVideoAccess(count > 0 ? "1" : "0");
// Long count2 = warnMap.getOrDefault(enterprise.getUnifiedSocialCode(), 0L);
// enterprise.setPermitAccess(count2 > 0 ? "1" : "0");
});
enterpriseRepository.saveAll(enterprises);
}
/**
* 企业感知信息同步任务
* 每天定时执行通过配置文件动态指定 cron 表达式
*/
@Scheduled(cron = "0 0 2 * * ?")
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void scheduledUpdateEnterpriseTask2() {
log.info("===== 开始执行企业感知设备信息同步任务 =====");
int page = 0;
final int limit = 2000;
Page<Enterprise> pageResult;
do {
// 分页查询企业信息
pageResult = pageEnterprise(page, limit);
List<Enterprise> enterprises = pageResult.getContent();
if (!enterprises.isEmpty()) {
// 更新企业感知设备信息
batchUpdate2(enterprises);
log.info("已处理企业数据page={}, size={}", page, enterprises.size());
}
page++;
} while (pageResult.hasNext());
log.info("===== 企业感知设备信息同步任务完成 =====");
}
@Transactional(propagation = Propagation.MANDATORY)
public void batchUpdate2(List<Enterprise> enterprises) {
String body = HttpUtil.createGet("http://10.22.245.227:1084/dah-api/public/monitor/units/list").execute().body();
log.info("企业感知设备信息body={}", body);
JSONObject jsonObject = JSONUtil.parseObj(body);
Long code = jsonObject.getLong("code");
if (code == 200) {
List<String> socialCodes = jsonObject.getJSONArray("data")
.stream()
.filter(JSONObject.class::isInstance)
.map(obj -> ((JSONObject) obj).getStr("socialCode"))
.collect(Collectors.toList());
// 批量更新企业感知设备信息
enterprises.forEach(enterprise -> {
String unifiedSocialCode = enterprise.getUnifiedSocialCode();
boolean hasPerceptionAccess = socialCodes.contains(unifiedSocialCode);
enterprise.setPerceptionAccess(hasPerceptionAccess ? "1" : "0");
});
}
enterpriseRepository.saveAll(enterprises);
}
/**
* 企业自查自报信息同步任务
* 每天定时执行通过配置文件动态指定 cron 表达式
*/
@Scheduled(cron = "0 0 3 * * ?")
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void scheduledUpdateEnterpriseTask3() {
if (tokenMobilePhone == null || tokenMobilePhone.isEmpty()) {
log.error("API令牌YDDH (third-party.enterprise.yddh) 未配置.");
return;
}
log.info("===== 开始执行企业自查自报信息同步任务 =====");
int page = 0;
final int limit = 2000;
Page<Enterprise> pageResult;
do {
// 分页查询企业信息
pageResult = pageEnterprise(page, limit);
List<Enterprise> enterprises = pageResult.getContent();
if (!enterprises.isEmpty()) {
// 更新企业自查自报信息
batchUpdate3(enterprises);
log.info("已处理企业数据page={}, size={}", page, enterprises.size());
}
page++;
} while (pageResult.hasNext());
log.info("===== 企业自查自报信息同步任务完成 =====");
}
@Transactional(propagation = Propagation.MANDATORY)
public void batchUpdate3(List<Enterprise> enterprises) {
try {
AccessToken tokenBackend = authService.getTokenBackend(tokenMobilePhone);
String accessToken = tokenBackend.getAccess_token();
String tokenType = tokenBackend.getToken_type();
String clientId = ssoClientProperties.getClientId();
for (Enterprise enterprise : enterprises) {
try {
Map<String, Object> param = new HashMap<>();
param.put("limit", "1");
param.put("page", 1);
Map<String, String> entity = new HashMap<>();
entity.put("unifiedSocialCode", enterprise.getUnifiedSocialCode());
param.put("entity", entity);
log.info("url{}, token{}, clientId{}", selfInsAndSelfReportUrl, accessToken, clientId);
String body = HttpRequest.post(selfInsAndSelfReportUrl)
.header("Content-Type", "application/json")
.header("Authorization", tokenType + " " + accessToken)
.header("appId", clientId)
.body(JSONUtil.toJsonStr(param))
.execute()
.body();
JSONObject jsonObject = JSONUtil.parseObj(body);
log.info("企业自查自报信息结果:{}", jsonObject);
if (jsonObject.getBool("success")) {
Long totalCount = Long.valueOf(jsonObject.getJSONObject("data").getStr("totalCount"));
enterprise.setInfoAccess(totalCount > 0 ? "1" : "0");
}
} catch (Exception e) {
log.error("处理企业 {} 时出错: {}", enterprise.getUnitName(), e.getMessage());
}
}
enterpriseRepository.saveAll(enterprises);
} catch (Exception e) {
log.error("获取 Token 失败: {}", e.getMessage());
}
}
}

View File

@ -0,0 +1,699 @@
package com.aisino.iles.lawenforcement.schedule.service;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import com.aisino.iles.lawenforcement.model.*;
import com.aisino.iles.lawenforcement.model.dto.IndustryEnterpriseDto;
import com.aisino.iles.lawenforcement.model.dto.WaferEnterpriseDto;
import com.aisino.iles.lawenforcement.repository.*;
import com.aisino.iles.lawenforcement.service.AuthService;
import com.aisino.iles.lawenforcement.service.DictInterfaceService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.smartlx.sso.client.model.AccessToken;
import com.smartlx.sso.client.properties.SsoClientProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* 企业信息定时任务
*/
@Service
@Slf4j
public class EnterprisePoniteScheduleService {
private final EnterpriseRepository enterpriseRepo;
private final EnterpriseHistoryRepository enterpriseHistoryRepo;
private final AgencyRepository agencyRepo;
private final AuthService authService;
private final TransactionTemplate transactionTemplate;
private final String mobilePhone;
private final DictInterfaceService dictService;
private String accessToken;
private String tokenType;
private String refreshToken;
private final ObjectMapper objectMapper;
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public EnterprisePoniteScheduleService(EnterpriseRepository enterpriseRepo,
EnterpriseHistoryRepository enterpriseHistoryRepo,
AgencyRepository agencyRepo,
AuthService authService,
ObjectMapper objectMapper,
@Value("${third-party.enterprise.yddh:}") String mobilePhone,
TransactionTemplate transactionTemplate,
DictInterfaceService dictService) {
this.enterpriseRepo = enterpriseRepo;
this.enterpriseHistoryRepo = enterpriseHistoryRepo;
this.agencyRepo = agencyRepo;
this.authService = authService;
this.objectMapper = objectMapper;
this.mobilePhone = mobilePhone;
this.transactionTemplate = transactionTemplate;
this.dictService = dictService;
}
/**
* 工作台信息导入
* 每天10点执行一次
* (cron = "0 0 15 * * ?")
* (cron = "${scheduler.expression}")
* (fixedRate = 120000)
*/
@Scheduled(cron = "${scheduler.task.enterprise.cron.expression}")
public void scheduledEnterpriseTask() {
getToken();
dictService.getDictItem("YJ_CODE_9017", tokenType, accessToken);
//enterpriseTask();
}
/**
* 工作台信息导入
* 每天15点执行一次
* (cron = "0 15 * * * ?")
* (cron = "${scheduler.expression}")
* (fixedRate = 120000)
*/
// @Scheduled(cron = "0 * * * * ?")
@Scheduled(cron = "${scheduler.task.waferEnterprise.cron.expression}")
public void scheduledWaferEnterpriseTask() {
getToken();
dictService.getDictItem("YJ_CODE_9017", tokenType, accessToken);
enterpriseTask();
enterpriseWaferTask();
}
/**
* 导入企业信息
*/
public void enterpriseTask() {
log.info("开始导入企业信息...");
int page = 1;
boolean b = updateOrImportIndustryEnterprise(page);
while (b) {
page++;
b = updateOrImportIndustryEnterprise(page);
}
log.info("企业信息导入完成...");
}
/**
* 危化导入企业信息
*/
public void enterpriseWaferTask() {
log.info("开始导入危化企业信息...");
int page = 1;
boolean b = updateOrImportWaferEnterprise(page);
while (b) {
page++;
b = updateOrImportWaferEnterprise(page);
}
log.info("危化企业信息导入完成...");
}
/**
* 获取token
*/
private void getToken() {
try {
AccessToken accessTokenObj = authService.getTokenBackend(mobilePhone);
if (accessTokenObj != null) {
accessToken = accessTokenObj.getAccess_token();
tokenType = accessTokenObj.getToken_type();
refreshToken = accessTokenObj.getRefresh_token();
log.info("获取token成功");
} else {
log.error("获取token失败返回为null");
throw new RuntimeException("无法获取有效的访问令牌");
}
} catch (Exception e) {
log.error("获取token失败", e);
throw new RuntimeException("无法获取有效的访问令牌", e);
}
}
/**
* 刷新token
*/
private void refreshToken() {
try {
authService.refreshTokenBackend(accessToken, tokenType, refreshToken, mobilePhone);
// 刷新后重新获取token
getToken();
log.info("刷新token成功");
} catch (Exception e) {
log.error("刷新token失败尝试重新获取token", e);
getToken();
}
}
@Transactional
public boolean updateOrImportIndustryEnterprise(int page) {
boolean flag = false;
try {
JSONObject jsonBody = new JSONObject();
JSONObject jsonPram = new JSONObject();
jsonBody.set("method", "GET");
jsonBody.set("jsonObject", jsonPram);
jsonBody.set("pageNum", page);
jsonBody.set("pageSize", 1000);
jsonBody.set("path", "/edataservice/api/gmqyxx");
jsonBody.set("secret", "805cd25953b1ba8852aac00564fe163213567518a5a509a849d8384b7b090b70");
String body = HttpUtil.createPost("http://10.22.245.216:29999/jeecg-data-service/edataservice/api/")
.header("Content-Type", "application/json")
.body(jsonBody.toString())
.execute()
.body();
JsonNode jsonNode = objectMapper.readValue(body, JsonNode.class);
if (jsonNode.has("code") && 200 == jsonNode.get("code").asInt() && jsonNode.has("result")) {
JsonNode data = objectMapper.readValue(jsonNode.get("result").toString(), JsonNode.class);
if (null != data && data.has("records")) {
JsonNode arrNode = data.get("records");
if (arrNode.isArray()) {
long current = data.get("current").asLong();
long pages = data.get("pages").asLong();
if (current < pages) flag = true;
List<IndustryEnterpriseDto> dtos = objectMapper.readValue(arrNode.toString(), new TypeReference<>() {});
Set<String> usccSet = dtos.stream().map(IndustryEnterpriseDto::getTyshxydm).filter(StringUtils::hasText).collect(Collectors.toSet());
// 历史企业
List<Enterprise> enterpriseList = enterpriseRepo.findByUnifiedSocialCodeIn(usccSet);
List<Enterprise> enterprises = new ArrayList<>();
log.info("开始处理:{}条数据",dtos.size());
for (IndustryEnterpriseDto dto : dtos) {
if (StringUtils.hasText(dto.getTyshxydm())) {
Enterprise oldLtd = enterpriseList.stream().filter(o -> o.getUnifiedSocialCode().equals(dto.getTyshxydm())).findFirst().orElse(null);
if (null != oldLtd) {
EnterpriseHistory history = new EnterpriseHistory();
BeanUtils.copyProperties(oldLtd, history);
history.setTheType("定时任务修改");
LocalDateTime now = LocalDateTime.now();
history.setHistoryTime(now);
enterpriseHistoryRepo.save(history);
oldLtd.setUnitName(dto.getQymc()); // 企业名称
//oldLtd.setUnitCode(); // 生产经营单位编码
oldLtd.setUnifiedSocialCode(dto.getTyshxydm()); // 统一社会信用代码
if ("0".equals(dto.getScjyztxh())) {
oldLtd.setBusinessStatus("11"); // 营业状态
} else {
oldLtd.setBusinessStatus("13"); // 营业状态
}
Optional.ofNullable(dto.getQxbm()).filter(StringUtils::hasText).flatMap(agencyRepo::findByAgencyCode).ifPresent(oldLtd::setAgency); // 机构
//oldLtd.setRegulatedIndustry(); // 国民经济行业分类
//oldLtd.setAreaComb(); // 注册地址
oldLtd.setDetailedAddress(dto.getDz()); // 注册详细地址
//oldLtd.setOpLocAreaComb(); // 经营地址
oldLtd.setOpLocAddress(dto.getDz()); // 经营详细地址
if (null != dto.getHylb() && "1".equals(dto.getHylb())) {
oldLtd.setIndustryType("7"); // 监管行业
} else {
oldLtd.setIndustryType("6"); // 监管行业
}
oldLtd.setLegalRepresentative(dto.getFddbr()); // 法定代表人姓名
oldLtd.setLegalPhone(dto.getFddbrlxdh()); // 法人联系电话
//oldLtd.setLegalDuty(); // 法定代表人职位
//oldLtd.setOpScope(); // 主营业务
//oldLtd.setAffiliation(); // 行政隶属关系
//oldLtd.setOilExtract(); // 是否石油开采
//oldLtd.setSafetyFocus(); // 是否安全生产监管重点企业
//oldLtd.setIsScaleEnterprise(); // 是否规模以上企业
//oldLtd.setSafetyLic(); // 是否有安全生产许可证
//oldLtd.setProvince(); // 注册地址-
//oldLtd.setCity(); // 注册地址-
//oldLtd.setCounty(); // 注册地址-/
//国民经济行业分类代码国民经济行业分类GB/T 47542017
// if (StringUtils.hasText(dto.getGmjjhyfldm())) {
// String xxdm = dictService.getTopXxdm(dto.getGmjjhyfldm());
// enterprise.setRegulatedIndustry(xxdm);
// String[] ss = xxdm.split("/");
// for (int i = 0; i < ss.length; i++) {
// if (i == 0) enterprise.setEconCategory(ss[i]); // 国民经济行业分类代码
// if (i == 1) enterprise.setEconCategoryTypea(ss[i]); // 国民经济行业分类A型
// if (i == 2) enterprise.setEconCategoryTypeb(ss[i]); // 国民经济行业分类B型
// if (i == 3) enterprise.setEconCategoryTypec(ss[i]); // 国民经济行业分类C型
// }
// }
//oldLtd.setOpLocProvince(); // 经营地址-
//oldLtd.setOpLocCity(); // 经营地址-
oldLtd.setOpLocArea(dto.getQxmc()); // 经营地址-
//oldLtd.setBusinessRating(); // 企业分级
//oldLtd.setBusinessCategory(); // 企业分类
//oldLtd.setPostalCode(); // 邮政编码
if (null != dto.getJjlxxh() && StringUtils.hasText(dto.getJjlxxh())) { // 国民经济类型
String economicType = dto.getJjlxxh();
switch (economicType) {
case "110" -> oldLtd.setEconomicType("1");
case "120" -> oldLtd.setEconomicType("2");
case "130" -> oldLtd.setEconomicType("3");
case "140" -> oldLtd.setEconomicType("4");
case "150" -> oldLtd.setEconomicType("5");
case "160" -> oldLtd.setEconomicType("6");
case "170" -> oldLtd.setEconomicType("7");
case "190" -> oldLtd.setEconomicType("8");
case "290" -> oldLtd.setEconomicType("9");
case "310" -> oldLtd.setEconomicType("10");
case "330" -> oldLtd.setEconomicType("11");
case "159" -> oldLtd.setEconomicType("12");
}
}
//oldLtd.setLegalPersonIdType(); // 法定代表人证件类型
//oldLtd.setLegalPersonIdNumber(); // 法定代表人证件号码
//oldLtd.setIsInChemicalPark(); // 是否位于化工园区
//oldLtd.setExpiryDate(); // 营业执照有效期
//oldLtd.setOrgCode(); // 组织机构代码
oldLtd.setUnitScale(dto.getQygm()); // 企业规模
//oldLtd.setEstablishmentDate(); // 成立日期
//oldLtd.setRegisteredCapital(); // 注册资本万元
Optional.ofNullable(dto.getJd()).filter(StringUtils::hasText).ifPresent(oldLtd::setLongitude); // 经度
Optional.ofNullable(dto.getWd()).filter(StringUtils::hasText).ifPresent(oldLtd::setLatitude); // 纬度
oldLtd.setRegistrationType(dto.getJjxz()); // 登记注册企业类别
//oldLtd.setLicenseNumber(); // 许可证编号
//oldLtd.setSafetyLevel(); // 安全生产标准化等级
//oldLtd.setIssuingAuthority(); // 发证机关
oldLtd.setEmployeeCount(dto.getZgzrs()); // 从业人员数量
//oldLtd.setIsTraining(); // 是否为培训机构
//oldLtd.setProductionManageInfoExp(); // 安全基础管理信息
//oldLtd.setProductionEquipmentExp(); // 生产设备设施信息
//oldLtd.setNocoalIndustryExpansion(); // 非煤行业扩展信息
//oldLtd.setDangerFeatureInfo(); // 危化行业扩展信息
//oldLtd.setFireworksAddInfo(); // 烟花爆竹行业扩展信息
oldLtd.setIndustryExpandInfos(dto.toString()); // 工贸行业扩展信息
oldLtd.setMainName(dto.getZyfzr()); // 主要负责人姓名
oldLtd.setMainPhone(dto.getZyfzrlxdh()); // 主要负责人电话
//oldLtd.setMajorAccidentHazard(); // 重大事故隐患年份
//oldLtd.setMajorDanger(); // 是否有重大危险源
//oldLtd.setInterid(dto.getYwlsh()); // 第三方对接ID
try {
Optional.ofNullable(dto.getCjsj()).filter(StringUtils::hasText).ifPresent(cjsj -> oldLtd.setEntryTime(LocalDateTime.parse(cjsj.substring(0, 19), DATE_TIME_FORMATTER))); // 录入时间
Optional.ofNullable(dto.getXgsj()).filter(StringUtils::hasText).ifPresent(xgsj -> oldLtd.setModifyTime(LocalDateTime.parse(xgsj.substring(0, 19), DATE_TIME_FORMATTER)));// 修改时间
} catch (Exception e) {
log.info("时间转换问题:{}", e);
}
//oldLtd.setModifyUserName(); // 修改用户名
//oldLtd.setModifyNickName(); // 修改用户昵称
//oldLtd.setDataSource(); // 数据来源
//oldLtd.setDelFlag(); // 是否删除
//oldLtd.setIsRemove(); // 是否移除计划清单
oldLtd.setPumpTime(now); // 抽取时间
//oldLtd.setShortName(); // 单位简称
oldLtd.setContactPerson(dto.getZyfzr()); // 单位联系人
oldLtd.setContactPhone(dto.getZyfzrlxdh()); // 联系电话
//oldLtd.setDynamicRiskLevel(); // 动态风险等级
//oldLtd.setBusinessScope(); // 经营范围
//oldLtd.setTown(); // 所在乡镇
//oldLtd.setVillage(); // 所在村
oldLtd.setStreet(dto.getXzjdmc()); // 所在街道
//oldLtd.setRiskCategory(); // 风险类别
//oldLtd.setUnitType(); // 单位类型
if ("0".equals(dto.getScjyztxh())) { // 运营状态
oldLtd.setOperationStatus("正常");
} else {
oldLtd.setOperationStatus("停业");
}
//oldLtd.setMunicipalRegulator(); // 市监管部门
//oldLtd.setDistrictRegulator(); // 区县监管部门
//oldLtd.setDistrictName(); // 区县名称
//oldLtd.setVideoAccess("0"); // 视频接入状态
//oldLtd.setPerceptionAccess("0"); // 感知接入状态
//oldLtd.setInfoAccess("0"); // 资料接入状态
//oldLtd.setPermitAccess("0"); // 许可接入状态
//oldLtd.setInsEnterprses(); // 巡查企业列表
//oldLtd.setIsWithin(); // 是否规上限上企业
//oldLtd.setGyqyfl(); // 工业企业分类
enterprises.add(oldLtd);
}
}else{
Enterprise enterprise = new Enterprise();
enterprise.setUnitName(dto.getQymc()); // 企业名称
enterprise.setUnifiedSocialCode(dto.getTyshxydm()); // 统一社会信用代码
if ("0".equals(dto.getScjyztxh())) {
enterprise.setBusinessStatus("11"); // 营业状态
} else {
enterprise.setBusinessStatus("13"); // 营业状态
}
Optional.ofNullable(dto.getQxbm()).filter(StringUtils::hasText).flatMap(agencyRepo::findByAgencyCode).ifPresent(enterprise::setAgency); // 机构
enterprise.setDetailedAddress(dto.getDz()); // 注册详细地址
enterprise.setOpLocAddress(dto.getDz()); // 经营详细地址
enterprise.setLegalRepresentative(dto.getFddbr()); // 法定代表人姓名
enterprise.setLegalPhone(dto.getFddbrlxdh()); // 法人联系电话
//国民经济行业分类代码国民经济行业分类GB/T 47542017
// if (StringUtils.hasText(dto.getGmjjhyfldm())) {
// String xxdm = dictService.getTopXxdm(dto.getGmjjhyfldm());
// enterprise.setRegulatedIndustry(xxdm);
// String[] ss = xxdm.split("/");
// for (int i = 0; i < ss.length; i++) {
// if (i == 0) enterprise.setEconCategory(ss[i]); // 国民经济行业分类代码
// if (i == 1) enterprise.setEconCategoryTypea(ss[i]); // 国民经济行业分类A型
// if (i == 2) enterprise.setEconCategoryTypeb(ss[i]); // 国民经济行业分类B型
// if (i == 3) enterprise.setEconCategoryTypec(ss[i]); // 国民经济行业分类C型
// }
// }
if(null!=dto.getHylb()&&"1".equals(dto.getHylb())){
enterprise.setIndustryType("7"); // 监管行业
}else {
enterprise.setIndustryType("6"); // 监管行业
}
enterprise.setOpLocArea(dto.getQxmc()); // 经营地址-
if (null!=dto.getJjlxxh()&&StringUtils.hasText(dto.getJjlxxh())) { // 国民经济类型
String economicType = dto.getJjlxxh();
switch (economicType) {
case "110" -> enterprise.setEconomicType("1");
case "120" -> enterprise.setEconomicType("2");
case "130" -> enterprise.setEconomicType("3");
case "140" -> enterprise.setEconomicType("4");
case "150" -> enterprise.setEconomicType("5");
case "160" -> enterprise.setEconomicType("6");
case "170" -> enterprise.setEconomicType("7");
case "190" -> enterprise.setEconomicType("8");
case "290" -> enterprise.setEconomicType("9");
case "310" -> enterprise.setEconomicType("10");
case "330" -> enterprise.setEconomicType("11");
case "159" -> enterprise.setEconomicType("12");
}
}
enterprise.setUnitScale(dto.getQygm()); // 企业规模
Optional.ofNullable(dto.getJd()).filter(StringUtils::hasText).ifPresent(enterprise::setLongitude); // 经度
Optional.ofNullable(dto.getWd()).filter(StringUtils::hasText).ifPresent(enterprise::setLatitude); // 纬度
enterprise.setRegistrationType(dto.getJjxz()); // 登记注册企业类别
enterprise.setEmployeeCount(dto.getZgzrs()); // 从业人员数量
enterprise.setIndustryExpandInfos(dto.toString()); // 工贸行业扩展信息
enterprise.setMainName(dto.getZyfzr()); // 主要负责人姓名
enterprise.setMainPhone(dto.getZyfzrlxdh()); // 主要负责人电话
try{
Optional.ofNullable(dto.getCjsj()).filter(StringUtils::hasText).ifPresent(cjsj->enterprise.setEntryTime(LocalDateTime.parse(cjsj.substring(0,19), DATE_TIME_FORMATTER))); // 录入时间
Optional.ofNullable(dto.getXgsj()).filter(StringUtils::hasText).ifPresent(xgsj->enterprise.setModifyTime(LocalDateTime.parse(xgsj.substring(0,19), DATE_TIME_FORMATTER)));// 修改时间
}catch (Exception e){
log.info("时间转换问题:{}",e);
}
enterprise.setPumpTime(LocalDateTime.now()); // 抽取时间
enterprise.setContactPerson(dto.getZyfzr()); // 单位联系人
enterprise.setContactPhone(dto.getZyfzrlxdh()); // 联系电话
enterprise.setStreet(dto.getXzjdmc()); // 所在街道
if ("0".equals(dto.getScjyztxh())) { // 运营状态
enterprise.setOperationStatus("正常");
} else {
enterprise.setOperationStatus("停业");
}
enterprises.add(enterprise);
}
}
if (!enterprises.isEmpty()) {
transactionTemplate.executeWithoutResult((status) -> enterpriseRepo.saveAll(enterprises));
log.info("保存成功:{}条数据", enterprises.size());
}
}
} else log.info("没有数据list");
} else {
log.info("刷新Token");
refreshToken();
}
} catch (Exception e) {
log.info("调用接口失败:{}",e);
}
return flag;
}
@Transactional
public boolean updateOrImportWaferEnterprise(int page) {
boolean flag = false;
try {
JSONObject jsonBody = new JSONObject();
JSONObject jsonPram = new JSONObject();
jsonBody.set("method", "GET");
jsonBody.set("jsonObject", jsonPram);
jsonBody.set("pageNum", page);
jsonBody.set("pageSize", 1000);
jsonBody.set("path", "/edataservice/api/whqyjbxx");
jsonBody.set("secret", "41982853a9e69e48c6eb73e1a80695ae58cb4fdc914137c55d6219ae4ea49579");
String body = HttpUtil.createPost("http://10.22.245.216:29999/jeecg-data-service/edataservice/api/")
.header("Content-Type", "application/json")
.body(jsonBody.toString())
.execute()
.body();
JsonNode jsonNode = objectMapper.readValue(body, JsonNode.class);
if (jsonNode.has("code") && 200 == jsonNode.get("code").asInt() && jsonNode.has("result")) {
JsonNode data = objectMapper.readValue(jsonNode.get("result").toString(), JsonNode.class);
if (null != data && data.has("records")) {
JsonNode arrNode = data.get("records");
if (arrNode.isArray()) {
long current = data.get("current").asLong();
long pages = data.get("pages").asLong();
if (current < pages) flag = true;
List<WaferEnterpriseDto> dtos = objectMapper.readValue(arrNode.toString(), new TypeReference<>() {});
Set<String> usccSet = dtos.stream().map(WaferEnterpriseDto::getTyshxydm).filter(StringUtils::hasText).collect(Collectors.toSet());
// 历史企业
List<Enterprise> enterpriseList = enterpriseRepo.findByUnifiedSocialCodeIn(usccSet);
List<Enterprise> enterprises = new ArrayList<>();
for (WaferEnterpriseDto dto : dtos) {
if (StringUtils.hasText(dto.getTyshxydm())) {
Enterprise oldLtd = enterpriseList.stream().filter(o -> o.getUnifiedSocialCode().equals(dto.getTyshxydm())).findFirst().orElse(null);
if (null != oldLtd) {
EnterpriseHistory history = new EnterpriseHistory();
BeanUtils.copyProperties(oldLtd, history);
history.setTheType("定时任务修改");
LocalDateTime now = LocalDateTime.now();
history.setHistoryTime(now);
enterpriseHistoryRepo.save(history);
oldLtd.setUnitName(dto.getQymc()); // 企业名称
oldLtd.setUnifiedSocialCode(dto.getTyshxydm()); // 统一社会信用代码
if ("opening".equals(dto.getYyzt())) {
oldLtd.setBusinessStatus("11"); // 营业状态
} else {
oldLtd.setBusinessStatus("13"); // 营业状态
}
Optional.ofNullable(dto.getQxdm()).filter(StringUtils::hasText).ifPresent(qxbm-> oldLtd.setAgency(agencyRepo.findLikeAgencyCode("%"+qxbm+"%",3).stream().findFirst().orElse(null)));
//oldLtd.setRegulatedIndustry(); // 国民经济行业分类
//oldLtd.setAreaComb(); // 注册地址
oldLtd.setDetailedAddress(dto.getZcdz()); // 注册详细地址
//oldLtd.setOpLocAreaComb(); // 经营地址
oldLtd.setOpLocAddress(dto.getJydz()); // 经营详细地址
if(null != dto.getJghylbxl()){
if(dto.getJghylbxl().contains("E040101")){
oldLtd.setIndustryType("2"); // 监管行业 危险化学品生产
}
else if(dto.getJghylbxl().contains("E040102")){
oldLtd.setIndustryType("3"); // 监管行业 危险化学品经营仓储
}
}else{
oldLtd.setIndustryType("4"); // 监管行业 危险化学品经营无仓储
}
oldLtd.setLegalRepresentative(dto.getFddbr()); // 法定代表人姓名
//oldLtd.setLegalPhone(dto.getFddbrlxdh()); // 法人联系电话
//oldLtd.setLegalDuty(); // 法定代表人职位
//oldLtd.setOpScope(dto.getJyfw()); // 主营业务
//oldLtd.setAffiliation(); // 行政隶属关系
//oldLtd.setOilExtract(); // 是否石油开采
//oldLtd.setSafetyFocus(); // 是否安全生产监管重点企业
//oldLtd.setIsScaleEnterprise(); // 是否规模以上企业
//oldLtd.setSafetyLic(); // 是否有安全生产许可证
oldLtd.setProvince(dto.getSjdmmc()); // 注册地址-
oldLtd.setCity(dto.getSjdm01mc()); // 注册地址-
oldLtd.setCounty(dto.getXjdmmc()); // 注册地址-/
oldLtd.setAreaComb(dto.getSjdmmc()+"/"+dto.getSjdm01mc()+"/"+dto.getXjdmmc());
oldLtd.setEconCategory(dto.getMllb());
//国民经济行业分类代码国民经济行业分类GB/T 47542017
StringBuilder regulatedIndustryStr = new StringBuilder(dto.getMllb());
Optional.ofNullable(dto.getDllb()).filter(StringUtils::hasText).ifPresent(s-> {
oldLtd.setEconCategoryTypea(s.substring(1));
regulatedIndustryStr.append("/"+s);
});
Optional.ofNullable(dto.getZllb()).filter(StringUtils::hasText).ifPresent(s-> {
oldLtd.setEconCategoryTypeb(s.substring(1));
regulatedIndustryStr.append("/"+s);
});
Optional.ofNullable(dto.getXllb()).filter(StringUtils::hasText).ifPresent(s-> {
oldLtd.setEconCategoryTypec(s.substring(1));
regulatedIndustryStr.append("/"+s);
});
oldLtd.setRegulatedIndustry(regulatedIndustryStr.toString());
//oldLtd.setOpLocProvince(); // 经营地址-
//oldLtd.setOpLocCity(); // 经营地址-
//oldLtd.setOpLocArea(dto.getQxmc()); // 经营地址-
//oldLtd.setBusinessRating(); // 企业分级
//oldLtd.setBusinessCategory(); // 企业分类
//oldLtd.setPostalCode(); // 邮政编码
//oldLtd.setLegalPersonIdType(); // 法定代表人证件类型
//oldLtd.setLegalPersonIdNumber(); // 法定代表人证件号码
//oldLtd.setIsInChemicalPark(); // 是否位于化工园区
//oldLtd.setExpiryDate(); // 营业执照有效期
oldLtd.setOrgCode(dto.getZzjgdm()); // 组织机构代码
oldLtd.setUnitScale(dto.getQygmmc()); // 企业规模
oldLtd.setEstablishmentDate(dto.getClrq()); // 成立日期
//oldLtd.setRegisteredCapital(); // 注册资本万元
oldLtd.setLongitude(dto.getJd()); // 经度
oldLtd.setLatitude(dto.getWd()); // 纬度
//oldLtd.setRegistrationType(dto.getJjxz()); // 登记注册企业类别
//oldLtd.setLicenseNumber(); // 许可证编号
//oldLtd.setSafetyLevel(); // 安全生产标准化等级
//oldLtd.setIssuingAuthority(); // 发证机关
//oldLtd.setEmployeeCount(dto.getZgzrs()); // 从业人员数量
//oldLtd.setIsTraining(); // 是否为培训机构
//oldLtd.setProductionManageInfoExp(); // 安全基础管理信息
//oldLtd.setProductionEquipmentExp(); // 生产设备设施信息
//oldLtd.setNocoalIndustryExpansion(); // 非煤行业扩展信息
oldLtd.setDangerFeatureInfo(dto.toString()); // 危化行业扩展信息
//oldLtd.setFireworksAddInfo(); // 烟花爆竹行业扩展信息
//oldLtd.setIndustryExpandInfos(dto.toString()); // 工贸行业扩展信息
//oldLtd.setMainName(dto.getLxr()); // 主要负责人姓名
//oldLtd.setMainPhone(dto.getLxdh()); // 主要负责人电话
//oldLtd.setMajorAccidentHazard(); // 重大事故隐患年份
//oldLtd.setMajorDanger(); // 是否有重大危险源
//oldLtd.setInterid(dto.getYwlsh()); // 第三方对接ID
//oldLtd.setEntryTime(dto.getCjsj()); // 录入时间
//oldLtd.setEntryUserName(); // 录入用户名
//oldLtd.setEntryNickName(); // 录入用户昵称
//oldLtd.setModifyTime(dto.getXgsj()); // 修改时间
//oldLtd.setModifyUserName(); // 修改用户名
//oldLtd.setModifyNickName(); // 修改用户昵称
//oldLtd.setDataSource(); // 数据来源
//oldLtd.setDelFlag(); // 是否删除
//oldLtd.setIsRemove(); // 是否移除计划清单
oldLtd.setPumpTime(now); // 抽取时间
//oldLtd.setShortName(); // 单位简称
oldLtd.setContactPerson(dto.getLxr()); // 单位联系人
oldLtd.setContactPhone(dto.getLxdh()); // 联系电话
oldLtd.setDynamicRiskLevel(dto.getDtfxdjmc()); // 动态风险等级
oldLtd.setBusinessScope(dto.getJyfw()); // 经营范围
//oldLtd.setTown(); // 所在乡镇
//oldLtd.setVillage(); // 所在村
oldLtd.setStreet(dto.getJdmc()); // 所在街道
//oldLtd.setRiskCategory(); // 风险类别
//oldLtd.setUnitType(); // 单位类型
// if ("0".equals(dto.getScjyztxh())) { // 运营状态
// oldLtd.setOperationStatus("正常");
// } else {
// oldLtd.setOperationStatus("停业");
// }
//oldLtd.setMunicipalRegulator(); // 市监管部门
//oldLtd.setDistrictRegulator(); // 区县监管部门
//oldLtd.setDistrictName(); // 区县名称
//oldLtd.setVideoAccess("0"); // 视频接入状态
//oldLtd.setPerceptionAccess("0"); // 感知接入状态
//oldLtd.setInfoAccess("0"); // 资料接入状态
//oldLtd.setPermitAccess("0"); // 许可接入状态
//oldLtd.setInsEnterprses(); // 巡查企业列表
//oldLtd.setIsWithin(); // 是否规上限上企业
//oldLtd.setGyqyfl(); // 工业企业分类
enterprises.add(oldLtd);
}
} else {
Enterprise enterprise = new Enterprise();
enterprise.setUnitName(dto.getQymc()); // 企业名称
enterprise.setUnifiedSocialCode(dto.getTyshxydm()); // 统一社会信用代码
enterprise.setUnitName(dto.getQymc()); // 企业名称
enterprise.setUnifiedSocialCode(dto.getTyshxydm()); // 统一社会信用代码
if ("opening".equals(dto.getYyzt())) {
enterprise.setBusinessStatus("11"); // 营业状态
} else {
enterprise.setBusinessStatus("13"); // 营业状态
}
Optional.ofNullable(dto.getQxdm()).filter(StringUtils::hasText).ifPresent(qxbm-> enterprise.setAgency(agencyRepo.findLikeAgencyCode("%"+qxbm+"%",3).stream().findFirst().orElse(null)));
enterprise.setDetailedAddress(dto.getZcdz()); // 注册详细地址
//oldLtd.setOpLocAreaComb(); // 经营地址
enterprise.setOpLocAddress(dto.getJydz()); // 经营详细地址
if(null!=dto.getJghylbxl()){
if(dto.getJghylbxl().contains("E040101")){
enterprise.setIndustryType("2"); // 监管行业 危险化学品生产
}
else if(dto.getJghylbxl().contains("E040102")){
enterprise.setIndustryType("3"); // 监管行业 危险化学品经营仓储
}
}else{
enterprise.setIndustryType("4"); // 监管行业 危险化学品经营无仓储
}
enterprise.setLegalRepresentative(dto.getFddbr()); // 法定代表人姓名
enterprise.setDangerFeatureInfo(dto.toString()); // 危化行业扩展信息
enterprise.setProvince(dto.getSjdmmc()); // 注册地址-
enterprise.setCity(dto.getSjdm01mc()); // 注册地址-
enterprise.setCounty(dto.getXjdmmc()); // 注册地址-/
enterprise.setAreaComb(dto.getSjdmmc()+"/"+dto.getSjdm01mc()+"/"+dto.getXjdmmc());
enterprise.setEconCategory(dto.getMllb());
//国民经济行业分类代码国民经济行业分类GB/T 47542017
StringBuilder regulatedIndustryStr = new StringBuilder(dto.getMllb());
Optional.ofNullable(dto.getDllb()).filter(StringUtils::hasText).ifPresent(s-> {
enterprise.setEconCategoryTypea(s.substring(1));
regulatedIndustryStr.append("/"+s);
});
Optional.ofNullable(dto.getZllb()).filter(StringUtils::hasText).ifPresent(s-> {
enterprise.setEconCategoryTypeb(s.substring(1));
regulatedIndustryStr.append("/"+s);
});
Optional.ofNullable(dto.getXllb()).filter(StringUtils::hasText).ifPresent(s-> {
enterprise.setEconCategoryTypec(s.substring(1));
regulatedIndustryStr.append("/"+s);
});
enterprise.setRegulatedIndustry(regulatedIndustryStr.toString());
enterprise.setOrgCode(dto.getZzjgdm()); // 组织机构代码
enterprise.setUnitScale(dto.getQygmmc()); // 企业规模
enterprise.setEstablishmentDate(dto.getClrq()); // 成立日期
enterprise.setLongitude(dto.getJd()); // 经度
enterprise.setLatitude(dto.getWd()); // 纬度
enterprise.setIndustryExpandInfos(dto.toString()); // 工贸行业扩展信息
enterprise.setPumpTime(LocalDateTime.now()); // 抽取时间
enterprise.setContactPerson(dto.getLxr()); // 单位联系人
enterprise.setContactPhone(dto.getLxdh()); // 联系电话
enterprise.setDynamicRiskLevel(dto.getDtfxdjmc()); // 动态风险等级
enterprise.setBusinessScope(dto.getJyfw()); // 经营范围
enterprise.setStreet(dto.getJdmc()); // 所在街道
enterprises.add(enterprise);
}
}
if (!enterprises.isEmpty()) {
transactionTemplate.executeWithoutResult((status) -> enterpriseRepo.saveAll(enterprises));
log.info("保存成功:{}条数据", enterprises.size());
}
}
} else log.info("没有数据list");
} else {
log.info("刷新Token");
refreshToken();
}
} catch (Exception e) {
log.info("危化企业信息查询查询异常:" + e);
}
return flag;
}
}

View File

@ -0,0 +1,778 @@
package com.aisino.iles.lawenforcement.schedule.service;
import cn.hutool.http.HttpUtil;
import com.aisino.iles.lawenforcement.model.*;
import com.aisino.iles.lawenforcement.model.dto.EnterpriseInterfaceDto;
import com.aisino.iles.lawenforcement.repository.*;
import com.aisino.iles.lawenforcement.service.AuthService;
import com.aisino.iles.lawenforcement.service.DictInterfaceService;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.smartlx.sso.client.model.AccessToken;
import com.smartlx.sso.client.properties.SsoClientProperties;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* 企业信息定时任务
*/
@Service
@Slf4j
public class EnterpriseScheduleService {
private final EnterpriseRepository enterpriseRepo;
private final EnterpriseHistoryRepository enterpriseHistoryRepo;
private final AdministrativeLicenseRepository administrativeLicenseRepo;
private final AccidentHazardRepository accidentHazardRepo;
private final DangerInfoRepository dangerInfoRepo;
private final AgencyRepository agencyRepo;
private final SsoClientProperties ssoClientProperties;
private final TransactionTemplate transactionTemplate;
private final ObjectMapper objectMapper;
private final AuthService authService;
private final String queryUrl;
private final String mobilePhone;
private String accessToken;
private String tokenType;
private String refreshToken;
private final String produceLicensePage;
private final String hazardPage;
private final String sourcesDangerPage;
private final DictInterfaceService dictService;
private final DateTimeFormatter yyyy = DateTimeFormatter.ofPattern("yyyy");
public EnterpriseScheduleService(EnterpriseRepository enterpriseRepo,
EnterpriseHistoryRepository enterpriseHistoryRepo,
AdministrativeLicenseRepository administrativeLicenseRepo,
AccidentHazardRepository accidentHazardRepo,
DangerInfoRepository dangerInfoRepo,
AgencyRepository agencyRepo,
@Value("${third-party.enterprise.query:}") String queryUrl,
@Value("${third-party.enterprise.yddh:}") String mobilePhone,
SsoClientProperties ssoClientProperties,
TransactionTemplate transactionTemplate,
ObjectMapper objectMapper,
AuthService authService,
@Value("${third-party.enterprise.produceLicensePage:}") String produceLicensePage,
@Value("${third-party.enterprise.hazardPage:}") String hazardPage,
@Value("${third-party.enterprise.sourcesDangerPage:}") String sourcesDangerPage,
DictInterfaceService dictService) {
this.enterpriseRepo = enterpriseRepo;
this.enterpriseHistoryRepo = enterpriseHistoryRepo;
this.administrativeLicenseRepo = administrativeLicenseRepo;
this.accidentHazardRepo = accidentHazardRepo;
this.dangerInfoRepo = dangerInfoRepo;
this.agencyRepo = agencyRepo;
this.queryUrl = queryUrl;
this.ssoClientProperties = ssoClientProperties;
this.transactionTemplate = transactionTemplate;
this.objectMapper = objectMapper;
this.mobilePhone = mobilePhone;
this.authService = authService;
this.produceLicensePage = produceLicensePage;
this.hazardPage = hazardPage;
this.sourcesDangerPage = sourcesDangerPage;
this.dictService = dictService;
}
/**
* 工作台信息导入
* 每天10点执行一次
* (cron = "0 0 15 * * ?")
* (cron = "${scheduler.expression}")
* (fixedRate = 120000)
*/
@Scheduled(cron = "${scheduler.task.enterprise.cron.expression}")
public void scheduledEnterpriseTask() {
getToken();
dictService.getDictItem("YJ_CODE_9017", tokenType, accessToken);
// enterpriseTask();
administrativeLicenseTask();
accidentHazardTask();
dangerInfoTask();
}
/**
* 导入企业信息
*/
private void enterpriseTask() {
log.info("开始导入企业信息...");
int page = 1;
boolean b = importEnterprise(page);
while (b) {
page++;
b = importEnterprise(page);
}
log.info("企业信息导入完成...");
}
/**
* 刷新token
*/
private void refreshToken() {
try {
authService.refreshTokenBackend(accessToken, tokenType, refreshToken, mobilePhone);
// 刷新后重新获取token
getToken();
log.info("刷新token成功");
} catch (Exception e) {
log.error("刷新token失败尝试重新获取token", e);
getToken();
}
}
/**
* 获取token
*/
private void getToken() {
try {
AccessToken accessTokenObj = authService.getTokenBackend(mobilePhone);
if (accessTokenObj != null) {
accessToken = accessTokenObj.getAccess_token();
tokenType = accessTokenObj.getToken_type();
refreshToken = accessTokenObj.getRefresh_token();
log.info("获取token成功");
} else {
log.error("获取token失败返回为null");
throw new RuntimeException("无法获取有效的访问令牌");
}
} catch (Exception e) {
log.error("获取token失败", e);
throw new RuntimeException("无法获取有效的访问令牌", e);
}
}
private boolean importEnterprise(int page) {
boolean goon = false;
try {
String body = HttpUtil.createPost(queryUrl)
.header("Content-Type", "application/json")
.header("Authorization", tokenType + " " + accessToken)
.header("appId", ssoClientProperties.getClientId())
.body("{\"page\": " + page + ",\"limit\": 1000,\"entity\": {}}")
.execute()
.body();
log.info("企业信息查询结果:{}", body);
JsonNode jsonNode = objectMapper.readValue(body, JsonNode.class);
if (jsonNode.has("code") && 200 == jsonNode.get("code").asInt() && jsonNode.has("data")) {
JsonNode data = objectMapper.readValue(jsonNode.get("data").toString(), JsonNode.class);
if (null != data && data.has("list")) {
JsonNode arrNode = data.get("list");
if (arrNode.isArray()) {
long total = data.get("totalCount").asLong();
int limit = data.get("limit").asInt();
if (total > limit && arrNode.size() >= limit)
goon = true;
List<Enterprise> enterprises = new ArrayList<>();
List<EnterpriseInterfaceDto> dtos = objectMapper.readValue(arrNode.toString(), new TypeReference<>() {
});
Set<String> usccSet = dtos.stream().map(EnterpriseInterfaceDto::getTyshxydm).filter(StringUtils::hasText).collect(Collectors.toSet());
List<Enterprise> enterpriseList = enterpriseRepo.findByUnifiedSocialCodeIn(usccSet);
for (EnterpriseInterfaceDto dto : dtos) {
if (StringUtils.hasText(dto.getTyshxydm())) {
Enterprise oldLtd = enterpriseList.stream().filter(o -> o.getUnifiedSocialCode().equals(dto.getTyshxydm())).findFirst().orElse(null);
if (null == oldLtd || !"31".equals(oldLtd.getDataSource())) {
Enterprise enterprise = new Enterprise();
LocalDateTime now = LocalDateTime.now();
if (null != oldLtd) {
BeanUtils.copyProperties(oldLtd, enterprise);
EnterpriseHistory history = new EnterpriseHistory();
BeanUtils.copyProperties(enterprise, history);
history.setTheType("定时任务修改");
history.setHistoryTime(now);
enterpriseHistoryRepo.save(history);
} else {
enterprise.setIsWithin("0");
enterprise.setPumpTime(now);
enterprise.setBusinessCategory("1");
}
enterprise.setEntryUserName(dto.getCjrYhwybs());//创建人用户唯一标识
if (null != dto.getCjsj()) {
enterprise.setEntryTime(dto.getCjsj());//创建时间
enterprise.setModifyUserName(dto.getGxrYhwybs());//更新人用户唯一标识
if (null != dto.getGxsj()) enterprise.setModifyTime(dto.getGxsj());//更新时间
else enterprise.setModifyTime(dto.getCjsj());
} else {
enterprise.setEntryTime(now);//创建时间
enterprise.setModifyTime(now);
}
enterprise.setUnitName(dto.getQymc());//企业名称
enterprise.setUnifiedSocialCode(dto.getTyshxydm());//统一社会信用代码
enterprise.setShortName(dto.getQyjc());//企业简称
enterprise.setUnitScale(dto.getQygm());//企业规模代码
enterprise.setEmployeeCount(dto.getZgrs());//职工人数
enterprise.setDetailedAddress(dto.getZcdzXxdz());//注册地址详细地址
enterprise.setAreaComb(dto.getZcdzXzqhdm());//注册地址行政区划代码
enterprise.setOpLocAddress(dto.getScjydzXxdz());//生产经营地址详细地址
enterprise.setOpLocAreaComb(dto.getScjydzXzqhdm());//生产经营地址行政区划代码
enterprise.setOpScope(dto.getJyfw());//经营范围
Optional.ofNullable(dto.getYygldwZzjgdm()).filter(StringUtils::hasText).flatMap(agencyRepo::findByAgencyCode).ifPresent(enterprise::setAgency);//发证机关代码
if (StringUtils.hasText(dto.getGmjjhyfldm())) {//国民经济行业分类代码国民经济行业分类GB/T 47542017
String xxdm = dictService.getTopXxdm(dto.getGmjjhyfldm());
enterprise.setRegulatedIndustry(xxdm);
String[] ss = xxdm.split("/");
for (int i = 0; i < ss.length; i++) {
if (i == 0) enterprise.setEconCategory(ss[i]);
if (i == 1) enterprise.setEconCategoryTypea(ss[i]);
if (i == 2) enterprise.setEconCategoryTypeb(ss[i]);
if (i == 3) enterprise.setEconCategoryTypec(ss[i]);
}
}
enterprise.setOrgCode(dto.getFzjgdm());//应急管理单位组织机构代码
enterprise.setLegalRepresentative(dto.getLxrxm());//企业联系人
Optional.ofNullable(dto.getScjydzJd()).filter(StringUtils::hasText).ifPresent(enterprise::setLongitude);//经营地址经度
Optional.ofNullable(dto.getScjydzWd()).filter(StringUtils::hasText).ifPresent(enterprise::setLatitude);//经营地址纬度
Optional.ofNullable(dto.getYyzt()).filter(StringUtils::hasText).ifPresent(o -> {
if ("1".equals(o)) enterprise.setBusinessStatus("11");
else enterprise.setBusinessStatus("13");
});//1-正常存续在营开业注册设立2-异常未年报未年检证书逾期未年度考核3-吊销4-注销/撤销9-其他
String economicType = dto.getJjlxfldm();
if (StringUtils.hasText(economicType)) {//经济类型分类代码
switch (economicType) {
case "110" -> enterprise.setEconomicType("1");
case "120" -> enterprise.setEconomicType("2");
case "130" -> enterprise.setEconomicType("3");
case "140" -> enterprise.setEconomicType("4");
case "150" -> enterprise.setEconomicType("5");
case "160" -> enterprise.setEconomicType("6");
case "170" -> enterprise.setEconomicType("7");
case "190" -> enterprise.setEconomicType("8");
case "290" -> enterprise.setEconomicType("9");
case "310" -> enterprise.setEconomicType("10");
case "330" -> enterprise.setEconomicType("11");
case "159" -> enterprise.setEconomicType("12");
}
}
enterprise.setUnitCode(dto.getQybh());
enterprise.setMainName(dto.getQyfzrxm());
String qyLxdh = dto.getQyLxdh();
enterprise.setContactPhone(qyLxdh);
enterprise.setMainPhone(qyLxdh);
enterprise.setLegalPhone(qyLxdh);
enterprise.setContactPerson(dto.getLxrxm());
if (null != dto.getClrq())
enterprise.setEstablishmentDate(LocalDate.from(dto.getClrq()));//成立日期
if (null != dto.getZczb())
enterprise.setRegisteredCapital(BigDecimal.valueOf(dto.getZczb()));//注册资本
if (null != dto.getYyqx())
enterprise.setExpiryDate(LocalDate.from(dto.getYyqx()));//营业期限
//1-工贸企业 2-危化企业 3-矿山企业 4-建筑施工企业 5-民用爆炸物企业 6-食品药品企业 7-交通运输企业
//1-矿山 2-危险化学品生产 3-危险化学品经营仓储 4-危险化学品经营无仓储 5-加油站 6-工业企业 7-商贸企业 8-安全生产中介机构 9-安全生产检验检测机构 10-安全生产培训机构 99-其他
String gllx = dto.getGllx();//管理类型代码
Optional.ofNullable(gllx).ifPresentOrElse(o -> {
switch (o) {
case "1" -> enterprise.setIndustryType("6");
case "3" -> enterprise.setIndustryType("1");
case "2" -> enterprise.setIndustryType("2");
default -> enterprise.setIndustryType("99");
}
}, () -> enterprise.setIndustryType("99"));
if (enterprise.getUnitName().contains("加油站"))
enterprise.setIndustryType("5");
enterprise.setIsRemove((short) 0);
if ("0".equals(dto.getSjyxx()))
enterprise.setDelFlag((short) 1);
else enterprise.setDelFlag((short) 0);
if ("5".equals(enterprise.getIndustryType()))
enterprise.setBusinessCategory("2");
else enterprise.setBusinessCategory("1");
enterprise.setDataSource("3");
enterprise.setInterid(dto.getYwlsh());
enterprises.add(enterprise);
}
} else log.info("统一信用代码为空:{}", dto.getYwlsh());
}
int i = 0;
if (!enterprises.isEmpty()) {
i++;
transactionTemplate.executeWithoutResult((status) -> enterpriseRepo.saveAll(enterprises));
log.info("成功次数:{}", i);
}
}
} else log.info("没有数据list");
} else {
log.info("刷新Token");
refreshToken();
}
} catch (Exception e) {
log.info("企业查询异常:" + e);
}
return goon;
}
/**
* 企业生产许可信息导入
*/
public void administrativeLicenseTask() {
log.info("开始企业生产许可信息导入...");
int page = 1;
boolean b = importAdministrativeLicense(page);
while (b) {
page++;
b = importAdministrativeLicense(page);
}
log.info("企业生产许可信息导入完成...");
}
private boolean importAdministrativeLicense(int page) {
boolean goon = false;
try {
String body = HttpUtil.createPost(produceLicensePage)
.header("Content-Type", "application/json")
.header("Authorization", tokenType + " " + accessToken)
.header("appId", ssoClientProperties.getClientId())
.body("{\"page\": " + page + ",\"limit\": 1000,\"entity\": {}}")
.execute()
.body();
log.info("生产许可查询结果:{}", body);
JsonNode jsonNode = objectMapper.readValue(body, JsonNode.class);
if (jsonNode.has("code") && 200 == jsonNode.get("code").asInt() && jsonNode.has("data")) {
JsonNode data = objectMapper.readValue(jsonNode.get("data").toString(), JsonNode.class);
if (null != data && data.has("list")) {
JsonNode arrNode = data.get("list");
if (arrNode.isArray()) {
long total = data.get("totalCount").asLong();
int limit = data.get("limit").asInt();
if (total > limit && arrNode.size() >= limit)
goon = true;
List<AdministrativeLicense> licenses = new ArrayList<>();
List<AdministrativeLicenseInterfaceDto> dtos = objectMapper.readValue(arrNode.toString(), new TypeReference<>() {
});
for (AdministrativeLicenseInterfaceDto dto : dtos) {
AdministrativeLicense license = new AdministrativeLicense();
license.setLicenseNum(dto.getLicensenumber());//": "陕西危化经字2021012001",
license.setIssuingOffice(dto.getIssuingoffice());//": "西安市应急管理局",
if (null != dto.getValidfrom())
license.setValidFrom(LocalDate.from(dto.getValidfrom()));//": "2021-06-23 00:00:00",
if (null != dto.getValidend())
license.setValidFrom(LocalDate.from(dto.getValidend()));//": "2024-06-22 00:00:00",
license.setLicenseType(dto.getLicensetype());//": "510400P02",
enterpriseRepo.findByUnifiedSocialCode(dto.getUnitid())
.ifPresentOrElse(enterprise -> {
license.setEnterpriseId(enterprise.getEnterpriseId());
if (!StringUtils.hasText(dto.getQymc()))
license.setUnitName(enterprise.getUnitName());
},
() -> {
license.setEnterpriseId(dto.getUnitid());
license.setUnitName(dto.getQymc());
});
license.setInterid(dto.getId());//": "539392900627437727744",
license.setDataScope(dto.getDataScope());//": null,
license.setDwdmScope(dto.getDwdmScope());//": null,
license.setUsergw(dto.getUsergw());//": null,
license.setLicensename(dto.getLicensename());//": "危险化学品经营许可有仓储",
license.setResponsibleperson(dto.getResponsibleperson());//": null,
license.setLicensestatus(dto.getLicensestatus());//": "有效",
license.setChangerecord(dto.getChangerecord());//": null,
license.setDutydepartmentmanager(dto.getDutydepartmentmanager());//": null,
license.setDutypeoplemanager(dto.getDutypeoplemanager());//": null,
license.setApplydepartment(dto.getApplydepartment());//": null,
license.setReviewcomments(dto.getReviewcomments());//": null,
license.setReviewdepartment(dto.getReviewdepartment());//": null,
license.setReviewpeople(dto.getReviewpeople());//": null,
license.setRectificationnoncompliance(dto.getRectificationnoncompliance());//": null,
license.setCreatedby(dto.getCreatedby());//": "262",
license.setCreatedon(dto.getCreatedon());//": "2023-10-11 10:08:15",
license.setModifiedby(dto.getModifiedby());//": "262",
license.setModifiedon(dto.getModifiedon());//": "2023-10-11 10:08:15",
license.setDeletestatus(dto.getDeletestatus());//": 0,
license.setDataSource(dto.getSjly());//": "危化",
license.setPumpTime(LocalDateTime.now());
licenses.add(license);
}
int i = 0;
if (!licenses.isEmpty()) {
i++;
// transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
transactionTemplate.executeWithoutResult((status) -> administrativeLicenseRepo.saveAll(licenses));
log.info("企业生产许可成功次数:{}", i);
}
}
} else log.info("企业生产许可没有数据list");
} else {
log.info("企业生产许可刷新Token");
refreshToken();
}
} catch (Exception e) {
log.info("企业生产许可查询异常:" + e);
}
return goon;
}
@Data
public static class AdministrativeLicenseInterfaceDto {
/**
* 适用部门50
*/
private String applydepartment;
/**
* 变更记录50
*/
private String changerecord;
/**
* 创建人
*/
private String createdby;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdon;
/**
* 当前用户等级 后台查看数据权限用
*/
private String dataScope;
/**
* 删除标记默认为0; 0=未删除,1=已删除
*/
private Integer deletestatus;
/**
* 归口管理责任部门50
*/
private String dutydepartmentmanager;
/**
* 归口管理责任人50
*/
private String dutypeoplemanager;
/**
* 当前用户单位 后台查看数据权限用
*/
private String dwdmScope;
/**
* ID
*/
private String id;
/**
* 发证机关
*/
private String issuingoffice;
/**
* 许可证书名称
*/
private String licensename;
/**
* 许可证编号
*/
private String licensenumber;
/**
* 许可证状态
*/
private String licensestatus;
/**
* 许可类型approvalType
*/
private String licensetype;
/**
* 修改人
*/
private String modifiedby;
/**
* 修改时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime modifiedon;
/**
* 企业名称
*/
private String qymc;
/**
* 不符合项整改情况500
*/
private String rectificationnoncompliance;
/**
* 主要负责人
*/
private String responsibleperson;
/**
* 符合性评审意见500
*/
private String reviewcomments;
/**
* 评审部门50
*/
private String reviewdepartment;
/**
* 评审责任人50
*/
private String reviewpeople;
/**
* 数据来源 危化 工贸等
*/
private String sjly;
/**
* 企业id
*/
private String unitid;
/**
* 当前用户岗位 后台查看数据权限用
*/
private String usergw;
/**
* 有效期至
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime validend;
/**
* 有效期自
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime validfrom;
}
/**
* 重大事故隐患信息导入
*/
public void accidentHazardTask() {
log.info("开始重大事故隐患信息导入...");
int page = 1;
boolean b = importAccidentHazard(page);
while (b) {
page++;
b = importAccidentHazard(page);
}
log.info("企业重大事故隐患信息导入完成...");
}
private boolean importAccidentHazard(int page) {
boolean goon = false;
try {
String body = HttpUtil.createPost(hazardPage)
.header("Content-Type", "application/json")
.header("Authorization", tokenType + " " + accessToken)
.header("appId", ssoClientProperties.getClientId())
.body("{\"page\": " + page + ",\"limit\": 1000,\"entity\": {}}")
.execute()
.body();
log.info("重大事故隐患查询结果:{}", body);
JsonNode jsonNode = objectMapper.readValue(body, JsonNode.class);
if (jsonNode.has("code") && 200 == jsonNode.get("code").asInt() && jsonNode.has("data")) {
JsonNode data = objectMapper.readValue(jsonNode.get("data").toString(), JsonNode.class);
if (null != data && data.has("list")) {
JsonNode arrNode = data.get("list");
if (arrNode.isArray()) {
long total = data.get("totalCount").asLong();
int limit = data.get("limit").asInt();
if (total > limit && arrNode.size() >= limit)
goon = true;
List<AccidentHazard> hazards = new ArrayList<>();
List<AccidentHazardDto> dtos = objectMapper.readValue(arrNode.toString(), new TypeReference<>() {
});
for (AccidentHazardDto dto : dtos) {
AccidentHazard hazard = new AccidentHazard();
BeanUtils.copyProperties(dto, hazard);
enterpriseRepo.findByUnifiedSocialCode(dto.getUnitid())
.ifPresentOrElse(enterprise -> {
hazard.setEnterpriseId(enterprise.getEnterpriseId());
if (null != hazard.getCreatedon()) {
String year = hazard.getCreatedon().format(yyyy);
if (StringUtils.hasText(enterprise.getMajorAccidentHazard())) {
Set<String> set = Arrays.stream(enterprise.getMajorAccidentHazard().split(",")).collect(Collectors.toSet());
if (!set.contains(year)) {
set.add(year);
String majorAccidentHazard = String.join(",", set);
EnterpriseHistory history = new EnterpriseHistory();
BeanUtils.copyProperties(enterprise, history);
LocalDateTime now = LocalDateTime.now();
history.setTheType("修改重大事故隐患年份");
history.setHistoryTime(now);
enterpriseHistoryRepo.save(history);
enterprise.setMajorAccidentHazard(majorAccidentHazard);
enterprise.setModifyTime(now);
enterpriseRepo.save(enterprise);
}
} else
enterprise.setMajorAccidentHazard(year);
}
if (!StringUtils.hasText(dto.getQymc()))
hazard.setUnitname(enterprise.getUnitName());
},
() -> {
hazard.setEnterpriseId(dto.getUnitid());
hazard.setUnitname(dto.getQymc());
});
hazard.setInterid(dto.getId());
hazard.setDataSource(dto.getSjly());
hazard.setPumpTime(LocalDateTime.now());
hazards.add(hazard);
}
int i = 0;
if (!hazards.isEmpty()) {
i++;
transactionTemplate.executeWithoutResult((status) -> accidentHazardRepo.saveAll(hazards));
log.info("重大事故隐患成功次数:{}", i);
}
}
} else log.info("重大事故隐患没有数据list");
} else {
log.info("重大事故隐患刷新Token");
refreshToken();
}
} catch (Exception e) {
log.info("重大事故隐患查询异常:" + e);
}
return goon;
}
@Data
public static class AccidentHazardDto extends AccidentHazard {
/**
* 企业统一信用社代码
*/
private String unitid;
/**
* 企业名称
*/
private String qymc;
/**
* 数据来源 危化 工贸等
*/
private String sjly;
private String id;
}
/**
* 重大危险源信息导入
*/
public void dangerInfoTask() {
log.info("开始重大危险源信息导入...");
int page = 1;
boolean b = importDangerInfo(page);
while (b) {
page++;
b = importDangerInfo(page);
}
log.info("重大危险源信息导入完成...");
}
private boolean importDangerInfo(int page) {
boolean goon = false;
try {
String body = HttpUtil.createPost(sourcesDangerPage)
.header("Content-Type", "application/json")
.header("Authorization", tokenType + " " + accessToken)
.header("appId", ssoClientProperties.getClientId())
.body("{\"page\": " + page + ",\"limit\": 1000,\"entity\": {}}")
.execute()
.body();
log.info("重大危险源查询结果:{}", body);
JsonNode jsonNode = objectMapper.readValue(body, JsonNode.class);
if (jsonNode.has("code") && 200 == jsonNode.get("code").asInt() && jsonNode.has("data")) {
JsonNode data = objectMapper.readValue(jsonNode.get("data").toString(), JsonNode.class);
if (null != data && data.has("list")) {
JsonNode arrNode = data.get("list");
if (arrNode.isArray()) {
long total = data.get("totalCount").asLong();
int limit = data.get("limit").asInt();
if (total > limit && arrNode.size() >= limit)
goon = true;
List<DangerInfo> dangerInfos = new ArrayList<>();
List<DangerInfoDto> dtos = objectMapper.readValue(arrNode.toString(), new TypeReference<>() {
});
for (DangerInfoDto dto : dtos) {
DangerInfo dangerInfo = new DangerInfo();
BeanUtils.copyProperties(dto, dangerInfo);
enterpriseRepo.findByUnifiedSocialCode(dto.getUnitid())
.ifPresentOrElse(enterprise -> {
dangerInfo.setEnterpriseId(enterprise.getEnterpriseId());
if (!StringUtils.hasText(dto.getQymc()))
dangerInfo.setUnitname(enterprise.getUnitName());
EnterpriseHistory history = new EnterpriseHistory();
BeanUtils.copyProperties(enterprise, history);
LocalDateTime now = LocalDateTime.now();
history.setTheType("修改危险源状态");
history.setHistoryTime(now);
enterpriseHistoryRepo.save(history);
enterprise.setMajorDanger("1");
enterprise.setModifyTime(now);
enterpriseRepo.save(enterprise);
},
() -> {
dangerInfo.setEnterpriseId(dto.getUnitid());
dangerInfo.setUnitname(dto.getQymc());
});
dangerInfo.setInterid(dto.getId());
dangerInfo.setDataSource(dto.getSjly());
dangerInfo.setPumpTime(LocalDateTime.now());
dangerInfos.add(dangerInfo);
}
int i = 0;
if (!dangerInfos.isEmpty()) {
i++;
transactionTemplate.executeWithoutResult((status) -> dangerInfoRepo.saveAll(dangerInfos));
log.info("重大危险源成功次数:{}", i);
}
}
} else log.info("重大危险源没有数据list");
} else {
log.info("重大危险源刷新Token");
refreshToken();
}
} catch (Exception e) {
log.info("重大危险源查询异常:" + e);
}
return goon;
}
@Data
public static class DangerInfoDto extends DangerInfo {
/**
* 企业统一信用社代码
*/
private String unitid;
/**
* 企业名称
*/
private String qymc;
/**
* 数据来源 危化 工贸等
*/
private String sjly;
private String id;
}
}

View File

@ -0,0 +1,238 @@
package com.aisino.iles.lawenforcement.schedule.service;
import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aisino.iles.lawenforcement.model.EquipmentHistoryVideo;
import com.aisino.iles.lawenforcement.repository.EquipmentHistoryVideoRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.net.HttpCookie;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* 执法装备历史视频信息同步调度服务
* <p>
* 通过定时任务从外部API同步装备历史视频信息到本地数据库
*/
@Slf4j
@Service
public class EquipmentHistoryVideoScheduleService {
@Value("${media.service.login.url:http://222.91.125.86:8090/rest/index/login/login}")
private String loginUrl;
@Value("${media.service.data.url:http://222.91.125.86:8090/rest/media/media/get}")
private String dataUrl;
@Value("${media.service.username:SLtest}")
private String username;
@Value("${media.service.password:Pe26957381}")
private String password;
@Value("${media.service.device.code:1001}")
private String deviceCode;
@Value("${media.service.page.size:100}")
private int pageSize;
@Value("${media.service.date.start:2000-01-01 00:00:00}")
private String defaultStartDate;
@Value("${media.service.date.end:2030-01-01 00:00:00}")
private String defaultEndDate;
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final String SESSION_COOKIE_NAME = "PHPSESSID";
private static final int MAX_RETRIES = 3;
private final EquipmentHistoryVideoRepository equipmentHistoryVideoRepository;
@Autowired
public EquipmentHistoryVideoScheduleService(EquipmentHistoryVideoRepository equipmentHistoryVideoRepository) {
this.equipmentHistoryVideoRepository = equipmentHistoryVideoRepository;
}
@Scheduled(cron = "0 * * * * ?")
public void scheduleTask() {
log.info("获取装备历史视频开始。。。。");
try {
HttpCookie sessionCookie = login();
if (sessionCookie != null) {
fetchAllMediaPages(sessionCookie);
}
} catch (Exception e) {
log.error("任务异常", e);
}
log.info("获取装备历史视频结束。。。。");
}
public HttpCookie login() {
String encryptedPassword = DigestUtil.md5Hex(password);
// 构造登录参数
JSONObject param = new JSONObject();
param.set("username", username);
param.set("password", encryptedPassword);
try {
// 编码处理
String jsonString = param.toString();
String urlEncodedString = URLEncoder.encode(jsonString, StandardCharsets.UTF_8.name());
String loginInfo = Base64.encode(urlEncodedString);
// 构造请求体
JSONObject requestBody = new JSONObject();
requestBody.set("login_info", loginInfo);
// 发送登录请求
HttpResponse response = HttpRequest.post(loginUrl)
.header("Content-Type", "application/json")
.body(requestBody.toString())
.execute();
if (response.getStatus() != 200) {
log.error("登录失败: {}", response.getStatus());
return null;
}
HttpCookie sessionCookie = response.getCookie(SESSION_COOKIE_NAME);
if (sessionCookie == null) {
log.error("登录失败PHPSESSID为空");
return null;
}
log.info("登录成功");
return sessionCookie;
} catch (Exception e) {
log.error("登录失败:", e);
return null;
}
}
@Transactional
public void fetchAllMediaPages(HttpCookie sessionCookie) {
int curPage = 1;
int retryCount = 0;
boolean hasMorePages = true;
while (hasMorePages && retryCount < MAX_RETRIES) {
try {
// 构造请求参数
JSONObject param = buildRequestParams(curPage);
// 发送请求
HttpResponse response = HttpRequest.post(dataUrl)
.header("Content-Type", "application/json")
.body(param.toString())
.cookie(sessionCookie)
.execute();
// 检查响应状态
if (response.getStatus() != 200) {
log.error("请求失败: {}", response.getStatus());
throw new RuntimeException("API请求失败 " + response.getStatus());
}
// 解析响应
JSONObject result = JSONUtil.parseObj(response.body());
if (result.getInt("code") != 200) {
log.error("API数据接口请求失败 code: {}, message: {}", result.getInt("code"), result.getStr("message"));
throw new RuntimeException("API数据接口请求失败 code: " + result.getInt("code"));
}
// 处理数据
boolean pageProcessed = processPageData(result);
if (!pageProcessed) {
throw new RuntimeException("当前页数据处理失败");
}
// 检查是否还有更多页
JSONObject pageInfo = result.getJSONObject("page");
int totalPages = pageInfo.getInt("page_nums");
curPage = pageInfo.getInt("cur_page") + 1;
hasMorePages = (curPage <= totalPages);
retryCount = 0; // 重置重试计数器
log.info("当前页 {}/{} 处理成功", curPage - 1, totalPages);
} catch (Exception e) {
retryCount++;
log.error("当前页 {} 处理失败,重试次数 {}/{}", curPage, retryCount, MAX_RETRIES, e);
if (retryCount >= MAX_RETRIES) {
log.error("当前页 {} 重试超过最大次数,终止任务", curPage);
throw new RuntimeException("分页请求失败,已达最大重试次数");
}
}
}
}
private JSONObject buildRequestParams(int curPage) {
JSONObject param = new JSONObject();
param.set("bh", deviceCode);
param.set("pssj_type", "3");
param.set("pssj_start", defaultStartDate);
param.set("pssj_end", defaultEndDate);
param.set("scsj_type", "3");
param.set("scsj_start", defaultStartDate);
param.set("scsj_end", defaultEndDate);
param.set("media_type", "1");
param.set("sjly", "1");
param.set("is_del", "0");
param.set("page_size", String.valueOf(pageSize));
param.set("cur_page", String.valueOf(curPage));
return param;
}
private boolean processPageData(JSONObject result) {
JSONArray lines = result.getJSONObject("data").getJSONArray("lines");
if (lines == null || lines.isEmpty()) {
log.warn("当前页没有数据");
return true;
}
List<EquipmentHistoryVideo> videos = new ArrayList<>();
for (Object item : lines) {
try {
JSONObject jsonObject = JSONUtil.parseObj(item);
String id = jsonObject.getStr("id");
boolean exists = equipmentHistoryVideoRepository.existsByLssjid(id);
if (!exists) {
EquipmentHistoryVideo video = new EquipmentHistoryVideo();
// 基本字段映射
video.setLssjid(id);
video.setZbmc(jsonObject.getStr("dname"));
video.setZbdm(jsonObject.getStr("hostbody"));
video.setZblxmc(jsonObject.getStr("sjly_name"));
video.setSpbfdz(jsonObject.getStr("play_url"));
video.setSpxzdz(jsonObject.getStr("download_url"));
// 日期字段特殊处理
if (jsonObject.getStr("createdate") != null) {
video.setCjsj(LocalDateTime.parse(jsonObject.getStr("createdate"), DATE_TIME_FORMATTER));
}
videos.add(video);
}
} catch (Exception e) {
log.error("当前数据解析失败: {}", item, e);
}
}
if (!videos.isEmpty()) {
try {
equipmentHistoryVideoRepository.saveAll(videos);
log.info("当前页数据保存成功", videos.size());
return true;
} catch (Exception e) {
log.error("当前页数据保存失败:", e);
}
}
return true;
}
}

View File

@ -0,0 +1,400 @@
package com.aisino.iles.lawenforcement.schedule.service;
import com.aisino.iles.common.util.StringUtils;
import com.aisino.iles.lawenforcement.config.ThirdPartyProperties;
import com.aisino.iles.lawenforcement.model.Agency;
import com.aisino.iles.lawenforcement.model.Officer;
import com.aisino.iles.lawenforcement.repository.AgencyRepository;
import com.aisino.iles.lawenforcement.repository.OfficerRepository;
import com.aisino.iles.lawenforcement.service.AuthService;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.smartlx.sso.client.model.AccessToken;
import com.smartlx.sso.client.properties.SsoClientProperties;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.util.*;
import java.util.stream.Collectors;
/**
* 执法人员信息同步调度服务
*
* 通过定时任务从外部API同步执法人员信息到本地数据库
*/
@Slf4j
@Service
public class OfficerScheduleService {
private final OfficerRepository officerRepository;
private final AgencyRepository agencyRepository;
private final AuthService authService;
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
private final ThirdPartyProperties thirdPartyProperties;
private final SsoClientProperties ssoClientProperties;
/**
* OfficerScheduleService constructor.
*
* @param officerRepository the officer repository
* @param agencyRepository the agency repository
* @param authService the auth service
* @param restTemplate the rest template
* @param objectMapper the object mapper
* @param thirdPartyProperties the third party properties
* @param ssoClientProperties the sso client properties
*/
@Autowired
public OfficerScheduleService(OfficerRepository officerRepository, AgencyRepository agencyRepository, AuthService authService, RestTemplate restTemplate, ObjectMapper objectMapper, ThirdPartyProperties thirdPartyProperties, SsoClientProperties ssoClientProperties) {
this.officerRepository = officerRepository;
this.agencyRepository = agencyRepository;
this.authService = authService;
this.restTemplate = restTemplate;
this.objectMapper = objectMapper;
this.thirdPartyProperties = thirdPartyProperties;
this.ssoClientProperties = ssoClientProperties;
}
/**
* 定时任务每天凌晨2点执行
*/
/// @Scheduled(cron = "${scheduler.task.officer.cron.expression:0 0 2 * * ?}")
@Scheduled(fixedRate = 3600000, initialDelay = 5000)
public void scheduleTask() {
log.info("开始执行执法人员信息同步任务...");
if (StringUtils.isEmpty(thirdPartyProperties.getPerson().getQuery())) {
log.error("执法人员API URL (third-party.person.query) 未配置。");
return;
}
if (StringUtils.isEmpty(thirdPartyProperties.getEnterprise().getYddh())) {
log.error("执法人员API令牌IDNO (third-party.enterprise.idno) 未配置。");
return;
}
if (thirdPartyProperties.getPerson().getRoles() == null || thirdPartyProperties.getPerson().getRoles().isEmpty()) {
log.error("执法人员角色列表 (third-party.person.roles) 未配置。");
return;
}
try {
List<ApiOfficer> allApiOfficers = new ArrayList<>();
// 遍历所有角色进行查询
for (String role : thirdPartyProperties.getPerson().getRoles()) {
log.info("正在查询角色: {}", role);
// 构建查询条件
Map<String, Object> requestBody = new HashMap<>();
Map<String, String> entity = new HashMap<>();
entity.put("jsdm", role); // 使用当前角色
requestBody.put("entity", entity);
log.info("准备从API获取执法人员数据. URL: {}, Role: {}", thirdPartyProperties.getPerson().getQuery(), role);
int currentPage = 1;
int totalPages = 1;
final int pageSize = 100; // 每页大小
do {
requestBody.put("page", currentPage);
requestBody.put("limit", pageSize);
String responseBody = fetchDataFromApi(requestBody, thirdPartyProperties.getPerson().getQuery());
if (responseBody != null) {
ApiResponse apiResponse = objectMapper.readValue(responseBody, ApiResponse.class);
if (apiResponse.isSuccess() && apiResponse.getData() != null && apiResponse.getData().getRecords() != null) {
allApiOfficers.addAll(apiResponse.getData().getRecords());
totalPages = apiResponse.getData().getPages();
log.info("成功获取第 {}/{} 页数据,记录数: {}", currentPage, totalPages, apiResponse.getData().getRecords().size());
} else {
log.error("API响应失败或数据为空. 角色: {}, 响应: {}", role, responseBody);
break; // 如果某页失败则停止该角色的后续分页
}
} else {
log.error("从API获取数据失败. 角色: {}, 页码: {}", role, currentPage);
break; // 如果获取失败则停止该角色的后续分页
}
currentPage++;
} while (currentPage <= totalPages);
}
if (allApiOfficers.isEmpty()) {
log.info("未从API获取到任何执法人员数据。");
return;
}
List<Officer> officersToSave = processApiOfficers(allApiOfficers);
officerRepository.saveAll(officersToSave);
log.info("成功同步 {} 名执法人员信息。", officersToSave.size());
} catch (Exception e) {
log.error("同步执法人员信息时发生未知异常", e);
}
}
/**
* 从第三方API获取数据
*
* @param requestBody 请求体
* @param url 请求URL
* @return 响应体
*/
@SneakyThrows
private String fetchDataFromApi(Map<String, Object> requestBody, String url) {
int maxRetries = 2; // 允许一次初始尝试和一次重试
for (int attempt = 1; attempt <= maxRetries; attempt++) {
AccessToken accessToken = authService.getTokenBackend(thirdPartyProperties.getEnterprise().getYddh());
if (accessToken == null || accessToken.getAccess_token() == null) {
log.error("获取访问令牌失败 (尝试 {}/{})URL: {}. 请检查AuthService配置和令牌提供者。", attempt, maxRetries, url);
throw new RuntimeException("获取API调用的访问令牌失败。");
}
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken.getAccess_token());
headers.setContentType(MediaType.APPLICATION_JSON);
try {
String requestBodyJson = objectMapper.writeValueAsString(requestBody);
HttpEntity<String> entity = new HttpEntity<>(requestBodyJson, headers);
log.debug("向API发送请求. URL: {}, Body: {}", url, requestBodyJson);
ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
if (response.getStatusCode().is2xxSuccessful()) {
return response.getBody();
}
// 处理401以外的非成功状态码
log.error("API请求失败 (尝试 {}/{})URL: {}, 状态码: {}, 响应: {}",
attempt, maxRetries, url, response.getStatusCode(), response.getBody());
return null; // 对于其他客户端或服务器错误直接返回null
} catch (HttpClientErrorException.Unauthorized e) {
log.warn("API请求未授权 (401) (尝试 {}/{})URL: {}. 令牌可能已过期。",
attempt, maxRetries, url);
if (attempt < maxRetries) {
try {
authService.refreshTokenBackend(accessToken.getAccess_token(), accessToken.getToken_type(), accessToken.getRefresh_token(), thirdPartyProperties.getEnterprise().getYddh());
log.info("请求刷新令牌成功。下一次尝试将使用新令牌。");
} catch (Exception refreshException) {
log.error("请求刷新令牌期间发生异常: {}. 中止对URL: {} 的重试。",
refreshException.getMessage(), url, refreshException);
return null; // 刷新失败不再重试
}
} else {
log.error("刷新令牌后重试仍然失败 (尝试 {}/{})URL: {}", attempt, maxRetries, url);
}
} catch (Exception e) {
log.error("调用API时发生异常 (尝试 {}/{})URL: {}", attempt, maxRetries, url, e);
}
}
return null; // 所有尝试失败后返回null
}
/**
* 处理从API获取的人员信息
*
* @param apiOfficers API返回的人员列表
* @return 处理后的Officer对象列表准备保存到数据库
*/
private List<Officer> processApiOfficers(List<ApiOfficer> apiOfficers) {
log.info("开始处理 {} 条API执法人员数据...", apiOfficers.size());
// 去重以人员唯一标识为准后出现的会覆盖先出现的
Map<String, ApiOfficer> distinctApiOfficersMap = apiOfficers.stream()
.filter(officer -> StringUtils.isNotEmpty(officer.getYhwybs()))
.collect(Collectors.toMap(ApiOfficer::getYhwybs, p -> p, (existing, replacement) -> replacement));
List<ApiOfficer> distinctApiOfficers = new ArrayList<>(distinctApiOfficersMap.values());
log.info("去重后还有 {} 条API执法人员数据", distinctApiOfficers.size());
// 预先加载所有机构以提高性能
List<Agency> allAgencies = agencyRepository.findAll();
Map<String, Agency> agencyCodeMap = allAgencies.stream()
.filter(agency -> StringUtils.isNotEmpty(agency.getAgencyCode()))
.collect(Collectors.toMap(agency -> StringUtils.trimEven0(agency.getAgencyCode()), agency -> agency, (a1, a2) -> a1));
log.info("已加载 {} 个机构用于匹配", agencyCodeMap.size());
List<Officer> officersToSave = new ArrayList<>();
for (ApiOfficer apiOfficer : distinctApiOfficers) {
// 仅处理有姓名的人员
if (StringUtils.isEmpty(apiOfficer.getXm())) {
log.warn("API返回的执法人员数据缺少 xm (姓名),跳过此条记录: {}", apiOfficer);
continue;
}
// 优先通过人员唯一标识查找不存在则创建新记录
Optional<Officer> existingOfficer = officerRepository.findByCertificateNo(apiOfficer.getYhwybs());
Officer officer = existingOfficer.orElse(new Officer());
// 设置基本信息
officer.setOfficerName(apiOfficer.getXm());
officer.setCertificateNo(apiOfficer.getYhwybs()); // 使用唯一标识作为证号
officer.setRole(apiOfficer.getJsdm());
officer.setRoleName(apiOfficer.getJsmc());
// 转换机构代码并查找对应机构
String apiOfficerAgencyCode = apiOfficer.getGajgjgdm();
Agency matchedAgency = findMatchingAgency(apiOfficerAgencyCode, agencyCodeMap);
if (matchedAgency != null) {
officer.setAgencyId(matchedAgency.getAgencyId());
log.debug("为执法人员 {} 找到匹配机构: {}({})",
apiOfficer.getXm(), matchedAgency.getAgencyName(), matchedAgency.getAgencyCode());
} else {
log.warn("无法为执法人员 {} 找到匹配的机构,原机构代码: {}",
apiOfficer.getXm(), apiOfficerAgencyCode);
// 跳过无法匹配机构的人员
continue;
}
officersToSave.add(officer);
}
log.info("成功处理 {} 条执法人员数据", officersToSave.size());
return officersToSave;
}
/**
* 从最大机构级别开始逐级递减匹配机构
*
* @param officerAgencyCode 执法人员所属的机构代码
* @param agencyCodeMap 所有本地机构的映射键为去掉末尾偶数0后的机构代码
* @return 匹配到的机构如果没有匹配则返回null
*/
private Agency findMatchingAgency(String officerAgencyCode, Map<String, Agency> agencyCodeMap) {
if (officerAgencyCode == null || officerAgencyCode.isEmpty()) {
return null;
}
// 去掉执法人员机构代码末尾的偶数个0
String trimmedOfficerCode = StringUtils.trimEven0(officerAgencyCode);
// 1. 先尝试完全匹配
Agency directMatch = agencyCodeMap.get(trimmedOfficerCode);
if (directMatch != null) {
log.debug("执法人员机构代码 {} 直接匹配到机构 {}", officerAgencyCode, directMatch.getAgencyName());
return directMatch;
}
// 2. 如果没有完全匹配从最长的机构代码开始尝试前缀匹配
// 按机构代码长度排序从长到短代表从较低级别到较高级别机构
List<String> sortedAgencyCodes = agencyCodeMap.keySet().stream()
.sorted((a, b) -> Integer.compare(b.length(), a.length()))
.toList();
// 只考虑级别2及以上的机构一般来说代码长度较短
for (String agencyCode : sortedAgencyCodes) {
// 检查该机构代码是否是执法人员机构代码的前缀
if (trimmedOfficerCode.startsWith(agencyCode)) {
Agency matchedAgency = agencyCodeMap.get(agencyCode);
log.debug("执法人员机构代码 {} 通过前缀匹配到机构 {} ({})",
officerAgencyCode, matchedAgency.getAgencyName(), agencyCode);
return matchedAgency;
}
}
// 3. 反向尝试看执法人员的机构代码是否是某个本地机构的前缀
// 这种情况比较少见执法人员可能来自更高级别的机构
for (String agencyCode : agencyCodeMap.keySet()) {
if (agencyCode.startsWith(trimmedOfficerCode)) {
Agency matchedAgency = agencyCodeMap.get(agencyCode);
log.debug("本地机构 {} ({}) 的代码以执法人员机构代码 {} 为前缀",
matchedAgency.getAgencyName(), agencyCode, officerAgencyCode);
return matchedAgency;
}
}
return null;
}
/**
* API响应结构定义
*/
@Getter
@Setter
private static class ApiResponse {
private String code;
private boolean success;
private ApiData data;
private String msg;
public boolean isSuccess() {
return "200".equals(code) && success;
}
}
/**
* API数据结构定义
*/
@Getter
@Setter
private static class ApiData {
private int offset;
private int limit;
@JsonAlias("totalCount")
private String totalCountStr;
@JsonAlias("list")
private List<ApiOfficer> records;
public int getTotalPage() {
if (limit <= 0) {
return 0;
}
return (int) Math.ceil((double) getTotalCount() / limit);
}
public int getTotalCount() {
try {
return Integer.parseInt(totalCountStr);
} catch (NumberFormatException e) {
log.warn("无法解析 totalCount: '{}'", totalCountStr, e);
return 0;
}
}
public int getPages() {
return getTotalPage();
}
}
/**
* API人员信息结构定义
*/
@Getter
@Setter
@ToString
private static class ApiOfficer {
// 人员唯一标识
private String yhwybs;
// 姓名
private String xm;
// 机构代码
private String gajgjgdm;
// 角色代码
private String jsdm;
// 角色名称
private String jsmc;
}
}

View File

@ -0,0 +1,258 @@
package com.aisino.iles.lawenforcement.schedule.service;
import cn.hutool.http.HttpUtil;
import com.aisino.iles.common.util.BeanUtils;
import com.aisino.iles.common.util.Md5Utils;
import com.aisino.iles.lawenforcement.model.Materials;
import com.aisino.iles.lawenforcement.model.ReportCheck;
import com.aisino.iles.lawenforcement.repository.MaterialsRepository;
import com.aisino.iles.lawenforcement.repository.ReportCheckRepository;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
/**
* 举报核查定时任务
*/
@Service
@Slf4j
public class ReportCheckScheduleService {
private final String queryUrl;
private final String singleUrl;
private final String sign;
private final ObjectMapper objectMapper;
private final ReportCheckRepository reportCheckRepo;
private final MaterialsRepository materialsRepo;
public ReportCheckScheduleService(@Value("${third-party.report_check.query:}") String queryUrl,
@Value("${third-party.report_check.single:}") String singleUrl,
@Value("${third-party.report_check.sign:}") String sign,
ObjectMapper objectMapper,
ReportCheckRepository reportCheckRepo,
MaterialsRepository materialsRepo) {
this.queryUrl = queryUrl;
this.singleUrl = singleUrl;
this.sign = sign;
this.objectMapper = objectMapper;
this.reportCheckRepo = reportCheckRepo;
this.materialsRepo = materialsRepo;
}
/**
* 12350投诉举报信息导入
* 每隔一小时执行一次
*/
@Scheduled(fixedDelay = 120000)
@Transactional
public void scheduledTask() {
log.info("开始导入举报核查信息...");
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String create_time = null;
LocalDateTime maxAcceptTime = reportCheckRepo.getMaxAcceptTime();
if (null != maxAcceptTime) {
create_time = "[\"" + maxAcceptTime.format(df) + "\",\"" + LocalDateTime.now().format(df) + "\"]";
}
extracted(create_time);
}
private void extracted(String create_time) {
try {
int page = 1, pagesize = 99999;
log.info("条件={}", "{\"page\": " + page + ",\"pagesize\": " + pagesize + ",\"create_time\": " + create_time + "}");
String body = HttpUtil.createPost(queryUrl)
.header("Content-Type", "application/json")
.header("Sign", Md5Utils.getMd5Str(sign))
.body("{\"page\": " + page + ",\"pagesize\": " + pagesize + ",\"create_time\": " + create_time + "}")
.execute()
.body();
log.info("信息查询结果:{}", body);
JsonNode jsonNode = objectMapper.readValue(body, JsonNode.class);
if (jsonNode.has("code") && 1 == jsonNode.get("code").asInt() && jsonNode.has("data")) {
JsonNode data = objectMapper.readValue(jsonNode.get("data").toString(), JsonNode.class);
if (null != data && data.has("result")) {
JsonNode arrNode = data.get("result");
if (arrNode.isArray()) {
for (JsonNode node : arrNode) {
ReportCheckInterfaceDto dto = objectMapper.readValue(node.toString(), ReportCheckInterfaceDto.class);
ReportCheck reportCheck = new ReportCheck();
LocalDateTime now = LocalDateTime.now();
reportCheckRepo.findByPumpId(dto.getId()).ifPresent(o -> {
BeanUtils.copyProperties(o, reportCheck);
List<String> ids = materialsRepo.findByLinkId(o.getPcid()).stream().map(Materials::getMaterialsId).collect(Collectors.toList());
materialsRepo.deleteAllById(ids);
reportCheck.setUpdateTime(now);
});
reportCheck.setPumpId(dto.getId());//数据id
// (dto.getWork_order_number());//工单编号
// (dto.getWork_order_level());//工单等级
reportCheck.setAcceptTime(dto.getCreate_time());//受理时间
reportCheck.setReportCanal(dto.getComplaint_resource_one());//一级举报渠道-举报渠道
reportCheck.setCanalCategory(dto.getComplaint_resource_two());//二级举报渠道-渠道分类
reportCheck.setReportCategory(dto.getComplaint_kind_one());//一级投诉类别-投诉类别
reportCheck.setCategorization(dto.getComplaint_kind_two());//二级投诉类别-类别分类
reportCheck.setReporterName(dto.getComplainant_name());//姓名
reportCheck.setReporterPhone(dto.getComplaint_phone());//联系方式
if (StringUtils.hasText(dto.getComplaint_phone()) && dto.getComplaint_phone().contains("**"))
reportCheck.setIsAnon("1");
reportCheck.setReporterSex(dto.getComplainant_sex());//性别
reportCheck.setComplainTime(dto.getComplaint_time());//投诉时间
reportCheck.setBriefFact(dto.getReport_situation());//举报情况
reportCheck.setIndustryType(dto.getTrade());//所属行业
reportCheck.setReportLocal(dto.getLocation_data());//举报问题所在地
String detailBody = HttpUtil.createPost(singleUrl)
.header("Content-Type", "application/json")
.header("sign", Md5Utils.getMd5Str(sign))
.body("{\"id\": \"" + dto.getId() + "\"}")
.execute()
.body();
JsonNode detailNode = objectMapper.readValue(detailBody, JsonNode.class);
if (detailNode.has("code") && 1 == detailNode.get("code").asInt() && detailNode.has("data")) {
ReportCheckInterfaceDto detailDto = objectMapper.readValue(detailNode.get("data").toString(), ReportCheckInterfaceDto.class);
reportCheck.setRemark(detailDto.getRemark());//备注
reportCheck.setTransferDistrict(detailDto.getTransfer_district());//转办区县
reportCheck.setResTime(detailDto.getReply_time());//区县回复时间
reportCheck.setReplyContent(detailDto.getReply_content());//回复内容
// reportCheck.setComplainAcceptStatus(detailDto.getComplaint_status());//受理状态
reportCheck.setDataSource("2");
ReportCheck save = reportCheckRepo.save(reportCheck);
if (null != detailDto.getAttach() && !detailDto.getAttach().isEmpty()) {
detailDto.getAttach().forEach(attachDto -> {
Materials materials = new Materials();
materials.setLrsj(now);
String name = attachDto.getName();
materials.setFileType(StringUtils.hasText(name) ? name.split("\\.")[1] : null);
materials.setName(name);
materials.setSavePath(attachDto.getUrl());
materials.setIsOriginal("2");
materials.setMaterialsTypeCode("1");
materials.setMaterialsTypeName("举报核查材料");
materials.setLinkId(save.getPcid());
materialsRepo.save(materials);
});
}
}
}
}
} else log.info("没有数据list");
} else log.info("没有数据");
} catch (Exception e) {
log.info("举报核查获取异常:" + e);
}
}
@Data
public static class ReportCheckInterfaceDto {
/**
* 数据id
*/
private String id;
/**
* 工单编号
*/
private String work_order_number;
/**
* 工单等级
*/
private String work_order_level;
/**
* 受理时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime create_time;
/**
* 一级举报渠道
*/
private String complaint_resource_one;
/**
* 二级举报渠道
*/
private String complaint_resource_two;
/**
* 一级投诉类别
*/
private String complaint_kind_one;
/**
* 二级投诉类别
*/
private String complaint_kind_two;
/**
* 姓名
*/
private String complainant_name;
/**
* 联系方式
*/
private String complaint_phone;
/**
* 性别
*/
private String complainant_sex;
/**
* 投诉时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime complaint_time;
/**
* 举报情况
*/
private String report_situation;
/**
* 所属行业
*/
private String trade;
/**
* 举报问题所在地
*/
private String location_data;
/* ************************详情字段***********************************/
/**
* 备注
*/
private String remark;
/**
* 转办区县
*/
private String transfer_district;
/**
* 区县回复时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime reply_time;
/**
* 相关材料
*/
private List<AttachDto> attach;
/**
* 回复内容
*/
private String reply_content;
/**
* 受理状态 1不予受理 2受理中 3 已受理
*/
private String complaint_status;
/**
* 受理状态
*/
private String complaint_status_text;
}
@Data
public static class AttachDto {
private String name;
private String uid;
private String url;
}
}