feat: 接口定义保存tag

This commit is contained in:
Captain.B 2021-01-07 14:04:21 +08:00
parent edf8eaed08
commit c609ce254f
13 changed files with 423 additions and 175 deletions

View File

@ -6,6 +6,7 @@ import io.metersphere.base.domain.Schedule;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Setter
@ -47,4 +48,6 @@ public class SaveApiDefinitionRequest {
private String triggerMode;
private List<String> bodyUploadIds;
private List<String> tags = new ArrayList<>();
}

View File

@ -82,10 +82,10 @@ public class ApiDefinitionService {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
//判断是否查询本周数据
if(request.isSelectThisWeedData()){
if (request.isSelectThisWeedData()) {
Map<String, Date> weekFirstTimeAndLastTime = DateUtils.getWeedFirstTimeAndLastTime(new Date());
Date weekFirstTime = weekFirstTimeAndLastTime.get("firstTime");
if(weekFirstTime!=null){
if (weekFirstTime != null) {
request.setCreateTime(weekFirstTime.getTime());
}
}
@ -228,6 +228,7 @@ public class ApiDefinitionService {
test.setResponse(JSONObject.toJSONString(request.getResponse()));
test.setEnvironmentId(request.getEnvironmentId());
test.setUserId(request.getUserId());
test.setTags(JSON.toJSONString(new HashSet<>(request.getTags())));
apiDefinitionMapper.updateByPrimaryKeySelective(test);
return test;
@ -258,6 +259,7 @@ public class ApiDefinitionService {
test.setUserId(request.getUserId());
}
test.setDescription(request.getDescription());
test.setTags(JSON.toJSONString(new HashSet<>(request.getTags())));
apiDefinitionMapper.insert(test);
return test;
}

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 ApiDefinition implements Serializable {
private String id;
@ -35,5 +36,7 @@ public class ApiDefinition implements Serializable {
private Integer num;
private String tags;
private static final long serialVersionUID = 1L;
}

View File

@ -1123,6 +1123,76 @@ public class ApiDefinitionExample {
addCriterion("num not between", value1, value2, "num");
return (Criteria) this;
}
public Criteria andTagsIsNull() {
addCriterion("tags is null");
return (Criteria) this;
}
public Criteria andTagsIsNotNull() {
addCriterion("tags is not null");
return (Criteria) this;
}
public Criteria andTagsEqualTo(String value) {
addCriterion("tags =", value, "tags");
return (Criteria) this;
}
public Criteria andTagsNotEqualTo(String value) {
addCriterion("tags <>", value, "tags");
return (Criteria) this;
}
public Criteria andTagsGreaterThan(String value) {
addCriterion("tags >", value, "tags");
return (Criteria) this;
}
public Criteria andTagsGreaterThanOrEqualTo(String value) {
addCriterion("tags >=", value, "tags");
return (Criteria) this;
}
public Criteria andTagsLessThan(String value) {
addCriterion("tags <", value, "tags");
return (Criteria) this;
}
public Criteria andTagsLessThanOrEqualTo(String value) {
addCriterion("tags <=", value, "tags");
return (Criteria) this;
}
public Criteria andTagsLike(String value) {
addCriterion("tags like", value, "tags");
return (Criteria) this;
}
public Criteria andTagsNotLike(String value) {
addCriterion("tags not like", value, "tags");
return (Criteria) this;
}
public Criteria andTagsIn(List<String> values) {
addCriterion("tags in", values, "tags");
return (Criteria) this;
}
public Criteria andTagsNotIn(List<String> values) {
addCriterion("tags not in", values, "tags");
return (Criteria) this;
}
public Criteria andTagsBetween(String value1, String value2) {
addCriterion("tags between", value1, value2, "tags");
return (Criteria) this;
}
public Criteria andTagsNotBetween(String value1, String value2) {
addCriterion("tags not between", value1, value2, "tags");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {

View File

@ -17,6 +17,7 @@
<result column="protocol" jdbcType="VARCHAR" property="protocol" />
<result column="path" jdbcType="VARCHAR" property="path" />
<result column="num" jdbcType="INTEGER" property="num" />
<result column="tags" jdbcType="VARCHAR" property="tags" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiDefinitionWithBLOBs">
<result column="description" jdbcType="LONGVARCHAR" property="description" />
@ -83,7 +84,7 @@
</sql>
<sql id="Base_Column_List">
id, project_id, `name`, `method`, module_path, environment_id, schedule, `status`,
module_id, user_id, create_time, update_time, protocol, `path`, num
module_id, user_id, create_time, update_time, protocol, `path`, num, tags
</sql>
<sql id="Blob_Column_List">
description, request, response
@ -142,15 +143,15 @@
schedule, `status`, module_id,
user_id, create_time, update_time,
protocol, `path`, num,
description, request, response
)
tags, description, request,
response)
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
#{method,jdbcType=VARCHAR}, #{modulePath,jdbcType=VARCHAR}, #{environmentId,jdbcType=VARCHAR},
#{schedule,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{moduleId,jdbcType=VARCHAR},
#{userId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
#{protocol,jdbcType=VARCHAR}, #{path,jdbcType=VARCHAR}, #{num,jdbcType=INTEGER},
#{description,jdbcType=LONGVARCHAR}, #{request,jdbcType=LONGVARCHAR}, #{response,jdbcType=LONGVARCHAR}
)
#{tags,jdbcType=VARCHAR}, #{description,jdbcType=LONGVARCHAR}, #{request,jdbcType=LONGVARCHAR},
#{response,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiDefinitionWithBLOBs">
insert into api_definition
@ -200,6 +201,9 @@
<if test="num != null">
num,
</if>
<if test="tags != null">
tags,
</if>
<if test="description != null">
description,
</if>
@ -256,6 +260,9 @@
<if test="num != null">
#{num,jdbcType=INTEGER},
</if>
<if test="tags != null">
#{tags,jdbcType=VARCHAR},
</if>
<if test="description != null">
#{description,jdbcType=LONGVARCHAR},
</if>
@ -321,6 +328,9 @@
<if test="record.num != null">
num = #{record.num,jdbcType=INTEGER},
</if>
<if test="record.tags != null">
tags = #{record.tags,jdbcType=VARCHAR},
</if>
<if test="record.description != null">
description = #{record.description,jdbcType=LONGVARCHAR},
</if>
@ -352,6 +362,7 @@
protocol = #{record.protocol,jdbcType=VARCHAR},
`path` = #{record.path,jdbcType=VARCHAR},
num = #{record.num,jdbcType=INTEGER},
tags = #{record.tags,jdbcType=VARCHAR},
description = #{record.description,jdbcType=LONGVARCHAR},
request = #{record.request,jdbcType=LONGVARCHAR},
response = #{record.response,jdbcType=LONGVARCHAR}
@ -375,7 +386,8 @@
update_time = #{record.updateTime,jdbcType=BIGINT},
protocol = #{record.protocol,jdbcType=VARCHAR},
`path` = #{record.path,jdbcType=VARCHAR},
num = #{record.num,jdbcType=INTEGER}
num = #{record.num,jdbcType=INTEGER},
tags = #{record.tags,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -425,6 +437,9 @@
<if test="num != null">
num = #{num,jdbcType=INTEGER},
</if>
<if test="tags != null">
tags = #{tags,jdbcType=VARCHAR},
</if>
<if test="description != null">
description = #{description,jdbcType=LONGVARCHAR},
</if>
@ -453,6 +468,7 @@
protocol = #{protocol,jdbcType=VARCHAR},
`path` = #{path,jdbcType=VARCHAR},
num = #{num,jdbcType=INTEGER},
tags = #{tags,jdbcType=VARCHAR},
description = #{description,jdbcType=LONGVARCHAR},
request = #{request,jdbcType=LONGVARCHAR},
response = #{response,jdbcType=LONGVARCHAR}
@ -473,7 +489,8 @@
update_time = #{updateTime,jdbcType=BIGINT},
protocol = #{protocol,jdbcType=VARCHAR},
`path` = #{path,jdbcType=VARCHAR},
num = #{num,jdbcType=INTEGER}
num = #{num,jdbcType=INTEGER},
tags = #{tags,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>

View File

@ -194,7 +194,7 @@
</sql>
<select id="list" resultType="io.metersphere.api.dto.definition.ApiDefinitionResult">
select api_definition.id, api_definition.project_id, api_definition.num,
select api_definition.id, api_definition.project_id, api_definition.num, api_definition.tags,
api_definition.name,api_definition.protocol,api_definition.path,api_definition.module_id,api_definition.module_path,api_definition.method,
api_definition.description,api_definition.request,api_definition.response,api_definition.environment_id,
api_definition.status, api_definition.user_id, api_definition.create_time, api_definition.update_time, project.name as

View File

@ -0,0 +1,8 @@
ALTER TABLE api_definition
ADD tag VARCHAR(1000) NULL;
ALTER TABLE api_test_case
ADD tag VARCHAR(1000) NULL;
ALTER TABLE test_case
ADD tag VARCHAR(1000) NULL;

View File

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

View File

@ -52,7 +52,32 @@
</el-row>
<el-row>
<el-col>
<el-col :span="8">
<el-form-item :label="$t('commons.tag')" prop="tag">
<el-tag
:key="tag"
v-for="tag in basicForm.tags"
closable
size="mini"
:disable-transitions="false"
@close="handleClose(tag)">
{{ tag }}
</el-tag>
<el-input
class="input-new-tag"
v-if="inputVisible"
v-model="inputValue"
ref="saveTagInput"
size="mini"
@keyup.enter.native="handleInputConfirm"
@blur="handleInputConfirm"
>
</el-input>
<el-button v-else class="button-new-tag" size="mini" @click="showInput">+</el-button>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item :label="$t('commons.description')" prop="description">
<el-input class="ms-http-textarea"
v-model="basicForm.description"
@ -67,10 +92,10 @@
</template>
<script>
import {API_STATUS} from "../../model/JsonData";
import {WORKSPACE_ID} from '../../../../../../common/js/constants';
import {API_STATUS} from "../../model/JsonData";
import {WORKSPACE_ID} from '../../../../../../common/js/constants';
export default {
export default {
name: "MsBasisApi",
components: {},
props: {
@ -83,6 +108,11 @@
},
created() {
this.getMaintainerOptions();
if (!this.basisData.tags) {
this.basisData.tags = [];
} else {
this.basisData.tags = JSON.parse(this.basisData.tags);
}
this.basicForm = this.basisData;
},
data() {
@ -103,7 +133,8 @@
},
value: API_STATUS[0].id,
options: API_STATUS,
inputVisible: false,
inputValue: ''
}
},
methods: {
@ -129,9 +160,45 @@
createModules(){
this.$emit("createRootModelInTree");
},
handleClose(tag) {
this.basicForm.tags.splice(this.basicForm.tags.indexOf(tag), 1);
},
showInput() {
this.inputVisible = true;
this.$nextTick(_ => {
this.$refs.saveTagInput.$refs.input.focus();
});
},
handleInputConfirm() {
let inputValue = this.inputValue;
if (inputValue) {
this.basicForm.tags.push(inputValue);
}
this.inputVisible = false;
this.inputValue = '';
}
}
}
</script>
<style scoped>
.el-tag + .el-tag {
margin-left: 10px;
}
.button-new-tag {
margin-left: 10px;
height: 20px;
/*line-height: 30px;*/
padding-top: 0;
padding-bottom: 0;
}
.input-new-tag {
width: 90px;
margin-left: 10px;
vertical-align: bottom;
}
</style>

View File

@ -6,11 +6,11 @@
<el-form :model="httpForm" :rules="rule" ref="httpForm" :inline="true" label-position="right">
<!-- 操作按钮 -->
<div style="float: right;margin-right: 20px">
<el-button type="primary" size="small" @click="saveApi">{{$t('commons.save')}}</el-button>
<el-button type="primary" size="small" @click="runTest">{{$t('commons.test')}}</el-button>
<el-button type="primary" size="small" @click="saveApi">{{ $t('commons.save') }}</el-button>
<el-button type="primary" size="small" @click="runTest">{{ $t('commons.test') }}</el-button>
</div>
<br/>
<p class="tip">{{$t('test_track.plan_view.base_info')}} </p>
<p class="tip">{{ $t('test_track.plan_view.base_info') }} </p>
<!-- 基础信息 -->
<div class="base-info">
@ -42,9 +42,9 @@
<div v-else>
<el-option :key="0" :value="''">
<div style="margin-left: 40px">
<span style="font-size: 14px;color: #606266;font-weight: 48.93">{{$t('api_test.definition.select_comp.no_data')}},
<span style="font-size: 14px;color: #606266;font-weight: 48.93">{{ $t('api_test.definition.select_comp.no_data') }},
</span>
<el-link type="primary" @click="createModules">{{$t('api_test.definition.select_comp.add_data')}}</el-link>
<el-link type="primary" @click="createModules">{{ $t('api_test.definition.select_comp.add_data') }}</el-link>
</div>
</el-option>
</div>
@ -75,186 +75,261 @@
</el-row>
<el-row>
<el-form-item :label="$t('commons.description')" prop="description">
<el-input class="ms-http-textarea"
v-model="httpForm.description"
type="textarea"
:autosize="{ minRows: 2, maxRows: 10}"
:rows="2" size="small"/>
</el-form-item>
<el-col :span="8">
<el-form-item :label="$t('commons.tag')" prop="tag">
<el-tag
:key="tag"
v-for="tag in httpForm.tags"
closable
size="mini"
:disable-transitions="false"
@close="handleClose(tag)">
{{ tag }}
</el-tag>
<el-input
class="input-new-tag"
v-if="inputVisible"
v-model="inputValue"
ref="saveTagInput"
size="mini"
@keyup.enter.native="handleInputConfirm"
@blur="handleInputConfirm"
>
</el-input>
<el-button v-else class="button-new-tag" size="mini" @click="showInput">+</el-button>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item :label="$t('commons.description')" prop="description">
<el-input class="ms-http-textarea"
v-model="httpForm.description"
type="textarea"
:autosize="{ minRows: 2, maxRows: 10}"
:rows="2" size="small"/>
</el-form-item>
</el-col>
</el-row>
</div>
<!-- 请求参数 -->
<div>
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<ms-api-request-form :showScript="false" :request="request" :headers="request.headers" :isShowEnable="isShowEnable"/>
</div>
</el-form>
<!-- 响应内容-->
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
<p class="tip">{{ $t('api_test.definition.request.res_param') }} </p>
<ms-response-text :response="response"></ms-response-text>
</el-card>
</div>
</template>
<script>
import MsApiRequestForm from "../request/http/ApiRequestForm";
import MsResponseText from "../response/ResponseText";
import {WORKSPACE_ID} from '../../../../../../common/js/constants';
import {REQ_METHOD, API_STATUS} from "../../model/JsonData";
import MsJsr233Processor from "../processor/Jsr233Processor";
import {KeyValue} from "../../model/ApiTestModel";
import MsApiRequestForm from "../request/http/ApiRequestForm";
import MsResponseText from "../response/ResponseText";
import {WORKSPACE_ID} from '../../../../../../common/js/constants';
import {API_STATUS, REQ_METHOD} from "../../model/JsonData";
import MsJsr233Processor from "../processor/Jsr233Processor";
import {KeyValue} from "../../model/ApiTestModel";
export default {
name: "MsAddCompleteHttpApi",
components: {MsResponseText, MsApiRequestForm, MsJsr233Processor},
data() {
let validateURL = (rule, value, callback) => {
if (!this.httpForm.path.startsWith("/") || this.httpForm.path.match(/\s/) != null) {
callback(this.$t('api_test.definition.request.path_valid_info'));
}
callback();
};
return {
rule: {
name: [
{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
{max: 50, message: this.$t('test_track.length_less_than') + '50', trigger: 'blur'}
],
path: [{required: true, message: this.$t('api_test.definition.request.path_info'), trigger: 'blur'}, {validator: validateURL, trigger: 'blur'}],
userId: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
moduleId: [{required: true, message: this.$t('test_track.case.input_module'), trigger: 'change'}],
status: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}],
},
httpForm: {environmentId: ""},
isShowEnable: false,
maintainerOptions: [],
currentModule: {},
reqOptions: REQ_METHOD,
options: API_STATUS,
export default {
name: "MsAddCompleteHttpApi",
components: {MsResponseText, MsApiRequestForm, MsJsr233Processor},
data() {
let validateURL = (rule, value, callback) => {
if (!this.httpForm.path.startsWith("/") || this.httpForm.path.match(/\s/) != null) {
callback(this.$t('api_test.definition.request.path_valid_info'));
}
},
props: {moduleOptions: {}, request: {}, response: {}, basisData: {}},
methods: {
runTest() {
this.$refs['httpForm'].validate((valid) => {
if (valid) {
this.setParameter();
this.$emit('runTest', this.httpForm);
} else {
return false;
}
})
callback();
};
return {
rule: {
name: [
{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
{max: 50, message: this.$t('test_track.length_less_than') + '50', trigger: 'blur'}
],
path: [{required: true, message: this.$t('api_test.definition.request.path_info'), trigger: 'blur'}, {
validator: validateURL,
trigger: 'blur'
}],
userId: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
moduleId: [{required: true, message: this.$t('test_track.case.input_module'), trigger: 'change'}],
status: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}],
},
getMaintainerOptions() {
let workspaceId = localStorage.getItem(WORKSPACE_ID);
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
this.maintainerOptions = response.data;
});
},
setParameter() {
this.httpForm.modulePath = this.getPath(this.httpForm.moduleId);
this.request.path = this.httpForm.path;
this.request.method = this.httpForm.method;
this.httpForm.request.useEnvironment = undefined;
},
saveApi() {
this.$refs['httpForm'].validate((valid) => {
if (valid) {
this.setParameter();
this.$emit('saveApi', this.httpForm);
}
else {
return false;
}
})
},
createModules() {
this.$emit("createRootModelInTree");
},
getPath(id) {
if (id === null) {
return null;
}
let path = this.moduleOptions.filter(function (item) {
return item.id === id ? item.path : "";
});
return path[0].path;
},
urlChange() {
if (!this.httpForm.path || this.httpForm.path.indexOf('?') === -1) return;
let url = this.getURL(this.addProtocol(this.httpForm.path));
if (url) {
this.httpForm.path = decodeURIComponent("/" + url.hostname + url.pathname);
}
},
addProtocol(url) {
if (url) {
if (!url.toLowerCase().startsWith("https") && !url.toLowerCase().startsWith("http")) {
return "https://" + url;
}
}
return url;
},
getURL(urlStr) {
try {
let url = new URL(urlStr);
url.searchParams.forEach((value, key) => {
if (key && value) {
this.request.arguments.splice(0, 0, new KeyValue({name: key, required: false, value: value}));
}
});
return url;
} catch (e) {
this.$error(this.$t('api_test.request.url_invalid'), 2000);
}
},
},
created() {
this.getMaintainerOptions();
if (!this.basisData.environmentId) {
this.basisData.environmentId = "";
}
this.httpForm = JSON.parse(JSON.stringify(this.basisData));
httpForm: {environmentId: "", tags: []},
isShowEnable: false,
maintainerOptions: [],
currentModule: {},
reqOptions: REQ_METHOD,
options: API_STATUS,
inputVisible: false,
inputValue: ''
}
},
props: {moduleOptions: {}, request: {}, response: {}, basisData: {}},
methods: {
runTest() {
this.$refs['httpForm'].validate((valid) => {
if (valid) {
this.setParameter();
this.$emit('runTest', this.httpForm);
} else {
return false;
}
})
},
getMaintainerOptions() {
let workspaceId = localStorage.getItem(WORKSPACE_ID);
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
this.maintainerOptions = response.data;
});
},
setParameter() {
this.httpForm.modulePath = this.getPath(this.httpForm.moduleId);
this.request.path = this.httpForm.path;
this.request.method = this.httpForm.method;
this.httpForm.request.useEnvironment = undefined;
},
saveApi() {
this.$refs['httpForm'].validate((valid) => {
if (valid) {
this.setParameter();
this.$emit('saveApi', this.httpForm);
} else {
return false;
}
})
},
createModules() {
this.$emit("createRootModelInTree");
},
getPath(id) {
if (id === null) {
return null;
}
let path = this.moduleOptions.filter(function (item) {
return item.id === id ? item.path : "";
});
return path[0].path;
},
urlChange() {
if (!this.httpForm.path || this.httpForm.path.indexOf('?') === -1) return;
let url = this.getURL(this.addProtocol(this.httpForm.path));
if (url) {
this.httpForm.path = decodeURIComponent("/" + url.hostname + url.pathname);
}
},
addProtocol(url) {
if (url) {
if (!url.toLowerCase().startsWith("https") && !url.toLowerCase().startsWith("http")) {
return "https://" + url;
}
}
return url;
},
getURL(urlStr) {
try {
let url = new URL(urlStr);
url.searchParams.forEach((value, key) => {
if (key && value) {
this.request.arguments.splice(0, 0, new KeyValue({name: key, required: false, value: value}));
}
});
return url;
} catch (e) {
this.$error(this.$t('api_test.request.url_invalid'), 2000);
}
},
handleClose(tag) {
this.httpForm.tags.splice(this.httpForm.tags.indexOf(tag), 1);
},
showInput() {
this.inputVisible = true;
this.$nextTick(_ => {
this.$refs.saveTagInput.$refs.input.focus();
});
},
handleInputConfirm() {
let inputValue = this.inputValue;
if (inputValue) {
this.httpForm.tags.push(inputValue);
}
this.inputVisible = false;
this.inputValue = '';
}
},
created() {
this.getMaintainerOptions();
if (!this.basisData.environmentId) {
this.basisData.environmentId = "";
}
if (!this.basisData.tags) {
this.basisData.tags = [];
} else {
this.basisData.tags = JSON.parse(this.basisData.tags);
}
this.httpForm = JSON.parse(JSON.stringify(this.basisData));
}
}
</script>
<style scoped>
.base-info .el-form-item {
width: 100%;
}
.base-info .el-form-item {
width: 100%;
}
.base-info .el-form-item >>> .el-form-item__content {
width: 80%;
}
.base-info .el-form-item >>> .el-form-item__content {
width: 80%;
}
.base-info .ms-http-select {
width: 100%;
}
.base-info .ms-http-select {
width: 100%;
}
.tip {
padding: 3px 5px;
font-size: 16px;
border-radius: 4px;
border-left: 4px solid #783887;
margin: 20px 0;
}
.tip {
padding: 3px 5px;
font-size: 16px;
border-radius: 4px;
border-left: 4px solid #783887;
margin: 20px 0;
}
.ms-http-textarea {
width: 400px;
}
.ms-http-textarea {
width: 400px;
}
.ms-left-cell {
margin-top: 100px;
}
.ms-left-cell {
margin-top: 100px;
}
.ms-left-buttion {
margin: 6px 0px 8px 30px;
}
.ms-left-buttion {
margin: 6px 0px 8px 30px;
}
.el-tag + .el-tag {
margin-left: 10px;
}
.button-new-tag {
margin-left: 10px;
height: 20px;
/*line-height: 30px;*/
padding-top: 0;
padding-bottom: 0;
}
.input-new-tag {
width: 90px;
margin-left: 10px;
vertical-align: bottom;
}
</style>

View File

@ -174,7 +174,8 @@ export default {
case: "all",
review: "all"
},
image: 'Image'
image: 'Image',
tag: 'Tag'
},
license: {
title: 'Authorization management',

View File

@ -174,7 +174,8 @@ export default {
case: "全部用例",
review: "全部评审"
},
image: '镜像'
image: '镜像',
tag: '标签'
},
license: {
title: '授权管理',

View File

@ -174,7 +174,8 @@ export default {
case: "全部用例",
review: "全部評審"
},
image: '鏡像'
image: '鏡像',
tag: '標簽'
},
license: {
title: '授權管理',