feat: 同步Jira、TAPD缺陷

This commit is contained in:
chenjianxing 2021-06-29 19:57:01 +08:00 committed by jianxing
parent ebf684edef
commit 47842c10bc
30 changed files with 499 additions and 143 deletions

View File

@ -272,7 +272,8 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
checkApiScenarioModuleExist(request);
List<ApiScenarioDTO> apiScenarios = queryByModuleIds(request);
apiScenarios.forEach(apiScenario -> {
StringBuilder path = new StringBuilder(apiScenario.getModulePath());
String modulePath = apiScenario.getModulePath();
StringBuilder path = new StringBuilder(modulePath == null ? "" : modulePath);
List<String> pathLists = Arrays.asList(path.toString().split("/"));
if (pathLists.size() > request.getLevel()) {
pathLists.set(request.getLevel(), request.getName());

View File

@ -16,4 +16,6 @@ public interface ExtIssuesMapper {
List<IssuesDao> getRelateIssues(@Param("request") IssuesRequest request);
Issues getNextNum(String projectId);
List<IssuesDao> getIssueForSync(String projectId);
}

View File

@ -34,12 +34,20 @@
and test_case_issues.issues_id is null
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
</select>
<select id="getIssueForSync" resultType="io.metersphere.base.domain.IssuesDao">
select id,platform
from issues
where project_id = #{projectId} and platform != 'Local';
</select>
<sql id="queryWhereCondition">
<where>
<if test="request.name != null">
and issues.title LIKE CONCAT('%', #{request.name}, '%')
and (
issues.title LIKE CONCAT('%', #{request.name}, '%')
or issues.id LIKE CONCAT('%', #{request.name}, '%')
)
</if>
<if test="request.projectId != null and request.projectId != ''">

View File

@ -18,4 +18,5 @@ public interface ExtProjectMapper {
String getSystemIdByProjectId(String projectId);
List<String> getProjectIds();
}

View File

@ -110,6 +110,9 @@
<select id="getSystemIdByProjectId" resultType="java.lang.String">
SELECT system_id FROM project WHERE id = #{0}
</select>
<select id="getProjectIds" resultType="java.lang.String">
select id from project;
</select>
<update id="removeIssuePlatform">

View File

@ -1,5 +1,5 @@
package io.metersphere.commons.constants;
public enum ScheduleGroup {
API_TEST, PERFORMANCE_TEST, API_SCENARIO_TEST, TEST_PLAN_TEST, SWAGGER_IMPORT
API_TEST, PERFORMANCE_TEST, API_SCENARIO_TEST, TEST_PLAN_TEST, SWAGGER_IMPORT, ISSUE_SYNC
}

View File

@ -0,0 +1,31 @@
package io.metersphere.job.sechedule;
import io.metersphere.commons.constants.ScheduleGroup;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.track.service.IssuesService;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
public class IssueSyncJob extends MsScheduleJob {
private IssuesService issuesService;
public IssueSyncJob() {
issuesService = CommonBeanFactory.getBean(IssuesService.class);
}
@Override
void businessExecute(JobExecutionContext context) {
issuesService.syncThirdPartyIssues();
}
public static JobKey getJobKey(String projectId) {
return new JobKey(projectId, ScheduleGroup.ISSUE_SYNC.name());
}
public static TriggerKey getTriggerKey(String projectId) {
return new TriggerKey(projectId, ScheduleGroup.ISSUE_SYNC.name());
}
}

View File

@ -451,4 +451,8 @@ public class ProjectService {
return returnList.get(0);
}
}
public List<String> getProjectIds() {
return extProjectMapper.getProjectIds();
}
}

View File

@ -92,10 +92,13 @@ public class IssuesController {
return issuesService.getZentaoBuilds(request);
}
@PostMapping("/get/platform/issue")
public IssuesWithBLOBs getPlatformIssue(@RequestBody IssuesWithBLOBs issue) {
return issuesService.getPlatformIssue(issue);
}
// @PostMapping("/get/platform/issue")
// public IssuesWithBLOBs getPlatformIssue(@RequestBody IssuesWithBLOBs issue) {
// return issuesService.getPlatformIssue(issue);
// }
@GetMapping("/sync/{projectId}")
public void getPlatformIssue(@PathVariable String projectId) {
issuesService.syncThirdPartyIssues(projectId);
}
}

View File

@ -1,6 +1,7 @@
package io.metersphere.track.issue;
import io.metersphere.base.domain.IssuesDao;
import io.metersphere.base.domain.Project;
import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.request.testcase.IssuesRequest;
@ -56,4 +57,11 @@ public interface IssuesPlatform {
* @return platform user list
*/
List<PlatformUser> getPlatformUser();
/**
* 同步缺陷最新变更
* @param project
* @param tapdIssues
*/
void syncIssues(Project project, List<IssuesDao> tapdIssues);
}

View File

@ -31,6 +31,7 @@ import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
@ -64,8 +65,6 @@ public class JiraPlatform extends AbstractIssuePlatform {
@Override
public List<IssuesDao> getIssue(IssuesRequest issuesRequest) {
List<IssuesDao> list = new ArrayList<>();
issuesRequest.setPlatform(IssuesManagePlatform.Jira.toString());
List<IssuesDao> issues;
if (StringUtils.isNotBlank(issuesRequest.getProjectId())) {
@ -73,26 +72,26 @@ public class JiraPlatform extends AbstractIssuePlatform {
} else {
issues = extIssuesMapper.getIssuesByCaseId(issuesRequest);
}
setConfig(issuesRequest.getOrganizationId());
issues.forEach(item -> {
String issuesId = item.getId();
parseIssue(item, jiraClientV2.getIssues(issuesId));
if (StringUtils.isBlank(item.getId())) {
// 缺陷不存在解除用例和缺陷的关联
TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
issuesExample.createCriteria()
.andTestCaseIdEqualTo(testCaseId)
.andIssuesIdEqualTo(issuesId);
testCaseIssuesMapper.deleteByExample(issuesExample);
issuesMapper.deleteByPrimaryKey(issuesId);
} else {
// 缺陷状态为 完成则不显示
if (!StringUtils.equals("done", item.getStatus())) {
list.add(item);
}
}
});
return list;
// setConfig(issuesRequest.getOrganizationId());
// issues.forEach(item -> {
// String issuesId = item.getId();
// parseIssue(item, jiraClientV2.getIssues(issuesId));
// if (StringUtils.isBlank(item.getId())) {
// // 缺陷不存在解除用例和缺陷的关联
// TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
// issuesExample.createCriteria()
// .andTestCaseIdEqualTo(testCaseId)
// .andIssuesIdEqualTo(issuesId);
// testCaseIssuesMapper.deleteByExample(issuesExample);
// issuesMapper.deleteByPrimaryKey(issuesId);
// } else {
// // 缺陷状态为 完成则不显示
// if (!StringUtils.equals("done", item.getStatus())) {
// list.add(item);
// }
// }
// });
return issues;
}
public void parseIssue(IssuesWithBLOBs item, JiraIssue jiraIssue) {
@ -296,6 +295,27 @@ public class JiraPlatform extends AbstractIssuePlatform {
return null;
}
@Override
public void syncIssues(Project project, List<IssuesDao> tapdIssues) {
tapdIssues.forEach(item -> {
setConfig(null);
try {
parseIssue(item, jiraClientV2.getIssues(item.getId()));
// 缺陷状态为 完成则不显示
if (StringUtils.equals("done", item.getStatus())) {
item.setStatus(IssuesStatus.RESOLVED.toString());
}
issuesMapper.updateByPrimaryKeySelective(item);
} catch (HttpClientErrorException e) {
if (e.getRawStatusCode() == 404) {
// 标记成删除
item.setStatus(IssuesStatus.DELETE.toString());
issuesMapper.deleteByPrimaryKey(item.getId());
}
}
});
}
@Override
String getProjectId(String projectId) {
if (StringUtils.isNotBlank(projectId)) {

View File

@ -2,6 +2,7 @@ package io.metersphere.track.issue;
import io.metersphere.base.domain.IssuesDao;
import io.metersphere.base.domain.IssuesWithBLOBs;
import io.metersphere.base.domain.Project;
import io.metersphere.commons.constants.IssuesManagePlatform;
import io.metersphere.commons.user.SessionUser;
import io.metersphere.commons.utils.BeanUtils;
@ -81,6 +82,11 @@ public class LocalPlatform extends AbstractIssuePlatform {
return null;
}
@Override
public void syncIssues(Project project, List<IssuesDao> tapdIssues) {
}
@Override
String getProjectId(String projectId) {
return null;

View File

@ -3,16 +3,24 @@ package io.metersphere.track.issue;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.base.domain.*;
import io.metersphere.base.domain.Issues;
import io.metersphere.base.domain.IssuesDao;
import io.metersphere.base.domain.Project;
import io.metersphere.base.domain.TestCaseWithBLOBs;
import io.metersphere.commons.constants.IssuesManagePlatform;
import io.metersphere.commons.constants.IssuesStatus;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.controller.ResultHolder;
import io.metersphere.dto.CustomFieldItemDTO;
import io.metersphere.dto.UserDTO;
import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.issue.client.TapdClient;
import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.issue.domain.TapdConfig;
import io.metersphere.track.issue.domain.TapdGetIssueResponse;
import io.metersphere.track.request.testcase.IssuesRequest;
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
import org.apache.commons.collections.CollectionUtils;
@ -33,15 +41,17 @@ public class TapdPlatform extends AbstractIssuePlatform {
protected String key = IssuesManagePlatform.Tapd.toString();
private TapdClient tapdClient = new TapdClient();
public TapdPlatform(IssuesRequest issueRequest) {
super(issueRequest);
}
@Override
public List<IssuesDao> getIssue(IssuesRequest issuesRequest) {
List<IssuesDao> list = new ArrayList<>();
String tapdId = getProjectId(issuesRequest.getProjectId());
// List<IssuesDao> list = new ArrayList<>();
// String tapdId = getProjectId(issuesRequest.getProjectId());
issuesRequest.setPlatform(IssuesManagePlatform.Tapd.toString());
List<IssuesDao> issues;
if (StringUtils.isNotBlank(issuesRequest.getProjectId())) {
@ -49,30 +59,29 @@ public class TapdPlatform extends AbstractIssuePlatform {
} else {
issues = extIssuesMapper.getIssuesByCaseId(issuesRequest);
}
issues.forEach(item -> {
String issuesId = item.getId();
IssuesDao dto = getTapdIssues(tapdId, issuesId);
dto.setNum(item.getNum());
if (StringUtils.isBlank(dto.getId())) {
// 缺陷不存在解除用例和缺陷的关联
TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
TestCaseIssuesExample.Criteria criteria = issuesExample.createCriteria();
if (StringUtils.isNotBlank(testCaseId)) {
criteria.andTestCaseIdEqualTo(testCaseId);
}
criteria.andIssuesIdEqualTo(issuesId);
testCaseIssuesMapper.deleteByExample(issuesExample);
issuesMapper.deleteByPrimaryKey(issuesId);
} else {
dto.setPlatform(IssuesManagePlatform.Tapd.toString());
// 缺陷状态为 关闭则不显示
if (!StringUtils.equals(IssuesStatus.CLOSED.toString(), dto.getStatus())) {
list.add(dto);
}
}
});
return list;
// issues.forEach(item -> {
// String issuesId = item.getId();
// IssuesDao dto = getTapdIssues(tapdId, issuesId);
// dto.setNum(item.getNum());
// if (StringUtils.isBlank(dto.getId())) {
// // 缺陷不存在解除用例和缺陷的关联
// TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
// TestCaseIssuesExample.Criteria criteria = issuesExample.createCriteria();
// if (StringUtils.isNotBlank(testCaseId)) {
// criteria.andTestCaseIdEqualTo(testCaseId);
// }
// criteria.andIssuesIdEqualTo(issuesId);
// testCaseIssuesMapper.deleteByExample(issuesExample);
// issuesMapper.deleteByPrimaryKey(issuesId);
// } else {
// dto.setPlatform(IssuesManagePlatform.Tapd.toString());
// // 缺陷状态为 关闭则不显示
// if (!StringUtils.equals(IssuesStatus.CLOSED.toString(), dto.getStatus())) {
// list.add(dto);
// }
// }
// });
return issues;
}
@Override
@ -152,7 +161,6 @@ public class TapdPlatform extends AbstractIssuePlatform {
List<CustomFieldItemDTO> customFields = getCustomFields(issuesRequest.getCustomFields());
String url = "https://api.tapd.cn/bugs";
String testCaseId = issuesRequest.getTestCaseId();
String tapdId = getProjectId(issuesRequest.getProjectId());
if (StringUtils.isBlank(tapdId)) {
@ -240,6 +248,33 @@ public class TapdPlatform extends AbstractIssuePlatform {
return users;
}
@Override
public void syncIssues(Project project, List<IssuesDao> tapdIssues) {
int pageNum = 1;
int limit = 200;
int count = 200;
List<String> ids = tapdIssues.stream()
.map(Issues::getId)
.collect(Collectors.toList());
setConfig(null);
while (count == limit) {
count = 0;
TapdGetIssueResponse result = tapdClient.getIssueForPageByIds(project.getTapdId(), pageNum, limit, ids);
List<TapdGetIssueResponse.Data> data = result.getData();
count = data.size();
pageNum++;
data.forEach(issue -> {
TapdGetIssueResponse.Bug bug = issue.getBug();
IssuesDao issuesDao = new IssuesDao();
BeanUtils.copyBean(issuesDao, bug);
// tapdClient.getStatusMap(projectId);
issuesMapper.updateByPrimaryKeySelective(issuesDao);
});
}
}
@Override
String getProjectId(String projectId) {
if (StringUtils.isNotBlank(projectId)) {
@ -250,6 +285,26 @@ public class TapdPlatform extends AbstractIssuePlatform {
return project.getTapdId();
}
public TapdConfig getConfig(String orgId) {
TapdConfig tapdConfig = null;
String config = getPlatformConfig(IssuesManagePlatform.Tapd.toString());
if (StringUtils.isNotBlank(config)) {
tapdConfig = JSONObject.parseObject(config, TapdConfig.class);
UserDTO.PlatformInfo userPlatInfo = getUserPlatInfo(orgId, SessionUtils.getUserId());
if (userPlatInfo != null && StringUtils.isNotBlank(userPlatInfo.getTapdUserName())) {
// tapdConfig.setAccount(userPlatInfo.getTapdUserName());
}
}
// validateConfig(tapdConfig);
return tapdConfig;
}
public TapdConfig setConfig(String orgId) {
TapdConfig config = getConfig(orgId);
tapdClient.setConfig(config);
return config;
}
private ResultHolder call(String url) {
return call(url, HttpMethod.GET, null);
}

View File

@ -371,6 +371,11 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
return users;
}
@Override
public void syncIssues(Project project, List<IssuesDao> tapdIssues) {
}
public List<ZentaoBuild> getBuilds() {
String session = login();
String projectId1 = getProjectId(projectId);

View File

@ -0,0 +1,79 @@
package io.metersphere.track.issue.client;
import io.metersphere.commons.exception.MSException;
import io.metersphere.track.issue.domain.TapdConfig;
import io.metersphere.track.issue.domain.TapdGetIssueResponse;
import io.metersphere.track.issue.domain.TapdStatusMapResponse;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
import java.util.List;
@Component
public class TapdClient extends BaseClient {
protected String ENDPOINT = "https://api.tapd.cn";
protected String USER_NAME;
protected String PASSWD;
// public JiraAddIssueResponse addIssue(String body) {
// LogUtil.debug("addIssue: " + body);
// HttpHeaders headers = getAuthHeader();
// headers.setContentType(MediaType.APPLICATION_JSON);
// HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
// ResponseEntity<String> response = restTemplate.exchange(getBaseUrl() + "/issue", HttpMethod.POST, requestEntity, String.class);
// return (JiraAddIssueResponse) getResultForObject(JiraAddIssueResponse.class, response);
// }
public TapdGetIssueResponse getIssueForPage(String projectId, int pageNum, int limit) {
return getIssueForPageByIds(projectId, pageNum, limit, null);
}
public TapdStatusMapResponse getStatusMap(String projectId) {
String url = getBaseUrl() + "/workflows/status_map?workspace_id={1}&system=bug";
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, getAuthHttpEntity(), String.class, projectId);
return (TapdStatusMapResponse) getResultForObject(TapdStatusMapResponse.class, response);
}
public TapdGetIssueResponse getIssueForPageByIds(String projectId, int pageNum, int limit, List<String> ids) {
String url = getBaseUrl() + "/bugs?workspace_id={1}&page={2}&limit={3}&fields={4}";
StringBuilder idStr = new StringBuilder();
ids.forEach(item -> {
idStr.append(item + ",");
});
if (!CollectionUtils.isEmpty(ids)) {
url += "&id={5}";
}
String fields = "id,title,description,priority,severity,reporter,status";
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, getAuthHttpEntity(), String.class,
projectId, pageNum, limit, fields, idStr);
return (TapdGetIssueResponse) getResultForObject(TapdGetIssueResponse.class, response);
}
protected HttpEntity<MultiValueMap> getAuthHttpEntity() {
return new HttpEntity<>(getAuthHeader());
}
protected HttpHeaders getAuthHeader() {
return getBasicHttpHeaders(USER_NAME, PASSWD);
}
protected String getBaseUrl() {
return ENDPOINT;
}
public void setConfig(TapdConfig config) {
if (config == null) {
MSException.throwException("config is null");
}
USER_NAME = config.getAccount();
PASSWD = config.getPassword();
}
}

View File

@ -0,0 +1,11 @@
package io.metersphere.track.issue.domain;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TapdConfig {
private String account;
private String password;
}

View File

@ -0,0 +1,33 @@
package io.metersphere.track.issue.domain;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class TapdGetIssueResponse {
private int status;
private List<Data> data;
private String info;
@Getter
@Setter
public static class Data {
private Bug bug;
}
@Getter
@Setter
public static class Bug {
private String id;
private String title;
private String description;
// private String priority;
// private String severity;
// private String reporter;
// private String status;
}
}

View File

@ -0,0 +1,29 @@
package io.metersphere.track.issue.domain;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TapdStatusMapResponse {
private int status;
private Data data;
private String info;
@Getter
@Setter
public class Data {
@JSONField(name = "new")
private String create;
@JSONField(name = "in_progress")
private String inProgress;
private String resolved;
private String verified;
private String reopened;
private String rejected;
private String closed;
}
}

View File

@ -1,7 +1,6 @@
package io.metersphere.track.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.IssueTemplateMapper;
import io.metersphere.base.mapper.IssuesMapper;
@ -42,6 +41,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
@Service
@ -299,18 +299,6 @@ public class IssuesService {
public List<IssuesDao> list(IssuesRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
// List<IssuesDao> list = new ArrayList<>();
// String projectId = request.getProjectId();
// Project project = projectService.getProjectById(projectId);
// List<String> platforms = getPlatforms(project);
// platforms.add(IssuesManagePlatform.Local.toString());
// List<AbstractIssuePlatform> platformList = IssueFactory.createPlatforms(platforms, request);
// platformList.forEach(platform -> {
// List<IssuesDao> issue = platform.getIssue(request);
// list.addAll(issue);
// });
List<IssuesDao> issues = extIssuesMapper.getIssuesByProjectId(request);
List<String> ids = issues.stream()
@ -334,17 +322,7 @@ public class IssuesService {
item.setResourceName(planMap.get(item.getResourceId()));
}
});
// Map<String, List<IssuesDao>> issueMap = getIssueMap(issues);
// Map<String, AbstractIssuePlatform> platformMap = getPlatformMap(request);
// issueMap.forEach((platformName, data) -> {
// AbstractIssuePlatform platform = platformMap.get(platformName);
// if (platform != null) {
// platform.filter(data);
// }
// });
return issues;
// return list;
}
public Map<String, List<IssuesDao>> getIssueMap(List<IssuesDao> issues) {
@ -372,41 +350,101 @@ public class IssuesService {
return IssueFactory.createPlatformsForMap(platforms, request);
}
public IssuesWithBLOBs getPlatformIssue(IssuesWithBLOBs issue) {
String platform = issue.getPlatform();
if (StringUtils.isNotBlank(issue.getProjectId())) {
Project project = projectService.getProjectById(issue.getProjectId());
Workspace workspace = workspaceMapper.selectByPrimaryKey(project.getWorkspaceId());
String orgId = workspace.getOrganizationId();
try {
if (StringUtils.equals(platform, IssuesManagePlatform.Tapd.name())) {
TapdPlatform tapdPlatform = new TapdPlatform(new IssuesRequest());
String tapdId = projectService.getProjectById(issue.getProjectId()).getTapdId();
IssuesDao tapdIssues = tapdPlatform.getTapdIssues(tapdId, issue.getId());
issue.setTitle(tapdIssues.getTitle());
issue.setDescription(tapdIssues.getDescription());
issue.setStatus(tapdIssues.getStatus());
} else if (StringUtils.equals(platform, IssuesManagePlatform.Jira.name())) {
JiraPlatform jiraPlatform = new JiraPlatform(new IssuesRequest());
jiraPlatform.getJiraIssues(issue, issue.getId());
} else if (StringUtils.equals(platform, IssuesManagePlatform.Zentao.name())) {
String config = getConfig(orgId, IssuesManagePlatform.Zentao.toString());
JSONObject object = JSON.parseObject(config);
String account = object.getString("account");
String password = object.getString("password");
String url = object.getString("url");
ZentaoPlatform zentaoPlatform = new ZentaoPlatform(account, password, url);
IssuesDao zentaoIssues = zentaoPlatform.getZentaoIssues(issue.getId());
issue.setTitle(zentaoIssues.getTitle());
issue.setDescription(zentaoIssues.getDescription());
issue.setStatus(zentaoIssues.getStatus());
// public IssuesWithBLOBs getPlatformIssue(IssuesWithBLOBs issue) {
// String platform = issue.getPlatform();
// if (StringUtils.isNotBlank(issue.getProjectId())) {
// Project project = projectService.getProjectById(issue.getProjectId());
// Workspace workspace = workspaceMapper.selectByPrimaryKey(project.getWorkspaceId());
// String orgId = workspace.getOrganizationId();
// try {
// if (StringUtils.equals(platform, IssuesManagePlatform.Tapd.name())) {
// TapdPlatform tapdPlatform = new TapdPlatform(new IssuesRequest());
// String tapdId = projectService.getProjectById(issue.getProjectId()).getTapdId();
// IssuesDao tapdIssues = tapdPlatform.getTapdIssues(tapdId, issue.getId());
// issue.setTitle(tapdIssues.getTitle());
// issue.setDescription(tapdIssues.getDescription());
// issue.setStatus(tapdIssues.getStatus());
// } else if (StringUtils.equals(platform, IssuesManagePlatform.Jira.name())) {
// JiraPlatform jiraPlatform = new JiraPlatform(new IssuesRequest());
// jiraPlatform.getJiraIssues(issue, issue.getId());
// } else if (StringUtils.equals(platform, IssuesManagePlatform.Zentao.name())) {
// String config = getConfig(orgId, IssuesManagePlatform.Zentao.toString());
// JSONObject object = JSON.parseObject(config);
// String account = object.getString("account");
// String password = object.getString("password");
// String url = object.getString("url");
// ZentaoPlatform zentaoPlatform = new ZentaoPlatform(account, password, url);
// IssuesDao zentaoIssues = zentaoPlatform.getZentaoIssues(issue.getId());
// issue.setTitle(zentaoIssues.getTitle());
// issue.setDescription(zentaoIssues.getDescription());
// issue.setStatus(zentaoIssues.getStatus());
// }
// } catch (Exception e) {
// LogUtil.error(e.getMessage(), e);
// }
// }
// return issue;
// }
public void syncThirdPartyIssues() {
List<String> projectIds = projectService.getProjectIds();
projectIds.forEach(id -> {
syncThirdPartyIssues(id);
});
}
public void syncThirdPartyIssues(String projectId) {
if (StringUtils.isNotBlank(projectId)) {
Project project = projectService.getProjectById(projectId);
List<IssuesDao> issues = extIssuesMapper.getIssueForSync(projectId);
if (CollectionUtils.isEmpty(issues)) {
return;
}
List<IssuesDao> tapdIssues = issues.stream()
.filter(item -> item.getPlatform().equals(IssuesManagePlatform.Tapd.name()))
.collect(Collectors.toList());
List<IssuesDao> jiraIssues = issues.stream()
.filter(item -> item.getPlatform().equals(IssuesManagePlatform.Jira.name()))
.collect(Collectors.toList());
// List<IssuesDao> zentaoIssues = issues.stream()
// .filter(item -> item.getPlatform().equals(IssuesManagePlatform.Zentao.name()))
// .collect(Collectors.toList());
IssuesRequest issuesRequest = new IssuesRequest();
issuesRequest.setProjectId(projectId);
if (CollectionUtils.isNotEmpty(tapdIssues)) {
TapdPlatform tapdPlatform = new TapdPlatform(issuesRequest);
syncThirdPartyIssues(tapdPlatform::syncIssues, project, tapdIssues);
}
if (CollectionUtils.isNotEmpty(jiraIssues)) {
JiraPlatform jiraPlatform = new JiraPlatform(new IssuesRequest());
syncThirdPartyIssues(jiraPlatform::syncIssues, project, tapdIssues);
}
// if (CollectionUtils.isNotEmpty(zentaoIssues)) {
// String config = getConfig(orgId, IssuesManagePlatform.Zentao.toString());
// JSONObject object = JSON.parseObject(config);
// String account = object.getString("account");
// String password = object.getString("password");
// String url = object.getString("url");
// ZentaoPlatform zentaoPlatform = new ZentaoPlatform(account, password, url);
// IssuesDao zentaoIssues = zentaoPlatform.getZentaoIssues(issue.getId());
// issue.setTitle(zentaoIssues.getTitle());
// issue.setDescription(zentaoIssues.getDescription());
// issue.setStatus(zentaoIssues.getStatus());
// }
}
}
public void syncThirdPartyIssues(BiConsumer<Project, List<IssuesDao>> syncFuc, Project project, List<IssuesDao> issues) {
try {
syncFuc.accept(project, issues);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
}
}
return issue;
}
private String getConfig(String orgId, String platform) {
IntegrationRequest request = new IntegrationRequest();

View File

@ -930,11 +930,6 @@ export default {
margin-bottom: 0px;
}
/deep/ .run-button {
background-color: #409EFF;
border-color: #409EFF;
}
/deep/ .el-table__fixed-body-wrapper {
z-index: auto !important;
}

View File

@ -375,7 +375,7 @@ export default {
this.createVisible = true;
listenGoBack(this.handleClose);
this.form = Object.assign({}, row);
this.$get("/service/integration/all/" + getCurrentUser().lastOrganizationId, response => {
this.$get("/service/integration/all/" + getCurrentOrganizationId(), response => {
let data = response.data;
let platforms = data.map(d => d.platform);
if (platforms.indexOf("Tapd") !== -1) {

View File

@ -5,7 +5,14 @@
<template v-slot:header>
<ms-table-header :create-permission="['PROJECT_TRACK_ISSUE:READ+CREATE']" :condition.sync="page.condition" @search="getIssues" @create="handleCreate"
:create-tip="$t('test_track.issue.create_issue')" :title="$t('test_track.issue.issue_list')"
:tip="$t('issue.search_name')" :have-search="false"/>
:tip="$t('commons.search_by_name_or_id')">
<template v-slot:button>
<el-tooltip v-if="hasThirdPart" :content="'更新第三方平台的缺陷内容'">
<ms-table-button icon="el-icon-refresh" v-if="true"
:content="'同步缺陷'" @click="syncIssues"/>
</el-tooltip>
</template>
</ms-table-header>
</template>
<ms-table
@ -40,6 +47,7 @@
:label="$t('test_track.issue.id')"
prop="num"
:field="item"
sortable
:fields-width="fieldsWidth">
</ms-table-column>
@ -47,6 +55,7 @@
:field="item"
:fields-width="fieldsWidth"
:label="$t('test_track.issue.title')"
sortable
prop="title">
</ms-table-column>
@ -136,7 +145,7 @@ import {
import MsTableHeader from "@/business/components/common/components/MsTableHeader";
import IssueDescriptionTableItem from "@/business/components/track/issue/IssueDescriptionTableItem";
import IssueEdit from "@/business/components/track/issue/IssueEdit";
import {getIssues} from "@/network/Issue";
import {getIssues, syncIssues} from "@/network/Issue";
import {
getCustomFieldValue,
getCustomTableWidth,
@ -147,6 +156,7 @@ import MsMainContainer from "@/business/components/common/components/MsMainConta
import {getCurrentProjectID} from "@/common/js/utils";
import {getIssueTemplate} from "@/network/custom-field-template";
import {getProjectMember} from "@/network/user";
import {getIntegrationService} from "@/network/organization";
export default {
name: "IssueList",
@ -183,13 +193,17 @@ export default {
}
],
issueTemplate: {},
members: []
members: [],
platforms: []
};
},
activated() {
getProjectMember((data) => {
this.members = data;
});
getIntegrationService((data) => {
this.platforms = data.map(d => d.platform);
});
getIssueTemplate()
.then((template) => {
this.issueTemplate = template;
@ -216,6 +230,14 @@ export default {
},
projectId() {
return getCurrentProjectID();
},
hasThirdPart() {
if (this.platforms.indexOf("Tapd") !== -1
|| this.platforms.indexOf("Jira") !== -1
|| this.platforms.indexOf("Zentao") !== -1) {
return true;
}
return false;
}
},
methods: {
@ -258,6 +280,10 @@ export default {
saveSortField(key,orders){
saveLastTableSortField(key,JSON.stringify(orders));
},
syncIssues() {
this.page.result = syncIssues();
this.getIssues();
},
getSortField(){
let orderJsonStr = getLastTableSortField(this.tableHeaderKey);
let returnObj = null;

View File

@ -64,7 +64,6 @@
import MsTablePagination from "@/business/components/common/pagination/TablePagination";
import ShowMoreBtn from "@/business/components/track/case/components/ShowMoreBtn";
import MsTag from "../../../../../common/components/MsTag";
import {getUUID, getCurrentProjectID} from "@/common/js/utils";
import MsApiReportDetail from "../../../../../api/automation/report/ApiReportDetail";
import MsTableMoreBtn from "../../../../../api/automation/scenario/TableMoreBtn";
import MsTestPlanList from "../../../../../api/automation/scenario/testplan/TestPlanList";

View File

@ -201,9 +201,4 @@
margin: 5px 10px;
}
/deep/ .run-button {
background-color: #409EFF;
border-color: #409EFF;
}
</style>

View File

@ -8,7 +8,8 @@
@relevanceCase="$emit('relevanceCase', 'scenario')"/>
</template>
<el-table ref="scenarioTable" border :data="tableData" class="test-content adjust-table ms-select-all-fixed"
<el-table ref="scenarioTable"
border :data="tableData" class="test-content adjust-table ms-select-all-fixed"
@select-all="handleSelectAll"
@sort-change="sort"
@filter-change="filter"
@ -35,6 +36,7 @@
label="ID"
:key="index"/>
<el-table-column v-if="item.id == 'name'" prop="name" :label="$t('api_test.automation.scenario_name')" min-width="120px"
sortable
show-overflow-tooltip :key="index"/>
<el-table-column v-if="item.id == 'level'" prop="level" :label="$t('api_test.automation.case_level')" min-width="100px"
column-key="level"

View File

@ -495,10 +495,6 @@ export default {
</script>
<style scoped>
/deep/ .run-button {
background-color: #409EFF;
border-color: #409EFF;
}
/deep/ .el-table__fixed-body-wrapper {
top: 59px !important;
}

View File

@ -195,9 +195,4 @@ export default {
margin: 5px 10px;
}
/deep/ .run-button {
background-color: #409EFF;
border-color: #409EFF;
}
</style>

View File

@ -239,3 +239,8 @@ textarea {
.el-button + .tooltip-btn, .tooltip-btn + .el-button, .tooltip-btn + .tooltip-btn {
margin-left: 10px;
}
.run-button .el-button {
background-color: #409EFF;
border-color: #409EFF;
}

View File

@ -1,5 +1,6 @@
import {post, get} from "@/common/js/ajax";
import {getPageDate} from "@/common/js/tableUtils";
import {getCurrentProjectID} from "@/common/js/utils";
export function buildIssues(page) {
let data = page.data;
@ -8,9 +9,9 @@ export function buildIssues(page) {
if (data[i].customFields) {
data[i].customFields = JSON.parse(data[i].customFields);
}
if (data[i].platform !== 'Local') {
page.result = buildPlatformIssue(data[i]);
}
// if (data[i].platform !== 'Local') {
// page.result = buildPlatformIssue(data[i]);
// }
}
}
}
@ -63,4 +64,10 @@ export function getRelateIssues(page) {
});
}
export function syncIssues() {
return get('issues/sync/' + getCurrentProjectID(), (response) => {
console.log('ok');
});
}

View File

@ -3,7 +3,6 @@ import {get} from "@/common/js/ajax";
export function getIntegrationService(success) {
return get("/service/integration/all/" + getCurrentOrganizationId(), response => {
let data = response.data;
if (success) {
success(response.data);
}