fix: 解决冲突

This commit is contained in:
chenjianxing 2021-05-21 12:55:17 +08:00 committed by jianxing
parent 73d6dcd9ca
commit 4e3b2166d0
28 changed files with 518 additions and 70 deletions

View File

@ -21,5 +21,7 @@ public class CustomFieldTemplate implements Serializable {
private String customData;
private Boolean isThirdPart;
private static final long serialVersionUID = 1L;
}

View File

@ -643,6 +643,66 @@ public class CustomFieldTemplateExample {
addCriterion("custom_data not between", value1, value2, "customData");
return (Criteria) this;
}
public Criteria andIsThirdPartIsNull() {
addCriterion("is_third_part is null");
return (Criteria) this;
}
public Criteria andIsThirdPartIsNotNull() {
addCriterion("is_third_part is not null");
return (Criteria) this;
}
public Criteria andIsThirdPartEqualTo(Boolean value) {
addCriterion("is_third_part =", value, "isThirdPart");
return (Criteria) this;
}
public Criteria andIsThirdPartNotEqualTo(Boolean value) {
addCriterion("is_third_part <>", value, "isThirdPart");
return (Criteria) this;
}
public Criteria andIsThirdPartGreaterThan(Boolean value) {
addCriterion("is_third_part >", value, "isThirdPart");
return (Criteria) this;
}
public Criteria andIsThirdPartGreaterThanOrEqualTo(Boolean value) {
addCriterion("is_third_part >=", value, "isThirdPart");
return (Criteria) this;
}
public Criteria andIsThirdPartLessThan(Boolean value) {
addCriterion("is_third_part <", value, "isThirdPart");
return (Criteria) this;
}
public Criteria andIsThirdPartLessThanOrEqualTo(Boolean value) {
addCriterion("is_third_part <=", value, "isThirdPart");
return (Criteria) this;
}
public Criteria andIsThirdPartIn(List<Boolean> values) {
addCriterion("is_third_part in", values, "isThirdPart");
return (Criteria) this;
}
public Criteria andIsThirdPartNotIn(List<Boolean> values) {
addCriterion("is_third_part not in", values, "isThirdPart");
return (Criteria) this;
}
public Criteria andIsThirdPartBetween(Boolean value1, Boolean value2) {
addCriterion("is_third_part between", value1, value2, "isThirdPart");
return (Criteria) this;
}
public Criteria andIsThirdPartNotBetween(Boolean value1, Boolean value2) {
addCriterion("is_third_part not between", value1, value2, "isThirdPart");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {

View File

@ -10,6 +10,7 @@
<result column="order" jdbcType="INTEGER" property="order" />
<result column="default_value" jdbcType="VARCHAR" property="defaultValue" />
<result column="custom_data" jdbcType="VARCHAR" property="customData" />
<result column="is_third_part" jdbcType="BIT" property="isThirdPart" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
@ -70,7 +71,8 @@
</where>
</sql>
<sql id="Base_Column_List">
id, field_id, template_id, scene, required, `order`, default_value, custom_data
id, field_id, template_id, scene, required, `order`, default_value, custom_data,
is_third_part
</sql>
<select id="selectByExample" parameterType="io.metersphere.base.domain.CustomFieldTemplateExample" resultMap="BaseResultMap">
select
@ -105,10 +107,12 @@
<insert id="insert" parameterType="io.metersphere.base.domain.CustomFieldTemplate">
insert into custom_field_template (id, field_id, template_id,
scene, required, `order`,
default_value, custom_data)
default_value, custom_data, is_third_part
)
values (#{id,jdbcType=VARCHAR}, #{fieldId,jdbcType=VARCHAR}, #{templateId,jdbcType=VARCHAR},
#{scene,jdbcType=VARCHAR}, #{required,jdbcType=BIT}, #{order,jdbcType=INTEGER},
#{defaultValue,jdbcType=VARCHAR}, #{customData,jdbcType=VARCHAR})
#{defaultValue,jdbcType=VARCHAR}, #{customData,jdbcType=VARCHAR}, #{isThirdPart,jdbcType=BIT}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.CustomFieldTemplate">
insert into custom_field_template
@ -137,6 +141,9 @@
<if test="customData != null">
custom_data,
</if>
<if test="isThirdPart != null">
is_third_part,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
@ -163,6 +170,9 @@
<if test="customData != null">
#{customData,jdbcType=VARCHAR},
</if>
<if test="isThirdPart != null">
#{isThirdPart,jdbcType=BIT},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.base.domain.CustomFieldTemplateExample" resultType="java.lang.Long">
@ -198,6 +208,9 @@
<if test="record.customData != null">
custom_data = #{record.customData,jdbcType=VARCHAR},
</if>
<if test="record.isThirdPart != null">
is_third_part = #{record.isThirdPart,jdbcType=BIT},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -212,7 +225,8 @@
required = #{record.required,jdbcType=BIT},
`order` = #{record.order,jdbcType=INTEGER},
default_value = #{record.defaultValue,jdbcType=VARCHAR},
custom_data = #{record.customData,jdbcType=VARCHAR}
custom_data = #{record.customData,jdbcType=VARCHAR},
is_third_part = #{record.isThirdPart,jdbcType=BIT}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -241,6 +255,9 @@
<if test="customData != null">
custom_data = #{customData,jdbcType=VARCHAR},
</if>
<if test="isThirdPart != null">
is_third_part = #{isThirdPart,jdbcType=BIT},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
@ -252,7 +269,8 @@
required = #{required,jdbcType=BIT},
`order` = #{order,jdbcType=INTEGER},
default_value = #{defaultValue,jdbcType=VARCHAR},
custom_data = #{customData,jdbcType=VARCHAR}
custom_data = #{customData,jdbcType=VARCHAR},
is_third_part = #{isThirdPart,jdbcType=BIT}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>

View File

@ -10,7 +10,7 @@
<select id="list" resultType="io.metersphere.dto.CustomFieldTemplateDao">
select
field_id, template_id, required, default_value, custom_data,
cft.id as id,
cft.id as id, is_third_part,
cf.name as name, cf.type as type, cf.remark as remark, cf.`system` as system, cf.options as options
from custom_field_template cft
inner join custom_field cf

View File

@ -12,4 +12,6 @@ public class CustomFieldDao extends CustomField {
private String defaultValue;
private String customData;
private Boolean isThirdPart;
}

View File

@ -8,4 +8,5 @@ public class CustomFieldItemDTO {
private String name;
private String value;
private String customData;
private Boolean isThirdPart;
}

View File

@ -16,4 +16,6 @@ public class CustomFieldTemplateDao extends CustomFieldTemplate {
private String options;
private Boolean system;
private Boolean isThirdPart;
}

View File

@ -168,6 +168,7 @@ public abstract class AbstractIssuePlatform implements IssuesPlatform {
issues.setPlatform(issuesRequest.getPlatform());
issues.setProjectId(issuesRequest.getProjectId());
issues.setCustomFields(issuesRequest.getCustomFields());
issues.setCreator(issuesRequest.getCreator());
issues.setCreateTime(System.currentTimeMillis());
issues.setUpdateTime(System.currentTimeMillis());
issuesMapper.insert(issues);

View File

@ -9,8 +9,10 @@ import io.metersphere.commons.constants.IssuesStatus;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.EncryptUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.dto.CustomFieldItemDTO;
import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.issue.client.JiraClient;
import io.metersphere.track.issue.domain.*;
import io.metersphere.track.request.testcase.IssuesRequest;
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
import org.apache.commons.lang3.StringUtils;
@ -40,6 +42,15 @@ public class JiraPlatform extends AbstractIssuePlatform {
super(issuesRequest);
}
public JiraConfig getConfig() {
String config = getPlatformConfig(IssuesManagePlatform.Jira.toString());
if (StringUtils.isNotBlank(config)) {
return JSONObject.parseObject(config, JiraConfig.class);
} else {
return null;
}
}
@Override
public List<IssuesDao> getIssue(IssuesRequest issuesRequest) {
List<IssuesDao> list = new ArrayList<>();
@ -51,15 +62,11 @@ public class JiraPlatform extends AbstractIssuePlatform {
} else {
issues = extIssuesMapper.getIssuesByCaseId(issuesRequest);
}
String config = getPlatformConfig(IssuesManagePlatform.Jira.toString());
JSONObject object = JSON.parseObject(config);
HttpHeaders headers = getAuthHeader(object);
String url = object.getString("url");
JiraConfig config = getConfig();
JiraClient.setConfig(config);
List<String> issuesIds = issues.stream().map(Issues::getId).collect(Collectors.toList());
issuesIds.forEach(issuesId -> {
IssuesDao dto = getJiraIssues(headers, url, issuesId);
IssuesDao dto = parseIssue(JiraClient.getIssues(issuesId));
if (StringUtils.isBlank(dto.getId())) {
// 缺陷不存在解除用例和缺陷的关联
TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
@ -78,6 +85,38 @@ public class JiraPlatform extends AbstractIssuePlatform {
return list;
}
public IssuesDao parseIssue(JiraIssue jiraIssue) {
String lastmodify = "";
String status = "";
JSONObject fields = jiraIssue.getFields();
JSONObject statusObj = (JSONObject) fields.get("status");
JSONObject assignee = (JSONObject) fields.get("assignee");
if (statusObj != null) {
JSONObject statusCategory = (JSONObject) statusObj.get("statusCategory");
status = statusCategory.getString("key");
}
String description = fields.getString("description");
Parser parser = Parser.builder().build();
Node document = parser.parse(description);
HtmlRenderer renderer = HtmlRenderer.builder().build();
description = renderer.render(document);
if (assignee != null) {
lastmodify = assignee.getString("displayName");
}
IssuesDao issues = new IssuesDao();
issues.setId(jiraIssue.getKey());
issues.setTitle(fields.getString("summary"));
issues.setCreateTime(fields.getLong("created"));
issues.setLastmodify(lastmodify);
issues.setDescription(description);
issues.setStatus(status);
issues.setPlatform(IssuesManagePlatform.Jira.toString());
return issues;
}
public HttpHeaders getAuthHeader(JSONObject object) {
if (object == null) {
MSException.throwException("tapd config is null");
@ -164,26 +203,18 @@ public class JiraPlatform extends AbstractIssuePlatform {
@Override
public void addIssue(IssuesUpdateRequest issuesRequest) {
String config = getPlatformConfig(IssuesManagePlatform.Jira.toString());
issuesRequest.setPlatform(IssuesManagePlatform.Jira.toString());
JSONObject object = JSON.parseObject(config);
if (object == null) {
JiraConfig config = getConfig();
if (config == null) {
MSException.throwException("jira config is null");
}
String account = object.getString("account");
String password = object.getString("password");
String url = object.getString("url");
String issuetype = object.getString("issuetype");
if (StringUtils.isBlank(issuetype)) {
if (StringUtils.isBlank(config.getIssuetype())) {
MSException.throwException("Jira 问题类型为空");
}
String auth = EncryptUtils.base64Encoding(account + ":" + password);
String jiraKey = getProjectId(issuesRequest.getProjectId());
if (StringUtils.isBlank(jiraKey)) {
MSException.throwException("未关联Jira 项目Key");
}
@ -198,30 +229,47 @@ public class JiraPlatform extends AbstractIssuePlatform {
String desc = Jsoup.clean(s, "", Whitelist.none(), new Document.OutputSettings().prettyPrint(false));
desc = desc.replace("&nbsp;", "");
String json = "{\n" +
" \"fields\":{\n" +
" \"project\":{\n" +
" \"key\":\"" + jiraKey + "\"\n" +
" },\n" +
" \"summary\":\"" + issuesRequest.getTitle() + "\",\n" +
" \"description\": " + JSON.toJSONString(desc) + ",\n" +
" \"issuetype\":{\n" +
" \"name\":\"" + issuetype + "\"\n" +
" }\n" +
" }\n" +
"}";
JSONObject addJiraIssueParam = new JSONObject();
JSONObject fields = new JSONObject();
JSONObject project = new JSONObject();
String result = addJiraIssue(url, auth, json);
JSONObject jsonObject = JSON.parseObject(result);
String id = jsonObject.getString("key");
fields.put("project", project);
project.put("key", jiraKey);
issuesRequest.setId(id);
JSONObject issuetype = new JSONObject();
issuetype.put("name", config.getIssuetype());
fields.put("summary", issuesRequest.getTitle());
fields.put("description", new JiraIssueDescription(desc));
fields.put("issuetype", issuetype);
addJiraIssueParam.put("fields", fields);
List<CustomFieldItemDTO> customFields = getCustomFields(issuesRequest.getCustomFields());
JiraClient.setConfig(config);
// List<JiraField> jiraFields = JiraClient.getFields();
// Map<String, Boolean> isCustomMap = jiraFields.stream().
// collect(Collectors.toMap(JiraField::getId, JiraField::isCustom));
customFields.forEach(item -> {
if (StringUtils.isNotBlank(item.getCustomData()) && item.getIsThirdPart() != null && item.getIsThirdPart()) {
// if (isCustomMap.get(item.getCustomData())) {
// fields.put(item.getCustomData(), item.getValue());
// } else {
JSONObject param = new JSONObject();
param.put("id", item.getValue());
fields.put(item.getCustomData(), param);
// }
}
});
JiraAddIssueResponse result = JiraClient.addIssue(JSONObject.toJSONString(addJiraIssueParam));
issuesRequest.setId(result.getKey());
// 用例与第三方缺陷平台中的缺陷关联
handleTestCaseIssues(issuesRequest);
// 插入缺陷表
insertIssuesWithoutContext(id, issuesRequest);
insertIssuesWithoutContext(result.getKey(), issuesRequest);
}
@Override

View File

@ -0,0 +1,68 @@
package io.metersphere.track.issue.client;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.EncryptUtils;
import io.metersphere.commons.utils.LogUtil;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.SSLContext;
import java.security.cert.X509Certificate;
import java.util.Arrays;
public abstract class BaseClient {
protected static RestTemplate restTemplate;
static {
try {
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(csf)
.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
restTemplate = new RestTemplate(requestFactory);
} catch (Exception e) {
LogUtil.error(e);
}
}
protected static HttpHeaders getBasicHttpHeaders(String userName, String passWd) {
String authKey = EncryptUtils.base64Encoding(userName + ":" + passWd);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + authKey);
return headers;
}
protected static String getResult(ResponseEntity<String> response) {
int statusCodeValue = response.getStatusCodeValue();
LogUtil.info("responseCode: " + statusCodeValue);
if(statusCodeValue >= 400){
MSException.throwException(response.getBody());
}
LogUtil.info("result: " + response.getBody());
return response.getBody();
}
protected static Object getResultForList(Class clazz, ResponseEntity<String> response) {
return Arrays.asList(JSONArray.parseArray(getResult(response), clazz).toArray());
}
protected static Object getResultForObject(Class clazz,ResponseEntity<String> response) {
return JSONObject.parseObject(getResult(response), clazz);
}
}

View File

@ -0,0 +1,70 @@
package io.metersphere.track.issue.client;
import io.metersphere.commons.exception.MSException;
import io.metersphere.track.issue.domain.JiraAddIssueResponse;
import io.metersphere.track.issue.domain.JiraConfig;
import io.metersphere.track.issue.domain.JiraField;
import io.metersphere.track.issue.domain.JiraIssue;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.*;
import org.springframework.util.MultiValueMap;
import java.util.List;
public class JiraClient extends BaseClient {
private static String ENDPOINT;
private static String PREFIX = "/rest/api/3";
private static String USER_NAME;
private static String PASSWD;
public static List<JiraField> getFields() {
String url = getBaseUrl() + "/field";
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, getAuthHttpEntity(), String.class);
return (List<JiraField>) getResultForList(JiraField.class, response);
}
public static JiraIssue getIssues(String issuesId) {
HttpEntity<MultiValueMap> requestEntity = getAuthHttpEntity();
ResponseEntity<String> responseEntity;
responseEntity = restTemplate.exchange(ENDPOINT + "/rest/api/2/issue/" + issuesId, HttpMethod.GET, requestEntity, String.class);
return (JiraIssue) getResultForObject(JiraIssue.class, responseEntity);
}
public static JiraAddIssueResponse addIssue(String body) {
HttpHeaders headers = getAuthHeader();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> entity = restTemplate.exchange(getBaseUrl() + "/issue", HttpMethod.POST, requestEntity, String.class);
return (JiraAddIssueResponse) getResultForObject(JiraAddIssueResponse.class, entity);
}
public static void setConfig(JiraConfig config) {
if (config == null) {
MSException.throwException("config is null");
}
String url = config.getUrl();
if (StringUtils.isNotBlank(url) && url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
ENDPOINT = url;
USER_NAME = config.getAccount();
PASSWD = config.getPassword();
}
private static HttpEntity<MultiValueMap> getAuthHttpEntity() {
return new HttpEntity<>(getAuthHeader());
}
private static HttpHeaders getAuthHeader() {
return getBasicHttpHeaders(USER_NAME, PASSWD);
}
private static String getBaseUrl() {
return ENDPOINT + PREFIX;
}
}

View File

@ -0,0 +1,12 @@
package io.metersphere.track.issue.domain;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class JiraAddIssueResponse {
private String id;
private String key;
private String self;
}

View File

@ -0,0 +1,14 @@
package io.metersphere.track.issue.domain;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class JiraConfig {
private String account;
private String password;
private String url;
private String issuetype;
private String storytype;
}

View File

@ -0,0 +1,28 @@
package io.metersphere.track.issue.domain;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class JiraField {
private String id;
private String key;
private String name;
private boolean custom;
// private boolean orderable;
// private boolean navigable;
// private boolean searchable;
// private List<String> clauseNames;
// private Schema schema;
//
// @Getter
// @Setter
// public class Schema {
// private String type;
// private String system;
// }
}

View File

@ -0,0 +1,15 @@
package io.metersphere.track.issue.domain;
import com.alibaba.fastjson.JSONObject;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class JiraIssue {
private String expand;
private String id;
private String self;
private String key;
private JSONObject fields;
}

View File

@ -0,0 +1,52 @@
package io.metersphere.track.issue.domain;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Data
@NoArgsConstructor
public class JiraIssueDescription {
private String type;
private int version;
private List<Content> content;
public JiraIssueDescription(String text) {
List<Content> list = new ArrayList<>();
Content content = new Content(text);
list.add(content);
this.type = "doc";
this.version = 1;
this.content = list;
}
@Data
@NoArgsConstructor
public class Content {
private String type;
private List<ContentInfo> content;
public Content(String text) {
List<ContentInfo> list = new ArrayList<>();
ContentInfo content = new ContentInfo(text);
list.add(content);
this.type = "paragraph";
this.content = list;
}
}
@Data
@NoArgsConstructor
public class ContentInfo {
private String text;
private String type;
public ContentInfo(String text) {
this.text = text;
this.type = "text";
}
}
}

View File

@ -78,6 +78,7 @@
<table tableName="test_plan"/>
<table tableName="test_case_test"/>-->
<table tableName="api_test_environment"></table>
<table tableName="custom_field_template"></table>
<!-- <table tableName="custom_field"></table>-->
<!-- <table tableName="test_case"></table>-->
<!-- <table tableName="test_case"></table>-->

View File

@ -3,9 +3,10 @@
<div>
<slot name="header">
<el-link class="add-text" :underline="false" :disabled="disable" @click="add">
<i class="el-icon-plus">添加选项</i>
<i class="el-icon-plus">{{$t('custom_field.add_option')}}</i>
</el-link>
</slot>
<ms-instructions-icon size="13" v-if="isKv" :content="$t('选项值用于对接Jira等平台提交缺陷时对应字段的属性值')"/>
</div>
<draggable :list="data" handle=".handle" class="list-group">
@ -16,17 +17,33 @@
<el-input size="mini" type="text"
class="text-item"
v-if="editIndex === idx"
@blur="handleEdit(element)"
v-model="element.value"/>
<span class="text-item" v-else>
:placeholder="$t('custom_field.field_text')"
v-if="editIndex === idx && isKv"
@blur="handleTextEdit(element)"
v-model="element.text"/>
<span class="text-item" v-else-if="isKv">
<span v-if="element.system">
{{$t(element.text)}}
({{$t(element.text)}})
</span>
<span v-else>
{{element.text}}
</span>
</span>
<el-input size="mini" type="value"
class="text-item"
:placeholder="$t('custom_field.field_value')"
v-if="editIndex === idx"
@blur="handleValueEdit(element)"
v-model="element.value"/>
<span class="text-item" v-else>
<span v-if="element.system">
{{$t(element.value)}}
</span>
<span v-else>
{{ (element.value && isKv ? '(' : '') + element.value + (element.value && isKv ? ')' : '')}}
</span>
</span>
<i class="operator-icon" v-for="(item, index) in operators"
:key="index"
:class="item.icon"
@ -41,9 +58,11 @@
<script>
import draggable from "vuedraggable";
import MsInstructionsIcon from "@/business/components/common/components/MsInstructionsIcon";
export default {
name: "MsSingleHandleDrag",
components: {
MsInstructionsIcon,
draggable
},
data() {
@ -53,6 +72,7 @@ export default {
},
props: {
disable: Boolean,
isKv: Boolean,
data: {
type: Array,
default() {
@ -99,9 +119,17 @@ export default {
this.data.push(item);
this.editIndex = this.data.length - 1;
},
handleEdit(element) {
this.editIndex = -1;
handleTextEdit(element) {
if (!this.isKv) {
element.text = element.value;
this.editIndex = -1;
}
},
handleValueEdit(element) {
this.editIndex = -1;
if (!this.isKv) {
element.text = element.value;
}
},
isSystem(element) {
if (element.system) {
@ -145,4 +173,8 @@ export default {
font-size: 13px;
font-weight: bold;
}
.instructions-icon {
margin-left: 5px;
}
</style>

View File

@ -44,6 +44,7 @@
:label="$t('custom_field.field_option')"
prop="options" :label-width="labelWidth">
<ms-single-handle-drag
:is-kv="form.scene === 'ISSUE'"
:disable="form.name === '用例等级'"
:data="form.options"/>
</el-form-item>

View File

@ -57,6 +57,16 @@
</template>
</ms-table-column>
<ms-table-column
v-if="platform !== 'metersphere'"
:label="platform + $t('custom_field.field')"
width="100"
prop="thirdPart">
<template v-slot="scope">
<el-checkbox v-model="scope.row.isThirdPart"/>
</template>
</ms-table-column>
<ms-table-column
:label="$t('commons.remark')"
prop="remark">
@ -97,6 +107,7 @@ export default {
},
},
scene: String,
platform: String,
templateContainIds: Set
},
watch: {
@ -128,6 +139,7 @@ export default {
}
item.fieldId = item.id;
item.id = null;
item.isThirdPart = false;
item.options = JSON.parse(item.options);
if (item.type === 'checkbox') {
item.defaultValue = [];

View File

@ -167,16 +167,7 @@ export default {
this.visible = true;
},
save() {
if (this.condition.selectAll) {
if (this.scene) {
// this.result = this.$post('custom/field/list/ids' + this.currentPage + '/' + this.pageSize,
// this.condition, (response) => {
// this.$emit('save', response.data);
// });
}
} else {
this.$emit('save', this.$refs.table.selectIds);
}
this.visible = false;
},
}

View File

@ -41,6 +41,7 @@
<custom-field-form-list
:table-data="relateFields"
:scene="scene"
:platform="form.platform"
:template-contain-ids="templateContainIds"
:custom-field-ids="form.customFieldIds"
ref="customFieldFormList"

View File

@ -140,7 +140,7 @@ export default {
for (let i = 0; i < this.tableData.length; i++) {
if (this.tableData[i]) {
if (this.tableData[i].platform !== 'Local') {
this.$post("issues/get/platform/issue", this.tableData[i]).then(response => {
this.result = this.$post("issues/get/platform/issue", this.tableData[i]).then(response => {
let issues = response.data.data;
if (issues) {
this.$set(this.tableData[i], "title", issues.title ? issues.title : "--");

View File

@ -102,11 +102,13 @@ textarea {
/* 表格拖拽表头调整宽度 --> */
/* <-- 表格 input 编辑效果 */
.table-edit-input .el-textarea__inner {
.table-edit-input .el-textarea__inner,
.table-edit-input .el-input__inner {
border-style: hidden;
}
.table-edit-input.is-disabled .el-textarea__inner {
.table-edit-input.is-disabled .el-textarea__inner,
.table-edit-input.is-disabled .el-input__inner {
background-color: white;
color: #606266;
}
@ -116,7 +118,8 @@ textarea {
border-radius: 5px;
}
.table-edit-input .el-textarea__inner:focus {
.table-edit-input .el-textarea__inner:focus,
.table-edit-input .el-input__inner:focus {
border: 1px solid #409EFF;
}

View File

@ -93,6 +93,7 @@ export function buildCustomFields(data, param, template) {
hasField = true;
customFields[index].name = item.name;
customFields[index].value = item.defaultValue;
customFields[index].isThirdPart = item.isThirdPart;
break;
}
}
@ -101,7 +102,8 @@ export function buildCustomFields(data, param, template) {
id: item.id,
name: item.name,
value: item.defaultValue,
customData: item.customData
customData: item.customData,
isThirdPart: item.isThirdPart
};
customFields.push(customField);
}

View File

@ -279,6 +279,7 @@ export default {
}
},
custom_field: {
add_option: 'Add Option',
case_status: 'Case Status',
case_maintainer: 'Maintainer',
case_priority: 'Case Priority',
@ -292,9 +293,12 @@ export default {
scene: 'Use Scene',
attribute_type: 'Attribute Type',
field_name: 'Field Name',
field: 'Field',
field_remark: 'Field Remark',
field_type: 'Field Type',
field_option: 'Options',
field_text: 'Field Text',
field_value: 'Field Value',
add_field: 'Add Field',
api_field_name: 'API Field Name',
template_setting: 'Template Setting',
@ -386,7 +390,7 @@ export default {
use_tip_tapd: 'Basic Auth account information is queried in "Company Management-Security and Integration-Open Platform"',
use_tip_jira: 'Jira software server authentication information is account password, Jira software cloud authentication information is account + token (account settings-security-create API token)',
use_tip_zentao: 'The account password is a Zentao account with corresponding permissions, and the account needs to have super model calling interface permissions',
use_tip_two: 'After saving the Basic Auth account information, you need to manually associate the ID/key in the MeterSphere project',
use_tip_two: 'After saving the Basic Auth account information, you need to manually associate the ID/key and issue template in the MeterSphere project',
link_the_project_now: 'Link the project now',
cancel_edit: 'Cancel edit',
cancel_integration: 'Cancel integration',

View File

@ -280,6 +280,7 @@ export default {
}
},
custom_field: {
add_option: '添加选项',
case_status: '用例状态',
case_maintainer: '责任人',
case_priority: '用例等级',
@ -293,9 +294,12 @@ export default {
scene: '使用场景',
attribute_type: '属性类型',
field_name: '字段名',
field: '字段',
field_remark: '字段备注',
field_type: '字段类型',
field_option: '选项值',
field_text: '选项内容',
field_value: '选项值',
add_field: '添加字段',
api_field_name: 'API字段名',
template_setting: '模板设置',
@ -384,7 +388,7 @@ export default {
use_tip_tapd: 'Tapd Basic Auth 账号信息在"公司管理-安全与集成-开放平台"中查询',
use_tip_jira: 'Jira software server 认证信息为 账号密码Jira software cloud 认证信息为 账号+令牌(账户设置-安全-创建API令牌)',
use_tip_zentao: '账号密码为具有相应权限的Zentao账号账号需要具有 超级model调用接口权限',
use_tip_two: '保存 Basic Auth 账号信息后,需要在 MeterSphere 项目中手动关联 ID/key',
use_tip_two: '保存 Basic Auth 账号信息后,需要在 MeterSphere 项目中手动关联 ID/key 和缺陷模板',
link_the_project_now: '马上关联项目',
cancel_edit: '取消编辑',
cancel_integration: '取消集成',

View File

@ -280,6 +280,7 @@ export default {
}
},
custom_field: {
add_option: '添加選項',
case_status: '用例狀態',
case_maintainer: '責任人',
case_priority: '用例等級',
@ -293,9 +294,12 @@ export default {
scene: '使用場景',
attribute_type: '屬性類型',
field_name: '字段名',
field: '字段名',
field_remark: '字段備註',
field_type: '字段類型',
field_option: '選項值',
field_text: '選項內容',
field_value: '選項值',
add_field: '添加字段',
api_field_name: 'API字段名',
template_setting: '模板設置',
@ -384,7 +388,7 @@ export default {
use_tip_tapd: 'Tapd Basic Auth 賬號信息在"公司管理-安全與集成-開放平臺"中查詢',
use_tip_jira: 'Jira software server 認證信息為 賬號密碼Jira software cloud 認證信息為 賬號+令牌(賬戶設置-安全-創建API令牌)',
use_tip_zentao: '賬號密碼為具有相應權限的Zentao賬號賬號需要具有 超級model調用接口權限',
use_tip_two: '保存 Basic Auth 賬號信息後,需要在 MeterSphere 項目中手動關聯 ID/key',
use_tip_two: '保存 Basic Auth 賬號信息後,需要在 MeterSphere 項目中手動關聯 ID/key 和缺陷模板',
link_the_project_now: '馬上關聯項目',
cancel_edit: '取消編輯',
cancel_integration: '取消集成',