diff --git a/test-admin/pom.xml b/test-admin/pom.xml index 14e0dba..b22f28e 100644 --- a/test-admin/pom.xml +++ b/test-admin/pom.xml @@ -61,9 +61,6 @@ org.springframework.boot spring-boot-maven-plugin 2.5.15 - - true - diff --git a/test-test/src/main/java/com/test/test/controller/TestApiController.java b/test-test/src/main/java/com/test/test/controller/TestApiController.java index 93ef420..b1c4ff1 100644 --- a/test-test/src/main/java/com/test/test/controller/TestApiController.java +++ b/test-test/src/main/java/com/test/test/controller/TestApiController.java @@ -14,7 +14,6 @@ import com.test.common.enums.BusinessType; import com.test.test.domain.TestApi; import com.test.test.service.ITestApiService; import com.test.common.core.page.TableDataInfo; -import org.springframework.web.multipart.MultipartFile; /** * 接口Controller diff --git a/test-test/src/main/java/com/test/test/controller/TestGroupController.java b/test-test/src/main/java/com/test/test/controller/TestGroupController.java index 2ef9a9c..2aa5d8d 100644 --- a/test-test/src/main/java/com/test/test/controller/TestGroupController.java +++ b/test-test/src/main/java/com/test/test/controller/TestGroupController.java @@ -20,7 +20,7 @@ public class TestGroupController extends BaseController { private ITestGroupService testGroupService; /** - * 查询接口节点列表 + * 查询节点列表 */ @GetMapping("/list") public AjaxResult list(String type) { @@ -29,27 +29,27 @@ public class TestGroupController extends BaseController { } /** - * 新增接口节点 + * 新增节点 */ - @Log(title = "接口节点", businessType = BusinessType.INSERT) + @Log(title = "节点", businessType = BusinessType.INSERT) @PostMapping("/add") public AjaxResult add(@RequestBody TestGroup testGroup) { return success(testGroupService.insertTestGroup(testGroup)); } /** - * 修改接口节点 + * 修改节点 */ - @Log(title = "接口节点", businessType = BusinessType.UPDATE) + @Log(title = "节点", businessType = BusinessType.UPDATE) @PostMapping("/edit") public AjaxResult edit(@RequestBody TestGroup testGroup) { return toAjax(testGroupService.updateTestGroup(testGroup)); } /** - * 删除接口节点 + * 删除节点 */ - @Log(title = "接口节点", businessType = BusinessType.DELETE) + @Log(title = "节点", businessType = BusinessType.DELETE) @PostMapping("/del") public AjaxResult remove(@RequestBody @Validated GroupDelectQO qo) throws Exception { return toAjax(testGroupService.deleteTestGroupById(qo)); diff --git a/test-test/src/main/java/com/test/test/domain/dto/SwaggerInfo.java b/test-test/src/main/java/com/test/test/domain/dto/SwaggerInfo.java deleted file mode 100644 index 9afe569..0000000 --- a/test-test/src/main/java/com/test/test/domain/dto/SwaggerInfo.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.test.test.domain.dto; - -public class SwaggerInfo { -} diff --git a/test-test/src/main/java/com/test/test/mapper/TestGroupMapper.java b/test-test/src/main/java/com/test/test/mapper/TestGroupMapper.java index 275fbf5..856a20a 100644 --- a/test-test/src/main/java/com/test/test/mapper/TestGroupMapper.java +++ b/test-test/src/main/java/com/test/test/mapper/TestGroupMapper.java @@ -33,4 +33,5 @@ public interface TestGroupMapper */ int deleteTestGroupByIds(List ids); + TestGroup selectGroup(String name, Long parentId, String type); } diff --git a/test-test/src/main/java/com/test/test/service/ITestGroupService.java b/test-test/src/main/java/com/test/test/service/ITestGroupService.java index 5ab13c7..9b6f744 100644 --- a/test-test/src/main/java/com/test/test/service/ITestGroupService.java +++ b/test-test/src/main/java/com/test/test/service/ITestGroupService.java @@ -1,6 +1,7 @@ package com.test.test.service; import java.util.List; + import com.test.test.domain.TestGroup; import com.test.test.domain.qo.GroupDelectQO; @@ -9,8 +10,7 @@ import com.test.test.domain.qo.GroupDelectQO; * * @author xiaoe */ -public interface ITestGroupService -{ +public interface ITestGroupService { /** * 查询节点(文件夹)列表 */ @@ -21,6 +21,11 @@ public interface ITestGroupService */ TestGroup insertTestGroup(TestGroup testGroup); + /** + * 查询节点(文件夹) + */ + TestGroup selectGroup(String name, Long parentId, String type); + /** * 修改节点(文件夹) */ diff --git a/test-test/src/main/java/com/test/test/service/impl/TestApiServiceImpl.java b/test-test/src/main/java/com/test/test/service/impl/TestApiServiceImpl.java index 7b4ad91..b9076c6 100644 --- a/test-test/src/main/java/com/test/test/service/impl/TestApiServiceImpl.java +++ b/test-test/src/main/java/com/test/test/service/impl/TestApiServiceImpl.java @@ -1,16 +1,20 @@ package com.test.test.service.impl; -import java.util.List; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import com.alibaba.fastjson2.JSONObject; import com.test.common.utils.DateUtils; import com.test.common.utils.http.HttpUtils; +import com.test.test.domain.TestGroup; import com.test.test.domain.qo.TestApiListQO; +import com.test.test.service.ITestGroupService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import com.test.test.mapper.TestApiMapper; import com.test.test.domain.TestApi; import com.test.test.service.ITestApiService; +import org.springframework.transaction.annotation.Transactional; /** * 接口Service业务层处理 @@ -22,6 +26,9 @@ public class TestApiServiceImpl implements ITestApiService { @Resource private TestApiMapper testApiMapper; + @Resource + private ITestGroupService testGroupService; + /** * 查询接口 * @@ -57,9 +64,159 @@ public class TestApiServiceImpl implements ITestApiService { } @Override + @Transactional public int importSwaggerApi(String url) { - JSONObject json = JSONObject.parse(HttpUtils.sendGet(url)); - return 0; + AtomicInteger count = new AtomicInteger(); + JSONObject jsonObject = JSONObject.parseObject(HttpUtils.sendGet(url)); + String title = jsonObject.getJSONObject("info").getString("title"); + // 设置顶级节点 + Long parentId = getGroupId(title, 0L); + // 获取Schemas + JSONObject schemas = jsonObject.getJSONObject("components").getJSONObject("schemas"); + // 获取所有接口 + jsonObject.getJSONObject("paths").forEach((uri, pathJson) -> { + ((JSONObject) pathJson).forEach((method, v) -> { + JSONObject json = (JSONObject) v; + // 获取接口名 + String name = json.getString("summary"); + if (name == null) name = uri; + // 获取接口分组 + String groupName = title; + List tags = json.getList("tags", String.class); + if (!tags.isEmpty()) { + groupName = tags.get(0); + } + // 获取body + String body = ""; + String contentType = ""; + if (json.getJSONObject("requestBody") != null) { + JSONObject bodyJson = json.getJSONObject("requestBody").getJSONObject("content"); + if (bodyJson != null) { + Set keys = bodyJson.keySet(); + if (!keys.isEmpty()) { + contentType = keys.iterator().next(); + JSONObject schema = bodyJson.getJSONObject(contentType).getJSONObject("schema"); + body = JSONObject.toJSONString(parseSchema(schema, schemas)); + } + } + } + // 获取Param + String param = ""; + JSONObject parameters = json.getJSONObject("parameters"); + if (parameters!=null) { + JSONObject paramsJson = parseParams(parameters, schemas); + param = JSONObject.toJSONString(paramsJson); + } + TestApi testApi = new TestApi(); + testApi.setUri(uri); + testApi.setMethod(method); + testApi.setName(name); + testApi.setGroupId(getGroupId(groupName, parentId)); + testApi.setBody(body); + testApi.setParam(param); + + count.addAndGet(testApiMapper.insertTestApi(testApi)); + }); + }); + return count.get(); + } + + private static JSONObject parseSchema(JSONObject schema, JSONObject schemas) { + JSONObject result = new JSONObject(); + + // 如果 schema 包含 $ref,则解析引用 + if (schema.containsKey("$ref")) { + String ref = schema.getString("$ref"); + // 去掉 #/components/schemas/ 前缀,获取引用的 schema 名称 + String schemaName = ref.replace("#/components/schemas/", ""); + JSONObject referencedSchema = schemas.getJSONObject(schemaName); + // 递归解析引用的 schema + return parseSchema(referencedSchema, schemas); + } + + // 如果 schema 包含 type,则直接根据类型构建结果 + if (schema.containsKey("type")) { + String type = schema.getString("type"); + switch (type) { + case "integer": + result.put("value", 0); + break; + case "string": + result.put("value", "string"); + break; + case "boolean": + result.put("value", false); + break; + default: + result.put("value", type); + } + } + + // 如果 schema 有 properties,则遍历 properties 并递归解析 + if (schema.containsKey("properties")) { + JSONObject properties = schema.getJSONObject("properties"); + for (Map.Entry entry : properties.entrySet()) { + String key = entry.getKey(); + JSONObject propertySchema = (JSONObject) entry.getValue(); + JSONObject propertyResult = parseSchema(propertySchema, schemas); // 递归解析每个字段 + result.put(key, propertyResult.get("value")); // 获取解析结果的值 + } + } + + return result; + } + + private static JSONObject parseParams(JSONObject params, JSONObject schemas) { + JSONObject result = new JSONObject(); + + // 遍历 params 中的每个参数 + for (String key : params.keySet()) { + // 获取当前参数的 schema 定义 + Object value = params.get(key); + + // 获取 schema + JSONObject schema = schemas.getJSONObject(key); + + // 如果 schema 是基础类型,则直接赋值 + if (schema != null && schema.containsKey("type")) { + String type = schema.getString("type"); + if ("string".equals(type)) { + result.put(key, value != null ? value : "string"); // 默认值为 "string" + } else if ("integer".equals(type)) { + result.put(key, value != null ? value : 0); // 默认值为 0 + } else if ("boolean".equals(type)) { + result.put(key, value != null ? value : false); // 默认值为 false + } + } + // 如果 schema 是引用类型,则递归解析该引用 + else if (schema != null && schema.containsKey("$ref")) { + String ref = schema.getString("$ref"); + String schemaName = ref.replace("#/components/schemas/", ""); + JSONObject referencedSchema = schemas.getJSONObject(schemaName); + + // 如果引用的 schema 存在,递归解析该 schema + if (referencedSchema != null) { + // 递归调用,解析引用的 schema + JSONObject nestedResult = parseParams(new JSONObject(), schemas); + result.putAll(nestedResult); + } + } + } + + return result; + } + + private Long getGroupId(String groupName, Long parentId) { + TestGroup group = testGroupService.selectGroup(groupName, parentId, "api"); + if (group == null) { + group = new TestGroup(); + group.setParentId(parentId); + group.setName(groupName); + group.setType("api"); + group.setCreateTime(DateUtils.getNowDate()); + testGroupService.insertTestGroup(group); + } + return group.getId(); } /** diff --git a/test-test/src/main/java/com/test/test/service/impl/TestGroupServiceImpl.java b/test-test/src/main/java/com/test/test/service/impl/TestGroupServiceImpl.java index c6974f7..c5259a7 100644 --- a/test-test/src/main/java/com/test/test/service/impl/TestGroupServiceImpl.java +++ b/test-test/src/main/java/com/test/test/service/impl/TestGroupServiceImpl.java @@ -8,6 +8,7 @@ import com.test.common.utils.DateUtils; import com.test.common.utils.StringUtils; import com.test.test.domain.qo.GroupDelectQO; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import com.test.test.mapper.TestGroupMapper; import com.test.test.domain.TestGroup; @@ -26,6 +27,7 @@ public class TestGroupServiceImpl implements ITestGroupService { private TestGroupMapper testGroupMapper; @Resource + @Lazy private TestApiServiceImpl testApiServiceImpl; /** @@ -46,6 +48,11 @@ public class TestGroupServiceImpl implements ITestGroupService { return testGroup; } + @Override + public TestGroup selectGroup(String name, Long parentId, String type) { + return testGroupMapper.selectGroup(name, parentId, type); + } + /** * 修改节点(文件夹) */ diff --git a/test-test/src/main/resources/mapper/test/TestApiMapper.xml b/test-test/src/main/resources/mapper/test/TestApiMapper.xml index 5446865..57ead91 100644 --- a/test-test/src/main/resources/mapper/test/TestApiMapper.xml +++ b/test-test/src/main/resources/mapper/test/TestApiMapper.xml @@ -33,6 +33,7 @@ and method = #{method} and uri like concat('%', #{uri}, '%') + order by create_time desc + + insert into test_group diff --git a/test-ui/src/api/test/api.js b/test-ui/src/api/test/api.js index bda0365..9eaac71 100644 --- a/test-ui/src/api/test/api.js +++ b/test-ui/src/api/test/api.js @@ -39,8 +39,16 @@ export function updateApi(data) { // 删除接口 export function delApi(id) { return request({ - url: '/test/api/del/', + url: '/test/api/del', method: 'post', - params: {id} + data: {id} + }) +} + +export function importApi(url) { + return request({ + url: '/test/api/import/swagger', + method: 'post', + params: url }) } diff --git a/test-ui/src/views/test/api/add.vue b/test-ui/src/views/test/api/add.vue index 2b8bc7e..69c4857 100644 --- a/test-ui/src/views/test/api/add.vue +++ b/test-ui/src/views/test/api/add.vue @@ -143,7 +143,7 @@ export default { this.form.header.splice(scope.$index, 1) }, cancel() { - this.$tab.closeOpenPage({ path: "/api" }); + this.$tab.closeOpenPage({path: "/api"}); } } } @@ -158,9 +158,11 @@ export default { ::v-deep .el-collapse-item__wrap { padding: 0 16px; } + ::v-deep.el-select { width: 130px; } + .input-with-select ::v-deep .el-input-group__prepend { background-color: #fff; } diff --git a/test-ui/src/views/test/api/edit.vue b/test-ui/src/views/test/api/edit.vue index d948641..1feb255 100644 --- a/test-ui/src/views/test/api/edit.vue +++ b/test-ui/src/views/test/api/edit.vue @@ -139,7 +139,7 @@ export default { contentType: this.form.contentType, body: this.form.body, }).then(res => { - this.$message.success("新增成功"); + this.$message.success("修改成功"); this.cancel(); }) }, @@ -165,7 +165,7 @@ export default { this.form.header.splice(scope.$index, 1) }, cancel() { - this.$tab.closeOpenPage({ path: "/api" }); + this.$tab.closeOpenPage({path: "/api"}); } } } @@ -180,9 +180,11 @@ export default { ::v-deep .el-collapse-item__wrap { padding: 0 16px; } + ::v-deep.el-select { width: 130px; } + .input-with-select ::v-deep .el-input-group__prepend { background-color: #fff; } diff --git a/test-ui/src/views/test/api/import.vue b/test-ui/src/views/test/api/import.vue index dbd3049..b0bcde1 100644 --- a/test-ui/src/views/test/api/import.vue +++ b/test-ui/src/views/test/api/import.vue @@ -1,22 +1,46 @@