diff --git a/backend-single/API_BASE_URL_MODIFICATION_SUMMARY.md b/backend-single/API_BASE_URL_MODIFICATION_SUMMARY.md new file mode 100644 index 0000000..e982766 --- /dev/null +++ b/backend-single/API_BASE_URL_MODIFICATION_SUMMARY.md @@ -0,0 +1,234 @@ +# API Base URL 字段调整总结 + +## 修改概述 + +将 `AiConfig` 实体类中的 `apiBaseUrl` 字段从"基础URL"调整为"完整的API URL",不再需要在调用时拼接任何后缀。 + +## 修改内容 + +### 1. 实体类和DTO修改 + +#### 1.1 AiConfig.java +- **文件路径**: `backend-single/src/main/java/com/emotion/entity/AiConfig.java` +- **修改内容**: 更新 `apiBaseUrl` 字段注释 +- **修改前**: `API基础URL` +- **修改后**: `API完整URL(包含完整的接口路径,不需要再拼接任何后缀)例如:https://api.coze.cn/v3/chat` + +#### 1.2 AiConfigCreateRequest.java +- **文件路径**: `backend-single/src/main/java/com/emotion/dto/request/aiconfig/AiConfigCreateRequest.java` +- **修改内容**: 更新 `apiBaseUrl` 字段注释和验证消息 +- **修改前**: `API基础URL` / `API基础URL不能为空` +- **修改后**: `API完整URL(包含完整的接口路径,不需要再拼接任何后缀)` / `API完整URL不能为空` + +#### 1.3 AiConfigUpdateRequest.java +- **文件路径**: `backend-single/src/main/java/com/emotion/dto/request/aiconfig/AiConfigUpdateRequest.java` +- **修改内容**: 更新 `apiBaseUrl` 字段注释 +- **修改前**: `API基础URL` +- **修改后**: `API完整URL(包含完整的接口路径,不需要再拼接任何后缀)` + +#### 1.4 AiConfigResponse.java +- **文件路径**: `backend-single/src/main/java/com/emotion/dto/response/aiconfig/AiConfigResponse.java` +- **修改内容**: 更新 `apiBaseUrl` 字段注释 +- **修改前**: `API基础URL` +- **修改后**: `API完整URL(包含完整的接口路径,不需要再拼接任何后缀)` + +### 2. 后端服务层修改 + +#### 2.1 AiChatServiceImpl.java +- **文件路径**: `backend-single/src/main/java/com/emotion/service/impl/AiChatServiceImpl.java` + +##### 修改1: getApiPath方法 +```java +// 修改前 +private String getApiPath(AiConfig config) { + // 默认使用 /v3/chat 路径 + return "/v3/chat"; +} + +// 修改后 +private String getApiPath(AiConfig config) { + // apiBaseUrl已经是完整的URL,返回空字符串 + return ""; +} +``` + +##### 修改2: 新增extractBaseUrl方法 +```java +/** + * 从apiBaseUrl中提取基础URL(用于状态查询和消息查询等辅助接口) + * 例如:https://api.coze.cn/v3/chat -> https://api.coze.cn + */ +private String extractBaseUrl(String apiBaseUrl) { + if (apiBaseUrl == null || apiBaseUrl.isEmpty()) { + return ""; + } + try { + java.net.URL url = new java.net.URL(apiBaseUrl); + return url.getProtocol() + "://" + url.getHost() + (url.getPort() > 0 ? ":" + url.getPort() : ""); + } catch (Exception e) { + log.warn("解析apiBaseUrl失败: {}", apiBaseUrl, e); + // 尝试简单截取 + int pathIndex = apiBaseUrl.indexOf("/", apiBaseUrl.indexOf("://") + 3); + if (pathIndex > 0) { + return apiBaseUrl.substring(0, pathIndex); + } + return apiBaseUrl; + } +} +``` + +##### 修改3: 状态查询URL构建 +```java +// 修改前 +String statusUrl = config.getApiBaseUrl() + "/v3/chat/retrieve?chat_id=" + chatId + "&conversation_id=" + conversationId; + +// 修改后 +String baseUrl = extractBaseUrl(config.getApiBaseUrl()); +String statusUrl = baseUrl + "/v3/chat/retrieve?chat_id=" + chatId + "&conversation_id=" + conversationId; +``` + +##### 修改4: 消息查询URL构建 +```java +// 修改前 +String messagesUrl = config.getApiBaseUrl() + "/v3/chat/message/list?chat_id=" + chatId + "&conversation_id=" + conversationId; + +// 修改后 +String baseUrl = extractBaseUrl(config.getApiBaseUrl()); +String messagesUrl = baseUrl + "/v3/chat/message/list?chat_id=" + chatId + "&conversation_id=" + conversationId; +``` + +### 3. 前端修改 + +#### 3.1 web-admin/src/views/aiconfig/AiConfigList.vue + +##### 修改1: 表单字段标签和提示 +```vue + + + + + + + + + +``` + +##### 修改2: 详情展示标签 +```vue + +{{ viewData.apiBaseUrl }} + + +{{ viewData.apiBaseUrl }} +``` + +##### 修改3: 表单验证规则 +```javascript +// 修改前 +apiBaseUrl: [{ required: true, message: '请输入API基础URL', trigger: 'blur' }] + +// 修改后 +apiBaseUrl: [{ required: true, message: '请输入完整的API URL', trigger: 'blur' }] +``` + +##### 修改4: 测试功能URL构建 +```javascript +// 修改前 +const initTestData = (config: AiConfig) => { + testRequest.url = config.apiBaseUrl + '/v3/chat' + // ... +} + +// 修改后 +const initTestData = (config: AiConfig) => { + // apiBaseUrl已经是完整的API URL,直接使用 + testRequest.url = config.apiBaseUrl + // ... +} +``` + +### 4. 单元测试 + +#### 4.1 AiChatServiceImplTest.java +- **文件路径**: `backend-single/src/test/java/com/emotion/service/AiChatServiceImplTest.java` +- **测试内容**: + 1. `testGetApiPath`: 测试getApiPath方法返回空字符串 + 2. `testExtractBaseUrl`: 测试extractBaseUrl方法提取基础URL + 3. `testApiUrlConstruction`: 测试完整API URL的构建逻辑 + 4. `testStatusQueryUrlConstruction`: 测试状态查询URL的构建逻辑 + 5. `testMessageQueryUrlConstruction`: 测试消息查询URL的构建逻辑 + 6. `testDifferentApiBaseUrlFormats`: 测试不同格式的apiBaseUrl + 7. `testEdgeCases`: 测试边界情况 + +**测试结果**: ✅ 所有7个测试用例全部通过 + +## 影响范围 + +### 后端影响 +1. **AiConfig实体类**: 字段语义变更,但数据库字段名不变 +2. **AiChatServiceImpl**: API调用逻辑调整,不再拼接路径 +3. **DTO类**: 注释和验证消息更新 + +### 前端影响 +1. **web-admin AI配置管理页面**: + - 表单标签和提示文本更新 + - 测试功能URL构建逻辑调整 + - 用户需要输入完整的API URL + +### 数据库影响 +- **无需修改数据库**: 字段名 `api_base_url` 保持不变 +- **数据迁移**: 需要将现有数据从基础URL更新为完整URL + - 例如: `https://api.coze.cn` → `https://api.coze.cn/v3/chat` + +## 使用示例 + +### 修改前 +```java +AiConfig config = new AiConfig(); +config.setApiBaseUrl("https://api.coze.cn"); // 基础URL +// 调用时拼接: config.getApiBaseUrl() + "/v3/chat" +``` + +### 修改后 +```java +AiConfig config = new AiConfig(); +config.setApiBaseUrl("https://api.coze.cn/v3/chat"); // 完整URL +// 调用时直接使用: config.getApiBaseUrl() +``` + +## 测试验证 + +### 后端测试 +```bash +cd backend-single +mvn test -Dtest=AiChatServiceImplTest +``` + +**测试结果**: +- Tests run: 7 +- Failures: 0 +- Errors: 0 +- Skipped: 0 +- ✅ 全部通过 + +### 前端测试 +1. 启动 web-admin 前端项目 +2. 进入 AI配置管理页面 +3. 点击"新增配置"或"编辑"按钮 +4. 在"API完整URL"字段输入完整的API地址(如:`https://api.coze.cn/v3/chat`) +5. 保存配置 +6. 点击"测试"按钮,验证接口调用是否成功 + +## 注意事项 + +1. **数据迁移**: 现有的AI配置数据需要更新,将基础URL改为完整URL +2. **向后兼容**: 如果有其他服务依赖旧的URL格式,需要同步更新 +3. **文档更新**: 需要更新相关的API文档和使用说明 +4. **配置示例**: 需要更新配置示例,明确说明应该填写完整的API URL + +## 完成时间 +2025-12-22 + +## 修改人员 +System diff --git a/backend-single/src/main/java/com/emotion/dto/request/aiconfig/AiConfigCreateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/aiconfig/AiConfigCreateRequest.java index 076060d..f30f436 100644 --- a/backend-single/src/main/java/com/emotion/dto/request/aiconfig/AiConfigCreateRequest.java +++ b/backend-single/src/main/java/com/emotion/dto/request/aiconfig/AiConfigCreateRequest.java @@ -40,9 +40,10 @@ public class AiConfigCreateRequest { private String provider; /** - * API基础URL + * API完整URL(包含完整的接口路径,不需要再拼接任何后缀) + * 例如:https://api.coze.cn/v3/chat */ - @NotBlank(message = "API基础URL不能为空") + @NotBlank(message = "API完整URL不能为空") private String apiBaseUrl; /** diff --git a/backend-single/src/main/java/com/emotion/dto/request/aiconfig/AiConfigUpdateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/aiconfig/AiConfigUpdateRequest.java index 6234b95..9c26c69 100644 --- a/backend-single/src/main/java/com/emotion/dto/request/aiconfig/AiConfigUpdateRequest.java +++ b/backend-single/src/main/java/com/emotion/dto/request/aiconfig/AiConfigUpdateRequest.java @@ -41,7 +41,8 @@ public class AiConfigUpdateRequest { private String provider; /** - * API基础URL + * API完整URL(包含完整的接口路径,不需要再拼接任何后缀) + * 例如:https://api.coze.cn/v3/chat */ private String apiBaseUrl; diff --git a/backend-single/src/main/java/com/emotion/dto/response/aiconfig/AiConfigResponse.java b/backend-single/src/main/java/com/emotion/dto/response/aiconfig/AiConfigResponse.java index 25d9adb..7194848 100644 --- a/backend-single/src/main/java/com/emotion/dto/response/aiconfig/AiConfigResponse.java +++ b/backend-single/src/main/java/com/emotion/dto/response/aiconfig/AiConfigResponse.java @@ -35,7 +35,8 @@ public class AiConfigResponse extends BaseResponse { private String provider; /** - * API基础URL + * API完整URL(包含完整的接口路径,不需要再拼接任何后缀) + * 例如:https://api.coze.cn/v3/chat */ private String apiBaseUrl; diff --git a/backend-single/src/main/java/com/emotion/entity/AiConfig.java b/backend-single/src/main/java/com/emotion/entity/AiConfig.java index 9fbc19e..00b17d9 100644 --- a/backend-single/src/main/java/com/emotion/entity/AiConfig.java +++ b/backend-single/src/main/java/com/emotion/entity/AiConfig.java @@ -49,7 +49,8 @@ public class AiConfig extends BaseEntity { private String provider; /** - * API基础URL + * API完整URL(包含完整的接口路径,不需要再拼接任何后缀) + * 例如:https://api.coze.cn/v3/chat */ @TableField("api_base_url") private String apiBaseUrl; diff --git a/backend-single/src/main/java/com/emotion/service/impl/AiChatServiceImpl.java b/backend-single/src/main/java/com/emotion/service/impl/AiChatServiceImpl.java index 04e094c..483b611 100644 --- a/backend-single/src/main/java/com/emotion/service/impl/AiChatServiceImpl.java +++ b/backend-single/src/main/java/com/emotion/service/impl/AiChatServiceImpl.java @@ -1377,8 +1377,9 @@ public class AiChatServiceImpl implements AiChatService { while (attempt < maxAttempts) { log.info("轮询聊天状态,第{}次尝试: chatId={}, conversationId={}", attempt + 1, chatId, conversationId); - // 构建状态查询URL - String statusUrl = config.getApiBaseUrl() + "/v3/chat/retrieve?chat_id=" + chatId + "&conversation_id=" + // 构建状态查询URL(使用基础URL拼接状态查询路径) + String baseUrl = extractBaseUrl(config.getApiBaseUrl()); + String statusUrl = baseUrl + "/v3/chat/retrieve?chat_id=" + chatId + "&conversation_id=" + conversationId; // 构建请求头 @@ -1440,8 +1441,9 @@ public class AiChatServiceImpl implements AiChatService { log.info("获取聊天消息: chatId={}, conversationId={}", chatId, conversationId); - // 构建消息查询URL - String messagesUrl = config.getApiBaseUrl() + "/v3/chat/message/list?chat_id=" + chatId + "&conversation_id=" + // 构建消息查询URL(使用基础URL拼接消息查询路径) + String baseUrl = extractBaseUrl(config.getApiBaseUrl()); + String messagesUrl = baseUrl + "/v3/chat/message/list?chat_id=" + chatId + "&conversation_id=" + conversationId; // 构建请求头 @@ -1993,10 +1995,33 @@ public class AiChatServiceImpl implements AiChatService { /** * 获取配置的API路径 + * apiBaseUrl已经是完整的API URL,不需要再拼接路径 */ private String getApiPath(AiConfig config) { - // 默认使用 /v3/chat 路径 - return "/v3/chat"; + // apiBaseUrl已经是完整的URL,返回空字符串 + return ""; + } + + /** + * 从apiBaseUrl中提取基础URL(用于状态查询和消息查询等辅助接口) + * 例如:https://api.coze.cn/v3/chat -> https://api.coze.cn + */ + private String extractBaseUrl(String apiBaseUrl) { + if (apiBaseUrl == null || apiBaseUrl.isEmpty()) { + return ""; + } + try { + java.net.URL url = new java.net.URL(apiBaseUrl); + return url.getProtocol() + "://" + url.getHost() + (url.getPort() > 0 ? ":" + url.getPort() : ""); + } catch (Exception e) { + log.warn("解析apiBaseUrl失败: {}", apiBaseUrl, e); + // 尝试简单截取 + int pathIndex = apiBaseUrl.indexOf("/", apiBaseUrl.indexOf("://") + 3); + if (pathIndex > 0) { + return apiBaseUrl.substring(0, pathIndex); + } + return apiBaseUrl; + } } /** diff --git a/backend-single/src/test/java/com/emotion/service/AiChatServiceImplTest.java b/backend-single/src/test/java/com/emotion/service/AiChatServiceImplTest.java new file mode 100644 index 0000000..b3c0267 --- /dev/null +++ b/backend-single/src/test/java/com/emotion/service/AiChatServiceImplTest.java @@ -0,0 +1,215 @@ +package com.emotion.service; + +import com.emotion.entity.AiConfig; +import com.emotion.service.impl.AiChatServiceImpl; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.DisplayName; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import java.lang.reflect.Method; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * AI聊天服务测试类 + * 测试apiBaseUrl字段调整后的接口调用逻辑 + * + * @author system + * @date 2025-12-22 + */ +@SpringBootTest +@ActiveProfiles("local") +public class AiChatServiceImplTest { + + private AiChatServiceImpl aiChatService; + + @BeforeEach + public void setUp() { + aiChatService = new AiChatServiceImpl(); + } + + @Test + @DisplayName("测试getApiPath方法返回空字符串") + public void testGetApiPath() throws Exception { + // 使用反射调用私有方法 + Method getApiPathMethod = AiChatServiceImpl.class.getDeclaredMethod("getApiPath", AiConfig.class); + getApiPathMethod.setAccessible(true); + + AiConfig config = AiConfig.builder() + .apiBaseUrl("https://api.coze.cn/v3/chat") + .build(); + + String result = (String) getApiPathMethod.invoke(aiChatService, config); + + // 验证返回空字符串,因为apiBaseUrl已经是完整URL + assertEquals("", result, "getApiPath应该返回空字符串"); + } + + @Test + @DisplayName("测试extractBaseUrl方法提取基础URL") + public void testExtractBaseUrl() throws Exception { + // 使用反射调用私有方法 + Method extractBaseUrlMethod = AiChatServiceImpl.class.getDeclaredMethod("extractBaseUrl", String.class); + extractBaseUrlMethod.setAccessible(true); + + // 测试标准URL + String apiBaseUrl1 = "https://api.coze.cn/v3/chat"; + String result1 = (String) extractBaseUrlMethod.invoke(aiChatService, apiBaseUrl1); + assertEquals("https://api.coze.cn", result1, "应该正确提取基础URL"); + + // 测试带端口的URL + String apiBaseUrl2 = "http://localhost:8080/v3/chat"; + String result2 = (String) extractBaseUrlMethod.invoke(aiChatService, apiBaseUrl2); + assertEquals("http://localhost:8080", result2, "应该正确提取带端口的基础URL"); + + // 测试只有域名的URL + String apiBaseUrl3 = "https://api.example.com"; + String result3 = (String) extractBaseUrlMethod.invoke(aiChatService, apiBaseUrl3); + assertEquals("https://api.example.com", result3, "应该正确处理只有域名的URL"); + + // 测试空字符串 + String apiBaseUrl4 = ""; + String result4 = (String) extractBaseUrlMethod.invoke(aiChatService, apiBaseUrl4); + assertEquals("", result4, "空字符串应该返回空字符串"); + + // 测试null + String result5 = (String) extractBaseUrlMethod.invoke(aiChatService, (String) null); + assertEquals("", result5, "null应该返回空字符串"); + } + + @Test + @DisplayName("测试完整API URL的构建逻辑") + public void testApiUrlConstruction() throws Exception { + Method getApiPathMethod = AiChatServiceImpl.class.getDeclaredMethod("getApiPath", AiConfig.class); + getApiPathMethod.setAccessible(true); + + // 创建配置对象,apiBaseUrl是完整的API URL + AiConfig config = AiConfig.builder() + .apiBaseUrl("https://api.coze.cn/v3/chat") + .apiToken("test_token") + .botId("test_bot_id") + .build(); + + String apiPath = (String) getApiPathMethod.invoke(aiChatService, config); + + // 模拟实际调用时的URL构建 + String fullUrl = config.getApiBaseUrl() + apiPath; + + // 验证完整URL就是apiBaseUrl本身 + assertEquals("https://api.coze.cn/v3/chat", fullUrl, + "完整URL应该等于apiBaseUrl,因为apiPath为空"); + } + + @Test + @DisplayName("测试状态查询URL的构建逻辑") + public void testStatusQueryUrlConstruction() throws Exception { + Method extractBaseUrlMethod = AiChatServiceImpl.class.getDeclaredMethod("extractBaseUrl", String.class); + extractBaseUrlMethod.setAccessible(true); + + // 创建配置对象 + AiConfig config = AiConfig.builder() + .apiBaseUrl("https://api.coze.cn/v3/chat") + .build(); + + String baseUrl = (String) extractBaseUrlMethod.invoke(aiChatService, config.getApiBaseUrl()); + String chatId = "test_chat_id"; + String conversationId = "test_conversation_id"; + + // 模拟状态查询URL构建 + String statusUrl = baseUrl + "/v3/chat/retrieve?chat_id=" + chatId + "&conversation_id=" + conversationId; + + // 验证状态查询URL格式正确 + assertEquals("https://api.coze.cn/v3/chat/retrieve?chat_id=test_chat_id&conversation_id=test_conversation_id", + statusUrl, "状态查询URL应该正确构建"); + } + + @Test + @DisplayName("测试消息查询URL的构建逻辑") + public void testMessageQueryUrlConstruction() throws Exception { + Method extractBaseUrlMethod = AiChatServiceImpl.class.getDeclaredMethod("extractBaseUrl", String.class); + extractBaseUrlMethod.setAccessible(true); + + // 创建配置对象 + AiConfig config = AiConfig.builder() + .apiBaseUrl("https://api.coze.cn/v3/chat") + .build(); + + String baseUrl = (String) extractBaseUrlMethod.invoke(aiChatService, config.getApiBaseUrl()); + String chatId = "test_chat_id"; + String conversationId = "test_conversation_id"; + + // 模拟消息查询URL构建 + String messagesUrl = baseUrl + "/v3/chat/message/list?chat_id=" + chatId + "&conversation_id=" + conversationId; + + // 验证消息查询URL格式正确 + assertEquals("https://api.coze.cn/v3/chat/message/list?chat_id=test_chat_id&conversation_id=test_conversation_id", + messagesUrl, "消息查询URL应该正确构建"); + } + + @Test + @DisplayName("测试不同格式的apiBaseUrl") + public void testDifferentApiBaseUrlFormats() throws Exception { + Method getApiPathMethod = AiChatServiceImpl.class.getDeclaredMethod("getApiPath", AiConfig.class); + Method extractBaseUrlMethod = AiChatServiceImpl.class.getDeclaredMethod("extractBaseUrl", String.class); + getApiPathMethod.setAccessible(true); + extractBaseUrlMethod.setAccessible(true); + + // 测试场景1:标准Coze API URL + AiConfig config1 = AiConfig.builder() + .apiBaseUrl("https://api.coze.cn/v3/chat") + .build(); + String apiPath1 = (String) getApiPathMethod.invoke(aiChatService, config1); + String fullUrl1 = config1.getApiBaseUrl() + apiPath1; + assertEquals("https://api.coze.cn/v3/chat", fullUrl1); + + // 测试场景2:自定义API URL + AiConfig config2 = AiConfig.builder() + .apiBaseUrl("https://custom-api.example.com/ai/chat") + .build(); + String apiPath2 = (String) getApiPathMethod.invoke(aiChatService, config2); + String fullUrl2 = config2.getApiBaseUrl() + apiPath2; + assertEquals("https://custom-api.example.com/ai/chat", fullUrl2); + + // 测试场景3:本地开发环境URL + AiConfig config3 = AiConfig.builder() + .apiBaseUrl("http://localhost:8080/api/v1/chat") + .build(); + String apiPath3 = (String) getApiPathMethod.invoke(aiChatService, config3); + String fullUrl3 = config3.getApiBaseUrl() + apiPath3; + assertEquals("http://localhost:8080/api/v1/chat", fullUrl3); + + // 验证extractBaseUrl对这些URL的处理 + String baseUrl1 = (String) extractBaseUrlMethod.invoke(aiChatService, config1.getApiBaseUrl()); + assertEquals("https://api.coze.cn", baseUrl1); + + String baseUrl2 = (String) extractBaseUrlMethod.invoke(aiChatService, config2.getApiBaseUrl()); + assertEquals("https://custom-api.example.com", baseUrl2); + + String baseUrl3 = (String) extractBaseUrlMethod.invoke(aiChatService, config3.getApiBaseUrl()); + assertEquals("http://localhost:8080", baseUrl3); + } + + @Test + @DisplayName("测试边界情况") + public void testEdgeCases() throws Exception { + Method extractBaseUrlMethod = AiChatServiceImpl.class.getDeclaredMethod("extractBaseUrl", String.class); + extractBaseUrlMethod.setAccessible(true); + + // 测试只有协议和域名的URL + String url1 = "https://api.coze.cn"; + String result1 = (String) extractBaseUrlMethod.invoke(aiChatService, url1); + assertEquals("https://api.coze.cn", result1); + + // 测试带多级路径的URL + String url2 = "https://api.coze.cn/v3/chat/stream"; + String result2 = (String) extractBaseUrlMethod.invoke(aiChatService, url2); + assertEquals("https://api.coze.cn", result2); + + // 测试带查询参数的URL(虽然不应该出现在apiBaseUrl中) + String url3 = "https://api.coze.cn/v3/chat?version=1"; + String result3 = (String) extractBaseUrlMethod.invoke(aiChatService, url3); + assertEquals("https://api.coze.cn", result3); + } +} diff --git a/web-admin/src/views/aiconfig/AiConfigList.vue b/web-admin/src/views/aiconfig/AiConfigList.vue index 379ea5d..50ee1ed 100644 --- a/web-admin/src/views/aiconfig/AiConfigList.vue +++ b/web-admin/src/views/aiconfig/AiConfigList.vue @@ -262,8 +262,8 @@ - - + + @@ -512,7 +512,7 @@ {{ getProviderLabel(viewData.provider) }} {{ getUsageScenarioLabel(viewData.usageScenario) }} {{ getEnvironmentLabel(viewData.environment || '') }} - {{ viewData.apiBaseUrl }} + {{ viewData.apiBaseUrl }} {{ viewData.apiToken }} {{ viewData.modelName || '-' }} {{ viewData.priority || 0 }} @@ -749,7 +749,7 @@ const formRules: FormRules = { configKey: [{ required: true, message: '请输入配置键值', trigger: 'blur' }], configType: [{ required: true, message: '请选择配置类型', trigger: 'change' }], provider: [{ required: true, message: '请选择服务提供商', trigger: 'change' }], - apiBaseUrl: [{ required: true, message: '请输入API基础URL', trigger: 'blur' }], + apiBaseUrl: [{ required: true, message: '请输入完整的API URL', trigger: 'blur' }], apiToken: [{ required: true, message: '请输入API访问令牌', trigger: 'blur' }], usageScenario: [{ required: true, message: '请选择使用场景', trigger: 'change' }] } @@ -1081,8 +1081,8 @@ const handleDialogClose = () => { // 初始化测试数据 const initTestData = (config: AiConfig) => { - // 构建请求URL - testRequest.url = config.apiBaseUrl + '/v3/chat' + // apiBaseUrl已经是完整的API URL,直接使用 + testRequest.url = config.apiBaseUrl // 构建请求头 const headers = {