package com.ruoyi.project.service; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.http.HttpUtilsEx; import com.ruoyi.project.domain.*; import com.ruoyi.project.mapper.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.*; import java.util.*; /** * 词库同步客户端服务 - 包含数据保存到数据库 */ @Service public class TrsWordSyncClientService { private static final Logger log = LoggerFactory.getLogger(TrsWordSyncClientService.class); private static final int batchSize = 100; // 最后同步时间戳文件路径 private static final String LAST_SYNC_TIME_FILE = "lastSyncTime.txt"; // 默认最后同步时间(2025-01-01 00:00:00) private static final long DEFAULT_LAST_SYNC_TIME = 1770652800000L; // 注入各个词库的服务 @Autowired private ITrsSensitiveWordsService sensitiveWordsService; @Autowired private ITrsDomainWordsService domainWordsService; @Autowired private ITrsNameWordsService nameWordsService; @Autowired private ITrsPolicyWordsService policyWordsService; @Autowired private ITrsTechnicalWordsService technicalWordsService; @Autowired private ITrsNamenmgWordsService namenmgWordsService; @Autowired private ITrsRegionWordsService regionWordsService; /** * 同步词库数据(全量或增量)并保存到数据库 */ // @Transactional(rollbackFor = Exception.class) public AjaxResult syncWords(String wordType) { boolean syncEnabled = true; // String serverUrl = "https://www.nmg.gov.cn/trsjd/"; String serverUrl = "http://localhost:90/nmg"; String apiKey = "TRSword123!@#"; if (!syncEnabled) { log.warn("词库同步功能已禁用"); return AjaxResult.error("词库同步功能已禁用"); } try { // 构建请求URL StringBuilder urlBuilder = new StringBuilder(serverUrl); if (!serverUrl.endsWith("/")) { urlBuilder.append("/"); } urlBuilder.append("project/check/sync"); // 构建请求参数 Map params = new HashMap<>(); params.put("wordType", wordType); // 从文件读取最后同步时间 Long lastSyncTimestamp = readLastSyncTime(); if (lastSyncTimestamp != null && lastSyncTimestamp > 0) { params.put("lastSyncTime", lastSyncTimestamp); log.info("执行增量同步,词库类型: {},最后同步时间: {}", wordType, new Date(lastSyncTimestamp)); } else { log.info("执行全量同步,词库类型: {}", wordType); } String url = urlBuilder.toString(); String paramStr = HttpUtilsEx.buildParams(params); // 构建请求头 Map headers = new HashMap<>(); headers.put("X-API-KEY", apiKey); headers.put("Accept", "application/json"); log.info("开始同步请求,URL: {}, 参数: {}", url, paramStr); // 发送HTTP请求(使用支持Header的HttpUtilsEx) String response = HttpUtilsEx.sendGet(url, paramStr, headers); if (StringUtils.isEmpty(response)) { return AjaxResult.error("同步请求失败,服务器无响应"); } log.debug("收到同步响应: {}", response); // 解析响应 JSONObject result = JSON.parseObject(response); int code = result.getIntValue("code"); String msg = result.getString("msg"); Object data = result.get("data"); if (code == 0 && data != null) { JSONObject dataObj = (JSONObject) data; // 更新最后同步时间 Long newSyncTime = dataObj.getLong("syncTime"); if (newSyncTime != null) { // 保存到文件 saveLastSyncTime(newSyncTime); log.info("同步成功,更新时间戳: {}", new Date(newSyncTime)); } // 处理返回的数据并保存到数据库 int totalCount = dataObj.getIntValue("totalCount"); String wordTypeName = dataObj.getString("wordTypeName"); // 保存数据到数据库 int savedCount = saveWordsToDatabase(dataObj, wordType); log.info("同步完成,词库类型: {},接收数据量: {} 条,保存成功: {} 条", wordTypeName, totalCount, savedCount); Map resultMap = new HashMap<>(); resultMap.put("syncTime", newSyncTime); resultMap.put("wordType", wordTypeName); resultMap.put("totalCount", totalCount); resultMap.put("savedCount", savedCount); resultMap.put("message", "同步并保存成功"); return AjaxResult.success(msg, resultMap); } else { log.error("同步失败,错误信息: {}", msg); return AjaxResult.error(msg); } } catch (Exception e) { log.error("词库同步异常", e); return AjaxResult.error("同步异常: " + e.getMessage()); } } /** * 从文件读取最后同步时间 */ private Long readLastSyncTime() { try { File file = new File(LAST_SYNC_TIME_FILE); if (!file.exists()) { log.info("最后同步时间文件不存在,使用默认时间"); return DEFAULT_LAST_SYNC_TIME; } try (BufferedReader reader = new BufferedReader(new FileReader(file))) { String line = reader.readLine(); if (StringUtils.isNotEmpty(line)) { Long timestamp = Long.parseLong(line.trim()); log.info("从文件读取最后同步时间: {}", new Date(timestamp)); return timestamp; } } } catch (Exception e) { log.error("读取最后同步时间失败", e); } return DEFAULT_LAST_SYNC_TIME; } /** * 保存最后同步时间到文件 */ private void saveLastSyncTime(Long timestamp) { try { File file = new File(LAST_SYNC_TIME_FILE); try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { writer.write(String.valueOf(timestamp)); writer.flush(); log.info("保存最后同步时间到文件: {}", new Date(timestamp)); } } catch (Exception e) { log.error("保存最后同步时间失败", e); } } /** * 保存词库数据到数据库 */ private int saveWordsToDatabase(JSONObject data, String wordType) { int savedCount = 0; try { if ("all".equals(wordType) || wordType == null) { // 保存所有类型的词库数据 savedCount += saveSensitiveWords(data.getJSONObject("data").getJSONArray("sensitive")); savedCount += saveDomainWords(data.getJSONObject("data").getJSONArray("domain")); savedCount += saveNameWords(data.getJSONObject("data").getJSONArray("name")); savedCount += savePolicyWords(data.getJSONObject("data").getJSONArray("policy")); savedCount += saveTechnicalWords(data.getJSONObject("data").getJSONArray("technical")); savedCount += saveNamenmgWords(data.getJSONObject("data").getJSONArray("namenmg")); savedCount += saveRegionWords(data.getJSONObject("data").getJSONArray("region")); } else { // 保存指定类型的词库数据 switch (wordType.toLowerCase()) { case "sensitive": savedCount += saveSensitiveWords(data.getJSONObject("data").getJSONArray("sensitive")); break; case "domain": savedCount += saveDomainWords(data.getJSONObject("data").getJSONArray("domain")); break; case "name": savedCount += saveNameWords(data.getJSONObject("data").getJSONArray("name")); break; case "policy": savedCount += savePolicyWords(data.getJSONObject("data").getJSONArray("policy")); break; case "technical": savedCount += saveTechnicalWords(data.getJSONObject("data").getJSONArray("technical")); break; case "namenmg": savedCount += saveNamenmgWords(data.getJSONObject("data").getJSONArray("namenmg")); break; case "region": savedCount += saveRegionWords(data.getJSONObject("data").getJSONArray("region")); break; } } } catch (Exception e) { log.error("保存词库数据到数据库失败", e); throw new RuntimeException("保存数据失败: " + e.getMessage(), e); } return savedCount; } /** * 保存常见错误词库(按wrongWord查询) */ private int saveSensitiveWords(JSONArray dataArray) { if (dataArray == null || dataArray.isEmpty()) { return 0; } int savedCount = 0; List batchList = new ArrayList<>(); for (int i = 0; i < dataArray.size(); i++) { JSONObject item = dataArray.getJSONObject(i); TrsSensitiveWords word = new TrsSensitiveWords(); // 设置字段值 // word.setId(item.getLong("id")); word.setWrongWord(item.getString("wrongWord")); word.setCorrectWord(item.getString("correctWord")); word.setErrorType(item.getString("errorType")); word.setErrorGrade(item.getString("errorGrade")); word.setDictType(item.getString("dictType")); word.setFlag(item.getInteger("flag")); word.setStatus(item.getString("status")); word.setTime(item.getDate("time")); // 处理日期字段 Long time = item.getLong("time"); if (time != null && time > 0) { word.setTime(new Date(time)); } Long effectstart = item.getLong("effectstart"); if (effectstart != null && effectstart > 0) { word.setEffectstart(new Date(effectstart)); } Long effectend = item.getLong("effectend"); if (effectend != null && effectend > 0) { word.setEffectend(new Date(effectend)); } batchList.add(word); // 批量保存 if (batchList.size() >= batchSize) { savedCount += batchInsertSensitiveWords(batchList); batchList.clear(); } } // 保存剩余数据 if (!batchList.isEmpty()) { savedCount += batchInsertSensitiveWords(batchList); } log.info("保存常见错误词库 {} 条", savedCount); return savedCount; } /** * 批量插入常见错误词库(按wrongWord查询) */ @Autowired private TrsSensitiveWordsMapper trsSensitiveWordsMapper; private int batchInsertSensitiveWords(List wordList) { int count = 0; for (TrsSensitiveWords word : wordList) { try { // 按wrongWord查询是否已存在 TrsSensitiveWords query = new TrsSensitiveWords(); query.setWrongWord(word.getWrongWord()); List existingList = trsSensitiveWordsMapper.selectTrsSensitiveWordsList(query); if (existingList != null && !existingList.isEmpty()) { // 更新现有记录 TrsSensitiveWords existing = existingList.get(0); word.setId(existing.getId()); trsSensitiveWordsMapper.updateTrsSensitiveWords(word); } else { // 插入新记录 trsSensitiveWordsMapper.insertTrsSensitiveWords(word); } count++; } catch (Exception e) { log.error("保存常见错误词条失败: {}", word.getWrongWord(), e); } } return count; } /** * 保存领域常识词库(按wrongWord查询) */ private int saveDomainWords(JSONArray dataArray) { if (dataArray == null || dataArray.isEmpty()) { return 0; } int savedCount = 0; List batchList = new ArrayList<>(); for (int i = 0; i < dataArray.size(); i++) { JSONObject item = dataArray.getJSONObject(i); TrsDomainWords word = new TrsDomainWords(); // 设置字段值 // word.setId(item.getLong("id")); word.setWrongWord(item.getString("wrongWord")); word.setDomainType(item.getString("domainType")); word.setDictType(item.getString("dictType")); word.setFlag(item.getInteger("flag")); word.setStatus(item.getString("status")); word.setTime(item.getDate("time")); // 处理日期字段 Long time = item.getLong("time"); if (time != null && time > 0) { word.setTime(new Date(time)); } Long effectstart = item.getLong("effectstart"); if (effectstart != null && effectstart > 0) { word.setEffectstart(new Date(effectstart)); } Long effectend = item.getLong("effectend"); if (effectend != null && effectend > 0) { word.setEffectend(new Date(effectend)); } batchList.add(word); // 批量保存 if (batchList.size() >= batchSize) { savedCount += batchInsertDomainWords(batchList); batchList.clear(); } } if (!batchList.isEmpty()) { savedCount += batchInsertDomainWords(batchList); } log.info("保存领域常识词库 {} 条", savedCount); return savedCount; } @Autowired private TrsDomainWordsMapper trsDomainWordsMapper; private int batchInsertDomainWords(List wordList) { int count = 0; for (TrsDomainWords word : wordList) { try { // 按wrongWord查询 TrsDomainWords query = new TrsDomainWords(); query.setWrongWord(word.getWrongWord()); List existingList = trsDomainWordsMapper.selectTrsDomainWordsList(query); if (existingList != null && !existingList.isEmpty()) { TrsDomainWords existing = existingList.get(0); word.setId(existing.getId()); trsDomainWordsMapper.updateTrsDomainWords(word); } else { trsDomainWordsMapper.insertTrsDomainWords(word); } count++; } catch (Exception e) { log.error("保存领域常识词条失败: {}", word.getWrongWord(), e); } } return count; } /** * 保存人名职务词库(按wrongWord查询) */ private int saveNameWords(JSONArray dataArray) { if (dataArray == null || dataArray.isEmpty()) { return 0; } int savedCount = 0; List batchList = new ArrayList<>(); for (int i = 0; i < dataArray.size(); i++) { JSONObject item = dataArray.getJSONObject(i); TrsNameWords word = new TrsNameWords(); // 设置字段值 // word.setId(item.getLong("id")); word.setWrongWord(item.getString("wrongWord")); word.setCountry(item.getString("country")); word.setDutyAll(item.getString("dutyAll")); word.setDutyShort(item.getString("dutyShort")); word.setSort(item.getString("sort")); word.setDictType(item.getString("dictType")); word.setFlag(item.getInteger("flag")); word.setStatus(item.getString("status")); word.setAccord(item.getString("accord")); word.setSource(item.getString("source")); word.setLinkurl(item.getString("linkurl")); word.setTime(item.getDate("time")); // 处理日期字段 Long time = item.getLong("time"); if (time != null && time > 0) { word.setTime(new Date(time)); } Long effectstart = item.getLong("effectstart"); if (effectstart != null && effectstart > 0) { word.setEffectstart(new Date(effectstart)); } Long effectend = item.getLong("effectend"); if (effectend != null && effectend > 0) { word.setEffectend(new Date(effectend)); } batchList.add(word); if (batchList.size() >= batchSize) { savedCount += batchInsertNameWords(batchList); batchList.clear(); } } if (!batchList.isEmpty()) { savedCount += batchInsertNameWords(batchList); } log.info("保存人名职务词库 {} 条", savedCount); return savedCount; } @Autowired private TrsNameWordsMapper trsNameWordsMapper; private int batchInsertNameWords(List wordList) { int count = 0; for (TrsNameWords word : wordList) { try { // 按wrongWord查询 TrsNameWords query = new TrsNameWords(); query.setWrongWord(word.getWrongWord()); List existingList = trsNameWordsMapper.selectTrsNameWordsList(query); if (existingList != null && !existingList.isEmpty()) { TrsNameWords existing = existingList.get(0); word.setId(existing.getId()); trsNameWordsMapper.updateTrsNameWords(word); } else { trsNameWordsMapper.insertTrsNameWords(word); } count++; } catch (Exception e) { log.error("保存人名职务词条失败: {}", word.getWrongWord(), e); } } return count; } /** * 保存政治常识词库(按wrongWord查询) */ private int savePolicyWords(JSONArray dataArray) { if (dataArray == null || dataArray.isEmpty()) { return 0; } int savedCount = 0; List batchList = new ArrayList<>(); for (int i = 0; i < dataArray.size(); i++) { JSONObject item = dataArray.getJSONObject(i); TrsPolicyWords word = new TrsPolicyWords(); // 设置字段值 // word.setId(item.getLong("id")); word.setWrongWord(item.getString("wrongWord")); word.setErrorRule(item.getString("errorRule")); word.setErrorType(item.getString("errorType")); word.setErrorGrade(item.getString("errorGrade")); word.setDictType(item.getString("dictType")); word.setFlag(item.getInteger("flag")); word.setStatus(item.getString("status")); word.setAccord(item.getString("accord")); word.setSource(item.getString("source")); word.setLinkurl(item.getString("linkurl")); word.setTime(item.getDate("time")); // 处理日期字段 Long time = item.getLong("time"); if (time != null && time > 0) { word.setTime(new Date(time)); } Long effectstart = item.getLong("effectstart"); if (effectstart != null && effectstart > 0) { word.setEffectstart(new Date(effectstart)); } Long effectend = item.getLong("effectend"); if (effectend != null && effectend > 0) { word.setEffectend(new Date(effectend)); } batchList.add(word); if (batchList.size() >= batchSize) { savedCount += batchInsertPolicyWords(batchList); batchList.clear(); } } if (!batchList.isEmpty()) { savedCount += batchInsertPolicyWords(batchList); } log.info("保存政治常识词库 {} 条", savedCount); return savedCount; } @Autowired private TrsPolicyWordsMapper trsPolicyWordsMapper; private int batchInsertPolicyWords(List wordList) { int count = 0; for (TrsPolicyWords word : wordList) { try { // 按wrongWord查询 TrsPolicyWords query = new TrsPolicyWords(); query.setWrongWord(word.getWrongWord()); List existingList = trsPolicyWordsMapper.selectTrsPolicyWordsList(query); if (existingList != null && !existingList.isEmpty()) { TrsPolicyWords existing = existingList.get(0); word.setId(existing.getId()); trsPolicyWordsMapper.updateTrsPolicyWords(word); } else { trsPolicyWordsMapper.insertTrsPolicyWords(word); } count++; } catch (Exception e) { log.error("保存政治常识词条失败: {}", word.getWrongWord(), e); } } return count; } /** * 保存专业术语词库(按wrongWord查询) */ private int saveTechnicalWords(JSONArray dataArray) { if (dataArray == null || dataArray.isEmpty()) { return 0; } int savedCount = 0; List batchList = new ArrayList<>(); for (int i = 0; i < dataArray.size(); i++) { JSONObject item = dataArray.getJSONObject(i); TrsTechnicalWords word = new TrsTechnicalWords(); // 设置字段值 // word.setId(item.getLong("id")); word.setWrongWord(item.getString("wrongWord")); word.setErrorType(item.getString("errorType")); word.setDictType(item.getString("dictType")); word.setFlag(item.getInteger("flag")); word.setStatus(item.getString("status")); word.setAccord(item.getString("accord")); word.setSource(item.getString("source")); word.setLinkurl(item.getString("linkurl")); word.setTime(item.getDate("time")); // 处理日期字段 Long time = item.getLong("time"); if (time != null && time > 0) { word.setTime(new Date(time)); } Long effectstart = item.getLong("effectstart"); if (effectstart != null && effectstart > 0) { word.setEffectstart(new Date(effectstart)); } Long effectend = item.getLong("effectend"); if (effectend != null && effectend > 0) { word.setEffectend(new Date(effectend)); } batchList.add(word); if (batchList.size() >= batchSize) { savedCount += batchInsertTechnicalWords(batchList); batchList.clear(); } } if (!batchList.isEmpty()) { savedCount += batchInsertTechnicalWords(batchList); } log.info("保存专业术语词库 {} 条", savedCount); return savedCount; } @Autowired private TrsTechnicalWordsMapper trsTechnicalWordsMapper; private int batchInsertTechnicalWords(List wordList) { int count = 0; for (TrsTechnicalWords word : wordList) { try { // 按wrongWord查询 TrsTechnicalWords query = new TrsTechnicalWords(); query.setWrongWord(word.getWrongWord()); List existingList = trsTechnicalWordsMapper.selectTrsTechnicalWordsList(query); if (existingList != null && !existingList.isEmpty()) { TrsTechnicalWords existing = existingList.get(0); word.setId(existing.getId()); trsTechnicalWordsMapper.updateTrsTechnicalWords(word); } else { trsTechnicalWordsMapper.insertTrsTechnicalWords(word); } count++; } catch (Exception e) { log.error("保存专业术语词条失败: {}", word.getWrongWord(), e); } } return count; } /** * 保存内蒙古自治区领导人词库(按wrongWord查询) */ private int saveNamenmgWords(JSONArray dataArray) { if (dataArray == null || dataArray.isEmpty()) { return 0; } int savedCount = 0; List batchList = new ArrayList<>(); for (int i = 0; i < dataArray.size(); i++) { JSONObject item = dataArray.getJSONObject(i); TrsNamenmgWords word = new TrsNamenmgWords(); // 设置字段值 // word.setId(item.getLong("id")); word.setWrongWord(item.getString("wrongWord")); word.setCountry(item.getString("country")); word.setDutyAll(item.getString("dutyAll")); word.setDutyShort(item.getString("dutyShort")); word.setSort(item.getString("sort")); word.setDictType(item.getString("dictType")); word.setFlag(item.getInteger("flag")); word.setStatus(item.getString("status")); word.setTime(item.getDate("time")); // 处理日期字段 Long time = item.getLong("time"); if (time != null && time > 0) { word.setTime(new Date(time)); } batchList.add(word); if (batchList.size() >= batchSize) { savedCount += batchInsertNamenmgWords(batchList); batchList.clear(); } } if (!batchList.isEmpty()) { savedCount += batchInsertNamenmgWords(batchList); } log.info("保存内蒙古领导人词库 {} 条", savedCount); return savedCount; } private int batchInsertNamenmgWords(List wordList) { int count = 0; for (TrsNamenmgWords word : wordList) { try { // 按wrongWord查询 TrsNamenmgWords query = new TrsNamenmgWords(); query.setWrongWord(word.getWrongWord()); List existingList = namenmgWordsService.selectTrsNamenmgWordsList(query); if (existingList != null && !existingList.isEmpty()) { TrsNamenmgWords existing = existingList.get(0); word.setId(existing.getId()); namenmgWordsService.updateTrsNamenmgWords(word); } else { namenmgWordsService.insertTrsNamenmgWords(word); } count++; } catch (Exception e) { log.error("保存内蒙古领导人词条失败: {}", word.getWrongWord(), e); } } return count; } /** * 保存内蒙古自治区地区词库(按code查询) */ private int saveRegionWords(JSONArray dataArray) { if (dataArray == null || dataArray.isEmpty()) { return 0; } int savedCount = 0; List batchList = new ArrayList<>(); for (int i = 0; i < dataArray.size(); i++) { JSONObject item = dataArray.getJSONObject(i); TrsRegionWords word = new TrsRegionWords(); // 设置字段值 // word.setId(item.getLong("id")); word.setCode(item.getString("code")); word.setName(item.getString("name")); word.setParentCode(item.getString("parentCode")); word.setIsAble(item.getString("isAble")); word.setOrderNum(item.getInteger("orderNum")); word.setBannerName(item.getString("bannerName")); word.setRegionLevel(item.getString("regionLevel")); word.setShortName(item.getString("shortName")); word.setIsDelete(item.getString("isDelete")); word.setStatus(item.getString("status")); word.setTime(item.getDate("time")); // 处理日期字段 Long time = item.getLong("time"); if (time != null && time > 0) { word.setTime(new Date(time)); } batchList.add(word); if (batchList.size() >= batchSize) { savedCount += batchInsertRegionWords(batchList); batchList.clear(); } } if (!batchList.isEmpty()) { savedCount += batchInsertRegionWords(batchList); } log.info("保存内蒙古地区词库 {} 条", savedCount); return savedCount; } private int batchInsertRegionWords(List wordList) { int count = 0; for (TrsRegionWords word : wordList) { try { // 根据code查找现有记录 TrsRegionWords query = new TrsRegionWords(); query.setCode(word.getCode()); List existingList = regionWordsService.selectTrsRegionWordsList(query); if (existingList != null && !existingList.isEmpty()) { // 更新现有记录 TrsRegionWords existing = existingList.get(0); word.setId(existing.getId()); regionWordsService.updateTrsRegionWords(word); } else { // 插入新记录 regionWordsService.insertTrsRegionWords(word); } count++; } catch (Exception e) { log.error("保存内蒙古地区词条失败: {}", word.getName(), e); } } return count; } // 其他辅助方法 public AjaxResult syncAllWords() { return syncWords("all"); } public AjaxResult syncSensitiveWords() { return syncWords("sensitive"); } public AjaxResult syncDomainWords() { return syncWords("domain"); } public AjaxResult syncNameWords() { return syncWords("name"); } public AjaxResult syncPolicyWords() { return syncWords("policy"); } public AjaxResult syncTechnicalWords() { return syncWords("technical"); } public AjaxResult syncNamenmgWords() { return syncWords("namenmg"); } public AjaxResult syncRegionWords() { return syncWords("region"); } /** * 重置同步时间(手动重置文件中的时间) */ public AjaxResult resetSync() { try { saveLastSyncTime(DEFAULT_LAST_SYNC_TIME); log.info("同步记录已重置,下次将执行全量同步"); return AjaxResult.success("同步记录已重置"); } catch (Exception e) { log.error("重置同步时间失败", e); return AjaxResult.error("重置同步时间失败: " + e.getMessage()); } } /** * 获取当前最后同步时间 */ public AjaxResult getLastSyncTime() { Long timestamp = readLastSyncTime(); Map result = new HashMap<>(); result.put("timestamp", timestamp); result.put("timeString", new Date(timestamp)); return AjaxResult.success(result); } /** * 设置最后同步时间 */ public AjaxResult setLastSyncTime(Long timestamp) { saveLastSyncTime(timestamp); return AjaxResult.success("设置成功"); } }