案例助手:增加字段,增加白名单机制等

This commit is contained in:
liu.zixi
2025-09-30 10:56:44 +08:00
parent 7a74f70308
commit 960de20658
9 changed files with 321 additions and 39 deletions

View File

@@ -0,0 +1,50 @@
package com.xboe.enums;
/**
* AI调用日志接口运行状态枚举
*/
public enum CaseDocumentLogRunStatusEnum {
RUNNING(0, "运行中"),
COMPLETED(1, "运行完成");
private final Integer code;
private final String desc;
CaseDocumentLogRunStatusEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public Integer getCode() {
return code;
}
public String getDesc() {
return desc;
}
/**
* 根据code获取描述
*/
public static String getDescByCode(Integer code) {
for (CaseDocumentLogRunStatusEnum statusEnum : values()) {
if (statusEnum.getCode().equals(code)) {
return statusEnum.getDesc();
}
}
return "";
}
/**
* 根据code获取枚举
*/
public static CaseDocumentLogRunStatusEnum getByCode(Integer code) {
for (CaseDocumentLogRunStatusEnum statusEnum : values()) {
if (statusEnum.getCode().equals(code)) {
return statusEnum;
}
}
return null;
}
}

View File

@@ -67,6 +67,13 @@ public class CaseDocumentLog extends BaseEntity {
@Column(name = "opt_time") @Column(name = "opt_time")
private LocalDateTime optTime; private LocalDateTime optTime;
/**
* 接口运行状态
* 0-运行中, 1-运行完毕
*/
@Column(name = "run_status")
private Integer runStatus;
/** /**
* 接口调用状态 * 接口调用状态
* 0-调用中, 1-调用成功, 2-调用失败 * 0-调用中, 1-调用成功, 2-调用失败

View File

@@ -37,6 +37,11 @@ public class CaseAiProperties {
*/ */
private String caseKnowledgeId; private String caseKnowledgeId;
/**
* 文件上传是否使用回调接口
*/
private boolean fileUploadUseCallback;
/** /**
* 文档上传回调接口地址 * 文档上传回调接口地址
*/ */

View File

@@ -38,4 +38,9 @@ public interface ICaseKnowledgeService {
* @return 是否处理成功 * @return 是否处理成功
*/ */
boolean handleUploadCallback(String taskId, String message, String fileStatus); boolean handleUploadCallback(String taskId, String message, String fileStatus);
/**
* 批量检查文件状态
*/
void batchCheckFileStatus();
} }

View File

