fix(aihr): redact processing error details

This commit is contained in:
2026-07-14 08:42:24 +08:00
parent e311a18414
commit c16dc0e203
11 changed files with 48 additions and 31 deletions
@@ -87,14 +87,14 @@ public class AihrSpeechController {
SysOssVo oss = ossService.upload(file);
return R.ok(new TtsResponse(oss.getUrl(), "openai-compatible", oss.getOssId(), inlineAudioUrl));
} catch (Exception e) {
log.warn("tts audio upload failed: {}", e.getMessage());
log.warn("tts audio upload failed(处理错误已隐藏)");
return R.ok(new TtsResponse(inlineAudioUrl, "openai-compatible"));
} finally {
if (tempFile != null) {
try {
Files.deleteIfExists(tempFile);
} catch (IOException e) {
log.warn("delete tts temp file failed: {}", e.getMessage());
log.warn("delete tts temp file failed(处理错误已隐藏)");
}
}
}
@@ -68,7 +68,7 @@ public class AihrCaseService {
} catch (IllegalStateException e) {
throw e;
} catch (Exception e) {
log.warn("case audio upload failed: {}", e.getMessage());
log.warn("case audio upload failed(处理错误已隐藏)");
throw new IllegalStateException("语音上传或转写失败");
}
}
@@ -190,7 +190,7 @@ public class AihrCaseService {
ORDER BY project_ext_org_id
""", (rs, rowNum) -> rs.getString("project_ext_org_id"), tenantId(), username, username);
} catch (DataAccessException e) {
log.warn("resolve app user project scope failed: {}", e.getMessage());
log.warn("resolve app user project scope failed(处理错误已隐藏)");
return List.of();
}
}
@@ -215,7 +215,7 @@ public class AihrCaseService {
""", Integer.class, tenantId(), username, username);
return count != null && count > 0;
} catch (DataAccessException e) {
log.warn("resolve case contributor failed: {}", e.getMessage());
log.warn("resolve case contributor failed(处理错误已隐藏)");
return false;
}
}
@@ -335,7 +335,7 @@ public class AihrCaseService {
}
return Optional.of(new CaseSummary(summary, tags, truncate(maskSensitiveText(root.path("aiSummary").asText("")), 180), "real-llm"));
} catch (Exception e) {
log.warn("case summary parse failed, uses local transcript summary: {}", e.getMessage());
log.warn("case summary parse failed, uses local transcript summary(处理错误已隐藏)");
return Optional.empty();
}
}
@@ -420,7 +420,7 @@ public class AihrInterviewService {
}
return questions.size() == 3 ? Optional.of(new GeneratedQuestions(questions, "real-llm")) : Optional.empty();
} catch (Exception e) {
log.warn("interview question parse failed, uses local rubric: {}", e.getMessage());
log.warn("interview question parse failed, uses local rubric(处理错误已隐藏)");
return Optional.empty();
}
}
@@ -447,7 +447,7 @@ public class AihrInterviewService {
"real-llm"
));
} catch (Exception e) {
log.warn("interview score parse failed, uses local rubric: {}", e.getMessage());
log.warn("interview score parse failed, uses local rubric(处理错误已隐藏)");
return Optional.empty();
}
}
@@ -263,7 +263,7 @@ public class AihrModelSeedService {
.filter(model -> configured(model.baseUrl(), model.modelName(), model.apiKey()))
.findFirst();
} catch (DataAccessException e) {
log.debug("aihr speech model db fallback: {}", e.getMessage());
log.debug("aihr speech model db fallback(处理错误已隐藏)");
return Optional.empty();
}
}
@@ -286,7 +286,7 @@ public class AihrModelSeedService {
try {
return Optional.of(callOpenAiCompatible(runtime, runtime.modelName(), userPrompt, systemPrompt, temperature));
} catch (Exception e) {
log.warn("aihr llm tryChat failed, caller falls back to seed: {}", e.getMessage());
log.warn("aihr llm tryChat failed, caller falls back to seed(处理错误已隐藏)");
return Optional.empty();
}
}
@@ -318,7 +318,7 @@ public class AihrModelSeedService {
configured(rs.getString("api_host"), "model", rs.getString("api_key"))
), tenantId());
} catch (DataAccessException e) {
log.debug("aihr model provider db fallback: {}", e.getMessage());
log.debug("aihr model provider db fallback(处理错误已隐藏)");
return List.of();
}
}
@@ -349,7 +349,7 @@ public class AihrModelSeedService {
configured(rs.getString("resolved_api_host"), rs.getString("model_name"), rs.getString("resolved_api_key"))
), tenantId());
} catch (DataAccessException e) {
log.debug("aihr model config db fallback: {}", e.getMessage());
log.debug("aihr model config db fallback(处理错误已隐藏)");
return List.of();
}
}
@@ -371,7 +371,7 @@ public class AihrModelSeedService {
}, runtimeArgs(requestedModel));
return rows.stream().findFirst();
} catch (DataAccessException e) {
log.debug("aihr model runtime db fallback: {}", e.getMessage());
log.debug("aihr model runtime db fallback(处理错误已隐藏)");
return Optional.empty();
}
}
@@ -224,7 +224,7 @@ public class AihrOrgSyncService {
try {
return fetchSnapshot(baseUrl, token, req, resourceType, pageSize, maxPages);
} catch (Exception e) {
String warning = "外部 " + resourceType + " 快照拉取失败,已用员工字段兜底: " + AihrSensitiveText.forModel(e.getMessage());
String warning = "外部 " + resourceType + " 快照拉取失败,已用员工字段兜底(处理错误已隐藏)";
warnings.add(warning);
log.warn(warning);
return List.of();
@@ -286,7 +286,7 @@ public class AihrOrgSyncService {
}
return fetchedToken;
} catch (Exception e) {
throw new IllegalStateException("外部组织同步令牌获取失败: " + AihrSensitiveText.forModel(e.getMessage()), e);
throw new IllegalStateException("外部组织同步令牌获取失败(处理错误已隐藏)", e);
}
}
@@ -320,7 +320,7 @@ public class AihrOrgSyncService {
}
return root;
} catch (Exception e) {
throw new IllegalStateException(AihrSensitiveText.forModel(e.getMessage()), e);
throw new IllegalStateException("外部组织接口请求失败(处理错误已隐藏)", e);
}
}
@@ -513,7 +513,7 @@ public class AihrOrgSyncService {
ensureSnapshotColumn("person_phone", "ALTER TABLE aihr_org_snapshot ADD COLUMN `person_phone` varchar(30) DEFAULT NULL COMMENT '手机号(仅用于登录身份映射)' AFTER `ext_party_id`");
ensureSnapshotIndex("idx_aihr_org_phone", "ALTER TABLE aihr_org_snapshot ADD KEY `idx_aihr_org_phone` (`tenant_id`, `person_phone`)");
} catch (DataAccessException e) {
throw new IllegalStateException("组织人员快照表检查失败: " + e.getMessage(), e);
throw new IllegalStateException("组织人员快照表检查失败(处理错误已隐藏)", e);
}
}
@@ -170,7 +170,7 @@ public class AihrPracticeLlmService {
truncateText(root.path("summary").asText(""), 300)
));
} catch (Exception e) {
log.warn("practice score parse failed, falls back to seed: {}", e.getMessage());
log.warn("practice score parse failed, falls back to seed(处理错误已隐藏)");
return Optional.empty();
}
}
@@ -190,7 +190,7 @@ public class AihrPracticeLlmService {
root.path("redFlag").asBoolean(false)
));
} catch (Exception e) {
log.warn("practice turn parse failed, falls back to seed: {}", e.getMessage());
log.warn("practice turn parse failed, falls back to seed(处理错误已隐藏)");
return Optional.empty();
}
}
@@ -350,7 +350,7 @@ public class AihrSopSeedService {
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
log.warn("summary card failed: {}", e.getMessage());
log.warn("summary card failed(处理错误已隐藏)");
throw new ServiceException("总结卡生成失败,请稍后重试");
}
}
@@ -532,7 +532,7 @@ public class AihrSopSeedService {
if (isLocalImportTaskCanceled(taskId)) {
return;
}
finishLocalImportTask(taskId, 3, 0, 0, e.getMessage());
finishLocalImportTask(taskId, 3, 0, 0, "目录导入失败,请重试或联系管理员");
}
}
@@ -557,7 +557,7 @@ public class AihrSopSeedService {
items.add(new LocalImportItemResponse(fileName, "success", "已导入", response.fragments()));
} catch (Exception e) {
failed++;
items.add(new LocalImportItemResponse(fileName, "failed", e.getMessage(), 0));
items.add(new LocalImportItemResponse(fileName, "failed", "文件处理失败,请重试或联系管理员", 0));
}
if (taskId != null) {
updateLocalImportTask(taskId, 1, imported, failed, fileName, "已处理 " + (imported + failed) + " / " + plan.files().size());
@@ -740,7 +740,7 @@ public class AihrSopSeedService {
try {
fragments = split(content, config.blockSize(), config.overlap());
} catch (RuntimeException e) {
markAttachStatus(config.knowledgeId(), docId, 3, "parse-failed:" + e.getMessage());
markAttachStatus(config.knowledgeId(), docId, 3, "parse-failed:处理错误已隐藏");
throw e;
}
@@ -1790,7 +1790,7 @@ public class AihrSopSeedService {
}
return reranked;
} catch (Exception e) {
log.warn("rerank failed, keep rrf order: {}", e.getMessage());
log.warn("rerank failed, keep rrf order(处理错误已隐藏)");
return hits;
}
}
@@ -2403,7 +2403,7 @@ public class AihrSopSeedService {
result.promptVersion()
);
} catch (Exception e) {
log.warn("search digest failed, keep raw answer: {}", e.getMessage());
log.warn("search digest failed, keep raw answer(处理错误已隐藏)");
return null;
}
}
@@ -66,7 +66,7 @@ public class AihrSpeechService {
String text = objectMapper.readTree(response.body()).path("text").asText("");
return text.isBlank() ? Optional.empty() : Optional.of(text.trim());
} catch (Exception e) {
log.warn("asr call failed: {}", e.getMessage());
log.warn("asr call failed(处理错误已隐藏)");
return Optional.empty();
}
}
@@ -97,7 +97,7 @@ public class AihrSpeechService {
}
return response.body().length == 0 ? Optional.empty() : Optional.of(response.body());
} catch (Exception e) {
log.warn("tts call failed: {}", e.getMessage());
log.warn("tts call failed(处理错误已隐藏)");
return Optional.empty();
}
}
@@ -223,7 +223,7 @@ public class AihrUploadQueueService {
}
return null;
} catch (DataAccessException e) {
log.warn("upload queue claim failed: {}", e.getMessage());
log.warn("upload queue claim failed(处理错误已隐藏)");
return null;
}
}
@@ -386,7 +386,7 @@ public class AihrUploadQueueService {
cleanExpiredStaging();
triggerProcessing();
} catch (Exception e) {
log.debug("upload queue sweep skipped: {}", e.getMessage());
log.debug("upload queue sweep skipped(处理错误已隐藏)");
}
}
@@ -407,7 +407,7 @@ public class AihrUploadQueueService {
})
.forEach(AihrUploadQueueService::deleteQuietly);
} catch (IOException e) {
log.debug("staging cleanup skipped: {}", e.getMessage());
log.debug("staging cleanup skipped(处理错误已隐藏)");
}
}
@@ -43,6 +43,9 @@ class AihrSensitiveTextTest {
String speechSource = Files.readString(source("AihrSpeechService.java"));
String orgSyncSource = Files.readString(source("AihrOrgSyncService.java"));
String videoSource = Files.readString(source("AihrVideoService.java"));
String caseSource = Files.readString(source("AihrCaseService.java"));
String practiceLlmSource = Files.readString(source("AihrPracticeLlmService.java"));
String speechControllerSource = Files.readString(controllerSource("AihrSpeechController.java"));
assertTrue(modelSource.contains("AihrSensitiveText.forModel(prompt)"));
assertTrue(modelSource.contains("外部响应体已隐藏"));
@@ -53,11 +56,14 @@ class AihrSensitiveTextTest {
assertTrue(interviewSource.contains("AihrSensitiveText.personName(candidate.name(), \"候选人\")"));
assertTrue(speechSource.contains("AihrSensitiveText.forModel(text.trim())"));
assertTrue(speechSource.contains("asr http {}(外部响应体已隐藏)"));
assertTrue(speechControllerSource.contains("tts audio upload failed(处理错误已隐藏)"));
assertTrue(orgSyncSource.contains("外部响应体已隐藏"));
assertTrue(orgSyncSource.contains("AihrSensitiveText.forModel(e.getMessage())"));
assertTrue(orgSyncSource.contains("外部组织接口请求失败(处理错误已隐藏)"));
assertTrue(videoSource.contains("视频解析失败,请稍后重试"));
assertTrue(videoSource.contains("视频文件无法识别,请更换文件后重试"));
assertTrue(videoSource.contains("处理输出已隐藏"));
assertTrue(caseSource.contains("case audio upload failed(处理错误已隐藏)"));
assertTrue(practiceLlmSource.contains("practice score parse failed, falls back to seed(处理错误已隐藏)"));
}
private static Path source(String fileName) {
@@ -66,4 +72,11 @@ class AihrSensitiveTextTest {
? direct
: Path.of("ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service", fileName);
}
private static Path controllerSource(String fileName) {
Path direct = Path.of("src/main/java/org/dromara/aihr/controller", fileName);
return Files.exists(direct)
? direct
: Path.of("ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller", fileName);
}
}