feat(接口自动化): 增加URL唯一性校验开关,控制URL校验规则

This commit is contained in:
fit2-zhao 2021-01-06 13:38:17 +08:00
parent e975dcbc18
commit 09fd2c2ab6
13 changed files with 301 additions and 208 deletions

View File

@ -316,8 +316,11 @@ public class ApiAutomationService {
boolean isFirst = true;
for (ApiScenarioWithBLOBs item : apiScenarios) {
if (item.getStepTotal() == 0) {
MSException.throwException(item.getName() + "" + Translator.get("automation_exec_info"));
break;
if (apiScenarios.size() == 1) {
MSException.throwException(item.getName() + "" + Translator.get("automation_exec_info"));
break;
}
continue;
}
MsThreadGroup group = new MsThreadGroup();
group.setLabel(item.getName());

View File

@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.APIReportResult;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.automation.ApiScenarioDTO;
import io.metersphere.api.dto.automation.ApiScenarioRequest;
import io.metersphere.api.dto.automation.ReferenceDTO;
import io.metersphere.api.dto.datacount.ApiDataCountResult;
@ -18,6 +17,7 @@ import io.metersphere.api.parse.ApiImportParserFactory;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDefinitionMapper;
import io.metersphere.base.mapper.ApiTestFileMapper;
import io.metersphere.base.mapper.ProjectMapper;
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ext.ExtApiDefinitionMapper;
import io.metersphere.base.mapper.ext.ExtApiScenarioMapper;
@ -71,6 +71,8 @@ public class ApiDefinitionService {
private ExtApiScenarioMapper extApiScenarioMapper;
@Resource
private ExtTestPlanMapper extTestPlanMapper;
@Resource
private ProjectMapper projectMapper;
private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24);
@ -168,7 +170,8 @@ public class ApiDefinitionService {
example.createCriteria().andMethodEqualTo(request.getMethod()).andStatusNotEqualTo("Trash")
.andProtocolEqualTo(request.getProtocol()).andPathEqualTo(request.getPath())
.andProjectIdEqualTo(request.getProjectId()).andIdNotEqualTo(request.getId());
if (apiDefinitionMapper.countByExample(example) > 0) {
Project project = projectMapper.selectByPrimaryKey(request.getProjectId());
if (apiDefinitionMapper.countByExample(example) > 0 && !project.getRepeatable()) {
MSException.throwException(Translator.get("api_definition_url_not_repeating"));
}
} else {
@ -429,8 +432,8 @@ public class ApiDefinitionService {
public void editApiByParam(ApiBatchRequest request) {
List<String> ids = request.getIds();
if(request.isSelectAllDate()){
ids = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds());
if (request.isSelectAllDate()) {
ids = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds());
}
//name在这里只是查询参数
request.setName(null);
@ -493,15 +496,15 @@ public class ApiDefinitionService {
public void deleteByParams(ApiDefinitionBatchProcessingRequest request) {
List<String> apiIds = request.getDataIds();
if(request.isSelectAllDate()){
apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds());
if (request.isSelectAllDate()) {
apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds());
}
ApiDefinitionExample example = new ApiDefinitionExample();
example.createCriteria().andIdIn(apiIds);
apiDefinitionMapper.deleteByExample(example);
}
private List<String> getAllApiIdsByFontedSelect(List<String> filter,String name,List<String> moduleIds,String projectId,List<String>unSelectIds) {
private List<String> getAllApiIdsByFontedSelect(List<String> filter, String name, List<String> moduleIds, String projectId, List<String> unSelectIds) {
ApiDefinitionRequest request = new ApiDefinitionRequest();
request.setFilters(filter);
request.setName(name);
@ -519,8 +522,8 @@ public class ApiDefinitionService {
public void removeToGcByParams(ApiDefinitionBatchProcessingRequest request) {
List<String> apiIds = request.getDataIds();
if(request.isSelectAllDate()){
apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds());
if (request.isSelectAllDate()) {
apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds());
}
extApiDefinitionMapper.removeToGc(apiIds);
}

View File

@ -1,8 +1,9 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
import java.io.Serializable;
@Data
public class Project implements Serializable {
private String id;
@ -23,5 +24,7 @@ public class Project implements Serializable {
private String zentaoId;
private Boolean repeatable;
private static final long serialVersionUID = 1L;
}

View File

@ -713,6 +713,66 @@ public class ProjectExample {
addCriterion("zentao_id not between", value1, value2, "zentaoId");
return (Criteria) this;
}
public Criteria andRepeatableIsNull() {
addCriterion("`repeatable` is null");
return (Criteria) this;
}
public Criteria andRepeatableIsNotNull() {
addCriterion("`repeatable` is not null");
return (Criteria) this;
}
public Criteria andRepeatableEqualTo(Boolean value) {
addCriterion("`repeatable` =", value, "repeatable");
return (Criteria) this;
}
public Criteria andRepeatableNotEqualTo(Boolean value) {
addCriterion("`repeatable` <>", value, "repeatable");
return (Criteria) this;
}
public Criteria andRepeatableGreaterThan(Boolean value) {
addCriterion("`repeatable` >", value, "repeatable");
return (Criteria) this;
}
public Criteria andRepeatableGreaterThanOrEqualTo(Boolean value) {
addCriterion("`repeatable` >=", value, "repeatable");
return (Criteria) this;
}
public Criteria andRepeatableLessThan(Boolean value) {
addCriterion("`repeatable` <", value, "repeatable");
return (Criteria) this;
}
public Criteria andRepeatableLessThanOrEqualTo(Boolean value) {
addCriterion("`repeatable` <=", value, "repeatable");
return (Criteria) this;
}
public Criteria andRepeatableIn(List<Boolean> values) {
addCriterion("`repeatable` in", values, "repeatable");
return (Criteria) this;
}
public Criteria andRepeatableNotIn(List<Boolean> values) {
addCriterion("`repeatable` not in", values, "repeatable");
return (Criteria) this;
}
public Criteria andRepeatableBetween(Boolean value1, Boolean value2) {
addCriterion("`repeatable` between", value1, value2, "repeatable");
return (Criteria) this;
}
public Criteria andRepeatableNotBetween(Boolean value1, Boolean value2) {
addCriterion("`repeatable` not between", value1, value2, "repeatable");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {

View File

@ -11,6 +11,7 @@
<result column="tapd_id" jdbcType="VARCHAR" property="tapdId" />
<result column="jira_key" jdbcType="VARCHAR" property="jiraKey" />
<result column="zentao_id" jdbcType="VARCHAR" property="zentaoId" />
<result column="repeatable" jdbcType="BIT" property="repeatable" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
@ -72,7 +73,7 @@
</sql>
<sql id="Base_Column_List">
id, workspace_id, `name`, description, create_time, update_time, tapd_id, jira_key,
zentao_id
zentao_id, `repeatable`
</sql>
<select id="selectByExample" parameterType="io.metersphere.base.domain.ProjectExample" resultMap="BaseResultMap">
select
@ -107,12 +108,12 @@
<insert id="insert" parameterType="io.metersphere.base.domain.Project">
insert into project (id, workspace_id, `name`,
description, create_time, update_time,
tapd_id, jira_key, zentao_id
)
tapd_id, jira_key, zentao_id,
`repeatable`)
values (#{id,jdbcType=VARCHAR}, #{workspaceId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
#{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
#{tapdId,jdbcType=VARCHAR}, #{jiraKey,jdbcType=VARCHAR}, #{zentaoId,jdbcType=VARCHAR}
)
#{tapdId,jdbcType=VARCHAR}, #{jiraKey,jdbcType=VARCHAR}, #{zentaoId,jdbcType=VARCHAR},
#{repeatable,jdbcType=BIT})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.Project">
insert into project
@ -144,6 +145,9 @@
<if test="zentaoId != null">
zentao_id,
</if>
<if test="repeatable != null">
`repeatable`,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
@ -173,6 +177,9 @@
<if test="zentaoId != null">
#{zentaoId,jdbcType=VARCHAR},
</if>
<if test="repeatable != null">
#{repeatable,jdbcType=BIT},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.base.domain.ProjectExample" resultType="java.lang.Long">
@ -211,6 +218,9 @@
<if test="record.zentaoId != null">
zentao_id = #{record.zentaoId,jdbcType=VARCHAR},
</if>
<if test="record.repeatable != null">
`repeatable` = #{record.repeatable,jdbcType=BIT},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -226,7 +236,8 @@
update_time = #{record.updateTime,jdbcType=BIGINT},
tapd_id = #{record.tapdId,jdbcType=VARCHAR},
jira_key = #{record.jiraKey,jdbcType=VARCHAR},
zentao_id = #{record.zentaoId,jdbcType=VARCHAR}
zentao_id = #{record.zentaoId,jdbcType=VARCHAR},
`repeatable` = #{record.repeatable,jdbcType=BIT}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -258,6 +269,9 @@
<if test="zentaoId != null">
zentao_id = #{zentaoId,jdbcType=VARCHAR},
</if>
<if test="repeatable != null">
`repeatable` = #{repeatable,jdbcType=BIT},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
@ -270,7 +284,8 @@
update_time = #{updateTime,jdbcType=BIGINT},
tapd_id = #{tapdId,jdbcType=VARCHAR},
jira_key = #{jiraKey,jdbcType=VARCHAR},
zentao_id = #{zentaoId,jdbcType=VARCHAR}
zentao_id = #{zentaoId,jdbcType=VARCHAR},
`repeatable` = #{repeatable,jdbcType=BIT}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>

View File

@ -4,7 +4,7 @@
<select id="getProjectWithWorkspace" resultType="io.metersphere.dto.ProjectDTO">
select p.id, p.workspace_id, p.name, p.description, p.update_time,
p.create_time, w.id as workspaceId, w.name as workspaceName, p.tapd_id, p.jira_key, p.zentao_id
p.create_time, w.id as workspaceId, w.name as workspaceName, p.tapd_id, p.jira_key, p.zentao_id,p.repeatable
from project p
join workspace w on p.workspace_id = w.id
<where>
@ -42,11 +42,11 @@
</if>
</set>
where project.id in (select id from (select id
from project
where workspace_id in
(select workspace.id
from workspace
where organization_id = #{orgId})) as a)
from project
where workspace_id in
(select workspace.id
from workspace
where organization_id = #{orgId})) as a)
</update>
</mapper>

View File

@ -17,4 +17,6 @@ public class ProjectDTO {
private String tapdId;
private String jiraKey;
private String zentaoId;
private boolean repeatable;
}

View File

@ -0,0 +1 @@
ALTER TABLE project ADD repeatable tinyint(1) DEFAULT null;

View File

@ -64,7 +64,7 @@
<!--要生成的数据库表 -->
<table tableName="api_scenario"/>
<table tableName="project"/>
<!--<table tableName="test_plan_api_scenario"/>-->
<!--<table tableName="test_plan"/>-->
<!--<table tableName="api_scenario_report"/>-->

View File

@ -48,7 +48,7 @@
</el-card>
<el-dialog :close-on-click-modal="false" :title="title" :visible.sync="createVisible" destroy-on-close @close="handleClose">
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small">
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="140px" size="small">
<el-form-item :label="$t('commons.name')" prop="name">
<el-input v-model="form.name" autocomplete="off"></el-input>
</el-form-item>
@ -64,6 +64,9 @@
<el-form-item :label="$t('project.zentao_id')" v-if="zentao">
<el-input v-model="form.zentaoId" autocomplete="off"></el-input>
</el-form-item>
<el-form-item :label="$t('project.repeatable')" prop="repeatable">
<el-switch v-model="form.repeatable"></el-switch>
</el-form-item>
</el-form>
<template v-slot:footer>
<div class="dialog-footer">
@ -82,192 +85,192 @@
</template>
<script>
import MsCreateBox from "../CreateBox";
import {Message} from "element-ui";
import MsTablePagination from "../../common/pagination/TablePagination";
import MsTableHeader from "../../common/components/MsTableHeader";
import MsTableOperator from "../../common/components/MsTableOperator";
import MsDialogFooter from "../../common/components/MsDialogFooter";
import {_sort, getCurrentProjectID, getCurrentUser, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import MsContainer from "../../common/components/MsContainer";
import MsMainContainer from "../../common/components/MsMainContainer";
import MsDeleteConfirm from "../../common/components/MsDeleteConfirm";
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
import ApiEnvironmentConfig from "../../api/test/components/ApiEnvironmentConfig";
import TemplateComponent from "../../track/plan/view/comonents/report/TemplateComponent/TemplateComponent";
import {PROJECT_ID} from "@/common/js/constants";
import MsCreateBox from "../CreateBox";
import {Message} from "element-ui";
import MsTablePagination from "../../common/pagination/TablePagination";
import MsTableHeader from "../../common/components/MsTableHeader";
import MsTableOperator from "../../common/components/MsTableOperator";
import MsDialogFooter from "../../common/components/MsDialogFooter";
import {_sort, getCurrentProjectID, getCurrentUser, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import MsContainer from "../../common/components/MsContainer";
import MsMainContainer from "../../common/components/MsMainContainer";
import MsDeleteConfirm from "../../common/components/MsDeleteConfirm";
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
import ApiEnvironmentConfig from "../../api/test/components/ApiEnvironmentConfig";
import TemplateComponent from "../../track/plan/view/comonents/report/TemplateComponent/TemplateComponent";
import {PROJECT_ID} from "@/common/js/constants";
export default {
name: "MsProject",
components: {
TemplateComponent,
ApiEnvironmentConfig,
MsTableOperatorButton,
MsDeleteConfirm,
MsMainContainer,
MsContainer, MsTableOperator, MsCreateBox, MsTablePagination, MsTableHeader, MsDialogFooter
},
data() {
return {
createVisible: false,
result: {},
btnTips: this.$t('project.create'),
title: this.$t('project.create'),
condition: {},
items: [],
tapd: false,
jira: false,
zentao: false,
form: {},
currentPage: 1,
pageSize: 10,
total: 0,
rules: {
name: [
{required: true, message: this.$t('project.input_name'), trigger: 'blur'},
{min: 2, max: 50, message: this.$t('commons.input_limit', [2, 50]), trigger: 'blur'}
],
description: [
{max: 250, message: this.$t('commons.input_limit', [0, 250]), trigger: 'blur'}
],
},
}
},
props: {
baseUrl: {
type: String
}
},
mounted() {
if (this.$route.path.split('/')[2] === 'project' &&
this.$route.path.split('/')[3] === 'create') {
this.create();
this.$router.replace('/setting/project/all');
}
this.list();
},
activated() {
this.list();
},
computed: {
currentUser: () => {
return getCurrentUser();
}
},
destroyed() {
this.createVisible = false;
},
methods: {
create() {
let workspaceId = this.currentUser.lastWorkspaceId;
if (!workspaceId) {
this.$warning(this.$t('project.please_choose_workspace'));
return false;
export default {
name: "MsProject",
components: {
TemplateComponent,
ApiEnvironmentConfig,
MsTableOperatorButton,
MsDeleteConfirm,
MsMainContainer,
MsContainer, MsTableOperator, MsCreateBox, MsTablePagination, MsTableHeader, MsDialogFooter
},
data() {
return {
createVisible: false,
result: {},
btnTips: this.$t('project.create'),
title: this.$t('project.create'),
condition: {},
items: [],
tapd: false,
jira: false,
zentao: false,
form: {},
currentPage: 1,
pageSize: 10,
total: 0,
rules: {
name: [
{required: true, message: this.$t('project.input_name'), trigger: 'blur'},
{min: 2, max: 50, message: this.$t('commons.input_limit', [2, 50]), trigger: 'blur'}
],
description: [
{max: 250, message: this.$t('commons.input_limit', [0, 250]), trigger: 'blur'}
],
},
}
this.title = this.$t('project.create');
// listenGoBack(this.handleClose);
this.createVisible = true;
this.form = {};
},
edit(row) {
this.title = this.$t('project.edit');
this.createVisible = true;
listenGoBack(this.handleClose);
this.form = Object.assign({}, row);
this.$get("/service/integration/all/" + getCurrentUser().lastOrganizationId, response => {
let data = response.data;
let platforms = data.map(d => d.platform);
if (platforms.indexOf("Tapd") !== -1) {
this.tapd = true;
}
if (platforms.indexOf("Jira") !== -1) {
this.jira = true;
}
if (platforms.indexOf("Zentao") !== -1) {
this.zentao = true;
}
});
props: {
baseUrl: {
type: String
}
},
submit(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
let saveType = "add";
if (this.form.id) {
saveType = "update"
}
this.result = this.$post("/project/" + saveType, this.form, () => {
this.createVisible = false;
this.list();
Message.success(this.$t('commons.save_success'));
});
} else {
mounted() {
if (this.$route.path.split('/')[2] === 'project' &&
this.$route.path.split('/')[3] === 'create') {
this.create();
this.$router.replace('/setting/project/all');
}
this.list();
},
activated() {
this.list();
},
computed: {
currentUser: () => {
return getCurrentUser();
}
},
destroyed() {
this.createVisible = false;
},
methods: {
create() {
let workspaceId = this.currentUser.lastWorkspaceId;
if (!workspaceId) {
this.$warning(this.$t('project.please_choose_workspace'));
return false;
}
});
},
handleDelete(project) {
this.$refs.deleteConfirm.open(project);
},
_handleDelete(project) {
this.$confirm(this.$t('project.delete_tip'), '', {
confirmButtonText: this.$t('commons.confirm'),
cancelButtonText: this.$t('commons.cancel'),
type: 'warning'
}).then(() => {
this.$get('/project/delete/' + project.id, () => {
if (project.id === getCurrentProjectID()) {
localStorage.removeItem(PROJECT_ID);
this.$post("/user/update/current", {id: getCurrentUser().id, lastProjectId: ''});
this.title = this.$t('project.create');
// listenGoBack(this.handleClose);
this.createVisible = true;
this.form = {};
},
edit(row) {
this.title = this.$t('project.edit');
this.createVisible = true;
listenGoBack(this.handleClose);
this.form = Object.assign({}, row);
this.$get("/service/integration/all/" + getCurrentUser().lastOrganizationId, response => {
let data = response.data;
let platforms = data.map(d => d.platform);
if (platforms.indexOf("Tapd") !== -1) {
this.tapd = true;
}
if (platforms.indexOf("Jira") !== -1) {
this.jira = true;
}
if (platforms.indexOf("Zentao") !== -1) {
this.zentao = true;
}
Message.success(this.$t('commons.delete_success'));
this.list();
});
}).catch(() => {
this.$message({
type: 'info',
message: this.$t('commons.delete_cancelled')
},
submit(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
let saveType = "add";
if (this.form.id) {
saveType = "update"
}
this.result = this.$post("/project/" + saveType, this.form, () => {
this.createVisible = false;
this.list();
Message.success(this.$t('commons.save_success'));
});
} else {
return false;
}
});
});
},
handleDelete(project) {
this.$refs.deleteConfirm.open(project);
},
_handleDelete(project) {
this.$confirm(this.$t('project.delete_tip'), '', {
confirmButtonText: this.$t('commons.confirm'),
cancelButtonText: this.$t('commons.cancel'),
type: 'warning'
}).then(() => {
this.$get('/project/delete/' + project.id, () => {
if (project.id === getCurrentProjectID()) {
localStorage.removeItem(PROJECT_ID);
this.$post("/user/update/current", {id: getCurrentUser().id, lastProjectId: ''});
}
Message.success(this.$t('commons.delete_success'));
this.list();
});
}).catch(() => {
this.$message({
type: 'info',
message: this.$t('commons.delete_cancelled')
});
});
},
handleClose() {
removeGoBackListener(this.handleClose);
this.createVisible = false;
this.tapd = false;
this.jira = false;
this.zentao = false;
},
search() {
this.list();
},
list() {
let url = "/project/list/" + this.currentPage + '/' + this.pageSize;
this.result = this.$post(url, this.condition, (response) => {
let data = response.data;
this.items = data.listObject;
this.total = data.itemCount;
})
},
sort(column) {
_sort(column, this.condition);
this.list();
},
openEnvironmentConfig(project) {
this.$refs.environmentConfig.open(project.id);
},
handleEvent(event) {
if (event.keyCode === 13) {
this.submit('form')
}
},
},
handleClose() {
removeGoBackListener(this.handleClose);
this.createVisible = false;
this.tapd = false;
this.jira = false;
this.zentao = false;
created() {
document.addEventListener('keydown', this.handleEvent)
},
search() {
this.list();
},
list() {
let url = "/project/list/" + this.currentPage + '/' + this.pageSize;
this.result = this.$post(url, this.condition, (response) => {
let data = response.data;
this.items = data.listObject;
this.total = data.itemCount;
})
},
sort(column) {
_sort(column, this.condition);
this.list();
},
openEnvironmentConfig(project) {
this.$refs.environmentConfig.open(project.id);
},
handleEvent(event) {
if (event.keyCode === 13) {
this.submit('form')
}
},
},
created() {
document.addEventListener('keydown', this.handleEvent)
},
beforeDestroy() {
document.removeEventListener('keydown', this.handleEvent);
beforeDestroy() {
document.removeEventListener('keydown', this.handleEvent);
}
}
}
</script>
<style scoped>

View File

@ -308,7 +308,8 @@ export default {
zentao_id: 'Zentao Project ID',
manager: 'Manager',
no_data: 'No Data',
select: 'Select'
select: 'Select',
repeatable: 'Interface definition URL repeatable'
},
member: {
create: 'Create',

View File

@ -305,7 +305,8 @@ export default {
zentao_id: 'Zentao项目ID',
manager: '项目管理',
no_data: '无数据',
select: '选择项目'
select: '选择项目',
repeatable: '接口定义URL可重复'
},
member: {
create: '添加成员',
@ -487,7 +488,7 @@ export default {
file_exist: "该项目下已存在该jar包",
upload_limit_size: "上传文件大小不能超过 30MB!",
},
batch_menus:{
batch_menus: {
select_all_data: "选择所有数据(共{0}条)",
select_show_data: "选择可见数据(共{0}条)",
},
@ -503,9 +504,9 @@ export default {
api_case_status: "用例状态",
api_case_passing_rate: "用例通过率",
create_tip: "注: 详细的接口信息可以在编辑页面填写",
select_comp:{
no_data:"无数据",
add_data:"去添加"
select_comp: {
no_data: "无数据",
add_data: "去添加"
},
request: {
grade_info: "按等级筛选",

View File

@ -305,7 +305,8 @@ export default {
zentao_id: 'Zentao項目ID',
manager: '項目管理',
no_data: '無數據',
select: '選擇項目'
select: '選擇項目',
repeatable: '接口定义URL可重复'
},
member: {
create: '添加成員',