@@ -7,6 +7,7 @@ import com.xboe.common.PageList;
import com.xboe.core.orm.FieldFilters; import com.xboe.core.orm.FieldFilters;
import com.xboe.core.orm.IFieldFilter; import com.xboe.core.orm.IFieldFilter;
import com.xboe.core.orm.LikeMatchMode; import com.xboe.core.orm.LikeMatchMode;
import com.xboe.enums.CaseDocumentLogRunStatusEnum;
import com.xboe.module.boecase.dao.CaseDocumentLogDao; import com.xboe.module.boecase.dao.CaseDocumentLogDao;
import com.xboe.module.boecase.dto.CaseDocumentLogQueryDto; import com.xboe.module.boecase.dto.CaseDocumentLogQueryDto;
import com.xboe.module.boecase.entity.CaseDocumentLog; import com.xboe.module.boecase.entity.CaseDocumentLog;
@@ -47,16 +48,9 @@ public class CaseDocumentLogServiceImpl implements ICaseDocumentLogService {
public PageList<CaseDocumentLogVo> pageQuery(int pageIndex, int pageSize, CaseDocumentLogQueryDto queryDto) { public PageList<CaseDocumentLogVo> pageQuery(int pageIndex, int pageSize, CaseDocumentLogQueryDto queryDto) {
// 构建查询条件 // 构建查询条件
List<IFieldFilter> filters = new ArrayList<>(); List<IFieldFilter> filters = new ArrayList<>();
// 删除标识过滤
filters.add(FieldFilters.eq("deleted", false));
// 接口调用状态 // 运行状态过滤
if (queryDto.getOptStatus() != null) { filters.add(FieldFilters.eq("runStatus", CaseDocumentLogRunStatusEnum.COMPLETED.getCode()));
filters.add(FieldFilters.eq("optStatus", queryDto.getOptStatus()));
} else {
filters.add(FieldFilters.ge("optStatus", 1));
}
// 案例标题模糊查询 // 案例标题模糊查询
if (StringUtil.isNotBlank(queryDto.getCaseTitle())) { if (StringUtil.isNotBlank(queryDto.getCaseTitle())) {
@@ -76,11 +70,19 @@ public class CaseDocumentLogServiceImpl implements ICaseDocumentLogService {
filters.add(FieldFilters.le("optTime", queryDto.getOptTimeEnd())); filters.add(FieldFilters.le("optTime", queryDto.getOptTimeEnd()));
} }
// 接口调用状态
if (queryDto.getOptStatus() != null) {
filters.add(FieldFilters.eq("optStatus", queryDto.getOptStatus()));
}
// 业务处理状态 // 业务处理状态
if (queryDto.getCaseStatus() != null) { if (queryDto.getCaseStatus() != null) {
filters.add(FieldFilters.eq("caseStatus", queryDto.getCaseStatus())); filters.add(FieldFilters.eq("caseStatus", queryDto.getCaseStatus()));
} }
// 删除标识过滤
filters.add(FieldFilters.eq("deleted", false));
// 按创建时间降序排序 // 按创建时间降序排序
OrderCondition order = OrderCondition.desc("sysCreateTime"); OrderCondition order = OrderCondition.desc("sysCreateTime");
@@ -106,16 +108,9 @@ public class CaseDocumentLogServiceImpl implements ICaseDocumentLogService {
public int clearLogsByCondition(CaseDocumentLogQueryDto queryDto) { public int clearLogsByCondition(CaseDocumentLogQueryDto queryDto) {
// 构建查询条件(与分页查询相同的逻辑) // 构建查询条件(与分页查询相同的逻辑)
List<IFieldFilter> filters = new ArrayList<>(); List<IFieldFilter> filters = new ArrayList<>();
// 删除标识过滤
filters.add(FieldFilters.eq("deleted", false));
// 接口调用状态 // 运行状态过滤
if (queryDto.getOptStatus() != null) { filters.add(FieldFilters.eq("runStatus", CaseDocumentLogRunStatusEnum.COMPLETED.getCode()));
filters.add(FieldFilters.eq("optStatus", queryDto.getOptStatus()));
} else {
filters.add(FieldFilters.ge("optStatus", 1));
}
// 案例标题模糊查询 // 案例标题模糊查询
if (StringUtil.isNotBlank(queryDto.getCaseTitle())) { if (StringUtil.isNotBlank(queryDto.getCaseTitle())) {
@@ -135,11 +130,19 @@ public class CaseDocumentLogServiceImpl implements ICaseDocumentLogService {
filters.add(FieldFilters.le("optTime", queryDto.getOptTimeEnd())); filters.add(FieldFilters.le("optTime", queryDto.getOptTimeEnd()));
} }
// 接口调用状态
if (queryDto.getOptStatus() != null) {
filters.add(FieldFilters.eq("optStatus", queryDto.getOptStatus()));
}
// 业务处理状态 // 业务处理状态
if (queryDto.getCaseStatus() != null) { if (queryDto.getCaseStatus() != null) {
filters.add(FieldFilters.eq("caseStatus", queryDto.getCaseStatus())); filters.add(FieldFilters.eq("caseStatus", queryDto.getCaseStatus()));
} }
// 删除标识过滤
filters.add(FieldFilters.eq("deleted", false));
// 查询符合条件的所有记录 // 查询符合条件的所有记录
IFieldFilter[] filtersArray = filters.toArray(new IFieldFilter[0]); IFieldFilter[] filtersArray = filters.toArray(new IFieldFilter[0]);
List<CaseDocumentLog> logsToDelete = caseDocumentLogDao.getGenericDao() List<CaseDocumentLog> logsToDelete = caseDocumentLogDao.getGenericDao()
@@ -273,8 +276,6 @@ public class CaseDocumentLogServiceImpl implements ICaseDocumentLogService {
return ""; return "";
} }
switch (optStatus) { switch (optStatus) {
case 0:
return "调用中";
case 1: case 1:
return "调用成功"; return "调用成功";
case 2: case 2:

View File

@@ -10,6 +10,7 @@ import com.xboe.core.upload.XFileUploader;
import com.xboe.enums.CaseDocumentLogCaseStatusEnum; import com.xboe.enums.CaseDocumentLogCaseStatusEnum;
import com.xboe.enums.CaseDocumentLogOptStatusEnum; import com.xboe.enums.CaseDocumentLogOptStatusEnum;
import com.xboe.enums.CaseDocumentLogOptTypeEnum; import com.xboe.enums.CaseDocumentLogOptTypeEnum;
import com.xboe.enums.CaseDocumentLogRunStatusEnum;
import com.xboe.module.boecase.dao.CaseDocumentLogDao; import com.xboe.module.boecase.dao.CaseDocumentLogDao;
import com.xboe.module.boecase.dao.CasesDao; import com.xboe.module.boecase.dao.CasesDao;
import com.xboe.module.boecase.entity.CaseDocumentLog; import com.xboe.module.boecase.entity.CaseDocumentLog;
@@ -139,8 +140,11 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
requestBody.put("fileType", fileType); requestBody.put("fileType", fileType);
builder.addTextBody("parseType", "AUTO", ContentType.TEXT_PLAIN); builder.addTextBody("parseType", "AUTO", ContentType.TEXT_PLAIN);
requestBody.put("parseType", "AUTO"); requestBody.put("parseType", "AUTO");
builder.addTextBody("callbackUrl", caseAiProperties.getFileUploadCallbackUrl(), ContentType.TEXT_PLAIN); // 由于接口权限,目前采用不回调,而是通过批处理的方式,处理文件状态
requestBody.put("callbackUrl", caseAiProperties.getFileUploadCallbackUrl()); if (caseAiProperties.isFileUploadUseCallback()) {
builder.addTextBody("callbackUrl", caseAiProperties.getFileUploadCallbackUrl(), ContentType.TEXT_PLAIN);
requestBody.put("callbackUrl", caseAiProperties.getFileUploadCallbackUrl());
}
HttpEntity multipart = builder.build(); HttpEntity multipart = builder.build();
httpPost.setEntity(multipart); httpPost.setEntity(multipart);
@@ -158,15 +162,17 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
// 保存成功的CaseDocumentLog记录 // 保存成功的CaseDocumentLog记录
saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl,
requestBody.toJSONString(), responseBody, CaseDocumentLogOptStatusEnum.CALLING.getCode(), CaseDocumentLogCaseStatusEnum.SUCCESS.getCode(), taskId); requestBody.toJSONString(), responseBody,
CaseDocumentLogRunStatusEnum.RUNNING.getCode(), null, null, taskId);
log.info("上传案例文档成功caseId: {}, taskId: {}, 尝试次数: {}", caseId, taskId, attempt); log.info("上传案例文档成功,等待文档状态变更. caseId: {}, taskId: {}, 尝试次数: {}", caseId, taskId, attempt);
return true; return true;
} else { } else {
// 业务处理失败,不重试 // 业务处理失败,不重试
log.error("上传案例文档业务处理失败不重试response: {}", responseBody); log.error("上传案例文档业务处理失败不重试response: {}", responseBody);
saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl,
requestBody.toJSONString(), responseBody, CaseDocumentLogOptStatusEnum.CALLING.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); requestBody.toJSONString(), responseBody,
CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.SUCCESS.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null);
return false; return false;
} }
} else { } else {
@@ -175,7 +181,8 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
if (attempt == maxRetries) { if (attempt == maxRetries) {
// 最后一次尝试仍然失败 // 最后一次尝试仍然失败
saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl,
requestBody.toJSONString(), responseBody, CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); requestBody.toJSONString(), responseBody,
CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.SUCCESS.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null);
return false; return false;
} }
// 继续下一次重试 // 继续下一次重试
@@ -188,7 +195,8 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
// 最后一次尝试仍然异常 // 最后一次尝试仍然异常
log.error("上传案例文档最终失败,已重试{}次", maxRetries); log.error("上传案例文档最终失败,已重试{}次", maxRetries);
saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl,
requestBody.toJSONString(), "接口调用异常: " + e.getMessage(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); requestBody.toJSONString(), "接口调用异常: " + e.getMessage(),
CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null);
return false; return false;
} }
// 继续下一次重试 // 继续下一次重试
@@ -274,7 +282,8 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
CaseDocumentLogCaseStatusEnum.SUCCESS.getCode() : CaseDocumentLogCaseStatusEnum.FAILED.getCode(); CaseDocumentLogCaseStatusEnum.SUCCESS.getCode() : CaseDocumentLogCaseStatusEnum.FAILED.getCode();
saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl,
params, responseBody, optStatus, caseStatus, null); params, responseBody,
CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), optStatus, caseStatus, null);
if (deleteSuccess != null && deleteSuccess) { if (deleteSuccess != null && deleteSuccess) {
log.info("删除案例文档成功caseId: {}, taskId: {}, 尝试次数: {}", caseId, taskId, attempt); log.info("删除案例文档成功caseId: {}, taskId: {}, 尝试次数: {}", caseId, taskId, attempt);
@@ -288,7 +297,8 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
// 业务处理失败,不重试 // 业务处理失败,不重试
log.error("删除案例文档业务处理失败不重试response: {}", responseBody); log.error("删除案例文档业务处理失败不重试response: {}", responseBody);
saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl,
params, responseBody, CaseDocumentLogOptStatusEnum.SUCCESS.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); params, responseBody,
CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.SUCCESS.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null);
return false; return false;
} }
} else { } else {
@@ -297,7 +307,8 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
if (attempt == maxRetries) { if (attempt == maxRetries) {
// 最后一次尝试仍然失败 // 最后一次尝试仍然失败
saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl,
params, responseBody, CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); params, responseBody,
CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null);
return false; return false;
} }
// 继续下一次重试 // 继续下一次重试
@@ -310,7 +321,8 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
// 最后一次尝试仍然异常 // 最后一次尝试仍然异常
log.error("删除案例文档最终失败,已重试{}次", maxRetries); log.error("删除案例文档最终失败,已重试{}次", maxRetries);
saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl,
params, "接口调用异常: " + e.getMessage(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); params, "接口调用异常: " + e.getMessage(),
CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null);
return false; return false;
} }
// 继续下一次重试 // 继续下一次重试
@@ -374,7 +386,8 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
if (!deleteSuccess) { if (!deleteSuccess) {
log.error("更新案例文档失败删除接口调用失败不继续执行上传操作caseId: {}", caseId); log.error("更新案例文档失败删除接口调用失败不继续执行上传操作caseId: {}", caseId);
saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl,
deleteParam, "删除接口:失败,上传接口:未执行", CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); deleteParam, "删除接口:失败,上传接口:未执行",
CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null);
return false; return false;
} }
@@ -408,20 +421,24 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
uploadRequestBody.put("fileName", fileName); uploadRequestBody.put("fileName", fileName);
uploadRequestBody.put("fileType", fileType); uploadRequestBody.put("fileType", fileType);
uploadRequestBody.put("parseType", "AUTO"); uploadRequestBody.put("parseType", "AUTO");
uploadRequestBody.put("callbackUrl", caseAiProperties.getFileUploadCallbackUrl()); if (caseAiProperties.isFileUploadUseCallback()) {
uploadRequestBody.put("callbackUrl", caseAiProperties.getFileUploadCallbackUrl());
}
requestBody = uploadRequestBody.toJSONString(); requestBody = uploadRequestBody.toJSONString();
String taskId = callUploadInterface(caseId, file, fileName, fileType, userId, accessToken, requestUrl); String taskId = callUploadInterface(caseId, file, fileName, fileType, userId, accessToken, requestUrl);
boolean uploadSuccess = StringUtil.isNotBlank(taskId); boolean uploadSuccess = StringUtil.isNotBlank(taskId);
// 4. 根据结果保存一条CaseDocumentLog数据 // 4. 根据结果保存一条CaseDocumentLog数据
int optStatus = uploadSuccess ? CaseDocumentLogOptStatusEnum.SUCCESS.getCode() : CaseDocumentLogOptStatusEnum.FAILED.getCode(); int runStatus = uploadSuccess ? CaseDocumentLogRunStatusEnum.RUNNING.getCode() : CaseDocumentLogRunStatusEnum.COMPLETED.getCode();
int caseStatus = uploadSuccess ? CaseDocumentLogCaseStatusEnum.SUCCESS.getCode() : CaseDocumentLogCaseStatusEnum.FAILED.getCode(); Integer optStatus = uploadSuccess ? null : CaseDocumentLogOptStatusEnum.SUCCESS.getCode();
Integer caseStatus = uploadSuccess ? null : CaseDocumentLogCaseStatusEnum.FAILED.getCode();
String result = String.format("删除接口:成功,上传接口:%s", String result = String.format("删除接口:成功,上传接口:%s",
uploadSuccess ? "成功" : "失败"); uploadSuccess ? "成功" : "失败");
saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl,
requestBody, result, optStatus, caseStatus, taskId); requestBody, result,
runStatus, optStatus, caseStatus, taskId);
if (uploadSuccess) { if (uploadSuccess) {
log.info("更新案例文档成功caseId: {}, taskId: {}", caseId, taskId); log.info("更新案例文档成功caseId: {}, taskId: {}", caseId, taskId);
@@ -434,7 +451,8 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
} catch (Exception e) { } catch (Exception e) {
log.error("更新案例文档异常", e); log.error("更新案例文档异常", e);
saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, saveCaseDocumentLog(caseId, caseEntity.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl,
requestBody, "更新异常: " + e.getMessage(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); requestBody, "更新异常: " + e.getMessage(),
CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null);
return false; return false;
} }
} }
@@ -515,6 +533,81 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
} }
} }
@Override
public void batchCheckFileStatus() {
log.info("开始批量检查文件状态");
// 1. 查询CaseDocumentLog表中所有run_status等于0的数据
List<CaseDocumentLog> runningLogs = caseDocumentLogDao.getGenericDao()
.findList(CaseDocumentLog.class,
FieldFilters.eq("runStatus", CaseDocumentLogRunStatusEnum.RUNNING.getCode()));
// 2. 如果没有符合条件的数据,完成
if (runningLogs.isEmpty()) {
log.info("没有需要检查状态的文档,批量检查完成");
return;
}
log.info("找到{}条需要检查状态的文档记录", runningLogs.size());
// 3. 把这些数据的taskId聚合成一个List<String>
List<String> taskIds = runningLogs.stream()
.map(CaseDocumentLog::getTaskId)
.filter(StringUtil::isNotBlank)
.distinct()
.collect(java.util.stream.Collectors.toList());
if (taskIds.isEmpty()) {
log.warn("所有运行中的记录都没有有效的taskId");
return;
}
log.info("需要检查状态的taskId数量: {}", taskIds.size());
// 4. 获取access_token
String accessToken = aiAccessTokenService.getAccessToken();
if (StringUtil.isBlank(accessToken)) {
log.error("批量检查文件状态失败获取access_token失败");
return;
}
// 5. 调用三方接口检查状态
try {
String statusUrl = caseAiProperties.getBaseUrl() + "/apigateway/knowledge/v1/file/status";
String kId = caseAiProperties.getCaseKnowledgeId();
String taskIdsParam = String.join(",", taskIds);
String queryParams = "kId=" + URLEncoder.encode(kId, StandardCharsets.UTF_8.name()) +
"&taskIds=" + URLEncoder.encode(taskIdsParam, StandardCharsets.UTF_8.name());
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpGet httpGet = new HttpGet(statusUrl + "?" + queryParams);
httpGet.setHeader("X-AI-ApiCode", caseAiProperties.getAiApiCode());
httpGet.setHeader("access_token", accessToken);
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
int statusCode = response.getStatusLine().getStatusCode();
String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
if (statusCode == 200) {
JSONObject result = JSON.parseObject(responseBody);
if (result.getBooleanValue("success")) {
// 6. 解析返回结果并更新状态
processFileStatusResponse(result, runningLogs);
} else {
log.error("调用文件状态接口业务处理失败response: {}", responseBody);
}
} else {
log.error("调用文件状态接口失败status: {}, response: {}", statusCode, responseBody);
}
}
}
} catch (Exception e) {
log.error("批量检查文件状态异常", e);
}
log.info("批量检查文件状态完成");
}
/** /**
* 根据文件名获取文件类型 * 根据文件名获取文件类型
*/ */
@@ -668,7 +761,9 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
builder.addTextBody("fileName", fileName, ContentType.TEXT_PLAIN); builder.addTextBody("fileName", fileName, ContentType.TEXT_PLAIN);
builder.addTextBody("fileType", fileType, ContentType.TEXT_PLAIN); builder.addTextBody("fileType", fileType, ContentType.TEXT_PLAIN);
builder.addTextBody("parseType", "AUTO", ContentType.TEXT_PLAIN); builder.addTextBody("parseType", "AUTO", ContentType.TEXT_PLAIN);
builder.addTextBody("callbackUrl", caseAiProperties.getFileUploadCallbackUrl(), ContentType.TEXT_PLAIN); if (caseAiProperties.isFileUploadUseCallback()) {
builder.addTextBody("callbackUrl", caseAiProperties.getFileUploadCallbackUrl(), ContentType.TEXT_PLAIN);
}
HttpEntity multipart = builder.build(); HttpEntity multipart = builder.build();
httpPost.setEntity(multipart); httpPost.setEntity(multipart);
@@ -714,12 +809,94 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
return null; return null;
} }
/**
* 处理文件状态接口响应
*/
private void processFileStatusResponse(JSONObject result, List<CaseDocumentLog> runningLogs) {
try {
com.alibaba.fastjson.JSONArray dataArray = result.getJSONArray("data");
if (dataArray == null || dataArray.isEmpty()) {
log.warn("文件状态接口返回的data为空");
return;
}
// 创建taskId到状态的映射
java.util.Map<String, String> taskStatusMap = new java.util.HashMap<>();
for (int i = 0; i < dataArray.size(); i++) {
JSONObject statusItem = dataArray.getJSONObject(i);
String taskId = statusItem.getString("taskId");
String fileStatus = statusItem.getString("fileStatus");
if (StringUtil.isNotBlank(taskId) && StringUtil.isNotBlank(fileStatus)) {
taskStatusMap.put(taskId, fileStatus);
}
}
// 根据状态更新对应的CaseDocumentLog记录
for (CaseDocumentLog caseDocumentLog : runningLogs) {
String taskId = caseDocumentLog.getTaskId();
if (StringUtil.isBlank(taskId)) {
continue;
}
String fileStatus = taskStatusMap.get(taskId);
if (StringUtil.isBlank(fileStatus)) {
log.warn("未找到taskId对应的文件状态: {}", taskId);
continue;
}
updateLogStatusByFileStatus(caseDocumentLog, fileStatus);
}
} catch (Exception e) {
log.error("处理文件状态响应异常", e);
}
}
/**
* 根据文件状态更新日志记录
*/
private void updateLogStatusByFileStatus(CaseDocumentLog caseLog, String fileStatus) {
try {
boolean needUpdate = false;
if ("vectored".equals(fileStatus)) {
// 状态为vectored将run_status、opt_status和case_status都变更为1
caseLog.setRunStatus(CaseDocumentLogRunStatusEnum.COMPLETED.getCode());
caseLog.setOptStatus(CaseDocumentLogOptStatusEnum.SUCCESS.getCode());
caseLog.setCaseStatus(CaseDocumentLogCaseStatusEnum.SUCCESS.getCode());
needUpdate = true;
log.info("文档向量化成功更新状态taskId: {}, caseId: {}", caseLog.getTaskId(), caseLog.getCaseId());
} else if ("failed".equals(fileStatus)) {
// 状态为failedrun_status、opt_status变更为1case_status变更为2
caseLog.setRunStatus(CaseDocumentLogRunStatusEnum.COMPLETED.getCode());
caseLog.setOptStatus(CaseDocumentLogOptStatusEnum.SUCCESS.getCode());
caseLog.setCaseStatus(CaseDocumentLogCaseStatusEnum.FAILED.getCode());
needUpdate = true;
log.warn("文档处理失败更新状态taskId: {}, caseId: {}", caseLog.getTaskId(), caseLog.getCaseId());
} else {
// 其他状态uploaded、texted、vectoring不做数据变更
log.debug("文档状态为{}暂不更新数据库taskId: {}", fileStatus, caseLog.getTaskId());
}
// 如果需要更新执行update操作
if (needUpdate) {
caseLog.setSysUpdateTime(LocalDateTime.now());
caseDocumentLogDao.save(caseLog);
log.info("更新CaseDocumentLog成功logId: {}, taskId: {}, fileStatus: {}",
caseLog.getId(), caseLog.getTaskId(), fileStatus);
}
} catch (Exception e) {
log.error("更新日志状态异常taskId: {}, fileStatus: {}", caseLog.getTaskId(), fileStatus, e);
}
}
/** /**
* 保存CaseDocumentLog记录 * 保存CaseDocumentLog记录
*/ */
private void saveCaseDocumentLog(String caseId, String caseTitle, String optType, private void saveCaseDocumentLog(String caseId, String caseTitle, String optType,
String requestUrl, String requestBody, String responseBody, String requestUrl, String requestBody, String responseBody,
Integer optStatus, Integer caseStatus, String taskId) { Integer runStatus, Integer optStatus, Integer caseStatus, String taskId) {
try { try {
CaseDocumentLog caseDocumentLog = new CaseDocumentLog(); CaseDocumentLog caseDocumentLog = new CaseDocumentLog();
caseDocumentLog.setId(IDGenerator.generate()); caseDocumentLog.setId(IDGenerator.generate());
@@ -731,6 +908,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService {
caseDocumentLog.setRequestBody(requestBody); caseDocumentLog.setRequestBody(requestBody);
caseDocumentLog.setResponseBody(responseBody); caseDocumentLog.setResponseBody(responseBody);
caseDocumentLog.setOptTime(LocalDateTime.now()); caseDocumentLog.setOptTime(LocalDateTime.now());
caseDocumentLog.setRunStatus(runStatus);
caseDocumentLog.setOptStatus(optStatus); caseDocumentLog.setOptStatus(optStatus);
caseDocumentLog.setCaseStatus(caseStatus); caseDocumentLog.setCaseStatus(caseStatus);
caseDocumentLog.setExecuteDuration(0L); caseDocumentLog.setExecuteDuration(0L);

View File

@@ -0,0 +1,22 @@
package com.xboe.module.boecase.task;
import com.xboe.module.boecase.service.ICaseKnowledgeService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class CaseDocumentLogTask {
@Autowired
private ICaseKnowledgeService caseKnowledgeService;
// @XxlJob("batchCheckFileStatus")
public void batchCheckFileStatus() {
log.info("开始批量查询文件状态");
caseKnowledgeService.batchCheckFileStatus();
log.info("结束批量查询文件状态");
}
}

View File

@@ -0,0 +1,12 @@
package com.xboe.module.boecase.task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 旧案例上传
*/
@Component
@Slf4j
public class CaseUploadTask {
}

View File

@@ -119,6 +119,8 @@ xboe:
ai-api-code: 30800 ai-api-code: 30800
case-knowledge-id: de2e006e-82fb-4ace-8813-f25c316be4ff case-knowledge-id: de2e006e-82fb-4ace-8813-f25c316be4ff
file-upload-callback-url: http://10.251.186.27:9090/xboe/m/boe/caseDocumentLog/uploadCallback file-upload-callback-url: http://10.251.186.27:9090/xboe/m/boe/caseDocumentLog/uploadCallback
use-white-list: true
white-user-code-list: 00004409
jasypt: jasypt:
encryptor: encryptor:
algorithm: PBEWithMD5AndDES algorithm: PBEWithMD5AndDES