From c25f10050b9cd27100c93592302763a7af17c208 Mon Sep 17 00:00:00 2001 From: Coooder-X <55648333+Coooder-X@users.noreply.github.com> Date: Thu, 11 Mar 2021 20:44:29 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89):=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E4=B8=BA=20swagger=20=E6=A0=BC=E5=BC=8F=20(#1606)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(测试跟踪): 测试用例下载模版增加标签列 * fix(接口定义): 扩大请求头键长度 * feat(接口定义): 支持接口定义导出为 swagger 格式 --- .../controller/ApiDefinitionController.java | 6 +- .../api/dto/definition/ApiExportResult.java | 11 +- .../api/dto/definition/MsApiExportResult.java | 20 +++ .../definition/SwaggerApiExportResult.java | 22 ++++ .../dto/definition/parse/Swagger2Parser.java | 6 +- .../dto/definition/parse/Swagger3Parser.java | 119 ++++++++++++++++++ .../parse/swagger/SwaggerApiInfo.java | 17 +++ .../parse/swagger/SwaggerParams.java | 12 ++ .../api/service/ApiDefinitionService.java | 26 ++-- .../api/definition/ApiDefinition.vue | 4 +- .../definition/components/list/ApiList.vue | 15 ++- .../components/module/ApiModule.vue | 4 +- .../components/module/ApiModuleHeader.vue | 42 +++++-- frontend/src/i18n/en-US.js | 4 +- frontend/src/i18n/zh-CN.js | 4 +- frontend/src/i18n/zh-TW.js | 4 +- 16 files changed, 271 insertions(+), 45 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/api/dto/definition/MsApiExportResult.java create mode 100644 backend/src/main/java/io/metersphere/api/dto/definition/SwaggerApiExportResult.java create mode 100644 backend/src/main/java/io/metersphere/api/dto/definition/parse/swagger/SwaggerApiInfo.java create mode 100644 backend/src/main/java/io/metersphere/api/dto/definition/parse/swagger/SwaggerParams.java diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java index 3b2a394e4c..c801121e83 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java @@ -148,10 +148,10 @@ public class ApiDefinitionController { return apiDefinitionService.apiTestImport(file, request); } - @PostMapping(value = "/export") + @PostMapping(value = "/export/{type}") @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) - public ApiExportResult export(@RequestBody ApiBatchRequest request) { - return apiDefinitionService.export(request); + public ApiExportResult export(@RequestBody ApiBatchRequest request, @PathVariable String type) { + return apiDefinitionService.export(request, type); } //定时任务创建 diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/ApiExportResult.java b/backend/src/main/java/io/metersphere/api/dto/definition/ApiExportResult.java index c63c8ae4bd..11caf9410f 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/ApiExportResult.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/ApiExportResult.java @@ -1,19 +1,10 @@ package io.metersphere.api.dto.definition; -import io.metersphere.base.domain.ApiDefinitionWithBLOBs; -import io.metersphere.base.domain.ApiTestCaseWithBLOBs; import lombok.Getter; import lombok.Setter; -import java.util.List; - @Getter @Setter public class ApiExportResult { - private String projectName; - private String protocol; - private String projectId; - private String version; - private List data; - private List cases; + } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/MsApiExportResult.java b/backend/src/main/java/io/metersphere/api/dto/definition/MsApiExportResult.java new file mode 100644 index 0000000000..0b839273b6 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/MsApiExportResult.java @@ -0,0 +1,20 @@ +package io.metersphere.api.dto.definition; + +import io.metersphere.base.domain.ApiDefinitionWithBLOBs; +import io.metersphere.base.domain.ApiTestCaseWithBLOBs; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class MsApiExportResult extends ApiExportResult { + private String projectName; + private String protocol; + private String projectId; + private String version; + private List data; + private List cases; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/SwaggerApiExportResult.java b/backend/src/main/java/io/metersphere/api/dto/definition/SwaggerApiExportResult.java new file mode 100644 index 0000000000..627a369318 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/SwaggerApiExportResult.java @@ -0,0 +1,22 @@ +package io.metersphere.api.dto.definition; + +import com.alibaba.fastjson.JSONObject; +import io.metersphere.api.dto.definition.parse.swagger.SwaggerInfo; +import io.metersphere.api.dto.definition.parse.swagger.SwaggerTag; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class SwaggerApiExportResult extends ApiExportResult{ + private String openapi; + private SwaggerInfo info; + private String externalDocs; + private List servers; + private List tags; + private JSONObject paths; // Map, Object 里放 Operation 对象 + private List components; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger2Parser.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger2Parser.java index f41ef16da4..3701079c1e 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger2Parser.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger2Parser.java @@ -30,14 +30,14 @@ public class Swagger2Parser extends SwaggerAbstractParser { public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) { Swagger swagger; String sourceStr = ""; - if (StringUtils.isNotBlank(request.getSwaggerUrl())) { + if (StringUtils.isNotBlank(request.getSwaggerUrl())) { // 使用 url 导入 swagger swagger = new SwaggerParser().read(request.getSwaggerUrl()); } else { - sourceStr = getApiTestStr(source); + sourceStr = getApiTestStr(source); // 导入的二进制文件转换为 String swagger = new SwaggerParser().readWithInfo(sourceStr).getSwagger(); } - if (swagger == null || swagger.getSwagger() == null) { + if (swagger == null || swagger.getSwagger() == null) { // 不是 2.0 版本,则尝试转换 3.0 Swagger3Parser swagger3Parser = new Swagger3Parser(); return swagger3Parser.parse(sourceStr, request); } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java index e7602cfe18..8ad99168f6 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/Swagger3Parser.java @@ -4,14 +4,18 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import io.metersphere.api.dto.ApiTestImportRequest; +import io.metersphere.api.dto.definition.SwaggerApiExportResult; +import io.metersphere.api.dto.definition.parse.swagger.*; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.definition.response.HttpResponse; import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.request.RequestType; +import io.metersphere.api.service.ApiModuleService; import io.metersphere.base.domain.ApiDefinitionWithBLOBs; import io.metersphere.base.domain.ApiModule; import io.metersphere.commons.exception.MSException; +import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.XMLUtils; import io.swagger.parser.OpenAPIParser; @@ -362,4 +366,119 @@ public class Swagger3Parser extends SwaggerAbstractParser { QueryParameter queryParameter = (QueryParameter) parameter; arguments.add(new KeyValue(queryParameter.getName(), "", getDefaultStringValue(queryParameter.getDescription()), parameter.getRequired())); } +/* 导出的 swagger json描述文件样例 +{ + "openapi":"3.0.1", + "info":{}, + "externalDocs":{}, + "servers":{}, + "tags":{}, + "paths":{ // 对应 SwaggerApiExportResult 类的paths + "/lzx/test/{ball}":{ // key + "get":{ // 对应 SwaggerPath 类的 JSONObject 类型的成员,”get“为key + "tags":[ + "subModule2" + ], + "summary":"API", + "parameters":[ + { + "name":"ballName", + "in":"query",// path,header,query都可选。 + "description":"描述param", + "required":true // 是否必填参数 + } + ], + "requestBody":{ + "content":{ + "application/octet-stream":{ // type + "schema":{ + "type":null, + "format":null + } + } + } + } + } // SwaggerApiInfo类,为 value + } + }, + "components":{} +} */ + public SwaggerApiExportResult swagger3Export(List apiDefinitionList) { + SwaggerApiExportResult result = new SwaggerApiExportResult(); + + result.setOpenapi("3.0.1"); + result.setInfo(new SwaggerInfo()); + result.setServers(new ArrayList<>()); + result.setTags(new ArrayList<>()); + result.setComponents(new ArrayList<>()); + + JSONObject paths = new JSONObject(); + JSONObject swaggerPath = new JSONObject(); + for(ApiDefinitionWithBLOBs apiDefinition : apiDefinitionList) { + SwaggerApiInfo swaggerApiInfo = new SwaggerApiInfo(); // {tags:, summary:, description:, parameters:} + swaggerApiInfo.setSummary(apiDefinition.getName()); + // 设置导入后的模块名 (根据 api 的 moduleID 查库获得所属模块,作为导出的模块名) + ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); + String moduleName = apiModuleService.getNode(apiDefinition.getModuleId()).getName(); + swaggerApiInfo.setTags(Arrays.asList(moduleName)); + // 设置请求体 + JSONObject requestObject = JSON.parseObject(apiDefinition.getRequest()); // 将api的request属性转换成JSON对象以便获得参数 + JSONObject requestBody = buildRequestBody(requestObject); + swaggerApiInfo.setRequestBody(requestBody); + // 设置请求参数列表 + List paramsList = buildParameters(requestObject); + swaggerApiInfo.setParameters(paramsList); + swaggerPath.put(apiDefinition.getMethod().toLowerCase(), JSON.parseObject(JSON.toJSONString(swaggerApiInfo))); // 设置api的请求类型和api定义、参数 + paths.put(apiDefinition.getPath(), swaggerPath); + } + result.setPaths(paths); + return result; + } + + private List buildParameters(JSONObject request) { + List paramsList = new ArrayList<>(); + Hashtable typeMap = new Hashtable() {{ + put("headers", "header"); + put("rest", "path"); + put("arguments", "query"); + }}; + Set typeKeys = typeMap.keySet(); + for(String type : typeKeys) { + JSONArray params = request.getJSONArray(type); // 获得请求参数列表 + if(params != null) { + for(int i = 0; i < params.size(); ++i) { + JSONObject param = params.getJSONObject(i); // 对于每个参数: + SwaggerParams swaggerParam = new SwaggerParams(); + swaggerParam.setIn(typeMap.get(type)); // 利用 map,根据 request 的 key 设置对应的参数类型 + swaggerParam.setDescription((String) param.get("description")); + swaggerParam.setName((String) param.get("name")); + swaggerParam.setRequired((boolean) param.get("required")); + paramsList.add(JSON.parseObject(JSON.toJSONString(swaggerParam))); + } + } + } + return paramsList; + } + + private JSONObject buildRequestBody(JSONObject request) { + Hashtable typeMap = new Hashtable() {{ + put("XML", org.springframework.http.MediaType.APPLICATION_XML_VALUE); + put("JSON", org.springframework.http.MediaType.APPLICATION_JSON_VALUE); + put("Raw", "application/urlencoded"); + put("BINARY", org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE); + put("Form Data", org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE); + put("WWW_FORM", org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE); + }}; + String type = request.getJSONObject("body").getString("type"); + JSONObject requestBody = new JSONObject(); + JSONObject schema = new JSONObject(); + JSONObject typeName = new JSONObject(); + schema.put("type", null); + schema.put("format", null); + typeName.put("schema", schema); + JSONObject content = new JSONObject(); + content.put(typeMap.get(type), typeName); + requestBody.put("content", content); + return requestBody; + } } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/swagger/SwaggerApiInfo.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/swagger/SwaggerApiInfo.java new file mode 100644 index 0000000000..bc22f85037 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/swagger/SwaggerApiInfo.java @@ -0,0 +1,17 @@ +package io.metersphere.api.dto.definition.parse.swagger; +import lombok.*; +import com.alibaba.fastjson.JSONObject; + +import java.util.List; + +/* +该类表示 swagger3 的 paths 字段下每个请求类型中的 value,即表示一个 api 定义 + */ +@Getter +@Setter +public class SwaggerApiInfo { + private List tags; // 对应一个 API 在MS项目中所在的 module 名称 + private String summary; // 对应 API 的名字 + private List parameters; // 对应 API 的请求参数 + private JSONObject requestBody; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/swagger/SwaggerParams.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/swagger/SwaggerParams.java new file mode 100644 index 0000000000..7559992eb8 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/swagger/SwaggerParams.java @@ -0,0 +1,12 @@ +package io.metersphere.api.dto.definition.parse.swagger; + +import lombok.*; + +@Getter +@Setter +public class SwaggerParams { + private String name; // 对应 API 请求参数名 + private String in; // 参数类型,可选值为 path,header,query 等 + private String description; + private boolean required; // 是否是必填参数 +} diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java index 01148eaa55..d580c154af 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -10,6 +10,7 @@ import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.parse.ApiDefinitionImportParserFactory; +import io.metersphere.api.dto.definition.parse.Swagger3Parser; import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.definition.request.ScheduleInfoSwaggerUrlRequest; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; @@ -762,18 +763,27 @@ public class ApiDefinitionService { scheduleService.addOrUpdateCronJob(request, SwaggerUrlImportJob.getJobKey(request.getResourceId()), SwaggerUrlImportJob.getTriggerKey(request.getResourceId()), SwaggerUrlImportJob.class); } - public ApiExportResult export(ApiBatchRequest request) { + public ApiExportResult export(ApiBatchRequest request, String type) { + ApiExportResult apiExportResult; ServiceUtils.getSelectAllIds(request, request.getCondition(), (query) -> extApiDefinitionMapper.selectIds(query)); ApiDefinitionExample example = new ApiDefinitionExample(); example.createCriteria().andIdIn(request.getIds()); - ApiExportResult apiExportResult = new ApiExportResult(); - apiExportResult.setData(apiDefinitionMapper.selectByExampleWithBLOBs(example)); - apiExportResult.setCases(apiTestCaseService.selectCasesBydApiIds(request.getIds())); - apiExportResult.setProjectName(request.getProjectId()); - apiExportResult.setProtocol(request.getProtocol()); - apiExportResult.setProjectId(request.getProjectId()); - apiExportResult.setVersion(System.getenv("MS_VERSION")); + + if (StringUtils.equals(type, "MS")) { // 导出为 Metersphere 格式 + apiExportResult = new MsApiExportResult(); + ((MsApiExportResult) apiExportResult).setData(apiDefinitionMapper.selectByExampleWithBLOBs(example)); + ((MsApiExportResult) apiExportResult).setCases(apiTestCaseService.selectCasesBydApiIds(request.getIds())); + ((MsApiExportResult) apiExportResult).setProjectName(request.getProjectId()); + ((MsApiExportResult) apiExportResult).setProtocol(request.getProtocol()); + ((MsApiExportResult) apiExportResult).setProjectId(request.getProjectId()); + ((MsApiExportResult) apiExportResult).setVersion(System.getenv("MS_VERSION")); + } + else { // 导出为 Swagger 格式 + Swagger3Parser swagger3Parser = new Swagger3Parser(); + System.out.println(apiDefinitionMapper.selectByExampleWithBLOBs(example)); + apiExportResult = swagger3Parser.swagger3Export(apiDefinitionMapper.selectByExampleWithBLOBs(example)); + } return apiExportResult; } } diff --git a/frontend/src/business/components/api/definition/ApiDefinition.vue b/frontend/src/business/components/api/definition/ApiDefinition.vue index a23ddf060e..bafa5b22ee 100644 --- a/frontend/src/business/components/api/definition/ApiDefinition.vue +++ b/frontend/src/business/components/api/definition/ApiDefinition.vue @@ -348,12 +348,12 @@ import MsTabButton from "@/business/components/common/components/MsTabButton"; apiCaseClose() { this.showCasePage = true; }, - exportAPI() { + exportAPI(type) { if (!this.isApiListEnable) { this.$warning('用例列表暂不支持导出,请切换成接口列表'); return; } - this.$refs.apiList[0].exportApi(); + this.$refs.apiList[0].exportApi(type); }, refresh(data) { this.$refs.apiList[0].initTable(data); diff --git a/frontend/src/business/components/api/definition/components/list/ApiList.vue b/frontend/src/business/components/api/definition/components/list/ApiList.vue index 0246dc15d8..80b323b0b6 100644 --- a/frontend/src/business/components/api/definition/components/list/ApiList.vue +++ b/frontend/src/business/components/api/definition/components/list/ApiList.vue @@ -698,18 +698,23 @@ export default { let ids = rowArray.map(s => s.id); return ids; }, - exportApi() { + exportApi(type) { let param = buildBatchParam(this); param.protocol = this.currentProtocol; if (param.ids === undefined || param.ids.length < 1) { this.$warning(this.$t("api_test.definition.check_select")); return; } - this.result = this.$post("/api/definition/export", param, response => { + this.result = this.$post("/api/definition/export/" + type, param, response => { let obj = response.data; - obj.protocol = this.currentProtocol; - this.buildApiPath(obj.data); - downloadFile("Metersphere_Api_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj)); + if(type == 'MS') { + obj.protocol = this.currentProtocol; + this.buildApiPath(obj.data); + downloadFile("Metersphere_Api_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj)); + } + else { + downloadFile("Swagger_Api_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj)); + } }); }, buildApiPath(apis) { diff --git a/frontend/src/business/components/api/definition/components/module/ApiModule.vue b/frontend/src/business/components/api/definition/components/module/ApiModule.vue index 3d3feae393..f45dea9632 100644 --- a/frontend/src/business/components/api/definition/components/module/ApiModule.vue +++ b/frontend/src/business/components/api/definition/components/module/ApiModule.vue @@ -188,8 +188,8 @@ export default { this.$refs.nodeTree.append({}, dataArr[0]); } }, - exportAPI() { - this.$emit('exportAPI'); + exportAPI(type) { + this.$emit('exportAPI', type); }, debug() { this.$emit('debug'); diff --git a/frontend/src/business/components/api/definition/components/module/ApiModuleHeader.vue b/frontend/src/business/components/api/definition/components/module/ApiModuleHeader.vue index 404ad12629..4f5b2b6bb4 100644 --- a/frontend/src/business/components/api/definition/components/module/ApiModuleHeader.vue +++ b/frontend/src/business/components/api/definition/components/module/ApiModuleHeader.vue @@ -14,13 +14,29 @@ @@ -44,10 +60,11 @@ import ApiImport from "../import/ApiImport"; import ModuleTrashButton from "./ModuleTrashButton"; import {getCurrentProjectID} from "../../../../../../common/js/utils"; import {buildNodePath} from "@/business/components/api/definition/model/NodeTree"; +import TemplateComponent from "../../../../track/plan/view/comonents/report/TemplateComponent/TemplateComponent"; export default { name: "ApiModuleHeader", - components: {ModuleTrashButton, ApiImport, MsAddBasisApi}, + components: {TemplateComponent, ModuleTrashButton, ApiImport, MsAddBasisApi}, data() { return { options: OPTIONS, @@ -104,12 +121,19 @@ export default { }); this.$refs.apiImport.open(this.currentModule); break; - default: - if (!getCurrentProjectID()) { - this.$warning(this.$t('commons.check_project_tip')); - return; - } - this.$emit('exportAPI'); + } + }, + chooseExportType(e) { + if (!getCurrentProjectID()) { + this.$warning(this.$t('commons.check_project_tip')); + return; + } + switch (e) { + case "export-MS": + this.$emit('exportAPI', 'MS'); + break; + case "export-Swagger": + this.$emit('exportAPI', 'Swagger'); break; } }, diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index 598b566f14..32a16a6f4b 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -427,6 +427,8 @@ export default { downloadJtl: 'Download JTL', test_execute_again: 'Test Execute Again', export: 'Export', + export_to_ms_format: 'Export to Metersphere format', + export_to_swagger3_format: 'Export to Swagger3.0 format', compare: 'Compare', generation_error: 'Report generation error, unable to view, please check log details!', being_generated: 'Report is being generated...', @@ -597,7 +599,7 @@ export default { save_as_case: "Save as new use case", update_api: "Update interface", body_form_data: "form-data", - body_x_www_from_urlencoded: "x-www-from-urlencoded", + body_x_www_from_urlencoded: "x-www-form-urlencoded", body_raw: "raw", body_binary: "binary", body_json: "json", diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index 0d14572e6d..1638f93a73 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -425,6 +425,8 @@ export default { test_execute_again: '再次执行', downloadJtl: '下载JTL', export: '导出', + export_to_ms_format: '导出 Metersphere 格式', + export_to_swagger3_format: '导出 Swagger3.0 格式', compare: '比较', generation_error: '报告生成错误, 无法查看, 请检查日志详情!', being_generated: '报告正在生成中...', @@ -598,7 +600,7 @@ export default { save_as_case: "另存为新用例", update_api: "更新接口", body_form_data: "form-data", - body_x_www_from_urlencoded: "x-www-from-urlencoded", + body_x_www_from_urlencoded: "x-www-form-urlencoded", body_raw: "raw", body_binary: "binary", body_json: "json", diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index ef4e753bb9..3ff7115141 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -425,6 +425,8 @@ export default { test_execute_again: '再次執行', downloadJtl: '下載JTL', export: '導出', + export_to_ms_format: '導出 Metersphere 格式', + export_to_swagger3_format: '導出 Swagger3.0 格式', compare: '比較', generation_error: '報告生成錯誤, 無法查看, 請檢查日誌詳情!', being_generated: '報告正在生成中...', @@ -597,7 +599,7 @@ export default { save_as_case: "另存為新用例", update_api: "更新接口", body_form_data: "form-data", - body_x_www_from_urlencoded: "x-www-from-urlencoded", + body_x_www_from_urlencoded: "x-www-form-urlencoded", body_raw: "raw", body_binary: "binary", body_json: "json",