diff --git a/backend/src/main/java/io/metersphere/base/domain/TestCaseIssues.java b/backend/src/main/java/io/metersphere/base/domain/TestCaseIssues.java new file mode 100644 index 0000000000..cff8104fd7 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/domain/TestCaseIssues.java @@ -0,0 +1,15 @@ +package io.metersphere.base.domain; + +import java.io.Serializable; +import lombok.Data; + +@Data +public class TestCaseIssues implements Serializable { + private String id; + + private String testCaseId; + + private String issuesId; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/TestCaseIssuesExample.java b/backend/src/main/java/io/metersphere/base/domain/TestCaseIssuesExample.java new file mode 100644 index 0000000000..02920aa81a --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/domain/TestCaseIssuesExample.java @@ -0,0 +1,410 @@ +package io.metersphere.base.domain; + +import java.util.ArrayList; +import java.util.List; + +public class TestCaseIssuesExample { + protected String orderByClause; + + protected boolean distinct; + + protected List oredCriteria; + + public TestCaseIssuesExample() { + oredCriteria = new ArrayList(); + } + + public void setOrderByClause(String orderByClause) { + this.orderByClause = orderByClause; + } + + public String getOrderByClause() { + return orderByClause; + } + + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + public boolean isDistinct() { + return distinct; + } + + public List getOredCriteria() { + return oredCriteria; + } + + public void or(Criteria criteria) { + oredCriteria.add(criteria); + } + + public Criteria or() { + Criteria criteria = createCriteriaInternal(); + oredCriteria.add(criteria); + return criteria; + } + + public Criteria createCriteria() { + Criteria criteria = createCriteriaInternal(); + if (oredCriteria.size() == 0) { + oredCriteria.add(criteria); + } + return criteria; + } + + protected Criteria createCriteriaInternal() { + Criteria criteria = new Criteria(); + return criteria; + } + + public void clear() { + oredCriteria.clear(); + orderByClause = null; + distinct = false; + } + + protected abstract static class GeneratedCriteria { + protected List criteria; + + protected GeneratedCriteria() { + super(); + criteria = new ArrayList(); + } + + public boolean isValid() { + return criteria.size() > 0; + } + + public List getAllCriteria() { + return criteria; + } + + public List getCriteria() { + return criteria; + } + + protected void addCriterion(String condition) { + if (condition == null) { + throw new RuntimeException("Value for condition cannot be null"); + } + criteria.add(new Criterion(condition)); + } + + protected void addCriterion(String condition, Object value, String property) { + if (value == null) { + throw new RuntimeException("Value for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value)); + } + + protected void addCriterion(String condition, Object value1, Object value2, String property) { + if (value1 == null || value2 == null) { + throw new RuntimeException("Between values for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value1, value2)); + } + + public Criteria andIdIsNull() { + addCriterion("id is null"); + return (Criteria) this; + } + + public Criteria andIdIsNotNull() { + addCriterion("id is not null"); + return (Criteria) this; + } + + public Criteria andIdEqualTo(String value) { + addCriterion("id =", value, "id"); + return (Criteria) this; + } + + public Criteria andIdNotEqualTo(String value) { + addCriterion("id <>", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThan(String value) { + addCriterion("id >", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThanOrEqualTo(String value) { + addCriterion("id >=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThan(String value) { + addCriterion("id <", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThanOrEqualTo(String value) { + addCriterion("id <=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLike(String value) { + addCriterion("id like", value, "id"); + return (Criteria) this; + } + + public Criteria andIdNotLike(String value) { + addCriterion("id not like", value, "id"); + return (Criteria) this; + } + + public Criteria andIdIn(List values) { + addCriterion("id in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdNotIn(List values) { + addCriterion("id not in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdBetween(String value1, String value2) { + addCriterion("id between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andIdNotBetween(String value1, String value2) { + addCriterion("id not between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andTestCaseIdIsNull() { + addCriterion("test_case_id is null"); + return (Criteria) this; + } + + public Criteria andTestCaseIdIsNotNull() { + addCriterion("test_case_id is not null"); + return (Criteria) this; + } + + public Criteria andTestCaseIdEqualTo(String value) { + addCriterion("test_case_id =", value, "testCaseId"); + return (Criteria) this; + } + + public Criteria andTestCaseIdNotEqualTo(String value) { + addCriterion("test_case_id <>", value, "testCaseId"); + return (Criteria) this; + } + + public Criteria andTestCaseIdGreaterThan(String value) { + addCriterion("test_case_id >", value, "testCaseId"); + return (Criteria) this; + } + + public Criteria andTestCaseIdGreaterThanOrEqualTo(String value) { + addCriterion("test_case_id >=", value, "testCaseId"); + return (Criteria) this; + } + + public Criteria andTestCaseIdLessThan(String value) { + addCriterion("test_case_id <", value, "testCaseId"); + return (Criteria) this; + } + + public Criteria andTestCaseIdLessThanOrEqualTo(String value) { + addCriterion("test_case_id <=", value, "testCaseId"); + return (Criteria) this; + } + + public Criteria andTestCaseIdLike(String value) { + addCriterion("test_case_id like", value, "testCaseId"); + return (Criteria) this; + } + + public Criteria andTestCaseIdNotLike(String value) { + addCriterion("test_case_id not like", value, "testCaseId"); + return (Criteria) this; + } + + public Criteria andTestCaseIdIn(List values) { + addCriterion("test_case_id in", values, "testCaseId"); + return (Criteria) this; + } + + public Criteria andTestCaseIdNotIn(List values) { + addCriterion("test_case_id not in", values, "testCaseId"); + return (Criteria) this; + } + + public Criteria andTestCaseIdBetween(String value1, String value2) { + addCriterion("test_case_id between", value1, value2, "testCaseId"); + return (Criteria) this; + } + + public Criteria andTestCaseIdNotBetween(String value1, String value2) { + addCriterion("test_case_id not between", value1, value2, "testCaseId"); + return (Criteria) this; + } + + public Criteria andIssuesIdIsNull() { + addCriterion("issues_id is null"); + return (Criteria) this; + } + + public Criteria andIssuesIdIsNotNull() { + addCriterion("issues_id is not null"); + return (Criteria) this; + } + + public Criteria andIssuesIdEqualTo(String value) { + addCriterion("issues_id =", value, "issuesId"); + return (Criteria) this; + } + + public Criteria andIssuesIdNotEqualTo(String value) { + addCriterion("issues_id <>", value, "issuesId"); + return (Criteria) this; + } + + public Criteria andIssuesIdGreaterThan(String value) { + addCriterion("issues_id >", value, "issuesId"); + return (Criteria) this; + } + + public Criteria andIssuesIdGreaterThanOrEqualTo(String value) { + addCriterion("issues_id >=", value, "issuesId"); + return (Criteria) this; + } + + public Criteria andIssuesIdLessThan(String value) { + addCriterion("issues_id <", value, "issuesId"); + return (Criteria) this; + } + + public Criteria andIssuesIdLessThanOrEqualTo(String value) { + addCriterion("issues_id <=", value, "issuesId"); + return (Criteria) this; + } + + public Criteria andIssuesIdLike(String value) { + addCriterion("issues_id like", value, "issuesId"); + return (Criteria) this; + } + + public Criteria andIssuesIdNotLike(String value) { + addCriterion("issues_id not like", value, "issuesId"); + return (Criteria) this; + } + + public Criteria andIssuesIdIn(List values) { + addCriterion("issues_id in", values, "issuesId"); + return (Criteria) this; + } + + public Criteria andIssuesIdNotIn(List values) { + addCriterion("issues_id not in", values, "issuesId"); + return (Criteria) this; + } + + public Criteria andIssuesIdBetween(String value1, String value2) { + addCriterion("issues_id between", value1, value2, "issuesId"); + return (Criteria) this; + } + + public Criteria andIssuesIdNotBetween(String value1, String value2) { + addCriterion("issues_id not between", value1, value2, "issuesId"); + return (Criteria) this; + } + } + + public static class Criteria extends GeneratedCriteria { + + protected Criteria() { + super(); + } + } + + public static class Criterion { + private String condition; + + private Object value; + + private Object secondValue; + + private boolean noValue; + + private boolean singleValue; + + private boolean betweenValue; + + private boolean listValue; + + private String typeHandler; + + public String getCondition() { + return condition; + } + + public Object getValue() { + return value; + } + + public Object getSecondValue() { + return secondValue; + } + + public boolean isNoValue() { + return noValue; + } + + public boolean isSingleValue() { + return singleValue; + } + + public boolean isBetweenValue() { + return betweenValue; + } + + public boolean isListValue() { + return listValue; + } + + public String getTypeHandler() { + return typeHandler; + } + + protected Criterion(String condition) { + super(); + this.condition = condition; + this.typeHandler = null; + this.noValue = true; + } + + protected Criterion(String condition, Object value, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.typeHandler = typeHandler; + if (value instanceof List) { + this.listValue = true; + } else { + this.singleValue = true; + } + } + + protected Criterion(String condition, Object value) { + this(condition, value, null); + } + + protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.secondValue = secondValue; + this.typeHandler = typeHandler; + this.betweenValue = true; + } + + protected Criterion(String condition, Object value, Object secondValue) { + this(condition, value, secondValue, null); + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/TestCaseIssuesMapper.java b/backend/src/main/java/io/metersphere/base/mapper/TestCaseIssuesMapper.java new file mode 100644 index 0000000000..e0b9e56c33 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/TestCaseIssuesMapper.java @@ -0,0 +1,30 @@ +package io.metersphere.base.mapper; + +import io.metersphere.base.domain.TestCaseIssues; +import io.metersphere.base.domain.TestCaseIssuesExample; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface TestCaseIssuesMapper { + long countByExample(TestCaseIssuesExample example); + + int deleteByExample(TestCaseIssuesExample example); + + int deleteByPrimaryKey(String id); + + int insert(TestCaseIssues record); + + int insertSelective(TestCaseIssues record); + + List selectByExample(TestCaseIssuesExample example); + + TestCaseIssues selectByPrimaryKey(String id); + + int updateByExampleSelective(@Param("record") TestCaseIssues record, @Param("example") TestCaseIssuesExample example); + + int updateByExample(@Param("record") TestCaseIssues record, @Param("example") TestCaseIssuesExample example); + + int updateByPrimaryKeySelective(TestCaseIssues record); + + int updateByPrimaryKey(TestCaseIssues record); +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/TestCaseIssuesMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/TestCaseIssuesMapper.xml new file mode 100644 index 0000000000..10755b5265 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/TestCaseIssuesMapper.xml @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + id, test_case_id, issues_id + + + + + delete from test_case_issues + where id = #{id,jdbcType=VARCHAR} + + + delete from test_case_issues + + + + + + insert into test_case_issues (id, test_case_id, issues_id + ) + values (#{id,jdbcType=VARCHAR}, #{testCaseId,jdbcType=VARCHAR}, #{issuesId,jdbcType=VARCHAR} + ) + + + insert into test_case_issues + + + id, + + + test_case_id, + + + issues_id, + + + + + #{id,jdbcType=VARCHAR}, + + + #{testCaseId,jdbcType=VARCHAR}, + + + #{issuesId,jdbcType=VARCHAR}, + + + + + + update test_case_issues + + + id = #{record.id,jdbcType=VARCHAR}, + + + test_case_id = #{record.testCaseId,jdbcType=VARCHAR}, + + + issues_id = #{record.issuesId,jdbcType=VARCHAR}, + + + + + + + + update test_case_issues + set id = #{record.id,jdbcType=VARCHAR}, + test_case_id = #{record.testCaseId,jdbcType=VARCHAR}, + issues_id = #{record.issuesId,jdbcType=VARCHAR} + + + + + + update test_case_issues + + + test_case_id = #{testCaseId,jdbcType=VARCHAR}, + + + issues_id = #{issuesId,jdbcType=VARCHAR}, + + + where id = #{id,jdbcType=VARCHAR} + + + update test_case_issues + set test_case_id = #{testCaseId,jdbcType=VARCHAR}, + issues_id = #{issuesId,jdbcType=VARCHAR} + where id = #{id,jdbcType=VARCHAR} + + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/commons/constants/DedectManagePlatform.java b/backend/src/main/java/io/metersphere/commons/constants/IssuesManagePlatform.java similarity index 63% rename from backend/src/main/java/io/metersphere/commons/constants/DedectManagePlatform.java rename to backend/src/main/java/io/metersphere/commons/constants/IssuesManagePlatform.java index 4daa6e514a..e898914154 100644 --- a/backend/src/main/java/io/metersphere/commons/constants/DedectManagePlatform.java +++ b/backend/src/main/java/io/metersphere/commons/constants/IssuesManagePlatform.java @@ -1,5 +1,5 @@ package io.metersphere.commons.constants; -public enum DedectManagePlatform { +public enum IssuesManagePlatform { Tapd, Jira } diff --git a/backend/src/main/java/io/metersphere/commons/utils/RestTemplateUtils.java b/backend/src/main/java/io/metersphere/commons/utils/RestTemplateUtils.java new file mode 100644 index 0000000000..20a1b9323e --- /dev/null +++ b/backend/src/main/java/io/metersphere/commons/utils/RestTemplateUtils.java @@ -0,0 +1,42 @@ +package io.metersphere.commons.utils; + +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +public class RestTemplateUtils { + + private static RestTemplate restTemplate; + + private static void getTemplate() { + restTemplate = (RestTemplate) CommonBeanFactory.getBean("restTemplate"); + } + + public static String get(String url, HttpHeaders httpHeaders) { + getTemplate(); + try { + HttpEntity requestEntity = new HttpEntity<>(httpHeaders); + ResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class); + return responseEntity.getBody(); + } catch (Exception e) { + throw new RuntimeException("调用接口失败", e); + } + } + + public static String post(String url, Object paramMap, HttpHeaders httpHeaders) { + getTemplate(); + try { + HttpEntity requestEntity = new HttpEntity<>((MultiValueMap) paramMap, httpHeaders); + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); + return responseEntity.getBody(); + } catch (Exception e) { + throw new RuntimeException("调用接口失败", e); + } + + } + +} diff --git a/backend/src/main/java/io/metersphere/service/IssuesService.java b/backend/src/main/java/io/metersphere/service/IssuesService.java new file mode 100644 index 0000000000..40256412d9 --- /dev/null +++ b/backend/src/main/java/io/metersphere/service/IssuesService.java @@ -0,0 +1,101 @@ +package io.metersphere.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.metersphere.base.domain.ServiceIntegration; +import io.metersphere.commons.constants.IssuesManagePlatform; +import io.metersphere.commons.exception.MSException; +import io.metersphere.commons.user.SessionUser; +import io.metersphere.commons.utils.EncryptUtils; +import io.metersphere.commons.utils.RestTemplateUtils; +import io.metersphere.commons.utils.SessionUtils; +import io.metersphere.controller.ResultHolder; +import io.metersphere.controller.request.IntegrationRequest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.apache.commons.lang3.StringUtils; + +import javax.annotation.Resource; + +@Service +public class IssuesService { + + @Resource + private IntegrationService integrationService; + + + public void testAuth() { + String url = "https://api.tapd.cn/quickstart/testauth"; + ResultHolder call = call(url); + System.out.println(call.getData()); + } + + public void addIssues() { + String url = "https://api.tapd.cn/bugs"; + MultiValueMap paramMap = new LinkedMultiValueMap<>(); + paramMap.add("title", "20200812bug2"); + paramMap.add("workspace_id", "55049933"); + paramMap.add("description", "20200812 api add bug 2"); + ResultHolder call = call(url, HttpMethod.POST, paramMap); + System.out.println(call.getData()); + } + + private ResultHolder call(String url) { + return call(url, HttpMethod.GET, null); + } + + private ResultHolder call(String url, HttpMethod httpMethod, Object params) { + String responseJson; + + String config = tapdConfig(); + JSONObject object = JSON.parseObject(config); + + if (object == null) { + MSException.throwException("tapd config is null"); + } + + String account = object.getString("account"); + String password = object.getString("password"); + + HttpHeaders header = tapdAuth(account, password); + + if (httpMethod.equals(HttpMethod.GET)) { + responseJson = RestTemplateUtils.get(url, header); + } else { + responseJson = RestTemplateUtils.post(url, params, header); + } + + ResultHolder result = JSON.parseObject(responseJson, ResultHolder.class); + + if (!result.isSuccess()) { + MSException.throwException(result.getMessage()); + } + return JSON.parseObject(responseJson, ResultHolder.class); + + } + + private String tapdConfig() { + SessionUser user = SessionUtils.getUser(); + String orgId = user.getLastOrganizationId(); + + IntegrationRequest request = new IntegrationRequest(); + if (StringUtils.isBlank(orgId)) { + MSException.throwException("organization id is null"); + } + request.setOrgId(orgId); + request.setPlatform(IssuesManagePlatform.Tapd.toString()); + + ServiceIntegration integration = integrationService.get(request); + return integration.getConfiguration(); + } + + private HttpHeaders tapdAuth(String apiUser, String password) { + String authKey = EncryptUtils.base64Encoding(apiUser + ":" + password); + HttpHeaders headers = new HttpHeaders(); + headers.add("Authorization", "Basic " + authKey); + return headers; + } +} diff --git a/backend/src/main/resources/db/migration/V13__service_integration.sql b/backend/src/main/resources/db/migration/V13__service_integration.sql index fbf6627134..cf9aa07833 100644 --- a/backend/src/main/resources/db/migration/V13__service_integration.sql +++ b/backend/src/main/resources/db/migration/V13__service_integration.sql @@ -8,4 +8,11 @@ create table service_integration primary key (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +create table if not exists test_case_issues +( + id varchar(50) not null + primary key, + test_case_id varchar(50) not null, + issues_id varchar(100) not null +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseEdit.vue b/frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseEdit.vue index 99d00f7e6a..78c827baaa 100644 --- a/frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseEdit.vue +++ b/frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseEdit.vue @@ -180,13 +180,27 @@ @change="issuesChange" :active-text="$t('test_track.plan_view.submit_issues')"> + + + + + {{$t('commons.save')}} + {{$t('commons.cancel')}}