mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-28 01:53:53 +08:00
fix:优化rag配置的验证和报错
This commit is contained in:
@@ -209,4 +209,8 @@ public interface ErrorCode {
|
|||||||
int UPLOAD_FILE_ERROR = 10168; // 上传文件失败
|
int UPLOAD_FILE_ERROR = 10168; // 上传文件失败
|
||||||
int NO_PERMISSION = 10169; // 没有权限
|
int NO_PERMISSION = 10169; // 没有权限
|
||||||
int KNOWLEDGE_BASE_NAME_EXISTS = 10170; // 同名知识库已存在
|
int KNOWLEDGE_BASE_NAME_EXISTS = 10170; // 同名知识库已存在
|
||||||
|
int RAG_API_ERROR_URL_NULL = 10171; // RAG配置中base_url为空,请完善配置
|
||||||
|
int RAG_API_ERROR_API_KEY_NULL = 10172; // RAG配置中api_key为空,请完善配置
|
||||||
|
int RAG_API_ERROR_API_KEY_INVALID = 10173; // RAG配置中api_key包含占位符,请替换为实际的API密钥
|
||||||
|
int RAG_API_ERROR_URL_INVALID = 10174; // RAG配置中base_url格式不正确,请检查协议是否正确
|
||||||
}
|
}
|
||||||
|
|||||||
+98
-65
@@ -110,7 +110,10 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
|
|||||||
knowledgeBase.getRagModelId());
|
knowledgeBase.getRagModelId());
|
||||||
knowledgeBase.setDocumentCount(documentCount);
|
knowledgeBase.setDocumentCount(documentCount);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("获取知识库 {} 的文档数量失败: {}", knowledgeBase.getDatasetId(), e.getMessage());
|
// 构建详细的错误信息,包含异常类型和消息
|
||||||
|
String baseErrorMessage = e.getClass().getSimpleName() + " - 获取知识库文档数量失败";
|
||||||
|
String errorMessage = baseErrorMessage + (e.getMessage() != null ? ": " + e.getMessage() : "");
|
||||||
|
log.warn("知识库 {} {}", knowledgeBase.getDatasetId(), errorMessage);
|
||||||
knowledgeBase.setDocumentCount(0); // 设置默认值
|
knowledgeBase.setDocumentCount(0); // 设置默认值
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,7 +167,12 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
|
|||||||
Map<String, Object> ragConfig = getValidatedRAGConfig(knowledgeBaseDTO.getRagModelId());
|
Map<String, Object> ragConfig = getValidatedRAGConfig(knowledgeBaseDTO.getRagModelId());
|
||||||
deleteDatasetInRAGFlow(datasetId, ragConfig);
|
deleteDatasetInRAGFlow(datasetId, ragConfig);
|
||||||
} catch (Exception deleteException) {
|
} catch (Exception deleteException) {
|
||||||
log.warn("删除重复datasetId的RAGFlow数据集失败: {}", deleteException.getMessage());
|
// 提供更详细的错误信息,包括异常类型和消息
|
||||||
|
String errorMessage = "删除重复datasetId的RAGFlow数据集失败: " + deleteException.getClass().getSimpleName();
|
||||||
|
if (deleteException.getMessage() != null) {
|
||||||
|
errorMessage += " - " + deleteException.getMessage();
|
||||||
|
}
|
||||||
|
log.warn(errorMessage, deleteException);
|
||||||
}
|
}
|
||||||
throw new RenException(ErrorCode.DB_RECORD_EXISTS);
|
throw new RenException(ErrorCode.DB_RECORD_EXISTS);
|
||||||
}
|
}
|
||||||
@@ -207,17 +215,27 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
|
|||||||
&& StringUtils.isNotBlank(knowledgeBaseDTO.getRagModelId());
|
&& StringUtils.isNotBlank(knowledgeBaseDTO.getRagModelId());
|
||||||
|
|
||||||
if (needRagValidation) {
|
if (needRagValidation) {
|
||||||
// 先校验RAG配置
|
try {
|
||||||
Map<String, Object> ragConfig = getValidatedRAGConfig(knowledgeBaseDTO.getRagModelId());
|
// 先校验RAG配置
|
||||||
|
Map<String, Object> ragConfig = getValidatedRAGConfig(knowledgeBaseDTO.getRagModelId());
|
||||||
|
|
||||||
// 调用RAGFlow API更新数据集
|
// 调用RAGFlow API更新数据集
|
||||||
updateDatasetInRAGFlow(
|
updateDatasetInRAGFlow(
|
||||||
knowledgeBaseDTO.getDatasetId(),
|
knowledgeBaseDTO.getDatasetId(),
|
||||||
knowledgeBaseDTO.getName(),
|
knowledgeBaseDTO.getName(),
|
||||||
knowledgeBaseDTO.getDescription(),
|
knowledgeBaseDTO.getDescription(),
|
||||||
ragConfig);
|
ragConfig);
|
||||||
|
|
||||||
log.info("RAGFlow API更新成功,datasetId: {}", knowledgeBaseDTO.getDatasetId());
|
log.info("RAGFlow API更新成功,datasetId: {}", knowledgeBaseDTO.getDatasetId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 提供更详细的错误信息,包括异常类型和消息
|
||||||
|
String errorMessage = "更新RAGFlow数据集失败: " + e.getClass().getSimpleName();
|
||||||
|
if (e.getMessage() != null) {
|
||||||
|
errorMessage += " - " + e.getMessage();
|
||||||
|
}
|
||||||
|
log.error(errorMessage, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.warn("datasetId或ragModelId为空,跳过RAGFlow更新");
|
log.warn("datasetId或ragModelId为空,跳过RAGFlow更新");
|
||||||
}
|
}
|
||||||
@@ -281,7 +299,12 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
|
|||||||
log.info("RAGFlow API删除调用完成");
|
log.info("RAGFlow API删除调用完成");
|
||||||
apiDeleteSuccess = true;
|
apiDeleteSuccess = true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("删除RAGFlow数据集失败: {}", e.getMessage());
|
// 提供更详细的错误信息,包括异常类型和消息
|
||||||
|
String errorMessage = "删除RAGFlow数据集失败: " + e.getClass().getSimpleName();
|
||||||
|
if (e.getMessage() != null) {
|
||||||
|
errorMessage += " - " + e.getMessage();
|
||||||
|
}
|
||||||
|
log.error(errorMessage, e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -376,7 +399,7 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
|
|||||||
*/
|
*/
|
||||||
private void validateRagConfig(Map<String, Object> config) {
|
private void validateRagConfig(Map<String, Object> config) {
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
throw new RenException(ErrorCode.RAG_CONFIG_NOT_FOUND);
|
throw new RenException(ErrorCode.RAG_CONFIG_NOT_FOUND, "RAG配置为空,请检查配置");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从配置中提取必要的参数
|
// 从配置中提取必要的参数
|
||||||
@@ -385,7 +408,22 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
|
|||||||
|
|
||||||
// 验证base_url是否存在且非空
|
// 验证base_url是否存在且非空
|
||||||
if (StringUtils.isBlank(baseUrl)) {
|
if (StringUtils.isBlank(baseUrl)) {
|
||||||
throw new RenException(ErrorCode.RAG_API_ERROR);
|
throw new RenException(ErrorCode.RAG_API_ERROR_URL_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证api_key是否存在且非空
|
||||||
|
if (StringUtils.isBlank(apiKey)) {
|
||||||
|
throw new RenException(ErrorCode.RAG_API_ERROR_API_KEY_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查api_key是否包含占位符
|
||||||
|
if (apiKey.contains("你")) {
|
||||||
|
throw new RenException(ErrorCode.RAG_API_ERROR_API_KEY_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证base_url格式
|
||||||
|
if (!baseUrl.startsWith("http://") && !baseUrl.startsWith("https://")) {
|
||||||
|
throw new RenException(ErrorCode.RAG_API_ERROR_URL_INVALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,16 +515,22 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
|
|||||||
log.info("从RAGFlow API响应中解析出datasetId: {}", datasetId);
|
log.info("从RAGFlow API响应中解析出datasetId: {}", datasetId);
|
||||||
log.debug("完整响应内容: {}", responseBody);
|
log.debug("完整响应内容: {}", responseBody);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("解析RAGFlow API响应时发生IO异常: {}", e.getMessage(), e);
|
// 构建详细的错误信息,包含异常类型和消息
|
||||||
throw new RenException(ErrorCode.RAG_API_ERROR, "RAGFlow API响应解析失败: " + e.getMessage());
|
String baseErrorMessage = e.getClass().getSimpleName() + " - 解析RAGFlow API响应时发生IO异常";
|
||||||
|
String errorMessage = baseErrorMessage + (e.getMessage() != null ? ": " + e.getMessage() : "");
|
||||||
|
log.error(errorMessage, e);
|
||||||
|
throw new RenException(ErrorCode.RAG_API_ERROR, "RAGFlow API响应解析失败: " + errorMessage);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("解析RAGFlow API响应失败: {}", e.getMessage(), e);
|
// 构建详细的错误信息,包含异常类型和消息
|
||||||
|
String baseErrorMessage = e.getClass().getSimpleName() + " - 解析RAGFlow API响应失败";
|
||||||
|
String errorMessage = baseErrorMessage + (e.getMessage() != null ? ": " + e.getMessage() : "");
|
||||||
|
log.error(errorMessage, e);
|
||||||
// 如果解析失败,但响应体不为空,尝试直接使用响应体作为错误信息
|
// 如果解析失败,但响应体不为空,尝试直接使用响应体作为错误信息
|
||||||
String errorMessage = responseBody;
|
String finalErrorMessage = responseBody;
|
||||||
if (e.getMessage() != null) {
|
if (e.getMessage() != null) {
|
||||||
errorMessage += ",解析错误: " + e.getMessage();
|
finalErrorMessage += ",解析错误: " + errorMessage;
|
||||||
}
|
}
|
||||||
throw new RenException(ErrorCode.RAG_API_ERROR, errorMessage);
|
throw new RenException(ErrorCode.RAG_API_ERROR, finalErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,16 +609,22 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
|
|||||||
throw new RenException(ErrorCode.RAG_API_ERROR, errorMessage);
|
throw new RenException(ErrorCode.RAG_API_ERROR, errorMessage);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("解析RAGFlow API响应时发生IO异常: {}", e.getMessage(), e);
|
// 构建详细的错误信息,包含异常类型和消息
|
||||||
throw new RenException(ErrorCode.RAG_API_ERROR, "RAGFlow API响应解析失败: " + e.getMessage());
|
String baseErrorMessage = e.getClass().getSimpleName() + " - 解析RAGFlow API响应时发生IO异常";
|
||||||
|
String errorMessage = baseErrorMessage + (e.getMessage() != null ? ": " + e.getMessage() : "");
|
||||||
|
log.error(errorMessage, e);
|
||||||
|
throw new RenException(ErrorCode.RAG_API_ERROR, "RAGFlow API响应解析失败: " + errorMessage);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("解析RAGFlow API响应失败: {}", e.getMessage(), e);
|
// 构建详细的错误信息,包含异常类型和消息
|
||||||
|
String baseErrorMessage = e.getClass().getSimpleName() + " - 解析RAGFlow API响应失败";
|
||||||
|
String errorMessage = baseErrorMessage + (e.getMessage() != null ? ": " + e.getMessage() : "");
|
||||||
|
log.error(errorMessage, e);
|
||||||
// 如果解析失败,但响应体不为空,尝试直接使用响应体作为错误信息
|
// 如果解析失败,但响应体不为空,尝试直接使用响应体作为错误信息
|
||||||
String errorMessage = responseBody;
|
String finalErrorMessage = responseBody;
|
||||||
if (e.getMessage() != null) {
|
if (e.getMessage() != null) {
|
||||||
errorMessage += ",解析错误: " + e.getMessage();
|
finalErrorMessage += ",解析错误: " + errorMessage;
|
||||||
}
|
}
|
||||||
throw new RenException(ErrorCode.RAG_API_ERROR, errorMessage);
|
throw new RenException(ErrorCode.RAG_API_ERROR, finalErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,16 +693,22 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
|
|||||||
throw new RenException(ErrorCode.RAG_API_ERROR, errorMessage);
|
throw new RenException(ErrorCode.RAG_API_ERROR, errorMessage);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("解析RAGFlow API响应时发生IO异常: {}", e.getMessage(), e);
|
// 构建详细的错误信息,包含异常类型和消息
|
||||||
throw new RenException(ErrorCode.RAG_API_ERROR, "RAGFlow API响应解析失败: " + e.getMessage());
|
String baseErrorMessage = e.getClass().getSimpleName() + " - 解析RAGFlow API响应时发生IO异常";
|
||||||
|
String errorMessage = baseErrorMessage + (e.getMessage() != null ? ": " + e.getMessage() : "");
|
||||||
|
log.error(errorMessage, e);
|
||||||
|
throw new RenException(ErrorCode.RAG_API_ERROR, "RAGFlow API响应解析失败: " + errorMessage);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("解析RAGFlow API响应失败: {}", e.getMessage(), e);
|
// 构建详细的错误信息,包含异常类型和消息
|
||||||
|
String baseErrorMessage = e.getClass().getSimpleName() + " - 解析RAGFlow API响应失败";
|
||||||
|
String errorMessage = baseErrorMessage + (e.getMessage() != null ? ": " + e.getMessage() : "");
|
||||||
|
log.error(errorMessage, e);
|
||||||
// 如果解析失败,但响应体不为空,尝试直接使用响应体作为错误信息
|
// 如果解析失败,但响应体不为空,尝试直接使用响应体作为错误信息
|
||||||
String errorMessage = responseBody;
|
String finalErrorMessage = responseBody;
|
||||||
if (e.getMessage() != null) {
|
if (e.getMessage() != null) {
|
||||||
errorMessage += ",解析错误: " + e.getMessage();
|
finalErrorMessage += ",解析错误: " + errorMessage;
|
||||||
}
|
}
|
||||||
throw new RenException(ErrorCode.RAG_API_ERROR, errorMessage);
|
throw new RenException(ErrorCode.RAG_API_ERROR, finalErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,41 +727,12 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
|
|||||||
ragConfig = getDefaultRAGConfig();
|
ragConfig = getDefaultRAGConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证baseUrl和apiKey
|
// 验证RAG配置参数
|
||||||
validateRAGConfigParameters(ragConfig);
|
validateRagConfig(ragConfig);
|
||||||
|
|
||||||
return ragConfig;
|
return ragConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证RAG配置参数
|
|
||||||
*/
|
|
||||||
private void validateRAGConfigParameters(Map<String, Object> ragConfig) {
|
|
||||||
if (ragConfig == null) {
|
|
||||||
throw new RenException(ErrorCode.RAG_CONFIG_NOT_FOUND, "RAG配置为空,请检查配置");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从配置中提取必要的参数
|
|
||||||
String baseUrl = (String) ragConfig.get("base_url");
|
|
||||||
String apiKey = (String) ragConfig.get("api_key");
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(baseUrl)) {
|
|
||||||
throw new RenException(ErrorCode.RAG_API_ERROR, "RAG配置中base_url为空,请完善配置");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(apiKey)) {
|
|
||||||
throw new RenException(ErrorCode.RAG_API_ERROR, "RAG配置中api_key为空,请完善配置");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apiKey.contains("你")) {
|
|
||||||
throw new RenException(ErrorCode.RAG_API_ERROR, "RAG配置中api_key包含占位符'你',请替换为实际的API密钥");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!baseUrl.startsWith("http://") && !baseUrl.startsWith("https://")) {
|
|
||||||
throw new RenException(ErrorCode.RAG_API_ERROR, "RAG配置中base_url格式不正确,必须以http://或https://开头");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查是否存在同名知识库
|
* 检查是否存在同名知识库
|
||||||
*
|
*
|
||||||
@@ -805,9 +832,15 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
|
|||||||
log.error("RAGFlow API调用失败,响应码: {}, 响应内容: {}", code, responseBody);
|
log.error("RAGFlow API调用失败,响应码: {}, 响应内容: {}", code, responseBody);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("解析RAGFlow API响应时发生IO异常: {}", e.getMessage(), e);
|
// 构建详细的错误信息,包含异常类型和消息
|
||||||
|
String baseErrorMessage = e.getClass().getSimpleName() + " - 解析RAGFlow API响应时发生IO异常";
|
||||||
|
String errorMessage = baseErrorMessage + (e.getMessage() != null ? ": " + e.getMessage() : "");
|
||||||
|
log.error(errorMessage, e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("解析RAGFlow API响应失败: {}", e.getMessage(), e);
|
// 构建详细的错误信息,包含异常类型和消息
|
||||||
|
String baseErrorMessage = e.getClass().getSimpleName() + " - 解析RAGFlow API响应失败";
|
||||||
|
String errorMessage = baseErrorMessage + (e.getMessage() != null ? ": " + e.getMessage() : "");
|
||||||
|
log.error(errorMessage, e);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,3 +177,7 @@
|
|||||||
10168=Upload file failed
|
10168=Upload file failed
|
||||||
10169=No permission to operate this knowledge base
|
10169=No permission to operate this knowledge base
|
||||||
10170=Knowledge base name already exists
|
10170=Knowledge base name already exists
|
||||||
|
10171=RAG configuration base_url cannot be empty
|
||||||
|
10172=RAG configuration api_key cannot be empty
|
||||||
|
10173=RAG configuration api_key cannot contain placeholder, please replace with actual API key
|
||||||
|
10174=RAG configuration base_url format error, must start with http or https
|
||||||
|
|||||||
@@ -177,3 +177,7 @@
|
|||||||
10168=\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25
|
10168=\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25
|
||||||
10169=\u60A8\u6CA1\u6709\u6743\u9650\u64CD\u4F5C\u8BE5\u8BB0\u5F55
|
10169=\u60A8\u6CA1\u6709\u6743\u9650\u64CD\u4F5C\u8BE5\u8BB0\u5F55
|
||||||
10170=\u77E5\u8BC6\u5E93\u540D\u79F0\u91CD\u590D
|
10170=\u77E5\u8BC6\u5E93\u540D\u79F0\u91CD\u590D
|
||||||
|
10171=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684base_url\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
10172=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684api_key\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
10173=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684api_key\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u66F4\u6362\u4E3A\u5728\u53D6\u7684API\u53C2\u6570
|
||||||
|
10174=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684base_url\u683C\u5F0F\u9519\u8BEF\uFF0C\u5FC5\u987B\u4EE5http\u6216https\u5F00\u5934
|
||||||
@@ -177,3 +177,9 @@
|
|||||||
10168=\u4E0A\u50B3\u6587\u4EF6\u5931\u6557
|
10168=\u4E0A\u50B3\u6587\u4EF6\u5931\u6557
|
||||||
10169=\u60A8\u6C92\u6709\u6B0A\u9650\u64CD\u4F5C\u8A72\u8A18\u9304
|
10169=\u60A8\u6C92\u6709\u6B0A\u9650\u64CD\u4F5C\u8A72\u8A18\u9304
|
||||||
10170=\u77E5\u8B58\u5EAB\u540D\u7A31\u91CD\u8907
|
10170=\u77E5\u8B58\u5EAB\u540D\u7A31\u91CD\u8907
|
||||||
|
10171=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684base_url\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
10172=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684api_key\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
10173=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684api_key\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u66F4\u6362\u4E3A\u5728\u53D6\u7684API\u53C2\u6570
|
||||||
|
10174=\u0052\u0041\u0047\u914D\u7F6E\u4F53\u7684base_url\u683C\u5F0F\u9519\u8BEF\uFF0C\u5FC5\u987B\u4EE5http\u6216https\u5F00\u5934
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user